Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .changeset/5490-per-chunk-eager-budgets.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
---
---

Build tooling and CI only — `apps/console/vite.config.ts` (not published source:
`@object-ui/console`'s `files` list carries `dist`, `plugin.*` and `README.md`),
`scripts/check-eager-closure-budget.mjs` and its unit test. Nothing ships from
this change.

The console eager-closure budget weighed one total across 52 chunks. Inside its
headroom a single chunk can absorb the whole allowance while the others shrink,
and the total never moves — the shape of objectui#5266, whose 89 KiB landed
entirely in `vendor-objectstack`. Per-chunk gzipped ceilings now sit on top of
the aggregate for the three largest eager chunks, set at the measured current
state plus ~2%, with each headroom narrower than the regression the gate exists
to catch.

The ceilings key on the chunk names the report itself carries (`files[].name`,
new in report v2, taken from rolldown's own `chunk.name`) rather than on names
this checker expects to exist. A budgeted chunk that is absent — renamed group,
chunk gone — is therefore an error, not a skip: a ceiling with no subject weighs
nothing and would be green forever.
29 changes: 26 additions & 3 deletions apps/console/vite.config.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -326,17 +326,40 @@ function emitEagerClosureReport(reportFileName = 'eager-closure.json'): Plugin {
);
}

// The chunk's OWN name, as rolldown recorded it — the `advancedChunks`
// group name for a grouped chunk, the entry's name for an entry. The
// per-chunk ceilings in `scripts/check-eager-closure-budget.mjs` key on
// this field (objectui#5490) instead of stripping the hash out of
// `fileName` themselves: the group names are decided by `advancedChunks`
// a few hundred lines below, and a budget that re-derives them from a
// file name is a second opinion about the same fact — one that goes on
// reading plausibly while it matches nothing.
const name = chunks.get(fileName)?.name;
if (typeof name !== 'string' || name === '') {
this.error(
`[emit-eager-closure-report] eager-closure member \`${fileName}\` carries no chunk ` +
`\`name\` (${JSON.stringify(name)}), so a per-chunk ceiling has no way to find ` +
`its subject. Refused rather than published: a budgeted chunk MISSING from this ` +
`report is a budget with nothing to weigh, and a budget that weighs nothing ` +
`passes — the silent direction every counter-probe in this plugin exists to ` +
`refuse (objectui#5490).`,
);
}

const raw = fs.readFileSync(filePath);
// Level 6 — zlib's default, and the level `gzip -c` uses in the
// workflow's entry-chunk check, so the two numbers in one PR comment
// are measured the same way.
return { fileName, bytes: raw.length, gzipBytes: zlib.gzipSync(raw).length };
return { fileName, name, bytes: raw.length, gzipBytes: zlib.gzipSync(raw).length };
});

const report = {
// Bumped when the shape below changes; the checker refuses a report it
// does not understand rather than reading absent fields as zero.
reportVersion: 1,
// does not understand rather than reading absent fields as zero. v2
// added `files[].name` for the per-chunk ceilings (objectui#5490) — a
// v1 report reaching the v2 checker is therefore a REFUSAL, not a run
// in which every budgeted chunk happens to be missing.
reportVersion: 2,
entryChunks: entries.sort(),
eagerChunkCount: files.length,
totalChunkCount: chunks.size,
Expand Down
Loading
Loading