Skip to content

docs(scripts): record the eager-closure cause as a standing baseline - #8293

Merged
os-justin merged 2 commits into
mainfrom
claude/issue-8283-eager-closure-void-restore-condition
Sep 7, 2026
Merged

os-justin merged 2 commits into
mainfrom
claude/issue-8283-eager-closure-void-restore-condition

Conversation

@os-justin

Copy link
Copy Markdown
Collaborator

Fixes #8283

Prose and provenance only — no executable line in the file changed (proof below).

The eager-closure budget's cause note pointed the next author at an upstream fix that is not coming: RESTORE CONDITION: when that lands, re-measure and bring this ceiling and BASELINE back down together, conditioned on objectstack#16063. That upstream fix was ruled against — maintainer verbatim 「16063 c」, director-seat decision batch #59, recorded on objectui#7122 on 2026-09-06. The condition could therefore never fire, and the numbers read as a temporary exception awaiting reversal when they are the standing baseline.

The note now says so. It keeps the objectstack#16063 citation — the provenance the gate's own header requires — while stating that its sense changed from a condition to wait out into the recorded cause the ceiling rests on, forbids writing a fresh condition in its place, and names where the authorisation and figures landed (objectui#7122 decision batch 1 item 1 = "B + A"; objectui#7685, 639114c4d).

Verdict on the second sentence, :575

The card required a verdict on a second, similarly-shaped sentence — re-measure and lower both numbers together, at :559 before this change and :575 after. It is a different note, it is correct as written, and it is deliberately left untouched.

Four reasons, each re-derived rather than pattern-matched:

  1. Different constants. :575 closes the docblock attached to PER_CHUNK_GZIP_CEILINGS — heading ## Raising one at :564, declaration at :577. Its "both numbers" are a per-chunk ceiling and its measurement in PER_CHUNK_BASELINE (:681), which the same paragraph names at :568. The note corrected here governs the aggregate pair, MAX_EAGER_CLOSURE_GZIP_BYTES and BASELINE.
  2. Different trigger. Its condition is the landing of local payload-shrinking work, citing objectui#5324 as where the candidates are named. objectstack#16063 appears nowhere in that block — its only three occurrences in the file are :328, :329 and :334, all inside the aggregate note this PR rewrites.
  3. The trigger was not ruled against. The 「16063 c」 ruling refuses an upstream prose-stripped @objectstack/spec browser build. It says nothing about this repo shrinking its own eager closure, and the same docblock already names a concrete local candidate at :561 — taking the i18n catalogues out of the eager closure. If anything the ruling makes local shrink work the only remaining route, so this condition is more live, not less.
  4. Different sentence function. :570 is a ratchet guardrail: Do not LOWER one below the measured figure to express an aspiration. The trailing clause is its counterpart — it names the one legitimate route to lowering (do the real work, re-measure, move ceiling and baseline together). It makes no claim that today's numbers are temporary, which was the entire defect in the aggregate note. Rewriting it in this PR's idiom ("nothing is coming") would be false and would delete a correct rule.

Sweep for completeness rather than fixing only what was pointed at: grepping re-measure|RESTORE CONDITION|when that lands|when it lands|awaiting|back down together|lower both returns exactly two condition-shaped sentences in the file — the one rewritten here and :574-:575. The remaining hit at :1067 is evaluateHeadroomSensitivity's docblock describing when drift is detected, not a condition.

The frozen numbers are byte-identical

The card's safety argument for touching this file at all. Verified two ways against the current origin/main, not asserted:

  • Every changed line is docblock prose. All 30 changed lines (23 added, 7 removed — net +16, which is exactly the line-number shift) match ^[+-] \*. The set of changed lines that are not docblock continuations is empty.
  • Comment-stripped content hashes identical. Stripping every docblock and // line from both revisions and hashing the remainder gives 970db2bea4494c394f3ccb2562f93da7aa0e4423f5ba7d7ec0825ad456c8bf75 on both origin/main and this branch; diff of the two stripped files is empty.

The four frozen values as they now stand, all unmoved:

value line
MAX_EAGER_CLOSURE_GZIP_BYTES 3_597_000 :349 (was :333)
BASELINE.gzipBytes 3_551_191 :378 (was :362)
REGRESSION_THIS_GATE_MUST_CATCH_BYTES 89 * 1024 :390 (was :374)
PER_CHUNK_GZIP_CEILINGS 1_254_000 / 455_000 / 71_000 / 399_000 :582-:585

Sensitivity re-derived rather than trusted, reading 89 * 1024 as the expression it is: 3,597,000 - 3,551,191 = 45,809, and 45,809 / 91,136 = 0.503x — against the docblock's own H = REGRESSION / 2 requirement at :90. It holds.

Gates

Exit codes captured before any pipe; verdict lines quoted from each gate's own output. All run after merging origin/main.

gate exit verdict
the 5 test files referencing this gate, plus the attached-docs helper the two of them import 0 Test Files 5 passed (5) / Tests 219 passed (219)
node scripts/check-control-bytes.mjs 0 check-control-bytes: OK (scanned 6596 tracked text file(s); skipped 85 binary)
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.
node scripts/check-governed-queue-guard.mjs --self-test 0 OK check-governed-queue-guard self-test: 132 cases pass
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.

No changeset is added: the gate's own verdict line above says none is owed, this file being tooling rather than published source of a released package.

A pin does read docblock prose — reported, as the card asked

The card asked whether any pin reads the note's text. One class does, and a phrase-grep does not find it: scripts/__tests__/check-eager-closure-budget.test.ts pins attached prose structurally, through attachedDocs() in scripts/__tests__/helpers/attached-docs.ts, which locates the JSDoc block preceding an export const without using line numbers.

What saves this change is not that no pin reads prose, but that those pins are scoped to other constants' blocks. They read BASELINE and PER_CHUNK_BASELINE only, and assert:

  • every commit a baseline carries as data appears in its own attached prose;
  • what each baseline carries as data, recorded so the pin above cannot go vacuous in silence (BASELINE carries exactly one commit, PER_CHUNK_BASELINE carries none);
  • every "BASELINE carries X" claim in attached prose matches the live value — the objectui#6778 defect as an assertion;
  • and a boundary assertion, expect(perChunk.prose).not.toContain('## Raising one'), which pins that the locator does not over-capture into the neighbouring PER_CHUNK_GZIP_CEILINGS block.

This PR rewrites the block attached to MAX_EAGER_CLOSURE_GZIP_BYTES, and leaves the block attached to PER_CHUNK_GZIP_CEILINGS alone. Neither is among the pinned pair, and the ## Raising one heading the boundary assertion names is untouched. The suite is green.


🤖 Generated with Claude Code

https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S


Generated by Claude Code

The note on MAX_EAGER_CLOSURE_GZIP_BYTES told the next author to wait for
objectstack#16063 to land and then bring the ceiling and BASELINE back down
together. That upstream card was ruled against — maintainer verbatim
"16063 c", director-seat decision batch #59 recorded on objectui#7122 on
2026-09-06 — so the growth is accepted upstream permanently and the condition
can never fire. Left as it was, the note mislabels a standing baseline as a
temporary exception awaiting reversal.

The objectstack#16063 citation stays, because the gate's own header requires a
re-baseline to carry a visible, justified cause; what changes is that it reads
as the recorded ruling rather than a pending condition, and the authorising
decision (objectui#7122 decision batch 1 item 1 = "B + A", landed by
objectui#7685 as 639114c) is named so the next reader need not reconstruct
it.

Prose and provenance only. MAX_EAGER_CLOSURE_GZIP_BYTES, BASELINE, every
per-chunk ceiling and REGRESSION_THIS_GATE_MUST_CATCH_BYTES are byte-identical
across this commit.

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

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3472.1 KB 3512.7 KB
Main entry chunk (gzip) 143.9 KB 350 KB
Entry file index--2K1PeVY.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) 15.67KB 5.75KB
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) 5.13KB 2.35KB
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) 497.99KB 113.90KB
core (index.js) 7.20KB 2.88KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 189.15KB 52.56KB
fields (index.js) 243.14KB 61.38KB
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) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
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.94KB
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) 11.71KB 4.29KB
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) 5.12KB 1.74KB
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) 15.16KB 3.68KB
plugin-calendar (index.js) 48.03KB 13.29KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 193.54KB 46.04KB
plugin-dashboard (index.js) 131.43KB 34.43KB
plugin-designer (index.js) 213.21KB 43.63KB
plugin-detail (index.js) 248.56KB 63.89KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 131.01KB 32.32KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 208.58KB 56.63KB
plugin-kanban (index.js) 52.83KB 14.63KB
plugin-list (index.js) 113.38KB 27.73KB
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.33KB 3.25KB
plugin-view (index.js) 84.46KB 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) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
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.55KB 2.45KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 13.64KB 4.59KB
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.74KB 1.41KB
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 (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

@os-justin
os-justin marked this pull request as ready for review September 7, 2026 09:40
@os-justin
os-justin added this pull request to the merge queue Sep 7, 2026
Merged via the queue into main with commit 9de7758 Sep 7, 2026
32 checks passed
@os-justin
os-justin deleted the claude/issue-8283-eager-closure-void-restore-condition branch September 7, 2026 09:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants