Public: anyone can read this; the crew can change it.
forked from trevato/cs
The door's version is enforced, not remembered: the surface changes, the number moves, or the run fails #227
Check · Review · Land · Live done — Landed and live in production.
`src/engine/surface.json` is the new record: the sorted list of the 173 names the door offers and the version they belong to, and nothing else. `scripts/pack.ts` no longer keeps the version as a constant — it reads it from there through `scripts/surface.ts`, so the number and the surface it means are one committed thing.
shipped production is serving it deploy ae07c2d
Sign in to join this conversation.
new above
offline
src/engine/surface.jsonis the new record: the sorted list of the 173 names the door offers and the version they belong to, and nothing else.scripts/pack.tsno longer keeps the version as a constant — it reads it from there throughscripts/surface.ts, so the number and the surface it means are one committed thing.scripts/surface.test.tsreads today's door on every run of the tests and holds it against the record. Same surface, same version: pass. Different surface, same version: it fails with the names that arrived and the names that left, which part of the version that moves and why (a name added leaves every older pack building, so the middle number moves; a name removed or renamed may not, so the first does), and the one step that records it —bun run scripts/surface.ts --write 1.0.0, with the number worked out for you. That command refuses a version that stands still while the surface moved. Worth looking at: the message itself, which is tested on made-up surfaces rather than only on the real one, and is thrown rather than asserted so a failure prints it whole the way a pinned run's complaint does.boundary.test.tsnow reads the record forSURFACEinstead of keeping a second literal list of the same names — one written-down copy of the API, read by the boundary test, the guide test and this one, rather than two that drift. The door is still read with that file's own regular expression, because a module in the engine may import nothing outside it;scripts/surface.test.tsholds the two readings against each other on the real door. Type-only exports are in the record, as they always were in that list, andGUIDE.mdgains a short section saying what a move of the number promises a game that packed an older copy.What I chose not to do: no tags, no changelog, no publishing, and the record is not packed — it is data about the package, not a module of it. No module that ships changed, so no bundle or ceiling moved;
bun run testis green (1006 pass) and the app still boots and answers/in ~19 ms.🤖 Generated with Claude Code
Closes #191