Repository navigation
Add per-chunk budgets on top of the aggregate eager-closure ceiling — vendor-objectstack (38%) first — ruled follow-up of #5468 #5490
Description
Activity
- addeddomain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repoobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repo
on Aug 21, 2026 yinlianghui-tw commented
on Aug 25, 2026 CollaboratorMore actionsPM claim + dispatch order — R27
Claimed by the
domain:devx@ objectui execution seat (#5748), PM sessionsession_019b5UBNMtTzKbVtZZGvFuxe. Branch:claude/issue-5490-per-chunk-budgets.This card is already a ruling. ⛔ Nothing here is open.
It was written by the triage seat executing the maintainer's #5468 ruling (2026-08-21, verbatim 「其他接受」): A now + C next, B rejected. The aggregate ceiling stays as shipped in PR #5466; this card delivers C — per-chunk budgets, so a single chunk cannot grow unnoticed inside aggregate headroom.
⛔ Option B (a main-comparison ratchet) is rejected and must not be reintroduced, for two recorded reasons: its merge-queue double-ejection failure mode, and per-PR build cost. If the implementation starts to feel like it wants a comparison against
main, that is a signal to stop and report — not to build it.⚠️ The sequencing caveat is binding — check it before measuringThe ruling carries a recorded caveat: if #5325 / #5359 (the cleave work) has landed, set the per-chunk lines after it, not before.
Check that first. Baselines measured against a pre-cleave closure would be wrong the moment the cleave lands, and a budget set too high is a gate that cannot fail. Report which state you found and which you measured against.
What to build
Per-chunk gzipped ceilings in
scripts/__tests__/check-eager-closure-budget.test.ts(or a sibling in the same gauge), for at minimum:chunk card's figure vendor-objectstack1,493 KB / 38% of closure framework484 KB ui-components380 KB Set at truthful current state + small headroom, the same discipline as the aggregate ceiling. ⛔ No unilateral lowering — this is a ratchet, not an optimisation target, and lowering it below measured reality turns a budget into a bug report.
⚠️ Re-measure all three. Those figures are from 2026-08-21 and this repo has moved a great deal; every inherited number tonight has been stale.⭐ The requirement that decides whether this gate is worth anything
Chunk names/sizes come from the shipped gauge's own measurement (the
eager-closurereport), not hardcoded expectations that rot — pin the mapping loudly if a chunk disappears or renames.That last clause is the whole design. A per-chunk budget keyed on a chunk name that no longer exists is vacuously green — the budget passes because it is measuring nothing. So:
- If a budgeted chunk name is absent from the report, the gate must FAIL, not skip. Predict and prove it: rename or remove a budgeted chunk name and confirm the gate reds naming it.
- If the report yields zero chunks, the gate must FAIL. A collapsed measurement must never read as under-budget.
- Put the measured sizes in the verdict line, not just pass/fail, so a reader sees headroom rather than a tick.
Positive control: raise one chunk past its ceiling (or lower a ceiling below measured) and confirm the gate reds naming that chunk and both numbers. Predict each direction before running; prove mutations on disk by anchored counts, never an editor's exit code; restore via
git checkout HEAD --plus the explicit path with an emptygit diff HEAD.Scope
The budget test and whatever the gauge needs to expose per-chunk numbers. ⛔ Do not change chunking, ⛔ do not change the aggregate ceiling, ⛔ do not attempt the cleave work (#5325 / #5359).
Root vitest only (objectui#3378). Exit codes captured by redirect before any pipe.
⚠️ Derive the gate list frompackage.jsonand.github/workflows/rather than from this order.⚠️ This gate needs a real build to measure. Say plainly what happens if it runs against an unbuilt tree — ⛔ it must not silently pass. That exact false-green has bitten three of this seat's devs tonight on a different gate (check:doc-snippetsprints "NOT run" and exits 0).
Generated by Claude Code
yinlianghui-tw commented
on Aug 25, 2026 CollaboratorMore actionsos-dev-report
{ "issue": 5490, "status": "done", "branch": "claude/issue-5490-per-chunk-budgets", "pr": "https://github.com/objectstack-ai/objectui/pull/6210", "premise_still_valid": true, "summary": "Per-chunk gzipped ceilings added on top of the aggregate eager-closure ceiling in scripts/check-eager-closure-budget.mjs, for vendor-objectstack (967,000 B), framework (502,000 B) and ui-components (399,000 B) — each set at the freshly measured size plus ~2%, each headroom far narrower than the 89 KiB regression the gate exists to catch. SEQUENCING CAVEAT: the cleave work has NOT landed — #5325 was closed by PR #6007 (a checked ledger pinning the 43 ineffective dynamic imports; no import moved) and #5359 by PR #5925 (a docs correction), and advancedChunks is untouched by both — so the lines are measured against the current pre-cleave closure at main tip 2c8474c04. The card's figures were stale in one direction that matters: vendor-objectstack measures 926.2 KB, not 1,493 KB (framework 480.9 vs 484; ui-components 381.9 vs 380). The ceilings key on the chunk names the report itself carries: emitEagerClosureReport now publishes rolldown's own chunk.name as files[].name (report v2, SUPPORTED_REPORT_VERSION bumped in lockstep and pinned by a test that parses the emitter), and a budgeted name ABSENT from the report is exit 2 naming it and listing every name present — never a skip. Zero named chunks, an empty ceiling map, and an unnamed member are errors for the same reason. Aggregate ceiling, its baseline, and chunking are untouched.", "tests": "All at the final commit 32f162a77, exit codes captured by redirect before any pipe, heavy commands through the shared verify lock. (1) BUILD: `npx vite build` in apps/console — exit 0, 'eager closure: 52/508 chunks, 3298620 bytes gzipped'; three consecutive builds produced byte-identical totals, so the per-chunk numbers are measurements, not noise. (2) SHIPPED GATE against that real report: `node scripts/check-eager-closure-budget.mjs` exit 0, verdict lines carry the sizes — 'vendor-objectstack 926.2 KB / 944.3 KB ceiling (headroom 18.1 KB)', 'framework 480.9 KB / 490.2 KB (headroom 9.4 KB)', 'ui-components 381.9 KB / 389.6 KB (headroom 7.7 KB)'. (3) ROOT VITEST over the derived test set — eight tests in scripts/__tests__ read apps/console/vite.config.ts as their subject, so the whole directory was run: `npx vitest run scripts/__tests__ --maxWorkers=2` exit 0, 'Test Files 73 passed (73) / Tests 2019 passed (2019)'. (4) TYPE-CHECK: `npx tsc --noEmit -p tsconfig.scripts.json` exit 0, with both changed script files confirmed present in the program via --listFiles (a green run over a program that does not contain the file is the vacuity this guards against); `npx tsc -b apps/console/tsconfig.node.json --force` exit 0 — that, not tsconfig.scripts.json, is the program that owns vite.config.ts. (5) LINT: `pnpm lint:root` exit 0 over the FULL root scan (28 pre-existing warnings, 0 errors) plus targeted eslint on the three changed files, exit 0 with no problems — apps/console/vite.config.ts is outside lint:root's scope, so it was linted explicitly against the same flat config; eslint.config.js declares no project/projectService, so no type-aware rule can move a verdict on an untouched file. (6) OTHER DERIVED GATES: check:control-bytes, check:phantom-deps, check:esm-specifiers all exit 0. CONTROLS, each direction predicted before running: [A] POSITIVE — the #5266 incident replayed, +89 KiB onto vendor-objectstack in an internally consistent report (mutation confirmed on disk by reading the file back: 948461 -> 1039597, eagerGzipBytes 3389756): predicted exit 1 with the aggregate green, observed exactly that — 'Console eager closure is 3310.3 KB ... headroom 679.9 KB' green, per-chunk red 'vendor-objectstack 1015.2 KB / 944.3 KB ceiling (OVER by 70.9 KB)'. That single run is the whole argument for this card. [B] POSITIVE — ceiling lowered below measured (framework 502_000 -> 450_000; anchored counts on disk 1->0 and 0->1, never an editor exit code): predicted red naming framework, observed exit 1 '480.9 KB / 439.5 KB ceiling (OVER by 41.4 KB)'. Second direction: predicted at least the ceiling-vs-baseline unit test to red, observed SEVEN failures — wider than predicted, same direction, all one cause (fixtures are built from PER_CHUNK_BASELINE, which now exceeded the lowered ceiling). Restored with `git checkout HEAD -- scripts/check-eager-closure-budget.mjs`; anchored counts back to 1/0 and `git diff HEAD` empty (0 bytes). [C] NEGATIVE — a budgeted chunk renamed in a copy of the real report (anchored counts 1->0 and 0->1): predicted exit 2 naming it rather than a pass, observed exit 2 with the aggregate still green and 'Budgeted chunk `vendor-objectstack` is ABSENT ... That is a FAILURE, not a pass' followed by the 52 present names, vendor-objectstack-core at the top. [D] UNBUILT TREE, the question the dispatch asked: exit 2, both halves refusing — 'This is a broken gauge, not a passing budget' and 'Per-chunk ceilings measure nothing without a build — this is a broken gauge, not 3 budgets that all passed'. No path exits 0 having measured nothing; performance-budget.yml maps exit 2 to budget_status=error and fails the step, and it is the only CI caller, running after it builds the packages and the console.", "open_questions": [], "out_of_scope_findings": [ "NOT filed — already recorded as #5924 (searched first): the aggregate ceiling's live headroom is now ~769 KB, 8.4x the 89 KiB the gate is sized to catch, because the closure shrank ~707 KB below the frozen BASELINE (measured 3,298,620 on 2c8474c04 vs BASELINE 4,005,911 on 4c1623c0c). #5924 records the same drift measured at 3,308,221 on 0fce2ef81 and owns the disposition. Untouched here by ruling (#5468: the aggregate line stays as shipped), but recorded in the checker's header beside PER_CHUNK_BASELINE so the two readings are never mistaken for one measurement. The per-chunk headroom assertion inherits the same constant-vs-constant shape at a ~2% band instead of ~24%; the systemic fix (derive the headroom check from the report just read) belongs to #5924.", "Not filed, noted only: `pnpm --filter @object-ui/console build` fails on a fresh worktree until `pnpm turbo run build --filter='./packages/*'` has run — 358 TS2307/TS2882 errors from missing package dist. Expected toolchain behaviour (CI builds packages first) and not a defect; recorded because it reads exactly like a broken main for the first minute." ] }
Generated by Claude Code
- added a commit that references this issue
on Sep 1, 2026
Work card created by the triage seat executing the maintainer's #5468 ruling. Provenance: maintainer, live PM chat 2026-08-21, verbatim 「其他接受」 accepting the triage recommendation for #5468 — A now + C next, B rejected: the absolute aggregate ceiling stays as shipped (PR #5466); this card delivers C, per-chunk budgets, so a single chunk cannot grow unnoticed inside aggregate headroom.
Scope (S-size per the #5468 clause)
scripts/__tests__/check-eager-closure-budget.test.ts(or a sibling in the same gauge) with per-chunk gzipped ceilings for the largest eager chunks — at minimumvendor-objectstack(1,493 KB / 38% of closure),framework(484 KB),ui-components(380 KB) — set truthful-current-state + small headroom, same discipline as the aggregate ceiling (no unilateral lowering).eager-closurereport), not hardcoded expectations that rot — pin the mapping loudly if a chunk disappears/renames.Constraints from the ruling
packages/fields/src/index.tsxis defeated by a static import of the same module — 13+INEFFECTIVE_DYNAMIC_IMPORTwarnings per console build #5325 / finding(app-shell/console): the DraftChangesPanel/metaspelling fold puts@objectstack/spec/sharedon the console's EAGER graph — +60.1 KB gzipped that no budget weighs #5359 cleave work lands first, set the per-chunk lines after it, not before (the [Decision] Should the eager-closure budget be tightened below today's payload — absolute ceiling, true ratchet, or per-chunk budgets? #5468 facet block's recorded caveat).Refs: objectui#5468 (decision card, closing) · #5324 / PR #5463…#5466 (the gauge) · #5325, #5359 (cleave direction).