Skip to content

refactor(plugin-list,plugin-dashboard,app-shell): one authority each for ViewSwitcherProps, RecordDetailDrawerProps and PageHeaderComponentProps (objectui#6349, batch 8) - #12074

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-6349-batch8-component-props
Oct 10, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-6349-batch8-component-props

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Refs #6349 (batch 8)

Clause-②: yes

Batch 8 of the one-authority burn-down, on claim 6090897330 (seat domain:ui#3, session https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8). Three component-props rows of KNOWN_COLLISIONS converge, so the ledger goes from 16 rows to 13. None of the three has an @object-ui/types side. Each row was two components behind one props name, so in each row the side with the narrower meaning takes a specific name. Types, comments and changeset prose only: no runtime behaviour changes, and no emitted JavaScript changes.

This PR has no closing keyword. The card stays open for later batches.

This is a resumed run. A dev run on this claim was killed by a container restart after it pushed cc75cab8d and before it opened a PR or reported. This run reviewed that commit as its own draft against the brief and the claim, kept all of it, and added 5dd334645, which corrects one wrong statement the first commit made in three places (see "What the second commit corrects").

What each row was (measured on base 20c6d351)

The member lists come from one TypeScript program over each package's BUILT root entry (exports["."].types), with dist rebuilt for the base tree.

ViewSwitcherProps: two switchers, so plugin-list's side is renamed.

site members meaning built entry
packages/plugin-view/src/ViewSwitcher.tsx schema (a ViewSwitcherSchema), className?, onViewChange?, onCreateView?, onViewAction?, createViewLabel?, and a string index signature. Views are typed on @object-ui/types' ViewType the props of the registered view-switcher renderer exported at the plugin-view root
packages/plugin-list/src/ViewSwitcher.tsx currentView, availableViews?, onViewChange, className?, animated?. Views are typed on @object-ui/core's ListViewVisualization the props of the list view's own visualization switcher (ViewSwitcher and ViewSwitcherDropdown) exported at the plugin-list root. 0 readers through it in the repo, and 0 hits in @objectstack/spec 17.7.0

The two share className and onViewChange, and onViewChange differs in both optionality and parameter type. Neither package depends on the other, so batch 3's rule rules out a re-point in either direction. plugin-list's switcher is the narrower meaning. Its declaration becomes ListViewSwitcherProps, and the plugin-list root publishes that name in place of ViewSwitcherProps. This is the shape batch 7's amendment 6089430007 accepted for GroupAggregationConfig. The members are unchanged, and the ViewSwitcher and ViewSwitcherDropdown components keep their names.

RecordDetailDrawerProps: two drawers, so plugin-dashboard's side is renamed.

site members meaning built entry
packages/plugin-detail/src/RecordDetailDrawer.tsx open, onClose, title, record, objectName, recordId, dataSource?, objectSchema?, width?, columns?, systemFields?, onFieldSave?, onDelete?, resizable?, fullPageHref? the published, editable record drawer (save, delete, resize) exported at the plugin-detail root
packages/plugin-dashboard/src/RecordDetailDrawer.tsx record (may be null), objectName?, objectSchema?, fields?, title?, target? (drawer or dialog), onClose, objectTypesPending? the read-only drill drawer of the dashboard's table widget not exported. A program rooted at the plugin-dashboard entry loads 21 of the package's own declaration files, and RecordDetailDrawer.d.ts is not one of them

Five member names are shared, and four of those differ in optionality or type. Neither package depends on the other. The dashboard's declaration becomes DashboardRecordDetailDrawerProps. No entry reached it, so no published name moves.

PageHeaderComponentProps: two headers, so app-shell's side is renamed.

site members meaning built entry
packages/layout/src/PageHeader.tsx title: string and subtitle?: string (both resolve record tokens), icon? (a name or a node), action?, showBack?, actions? (action definitions handed to record:quick_actions), schema?, and every div attribute the props of layout's published PageHeader component exported at the layout root
packages/app-shell/src/layout/PageHeader.tsx title, subtitle?, icon? and actions? as rendered nodes, accentColor?, sticky?, className?, data-testid? the console's own title row, used by ObjectView and ObjectDataPage not exported by name. The entry loads the file through layout/index, and the exports map has no subpath that reaches it

app-shell depends on layout, so here a re-point is dependency-legal. This run measured it on base: with app-shell's name re-exported from @object-ui/layout (its own declaration set aside), app-shell's tsc --noEmit exits 2 with 8 errors. Three are TS2339 (accentColor, sticky and data-testid are not layout members), one is TS2322 inside the header, and four are in the two console callers (a rendered element is not a string title, and a rendered element is not an unknown[] of actions). The unmutated control exits 0 with 0 errors. So this is two meanings, not drift. The console's declaration becomes ConsolePageHeaderProps, and layout is the one authority for the name. Neither header is the page:header renderer: @object-ui/components registers that node type.

Published surface, base vs head

One TypeScript program per tree over the six packages' built root entries. Dist was rebuilt for each tree, and every head marker was read in dist before measuring.

  • Exported name sets:

    • plugin-view 39 = 39; plugin-detail 105 = 105; plugin-dashboard 25 = 25; layout 37 = 37; app-shell 258 = 258;
    • plugin-list 19 = 19: ViewSwitcherProps out, ListViewSwitcherProps in, with identical members.
  • Unchanged shapes: plugin-view's ViewSwitcherProps, plugin-detail's RecordDetailDrawerProps and layout's PageHeaderComponentProps. Each member list is identical on base and head.

  • Files each entry loads: the set of the package's own declaration files is identical on base and head in all six packages.

  • An external consumer, probed as a virtual file that resolves the packages through node_modules:

    • at head, import type { ViewSwitcherProps } from '@object-ui/plugin-list' fails loudly with TS2724, which names the replacement: "Did you mean 'ListViewSwitcherProps'?". ListViewSwitcherProps compiles with 0 diagnostics;
    • on base, the old spelling reads 0 diagnostics and the new one reads TS2724, so the probe is lit;
    • the old and new dashboard names from @object-ui/plugin-dashboard, and the old and new console names from @object-ui/app-shell, read TS2305 on BOTH trees. Neither name was ever importable from those entries;
    • the control leg imports ViewSwitcherProps from plugin-view, RecordDetailDrawerProps from plugin-detail, PageHeaderComponentProps from layout, and the ViewSwitcher and ViewSwitcherDropdown components from plugin-list. It reads 0 diagnostics on base and on head.
  • Emitted output: base and head dist differ only in declaration files:

    • plugin-list: ViewSwitcher and index (with their maps);
    • plugin-dashboard: RecordDetailDrawer (with its map);
    • app-shell: layout/PageHeader and layout/index;
    • layout: PageHeader (JSDoc only).

    No .js or .css file differs in any of the six packages, and plugin-view and plugin-detail dist are byte-identical. So no first-load bytes move.

Changesets

file grade why
6349-batch8-plugin-list.md minor A published name leaves the root (ViewSwitcherProps) and its replacement arrives (ListViewSwitcherProps). Breaking-change note with the migration and the TS2724 hint.
6349-batch8-plugin-dashboard.md patch A renamed declaration that no entry reaches. Nothing published moves.
6349-batch8-app-shell.md patch The same.
6349-batch8-layout.md patch JSDoc only on the published PageHeaderComponentProps: it no longer says app-shell shares the name.

plugin-view and plugin-detail are not touched, so they get no changeset. The grades follow the claim's per-package criterion. ⛔ No major.

Batch 7's pending changeset is edited too. .changeset/6349-batch7-plugin-list.md is not released yet. It said "ViewSwitcherProps keeps its members, and ViewSwitcherProps['currentView'] names the same union". This PR makes that sentence false in the same release, so it now names ListViewSwitcherProps and says the props were renamed in batch 8. Its declaration (@object-ui/plugin-list: minor) is unchanged. check-changeset-overwrite reports the touch as report-only, with the declaration unchanged on both sides.

What the second commit corrects

cc75cab8d called layout's PageHeader "the renderer of the authored page:header node" in three places: the ConsolePageHeaderProps JSDoc, the app-shell changeset and the ledger comment that replaces the PageHeaderComponentProps row. That is not so. @object-ui/components registers page:header, and layout's own registerLayout records that its header's registration (under the kebab page-header key) was retired. 5dd334645 describes layout's header by its props instead, and says which package renders page:header. It changes comments and changeset prose only.

Rider

From batch 7's ACCEPT: the plugin-list switcher's icon-map comment said "the same glyph for the same ViewType". Inside plugin-list that bare name now means @object-ui/types' wider vocabulary, so the comment now says "the same glyph for the same visualization".

Gates

Heavy runs went through os-verify-lock. Everything below is at head 5dd334645 unless it says cc75cab8d. The second commit changed only the app-shell header JSDoc, one changeset body and comment lines in the gate file, so the runs at cc75cab8d cover the same plugin-list, plugin-dashboard and layout sources as head.

  • The gate, pnpm exec vitest run scripts/__tests__/one-authority-per-exported-name-6273.test.ts: exit 0, Tests 11 passed (11). The ledger has 13 rows.
  • Suites:
    • at cc75cab8d: pnpm exec vitest run --maxWorkers=2 over packages/plugin-list/, packages/layout/, packages/app-shell/src/layout/, app-shell's spec-symbol-parity.test.ts and 18 test files elsewhere that read a touched file's text or path: exit 0, Test Files 239 passed (239), Tests 2735 passed (2735);
    • at cc75cab8d: packages/plugin-dashboard/: exit 0, Test Files 174 passed (174), Tests 1725 passed, 6 skipped (1731). The 6 skips are the two describe.runIf(DRIVEN) time-zone suites in the date-only-zone filter-bar test;
    • at head: packages/app-shell/src/layout/, the parity test, packages/layout/src/__tests__/ and the 18 readers again: exit 0, Test Files 114 passed (114), Tests 1351 passed (1351).
  • Type-checks, with dist rebuilt and the script names echoed:
    • at cc75cab8d: pnpm --filter @object-ui/PKG type-check for plugin-list, plugin-view, plugin-dashboard, plugin-detail and layout, chained: exit 0, 0 error TS lines;
    • at head: app-shell's type-check and pnpm type-check:scripts, chained: exit 0, 0 error TS lines;
    • the touched tests are in scope: app-shell's tsconfig.test.json lists both touched app-shell tests, layout's lists its touched test, and tsconfig.scripts.json lists the gate.
  • check:doc-snippets: 785 of 785 blocks judged, 0 failed, after its own scoped build. check:readme-exports: OK, 582 of 582 self-imports real.
  • Each exit 0: check:control-bytes, check:test-path-roots, check:changeset-claims, check:pending-changeset-literals, check:icon-record-names (it reads the plugin-list switcher's icon map), check:spec-symbols, check:handler-key-reads, check:new-line-citations (0 new), check-changeset-no-major, check-changeset-fixed, and check-changeset-presence (9 source files of 4 released packages, 4 changesets).
  • pnpm exec eslint on the 10 touched TS files: 0 errors. The 10 warnings sit on unchanged lines in layout's PageHeader.tsx, the dashboard drawer and the plugin-list barrel, and those three files carry the same counts at base (4, 3 and 3).
  • The governed-queue guard reads NOT GOVERNED over the 15 paths.
  • git merge-tree against main 20c6d351 is clean. main has not moved since the base.

Not run locally:

  • The full app-shell suite. CI runs it.
  • The type-checks of the console and the other dependants. No file outside the six packages names any of the renamed types, and the only published move is plugin-list's, which has 0 readers in the repo.
  • The i18n gates. No locale pack changed.

Reverse verification

Every leg went through ablation-replace in wrap mode, with predictions written before any leg ran. The gate is a source scan, so no dist leg applies. Each leg landed on disk (anchor count 1 to 0, blob changed) and was restored with blob equal to HEAD and an empty git diff HEAD, which the tool checked and the driver checked again. All legs below were re-run at head 5dd334645 with the same results.

leg mutation result (as predicted)
S1 the ViewSwitcherProps row put back Tests 1 failed, 10 passed; no longer collides at: lists both ViewSwitcher.tsx files
S2 the RecordDetailDrawerProps row put back same verdict; lists the plugin-dashboard and plugin-detail RecordDetailDrawer.tsx
S3 the PageHeaderComponentProps row put back same verdict; lists app-shell's and layout's PageHeader.tsx
F1 the plugin-list barrel re-exports ListViewSwitcherProps as ViewSwitcherProps (the tempting back-compat shim) ViewSwitcherProps — a NEW colliding name: the plugin-list barrel (aliasing re-export) and plugin-view's ViewSwitcher.tsx (type declaration)
F2 the dashboard declaration renamed back RecordDetailDrawerProps — a NEW colliding name: both RecordDetailDrawer.tsx (interface declaration each)
F3 the console declaration renamed back PageHeaderComponentProps — a NEW colliding name: both PageHeader.tsx (interface declaration each)
control unmutated, before and after the legs Tests 11 passed (11)

The failing test in every leg is "declares no name twice outside the named, shrinking baseline". The first attempt at S1 to S3 was a no-op: each replacement kept its neighbouring ledger row verbatim, so it contained its own anchor. ablation-replace saw the anchor count stay at 1, refused the write and restored the file without running the gate. Those three readings were voided, the anchors were moved onto each row's own comment line, and the legs above are the second attempt.

Acceptance notes

  • One published-name move. ListViewSwitcherProps is new on the plugin-list root, replacing ViewSwitcherProps. It is the rename target that the dispatch's rule implies for a published site ("a rename of a published site publishes the specific name at the same entry"), so this PR does not treat it as an extra export.
  • JSDoc on each renamed site says why the general name is not used, so the next author does not restore it.
  • Stale pointers, not touched (outside the claim's file surface). Four plugin comments and their four tripwire tests cite as precedent the rename of PageHeaderProps to PageHeaderComponentProps "(app-shell)": ObjectCalendar.tsx, ObjectForm.tsx, ObjectGrid.tsx, ObjectKanban.tsx, and the spec-symbol-4650.test.ts beside each. The precedent stays true as history (app-shell made that rename in objectui#3169, and layout carries the name today), but the "(app-shell)" pointer now lands on ConsolePageHeaderProps, whose JSDoc records the rename. The four source comments ship in each package's declaration JSDoc. Changing them here would add four packages and four changesets for prose alone, so they are left for the seat to carry as a rider if it wants one.
  • Pre-existing, not changed. app-shell's subtitle test header and layout's PageHeaderComponentProps JSDoc still describe layout's header as the rendered layer of the page:header node, although objectui#10859 retired its registration. That text predates this PR and this PR does not make it falser. It is noted here only.

Generated by Claude Code

claude added 2 commits October 9, 2026 23:34
…for ViewSwitcherProps, RecordDetailDrawerProps and PageHeaderComponentProps (objectui#6349, batch 8)

Each of the three names was declared in two published packages for two
different components, so the side with the narrower meaning takes a
specific name and the row leaves KNOWN_COLLISIONS (16 to 13 rows).

- ViewSwitcherProps: plugin-list's visualization switcher props are now
  ListViewSwitcherProps, and the plugin-list root publishes that name
  instead. plugin-view keeps ViewSwitcherProps for the view-switcher
  renderer. Neither package depends on the other.
- RecordDetailDrawerProps: plugin-dashboard's read-only drill drawer props
  are now DashboardRecordDetailDrawerProps (no entry reached them).
  plugin-detail keeps the name for its published record drawer.
- PageHeaderComponentProps: app-shell's console header props are now
  ConsolePageHeaderProps (no entry reached them). layout keeps the name
  for its page:header renderer; re-pointing app-shell at it does not
  compile.

Types and comments only. Also: the ViewSwitcher icon comment says
"visualization" instead of ViewType (batch 7 rider), and batch 7's pending
plugin-list changeset points at the new props name.

Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8
Co-authored-by: Claude <noreply@anthropic.com>
…(objectui#6349, batch 8)

The batch 8 commit described @object-ui/layout's PageHeader as "the renderer
of the authored page:header node" in three places: the ConsolePageHeaderProps
JSDoc, the app-shell changeset and the ledger comment that replaces the
PageHeaderComponentProps row. That is not so. @object-ui/components registers
the page:header node type; layout's PageHeader is a published React component
whose own registration (the kebab page-header key) was retired, and
layout's registerLayout() says so.

The three texts now describe layout's PageHeader by its props (string title
and subtitle with record tokens, action definitions, showBack, schema, every
DOM attribute) and say which package renders page:header. Comments and a
changeset body only; no type, export or runtime change.

Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 290 chunks) 3168.0 KB 3204.6 KB
Main entry chunk (gzip) 73.7 KB 350 KB
Entry file index-BvRmWNQP.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) 19.75KB 7.29KB
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.83KB 141.44KB
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) 269.42KB 68.20KB
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) 40.26KB 11.71KB
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.72KB 23.27KB
plugin-chatbot (index.js) 201.52KB 47.99KB
plugin-dashboard (index.js) 144.20KB 38.95KB
plugin-designer (index.js) 233.53KB 49.80KB
plugin-detail (index.js) 249.09KB 65.63KB
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) 249.62KB 69.16KB
plugin-kanban (index.js) 52.77KB 16.56KB
plugin-list (index.js) 120.10KB 30.28KB
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.06KB 11.80KB
plugin-tree (index.js) 15.07KB 5.33KB
plugin-view (index.js) 91.93KB 23.24KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
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.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
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: 5dd334645739a7c9bcd215bab72802c00d8fc9dd
Local-runs: none

Inputs read: card objectui#6349, its body and all 34 comments (the batch 8 claim 6090897330, the resumed dev's report 6091679483, the amendment 6091699602, the rules they cite in 5548770074, 6077155250, 6078948754, 6081214732 and 6089430007, and tier notice 5612085492); PR objectui#12074, its body, its 15-file list and the net diff against main at the head (369 lines, +124/−32); the 43 check-runs on the head. The six packages' barrels and exports maps at the head were read through the REST contents endpoint, as the batch 6 and 7 records did. Nothing was built, run or re-run.

① Derived judgments

The ledger KNOWN_COLLISIONS goes from 16 rows to 13. Each row, named right or wrong:

  1. ViewSwitcherProps — RENAME of the plugin-list side, right. Two meanings: plugin-view's is the props of the registered view-switcher renderer (a ViewSwitcherSchema plus host callbacks, keyed on the whole ViewType); plugin-list's is the list view's own visualization switcher (currentView, availableViews, onViewChange, keyed on core's ListViewVisualization). Dependency edges read at the head: plugin-list's @object-ui dependencies do not include plugin-view, and plugin-view's do not include plugin-list, so no re-point is dependency-legal in either direction and the narrower side takes the specific name ListViewSwitcherProps. Public surface: plugin-list's exports map is . only and its barrel has no star export; line 33 now publishes ListViewSwitcherProps and ViewSwitcherProps is gone from it, while the ViewSwitcher and ViewSwitcherDropdown components keep their names. plugin-view's barrel still publishes ViewSwitcherProps (line 25), unchanged. The published-name removal is not a stop under the claim's wording ("a name something reads through a package entry"): the Type Check and Build & E2E check-runs on the head are success, which corroborates the 0-reader census, and the shape is the one amendment 6089430007 accepted for GroupAggregationConfig in batch 7. Members are untouched by the diff.
  2. RecordDetailDrawerProps — RENAME of the plugin-dashboard side, right. Two drawers: plugin-detail's is the published, editable record drawer (open, recordId, dataSource, save, delete, resize); the dashboard's is the read-only drill drawer of a table widget (record may be null, target, fields). plugin-dashboard's dependencies do not include plugin-detail and plugin-detail's do not include plugin-dashboard, so a re-point is not dependency-legal; the narrower side takes DashboardRecordDetailDrawerProps. Public surface: plugin-dashboard's exports map is . only, and its barrel at the head has no star export and no mention of RecordDetailDrawer, so neither the old nor the new name was ever importable from @object-ui/plugin-dashboard. plugin-detail's barrel still publishes RecordDetailDrawerProps (line 105). No published name moves.
  3. PageHeaderComponentProps — RENAME of the app-shell side, right. app-shell depends on layout, so a re-point was dependency-legal; the dev's base probe (8 errors: accentColor, sticky and data-testid are not layout members, and the console callers hand rendered nodes where layout takes a string title and action definitions) shows two meanings, and the member lists in the diff bear that out. The console's declaration takes ConsolePageHeaderProps; layout is the one authority, and its barrel's export * from './PageHeader' is unchanged. Public surface: app-shell's root barrel re-exports a named list from ./layout/index.js (lines 143 to 156) that contains neither PageHeader nor either props name, has no star export, and its exports map is . plus ./styles.css, so neither name was ever importable from @object-ui/app-shell. app-shell/src/layout/index.ts now re-exports the new name. No published name moves.
  4. The ledger edit, right. The diff removes exactly the three rows and puts a "sat here" comment in each one's place, the pattern batches 4 to 7 landed; no other row changes. The gate's verdict on the head is the check-runs'.
  5. Tests beside the sites, right. spec-symbol-parity.test.ts moves its RENAMES entry to ConsolePageHeaderProps, so the pin that the spec does not own the name keeps its subject; PageHeader.subtitle.test.tsx changes a type import; layout's spec-symbol-batch7.test.ts changes a comment. All are re-point-only edits. Layout's JSDoc also corrects the pinned test's citation from .tsx to .ts, which matches the file list.
  6. Batch 7's rider, done. The plugin-list icon-map comment now says "the same glyph for the same visualization".
  7. The second commit, right. It corrects "the renderer of the authored page:header node" in the ConsolePageHeaderProps JSDoc, the app-shell changeset and the ledger comment. Corroborated at the head: layout's registerLayout records that its kebab page-header registration is retired (objectui#10859) and that @object-ui/components registers page:header. Comments and changeset prose only.
  8. Scope fence, held. No packages/components/src/ui/**, no packages/i18n/**, no other ledger row. No runtime change: every code hunk in the diff is an interface name or a type argument; Bundle Analysis is success and the perf-budget comment on the PR reads PASS.

Gate verdicts, from the 43 check-runs on the head: 40 success, 3 skipped (Test (coverage), Test (coverage shard), dependabot, the three every earlier batch recorded as expected), 0 failure. Among the successes: Type Check, Test with its 8 shards and dist pins, Build & E2E, Lint, Changeset Declaration, Changeset Bump Policy, Changeset Fixed Group Check, Changeset Overwrite Report, Changeset Claim Re-read, Governed Surface Queue Guard, README Export Check, Doc Snippet Type Check and Line Citation Gate.

PR shape: draft against main, based on 20c6d351 (the claim's ref), mergeable clean; first line Refs #6349 (batch 8), no closing keyword anywhere in the body; two commits, the second is the head, both carry the model-free trailer pair; no model name in the body.

② Semver level

  • Clause-②: yes at line 3 of the body, line-initial: right. A published name moves on the plugin-list root.
  • @object-ui/plugin-list: minor with a breaking note and the migration (the compiler names the replacement, TS2724): right under the claim's per-package criterion ("minor where a published shape moves or a name leaves, with a breaking note") and objectui AGENTS.md §9; check-changeset-no-major is success.
  • @object-ui/plugin-dashboard: patch and @object-ui/app-shell: patch: right. Neither renamed name was ever importable from its package entry (①.2 and ①.3).
  • @object-ui/layout: patch: right. JSDoc only; the type and its members are unchanged, and a changeset is owed because a source file of a released package changed (Changeset Declaration success, 9 source files of 4 released packages, 4 changesets).
  • plugin-view and plugin-detail are untouched, so no changeset is owed. Right.
  • .changeset/6349-batch7-plugin-list.md: one body sentence, front matter and @object-ui/plugin-list: minor unchanged in the diff; accepted on the surface by amendment 6091699602; Changeset Overwrite Report is success. Right.
  • Tier notice 5612085492 lifted this card's contract-review-tier requirement; the seat runs the review at this tier because of the Clause-②: yes line, as batch 4's record noted.

③ Boundary flags

open_questions in report 6091679483: none.

Deviations, each answered:

  • Resume. The killed run's cc75cab8d was kept whole and 5dd334645 was added, with no rewrite and no force-push: the PR lists exactly those two commits and the second is the head; amendment 6091699602 accepts the resume. Answered.
  • Batch 7's pending changeset edited. Accepted by the amendment; declaration unchanged (② above). Answered.
  • Ablation first attempt a refused no-op. A local-process note; nothing here rests on it, since the check-runs are the gate verdicts. Answered.
  • Trailers and footer. Verified on the commits and the body; no model name anywhere. Answered.
  • Not run locally. The full app-shell suite: Test, its 8 shards and Build & E2E are success. The console's and other dependants' type-checks: Type Check is success. The i18n gates: no locale pack and no packages/i18n/** file is in the 15-file list. Answered.
  • Scratch reuse and worktree cleanup. Not contract matters. Answered.

out_of_scope_findings, escalated to the seat (comment-only, no gate reads them, none blocks):

  • The stale "(app-shell)" precedent pointers in ObjectCalendar.tsx, ObjectForm.tsx, ObjectGrid.tsx, ObjectKanban.tsx and the spec-symbol-4650.test.ts beside each: carry as a named rider on the next batch that touches those files, the way batch 7's ViewSwitcher rider was carried into this one. Outside the claim's surface; the history they cite stays true.
  • Layout's PageHeaderComponentProps JSDoc still ends with the "authored layer vs rendered layer" paragraph, and the subtitle test's header still calls layout's header the rendered layer of page:header, although that registration is retired. Pre-existing; this PR edits the paragraphs above it in the same block and leaves this one. A rider candidate for the seat.
  • The first commit's message says "layout keeps the name for its page:header renderer"; the second commit and the PR body correct it. A commit message is history and needs no rewrite.

Implemented-by: claude/issue-6349-batch8-component-props
Reviewed-by: session_01CGZy1BGCjdN5cXqL9cnvB8

VERDICT: PASS

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 10, 2026 01:00
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 10, 2026 01:00
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 10, 2026
Merged via the queue into main with commit d758f2f Oct 10, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-6349-batch8-component-props branch October 10, 2026 01:20
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