Skip to content

The eager-closure gate is green through a +153.7 KB regression — its headroom invariant is asserted against frozen constants, not the live measurement #5924

Description

@claude

Found while verifying #5359 on origin/main (0fce2ef81). Filed unassigned; not graded.

What is wrong

scripts/check-eager-closure-budget.mjs states a binding constraint on its own sensitivity, in its header:

The headroom must stay SMALLER than the regression the gate exists to catch. objectui#5266 was 89 KiB = 91,136 bytes; 80,089 < 91,136, so this ceiling would have failed on that change.

That constraint holds between the two frozen constants. It no longer holds against the console that ships today.

gzipped bytes
MAX_EAGER_CLOSURE_GZIP_BYTES4,086,000
BASELINE.gzipBytes (frozen, 4c1623c0c)4,005,911
measured on 0fce2ef81 today3,308,221
live headroom (ceiling minus today)777,779 = 8.5xREGRESSION_THIS_GATE_MUST_CATCH_BYTES (91,136)

The eager closure got ~698 KB smaller since the constant was pinned. That is good news that silently widened the gate's blind band by an order of magnitude.

Demonstrated, not inferred

An eager @objectstack/spec/cloud namespace import was injected into apps/console/src/main.tsx (a use the bundler cannot fold away), the console rebuilt, and the shipped gauge run against the resulting report:

eager closure baseline 3,308,221 bytes gzip
eager closure with injection 3,465,582 bytes gzip (+157,361 = +153.7 KB)
$ node scripts/check-eager-closure-budget.mjs --report <injected report>
GAUGE_EXIT_ON_INJECTED_REGRESSION=0
✅ Console eager closure is 3384.4 KB gzipped across 52 of 508 chunks (budget: 3990.2 KB, headroom: 605.9 KB).

Exit 0, green tick, on a regression 1.7x larger than the 89 KiB incident this gate was built to catch. Removing the injection returned the measurement to 3,308,221 exactly (same chunk hash), so the movement is the injection and not build noise.

Why the unit test cannot notice

scripts/__tests__/check-eager-closure-budget.test.ts:

constheadroom=MAX_EAGER_CLOSURE_GZIP_BYTES-BASELINE.gzipBytes;expect(headroom).toBeLessThan(REGRESSION_THIS_GATE_MUST_CATCH_BYTES);

Both operands are frozen constants in the same module, so the assertion is true regardless of what the console actually weighs. It is green now, and it would stay green if the closure halved again. The invariant is stated about the live bundle but checked about two literals.

Why this is not folded into #5490

#5490 carries per-chunk budgets under a ruling whose text is explicit that the absolute aggregate ceiling "stays as shipped". This is about the aggregate gate's sensitivity having drifted away from its stated specification, so it needs its own disposition rather than riding on a card that is bound not to touch that ceiling.

⛔ Nothing here argues for silently lowering the ceiling. The script's header is right that re-baselining is a decision; this card records that the decision is now due, and that the test protecting the invariant cannot raise its hand.

Possible dispositions (triage's call)

  1. Derive the headroom check from the report the gate just read, instead of from BASELINE.gzipBytes, so drift in either direction is caught at the moment it opens.
  2. Re-baseline downward now, as a visible decision, and keep the constant-vs-constant test as a secondary guard.
  3. Both.

Refs: #5324 (the gauge), #5490 (per-chunk follow-up), #5359 (where this was found).


Generated by Claude Code


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repopm:dispatched

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions