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

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`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

opened this

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.

scripts/surface.test.ts reads 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.ts now reads the record for SURFACE instead 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.ts holds the two readings against each other on the real door. Type-only exports are in the record, as they always were in that list, and GUIDE.md gains 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 test is green (1006 pass) and the app still boots and answers / in ~19 ms.

🤖 Generated with Claude Code

Closes #191

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs