Public: anyone can read this; the crew can change it.
forked from trevato/cs · proposes · 4 behind
The trainer becomes engine: PPO through the door, proved on an environment that is not a game #126
Check · Review · Land · Live done — Landed and live in production.
`src/rl/ppo.ts` is now `src/engine/learn.ts`, moved and not improved: the only lines that differ are the import — `./net.ts` rather than the door, because a package does not go through its own door — and comments; `git diff -M` shows 19 added lines and 4 removed, all of them prose. GAE, the clipped surrogate, Adam and the hand-written backward pass are byte for byte what they were, the gradient ch…
shipped production is serving it deploy ae07c2d
Sign in to join this conversation.
new above
offline
src/rl/ppo.tsis nowsrc/engine/learn.ts, moved and not improved: the only lines that differ are the import —./net.tsrather than the door, because a package does not go through its own door — and comments;git diff -Mshows 19 added lines and 4 removed, all of them prose. GAE, the clipped surrogate, Adam and the hand-written backward pass are byte for byte what they were, the gradient check against finite differences moved with them and passes as written, andbun run scripts/train.ts --benchreports 12–13k steps/s across five runs against 13k before the move (the bench steps the arena and the network, not the trainer, so the two numbers are the same number).The issue's real half is the new test.
src/engine/learn.test.tstrains a two-armed bandit written out inside the test — the observation is which arm pays this pull, one-hot, so a policy that ignores what it sees is stuck at a half however long it trains — reaching the trainer throughindex.tsand nothing else: no map, no tick, no weapon anywhere in it. It asserts the mean reward of the rollout the updates were collected from rises from ~0.5 to past 0.9 within 40 updates, and that the last five rollouts average past the same floor; under its fixed seed it takes about 40 ms and reaches 1.0 by the eighth update, so the floor has room rather than being tuned to squeak past. A second test pins that the seed reproduces the run exactly and that another seed learns too.src/rl/keepsarena.ts, which is CS.scripts/train.tsnow reaches the network and the trainer through one import of the door;src/engine/index.ts, the pinnedSURFACEinboundary.test.tsandGUIDE.mdgain the fourteen names as a group, with the guide saying plainly that a game ships weights and not a trainer and that no browser loads this. That last claim is a test rather than an inference: "no committed bundle carries the trainer" reads all three committed bundles formaxGradNorm,valueCoef,lastValues,clipFractionandpolicyLossand finds none of them. No bundle grew — app 72,048 raw / 33,482 gzipped, range 28,978 / 12,320, example 8,754 / 4,227: the raw sizes are identical to the byte and the gzipped ones move by a byte or two where the minifier handed out different short names over a module graph that changed shape, the same thing that happened for #106.One thing to look at that is not the issue:
mainarrived with two range bundles committed,range.79e3fb073e.jsfrom #121 andrange.f0416248f9.jsfrom #125, neither sweeping the other, and eight tests failed on it — every reader of "exactly onerange.<hash>.js". The first commit here is a plainbun run buildthat resolves them into the one the sources produce, both changes at once, with no source touched.bun testis 596 pass / 0 fail, and the README's three places that namedsrc/rl/ppo.tsnow namesrc/engine/learn.ts.🤖 Generated with Claude Code
Closes #107