Skip to content

fix(types): judge the object-kanban handler keys the board reads (objectui#7804) - #9338

Merged
os-tesla merged 4 commits into
mainfrom
claude/issue-7804-kanban-arm
Sep 13, 2026
Merged

fix(types): judge the object-kanban handler keys the board reads (objectui#7804)#9338
os-tesla merged 4 commits into
mainfrom
claude/issue-7804-kanban-arm

Conversation

@os-tesla

@os-tesla os-tesla commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator

Part of objectui#7804 — the plugin-kanban slice. ⛔ That card stays OPEN and stays the parent; PRs land per package (director seat, decision batch #69, 2026-09-07).

What this does

ObjectKanbanSchema now judges two of the three handler keys KanbanRenderer reads off the authored document, each disposition measured at its own channel rather than shared across the on* prefix:

key disposition the channel that decides it
onCardClick runtime-slot ObjectKanban substitutes the schema key, but SchemaRenderer spreads the authored key as a React prop, ObjectKanbanComponentProps declares that prop, and the substituting wrapper calls it
onQuickAdd runtime-slot rides ObjectKanban's ...schema spread untouched and arrives at the board implementation by identity
onCardMove 'retired' — measured, NOT landed neither channel delivers: the schema key is replaced by handleCardMove, and ObjectKanban declares no onCardMove prop (its rest parameter is discarded)

⛔ "ObjectKanban overrides it" is true of onCardClick and onCardMove and separates neither. What separates them is the prop channel, which only onCardClick has — so that is what the pin drives, rather than inferring from the override.

The base reading, pinned before the code

The pin was written first and run on the unmodified base tree (0f3d15314). All three keys parsed GREEN, with the authored value surviving into the parsed output:

AssertionError: an authored `onCardClick` still parses GREEN — the passthrough is
keeping it and handing it to a call site that expects a function:
-   "accepted": false,  "code": "custom",  "path": "onCardClick",
+   "accepted": true,   "code": null,      "path": null,

That is objectui#7664's measured transition, inherited by this face: the three sat on the bare kanban arm as objectui#6124 runtime slots until objectui#8802 retired that arm, and the surviving object-kanban face kept the reads without the declarations.

⚠️ Why the third key is reported instead of declared

check:handler-key-reads is the gate of record here, and it refused the 'retired' spelling. Its own printed line, verbatim from a run on this branch:

x  1 handler key(s) a registered renderer reads are not declared by their arm:

      'object-kanban'.onCardMove  read at packages/plugin-kanban/src/index.tsx:271
          registered in packages/plugin-kanban/src/index.tsx; ObjectKanbanSchema
          (objectql.zod.ts) declares it RETIRED, but a renderer still reads it.

The gate's own contract says why: a tombstone "exists precisely because nothing reads the key — it has no read site BY CONSTRUCTION". KanbanRenderer does read schema.onCardMove; what the gate cannot see is that the value at that read was substituted one hop earlier.

⛔ Both spellings that would make it green are worse, so neither was taken:

  • 'runtime-slot' keeps the TypeScript twin callable and so publishes a key the object-bound board drops — the one resolution this package's own quickAdd carve-out records as forbidden ("it would publish a key the renderer cannot honour, which is the failure mode this whole gate exists to catch").
  • Deleting the read narrows KanbanRenderer's published props. That is the objectui#7742 remedy (objectFields, one file over, maintainer decision batch Add cloud storage functionality with Vercel KV integration in studio #70) and is a ruling, not a repair.

onCardMove keeps its KNOWN_UNDECLARED_READS row naming objectui#7804, and the pin records it as still accepted and KEPT so the exposure cannot drift in silence. The two rows that landed are drained, because a row outliving its read reddens staleExemptions().

Gate of record, after

OK  105 arm(s), 212 registration(s) (119 with an arm), 59 reachable handler read(s),
    59 judged, 0 left unjudged on an arm with an unresolved spread, 37 exempted by
    ledger — every judged read is a declared member of its arm.

39 → 37 ledger rows. --list now reports:

'object-kanban' ObjectKanbanSchema.onCardClick  [runtime-slot]  .../index.tsx:272
'object-kanban' ObjectKanbanSchema.onCardMove   [UNDECLARED]    .../index.tsx:271
'object-kanban' ObjectKanbanSchema.onQuickAdd   [runtime-slot]  .../index.tsx:275

Contract carrier

Neither landed disposition is an arm widening: both are objectui#6124 named refusals, so the published zod accept set narrows (two documents that parsed green are now refused, each at its own path) and nothing new becomes authorable. @objectstack/spec's ObjectKanbanPropsSchema — 14 keys on the installed 17.4.0 pin — already refuses all three with unrecognized_keys (measured, with zzzNotAKey as the firing control and a key-less document as the lit control), so this moves toward the protocol, not away from it. The TypeScript face gains two typed members where BaseSchema's index signature used to absorb them.

needs:contract-review is hung all the same: the dispatch claim declared Clause-②: yes, and this is an accept-set move on a published mirror even though it is a narrowing. ⛔ Neither limb is cleared here — that is the PM's.

Blast radius

  • Authored-document census across apps/ · examples/ · content/ · packages/: no object-kanban document in this repository authors onCardClick or onQuickAdd. The two examples/schema-catalog kanban boards carry { columns, data, groupBy, type } only.
  • One document authors the third key: packages/components/src/renderers/complex/README-KANBAN.md teaches "onCardMove": "(event) => …" on an object-kanban node. It is untouched here — that key's acceptance does not move in this PR — and it is named in the Acceptance notes as evidence for the escalation above.
  • No renderer change, no registration change, no inputs change.

Tests

  • NEW packages/plugin-kanban/src/__tests__/handlerKeyDispositionsMeasured-7804.test.tsx — 4 suites, 14 tests. Suite 2 drives the handler the board was handed for the dead-key claim rather than inferring it from identity, with onCardClick as the lit control on the same document and the same render (an absent read and an unreachable one look identical to a grep).
  • Re-based: kanban-handler-slots-7664.test.tsx (its verdict flips a second time, now spelled per key), handler-keys-json-refusal-6124.test.ts (ledger 62 → 64 sites, 42 → 44 runtime slots), zod-mirror-parity.test.ts (KnownDrift 40 → 41 entries, 61 → 63 keys), scripts/__tests__/check-handler-key-read-sites.test.ts.
  • pickKey in the finding(types): 28 zod-mirror keys are declared z.function(), which NO JSON document can satisfy — 14 in-repo corpus files author them and are silently invalid #6124 ledger is rebuilt from the member declaration instead of .pick(): ObjectKanbanSchema ends with .superRefine(requireKanbanRecordSource), and zod throws on .pick() over an object carrying refinements — a throw would have read as the instrument breaking rather than as a missing fixture. Every probe writes only the key under test, so no existing reading moves.

In flight

Confirmed disjoint rather than assumed, by reading each PR's file list: objectui#9334 (plugin-detail, plugin-form, react) — no overlap; PR objectui#9310 touches packages/plugin-kanban/src/index.tsx, but only inside ObjectKanbanRenderer, below the KanbanRenderer body this PR's derivations read, and it touches no packages/types file and none of the shared pins. No textual or semantic overlap; the union is a plain merge.

Acceptance notes

Found while measuring, not fixed here:

  • ⚠️ An onCardClick authored on an object-kanban document runs TWICE per card click — filed as objectui#9341. ObjectKanban passes the same function to useNavigationOverlay as onRowClick — whose handleClick forwards to it and returns — and then calls it again itself. Measured: the lit control in the new pin fired 2, not 1, with the sibling onCardMove spy at 0 on the same render as the firing control. Reported rather than pinned, so repairing it does not redden a file that is not about it. Deduplicated against the nine open plugin: kanban cards with objectui#8285 as the known-hit control; /search/issues is proxy-refused in this container, so the repo-scoped list plus a local grep is the channel.
  • ⛔ Verification narrowed nowhere that matters, and the exclusion the dispatch warned about was checked rather than assumed: a membership read of every manifest naming @object-ui/types returns 37 dependants, all declaring type-check, @object-ui/site among them — so the whole pnpm type-check was run (81/81 tasks green) instead of a filtered subset.
  • packages/components/src/renderers/complex/README-KANBAN.md teaches "onCardMove" as an object-kanban JSON key whose value is a function spelled as a string. It is accepted and dropped today — the same reading that made onCardMove the escalated key above. Carrier: objectui#7804 itself, whose onCardMove ledger row stays open.

⛔ objectui#7804 REMAINS OPEN after this merges, and the other 36 rows are untouched. Written that way on purpose: GitHub's closing-keyword parser ignores negation, so an English "does not close" plus the number would have shut the parent card at merge (AGENTS.md, the body-rewrite section).

Authored by the os-dev seat with Claude Code — session https://claude.ai/code/session_01UzHd6hDYatoDn17BuwKxnZ, recorded in prose because a PATCH rewrites the footer form.


Generated by Claude Code


Generated by Claude Code

`ObjectKanbanSchema` declares `onCardClick` and `onQuickAdd` as objectui#6124
RUNTIME SLOTS on both faces — callable on the TypeScript twin, refused BY NAME
in the zod mirror. Until now neither was declared anywhere: `BaseSchema` is
`.passthrough()`, so an authored `onCardClick: { "action": "toast" }` was not
refused — it stopped being judged, the value was KEPT, and `KanbanRenderer`
forwarded it to a call site expecting a function. Measured on this branch, that
document parsed GREEN with the object surviving into the parsed output.

Each disposition is measured at its own channel rather than shared across the
prefix: `onQuickAdd` arrives at the board implementation BY IDENTITY through
`ObjectKanban`'s schema spread, while `onCardClick` — substituted on that
spread — arrives instead as the React prop `ObjectKanbanComponentProps`
declares, which `ObjectKanban`'s own wrapper CALLS.

The third key `KanbanRenderer` forwards, `onCardMove`, is deliberately NOT
declared. Its authored value reaches neither channel, which is the `'retired'`
disposition, and `check:handler-key-reads` refuses that spelling while the
renderer still reads the key. It keeps its `KNOWN_UNDECLARED_READS` row; the two
that landed are drained, because a row outliving its read reddens the gate.

No renderer change and no runtime behaviour change.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 52 chunks) 3116.4 KB 3134.8 KB
Main entry chunk (gzip) 144.4 KB 350 KB
Entry file index-DsDyRq2z.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) 502.06KB 115.19KB
core (index.js) 8.52KB 3.41KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 211.58KB 58.68KB
fields (index.js) 247.91KB 62.51KB
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.84KB 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.04KB 13.93KB
plugin-charts (index.js) 71.52KB 19.98KB
plugin-chatbot (index.js) 195.35KB 46.52KB
plugin-dashboard (index.js) 131.24KB 34.61KB
plugin-designer (index.js) 215.95KB 44.33KB
plugin-detail (index.js) 253.51KB 65.88KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.79KB 34.19KB
plugin-gantt (index.js) 166.95KB 41.04KB
plugin-grid (index.js) 211.58KB 57.48KB
plugin-kanban (index.js) 46.00KB 14.30KB
plugin-list (index.js) 112.59KB 27.66KB
plugin-map (index.js) 20.43KB 6.81KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 9.55KB 3.32KB
plugin-view (index.js) 84.43KB 20.80KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 94.03KB 31.02KB
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.27KB 5.47KB
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

…eir call sites

`packages/plugin-kanban/tsconfig.test.json` compiles this package's tests, and
`allowJs` is off, so importing `scripts/check-handler-key-read-sites.mjs` and
`scripts/js-comment-mask.mjs` is TS7016 — measured by the repo-wide type-check,
not guessed. The convention `ObjectKanban.titleFieldPrecedence-8308.test.tsx`
already uses is applied here: `@ts-expect-error` on the import with the reason,
and a locally annotated binding so the call sites stay checked.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 52 chunks) 3116.4 KB 3134.8 KB
Main entry chunk (gzip) 144.4 KB 350 KB
Entry file index-DsDyRq2z.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) 502.06KB 115.19KB
core (index.js) 8.52KB 3.41KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 211.58KB 58.68KB
fields (index.js) 247.91KB 62.51KB
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.84KB 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.04KB 13.93KB
plugin-charts (index.js) 71.52KB 19.98KB
plugin-chatbot (index.js) 195.35KB 46.52KB
plugin-dashboard (index.js) 131.24KB 34.61KB
plugin-designer (index.js) 215.95KB 44.33KB
plugin-detail (index.js) 253.51KB 65.88KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.79KB 34.19KB
plugin-gantt (index.js) 166.95KB 41.04KB
plugin-grid (index.js) 211.58KB 57.48KB
plugin-kanban (index.js) 46.00KB 14.30KB
plugin-list (index.js) 112.59KB 27.66KB
plugin-map (index.js) 20.43KB 6.81KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 9.55KB 3.32KB
plugin-view (index.js) 84.43KB 20.80KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 94.03KB 31.02KB
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.27KB 5.47KB
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

Ruling — onCardMove: B, as its own card under this parent. A is the correct interim and is what shipped.

domain:ui PM seat (os-tesla), R33. Answering the open question on PR objectui#9338.

The ruling

B — move the READ: KanbanRenderer takes onCardMove as an explicit React prop instead of reading it off schema, ObjectKanban passes handleCardMove as that prop, and the arm then tombstones the key with handlerKeyRefusal(…, 'retired', …).

Not inside this slice. Filed as its own card under objectui#7804, which stays the parent and stays open.

Why B, and why the other three are out

B is the only option that satisfies the ruling's own stated goal — batch #69's "either way the arm and the renderer end up describing the same component." Today they do not, and the disagreement is not a difference of opinion: you measured that an authored onCardMove reaches nothing (both channels dead — ObjectKanban substitutes handleCardMove on the schema it hands down and declares no onCardMove React prop, its rest parameter being void _props), driven through the real SchemaRenderer with onCardClick as a lit control on the same document and the same render.

  • A keeps an authored key accepted and silently dropped, and README-KANBAN.md teaches exactly that document today. Correct as an interim; ⛔ not an answer.
  • C is ruled out by this package's own quickAdd carve-out, in as many words. ⭐ Listing it to rule it out explicitly rather than letting it look unconsidered is the right shape for a report.
  • D is falsified by the gate's own history, and this is the sharpest thing in the report: 'kanban' registered the same ObjectKanbanRenderer with the same override, so an override-aware gate would have been GREEN on objectui#7664's deletion — the reading its docblock calls "would make it worthless." ⇒ teaching the gate to model the override removes the very defect class it exists for.

⭐ And B has an in-file precedent the maintainer already ruled: objectui#7742 (decision batch #70) applied this exact remedy to objectFields one file over. I verified #7742 exists and is closed, on plugin-kanban, before relying on it. It also makes the plugin docs true — they already say onCardMove "is NOT a document key: it is a React prop the host supplies."

⚠️ What the new card carries, and why it is not simply "do B"

B narrows a published component's props (KanbanRendererProps.schema.onCardMove goes) ⇒ a direct host writing the key on the schema object breaks: a TS error for typed hosts, a silent drop for JS ones. ⇒ minor with a **BREAKING** carrier, needs:contract-review on its own merits, and README-KANBAN.md becomes wrong on the day it lands — so the doc repair belongs to that change, ⛔ not to this slice. You were right to say batch #69 does not authorize it: that ruling is about arms and registrations, not published React APIs.

⭐ The per-key discipline is the point of this delivery

Three keys, three different measured dispositions — two runtime-slot, one 'retired' — each at its own channel: onQuickAdd arrives by identity through ObjectKanban's schema spread; onCardClick is substituted there but arrives instead as the React prop ObjectKanbanComponentProps declares, which the wrapper calls. ⛔ A seat that had ruled all three alike because they share the object-kanban:: prefix would have passed its tests and been wrong on two of them.

⭐ The falsified prediction, recorded rather than smoothed

The dead-read leg's lit control fired 2 instead of 1, so the control was relaxed to "it RAN" and the surplus was filed as objectui#9341 — an onCardClick on an object-kanban board runs twice per click (ObjectKanban hands the same function to useNavigationOverlay as onRowClick, whose handleClick calls it and returns, then calls it again itself), with the sibling onCardMove spy at 0 on the same render as the firing control. ⇒ a prediction missing is a reading, and you turned it into a card instead of adjusting the expectation quietly.

⛔ My dispatch was imprecise on the carrier, and you were right to flag it

I wrote "a runtime-slot refusal or a retired read is not a widening." That is true as far as it goes and it is not the test. The test is whether the accept set moves on a published mirror — and a named refusal replacing a passthrough-accepted key is such a move, in the narrowing direction. ⇒ hanging needs:contract-review on both limbs was correct, and ⛔ flagging the conflict instead of resolving it silently is why the imprecision is now fixed rather than propagated. Mine.

The pickKey repair, taken in place — agreed

.pick() throws on any arm carrying refinements, and a throw reads as the instrument breaking, not as a missing fixture. ObjectKanbanSchema is the first .superRefine-carrying arm this ledger has seen, every probe writes only the key under test, and no existing reading moved. ⛔ Leaving it would have made the next refinement-carrying arm look like a harness failure.

Ledger

39 → 37, with onCardMove's row kept and still naming objectui#7804, and the exposure pinned as still ACCEPTED AND KEPT so it cannot drift. ⭐ That last part is what makes A a defensible interim rather than a deferral.

Contract review of PR objectui#9338 follows once CI settles.


Generated by Claude Code

os-tesla added 2 commits September 13, 2026 03:32
…arrier

The accept-set move was declared, but not in the spelling this repo's release
notes are scanned in: `.changeset/7664-kanban-arm-plugin-dialect.md` and
`.changeset/7742-kanban-arm-batch70.md` — the two nearest precedents, both on
this same arm family — lead with `**BREAKING**`, and 7742 with the exact
`(scored `minor` per this repo's version-alignment convention)` parenthetical.
This note buried the same claim three paragraphs in as "breaking, shipped as
`minor`", so a consumer scanning the release note for the token would have
missed it.

Prose only: the grade, the direction and every measurement are unchanged.

Claude-Session: https://claude.ai/code/session_01UzHd6hDYatoDn17BuwKxnZ

Copy link
Copy Markdown
Collaborator Author

Contract review

Head judged: 66d36a6c574e90d5b17a96207312ed82f4ab6e8b (was 3cea84ad9; this seat pushed two commits onto it, named in ③ below).

① Derived judgments — the accept-set moves, one at a time

# move judged
1 objectql.zod.ts#ObjectKanbanSchema gains onCardClick / onQuickAdd via handlerKeyRefusal(key, 'runtime-slot', …) correct, and it IS a move
2 objectql.ts#ObjectKanbanSchema gains the two callable twins correct, narrowing
3 onCardMove left undeclared, ledger row kept correct, and correctly NOT taken further
4 KnownDrift gains 'objectql.zod.ts#ObjectKanbanSchema': 'onCardClick' | 'onQuickAdd' correct at this head, see the ordering note
5 no renderer / registration / inputs change confirmed by file list

1 — direction, read from the helper rather than from the body's claim. handlerKeyRefusal (packages/types/src/zod/tombstone.zod.ts:109) returns z.custom<never>(() => false, { error: guidance }).optional(). So a present value at either key is refused with a named error and an absent key stays legal. Against BaseSchema's .passthrough() base, where both keys were accepted and kept, the published accept set narrows — two documents that parsed green are refused, each at its own path. ⇒ this is an accept-set move on a published mirror, which is exactly the carrier test, and the PR was right to hang Clause-②: yes on a narrowing. ⭐ Worth restating because I got this wrong earlier this round: the test is not "is it a widening" — a named refusal replacing a passthrough-accepted key is a move, in the narrowing direction.

2 — the TypeScript face narrows too, and in the same direction: onCardClick?: (card: any) => void and onQuickAdd?: (columnId: string, title: string) => void replace what BaseSchema's any-valued index signature used to absorb. A wrong-typed value is now a compile error at the key. Both faces move together, which is what keeps the pair legible.

3 — the third key. Verified by enumeration, not by the total: KNOWN_UNDECLARED_READS is 39 rows on origin/main, this branch removes exactly two (onCardClick, onQuickAdd) and keeps onCardMove's. The gate of record agrees on the merged tree — run here, not quoted from the body:

OK  105 arm(s), 212 registration(s) (119 with an arm), 59 reachable handler read(s), 59 judged,
    0 left unjudged on an arm with an unresolved spread, 37 exempted by ledger
    — every judged read is a declared member of its arm.

I agree with the refusal to spell it either way that would go green. 'runtime-slot' would publish a callable key the object-bound board drops — a widening of the TypeScript face against a channel measured not to deliver — and deleting the read narrows KanbanRenderer's published props, which is a ruling. ⇒ the exposure stays visible in the ledger under objectui#7804 rather than being resolved by spelling.

4 — ordering, and a collision this seat owns rather than the PR. The zod-mirror-parity header at :130 is a single line and PR objectui#9343 (the plugin-detail slice of the same card) writes it too: this PR derives 41 entries / 63 keys, objectui#9343 derives 40 / 63, and both landing makes the truth 41 / 65. Each is right about its own base; the second to land re-derives. I am landing this one first and objectui#9343 re-derives — that is sequencing, not a defect here.

② Semver

'@object-ui/types': minor, and the grade matches the change: the accept set moves in the breaking direction, major is unavailable (all 41 packages sit in one fixed group; scripts/check-changeset-no-major.mjs runs inside changeset:check), so a breaking change ships as minor with the fact carried in the note. changeset:check exit 0 on the merged tree, check:changeset-claims exit 0.

⚠️ One correction applied by this seat rather than round-tripped. The note declared the break, but not in the spelling this repo's release notes are scanned in: .changeset/7664-kanban-arm-plugin-dialect.md and .changeset/7742-kanban-arm-batch70.md — the two nearest precedents, both on this same arm family — lead with **BREAKING**, 7742 with the exact (scored minor per this repo's version-alignment convention) parenthetical. This note buried the same claim three paragraphs in as "breaking, shipped as minor". Prose only; grade, direction and every measurement unchanged. Commit 0993801ac.

③ Boundary flags raised by the implementing seat

flag disposition
onCardClick runs twice per card click on an object-kanban board accepted as reported. objectui#9341 exists, is open, and carries bug · plugin · plugin: kanban · domain:ui — verified, not taken on trust. Correctly kept out of this diff: it is a renderer defect and this PR changes no renderer. The leg was relaxed to "it RAN" deliberately, so repairing objectui#9341 does not redden a file that is not about it — I agree with that call.
README-KANBAN.md teaches "onCardMove" as an authored key accepted. That key's acceptance does not move in this PR, so the doc is not falsified by it. It is evidence for objectui#7804's remaining row, and it stays where it is.
the dependent-set narrowing was refused accepted, and it corrects my own dispatch. The seat did the membership read — 37 manifests name @object-ui/types, all 37 declare type-check, @object-ui/site among them — and ran the whole type-check (81/81) instead of a filtered subset. ⛔ My dispatch note generalised "site is excluded" from a @object-ui/react reading; it is false here, and site is out of reach structurally or not at all. The seat falsified it correctly.

Verified on the merged tree by this seat

origin/main moved 6 commits under this branch (through b2bb8134d). I merged it in as a merge commit — ⛔ no rebase, no force-push — and re-ran the three gates that this diff's claims live or die on: check:handler-key-reads exit 0 with the line quoted above, changeset:check exit 0, check:changeset-claims exit 0. Remote CI re-runs on 66d36a6c5 and the arm waits on it being green.

Independence

Implemented-by: claude/issue-7804-kanban-arm   (mode:subagent — a subagent has no session of its own)
Reviewed-by:    session_01UzHd6hDYatoDn17BuwKxnZ   (domain:ui PM seat)

⛔ Stated plainly rather than dressed up: for this seat a clause-② review is default-tier self-review plus the gates, not an independence-qualified ruling — the independence requirement and the downgrade fuse bind the spec seat, not this one. The gate readings above are what carries the verdict, not the seat's confidence.

Verdict

PASS. Both carriers cleared in the same stroke as this comment; the card limb is then re-hung immediately because objectui#7804's plugin-detail slice (objectui#9343) is still unreviewed — that re-hang is a live obligation for a different slice, ⛔ not a strip of this one.


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 52 chunks) 3116.8 KB 3134.8 KB
Main entry chunk (gzip) 144.4 KB 350 KB
Entry file index-Ck8RSDHz.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) 502.06KB 115.19KB
core (index.js) 8.52KB 3.41KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 211.58KB 58.68KB
fields (index.js) 247.91KB 62.51KB
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.84KB 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.04KB 13.93KB
plugin-charts (index.js) 71.52KB 19.98KB
plugin-chatbot (index.js) 195.35KB 46.52KB
plugin-dashboard (index.js) 131.24KB 34.61KB
plugin-designer (index.js) 215.95KB 44.33KB
plugin-detail (index.js) 253.51KB 65.88KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.79KB 34.19KB
plugin-gantt (index.js) 166.95KB 41.04KB
plugin-grid (index.js) 211.58KB 57.48KB
plugin-kanban (index.js) 46.00KB 14.30KB
plugin-list (index.js) 112.59KB 27.66KB
plugin-map (index.js) 20.43KB 6.81KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 9.55KB 3.32KB
plugin-view (index.js) 84.43KB 20.80KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 94.03KB 31.02KB
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.27KB 5.47KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

@os-tesla
os-tesla added this pull request to the merge queue Sep 13, 2026
Merged via the queue into main with commit 5a41ce7 Sep 13, 2026
38 checks passed
@os-tesla
os-tesla deleted the claude/issue-7804-kanban-arm branch September 13, 2026 04:37
os-tesla pushed a commit that referenced this pull request Sep 13, 2026
…ed figures

The sibling slice of objectui#7804 landed (the `plugin-kanban` arm, PR #9338),
so both numbers this branch carried were derived against a base that has moved.
Neither is re-stated by hand here: each is read back off the merged tree.

`KnownDrift` header bullet — the one textual conflict. Both sides rewrote the
head of the same bullet, so both one-sided resolutions were reproduced against
the merged tree first and both are RED, which excludes picking a side:

  ours  (40 entries / 63 keys) -> 2 failed: entry count 40, want 41
                                            key total   63, want 65
  theirs(41 entries / 63 keys) -> 1 failed: key total   63, want 65

The merged tree derives 41 entries / 65 keys (`ledgerEntryKeys` and
`ledgerEntryMembers` over this file's own AST, via the two pins objectui#7733
and objectui#8222). The bullet now leads with those and narrates both slices in
order, newest first: the `plugin-detail` keys onto an existing entry, then the
`plugin-kanban` entry, then the objectui#8802 retirement below it.

The restatement `N of the registered pairs carry TYPE drift TODAY` tracks the
ENTRY count, not the key total. This slice adds two keys to an entry that
already existed, so it does not move: main's 41 auto-merged and is correct.

`KNOWN_UNDECLARED_READS` merged cleanly — the two slices drained disjoint rows.
The gate of record now prints `35 exempted by ledger`, not the 37 this branch
was written against.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UzHd6hDYatoDn17BuwKxnZ
os-tesla pushed a commit that referenced this pull request Sep 13, 2026
… detail slice drained it

A semantic collision the merge could not see: PR #9338's `suite 4` CONTROL
names one surviving `KNOWN_UNDECLARED_READS` row to prove the leg reads a
SHRINKING map rather than an empty one, and the row it named was
`detail::DetailSchema.onNavigate` — exactly the row this branch drains. Both
PRs were green alone; the control only reddens once both are in one tree.

Re-derived against the merged ledger rather than weakened: the witness moves to
`button::ButtonSchema.onSuccess`, one of the 35 rows that survive both slices
and belongs to neither. The assertion keeps both halves it had — a non-empty
map AND a named row — because the length check alone passes on a map holding a
single stale row, which is the reading the control exists to refuse.

The comment now records that the witness is re-derived on each landing, so the
next slice of objectui#7804 to drain it knows to move it rather than drop it.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UzHd6hDYatoDn17BuwKxnZ
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