README accuracy pass, and fix the capture that framed an empty city - #145
Merged
Conversation
Deleted files: described the rendering ("faint gray stub"), which had
gone stale twice over — the stub height default dropped from 2 floors to
0.05 and they're crossed out now. Describes what it gets you instead, so
it stops going stale every time the treatment is retuned.
Wire types: dropped the backend bullet about the OpenAPI schema being
"drift-guarded by manifest.contract.ts". The commands table already says
`just gen-types` regenerates the wire types from the schema, and the
mechanism it named is mostly gone: those types are derived from the
generated schema now, so field drift can't happen rather than being
caught. What's left only pins the NodeKind discriminator.
Roof border: added to the building signals. Saturation and lightness were
documented as the aging axes with nothing saying what they fade FROM.
Steps 1-3 ran in containers; 4-6 shelled out to `cd app && npm run ...` on the host. So the gate quietly depended on app/node_modules existing, and a fresh worktree couldn't push at all — eslint: command not found, for a change that touched one markdown file. They're one containerized step now, running the same command `just lint` already used, so the gate and the recipe can't drift. Slower by one container start; in exchange the gate no longer cares what the host has installed, which is the point of having it.
Regenerated against current main, so the shots show this session's work:
crossed-out deleted files in Timeline, and the roof-border reference
colour on the buildings.
The timeline alt text described the old treatment ("gray stubs"), so it
moves with the image it describes.
demo.mp4 is deliberately not in here — it re-recorded too zoomed in.
The orbit posed against a city that had streets but no buildings yet, so the bounding box was just the root street: radius 79 world units, when a ten-floor building is already 160 tall. The camera locked onto that and orbited a close-up of one road for the full 18 seconds. The harness gate (RebuildStatus.Idle) goes true while the city is still assembling, and orbit never returned false, so unlike the trees shot it never retried — it committed to the first pose it got. It now defers until a tallest building exists, which is the cheapest available proof that buildings have landed. The retry budget is 48s, so there's room. Re-recorded demo.mp4 against this.
Correcting the previous commit: guarding inside the orbit shot fixed the symptom in one place while every other shot kept the same trap. Two things were wrong. REBUILD_STATUS started at Idle, so "nothing has been built yet" and "a build finished" were the same value and the harness's wait passed at boot; that's now Pending. And Idle isn't the right question anyway, since the skeleton apply reaches it too, with a city of streets and no buildings — a bbox of the root street alone, radius 79 where a ten-floor building is 160 tall. The harness now waits for a tallest building to exist. Reading anchors in the gate subscribes to bbox, so it re-fires when the buildings land, and the fix covers every shot rather than the one that happened to show it. Verified by re-recording: the orbit frames the whole city again.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An audit of the README against
mainafter the last five PRs, plus the two bugs that fell out of trying to regenerate its assets.README
Three claims had gone stale:
2floors to0.05, and they're crossed out now. Rewritten to describe what it gets you rather than what it looks like, so it stops going stale each time the treatment is retuned.manifest.contract.ts". Deleted: the commands table already documentsjust gen-types, and the mechanism it named is mostly gone since Move three derived values to the backend, and stop re-declaring the wire types #142 — those types are derived from the generated schema now, so field drift can't happen rather than being caught. What survives only pins theNodeKinddiscriminator.Screenshots regenerated against current
main, so they show the crossed-out deleted files and the roof-border reference colour. The timeline alt text moved with the image it describes.Verified mechanically rather than by eye: all 12
justrecipes the commands table promises exist, and the documented skip list is an exact 44/44 match withALWAYS_SKIP.The pre-push gate depended on the host
Steps 1–3 ran in containers; 4–6 shelled out to
cd app && npm run …. So the gate quietly requiredapp/node_modules, and a fresh worktree couldn't push at all —eslint: command not found, for a change that touched one markdown file. They're one containerized step now, running the same commandjust lintalready used, so the gate and the recipe can't drift.just demo-videorecorded an empty cityThe demo orbit was recording a close-up of a single road. Two defects behind it:
RebuildStatus.Idlewas both the initial value and the "finished" value. Anything waiting for Idle passed at boot, beforemarkRebuilding()had run. There's aPendingstate now, so "nothing has been built yet" and "a build finished" are answerable apart.Idle isn't the right question anyway. The skeleton apply reaches it too, via the trees decoration pass, with a city of streets and no buildings. Instrumenting the shot gave:
tallest: 0— no buildings. The bbox was the root street alone: radius 79 world units, where a ten-floor building is already 160 tall. The camera locked onto that and orbited it for the full 18 seconds, becauseorbitnever returnsfalseand so never retried, unlike thetreesshot.The harness now waits for a tallest building before posing. Reading anchors in the gate subscribes to
bbox, so it re-fires once buildings land, and it covers every shot rather than the one that happened to expose it.Two wrong turns kept in the history
The first attempt replaced
cityRadius * 0.95with proper FOV-and-aspect fitting math. That was wrong: the committed video, recorded with that exact multiplier, frames correctly — reverted. The second guarded inside theorbitshot, fixing one call site while every other shot kept the trap; superseded by the harness gate.Both are on the branch rather than amended away, since the squash-merge cleans it up.
Verified by re-recording and comparing extracted frames against the previously committed video, not by reading the code — which is how the first wrong turn got caught.
Full gate green via the pre-push hook (now containerized end to end): 369 pytest, ruff, 2838 vitest, eslint, prettier, typecheck.
🤖 Generated with Claude Code