Repository navigation
feat(app-shell): the built-in metadata designers leave the console's first load (objectui#11939 step 2) - #11982
Conversation
…mports dynamically (objectui#11939 step 2) The package entry keeps its bare import of `register-builtins.ts` for the three registrations whose registries are not observable (anchors, default JSONSchemas, the datasource resource) and loads the built-in previews and inspectors with a module-scope dynamic `import()` of the new `register-builtin-designers.ts`, then calls its `registerBuiltinDesigners()`. The built-in pass runs inside `registerAsBuiltIns`, so a built-in fills only a type with no entry: a host registration made before the chunk arrives is kept, and one made after replaces the built-in as before. The dev-only preview gallery registers the designers explicitly before its first render. Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
…dence, late arrival, entry auto-registration (objectui#11939 step 2) Three new pins: - builtinDesigners.hostPrecedence-11939: a host designer registered before the built-ins arrive is kept in all three registries; one registered after replaces the built-in and its reader re-renders; a second pass is inert. - builtinDesigners.lateArrival-11939: the Data pillar field rail shows its missing-inspector sentence, then the real ObjectFieldInspector when registerBuiltinDesigners() lands. - entryRegistersBuiltinDesigners-11939: importing the package entry registers the built-in designers with no host call. Tests that relied on the entry (or register-builtins) registering the designers synchronously now call registerBuiltinDesigners() at module scope. Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
…he lazy-views plugin's note on register-builtins (objectui#11939 step 2) Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
…a render-time mutation (objectui#11939 step 2) Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
…ing app-shell sources (objectui#11939 step 2) The console's tsc program checks with noUnusedLocals, app-shell's does not, so a static import of an app-shell source module pulled five designer files into the console's type-check (TS6133). The gallery now waits for the package entry's own designer chunk through the public `useRegisteredMetadataPreviewTypes` hook before it mounts its list, and the three console suites load the registration with `vi.importActual` at module scope. Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
… (objectui#11939 step 2) Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
… registrations run now (objectui#11939 step 2) Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
|
| Step | Outcome |
|---|---|
| Build packages | success |
| Check console performance budget | failure |
Which half objected:
| Eager-closure half | Verdict |
|---|---|
| Aggregate closure ceiling | ✅ pass |
| Per-chunk ceilings | ✅ pass |
| Per-chunk membership (declared packages) | ✅ pass |
| Ceiling sensitivity (headroom) | |
| Ceiling freshness (checkout vs. base branch) | ✅ pass |
⚠️ A broken gauge half is a verdict about the ceiling, not about the bundle: that line has drifted out of range of the regression it exists to catch, or the report behind it cannot be trusted. It does not say anything grew. TheCheck console performance budgetstep log carries the ceiling and the number it was compared against.
Reason: The entry chunk measured 71.5 KB, but the eager-closure half of this gate returned no trustworthy VERDICT: the report could not be read, a ceiling has drifted out of range of the regression it must catch, or (objectui#6245) a ceiling was replaced on the base branch after this checkout was made. The step log says which. This is not a passing budget — and it is not a size regression either.
See the workflow run for details.
📦 Bundle Size Report
| Package | Size | Gzipped |
|---|---|---|
| app-shell (consoleActionDispatch.js) | 0.20KB | 0.19KB |
| app-shell (index.js) | 19.52KB | 7.19KB |
| app-shell (runtime-config.js) | 22.59KB | 7.89KB |
| app-shell (types.js) | 0.01KB | 0.04KB |
| app-shell (urlParams.js) | 10.11KB | 3.87KB |
| auth (ActiveOrganizationStorage.js) | 27.95KB | 10.04KB |
| auth (AuthContext.js) | 0.31KB | 0.24KB |
| auth (AuthGuard.js) | 2.07KB | 1.00KB |
| auth (AuthProvider.js) | 40.22KB | 10.61KB |
| auth (AuthShell.js) | 3.49KB | 1.40KB |
| auth (ForgotPasswordForm.js) | 12.21KB | 3.45KB |
| auth (LoginForm.js) | 18.15KB | 5.40KB |
| auth (PreviewBanner.js) | 0.90KB | 0.50KB |
| auth (RegisterForm.js) | 6.72KB | 2.24KB |
| auth (SocialSignInButtons.js) | 9.70KB | 3.93KB |
| auth (UserMenu.js) | 3.39KB | 1.21KB |
| auth (auth-gate-events.js) | 1.29KB | 0.66KB |
| auth (authStyles.js) | 5.04KB | 1.72KB |
| auth (createAuthClient.js) | 41.19KB | 11.12KB |
| auth (createAuthenticatedFetch.js) | 8.54KB | 3.46KB |
| auth (index.js) | 3.63KB | 1.64KB |
| 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) | 27.11KB | 7.97KB |
| collaboration (LiveCursors.js) | 3.17KB | 1.27KB |
| collaboration (PresenceAvatars.js) | 6.28KB | 2.60KB |
| collaboration (PresenceProvider.js) | 2.79KB | 1.13KB |
| collaboration (index.js) | 1.68KB | 0.73KB |
| collaboration (useCollaborationTranslation.js) | 6.50KB | 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) | 587.49KB | 141.58KB |
| core (index.js) | 10.00KB | 3.96KB |
| create-plugin (index.js) | 27.94KB | 9.51KB |
| data-objectstack (index.js) | 240.39KB | 67.09KB |
| fields (index.js) | 268.74KB | 68.04KB |
| i18n (LocalizationContext.js) | 2.92KB | 1.42KB |
| i18n (builtinAggregateLabels.js) | 0.86KB | 0.49KB |
| i18n (currency.js) | 2.59KB | 1.22KB |
| i18n (fallbackInterpolation.js) | 6.25KB | 2.77KB |
| i18n (i18n.js) | 8.87KB | 3.64KB |
| i18n (index.js) | 5.52KB | 2.39KB |
| i18n (pickLocalized.js) | 9.86KB | 3.95KB |
| i18n (provider.js) | 39.35KB | 12.88KB |
| i18n (translateFn.js) | 0.20KB | 0.18KB |
| i18n (useDisplayLocale.js) | 3.52KB | 1.76KB |
| i18n (useObjectLabel.js) | 36.87KB | 9.88KB |
| i18n (useSafeTranslation.js) | 7.14KB | 2.92KB |
| layout (index.js) | 41.50KB | 11.82KB |
| 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) | 6.62KB | 2.45KB |
| mobile (useResponsive.js) | 0.72KB | 0.42KB |
| mobile (useSpecGesture.js) | 5.52KB | 2.10KB |
| mobile (useTouchTarget.js) | 1.01KB | 0.54KB |
| permissions (MePermissionsProvider.js) | 13.86KB | 5.00KB |
| permissions (PermissionContext.js) | 0.31KB | 0.25KB |
| permissions (PermissionGuard.js) | 0.89KB | 0.45KB |
| permissions (PermissionProvider.js) | 6.52KB | 2.26KB |
| permissions (discardProofCache.js) | 1.04KB | 0.55KB |
| permissions (evaluator.js) | 8.33KB | 3.07KB |
| 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) | 16.04KB | 3.92KB |
| plugin-calendar (index.js) | 53.43KB | 15.54KB |
| plugin-charts (index.js) | 84.71KB | 23.25KB |
| plugin-chatbot (index.js) | 199.63KB | 47.46KB |
| plugin-dashboard (index.js) | 144.20KB | 38.95KB |
| plugin-designer (index.js) | 231.46KB | 48.87KB |
| plugin-detail (index.js) | 248.57KB | 65.47KB |
| plugin-editor (index.js) | 2.23KB | 1.05KB |
| plugin-form (index.js) | 177.11KB | 45.88KB |
| plugin-gantt (index.js) | 179.17KB | 45.07KB |
| plugin-grid (index.js) | 248.22KB | 68.84KB |
| plugin-kanban (index.js) | 52.22KB | 16.38KB |
| plugin-list (index.js) | 117.68KB | 29.40KB |
| plugin-map (index.js) | 27.24KB | 9.03KB |
| plugin-markdown (index.js) | 13.88KB | 4.80KB |
| plugin-report (index.js) | 44.12KB | 12.29KB |
| plugin-timeline (index.js) | 39.10KB | 11.81KB |
| plugin-tree (index.js) | 15.07KB | 5.33KB |
| plugin-view (index.js) | 91.09KB | 22.94KB |
| 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.81KB | 3.58KB |
| 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) | 120.63KB | 39.56KB |
| react (data-invalidation.js) | 5.05KB | 2.08KB |
| react (index.js) | 4.50KB | 2.06KB |
| react (schema-input.js) | 4.31KB | 2.07KB |
| react (spec-input.js) | 0.20KB | 0.18KB |
| sdui-parser (body-dialect.js) | 4.50KB | 1.99KB |
| sdui-parser (codegen.js) | 9.45KB | 3.76KB |
| sdui-parser (dashboard-widget-options.js) | 3.07KB | 1.30KB |
| sdui-parser (index.js) | 7.30KB | 3.12KB |
| sdui-parser (input-type.js) | 2.84KB | 1.40KB |
| sdui-parser (parse.js) | 25.28KB | 7.80KB |
| sdui-parser (provenance.js) | 3.84KB | 1.90KB |
| sdui-parser (types.js) | 0.28KB | 0.23KB |
| sdui-parser (validate.js) | 23.87KB | 7.83KB |
| types (ai.js) | 4.39KB | 2.17KB |
| types (api-types.js) | 0.20KB | 0.18KB |
| types (app.js) | 4.12KB | 1.61KB |
| types (authoring-nodes.js) | 0.20KB | 0.19KB |
| types (base.js) | 0.20KB | 0.18KB |
| types (blocks.js) | 0.20KB | 0.18KB |
| types (cloud.js) | 0.20KB | 0.18KB |
| types (complex.js) | 4.44KB | 2.07KB |
| types (crud.js) | 0.20KB | 0.18KB |
| types (dashboard-filter-alias.js) | 6.23KB | 2.74KB |
| types (dashboard-widget-layout.js) | 2.06KB | 0.96KB |
| 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) | 1.13KB | 0.65KB |
| 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) | 5.78KB | 2.70KB |
| types (layout.js) | 0.20KB | 0.18KB |
| types (managed-by.js) | 0.19KB | 0.18KB |
| types (mobile.js) | 5.00KB | 2.39KB |
| types (navigation.js) | 0.20KB | 0.18KB |
| types (node-slots.js) | 7.18KB | 2.34KB |
| types (objectql.js) | 0.20KB | 0.18KB |
| types (overlay.js) | 0.20KB | 0.18KB |
| types (permissions.js) | 2.52KB | 1.31KB |
| 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) | 4.99KB | 1.96KB |
| types (spec-ui-namespace.js) | 0.20KB | 0.19KB |
| types (strict-authoring-face.js) | 19.93KB | 7.25KB |
| 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
…e designers left, plus half a regression (objectui#11939 step 2, ruling 6070754914) MAX_EAGER_CLOSURE_GZIP_BYTES 3,391,484 -> 3,281,467: the reading 3,235,899 on f05f015 plus 45,568 (half of the 89 KiB regression), under ruling D on objectui#11939 (record 6070754914). BASELINE moves onto f05f015 in the same commit. The docblock entry carries the ruling verbatim, the bytes that left (155,517 against the 2855785 control), the end of objectui#11942's 5,120 B allowance and the 5,052 B of drift it absorbed. No per-chunk row moves. Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
…INE to 3160.1 (objectui#11939 step 2) Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
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
Size Limits
|
Contract reviewServed-tier: PR objectui#11982 (card objectui#11939, step 2 of objectui#6795's order), read-only at tier. Inputs: the card's body and its 13 comments, the PR body, its 23-file list and the net diff against ① Derived judgments
② Semver level
③ Boundary flagsOpen questions (report 6062475046):
Deviations (report and PR body):
Acceptance notes (observed, no carrier):
Nothing is left unanswered, and nothing escalated here blocks the landing. Implemented-by: VERDICT: PASS |
Fixes #11939
Clause-②: yes
Step 2 of objectui#6795's order, as ruled on objectui#11942 (item C, comment 6056819248): the built-in metadata designers leave the console's first load. Step 1 (
a835c31, PR objectui#11963) made their three registries observable, so a reader that rendered before a designer was registered re-renders when it is; this step relies on that. Neither refused shape of ruling A on objectui#11798 is used: there is no per-route await and no lazy sub-entry — importing the package still registers every built-in designer with no host action.Implemented by a dispatched
os-dev(sessionhttps://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8), claim 6060604189 as amended by the seat after report 6062475046.The ruling, and the ceiling it pins
The ceiling is ruled: record 6070754914 on objectui#11939 (director-seat batch #294 item 3, letter D), the maintainer's 「11939 上线适当多预留一些没问题,不要一直因为这个改代码」. Its operative paragraph, verbatim:
Pinned in
scripts/check-eager-closure-budget.mjs, in one commit (8d5100ed):mainat28557855(control)f05f015(the reading)MAX_EAGER_CLOSURE_GZIP_BYTES: 3,391,484 →BASELINE: 3,375,344 on406f760→f05f015(289 of 2474 chunks)BASELINEmainread 3,385,979 on1c51e973, the commit that landed the allowance, which is 385 B under the pre-allowance line of 3,386,364. It read 3,391,416 on28557855: +5,437 in all, 5,052 B of it above that line and still eager after the designers leave. The literal objectui#11942 formula would land 5,052 B under this branch's reading. The same gap was 4,057 B ond7e9e9abin report 6062475046, beforemainmoved.vendor-objectstackmoved −6,468 (1,599,283 against its 1,623,000 ceiling, 0.26x),ui-components−19,framework+10 andi18n-locale-en0. ThePER_CHUNK_BASELINEprose now namesf05f015as the aggregate's commit.BASELINE.gzipBytes, and headroom (45,568) under one regression (91,136).pnpm check:eager-closureon this branch's build: "✅ aggregate closure 3160.1 KB measured / 3204.6 KB ceiling (headroom 44.5 KB = 0.50x the 89.0 KB regression)", every per-chunk line ✅, exit 0.Bundle Analysison head6db39695(merge ref onmain5bc55c0c) reads "✅ aggregate closure 3160.0 KB measured / 3204.6 KB ceiling (headroom 44.5 KB = 0.50x the 89.0 KB regression)", with every per-chunk line, membership and ceiling freshness ✅.When each built-in becomes available
main)register-builtins.ts)import()arrives: the entry's module scope runsimport('./views/metadata-admin/register-builtin-designers.js').then(({ registerBuiltinDesigners }) => registerBuiltinDesigners()), with a.catchthat logs oneconsole.errorregister-builtins.tsobject(studio-canvas-preview.tsx, the fourth registry)Between a reader's first render and the chunk's arrival, every reader shows its existing "designer missing" state, then the designer, with no reload (step 1's hooks). A plain
get*/list*read right after importing the package can find no built-in yet; that is stated in the changeset. No export is added, removed or changed.How a host's own registration keeps precedence
The built-ins register inside
registerAsBuiltIns(module-internal, inpreview-registry.ts): during that pass the shared store fills only a type that has no entry, in all three observable registries. So:register*replaces the built-in and readers re-render, last-write-wins as always.previews/index.tsandinspectors/index.tsare untouched; they still call the publicregister*, and only the pass changes what a registration may replace.The
sideEffectsdiffNone.
register-builtin-designers.tsperforms no load-time registration: it exports one function, which the entry's.thencalls, so every bundler keeps it by its USE. Measured alternative (the dispatch's suggested route — a side-effectful module named in the array, both spellings):check:side-effects-arrayexits 1 with "STALE ./dist/views/metadata-admin/register-builtin-designers.js — the array names it, but nothing in it registers at load time", because the gate walks the entry's static edges only.register-builtins.tskeeps its two entries (it still registers three things at load time).Measurements
Instrument: the console's
apps/console/vite.config.tsthrough Vitebuild(), with one read-only chunk-module dump plugin, underos-verify-lock.sh, all in the same container. It is calibrated against the ordinaryCI=true pnpm exec vite build, which wrote the sameeagerGzipBytesto the byte onf05f015(3,235,899). Two earlier pairs gave the same shape of move:d7e9e9ab→ its merge, 155,532 B (report 6062475046), anda835c314→ its merge.28557855(main)f05f015(this branch)165 modules leave the eager closure and none joins. By rendered bytes:
metadata-admin/previews554,838 (56 modules);metadata-admin/inspectors396,857 (38);metadata-admin41,664 (12: the three registries, the external-datasource panels, three schema helpers,metadata-form-i18n);lucide-reacticons 37,230 (56);@objectstack/specidentity/index.mjs27,098 (1);InterfaceListPage+pageKindNode14,572.Per-chunk gzip:
src−150,696,RecordDetailView−19,482,vendor-objectstack−6,468,createDerive−1,556,ActionResultDialog−1,244;default-inspector-registry−13,284,ReportDefaultInspector−8,156,InterfaceListPage−4,454,pageKindNode−80, and 56vendor-icon-*chunks −16,781;Tests
New pins:
views/metadata-admin/__tests__/builtinDesigners.hostPrecedence-11939.test.tsx— host-first kept in all three registries; host-after replaces and its reader re-renders; a second pass changes no entry and commits no render (counted withReact.Profiler).views/metadata-admin/__tests__/builtinDesigners.lateArrival-11939.test.tsx— the Data pillar field rail (objectui#6795's silent-failure site) shows its missing-inspector sentence, then the REALObjectFieldInspectorwhenregisterBuiltinDesigners()lands, with no remount.src/__tests__/entryRegistersBuiltinDesigners-11939.test.tsx— importing the package entry registersFlowPreview,FlowInspectorandHookDefaultInspectorby identity, with no host call.Suites that relied on synchronous registration now register explicitly at module scope: five
metadata-adminsuites that bare-import./register-builtins, and three console suites (preview-samples-designer-options,App.agentChatLink-10640,ApiConsolePage.requestPreset-10591), which load the registration withvi.importActualso the app-shell sources stay out of the console'stscprogram.The dev-only designer gallery waits for the entry's own chunk through the public
useRegisteredMetadataPreviewTypeshook before it mounts its list. Browser check (theverifyskill, own dev server): "Loading the built-in designers…" at DOMContentLoaded, then 19 designer sections; control ond7e9e9ab: 19 sections.Reverse verification, each through
scripts/ablation-replace.mjson a committed tree, each restored to the HEAD blob withgit diff HEADempty:.thenno longer calling the registration → the entry pin goes RED (no designer registered);On the final head
6db39695(after merging28557855and re-pinning the ceiling), these runs passed:check-eager-closure-budget,check-docs-route-eager-closure,check-eager-locale-catalogues,console-vite-alias-closure-4925,render-budget-comment,check-side-effects-array,vite-declared-lazy-views).8d5100ed:pnpm --filter @object-ui/app-shell type-checkandpnpm --filter @object-ui/console type-check.6db39695, every one exit 0:check:eager-closure,check:side-effects-array,check:sdui-registration-pins,check:control-bytes,check:changeset-claims, and the changeset-presence check.The budget suite's two rendered-baseline pins follow
BASELINEto "3160.1" (commit6db39695).Earlier, on
7a30a7b6, a run over 186 derived files (every suite that imports the entry,register-builtins, the registries or a built-in registrar) had 185 pass. The one failure is the flake noted under Acceptance notes.Deviations
sideEffectswas not taken (measured STALE, above); the door is a pure module plus an explicit call.noUnusedLocalstype-check (TS6133 ×5).origin/mainmerged three times (d7e9e9ab,989b1908,28557855), never rebased.Acceptance notes
Observed, not filed (no carrier):
inspectors/index.ts's header still says it is imported as a side effect frommetadata-admin/index.ts(stale since objectui#6776).previews/index.ts's "register after this module runs, last-write-wins" is still true, and now incomplete (a host may also register before; it is kept).scripts/vite-declared-lazy-views.tskeeps its "25 runtime values" count: it sits in the dated objectui#6776 narrative.ObjectHooksPanel.newHookTarget-11820.test.tsxfailed once in a 186-file parallel batch (its label not yet hydrated) and passes alone on this branch and ond7e9e9ab.Generated by Claude Code