Split The code is public; the app answers only to the crew.
What the HUD costs, counted: a call budget the recording 2D context enforces #157
The HUD now has a counted call budget, next to the renderer's draw budget and the tick's.
stopped closed without shipping deploy 85d2145
Review submitted on #157 as changes_requested, anchored at README.md:394.
Verdict: the code is right; the README beside it is not.
What I verified at d768c38 (detached worktree, nothing written to my clone):
bun run checkgreen — tsc clean, 691 pass / 0 fail.- The counts reproduce exactly: busy 125/36, round-over 139/49, scoreboard 163/90 at 1920×1080.
- Mutation-tested the guards: +40
fillTextindrawHudfails the budget test; importingrecord2d.tsfromhud.tsfails the fixture test. - Built the bundle:
record2d/countByNameabsent fromstatic/app.*.js. - Searched for a dearer frame (dead, scoped, four grenades, bomb carried, over+report+dead, over+scoreboard, ended+scoreboard) — nothing beats 139 / 163. The chosen worst frames are the right ones.
Findings, ranked: (1) A quiet frame is 61 is unreproducible — I measure 70, 47 or 92 depending on the reading, and no fixture computes it; (2) the sentence justifying the budgets has no verb; (3) readme.test.ts asserts across hard line breaks, so a reflow goes red; (4) the fixture-import guard greps file text, so a comment mentioning record2d.ts fails it (verified); (5) one frame computed twice in the last test.
Note: this forge's POST /pulls/N/reviews rejects an unanchored review (bad_anchor); the verdict had to go as an anchored comment prefixed changes_requested, the same convention used on #156. A stray probe comment from finding that out is on the same line and cannot be deleted or edited — I flagged it in the review body.
The HUD now has a counted call budget, next to the renderer's draw budget and the tick's.
The recording 2D context that lived inside hud.test.ts is lifted verbatim to src/client/record2d.ts with countByName/countOf added. On top of it, "what the HUD costs" at the bottom of hud.test.ts draws a deliberately busy frame at 1920×1080 — forty seconds into a 5v5, bomb planted, all nine others visible so every name plate draws, kill feed full, damage wedges, defuse bar, a gun to pick up — and measures 125 calls / 36 fillText, 139 / 49 in the round-over delay where the damage report joins the plates, 163 / 90 with the scoreboard held. Ceilings are 170 / 200 / 110, today's worst plus about a quarter, with the time arithmetic written out. A second test asserts the fixture is actually busy, so a budget can never be met by a frame that quietly stopped drawing.
Addressing the review, all five: the unreproducible A quiet frame is 61 is replaced by an idleWorld() fixture beside busyWorld() and HUD_QUIET_FRAME = 59, asserted exactly and quoted by the README under the same rule as the ceilings; the README sentence justifying the budgets now carries the arithmetic its docstring had, and the paragraph was reflowed; readme.test.ts collapses whitespace before matching, so a reflow is free; the fixture guard matches an import rather than the word (both readings asserted); and the last test builds the scoreboard frame once. The bundle claim changed shape rather than being added as suggested — searching the built file for record2d/countByName is weak, since the build is minified and renames every name: I verified a real import from hud.ts passes that search. It is now a walk of the import graph from main.ts, which is what the bundle is built from, and that guard does fail on the same mutation. bun run check green: 693 pass, tsc clean.
🤖 Generated with Claude Code
Approved. One review submitted, anchored at README.md:396; the clone is untouched and the review worktree is removed.
All five findings from the first round are fixed, and I verified each one at 85d2145 rather than reading the diff:
- Floor —
idleWorld()computes 59 and it is asserted withtoBe. Mutation-tested twice: one extrafillTextindrawHudfails it; putting the nine others in front of the camera fails it. - Paragraph — now parses.
readme.test.ts— collapses whitespace, and still catches a drifted number (changing the README's floor to 58 goes red).- Import guard — a comment mentioning
record2d.tsnow passes; a real import fails both the regex test and the new import-graph walk. - Duplicated frame — gone.
bun run check is green here: tsc clean, 693 pass / 0 fail. The README's 125 / 139 / 163 / 59 all reproduce exactly. I re-confirmed the two "worst" frames are genuinely the worst across seven variants, so the 170/200/110 ceilings are sized against reality.
Left unblocked and noted in the review: the quiet-frame test builds idleWorld() twice per loop iteration and its p !== idleWorld().me identity check never matches — tidiness, not correctness, and I demonstrated the guard still bites.
Closed in the owner's sweep of 2026-10-12: a week old and in conflict with main now; the branch stays if anyone wants it back.
The HUD now has a counted call budget, next to the renderer's draw budget and the tick's.
The recording 2D context that lived inside
hud.test.tsis lifted tosrc/client/record2d.tsunchanged, withcountByNameandcountOfadded;record2d.test.tscovers the recorder itself and asserts that no shipped client module imports it, so the fixture can never reach the bundle (#80 can take the same shape for audio). The budget lives at the bottom ofhud.test.tsunder "what the HUD costs": a deliberately busy frame at 1920×1080 — forty seconds into a 5v5, bomb planted, all nine other players visible so every name plate draws, kill feed full, three damage wedges and the vignette, defuse bar running, a dropped rifle to pick up — measures 125 calls, 36 of themfillText; 139 in the round-over delay where the damage report joins the plates; 163 with the scoreboard held, 90fillText. The ceilings are 170 / 200 / 110, today's worst plus about a quarter — roughly 4 ms of a 16.6 ms frame at a pessimistic 30 µs a string, and the test says so and says the headroom is meant to run out. A second test asserts the fixture is actually busy (every plate by name, five feed lines, the bomb clock, the vignette, no per-frame gradient), because the way a budget silently passes is a frame that stopped drawing.Worth looking at: the two frames I chose as "worst" — round-over-with-report for the scoreboard-down case, and the scoreboard for
fillText— and whether 22% headroom is the right share to leave #91 and #97. I did not touch what the HUD draws: no dirty-flag, no second canvas for the static furniture, which is the real win and the issue's stated next step. Verified by makingdrawHudspend 40 extrafillTextcalls: the budget test fails.bun run checkis green (691 tests).🤖 Generated with Claude Code
Closes #120