Uh oh!
There was an error while loading. Please reload this page.
test(scripts): derive the eager-closure headroom check from the report, and re-baseline the aggregate ceiling - #6229
Conversation
…t, and re-baseline the ceiling The gate stated a binding constraint on its own sensitivity — the headroom above the measured payload must stay SMALLER than the 89 KiB regression the gate exists to catch — and then checked it between two constants frozen in the same module. That assertion is an arithmetic fact about the file, true whatever the console weighs. The closure shrank 706,013 gzipped bytes below the pinned baseline without the ceiling following it down; the live headroom reached 8.6x the regression size, and the check meant to notice stayed green. `evaluateHeadroomSensitivity` derives the headroom from the report the gate just read — for the aggregate ceiling and each of the three per-chunk ceilings added by #6210 — and calls a ceiling more than one regression above its own measurement an ERROR (exit 2, a verdict about the gauge), never a size failure. `error` still outranks `fail`, now across three halves. The aggregate ceiling is re-baselined downward as the decision this records: MAX_EAGER_CLOSURE_GZIP_BYTES 4,086,000 -> 3,345,000 over a BASELINE moving 4,005,911 (4c1623c) -> 3,299,898 (48e5381). Headroom 8.63x -> 0.49x the regression size. Lowering a ceiling toward reality is a tightening; the floor is unchanged — never below a measured figure. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
yinlianghui-tw
commented
Aug 25, 2026
PM review — ACCEPT. Your premise correction is right, my acceptance test was confounded, and I found CI evidence that closes the one risk this PR carries.Reviewed by the ⛔ My ordered acceptance test was confounded — you caught itI wrote: "Predicted exit 0 before your change (reproducing the defect)." You measured that the shipped gate exits 1, because #6210's per-chunk half already catches this injection — Arithmetic confirms it: 1080.5 KB = 1,106,432 B > 967,000 B. The per-chunk half reds regardless of the aggregate. ⭐ So my acceptance test would have "failed" for a reason that has nothing to do with this card, and a dev following it literally would have reported a broken premise or, worse, tuned something to make the prediction come true. Running the aggregate half unconfounded instead — same injected report, varying only the ceiling — is the right experiment: Every figure re-derived here, all consistent
The
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#5924
Triage disposition 3, both halves. Build tooling and CI only — nothing ships.
(a) The headroom check now reads the report the gate just read
scripts/check-eager-closure-budget.mjsstates a binding constraint on its own sensitivity, in its header: the headroom must stay SMALLER than the regression the gate exists to catch. It then checked that constraint in the unit test asBoth operands are literals frozen in the same module, so the assertion is an arithmetic fact about the file — true regardless of what the console weighs, and it stayed true while the closure fell ~706 KB below the pinned baseline. The invariant was stated about the live bundle and checked about two constants.
New exported
evaluateHeadroomSensitivity({ report, budgetBytes, ceilings, regressionBytes })computes the headroom from the report, for all four ceilings this file ships — the aggregate plus the three per-chunk lines PR #6210 added — and calls a ceiling more than one regression above its own measurement an error (exit 2), not a size failure.Why
errorand notfail:failis a verdict about the bundle (it grew past a line). Nothing has grown here — the ceiling has stopped measuring anything. That is a verdict about the gauge, which is what exit 2 already means in this file, and it is the same asymmetryevaluatePerChunkBudgetsapplies to a budgeted chunk that is absent: a check that passes by measuring nothing must be louder than one that fails by measuring something, never quieter.Two things it deliberately does not do:
the size verdict owns this row, not this one, so the table is complete without double-reporting one regression as an error.The constant-vs-constant assertions stay in the unit test as the secondary guard triage asked for; they carry a docblock saying what they structurally cannot do.
(b) The aggregate ceiling, re-baselined downward — the stated decision
MAX_EAGER_CLOSURE_GZIP_BYTESBASELINE.gzipBytes4c1623c0c)48e53814e)BASELINE.chunks/totalChunksREGRESSION_THIS_GATE_MUST_CATCH_BYTESREGRESSION_THIS_GATE_MUST_CATCH_BYTES(91,136) is untouched — the gate's sensitivity is not part of this trade.Measured myself on
48e53814e, not carried from the card: 3,299,898 gzipped bytes, 52 of 508 chunks,vendor-objectstackat 948,461 B (926.2 KB). Every figure on the card was stale (it says 3,308,221 B and 1,493 KB); #6210's 3,298,620 B at2c8474c04is 1,278 B off from this tree, which is the commits that landed between. Two independent builds of the clean tree in this worktree gave byte-identical totals (3,299,898 both times), so the reading is stable.Why the headroom is now half the regression size rather than ~2%. Headroom H buys H bytes of growth before the gate reds for being over budget, and — now that the second constraint is enforced live — costs
REGRESSION - Hbytes of shrink before it reds for going blind. The old ~2% rule would have given 66 KB one way and 25 KB the other;H = REGRESSION / 2is the only value equidistant from both, ~45 KB in each direction. That is a change to how the number is derived, stated in the header next to the number.⛔ The floor is unchanged and I did not go near it: no ceiling is below a measured figure. The new aggregate ceiling is 45,102 B above today's payload and passes on this tree (see the union below). The three per-chunk ceilings and
PER_CHUNK_BASELINEare untouched — their live headrooms are 18.1 KB / 8.3 KB / 7.7 KB, all comfortably inside the sensitivity band, so there was nothing to re-pin. (frameworkhas grown 1,112 B since #6210's reading; the new live check is what makes that staleness harmless rather than something to chase.)Exit-code ordering — checked, as asked
.github/workflows/performance-budget.ymlmapsCLOSURE_CODE -eq 2tobudget_status=error(and exits the step) before the!= 0branch that maps tobudget_status=fail. #6210 madeerroroutrankfailacross both halves; this PR extends the same rule to three rather than giving sensitivity a code of its own:Pinned by a new test that runs one blind ceiling and one chunk over its line in the same report and asserts exit 2 with
closure_chunk_status=fail. A newclosure_headroom_statusoutput is published alongsideclosure_status/closure_chunk_status; likeclosure_chunk_statusit is not wired into the PR-comment renderer, which stays out of scope.The acceptance test — and a correction to the dispatch order's prediction
The card's own injection, reproduced: an eager
@objectstack/spec/cloudnamespace import intoapps/console/src/main.tsxplus aglobalThissink the bundler cannot fold away. Injection and restore were both proven on disk by anchored counts (marker lines 0 → 2,@objectstack/spec/cloud0 → 1, then back to 0 with an emptygit diff HEAD), under atrap ... EXIT INT TERM.48e53814e48e53814ebefore any of my edits, the shipped gate exits 1: the per-chunk half catches it (vendor-objectstack1080.5 KB over its 944.3 KB ceiling). The card's demonstration predates #6210. The defect the card actually records is still exactly reproducible, but it is a statement about the aggregate half, not the process exit code — so I ran the unconfounded comparison, same injected report, varying only the ceiling:Before:
✅ Console eager closure is 3376.9 KB gzipped … (budget: 3990.2 KB, headroom: 613.4 KB). After:❌ … 110.3 KB over the 3266.6 KB budget. Whole-gate exit on the injected report with the fix: 1.And the drift itself, judged by the new live check, with the ceiling of the day against today's payload:
That is the card, as a red gate. Both halves of the acceptance test are pinned in the suite so they cannot quietly come undone.
One fixture consequence, triaged rather than renamed
main'sbudgeted()fixture carried only the budgeted chunk names, totalling ~1.8 MB against a 3.3 MB ceiling. Under the live check that shape is a blind ceiling and now exits 2 — correctly. The fixture was wrong, not the check: a real report's total sits near the ceiling by construction. It now carries the rest of the closure as one filler chunk and totalsBASELINE.gzipBytes, with atotalDeltaparameter for tests that move the total on purpose.closure_gzip_kbin that test moves1814.3→3222.6andclosure_chunks4→5as a result.Also touched
One prose block in
.github/workflows/performance-budget.yml: it described the ceiling as "today's measured payload plus ~2% of headroom … not a statement that 3.79 MB is fine", both of which this PR makes false. Same defect class as the card (a frozen figure drifted from reality), same file family, no behaviour. Named here rather than left as an unreviewable drive-by.⛔ Out of scope and untouched:
advancedChunksinapps/console/vite.config.ts, any cleave (#5324 names those candidates),content/docs/releases/.Verification
All at
96b0685ea, the final commit. Exit codes captured by redirect before any pipe; verdicts quoted from what each gate printed.npx vitest run scripts/__tests__ --maxWorkers=2(whole directory, from the repo root perpnpm --filter @object-ui/app-shell test跑的是 @object-ui/console 的 22 个文件,app-shell 自己的 276 个一个没跑,却报绿 #3378 — several files there readapps/console/vite.config.tsas their subject) —Test Files 75 passed (75)/Tests 2083 passed (2083)pnpm type-check:scripts(tsc -p tsconfig.scripts.json, which infers the checker's types from the.mjs) — exit 0node scripts/check-eager-closure-budget.mjsagainst the real report from this tree's build — exit 0:check:control-bytes—✅ check-control-bytes: OK (scanned 5132 tracked text file(s); skipped 85 binary)check:node-esm-load,check:entry-guard,lint:coverage(✅ 46/46 packages linted),node scripts/check-changeset-presence.mjs,pnpm changeset:check— all exit 0eslint .is CI's run, not narrowed here.Changeset added with empty frontmatter (
.changeset/5924-live-headroom-invariant.md) — CI tooling only, nothing published, matching the#5490precedent.Refs: #5324 (the gauge) · #5490 / PR #6210 (the per-chunk half, which grew this card's population to four) · #5468 (bound #5490, not this card) · #5359 (where this was found).
Generated by Claude Code