Skip to content

fix(app-shell): the object / data previews and the federated datasource panel read the designer locale (objectui#10862, slice 3) - #10906

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-10862-designer-english-slice-3
Sep 28, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-10862-designer-english-slice-3

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Part of #10862
Clause-②: no — rows are added and a locale is passed; each en row equals today's literal. No declared surface or stored value moves.

Slice 3 of 3 (the object / data previews), per triage 5860733428, seat 4's release 5863137337 and the slice-1 / slice-2 ACCEPTs 5861649175 / 5862348719. Dispatched by the domain:ui seat 2 PM (claim 5863389454, session session_014mXUNuFomfj24w7s1pZzhN), implemented on claude/issue-10862-designer-english-slice-3 from main 35d68c4. Same shape as objectui#10832 / #10850 / #10857 / #10871 / #10880: engine.* rows whose en value is the literal each replaces, plus zh, read in the designer locale the surface receives. No second catalogue.

This PR leaves the card open. The dispatch made this the card's final slice unless a family site is still English after it. The census below found nine more files outside this slice's list that still render English under zh-CN (listed under Acceptance notes), so the first line is Part of, and objectui#10862 remains open as their carrier.

What changed

All under packages/app-shell/src/views/.

  • metadata-admin/i18n.ts: 140 en rows (each equal to the literal it replaces, byte for byte) and 140 zh rows, placeholders identical. Three existing rows are reused with the same meaning: designer.canvas.renameHint (the canvas rename tooltip), engine.inspector.add.block (the add-block trigger, the label PagePreview's outline strip already reads) and engine.inspector.view.object (the view preview's no-object code span, the label the view inspector shows that field under).
  • The registered previews (previews/ObjectPreview.tsx, DatasetPreview.tsx, ViewPreview.tsx, ReportPreview.tsx, PagePreview.tsx, ValidationPreview.tsx) read their rows in the locale prop their hosts already pass. Every fallbackHint literal in previews/ now reads a row: the ten the card counted in seven files. DashboardPreview and FlowPreview already read engine.dashboardPreview.malformed / engine.flowPreview.malformed, so they are recorded, not changed. A sentence around a code span is one row whose hole withNodes (previews/row-nodes.ts) fills: the view preview's no-object note, whose code span now shows the right panel's field label (engine.inspector.view.object) in the same locale, and the validation preview's removed-type sentence.
  • previews/PageBlockCanvas.tsx and previews/block-types.ts: the canvas's own words, plus the add-block picker's category headings and block names. BLOCK_TYPE_META entries gain a labelKey (the add-widget picker's shape from objectui#10804); CATEGORY_LABEL_EN becomes CATEGORY_LABEL_KEY, its en rows the English it carried. The picker's search matches the displayed name or the type id. label stays as the English name.
  • previews/SourcePageEditor.tsx: the textarea label and the preview hint.
  • The column manager: previews/FieldsListEditor.tsx (heading, empty note, positional label) and FieldListRow in previews/ViewColumnPanes.tsx (the remove control). previews/view-column-io.ts colLabel takes an optional positional formatter, so the col N fallback reads the designer row where it renders while the module stays free of the string tables (its default is unchanged).
  • metadata-admin/external/ExternalDatasourcePanel.tsx (carried from slice 2's ACCEPT): its own nine sites.
  • Locale threading: PagePreview passes its locale to PageBlockCanvas and SourcePageEditor; studio-design/StudioDesignSurface.tsx passes its own to its three SourcePageEditor mounts; previews/DatasourcePreview.tsx passes its locale to ExternalDatasourcePanel.
  • celAuthoring.ts is untouched: no static import is added to it.
  • One .changeset/10862-designer-object-data-previews-locale.md (patch for @object-ui/app-shell).

H1 census, confirmed per file

Read at source per file, then each hit confirmed as rendered by a pin through the real component. A site is one rendered designer word: an element's text, a title, an aria-label or a placeholder.

file rows rendered sites not counted, and why
ObjectPreview 1 1 hint props (PreviewShell no longer renders them)
DatasetPreview 15 15 hint; the error banner (the server's text); header labels and cell values (field metadata and data)
ViewPreview 4 (+1 reused) 4 hint (three); the reused row fills the no-object note's code span inside that note's own site
ReportPreview 6 6 hint
PagePreview 8 8 hint; the regions-shaped outline fallback region N · M (a regions page in design mode renders the block canvas, never the outline strip, so it cannot show); record labels (data)
PageBlockCanvas + block-types 55 (+2 reused) 57 region and slot names, block ids, type badges and region widths (author data); the region_N names addRegion writes (stored); blockLabel's block fallback (only a component with no type, which PageComponent refuses); the AI heading (routed through a row whose zh is AI, as the metadata domain table's is); the misc heading (no block type is in that category, so it never renders)
SourcePageEditor 2 2 hint; Monaco's model path
ValidationPreview 36 36 hint; the severity, rule-type and event tokens (stored enum values); a bare JSON Schema title (the standard's name); the — of an absent otherwise; label, name, description, message, tags, states, fields, regex and CEL sources (author data)
FieldsListEditor 3 3 column labels and field names (author data)
ViewColumnPanes 1 1 ColumnChip's own Remove … label: ColumnChip has no production importer (dead export; see Acceptance notes)
ExternalDatasourcePanel 9 9 the schemaMode token (stored value); the snapshot time (display-locale formatting, objectui#9909's channel); a refresh failure's own message (producer text)

Totals: 140 new rows, 142 rendered sites (Add region and Select … each render at two places; the two canvas reused rows add two sites; the third reused row adds none, being part of the view preview's no-object site), every site pinned. The AI and misc heading rows are the two rows not counted as sites.

H2: every production host passes the locale

  • The registered previews read the locale prop. Every registered-preview mount passes useMetadataLocale(): ResourceEditPage (PreviewComponent … locale={locale}), EmbeddedItemEditor (Preview … locale={locale}), StudioDesignSurface (the interfaces pillar's Preview and the automations pillar's React.createElement(Preview, {…, locale})).
  • PageBlockCanvas has one host, PagePreview, which now passes the locale it receives at both mounts.
  • SourcePageEditor has two hosts: PagePreview (split mode, now passes locale) and StudioDesignSurface (preview mode on the canvas, editor mode twice in the inspector; each now passes the surface's useMetadataLocale() value).
  • ExternalDatasourcePanel has one host, DatasourcePreview, which now passes its locale.
  • The column manager (FieldsListEditor, FieldListRow) reads useMetadataLocale(), as the add-field popover rendered beside those rows (AddFieldPopover, same file as FieldListRow) already did. Its hosts (ViewColumnInspector, ViewVariantInspector, ReportDefaultInspector) hold the same hook's value, so no host edit was needed.

Pins

Two new files, all mounting the real component under I18nProvider in the case's language: previews/dataPreviews.i18n-10862-s3.test.tsx (54 cases) and previews/externalDatasourcePanel.i18n-10862-s3.test.tsx (8 cases). PageBlockCanvas and SourcePageEditor are mounted through PagePreview, ExternalDatasourcePanel through DatasourcePreview, so the cases also read the threading. Every zh expectation is read back from the catalogue and guarded by zhRow (neither the echoed key nor the en row); every en case reads the en row through t / tFormat for en-US. A case reads every site on every mount before it judges, so a failing case lists each missing site. The error-boundary hints show through stand-ins that throw on demand (SchemaRenderer, the chart and report renderers, ObjectFormCanvas, InterfaceListPage), each mock spreading the real module; the report's loading text shows through a stand-in that suspends.

  • Red run on the base (the 15 changed sources checked out at 35d68c4, blobs equal base; i18n.ts and the pins at HEAD 497678c; trap restore, blobs equal HEAD, git diff HEAD 0 bytes, porcelain 0 lines): Tests 31 failed | 31 passed (62). The 31 failures are the 30 zh cases plus the one case that reads the new labelKey / CATEGORY_LABEL_KEY wiring. The 30 zh cases list 151 missing sites covering 140 distinct keys: 138 of the 140 new rows (all but the AI and misc headings named above) and the two canvas reused rows; the third reused row is read inside the no-object case's code-span check. All 30 en controls pass against the base sources, and so does the unit case that compares every block name's en row with the English the table carries, so each en row renders exactly what the literal rendered.
  • Ablation through ablation-replace.mjs (wrap mode) on PagePreview.tsx: the locale thread to the region canvas cut (anchor 1 to 0, blob e2f4198 to 6ba718f) gives Tests 5 failed | 49 passed (54). The five are exactly the zh PageBlockCanvas cases; every en case stays green. Restored: blob equals HEAD e2f4198, git diff HEAD empty. The pins import sources by relative path, so no dist sits between mutation and run.
  • Green at HEAD 497678c: the two pin files with FieldsListEditor.retiredAliases, view-column-io.retiredAliases and clientValidation.skew (the slice-1 skew test), Test Files 5 passed (5), Tests 77 passed (77).

Consumer sweep

  • Static closure: a base-vs-HEAD import-graph diff over every test file in the repo (vitest alias map, static non-type imports). Five tests' closures grow, each by previews/row-nodes.ts alone (it imports only react): EmbeddedItemEditor.preview, ValidationPreview.test, ViewPreview.optionsFold-7928, emptyCollection-8570 and the new pin file. The new ExternalDatasourcePanel edge to i18n.ts grows no test's closure (every test reaching the panel already reaches i18n.ts). celAuthoring.ts gains no import.
  • Full-replacement mocks: an AST census of vi.mock / vi.doMock of @objectstack/spec/ui, @object-ui/core and @object-ui/i18n across the 455 tests whose closure reaches a changed module: 33 sites, all spread the real module; positive control: the same recogniser flags clientValidation.skew.test.tsx's @objectstack/spec/ui mock (outside that set) as a full replacement. Every mock of the designer i18n module inherits it too.
  • Literal readers: a whole-repo scan of test files for the 140 replaced en literals finds 82 tests inside that 455 set (most on short common words); the ones that read this slice's sentences (DatasetPreview.test, PageBlockCanvas.test, ReportPreview.dataset, ValidationPreview.test, page-preview-record-type-10482, palette-discussion-alias, emptyCollection-8526 / -8570, inspectorStrings.i18n-10586, EmbeddedItemEditor.preview) mount in en and see the same words. Outside the set, e2e/live/studio-editor.spec.ts matches /Add block/i against a live en console, unchanged by construction.
  • The run: all 455 tests whose closure reaches a changed module, plus the 17 previews/ suites outside that set and the skew control, in seven locked batches at f19d127 (the code of HEAD; later commits touch only the changeset and a test type): Test Files 76 passed (76) six times and Test Files 17 passed (17) once: 473 files, 4665 tests passed, 0 failed, 1 skipped (a pre-existing conditional skip in flow-node-config.spec-reconciliation). Every batch VERDICT command-exit 0.
  • Type check at HEAD 497678c: turbo run build --filter=@object-ui/app-shell^... (28 of 28 tasks), then pnpm --filter @object-ui/app-shell type-check (script echoed: tsc --noEmit && tsc -p tsconfig.test.json), VERDICT command-exit 0; tsc -p tsconfig.test.json --listFilesOnly lists both pin files.

Gates (at HEAD 497678c, each exit 0)

check:i18n-designer-parity (Every en row has a zh row, and every shared row carries the same placeholders.) · check:i18n-drift (140 key(s) added, 0 en values changed) · check:i18n-keys · check:designer-field-key-parity · check:control-bytes · check:new-line-citations (0 new citations) · check:vi-mock-specifiers / check:vi-mock-inherit / check:vi-mock-override-shape · check:test-path-roots · check:unreferenced-sources · check:icon-record-names · check:esm-specifiers · check:self-import · check:phantom-deps · check:handler-key-reads · check:metadata-write-doors · check:action-forward-parity · check:element-data-source-declaration · check:prompt-keys · check:changeset-claims (report-only: five pending changesets name a touched file, 6310, 6681, 7125, 8632 and rotten-pugs-invent; each paragraph read, still true) · check:pending-changeset-literals · check-changeset-presence · check-changeset-no-major · check-changeset-fixed · check-changeset-overwrite · check-governed-queue-guard --test (NOT GOVERNED, 19 paths) · check:i18n-dead-keys (report-only; none of the 140 new rows listed).

ESLint on the 18 changed source and test files (--format json, 18 files): 0 errors. Every modified file carries the same error and warning counts as its base blob, with and without --no-inline-config; the two new test files carry none. The config enables no type-aware linting (no project / projectService in the resolved parser options) and no local rule reads the disk, so no untouched file can change verdict.

NOT MEASURED: check:eager-closure and check:eager-locale-catalogues (both read a console build; the latter printed PREREQUISITE NOT MET here); the console performance budget (CI's). A browser drive of the preview gallery, whose I18nProvider mounts in en (the dev-harness gap the card names as out of scope).

Serial

  • PR objectui#10888's previews/__tests__/block-config-schema-parity-8216.test.ts is untouched (it has since merged).
  • Open PRs' file lists re-read before the first edit (10 open, the release PR among them) and before opening this PR (6 open): no file in common with this branch.
  • git merge-tree --write-tree of HEAD against a fresh origin/main 9f0c84a: exit 0, no conflict. Re-run at fix round 1 (HEAD 6a21fd3) against a fresh origin/main 8522396: exit 0, tree 8ac1563, and no file main changed since the base is in this PR's diff.

Fix round 1 (HEAD 6a21fd3)

Contract review at 497678c returned wording findings only; this round takes all of them in one commit.

  • Glossary, zh only, each now the catalogue's existing term: engine.pageBlockCanvas.type.recordRelatedList 关联列表 (as engine.inspector.pageBlock.option.location.record_related and engine.inspector.action.location.record_related); engine.validationPreview.transitions 状态流转, .transitionsOn {field} 的状态流转, .noTransitions 未声明任何状态流转。 (as the rules editor's engine.studio.rules.transitions / .typeStateMachine); engine.pagePreview.sampleOne / .sampleOther {count} 条示例 (示例记录, as engine.actionPreview.placement.sampleRecord and perm.cel.test.record); engine.pageBlockCanvas.itemN 第 {n} 项. No en row moves; placeholders unchanged.
  • Changeset: the page-block-canvas bullet now names the sites converted (region and container labels; the no-regions, empty-region, inherited-slot and empty-group states; the add-region and add-block buttons; drop target, rename tooltip, select labels, each block's render-failure hint; the picker's search box, headings and names) and no longer claims slot labels, which show as written, as the closing paragraph says.
  • Pins read every zh value from the catalogue, so none needed an edit; none hard-codes 相关列表, 状态转换 or 样本.
  • Re-run at 6a21fd3: the two pin files with ValidationPreview.test, PageBlockCanvas.test, palette-discussion-alias and page-preview-record-type-10482 under the verify lock, Test Files 6 passed (6), Tests 95 passed (95), VERDICT command-exit 0. check:i18n-designer-parity (Every en row has a zh row, and every shared row carries the same placeholders.), check:i18n-drift (140 key(s) added, 0 en values changed), check:i18n-keys, check:control-bytes, check:new-line-citations, check:changeset-claims, check:pending-changeset-literals, check:i18n-dead-keys, check-changeset-presence, check-changeset-no-major, check-changeset-fixed, check-changeset-overwrite, check-governed-queue-guard --test (NOT GOVERNED, 19 paths): each exit 0.
  • Not taken: a pin for StudioDesignSurface's three SourcePageEditor locale threads. Mounting StudioDesignSurface needs its own scaffolding (router, metadata client, pillar state), which no existing pin file carries, so it would not be one case in an existing file. The threads are read by review and by tsc, not by a test.

Acceptance notes

  • The family is not closed: nine files outside this slice still render English under zh-CN (read at source, not driven in a browser), which is why this PR says Part of:
    • metadata-admin/external/SchemaBrowser.tsx, ValidationPanel.tsx, ImportObjectDialog.tsx: the federated panel's tab contents and import dialog never read the designer t (the filter placeholder, the Refresh button, the table headers, Import, the unavailable hint, the ten diff-kind labels, Run validation, the match summaries, the dialog's title, labels and buttons).
    • previews/FlowCanvas.tsx: the edge tooltips (the un-declared-cycle sentence, (back-edge)) and the approval node summary (N approver(s), · all).
    • previews/FlowPreview.tsx: the variables panel's in / out tags.
    • previews/FlowRunsPanel.tsx: an expanded run's run … / · trigger … line.
    • previews/FieldStub.tsx: the address field's placeholder (Street / City, State ZIP / Country).
    • previews/useObjectFields.ts (Object not found, shown inside the localized engine.form.noObjectFields sentence) and previews/useDatasetCatalog.ts (Dataset not found, the dashboard widget inspector's error slot).
  • Files outside the claim's listed files: studio-design/StudioDesignSurface.tsx and previews/DatasourcePreview.tsx (one locale attribute each, the threading the claim names), previews/block-types.ts (the picker's name table) and previews/view-column-io.ts (the optional positional formatter). Same defect class, no other behaviour.
  • ColumnChip in previews/ViewColumnPanes.tsx keeps its English Remove … label: nothing in the product imports it (dead export), so it is neither counted nor converted.
  • Pending changesets 8570-inline-empty-markers ("the wording of both sentences is preserved", about the validation preview's none) and palette-canonical-discussion-5495 (the label "Discussion") stay true in en; in zh the same words now read 无 and 讨论.
  • ActionPreview still carries its own copy of withNodes from slice 1 (a refactor, not a locale fix).
  • The preview gallery still mounts I18nProvider in en (out of scope, as the card says).
  • ExternalDatasourcePanel stores its federation-unavailable sentence in state when a refresh fails, so after a language switch that sentence keeps the old language until the next refresh (review note, not changed).

Generated by Claude Code

…ce panel read the designer locale (objectui#10862, slice 3)

ObjectPreview, DatasetPreview, ViewPreview, ReportPreview, PagePreview,
PageBlockCanvas (with its add-block picker), SourcePageEditor,
ValidationPreview, the view column manager (FieldsListEditor, FieldListRow)
and ExternalDatasourcePanel read engine.* rows in the designer locale, each
en row the literal it replaces. PagePreview threads its locale to
PageBlockCanvas and SourcePageEditor, the Studio surface to SourcePageEditor,
DatasourcePreview to ExternalDatasourcePanel; the column manager reads
useMetadataLocale() as its add-field popover already does.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN
…ol per site (objectui#10862)

Every site mounts the real component under the i18n provider in its
language: the previews in the locale their hosts pass, PageBlockCanvas and
SourcePageEditor through PagePreview, ExternalDatasourcePanel through
DatasourcePreview. zh expectations are read back from the catalogue and
guarded against a missing or English row; en cases read the en row through
t / tFormat for en-US.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN
…objectui#10862)

A case collects what it did not find across all of its mounts and fails
once, so a failing case lists each missing site; the controls a case drives
(the add-block trigger, the catalog refresh button) are found by what they
are rather than by the words under test.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN
…ldInfo (objectui#10862)

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

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 5 pending changeset(s) describe a file this change touches

Their bodies publish verbatim into the CHANGELOG at the next release, so this is a request to re-read them against your diff — addressed here because you are the one seat that can answer it without re-deriving anything.

⛔ Nothing here blocks, and nothing here is a verdict on your change. This gate exits 0, is not a required context, and judges name resolution, never meaning: it asked whether a pending body names a file you touched. "Is this sentence still true?" is the one question it will not answer, and the one you are being asked to answer.

.changeset/6310-designer-formula-key-retired.md

  • names packages/app-shell/src/views/metadata-admin/i18n.ts → packages/app-shell/src/views/metadata-admin/i18n.ts — edited by this change

    Not touched: designer.field.formula ('Formula (CEL)') in packages/app-shell/src/views/metadata-admin/i18n.ts, a different and live key belonging to metadata-admin's ObjectFieldInspector — the surface that still authors formula expressions.

.changeset/6681-declared-lazy-marketplace-routes.md

  • names views/studio-design/StudioDesignSurface.tsx → packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx — edited by this change

    Both marketplace chunks were held by CHUNK CO-TENANCY, not by any import of the page: rolldown had parked components/SuggestedBindingsPanel.tsx (statically imported by the eager views/studio-design/StudioDesignSurface.tsx) in the first, and console/marketplace/InstalledListWidget.tsx (bare-imported by the package barrel for its SDUI registration) in the second. An app-shell-eager-leaves group in apps/console/vite.config.ts isolates those co-tenants so the three declared-lazy pages chunk by their own dynamic-only reachability. The console eager closure moves 3180.2 KB → 3171.5 KB gzipped (−8,888 bytes, 48 → 45 eager chunks) with the three per-chunk ceilings unmoved.

.changeset/7125-dashboard-empty-state-keys-retired.md

  • names packages/app-shell/src/views/metadata-admin/i18n.ts → packages/app-shell/src/views/metadata-admin/i18n.ts — edited by this change

    Not touched: table.noRows ('No rows to display') and engine.form.noRows (packages/app-shell/src/views/metadata-admin/i18n.ts, read at widgets.tsx) — two different, same-named keys in different namespaces. Nor the comments in WidgetEmptyState.tsx, DatasetWidget.tsx, ObjectDataTable.tsx and PivotTable.tsx that record WHY three widgets with three strings became one shared empty state; the packs' own comment keeps that rationale and now names the retirement instead of a row that is gone.

.changeset/8632-malformed-picklist-option-loud.md

  • names views/metadata-admin/i18n.ts → packages/app-shell/src/views/metadata-admin/i18n.ts — edited by this change

    Two new strings land in the designer's own en / zh tables — the metadata-admin console owns its strings in views/metadata-admin/i18n.ts and is deliberately outside the ten locale packs (packages/i18n/README.md, "Scope — the engine.* carve-out").

.changeset/rotten-pugs-invent.md

  • names block-types.ts → packages/app-shell/src/views/metadata-admin/previews/block-types.ts — edited by this change

    block-types.ts now declares BLOCK_RENDERER_ALIAS_GROUPS — spellings that resolve to the same registered renderer — and the canvas resolves display chrome through resolveBlockDisplayMeta(), which falls back to an alias sibling's entry. Keyed on renderer identity, not on "is excluded": palette exclusions that genuinely are not page blocks (element:text_input, element:record_picker, element:form, ai:chat_window) keep the generic box, and nothing became draggable — the palette offer list is unchanged.

Read the paragraph, not the line: both false halves of the objectui#8617 claim sat in one paragraph, and correcting either alone would have left it asserting the same wrong thing.

If a claim did go false, correct the body. That is precedented and prose-only, frontmatter untouched; check-changeset-overwrite.mjs will report the correction as its own case 2 ("correcting a declaration on purpose … legitimate"), which is the intended shape — one gate asks for the read, the other records the write.

Not covered, stated so nobody reads this as more: a born-false claim that spells no line address at all (objectui#9495 coordinated one by ORDINAL — "a grep finds that member first" — and deciding that means reading what the sentence means), a claim spelled as a symbol or a package rather than a backticked file name, and a file named ambiguously.

Compared the checked-out tree with 8522396c0 (merge-base with origin/main): 18 file(s) changed outside .changeset/, read against 1669 pending declaration(s) that publish a body (2263 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3100.4 KB 3104.5 KB
Main entry chunk (gzip) 148.4 KB 350 KB
Entry file index-WvnL7Qh2.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.58KB 6.17KB
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) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.17KB 10.58KB
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.39KB 1.21KB
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.52KB 3.45KB
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.13KB 7.95KB
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) 557.59KB 133.60KB
core (index.js) 9.93KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 226.44KB 63.00KB
fields (index.js) 261.01KB 66.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
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.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
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.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.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.01KB 3.93KB
plugin-calendar (index.js) 51.96KB 14.83KB
plugin-charts (index.js) 83.99KB 22.86KB
plugin-chatbot (index.js) 197.67KB 46.90KB
plugin-dashboard (index.js) 136.93KB 36.48KB
plugin-designer (index.js) 215.03KB 44.21KB
plugin-detail (index.js) 233.48KB 61.79KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 161.21KB 41.41KB
plugin-gantt (index.js) 170.35KB 42.19KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.17KB 12.20KB
plugin-timeline (index.js) 31.00KB 9.09KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 88.55KB 22.21KB
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) 119.16KB 39.05KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
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.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.22KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
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.26KB
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 (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) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.27KB 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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 497678cba5e4fafad9bd5f42c543517a2f904a43

① Derived judgments

  • Byte-equality: holds, 140 of 140. I checked this with a script, not by sampling. I extracted the en and zh tables from i18n.ts at head and at base 35d68c4 with node and compared them.
    • 117 rows occur exactly in the base source file of the site that reads them. The comparison applied only JSX newline collapse and joined ' + ' concatenations.
    • The 33 block names and 7 category headings were compared id by id: base label, head label and en row are all equal.
    • The 23 rows with placeholders (the {count}, {n}, {type}, {label}, {field}, {priority}, {events}, {time} and {measures} rows, plus the two withNodes rows) were checked by hand against the base template literals and JSX. They render the same text.
    • I found no whitespace, punctuation or smart-quote difference. —, … and ∅ match the base bytes.
  • Placeholders and code spans: en and zh carry identical {x} sets and identical backtick spans in all 140 rows. There are 140 zh rows with no orphans.
  • Reused rows: three, not the "two" the PR body and dev report state. They are designer.canvas.renameHint, engine.inspector.add.block and engine.inspector.view.object. The third fills the code span in the ViewPreview no-object note. Its en value Object equals the base code text, and it matches the label ViewVariantInspector shows. The code is right; the body's count is wrong. This does not block.
  • zh quality: about 40 rows read. Most are correct and natural and use the same glossary as slices 1 and 2: 度量, 维度, 区块, 校验, “表单”/“源码” 标签页, 联合 (joined), 属性, 只读, and the ,即可… sentence pattern. Two terms break the catalogue's existing usage:
    • Related list.
      • engine.pageBlockCanvas.type.recordRelatedList reads 相关列表.
      • The catalogue says 关联列表 in engine.inspector.pageBlock.option.location.record_related (记录关联列表) and in engine.inspector.action.location.record_related (记录 · 关联列表). The first of these is the page-block inspector in the same Studio.
    • Transitions.
      • engine.validationPreview.transitions, .transitionsOn and .noTransitions use 状态转换.
      • The rules editor for the same state-machine rule uses 状态流转 (engine.studio.rules.transitions 允许的状态流转, .typeStateMachine, and .addTransition 新增流转).
    • Optional nits:
      • engine.pageBlockCanvas.itemN 项 {n} reads awkwardly; 第 {n} 项 would be better.
      • engine.pagePreview.sampleOne and .sampleOther use 样本, while the catalogue says 示例 for sample record (示例记录).
  • Author data and producer text stay literal in both files the brief named.
    • ValidationPreview keeps these as written: label, name, description, message, tags, severity, events and rule-type tokens, states, fields, regex and CEL sources, the — of an absent otherwise, and a bare JSON Schema.
    • DatasetPreview keeps state.error (the server's message), the header labels from field metadata, and the cell values.
    • ExternalDatasourcePanel keeps the schemaMode token and the refresh failure's own err.message.
    • The hint props are correctly not converted: PreviewShell no longer renders hint.
  • Locale reach: holds. Every registered-preview mount passes useMetadataLocale() (ResourceEditPage, EmbeddedItemEditor, StudioDesignSurface interfaces pillar).
    • PageBlockCanvas has one host, PagePreview, which passes locale at both mounts. Every internal child passes it too: RegionSection, BlockRow, NestedChildren, both AddBlockButton and both BlockLivePreview mounts.
    • SourcePageEditor has four mounts and all pass locale. The three in InterfacesPillar take it from useMetadataLocale().
    • ExternalDatasourcePanel has one host, which passes it.
    • In ValidationPreview, TypeBody, NestedRule and CelBlock all receive it.
    • The column manager reads the hook, and its production hosts hold the same value.
    • No optional locale prop is left unfed in production.
    • Minor: ExternalDatasourcePanel stores the translated "unavailable" string in state, so it keeps the old language after a locale switch until the next refresh.
  • view-column-io.ts: default unchanged. The default positional is (n) =] col ${n}, still called with i + 1, and ?? keeps it lazy. FieldsListEditor is the only production caller. view-column-io.retiredAliases still expects col N.
  • PageBlockCanvas labelKey: stored type untouched.
  • Pins: sound, no tautology.
    • zh expectations are read from the catalogue and guarded by zhRow, so neither an echoed key nor an en row passes.
    • The en controls are read through t/tFormat and pass against the base sources. That independently proves en is unchanged.
    • Red on base per the dev's quoted output: 31 failed and 31 passed of 62, which is 30 zh cases plus the labelKey-wiring case.
    • The ablation cut PagePreview's thread to the canvas: 5 zh PageBlockCanvas cases fail and every en case stays green.
    • Gap (does not block): nothing pins StudioDesignSurface's three SourcePageEditor locale threads. Dropping them would stay green.
  • Slice lessons: hold.
    • celAuthoring.ts is not in the diff.
    • The new ../i18n.js edges add nothing to any test's closure: PreviewShell already imports ../i18n.js, and the panel's test importers already reach it through FlowRunsPanel/DatasourcePreview.
    • The only growth is row-nodes.ts, which imports only react.
    • The new hook calls in FieldsListEditor and FieldListRow add runtime reach only. All shards are green.
  • Closure census and Part of: both right. I read external/SchemaBrowser.tsx (Filter tables…, Refresh), previews/FieldStub.tsx (address placeholder Street / City, State ZIP / Country) and previews/FlowRunsPanel.tsx (run {id} / · trigger). All are real and still English. Closing the card would have closed it with family sites still open.
  • Changeset, sentence by sentence. The title, the lead-in, bullets 1, 3, 4 and 5, the en-unchanged sentence and the slice line are accurate. Bullet 2 contradicts the closing paragraph:
    • Bullet 2 says the canvas's "region, slot and container labels" now localise.
    • No slot label is converted: a slot's header renders its canonical name as written.
    • The closing paragraph itself says "region and slot names … show as written in every locale".

② Semver level

  • '@object-ui/app-shell': patch is correct and Clause-②: no holds.
  • block-types.ts, view-column-io.ts, PageBlockCanvas, SourcePageEditor and ExternalDatasourcePanel are on no barrel and no exports entry. StudioDesignSurfaceProps is unchanged.
  • The new props are optional; there is no narrowing and no major.

③ Boundary flags

Implemented-by: claude/issue-10862-designer-english-slice-3
Reviewed-by: session_014mXUNuFomfj24w7s1pZzhN

VERDICT: FAIL

Only wording blocks. The code, byte-equality, locale reach, pins, semver and CI all hold. Required replacements:

  1. Changeset, bullet 2. Replace it with:
    "- the page block canvas: its region and container labels, its empty states (no regions, an empty region, an inherited slot, an empty container group), the add-region and add-block buttons, drop target, rename tooltip, select labels, each block's render-failure hint and the add-block picker's search box, category headings and block names;"
  2. Glossary, related list. Set 'engine.pageBlockCanvas.type.recordRelatedList': '关联列表'.
  3. Glossary, transitions. Set:
    • 'engine.validationPreview.transitions': '状态流转'
    • 'engine.validationPreview.transitionsOn': '{field} 的状态流转'
    • 'engine.validationPreview.noTransitions': '未声明任何状态流转。'

Optional, not blocking:

  • Set 'engine.pageBlockCanvas.itemN': '第 {n} 项'.
  • Correct the PR body's "two reused rows" to three.
  • Add a pin for the StudioDesignSurface SourcePageEditor thread.

…angeset names the canvas sites it converts (objectui#10862)

The related-list block reads 关联列表, the state-machine transitions read
状态流转 and the sample-record count reads 示例, as the page-block inspector,
the rules editor and the action preview already say; a tab item's positional
label reads 第 {n} 项. The changeset's page-block-canvas bullet names the sites
converted and no longer claims slot labels, which show as written.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3100.8 KB 3104.5 KB
Main entry chunk (gzip) 148.5 KB 350 KB
Entry file index-Dd51NYJF.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.58KB 6.17KB
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) 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.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.70KB 2.23KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
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) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
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.13KB 7.95KB
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) 557.59KB 133.60KB
core (index.js) 9.93KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 226.44KB 63.00KB
fields (index.js) 261.01KB 66.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
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.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
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.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.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.01KB 3.93KB
plugin-calendar (index.js) 51.96KB 14.83KB
plugin-charts (index.js) 83.99KB 22.86KB
plugin-chatbot (index.js) 197.67KB 46.90KB
plugin-dashboard (index.js) 136.93KB 36.48KB
plugin-designer (index.js) 215.03KB 44.21KB
plugin-detail (index.js) 233.48KB 61.79KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 161.21KB 41.41KB
plugin-gantt (index.js) 170.35KB 42.19KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.17KB 12.20KB
plugin-timeline (index.js) 31.00KB 9.09KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 88.55KB 22.21KB
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) 119.16KB 39.05KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
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.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.22KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
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.26KB
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 (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) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.27KB 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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 6a21fd35a7d53a0b295a9f764919b5e488aee110

This is an in-seat delta review of fix round 1 (497678cba to 6a21fd35a, one commit), against record 5864826804 (FAIL, wording only).

① Derived judgments

  • Required 1, changeset bullet 2: fixed. The page-block-canvas bullet is the record's replacement text, byte for byte. It no longer claims slot labels, so it agrees with the closing paragraph ("region and slot names … show as written").
  • Required 2, related list: fixed. engine.pageBlockCanvas.type.recordRelatedList reads 关联列表, the term engine.inspector.pageBlock.option.location.record_related and engine.inspector.action.location.record_related already use.
  • Required 3, transitions: fixed. engine.validationPreview.transitions / .transitionsOn / .noTransitions read 状态流转, {field} 的状态流转 and 未声明任何状态流转。, matching the rules editor for the same rule.
  • Nits taken:
    • engine.pageBlockCanvas.itemN reads 第 {n} 项;
    • engine.pagePreview.sampleOne / .sampleOther read {count} 条示例 (示例, as the catalogue's 示例记录).
  • Nothing else moved. Two files, 8 insertions and 10 deletions: seven zh values and one changeset bullet.
    • No en row and no placeholder changed. check:i18n-drift still reports 0 en values changed, and designer parity passes.
    • No pin hard-codes an old term. Every zh expectation is read from the catalogue.
  • Optional pin not taken: accepted. The StudioDesignSurface SourcePageEditor locale thread would need its own mount scaffolding; the body records it.
  • The five pending changesets changeset-claim-re-read lists (6310, 6681, 7125, 8632, rotten-pugs-invent): each named sentence is still true at this head, re-read by the seat.
    • designer.field.formula, table.noRows and engine.form.noRows are not in this PR's i18n.ts diff.
    • StudioDesignSurface still statically imports SuggestedBindingsPanel.
    • BLOCK_RENDERER_ALIAS_GROUPS and resolveBlockDisplayMeta remain, and the palette offer list is unchanged (labelKey moves only the displayed name).
  • The PR body r2 (applied with this landing) corrects the reused-row count to three and adds a Fix round 1 section. Line 1 is Part of #10862, and there is no closing keyword. No path:line reference.

② Semver level

patch for @object-ui/app-shell. Clause-②: no holds: zh values and changeset prose only. ⛔ Not major.

③ Boundary flags

  • CI: the landing waits for every check-run on this head to be final and green, and re-runs git merge-tree against current main first. The dev's merge-tree against 8522396c0 is clean (tree 8ac1563).
  • Open PRs: the round touches only i18n.ts and this PR's own changeset, and no open PR shares either.
  • NOT GOVERNED (19 paths).
  • Draft, assigned to os-elon-musk.

Implemented-by: claude/issue-10862-designer-english-slice-3
Reviewed-by: session_014mXUNuFomfj24w7s1pZzhN

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Seat note: ejected from the merge queue by Spec Main Shape Gate, which is not this PR's failure

domain:ui seat 2, session_014mXUNuFomfj24w7s1pZzhN.

  • What failed: on queue commit 68a2278d1c, Spec Main Shape Gate (check run 108821676628), the only red check. packages/types/src/__tests__/report-chart-query-spec-parity.test.ts fails with "TS1360: Type 'true' does not satisfy the expected type 'false'", compiled against spec main df3ba164a588. The CI workflow on that commit was green.
  • Why it is not this PR's: this PR touches no packages/types file. objectstack#20369 (681868ca7c) typed JoinedReportBlockSchema upstream, and the pin trips as its own docblock intends. Every PR entering the queue now fails the same way.
  • Fix: none exists yet. It is filed as objectui#10916 for triage to route. No retry of the gate would change the verdict, so none is spent.
  • Next: the seat keeps this PR watched. Once objectui#10916's fix is on main, the seat re-queues it (or auto-merge does) with no code change here.

akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Sep 28, 2026
…ts name 23 objectui issues that answer 404, and re-qualify 19 bare objectstack numbers (objectui#10803, batch 6) (objectstack-ai#10914)

Part of objectstack-ai#10803
Clause-②: no

Dispatched implementation of the `domain:ui` seat objectstack-ai#1 claim (comment
`5864334310`) on objectui#10803, batch 6, session
`https://claude.ai/code/session_01DuWo5bdP9SdVebamn99GGk`. Citations
only: no sentence's claim moves, and every edited pending changeset's
frontmatter is byte-identical. The one runtime string that moves is
`InputSchema.wrapperClass`'s zod `.describe()` text in
`@object-ui/types`, which loses its dead pointer and nothing else
(amendment `5860244997`, Q1 = A; `patch` changeset). No test pins any
changed text: the literal-anchor sweep below finds no specific anchor,
so no test file is edited.

This batch carries the release note `5863776648`'s three lists:
- the last **23 family numbers**;
- the **18 bare objectstack numbers above 10900** from PR
objectui#10892's C0 census, plus **#13086**, a 404 the C0 instrument
cannot see because it shares a token with #13337 (**Premise**);
- the live-but-wrong bare `objectstack-ai#3391` at the two `rowCrudAffordances.ts`
sites beside `objectstack#3720`.

## Why `Part of`, not a closing line

The order says `Part of`. With this PR the family list (all 115 numbers
of amendment `5860244997` Q2) and the C0 above-10900 list both read 0.
Whether the card now closes, or carries the dead `objectstack#N` class
measured in **Acceptance notes** 1, is the seat's call.

## Premise, re-measured on `origin/main` `9f0c84a44` (the branch point)

- **The 23 family numbers.** REST `GET
/repos/objectstack-ai/objectui/issues/N`: 23 of 23 answer 404, and a
second read of each answers 404 again. `GET .../pulls/N` answers 404 for
all 23. Lit controls: objectui#10533 and objectui#7714 answer 200.
- **No new family member.** The distinct `objectui#N` citations in the
two in-scope classes at the branch point, less those at batch 1's head
`6c3ad7c80`, are 24 numbers. Each was read once: 24 of 24 answer 200. So
the family list is still batch 5's 23.
- **#14026 was a sister-repo card written as objectui's.**
objectui#14026 answers 404 as an issue and as a pull. objectstack#14026
answers 301 to objectui#10102, the card it was transferred to. That
card's measurement-round claim (branch
`claude/issue-14026-import-mapping-selector-probe`) is the session of
`ecf14190e`, the commit that added `14026-list-import-mappings-pin.md`,
and six sibling in-scope lines already write `objectstack#14026` for the
same card.
- **C0, the bare-number census** (the instrument of PRs objectui#10875
and objectstack-ai#10892, at the branch point):

```
git grep -hoP '(?:^|(?<=[^\w#&/.\-]))#\d+(?![0-9A-Za-z_])' 9f0c84a -- '.changeset/*.md' 'packages/*/src/**' ':!**/__tests__/**' ':!**/*.test.*' ':!**/*.spec.*' ':!**/test/**' ':!**/tests/**' | sort -u | wc -l
```

- 984 distinct at `9f0c84a44`, against 998 at batch 5's `b2683a2c0`. The
14 that batch 5 re-pointed are gone, and none is new.
- Above 10900 there are 23: the same 5 CSS colours and the same 18
numbers. Each of the 18 answers 404 as an objectui issue and as an
objectui pull on two reads.
- In objectstack, 16 of the 18 answer 200 with the sentence's own
subject (the **C0 mapping** below). #13033 and #13413 answer 404 there
too, as issues and as pulls. Their squash commits exist in objectstack's
history (a full, not shallow, clone): `c459da6bc` "narrow the per-option
`default` key out of the form-view options vocabulary … (#13033)" and
`89448a52b` "remove the inert AUTH_SSO_PROVIDER_SCHEMA export (#13413)".
Both are ancestors of objectstack `main` (`git merge-base
--is-ancestor`, exit 0).
- **The C0 instrument's blind spot.** Its lookbehind refuses a `#`
preceded by `/`, `-`, `.` or `&`. That form (`#A/#B`, `-#N`) carries 109
distinct numbers at the branch point. The 17 that no earlier batch read
were each read once. 16 answer 200. **#13086 answers 404**, as an issue
and as a pull, in objectui and in objectstack. It sits in
`6985-wizard-card-r-alignment.md` as "the #13337/#13086 fence", in the
same token as #13337, so it rides here. objectstack's
`check-yaml-examples.ts` header, at its landing `2ebfe7e9f` (PR
objectstack#13267, which answers 200), reads "Check YAML Examples
(anti-drift for the AUTHORING format, #13086)" and "Ruled 2026-08-29
(#13086)".
- **objectstack-ai#3391.** objectui#3391 answers 200 with an unrelated subject (a
record-header api action placeholder). objectstack#3391 answers 200 as
the apiMethods whitelist contract card ("跟踪:UI 操作按钮与 apiMethods
白名单一致性契约落地"), and objectstack#3720's own title calls itself "objectstack-ai#3391
遗漏的第四个面".
- Every edited changeset is pending: it is present in `.changeset/` on
`main`. The checkout is not shallow.

## Census (the enumeration pin for this batch)

The instrument PR objectui#10854 printed and PRs objectui#10869 / objectstack-ai#10875
/ objectstack-ai#10892 reused, with this batch's 23 numbers substituted (REF = a
commit or tree):

```
git grep -nE '(objectui#|#|issues/)(8072|8127|8137|8204|8229|8248|8307|8408|9231|9241|9244|9365|9373|9375|9542|9553|9585|10117|10119|10120|10129|10132|14026)([^0-9]|$)' REF -- '.changeset/*.md' 'packages/*/src/**' ':!**/__tests__/**' ':!**/*.test.*' ':!**/*.spec.*' ':!**/test/**' ':!**/tests/**' | grep -v 'objectstack#' | wc -l
```

- REF = `9f0c84a44` (branch point): **104** lines.
- One more line is hidden by the `grep -v 'objectstack#'` filter:
`9943-viewtype-totals-page-row-retired.md` names objectui#8127 beside an
`objectstack#` citation.
- So the true population is **105** lines: 28 changeset lines in 26
files, and 77 src lines in 42 files.
- Unfiltered, REF reads 111. The other 6 lines are live
`objectstack#14026` lines.
- REF = `2b3d2061a` (this head): **0**. Unfiltered it reads 7, all live:
the six `objectstack#14026` lines and the re-qualified one.
- This head merged with a fresh `main` (`8522396c0`, `git merge-tree
--write-tree`, clean, tree `f19d17884`): **0**. REF = `8522396c0` alone:
104.
- **C0**, the 19 numbers, bare and not `objectstack#`-qualified: 28
lines in 23 files at the branch point; 0 at this head. At this head C0
reads 966 distinct numbers, and above 10900 only the five CSS colours
are left.
- Lit control, the printed instrument over live objectui#7714 at this
head: 17 lines. Hex-colour false positives (a number followed by a hex
letter) at the branch point: 0.
- **Out of scope, as it stands** (the 23 numbers, filtered, whole tree
at this head):
  - 94 test lines in 36 files;
  - 5 `.github` lines in 1 file (`ci.yml`, objectui#9241);
  - 2 `apps/console` lines in 1 file (`FormPage.tsx`, objectui#8408);
  - 1 line of the root `vitest.config.mts`;
  - 0 scripts, 0 governed, 0 `CHANGELOG.md`.
- For the 19 C0 numbers: 13 test lines in 10 files, and 1 line of
`packages/plugin-tree/README.md`.

## Citation form

- **Landing shas.** The 9-character backticked sha of the commit on
`main` that landed the change the sentence rests on, as in the earlier
batches. All 15 distinct objectui shas below are ancestors of `main`:
`git merge-base --is-ancestor`, exit 0 each. Control legs in the same
checkout: the head of PR objectui#10902 (`496c63c06`) answers exit 1,
and the known ancestor `5f789538d` answers exit 0. `git rev-parse
--short=9` returns the same 9 characters for each.
- **Own-card pointers** in a changeset are dropped, not replaced. The
configured changelog generator (`@changesets/cli/changelog`, per
`.changeset/config.json`) prefixes each released entry with the hash of
the commit that added the file, which is that landing.
- **The claim lived only on the card.** Where the sentence rests on
something that lived only on the dead card, the sha only locates it:
"the card behind SHA".
- **Nothing answers.** The pointer is dropped and the sentence names the
card by role (objectstack-ai#9553 only).
- **Sister-repo numbers.**
- A bare sister-repo number becomes `objectstack#N` after reading it
there.
- "objectstack PR #N" becomes "PR objectstack#N", since the qualifier
now carries the repository. "framework #N", "upstream #N" and "spec #N"
keep their word, as batch 4 kept "framework PR objectstack#6942".
- Where the objectstack pull request itself answers 404, the sentence
cites its commit in that repository as objectstack `SHA`, the spelling
the tree already uses for an objectstack commit ("Measured on
objectstack `9bd4344e4`").
- **Runtime text** carries no sha: see **Special cases** 6.

## Mapping, the 23 family numbers

Lines / files are the branch-point census for that number. "Method" is
how the landing was found; for every source site, `git log -S
'objectui#N' -- FILE` names the commit that wrote the citation, and it
is the landing below unless the row says otherwise.

| dead number | resolution | method | lines / files | why the commit
carries it |
|:--|:--|:--|:--|:--|
| objectstack-ai#8072 | `c974edf14`; own-card pointer dropped; runtime pointer dropped
| changeset's adding commit, subject "(objectui#8072)" | 5 / 3 | it
mirrors `wrapperClass` on `InputSchema`, which is what both comments and
the `7722` changeset say happened |
| objectstack-ai#8127 | `ca3942729`; "the card behind `ca3942729`" twice (**Special
cases** 2) | `git log -S` names `ca3942729` for the first citation in
all 10 source files; `05a49f2ee` (objectui#9880) and `8a7e09fa1` (the
`9943` changeset's landing) wrote three later sentences that cite the
same fix | 17 / 11 | it derives `ViewType` from `@objectstack/spec`
instead of re-declaring it, and its message records the
`page`-degrades-like-a-typo measurement the sentences cite |
| objectstack-ai#8137 | own-card pointer dropped (landing `0fa7a9c83`) | changeset's
adding commit | 1 / 1 | the only site is its own changeset's pointer |
| objectstack-ai#8204 | own-card pointer dropped (landing `580b0fdf4`) | changeset's
adding commit | 1 / 1 | the pointer opened a paragraph as its own
sentence |
| objectstack-ai#8229 | "a separate finding" (changeset); "the finding `8b7ea3945`
reconciled" (`flex.tsx`) | `8b7ea3945`'s message: "Reconciles the third
face objectui#8229 found" | 2 / 2 | the finding lived on the dead card;
`8b7ea3945` is the commit that reconciled it, and it is the `7735`
changeset's own landing |
| objectstack-ai#8248 | own-card label dropped from the second list item (landing
`d02942b0e`) | changeset's adding commit; its message covers
objectui#8458 and objectui#8248 | 1 / 1 | the changeset lists the two
cards its one landing closed |
| objectstack-ai#8307 | `5591f03bd`; own-card pointer dropped | changeset's adding
commit | 11 / 4 | it makes a lane header over a windowed fetch say
`77+`, and it wrote every comment that cites the card |
| objectstack-ai#8408 | own-card pointer dropped; "seam 2 of the card behind
`8241a4400`" | changeset's adding commit; `8241a4400`'s message names no
seams | 2 / 2 | the seam list lived on the dead card |
| objectstack-ai#9231 | `383502b23`; own-card pointer dropped | changeset's adding
commit | 3 / 2 | it gives the create dialog's confirm control its own
accessible name, the rule both `i18n.ts` comments state |
| objectstack-ai#9241 | own-card pointer dropped (landing `250429c8f`) | changeset's
adding commit | 1 / 1 | the only site is its own changeset's heading |
| objectstack-ai#9244 | `bd0995738` | `git log --grep`: its message names the card; it
wrote all three comments | 3 / 2 | it emits one col-span class per
breakpoint tier, not one for the widest |
| objectstack-ai#9365 | own-card pointer dropped (landing `0970a0e00`) | changeset's
adding commit | 1 / 1 | the only site is its own changeset's pointer |
| objectstack-ai#9373 | `c1006ed8e`; own-card pointer dropped | changeset's adding
commit | 2 / 2 | it resolves the inline locale map before the
interpolation options, the `ListView` comment's subject |
| objectstack-ai#9375 | own-card pointer dropped (landing `e427e9c00`) | changeset's
adding commit | 1 / 1 | the only site is its own changeset's pointer |
| objectstack-ai#9542 | `43c0d1710`; own-card pointer dropped; "filed as a separate
card" (**Special cases** 3) | changeset's adding commit; `git log -S`
names it for the `action-button` / `action-icon` comments too | 9 / 6 |
it accepts and resolves an inline `I18nLabel` on `resultDialog` and
makes `ResultDialogSpec` derive its label members |
| objectstack-ai#9553 | nothing answers: "a separate card carried that census" | `git
log --grep` finds only `40f34b4ba`, which points at the card; no commit
lands it | 1 / 1 | see **Special cases** 4 |
| objectstack-ai#9585 | "`ee70287e4`'s pin measures it NOT GATED"; in its own
changeset, "a pin in this change measures it" | no commit names it;
`ee70287e4` adds the test "NOT GATED: the renderer paints the very node
the mirror refuses, without parsing it" | 2 / 2 | see **Special cases**
5 |
| objectstack-ai#10117 | `4c6f549ef`; own-card pointer dropped | changeset's adding
commit | 3 / 2 | it resolves a lookup title candidate in `page:header`
and adds the record-key safety net both comments describe |
| objectstack-ai#10119 | `73a3c89af`; own-card pointer dropped | changeset's adding
commit | 4 / 2 | it makes a nav ancestor's gates reach its subtree and
stops a group outliving its children |
| objectstack-ai#10120 | `80c54122e`; own-card pointer dropped | changeset's adding
commit; for each file `git log -S` names it, or a later commit that
cites its gate: `e0f820246` (objectui#10563) or `b809375ac`
(objectui#10163) | 16 / 13 | it makes a form neither submit nor offer a
field the caller may read but not edit, the FLS half every site names |
| objectstack-ai#10129 | `6cc910b6d`; own-card pointer dropped | changeset's adding
commit | 10 / 5 | it routes a field-backed action param to its record
picker and refuses an unreadable one |
| objectstack-ai#10132 | `061f5e829`; own-card pointer dropped | changeset's adding
commit | 8 / 4 | it makes the two declared-translatable dashboard
surfaces resolve, including the axis `title` forward |
| #14026 | re-qualified `objectstack#14026` | see **Premise** | 1 / 1 |
it is the card the pin's measurement answered |

## Mapping, the 19 bare sister-repo numbers

| number | resolution | what objectstack says | lines / files |
|:--|:--|:--|:--|
| objectstack-ai#11289 | `objectstack#11289` ("upstream") | "record:details sections
cannot survive an empty record: `hideEmpty` / `collapsible` /
`showBorder` are honoured by the renderer but undeclared" | 2 / 2 |
| #11662 | PR `objectstack#11662` | "feat(spec): declare hideEmpty /
collapsible / showBorder on record:details sections" | 1 / 1 |
| #12616 | PR `objectstack#12616` | "feat(spec): declare record:details
section headerColor as a closed six-token enum" | 1 / 1 |
| #12718 | PR `objectstack#12718` | "feat(spec): retire preview mode —
the RuntimeMode 'preview' value and the whole PreviewModeConfig block" |
1 / 1 |
| #13033 | objectstack `c459da6bc` | the pull request answers 404; its
squash commit narrows the per-option `default` key out of the form-view
options vocabulary, the ruling `form-spec.ts` says was executed upstream
| 1 / 1 |
| #13337 | `objectstack#13337` | "docs(objectui): layout-dsl teaches
only shapes the live schemas accept" | 1 / 1 |
| #13086 | `objectstack#13267` | the card answers 404; PR
objectstack#13267 landed its ruled YAML-examples gate (see **Premise**)
| the same line |
| #13413 | objectstack `89448a52b` | the pull request answers 404; its
squash commit removes an inert schema export and leaves a note recording
the absence as a choice, the shape the `base.zod.ts` note cites as
precedent | 1 / 1 |
| #13632 | `objectstack#13632` | "[spec] `FieldSchema` accepts a
`lookup`/`master_detail` with no `reference` target …", the card
17.3.0's refinement answered | 3 / 3 |
| #13733 | PR `objectstack#13733` | "feat(spec): wizard view v1 —
declaration-and-refusal tightening of FormViewSchema type:'wizard' (Card
S)" | 1 / 1 |
| #13855 | `objectstack#13855` | the field-grouping decision card whose
option B is a section `group` reference, landed by `39404f3d9` (#13897)
"a layout section can reference a declared field group" | 1 / 1 |
| #13906 | `objectstack#13906` ("framework") | "two more
`computeExecCtx` seams read "failed" and "not wired" as one value …" | 6
/ 3 |
| #14274 | PR `objectstack#14274` | "fix(sdui-parser): refuse an
authored `type` attribute on the html tier …" | 1 / 1 |
| #14945 | `objectstack#14945` | "A flow cannot REFUSE with per-record
text …", honoured by `cca699149` "the flow `end` node honours `outcome:
'refused'`" | 1 / 1 |
| #15469 | `objectstack#15469` ("spec") | "`GanttConfigSchema` is
`strictObject(...).passthrough()` …", landed as `9c270bba0` "close the
gantt/tree config .passthrough() windows … (#15469)" | 2 / 2 |
| #15948 | `objectstack#15948` | "fix(plugin-auth)!: session payload
`positions[]` is the security axis, not the better-auth role scalar" | 1
/ 1 |
| #17493 | `objectstack#17493` | "three residues of #17322's node-door
refusal …", landed as `2c1011b01` "refuse a blank string in a flow
node's predicate slot" | 1 / 1 |
| #20051 | `objectstack#20051` | "judge a flattened view overlay's
top-level `options.KIND` …", whose door half is `6a4aec71d` | 1 / 1 |
| #20160 | PR `objectstack#20160` | "fix(spec): a joined report refuses
a top-level dataset / rows / columns / values, pointing each onto
blocks[]" | 2 / 2 |

The live-but-wrong number: "(`/me/permissions` `apiOperations`, objectstack-ai#3391)"
becomes "… `apiOperations`, objectstack#3391)" at the two
`rowCrudAffordances.ts` sites.

## Special cases (the judgement calls)

1. **#14026 is re-qualified, not dropped as an own-card pointer.** The
card behind `14026-list-import-mappings-pin.md` was never an objectui
card: it was objectstack#14026, now objectui#10102. Dropping the pointer
would lose which hypothesis the pin refuted. Re-qualifying it matches
the six sibling lines.
2. **objectstack-ai#8127, the card by role twice.**
- `CreateViewDialog.tsx`: "one of the sites the card records as
"drifted, …"" becomes "one of the sites the card behind `ca3942729`
records as …". That record lived on the card.
- `plugin-list` `ViewSwitcher.tsx`: "objectui#8127 was filed against the
two in `@object-ui/types`, and the maps below were described there as
total …" becomes "the card behind `ca3942729` was filed against …".
- `normalize-list-view.ts`: "The bug objectui#8127 records" becomes "The
bug `ca3942729` records". That commit's message carries the measurement:
`page` resolved "to exactly what it resolved a typo to".
3. **objectstack-ai#9542 in `8648-ui-action-four-undeclared-keys.md`.**
- The superseded paragraph keeps its pre-landing voice: "so it is filed
as a separate card and ⛔ not guessed at here".
- The superseding paragraph reads "`43c0d1710` landed the derivation".
- "(Noted here by the objectui#9542 seat, …)" becomes "(Noted here by
the seat that landed `43c0d1710`, …)".
4. **objectstack-ai#9553, nothing answers.** `base.zod.ts` said "No count of authored
`events` keys is stated here — objectui#9553 carries that census." No
commit landed that card. `40f34b4ba` only points at it, and the
`AGENTS.md` fix `7550728a6` names a different card. So the sentence now
reads "— a separate card carried that census". The census is not
restated, per AGENTS.md objectstack-ai#9.
5. **objectstack-ai#9585, the measurement's instrument.** The card measured the render
path NOT GATED, and no commit names it. But the commit that wrote both
citing sentences, `ee70287e4`, adds a pin that re-measures exactly that:
"NOT GATED: the renderer paints the very node the mirror refuses,
without parsing it".
- `disclosure.ts` now reads "(`ee70287e4`'s pin measures it NOT GATED)".
- Its own changeset, `8236-collapsible-open-intercept-retire.md`, whose
landing is `ee70287e4`, reads "(a pin in this change measures it NOT
GATED)".
6. **The runtime string.** Only the listed text moves.

| file | member | before | after |
|:--|:--|:--|:--|
| `types/src/zod/form.zod.ts` | `InputSchema.wrapperClass` `.describe()`
| "Classes on the wrapper div around the input and its label
(objectui#8072)" | "Classes on the wrapper div around the input and its
label" |

No test, doc or changeset quotes it: a whole-tree search for the old
string returns only the source line.
7. **objectstack-ai#8229 in `flex.tsx`.** "(objectui#8229, folded into objectui#7735's
ruling)" becomes "(the finding `8b7ea3945` reconciled, folded into
objectui#7735's ruling)". objectui#7735 answers 200 and stays.
8. **#13413's sentence.** "Precedent of the same shape:
objectstack#12009 / PR #13413." becomes "… objectstack#12009 /
objectstack `89448a52b`." objectstack#12009 answers 404 too, but it is a
qualified sister-repo number outside this batch's lists, so it is left
and listed (**Acceptance notes** 1).
9. **#20160 across a line break.** In
`10746-joined-report-clears-binding.md`, "(objectstack PR" ends one line
and "#20160: …" opens the next. They become "(PR" and
"objectstack#20160: …".

## The literal-anchor sweep (both test-pin classes, ruling `5861900779`)

- **Instrument.** Every string, template, numeric and regex literal in
all 4068 tracked test and script files (119016 distinct literals),
parsed with TypeScript.
- **Candidate filter.** A literal is a candidate only if it matches the
diff's removed lines with two lines of context, raw or
comment-flattened. That leaves 2839.
- **Test applied to each candidate.** Does its occurrence count DROP
between `9f0c84a44` and `2b3d2061a` in any of the 92 files this PR
changes, in raw text or in a comment-flattened form? 229 distinct
literals drop.
- **Every one is a generic token.** Digits and short numbers,
punctuation, single letters, `objectui#`, `objectui#1`, and whole-tree
scanners such as `/#\d+/` and `/objectui#\d+/`. The three `objectui#\d+`
matchers (`ActionRunner.disabledGate`, `registry-inputs-spec-parity`,
`catalog-gallery-render`) assert over their own test data and read no
changed file.
- **No specific anchor.** None is a batch number, a changed phrase, or
the changed `.describe()` string. So no test pins changed runtime text
(class one), and no source-reading test pins a changed comment or
docblock citation (class two).
- Test titles and comments that name these numbers are out of the card's
classes and stay (**Census**, out of scope).

## Held

**By the serial rule: nothing.** Re-mapped before the push, on 9 open
PRs: objectui#10910, objectstack-ai#10908, objectstack-ai#10907, objectstack-ai#10906, objectstack-ai#10901, objectstack-ai#10891, objectstack-ai#10777,
objectstack-ai#10278 and the release PR objectstack-ai#5400 (objectstack-ai#10902 and objectstack-ai#10904 had merged since the
claim).

Two of them share files with this PR. Their hunks were read against
their merge-bases; each file is identical at its merge-base and at
`9f0c84a44`, so the lines map directly.
- **objectui#10907, `types/src/zod/form.zod.ts`.** It inserts a refusal
constant before `InputSchema`, two tombstone members further down
`InputSchema`, and a comment in the `InputShorthandSchema` arm. This
PR's three edited lines (the `wrapperClass` comment and description, and
the arm's "shrank that row" comment) sit outside every one of its hunks
and their 3-line context.
- **objectui#10906, `metadata-admin/i18n.ts` and
`previews/ViewPreview.tsx`.** Its `i18n.ts` insertions are far from the
two `createDraft` comments, and its `ViewPreview.tsx` hunks are far from
the `options` fold docblock.

Trial merges with this head (`git merge-tree --write-tree`):
- clean for objectstack-ai#10910, objectstack-ai#10908, objectstack-ai#10907, objectstack-ai#10906, objectstack-ai#10901, objectstack-ai#10891 and objectstack-ai#10777;
- objectstack-ai#10278 (`eab4c8e52`) conflicts in `ObjectGrid.tsx`,
`plugin-grid/README.md` and `content/docs/plugins/plugin-grid.mdx`, and
conflicts identically against `9f0c84a44` alone;
- objectstack-ai#5400 (Version Packages) regenerates and is not a hold.

objectui#10891 shares no file with this PR.

## Changesets

- `.changeset/10803-dead-citation-sweep-sixth-batch.md`, EMPTY
frontmatter. It covers the comment-only edits in 15 released packages;
no published behaviour changes through them. It points at the second
file for `@object-ui/types`' runtime text.
- `.changeset/10803-sixth-batch-runtime-strings.md`,
`'@object-ui/types': patch`: the `wrapperClass` description loses its
pointer. No key, path, issue code, accept set, refusal or severity
moves.

## Proof of prose-only (C4), against `9f0c84a44`, on this head
`2b3d2061a`

- **Source.** Each of the 53 touched `.ts` / `.tsx` files was parsed at
`9f0c84a44` and at this head with TypeScript 6.0.3's `createSourceFile`,
and re-printed by `createPrinter({ removeComments: true })`.
  - 52 of 53 prints are identical.
- `form.zod.ts` is equal once the one listed substitution (**Special
cases** 6) is applied to the base print, matched once.
  - 0 parse diagnostics.
- Lit controls on the same instrument: editing a string literal moves
the print; re-spacing a comment does not.
- **Changesets.** The frontmatter block of every one of the 37 edited
changesets is byte-identical at `9f0c84a44` and this head (37 of 37, by
md5). The overwrite gate below agrees.
- **Scope of the diff:** 92 files, +175 / −140. That is 37 edited and 2
new changesets, and 53 non-test source files in 15 released packages. No
test file.

## Gates, on this head `2b3d2061a`

Each line is the gate's own verdict and exit code, captured by
redirect-then-`$?`.

- `node scripts/check-changeset-presence.mjs`, exit 0: "53 source
file(s) of 15 released package(s) changed, and this change declares 2
changeset(s): .changeset/10803-dead-citation-sweep-sixth-batch.md,
.changeset/10803-sixth-batch-runtime-strings.md."
- `pnpm changeset:check`, exit 0: "All workspace packages are in the
changeset fixed group." / "No changeset declares a `major` bump."
- `node scripts/check-changeset-overwrite.mjs` (report-only), exit 0: "2
changeset(s) added, 37 modified, 0 deleted". `declared at base` equals
`declares now` for 37 of 37.
- `pnpm check:changeset-claims` (report-only), exit 0:
- "Every one of those 1 address(es) either names the tree it was read
from, or points at a line this change does not move";
- "Every package declared across those 31 body(ies) is either not
negated …";
- the standing notice "75 pending changeset(s) describe a file this
change touches".
- Read against the diff: a pending changeset quoting a replaced pointer
would itself carry the dead number and sit in the census, which reads 0.
No pending changeset quotes the changed description.
- `pnpm check:control-bytes`, exit 0: "check-control-bytes: OK (scanned
9178 tracked text file(s); skipped 85 binary)."
- `pnpm check:new-line-citations`, exit 0: "VERDICT
new-cross-file-line-citations: 0 new citation(s), enforcement
report-only -> exit 0".
- `pnpm check:pending-changeset-literals`, exit 0: "No test source names
a pending changeset."
- Also run over the touched comments:
  - `pnpm check:installed-pin-claims`, exit 0 ("OK");
- `pnpm check:comment-mask-corpus`, exit 0 (1 disagreeing file, within
the ceiling objectui#7882 holds open);
- `pnpm check:handler-key-reads`, exit 0 ("every judged read is a
declared member of it").
- The governed-surface predicate over the 92 paths, exit 0: "NOT
GOVERNED — 92 path(s) checked against 5 governed surface(s); none
matched." Lit control `AGENTS.md`: exit 3.

**Tests**, through the shared verify lock, on `2b3d2061a`. Each is
`VERDICT command-exit 0`.
- `scripts/__tests__/`, the whole directory, whose whole-tree scanners
read the touched files: `Test Files 177 passed | 2 skipped (179)`,
`Tests 5322 passed | 2 skipped (5324)`. The two skipped files are the
network-escape fixtures that run only as a child.
- `packages/types/`, the whole package, whose runtime text moved: `Test
Files 264 passed (264)`, `Tests 5854 passed (5854)`. `pnpm --filter
@object-ui/types type-check`, exit 0.
- **The pins nearest the re-pointed text:**
- in `types`: `input-wrapper-class-mirrored-8072`, `zod-mirror-parity`,
`wrapper-class-declared-7722`, `zod-mirror-authors-no-defaults-7735`,
`collapsible-open-refusal-8236`, `tree-view-config-readers-8253` and
`layout-default-jsdoc-7361`;
- in `components`: `collapsible-open-intercept-8236`,
`registration-defaults-match-renderer-8229` and
`action-undeclared-keys-8648`;
- in `plugin-view`: `ViewSwitcher` and
`ViewSwitcher.viewTypeTotalsBothLegs-9943`;
  - in `plugin-kanban`: `laneCountHonesty-8307`;
  - in `plugin-grid`: `rowCrudAffordances` and `rowCrudEffectiveOps`.
  - Result: `Test Files  15 passed (15)`, `Tests  381 passed (381)`.
- No red leg: the sweep found no anchor to move, so there is no pin
whose old copy should fail.

**Declared narrowing.** NOT MEASURED locally:
- the full suites and type-check of the 14 other touched packages, and
eslint.
- Reason: the comment-stripped syntax tree of 52 of 53 touched source
files is identical to `main`, and the 53rd differs only by the listed
literal.
- CI runs the full farm.

## Acceptance notes

1. **A sister-repo class of the same defect: 30 `objectstack#N`
citations answer 404 in objectstack.**
- **Measurement.** Every distinct `objectstack#N` in the two in-scope
classes at the branch point is 359 numbers. Each was read once: 328
answer 200, 1 answers 301 (objectstack#14026 to objectui#10102), and 30
answer 404, each confirmed by a second read.
- **The 30:** objectstack-ai#5970 objectstack-ai#5976 objectstack-ai#6038 objectstack-ai#6124 objectstack-ai#6281 objectstack-ai#6331 objectstack-ai#6450 objectstack-ai#6483 objectstack-ai#6515
objectstack-ai#9933 objectstack-ai#9934 objectstack-ai#10354 objectstack-ai#10485 objectstack-ai#10695 objectstack-ai#11330 #11507 #11513 #11658 #11703
#11753 #11846 #12009 #12868 #13117 #13670 #16126 #17147 #17762 #17987
#18012.
- **Sites at this head:** 82 lines in 63 files, 26 of them changeset
lines.
- **Three of them sit in sentences this PR edits, and are left as they
are:**
- objectstack#11846, "(objectstack#11846, landed as PR
objectstack#12718)" in `6748-preview-mode-provenance-ratchet.md`;
     - objectstack#12009, in `base.zod.ts`'s precedent line;
- objectstack#12868, in `form-spec.ts`'s "RULED 2026-08-28
(objectui#6263 / objectstack#12868, …)".
- **Why left.** They were not in this batch's lists, and the class is
the seat's to scope. objectstack's own card for dead tracker citations
in its tree is objectstack#19123, whose landing `66e266c93` counts
#12868 among the dead numbers it measured. Triage item 3 would put a
dead number in these classes on this card. The fix shape measured here
for such a number is the objectstack commit, as with `c459da6bc`.
2. **The rest of the bare `objectstack-ai#3391` population.** Only the two sites the
claim names were re-qualified. 28 more in-scope lines in 10 files write
the apiMethods whitelist card as a bare `objectstack-ai#3391`, which resolves to the
unrelated objectui#3391:
   - `ObjectDataPage.tsx`, `ObjectView.tsx` (app-shell);
   - `managedBy.ts`;
- `MePermissionsProvider.tsx`, `PermissionContext.ts`,
`PermissionProvider.tsx`;
   - `fieldWriteGate.ts`;
   - `ImportWizard.tsx`, `ObjectGrid.tsx`;
   - `ListView.tsx`.

It is live, not a 404, so it is outside the family pin. Two of those
lines pair it with a bare 3546 that means objectstack#3546 ("detail/form
面的 edit/delete 按钮接入服务端 effective 操作集"), while objectui#3546 is an
unrelated i18n card. Carrier: none.
3. **A stale claim beside a re-pointed sentence.** The same
`base.zod.ts` paragraph says "AGENTS.md's abridged protocol sketch shows
`events?: Record…` and its action-system commandment authors one".
`7550728a6` removed both from `AGENTS.md`, so that sentence is now
false. It is not a citation, and this PR does not touch it. Carrier:
none.
4. **The C0 blind spot, for any later census.** The bare-number
instrument's lookbehind hides a number written after `/`, `-`, `.` or
`&` (`#13337/#13086`, `-objectstack-ai#2231`). This batch read the 17 such numbers no
batch had read, and #13086 was the only 404. A later census can narrow
the lookbehind to refuse only a word character, `#` or `&` before the
`#`, and drop URL fragments by hand.
5. **Filenames are not citations.** Pending changeset and test FILENAMES
carry several of these numbers. They stay, as in PRs objectui#10707,
objectstack-ai#10797, objectstack-ai#10854, objectstack-ai#10869, objectstack-ai#10875 and objectstack-ai#10892.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01DuWo5bdP9SdVebamn99GGk)_

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants