Skip to content

docs(scripts): record what a re-baseline absorbs, and that BASELINE.commit cannot be checked from main (objectui#7848) - #9208

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-7848-record-absorbed-drift
Sep 11, 2026
Merged

docs(scripts): record what a re-baseline absorbs, and that BASELINE.commit cannot be checked from main (objectui#7848)#9208
baozhoutao merged 1 commit into
mainfrom
claude/issue-7848-record-absorbed-drift

Conversation

@claude

@claude claude Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Part of #7848 — ruling item (2) of 2026-09-11T11:54Z. ⛔ This does not close the card: item (1) is answered, but the condition #7848 describes is still live (ui-components sits ~590 bytes from firing, and the slimming route is objectui#9204).

Prose only. The diff is 125 added comment lines in scripts/check-eager-closure-budget.mjs and nothing else. No constant moves in either direction — not MAX_EAGER_CLOSURE_GZIP_BYTES, not BASELINE, not any PER_CHUNK_GZIP_CEILINGS or PER_CHUNK_BASELINE entry, not EXHAUSTED_HEADROOM_FLOOR_MULTIPLE or its granularity, not REGRESSION_THIS_GATE_MUST_CATCH_BYTES, not the 'ui-components': 4_289 allowance. No verdict logic changes. Not a line of executable behaviour.

What goes in

1. The mechanism, and the one re-baseline here whose record can be audited. BASELINE is re-pinned by an absolute fresh reading of a named tree, never by a delta — the right construction, with a consequence the file states nowhere: a fresh reading is silent about its own composition, so every byte that arrived since the previous baseline and was not removed in between is inside the new constant with no name on it, while the record written above that constant names only the cause that motivated the move.

2. What was carried in anyway, with the chain from #7848 re-derived, and an explicit refusal to write a floor under it.

3. The provenance caveat. BASELINE.commit is a branch tip; a reader who runs git show BASELINE.commit from a main checkout gets nothing and, until this PR, had no way to learn from the file why.

⭐ The correction — one of the three figures I was dispatched to record does not mean what the dispatch says it means

The dispatch and the ACCEPT above it both carry this as "the stronger half":

In that same commit the total fell 410,553 (3,575,370 → 3,164,817) while the locale chunk alone fell 415,781 (456,196 → 40,415). ⇒ +5,228 B of non-locale content was absorbed in a single commit, silently.

Re-derived rather than copied. The arithmetic reproduces exactly and the inference does not. The answer is in the same table the two subtractions come from:

claimant bytes
aggregate fall -410,553
the catalogue chunk alone -415,781
⚠️ i18n-runtime, a new eager member +5,329
⇒ the i18n family, net -410,452
⇒ residual — everything that is not i18n -101

i18n-runtime is the i18n provider, hooks and formatters, carved out by the same change and staying eager. It does not exist in the control column at all, it is i18n, and it accounts for 5,329 of those 5,228 — leaving 101 bytes moving the other way. So that re-baseline absorbed essentially nothing; it is the clean case, not the incriminating one.

Two independent confirmations, neither of them the subtraction:

  • The chunk counts. Control d8b4739d4 weighed 50 of 518 chunks, 755d34a5f 51 of 528 — ten new chunks, exactly one of them eager. Nine deferred catalogues plus i18n-runtime is the only assignment that fits.
  • The report's own shape. In apps/console/vite.config.ts, emitEagerClosureReport sets eagerChunkCount: files.length and eagerGzipBytes as the sum over files, so any per-chunk figure the report carries is by construction an eager member. i18n-runtime appears in the "after" column as a report reading.

⇒ the PR records the accounting rather than the inference, and records what made it auditable: three unmoved control rows and both chunk counts. A re-baseline that publishes only its new constant cannot be audited at all — not because its number is wrong, but because nothing in it is falsifiable. That is the actionable half, and it is now a clause in "## Raising it".

⚠️ Second correction — "≥41,582 B" cannot be written as a floor

The chain reproduces where it is checkable:

  • 52cac3886 is an ancestor of 755d34a5f — compare reports ahead_by=627, behind_by=0, merge base 52cac3886. ✅
  • d8b4739d4 to 755d34a5f is ahead_by=1. ✅ The docblock's same-container one-commit A/B claim is independently confirmed.
  • 3,263,896 − 3,222,314 = 41,582. ✅

But the third leg of the argument — "#9122 removed locale-catalogue bytes, a chunk disjoint from the drift" — is an assertion about bytes that are, by the card's own words, unattributed, and this file's own record contradicts its premise: i18n-locales measured 446,076 on 177afeba1 (2026-09-03) and 454,602 on bbe285ee7 (2026-09-10), +8,526 bytes, and that window contains 52cac3886 (2026-09-05). No reading of the catalogue exists on 3d257c85a or on 52cac3886 to separate the two.

⇒ the file now says a large part of the 41,582 is inside the constant, and says why a floor is refused. Writing "at least 41,582" would be exactly the unbound figure objectui#8964 exists to refuse.

⭐ Third — a gap nobody on the card has named: the measured tree is not the tree that landed

755d34a5f is the first commit of the branch, not the pull request. PR #9122's head is d7d6c6a688, 22 commits further on, squash-merged as 77b2a18a16; one of those commits (bf268c3723) merged 15 more commits of main in. Three of the 22 edit non-test source inside framework's own group (packages/(core|react|types)), 175 added lines against 47 removed:

modified  +35   -32   packages/core/src/utils/filter-tokens.ts
modified  +118  -8    packages/react/src/SchemaRenderer.tsx
modified  +22   -7    packages/react/src/hooks/usePageAssignment.ts

Control with a known direction that hits in the same run — the same filter over the same 79-file compare, test files instead of source, which must be non-empty or the filter is matching nothing:

added     +157  -0    packages/core/src/utils/__tests__/filter-tokens.spec-derived-7265.test.ts
added     +322  -0    packages/react/src/__tests__/SchemaRenderer.enablementEnvelopeConfigBag.test.tsx
added     +192  -0    packages/react/src/hooks/__tests__/usePageAssignment.declarationOrder-7298.test.tsx

⛔ What that costs gzipped is unmeasured, not small — nobody has built 77b2a18a16, and this round deliberately spends no console build. The BASELINE docblock already warns that CI weighs the merge ref while this is the branch tree, "so the two differ by whatever has landed on main since"; the half it did not cover is that they also differ by whatever landed on the branch after the reading was taken. The PR adds the actionable rule: take the reading on the tree you are about to merge, or name the commits that arrived after it.

Provenance, recorded as a consequence — ⛔ not as a fix

git fetch origin 755d34a5f1 answers "couldn't find remote ref", and git merge-base --is-ancestor 755d34a5f1 origin/main exits 128 — the object does not resolve, which is ⛔ not the exit 1 that would mean "resolved, and not an ancestor". The previous 34a1578ef does resolve and is genuinely not an ancestor: exit 1, read against a control leg d9580f4647 (2026-09-06T01:40Z, five minutes newer than 34a1578ef, so at least as deep) that exits 0 in the same shallow checkout — an exit 1 from a shallow clone means nothing without one.

⛔ Both are squash-merged branch tips and that is the file's deliberate convention working, not an error, and nothing here proposes changing it. The consequence is what nobody had written down: the provenance of the number this board argues about cannot be checked from a main checkout with git alone. The file now says so, names the compare API as what does resolve these shas, and names the reachable squash merge 77b2a18a16 as a handle on what landed⚠️ explicitly never a substitute for the reading.

Verification

Exit codes by redirect-then-capture, ⛔ never through a pipe; verdict lines quoted from the tool, ⛔ never a bare $?.

check command exit verdict line
gate unit test vitest run --project unit scripts/__tests__/check-eager-closure-budget.test.ts 0 Test Files 1 passed (1) · Tests 138 passed (138)
every other test reading this source the six further files that reference check-eager-closure-budget 0 Test Files 6 passed (6) · Tests 226 passed (226)
Type Check pnpm type-check:scripts 0 tsc -p tsconfig.scripts.json, no diagnostics
Lint eslint scripts/check-eager-closure-budget.mjs --no-inline-config --format json 0 1 file linted, 0 errors, 0 warnings
Lint coverage node scripts/check-lint-coverage.mjs 0 lint coverage: 46/46 packages linted, 0 with outstanding errors (0 total).
Changeset Declaration node scripts/check-changeset-presence.mjs 0 No source or published contract of a released package changed in this range, so no changeset is owed.
Control Byte Scan node scripts/check-control-bytes.mjs 0 check-control-bytes: OK (scanned 7400 tracked text file(s); skipped 85 binary).
line-citation gate node scripts/check-new-cross-file-line-citations.mjs 0 VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0
governed surface node scripts/check-governed-queue-guard.mjs --test scripts/check-eager-closure-budget.mjs 0 NOT GOVERNED — 1 path(s) checked against 5 governed surface(s); none matched.

⭐ Ablation — the objectui#7528 pin really does read the two chunk counts this PR adds. Run from the committed state, HEAD carrying the change; mutation proved on disk before the run (HEAD blob 895a2c64 → mutated 09c9c907, both grep anchors printed verbatim, injected spelling counted 0 before and 2 after); restore is git checkout HEAD -- path under trap ... EXIT INT TERM with an absolute root, ⛔ never a bare git checkout -- path.

Removing the two commit hashes from that one paragraph — and nothing else — turns the pin red and it names both counts:

× check-eager-closure-budget.mjs writes no chunk count that no commit anchors
  states a chunk count (50 of 518 chunks, 51 of 528 chunks)
Tests  1 failed | 137 passed (138)

Restored and proved by state, ⛔ not by an exit code: git diff HEAD empty, and the file's blob back to 895a2c64 — byte-identical to HEAD.

Declared narrowings (⛔ these are declared deviations, not silent ones; the farm runs on CI):

  • Test (shard N/4): ran the seven test files that read this source rather than the whole sharded suite. Enumerated by grep -rl check-eager-closure-budget scripts/__tests__ plus the two consumers of scripts/__tests__/helpers/attached-docs.ts — both already in the set.
  • Lint: linted the one file the diff touches. Population read from ESLint's own --format json output over the root scope: 336 files, of which this diff touches 1. Invariance: eslint.config.js configures no type-aware linting (no parserOptions.project, no projectService), so a comment-only edit in one .mjs cannot move the verdict on any untouched file. The root scope's single pre-existing error is e2e/live/global-setup.ts no-console, untouched by this diff and outside pnpm lint's turbo scope.
  • Build Docs: its first step is "Check for docs changes" and this diff changes no docs input — declared to CI.
  • No console build was spent. This round is prose about numbers already measured, every figure is re-derived from this file's own recorded readings plus the GitHub compare API, and a sibling agent has the machine under load. The one figure that would need a build — what the 22 post-measurement commits cost gzipped — is written as unmeasured rather than estimated.

All figures above were re-derived in this round from the file, from apps/console/vite.config.ts, and from the compare API. ⛔ None were copied from the dispatch comment or from the item-(1) report.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr


Generated by Claude Code

…ommit cannot be checked from `main` (objectui#7848)

Prose only. No constant moves in either direction and no verdict logic changes:
the diff is comments in `scripts/check-eager-closure-budget.mjs`.

The file re-pins `BASELINE` by an absolute fresh reading of a named tree, never
by a delta. That is the right construction, and it has a consequence the file
states nowhere: a fresh reading is silent about its own composition, so every
byte that arrived since the previous baseline and was not removed in between is
inside the new constant with no name on it, while the record above that constant
names only the cause that motivated the move. Ruling item (2) of 2026-09-11 asks
for that to be written down. Three things go in.

1. The mechanism, plus the one re-baseline here whose record can be audited.
   objectui#7479's control/after table closes its own accounting: the aggregate
   fell 410,553 while the catalogue chunk alone fell 415,781, and the remaining
   5,228 is not absorbed non-locale content — it is `i18n-runtime` (+5,329), a
   new eager member of the closure that the same change created, leaving 101
   bytes moving the other way. The eager chunk counts agree independently
   (`d8b4739d4` 50 of 518, `755d34a5f` 51 of 528: of ten new chunks exactly one
   is eager). What makes that auditable is the three unmoved control rows, not
   the total.

2. What was carried in anyway. objectui#7848 measured 3,263,896 on `52cac3886`
   against 3,222,314 on `3d257c85a` — 41,582 unattributed bytes — and
   `52cac3886` is an ancestor of `755d34a5f` (`ahead_by=627, behind_by=0`), so a
   large part of it is inside the constant. A floor under that figure is refused
   and the refusal is recorded: the one large removal in the span is the
   catalogue change, and this file's own record has the catalogue growing across
   the drift window (446,076 on `177afeba1` to 454,602 on `bbe285ee7`), so drift
   that is unattributed cannot also be asserted disjoint from the chunk that
   left.

   And the tree that was measured is not the tree that landed: after
   `755d34a5f` that branch took 22 more commits before the squash merge
   `77b2a18a16`, three of which edit non-test source inside `framework`'s own
   group.

3. Provenance. `BASELINE.commit` is a branch tip; `git fetch origin 755d34a`
   answers "couldn't find remote ref" and `git merge-base --is-ancestor` cannot
   resolve the object. That is the convention working, not a defect — but the
   consequence is that the provenance of this constant cannot be checked from a
   `main` checkout with git alone, and the file now says so and names the
   compare API and the reachable squash merge.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 51 chunks) 3112.0 KB 3134.8 KB
Main entry chunk (gzip) 144.2 KB 350 KB
Entry file index-Cu_XhSZf.js
Status PASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.69KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 500.84KB 114.81KB
core (index.js) 8.52KB 3.41KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 209.38KB 57.92KB
fields (index.js) 247.41KB 62.43KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.21KB 2.26KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.95KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 14.81KB 3.63KB
plugin-calendar (index.js) 49.03KB 13.93KB
plugin-charts (index.js) 71.52KB 19.98KB
plugin-chatbot (index.js) 195.32KB 46.51KB
plugin-dashboard (index.js) 131.18KB 34.62KB
plugin-designer (index.js) 215.68KB 44.27KB
plugin-detail (index.js) 251.95KB 65.34KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.79KB 34.19KB
plugin-gantt (index.js) 166.94KB 41.04KB
plugin-grid (index.js) 211.56KB 57.50KB
plugin-kanban (index.js) 46.10KB 14.33KB
plugin-list (index.js) 112.58KB 27.65KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.54KB 3.31KB
plugin-view (index.js) 84.42KB 20.80KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 94.03KB 31.02KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 14.82KB 4.99KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 14.27KB 5.47KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

Copy link
Copy Markdown
Contributor

ACCEPT — objectui#7848 ruling item (2) / PR #9208

Reviewed against the diff at d7bc1c282069439ef67556b41c264cd0e0ccecdf; ls-remote, the report's sha and the branch head agree.

1. Verified in the tree

claim how verdict
one file, prose only git diff --numstat = 125 0, one path ✅ zero deletions
genuinely comment-only counted added lines that are not comment-or-blank: 0 ✅ not a claim — a count, with the predicate stated
no constant moved, either direction grepped every +/ line for MAX_EAGER_CLOSURE_GZIP_BYTES, PER_CHUNK_GZIP_CEILINGS, PER_CHUNK_BASELINE, EXHAUSTED_HEADROOM*, REGRESSION_THIS_GATE*, gzipBytes:, chunks: empty
the refutation behind §2 origin/main line 851 carries `` i18n-runtime (provider/hooks)

2. ⛔ The round refuted the starred centrepiece of its own dispatch, and it was right to

I told this round that +5,228 B of non-locale content absorbed in a single commit was "the stronger half of this PR". It does not exist. i18n-runtime is a new eager chunk carved out by the same change — - → 5,329 — so the i18n family net is −410,452 and the residual non-i18n movement is −101 bytes. The re-baseline absorbed essentially nothing.

The full retraction is on the card, at the altitude the claim was made: #7848 (comment) — it originated in the item-(1) report, I endorsed it as "a second absorption nobody had recorded", and I starred it in the dispatch. Three seats, two rows of a five-row table, nobody read to the bottom.

And the round found the rule my own instruction was missing. I wrote "re-derive every figure yourself… if one does not reproduce, that is the most valuable thing you can report." The four subtractions did reproduce, to the byte. In the round's words: "Arithmetic reproducing is not the same as an inference holding, and the instruction asks for the subtractions. What found the defect was reading the table the subtractions were taken from." ⇒ ⛔ re-deriving a figure is not re-deriving a claim. That goes into the dispatch template above the old line.

3. Why the PR is right to record less than it was told to

Two of the three things I ordered recorded did not survive re-derivation, and the PR says so instead of writing them:

  • ⛔ the 41,582 is not written as a floor. Its third leg asserts disjointness about bytes the card itself calls unattributed — you cannot hold both — and the file records i18n-locales growing +8,526 across a window containing 52cac3886. A large part is inside the constant; how large is not established, and that is what the PR states.
  • ⚠️ the provenance caveat is split rather than flattened. I said both baseline commits are "not an ancestor". 34a1578ef resolves and genuinely is not (exit 1, against a matched-age control leg that exits 0 in the same shallow checkout); 755d34a5f exits 128 — the object is not there at all. ⛔ An exit 128 is the absence of an ancestry reading, not a negative one, and an exit 1 from a shallow clone with no control leg means nothing either.

⭐ And what it recorded beyond the order is the best part: the accounting is published with its rows, its residual (−101), and the three unmoved control rows plus both chunk counts that make it auditable — with the observation that a record publishing only its new constant is not falsifiable at all. One clause landed in ## Raising it to that effect. That is the mechanism this card exists to close, stated generally rather than as one incident.

4. Routed, ⛔ not folded in — objectui#9209, and it re-opens a number I accepted

755d34a5f is the first commit of objectui#7479's branch, not the pull request. ahead_by=1 is exact; reading it as "the PR is one commit" kept 22 further branch commits invisible to four seats — one merging 15 commits of main, three editing non-test source inside framework's own group (175 added / 47 removed).

⚠️ BASELINE.gzipBytes under-reports the tree that merged by an unmeasured amount, and item (1)'s reading of the whole 21,912-byte live excess as post-merge drift is partly wrong — an unknown part was already on the branch at merge time. That figure appears in my ACCEPT on the card; it is now qualified there too. Filed bare, asking for one console build of 77b2a18a16 and ⛔ explicitly not asking for any constant to move.

5. Gates

Unit test 138/138, the six other tests that read this source 226/226, type-check:scripts 0, targeted lint 0, changeset "none owed", control bytes 7,400 files, line-citation gate 0 new. ⛔ Zero console builds spent, as ordered. ⭐ Narrowings declared with their evidence rather than taken silently, including the invariance argument for lint (no type-aware linting configured, so a comment-only edit in one .mjs cannot move any untouched file's verdict).

⭐ And the ablation is the right one: it mutates out the two commit hashes the new prose anchors and shows objectui#7528's pin go red, naming both new counts — states a chunk count (50 of 518 chunks, 51 of 528 chunks). ⇒ the prose this PR adds is held by a test, which is the only thing that makes a documentation PR more than a promise.

Governed Surface Queue Guard unparameterised exits 1 on could not read GITHUB_EVENT_PATH — correctly read as PRECONDITION NOT MET / NOT MEASURED, ⛔ not as a red gate; the --test form returns NOT GOVERNED.

6. Card state

objectui#7848 stays open — agreed, and for the round's reason: both ruled items are executed, but that is not the card's closing condition. Its first sentence is about a live margin, and ui-components sits at ~590 bytes of runway. ⛔ Closing on item (2) would be objectui#8241's shape, which is why objectui#8554 exists. The PR says Part of #7848, ⛔ never Fixes.

Proceeding to the merge queue.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 11, 2026 19:06

Copy link
Copy Markdown
Contributor

Armed — auto-merge SQUASH, and the probe I will run afterwards, written first

Armed 2026-09-11T19:06:59Z on head d7bc1c282069439ef67556b41c264cd0e0ccecdf. ⓘ The arm call echoed method: MERGE; ⛔ not the authority — origin/main is linear and prior branch commits are not ancestors of it, so the queue squashes.

The probe, posted BEFORE the merge

Every expected value extracted from the tree at d7bc1c2820 and 1f4e02995a just now, ⛔ not retyped from the report. Post-merge legs scoped to <merge>^ <merge>, ⛔ never origin/main. ⚠️ Every leg names an explicit ref — this seat's working checkout is ~580 commits stale, so a command that reads the working directory is reading 2026-09-06.

L1 — the file set. git diff --name-only <merge>^ <merge> = exactly 1 path: scripts/check-eager-closure-budget.mjs.

L2 — prose only, as a count with its predicate stated. git diff --numstat = 125 0 — ⛔ the zero is half the assertion — and the number of added lines that are not comment-or-blank must be 0 under grep -vcE '^\+[[:space:]]*(\*|//|/\*|$)'. ⛔ "Prose only" asserted as a claim is worth nothing; asserted as a count over a stated predicate it is a reading.

L3 — ⛔ the leg this whole round exists under: NOT ONE CONSTANT MOVED. Every line below must be byte-identical at <merge>^ and <merge>:

export const MAX_EAGER_CLOSURE_GZIP_BYTES = 3_210_000;
export const REGRESSION_THIS_GATE_MUST_CATCH_BYTES = 89 * 1024;
export const EXHAUSTED_HEADROOM_FLOOR_MULTIPLE = 0.1;
export const EXHAUSTED_HEADROOM_ALLOWANCE_GRANULARITY_MULTIPLE = 0.01;
PER_CHUNK_GZIP_CEILINGS  'vendor-objectstack':1_254_000  'i18n-locale-en':50_000  framework:100_000  'ui-components':399_000
PER_CHUNK_BASELINE       'vendor-objectstack':1_235_029  'i18n-locale-en':40_415  framework:72_245   'ui-components':391_095
EXHAUSTED_HEADROOM_ALLOWANCES  'ui-components':4_289
BASELINE  gzipBytes:3_164_817  chunks:51  totalChunks:528  commit:'755d34a5f'

⚠️ Their line numbers MOVEMAX_EAGER_CLOSURE_GZIP_BYTES sits at 371 on the base and 474 on the head, the mechanical consequence of 125 lines landing above it. ⛔ That is not a change, and it is exactly why this leg compares strings and never a path:line.

L4 — what moved, positive in both halves.

anchor <merge>^ <merge>
What a re-baseline ABSORBS 0 2
line count of the file 2,448 2,573 (+125)

⭐ The heading reads 2, not 1 — measured rather than assumed, because it appears in the header's index as well as at the section.

L5 — nothing moved in transit, by blob. scripts/check-eager-closure-budget.mjs on the merge commit = 895a2c64caa4243e07fc71e0731118b5fc3a7286. ⭐ Free cross-check: this is the same blob prefix the report quotes as the pre-mutation baseline of its ablation (895a2c6409c9c907). The round's ablation and my read of the tree describe one object.

L6 — the prose is HELD BY A TEST, and this leg is why that matters. objectui#7528's pin requires every chunk count in this file to be anchored by a commit hash. Both anchors, two-sided:

anchor <merge>^ <merge>
50 of 518 1 2
51 of 528 0 1

⇒ the new accounting introduces a chunk count that did not appear in this file before, and the pin the round ablated is what keeps it anchored. ⛔ A documentation PR whose sentences nothing tests is a promise; this one is not.

⛔ NOT MEASURED: the gate's own run and the seven test files. This seat has a bare, stale checkout — and the lesson of the last round is that a runnable gate here answers fluently about the wrong tree. CI's run on this head is the reading.

A leg that comes back amber will be published with its cause. ⛔ It will not be re-run into green.


Generated by Claude Code

@baozhoutao
baozhoutao added this pull request to the merge queue Sep 11, 2026
Merged via the queue into main with commit 75d34d6 Sep 11, 2026
36 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-7848-record-absorbed-drift branch September 11, 2026 19:32

Copy link
Copy Markdown
Contributor

LANDED — 75d34d6047

Probe run scoped to 75d34d6047^ 75d34d6047. All six legs green.

leg reading
L1 file set 1scripts/check-eager-closure-budget.mjs
L2 prose only numstat = 125 0, and added lines that are not comment-or-blank = 0 ✅ — the predicate stated, not the claim asserted
L3NOT ONE CONSTANT MOVED all 17 constant lines appear on both sides of the merge, byte-identical ✅
L4 what moved What a re-baseline ABSORBS 0 → 2; file 2,448 → 2,573 lines ✅
L5 nothing moved in transit blob 895a2c64caa4243e07fc71e0731118b5fc3a7286 ✅ — the same object the round's ablation used as its baseline
L6 the prose is held by a test 50 of 518 1 → 2, 51 of 528 0 → 1

⭐ L3 is the leg this whole round existed under, and it is why the constants' line numbers moving (MAX_EAGER_CLOSURE_GZIP_BYTES 371 → 474) is not a finding: the leg compares strings, never a path:line. 125 lines landed above them; nothing landed in them.

⭐ L6 is what makes this more than a promise. objectui#7528's pin requires every chunk count in this file to be anchored by a commit hash, the new accounting introduces a count that was not in the file before, and the round ablated that pin to show it go red naming both counts. A documentation PR whose sentences nothing tests is a wish.

⛔ The correction this round carried, restated so the PR record holds it

The dispatch's starred centrepiece — +5,228 B of non-locale content absorbed in a single commitdoes not exist. i18n-runtime is a new eager chunk carved out by the same change (- → 5,329); the i18n family nets −410,452 and the residual non-i18n movement is −101 bytes. That re-baseline absorbed essentially nothing.

The figure originated in the item-(1) report, I endorsed it, and I starred it in the dispatch. Full retraction on the card: #7848 (comment)

⭐ And the rule it produced, in the round's own words: "the four subtractions DID reproduce, to the byte. Arithmetic reproducing is not the same as an inference holding… What found the defect was reading the table the subtractions were taken from." ⇒ ⛔ re-deriving a figure is not re-deriving a claim.

⇒ the PR correctly records less than it was told to: the 41,582 is not written as a floor (its third leg asserts disjointness about bytes the card calls unattributed — you cannot hold both), and the provenance caveat is split rather than flattened (34a1578ef exits 1 and genuinely is not an ancestor; 755d34a5f exits 128 — the absence of a reading, not a negative one).

Card state

objectui#7848 stays open. Both ruled items are executed, but that is not the card's closing condition — its first sentence is about a live margin, and ui-components sits ~590 bytes from firing. ⛔ Closing on item (2) would be objectui#8241's shape, which is why objectui#8554 exists. The slimming route is filed as objectui#9204; the branch/PR gap this round found is objectui#9209.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants