Skip to content

feat(types): declare the five handler keys the list-view renderer reads (objectui#7804) - #9565

Merged
os-justin merged 3 commits into
mainfrom
claude/issue-7804-listview-handler-keys-slice3
Sep 15, 2026
Merged

os-justin merged 3 commits into
mainfrom
claude/issue-7804-listview-handler-keys-slice3

Conversation

@os-justin

@os-justin os-justin commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

Part of #7804 — slice 3 of the handler-key burn-down: the ListViewSchema family.

⛔ No closing keyword: this card's ledger is not empty. Measured on this branch,
with the command:

$ node -e 'import("./scripts/check-handler-key-read-sites.mjs").then(m=>{
    const k=[...m.KNOWN_UNDECLARED_READS.keys()];
    console.log("total",k.length,
                "| list-view::",k.filter(x=>x.startsWith("list-view::")).length,
                "| control list::",k.filter(x=>x.startsWith("list::")).length);})'
total 15 | list-view:: 0 | control list:: 5

KNOWN_UNDECLARED_READS read 20 rows at this branch's base (88561fdc4) and reads
15 here. list-view:: drained to 0; the lit control in the same pass is the five
list:: rows, which are still there — so the zero is a reading, not an empty query.

What this slice does

The zod arm type: 'list-view' selects now declares onAddRecord, onBulkAction,
onDensityChange, onNavigate and onPageSizeChange as objectui#6124 RUNTIME SLOTS.

Disposition measured per key, never forced to match the group. 'retired' was
refused for all five — every one is read AND invoked. The channel is not the same face
for all of them, and that split is what this slice turned on:

key read as TypeScript channel in-repo supplier
onNavigate schema.onNavigate into useNavigationOverlay ListViewRuntimeProps (already declared) none; channel wired end to end
onDensityChange schema.onDensityChange into useDensityMode ListViewRuntimeProps (already declared) app-shell's ObjectView, on its const fullSchema: ListViewSchema node
onAddRecord props.onAddRecord?.() on the toolbar add button React prop on ListViewProps + newly declared on ListViewRuntimeProps StudioDesignSurface, as a React prop
onBulkAction props.onBulkAction?.(action, rows) same pair none; channel wired end to end
onPageSizeChange props.onPageSizeChange(newSize) on the pager same pair none; channel wired end to end

three members ARE added to ListViewRuntimeProps, so a published interface widens.
That corrects this branch's own first reading — see the Clause-② verdict below.

⚠️ The finding that changes the method: this arm feeds its own TypeScript face

Every earlier slice of this card drained a plain export interface X extends BaseSchema,
whose TypeScript face is hand-written and therefore untouched by what the mirror declares.
ListViewSchema is not that shape — it is z.input of the mirror (ListViewInferred)
intersected with ListViewRuntimeProps. A handlerKeyRefusal arm's z.input is
never | undefined, and an intersection ANDs per key, so:

(never | undefined) & (((recordId, action?) => void) | undefined)   ===   undefined

Measured, before any fix was written (tsc -p packages/types/tsconfig.test.json,
probing the resolved type by assigning it to 0):

probe before the arms with the arms, bare intersection
ListViewSchema['onNavigate'] ((recordId: string | number, action?: string) => void) | undefined undefined
ListViewSchema['onDensityChange'] ((mode: 'compact' | 'comfortable' | 'spacious') => void) | undefined undefined
ListViewSchema['onAddRecord'] unknown undefined

⛔ And nothing went redundefined is assignable to every optional callback
parameter the reads hand it. That is the silent failure mode: a 'runtime-slot'
disposition promises "the TypeScript twin stays callable", and a bare intersection makes
it a lie while every gate stays green.

The intersection now gives the runtime half precedence (ListViewAuthored). It is a
key-remapped mapped type and ⛔ not Omit, measured the same way: ListViewInferred
carries the passthrough index signature, so Omit over keyof ListViewRuntimeProps keeps
only that signature — objectName read unknown instead of string under the Omit
candidate. That is the same trap ListViewProps documents for PropsWithoutRef.
Both readings are pinned where they fail, at tsc, in
list-view-handler-slots-7804.test.ts.

Verdicts on the dispatch's five stated assumptions

  1. Five rows, still list-view:: — HALF FALSIFIED, and the half that moved matters.
    The five list-view:: rows are real and are exactly this slice. But the ledger holds
    ten rows for these same five read sites: plugin-list registers ListViewRenderer
    under 'list' as well, and the census keys a registration by its raw type string, so
    the alias's reads are judged a second time against ListSchema — the bullet-list
    display primitive. Detail and the reason it is ⛔ not drained here: see Acceptance
    notes.
  2. The intersection split — FALSIFIED. The two halves are not independent: the
    zod arm feeds ListViewInferred, which feeds the declared type. Reported above; the
    precedence type is the repair.
  3. Propagation — DOES NOT OCCUR here, measured. Nothing nests the local
    ListViewSchema mirror by reference. Its only references are the export in
    index.zod.ts, the ObjectQLComponentSchema discriminated union, and
    ListViewInferred. No sibling slot picks up the refusals the way ObjectViewSchema's
    nested form / table slots did in slice 2. ⇒ no blast radius to report on that axis.
  4. A duplicate declaration mis-anchoring the arity reader — DOES NOT OCCUR. The five
    names this slice adds to objectql.ts are checked against what that file already
    declares: onNavigate already appears there twice (on ObjectGridSchema and
    ObjectViewSchema), so this is a third — see Acceptance notes for the reading.
  5. Clause-②: yes — CONFIRMED, and my first reading of it was wrong. I initially
    measured that the three props-half keys need nothing added, because ListViewProps
    in @object-ui/plugin-list already declares all three by name. ⛔ That measured only
    ONE of the two supply paths into the props bag. SchemaRenderer spreads every
    non-metadata top-level key of the node into the props it creates the component with,
    so a host that builds the NODE in TypeScript reaches the same read — and that path was
    typed only by BaseSchema's passthrough index signature. Declaring the refusal arms
    without declaring the slots would have narrowed a live programmatic channel from
    unknown to undefined. So the three are declared on ListViewRuntimeProps, which is
    the same repair objectui#9344's slice made on ObjectGallerySchema for the same
    spread. ⇒ the slice is genuinely mixed-direction and yes is right.

⛔ FILE-SURFACE BREACH, declared — one file, and the PM's call

This claim's declared surface is packages/types/src/ (incl. __tests__/),
scripts/check-handler-key-read-sites.mjs, and one changeset. One file outside it is
edited
: packages/app-shell/src/views/ObjectView.relayRungCensus-7559.test.ts,
three lines plus a comment.

Why, measured: that census derives its population from the list-view mirror's shape
and from ListViewRuntimeProps' declared members, so the three slots entered it with
this change. It reddens — onAddRecord, onBulkAction, onPageSizeChange reported as
neither relayed nor declared — and its own failure text reads "If the member is new on
ListViewSchema, (1) or (2) is owed BY THE CHANGE THAT ADDED IT."
The repair is three
host-runtime absence entries: an EXISTING absence kind, whose existing validator
requires exactly ListViewRuntimeProps membership, so no new kind and no new assertion
were introduced.

⭐ Measured before touching it: neither sibling claim in this batch holds that file —
objectui#7234's branch touches ObjectView.objectBoundActions-7234.test.tsx and
metadata-admin/**, objectui#9295 touches no app-shell file at all.

The PM ratifies or reverts. To revert just that file:
git checkout 88561fdc4 -- packages/app-shell/src/views/ObjectView.relayRungCensus-7559.test.ts
— the rest of the branch stands on its own, and that test goes red again.

Gates

Captured to a file before reading the exit code, every one of them.

All at the final head cd4eb52aa, working tree clean.

command exit
pnpm check:handler-key-reads 0
pnpm check:changeset-claims 0
pnpm check:control-bytes 0
pnpm check:new-line-citations 0 (0 new citations)
pnpm changeset:check · node scripts/check-changeset-presence.mjs 0 · 0
pnpm --filter @object-ui/types type-check 0
pnpm --filter @object-ui/app-shell type-check 0
plugin-list · plugin-view · core · plugin-grid · react · components · plugin-detail type-check 0 each
pnpm exec vitest run --maxWorkers=2 over the affected suites 0 — 197 files, 4637 tests
pnpm exec eslint --no-inline-config over the 6 changed lintable files 0 errors
node scripts/check-governed-queue-guard.mjs --test … NOT GOVERNED

The gate can still fail. Deleting the onNavigate arm (mutation proven on disk,
1 → 0 occurrences) turns check:handler-key-reads RED, naming 'list-view'.onNavigate
as undeclared; restored, and the restore proven by blob hash equal to HEAD's and an empty
git diff HEAD for the path. Collapsing ListViewAuthored back to a bare intersection
turns tsc RED with exactly the two type pins, "does not satisfy the expected type
never"
.

The full table, with the ablation that proves the gate can still fail, is in the
os-dev-report comment on #7804.

Acceptance notes

noted, not filed — the list::ListSchema twin of these five rows. plugin-list
registers ListViewRenderer under 'list' with { namespace: 'view', skipFallback: true },
and skipFallback is precisely what stops that alias claiming the bare list key — which
belongs to the bullet/numbered-list display primitive in @object-ui/components. The
census keys a registration by raw type string, so the alias's five reads are scored against
ListSchema (items / ordered / dividers / dense). Declaring the five there would
publish a density handler on a bullet list, so ⛔ they are not drained here; the ledger now
records the measurement at the rows themselves. The same shape produces form::FormSchema
and grid::GridSchema.onNavigateplugin-form and plugin-grid register view:form
and view:grid the same way. Successor: the next slice of this card reads those rows.
Dedupe words: skipFallback, KNOWN_UNDECLARED_READS, namespaced alias, bare type key,
check-handler-key-read-sites.

noted, not filed — a third onNavigate declaration in objectql.ts. Slice 2 recorded
that objectui#9357's file-scoped arity reader mis-anchors when one file carries two
declarations of a name with different contracts. This slice adds a third onNavigate to
that file. It is a handlerKeyRefusal arm, not a signature-bearing declaration, and the
signature it pairs with (ListViewRuntimeProps.onNavigate) is unchanged and lives in
objectql.ts where it always did. CI is the instrument for that reader, and this PR's run
is what answers it.

noted, not filed — objectui#9547 is untouched. ObjectGridSchema.onNavigate's docblock
was not read, edited or relied on here.


Generated by Claude Code


Generated by Claude Code

…eads (objectui#7804)

The zod arm `type: 'list-view'` selects now declares `onAddRecord`,
`onBulkAction`, `onDensityChange`, `onNavigate` and `onPageSizeChange` as
objectui#6124 RUNTIME SLOTS — a named refusal on the JSON face, a callable
twin on the TypeScript face — and the five matching rows leave
`KNOWN_UNDECLARED_READS`.

Disposition measured per key, not per group. `'retired'` was refused for all
five: every one is read AND invoked. The channel is not the same face for all
of them, which is what this slice turned on:

  - `onNavigate` / `onDensityChange` are read off the NODE (`schema.onX`) and
    already declared on `ListViewRuntimeProps`.
  - `onAddRecord` / `onBulkAction` / `onPageSizeChange` are read off the PROPS
    bag (`props.onX`) and already declared as React props on `ListViewProps`
    in `@object-ui/plugin-list`.

⇒ nothing is added to `ListViewRuntimeProps`; no published interface widens.

⚠️ This arm FEEDS its own TypeScript face — `ListViewSchema` is `z.input` of
the mirror intersected with `ListViewRuntimeProps` — and a refusal arm's
`z.input` is `never | undefined`, which ANDs a runtime declaration down to
`undefined`. Measured before the fix: `ListViewSchema['onNavigate']` resolved
to `undefined`, down from its function type, and nothing went red, because
`undefined` is assignable to every optional callback parameter the reads hand
it. `ListViewAuthored` gives the runtime half precedence so `'runtime-slot'`'s
promise stays true, and it is a key-remapped mapped type rather than `Omit`
because `Omit` over the passthrough index signature keeps only that signature
(measured: `objectName` read `unknown`). Both readings are pinned in
`list-view-handler-slots-7804.test.ts`, where they fail at `tsc`.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3063.1 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-fjvSioHE.js
Status PASS

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


📦 Bundle Size Report

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

Size Limits

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

`list-view-spec-parity.test.ts` asks every objectui-only member of the
`list-view` arm to be a conscious local-vs-upstream decision. The five
`handlerKeyRefusal` arms this slice declared are neither branch it offers:
promoting one into `@objectstack/spec` would ask the protocol to declare a key
JSON cannot express, and calling it a "genuine objectui-only extension" would
say the arm accepts something — it accepts nothing.

So they get their own named category rather than a row in `SANCTIONED_LOCAL`,
and membership is CHECKED: a new assertion refuses a member the arm does not
declare, or that accepts either an authored action object or a function, with
an authorable sanctioned-local key (`viewType`) as the lit control in the same
pass. The set therefore cannot be used to park a real authorable field outside
the drift guard.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3063.1 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-fjvSioHE.js
Status PASS

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


📦 Bundle Size Report

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

Size Limits

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

Corrects this branch's own first reading. I had concluded that nothing needed
adding to `ListViewRuntimeProps` because `onAddRecord` / `onBulkAction` /
`onPageSizeChange` are read off the PROPS bag and `ListViewProps`
(`@object-ui/plugin-list`) already declares all three as React props.

⛔ That measured only ONE of the two supply paths into that bag. `SchemaRenderer`
spreads every non-metadata top-level key of the node into the props it creates
the component with, so a host that builds the NODE in TypeScript reaches the
same read — and that path was typed only by `BaseSchema`'s passthrough index
signature. Declaring the refusal arms without declaring the slots would have
narrowed a live programmatic channel from `unknown` to `undefined`, which is
wider than this card asks for and is not what `'runtime-slot'` means. It is the
same repair objectui#9344's slice made on `ObjectGallerySchema` for the same
spread, and it means a published interface WIDENS here as well as narrowing —
the changeset says so.

`ObjectView.relayRungCensus-7559.test.ts` follows from that: the three entered
its derived population with this declaration, and its own failure text says the
answer is owed by the change that added them. Three `host-runtime` absences,
the existing kind whose validator requires exactly `ListViewRuntimeProps`
membership — no new absence kind, no new assertion.

⚠️ FILE SURFACE: that census file is outside this claim's declared surface
(`packages/types/src/`, `scripts/check-handler-key-read-sites.mjs`, one
changeset). It is reported rather than hidden; see the pull request body.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3063.1 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-fjvSioHE.js
Status PASS

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


📦 Bundle Size Report

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

Size Limits

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

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: cd4eb52aa

In-seat clause-② review by the dispatching domain:ui seat, default judgement tier plus the gates, per this lane's recorded tier ruling (5612097546, objectstack#17285) and contract-review.md:26 「余席默认档自审加门禁」; the 降档保险丝 at :51 binds only the spec and skills seats. Judged from the PR's actual diff, ⛔ not from the claim and ⛔ not from the report's account of itself.

① Derived judgments

The card-side declaration was Clause-②: yes, and unlike the sibling card this round it is ⛔ not merely conservative — the diff is genuinely mixed-direction. Both halves measured in the diff:

direction reading on this head
NARROWS the accept set five handlerKeyRefusal(..., 'runtime-slot', ...) arms added to the type: 'list-view' zod arm: onAddRecord, onBulkAction, onDensityChange, onNavigate, onPageSizeChange. Previously BaseSchema.passthrough() left them un-judged and KEPT; they are now refused by name at the key's own path with code: 'custom'
WIDENS a published surface three members added to ListViewRuntimePropsonAddRecord?, onBulkAction?, onPageSizeChange?. That interface is published from @object-ui/types ⇒ a real public-surface addition
new exported symbol 1 added line carries export, and it is the re-declaration of the already-exported ListViewSchema. The new precedence type ListViewAuthored is local, not exported ⇒ no new export
packages/spec/** touched no

Clause-②: yes CONFIRMED, and correctly so: the narrowing half does not cancel the widening half.

The judgment that matters most is one the dev found and I had assumed away. My dispatch said the zod arm and the TypeScript face were two independent questions. They are not: this arm feeds its own TS face (ListViewSchema = z.input(mirror) & ListViewRuntimeProps), and a refusal arm's z.input is never | undefined, which ANDs a runtime declaration down to undefined. Measured before repair: ListViewSchema['onNavigate'] resolved to undefined, down from its function type — and nothing went red, because undefined is assignable to every optional callback parameter the reads hand it. ⇒ declaring the refusals without the precedence type would have silently narrowed a live programmatic channel from a callable to undefined, with every gate green. Repaired with a key-remapped precedence type (ListViewAuthored), ⛔ not OmitOmit over the passthrough index signature was measured to keep only that signature, dropping objectName from string to unknown.

② Semver level

@object-ui/types: minor, one changeset. Correct, and the break is real: the accept-set move refuses keys that previously parsed green and were kept. The changeset spells it out with the measurement (each of the five parsed green carrying {"action":"toast"} into the output while ListView went on reading and invoking it) and names its lit controlonRowClick, still undeclared on the same arm, still accepted and still kept, proving the probe distinguishes a refusal from a parser rejecting everything. major is unavailable because this package ships inside the fixed group, cited to scripts/check-changeset-no-major.mjs; gate exit 0 and all five changeset checks green in CI.

③ Boundary flags

  • Governed surface: NOT GOVERNED — all 7 changed paths checked by this seat against the five governed surfaces; no match ⇒ merge-queue route.
  • File-surface breach: ratified separately, ⛔ not silently absorbed — one file outside the declared surface (packages/app-shell/src/views/ObjectView.relayRungCensus-7559.test.ts), declared by the dev in both the report and the PR body, four adjacency conditions answered, claim surface amended in-round at 5682977889.
  • open_questions: empty.
  • dev flags answered: the three declared narrowings (heavy runs, type-check sweep, lint) each carry population, count and an invariance argument, and the two ablations each proved mutation-on-disk before the run and restore-by-blob-hash after. ⭐ exit 99 on the shared lock was read as NOT MEASURED, ⛔ never as green.
  • One API write over budget (a PATCH of the PR body after the clause-② finding reversed mid-branch). Disclosed, and the right call: publishing a body the author knew to be false is the worse option. ⛔ Not a rework trigger.
  • An out-of-scope card is owed and is this seat's to file: the ledger keys a registration by its raw type string, so a namespaced-only alias registered { namespace: 'view', skipFallback: true } is judged against the bare key's arm — which skipFallback exists precisely to stop it claiming. 10 of the 15 rows left on this card are that shape.

Implemented-by: claude/issue-7804-listview-handler-keys-slice3
Reviewed-by: session_01KSd9P5u2Mf4p8g4n4SD4Fx

⚠️ A mode:subagent dev records its BRANCH, having no session of its own, so the session field echoed in the dev's own JSON is the dispatching session by construction and is ⛔ not a SELF-REVIEW tell.

CI on this exact head: 36 checks — 33 success, 3 skipped, 0 non-green, 0 pending; Lint and Type Check read individually, both success, each pinned to head.sha.

VERDICT: PASS

domain:ui execution seat · session_01KSd9P5u2Mf4p8g4n4SD4Fx (os-justin) · reviewed at 2026-09-15T15:40Z


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Provenance for the carrier clear — objectui#7804 / PR objectui#9565

Both needs:contract-review carriers (PR-side and card-side) stripped by the dispatching domain:ui seat, session_01KSd9P5u2Mf4p8g4n4SD4Fx (os-justin).

  • Record of record: comment 5683239148 on this PR — ## Contract review, VERDICT: PASS.
  • Head judged: cd4eb52aa, this PR's current head.
  • Machine check: PM_SWEEP_REPO=objectstack-ai/objectui node scripts/pm/check-clause2-carriers.mjs --pair 9565exit 0, run BEFORE the strip this time and captured to a file before reading $?. The guard read the record at tier on both C6 and C7.

⭐ Sequence corrected from the sibling PR objectui#9567 earlier this round, where I stripped first and the guard then refused my record at exit 4. ⇒ --pair before the strip, ⛔ not after.


Generated by Claude Code

@os-justin
os-justin marked this pull request as ready for review September 15, 2026 15:41
@os-justin
os-justin added this pull request to the merge queue Sep 15, 2026
Merged via the queue into main with commit f1cd290 Sep 15, 2026
38 checks passed
@os-justin
os-justin deleted the claude/issue-7804-listview-handler-keys-slice3 branch September 15, 2026 15:59
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