Skip to content

feat(types): declare navigation on the object-kanban and object-calendar arms, by reference to the spec (objectui#8652) - #11292

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-8652-kanban-navigation-family
Oct 1, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-8652-kanban-navigation-family

Conversation

@objectstack-fleet

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

Copy link
Copy Markdown
Contributor

Fixes #8652
Clause-②: yes

navigation is now declared on the object-kanban and object-calendar blocks, by reference to the spec. This is the objectui half of the maintainer ruling on objectui#8652 (verbatim 「B」): declare navigation on the platform element schema first, then mirror it here. The platform half shipped in @objectstack/spec 17.5.0, the release this repo resolves: ComponentPropsMap['object-kanban'] and ComponentPropsMap['object-calendar'] both declare navigation: NavigationConfigSchema.optional().

Dispatched by the domain:spec @ objectui seat, session https://claude.ai/code/session_01VhxTqosz7wn54ahqyxgERT.

Premises, re-measured on origin/main e420df31 before the first edit

  • H1, partly falsified. On the installed 17.5.0, navigation is declared on ObjectKanbanPropsSchema and ObjectCalendarPropsSchema: a valid block parses, a bogus key beside it is refused with unrecognized_keys, and mode: 'not-a-mode' is refused at navigation.mode. ⚠️ ObjectTimelinePropsSchema ALSO declares it, as NavigationConfigSchema.optional(), with the same three verdicts. The dispatch read zero navigation lines in the timeline schema. The timeline is untouched here, as ordered: it belongs to objectui#8654, which remains open.
  • H2, confirmed with the TypeScript checker (getPropertyOfType, not a grep). ObjectKanbanSchema.navigation and ObjectCalendarSchema.navigation were not declared, and both interfaces carry a string index signature typed any. Lit control: ObjectGanttSchema.navigation and ObjectGridSchema.navigation read DECLARED on the same instrument. A nonsense key reads not declared. The zod arms carried no navigation member either.
  • H3, partly stale. Both renderers read the key. ObjectKanban reads schema.navigation with no cast, which compiled only through the index signature. ObjectCalendar read it through (schema as any). KanbanSchema no longer declares it: that arm retired with the bare kanban key (objectui#8802), so ObjectKanbanSchema is the only kanban face.
  • H4, confirmed, and it owes more than two lines. The parity gate booked object-kanban.navigation and object-calendar.navigation as OWED to this card. Publishing an object-armed input also carries the objectui#8212 obligation, a member pin apiece. See "What changed".

What changed

  • @object-ui/types:
    • ObjectKanbanSchema.navigation and ObjectCalendarSchema.navigation are declared on both faces: ViewNavigationConfig on the TS face, and stripImportedDefaults(SpecNavigationConfigSchema).optional() on the zod face. These are the spellings the gantt, map and gallery arms already use, taken by reference and not restated.
    • The import-boundary strip keeps the spec's mode: 'page' default out of a parsed document, so an absent key still reaches the renderer's own { mode: 'drawer' } fallback.
  • @object-ui/plugin-calendar: the (schema as any).navigation cast that objectui#8651 left for this card is gone. OBJECT_CALENDAR_INPUTS, shared by the object-calendar and calendar tags, publishes navigation.
  • @object-ui/plugin-kanban: OBJECT_KANBAN_INPUTS publishes navigation. The read-site comment is rewritten, because it named a designer-face declaration that did not exist.
  • registry-inputs-spec-parity.test.ts:
    • The two booked entries are struck, and the unpublishedKeys cap goes from 5 to 3.
    • The objectui#8176 backlog ceiling goes from 2 to 0, in all three assertions. The per-owner total for objectui#8652 goes from 2 to 0.
    • Two MEMBER_PINS entries are added, one per block.
    • The objectui#11168 entries are untouched. It is the last owner card, so it restores the empty ledgers.
  • calendarUnionReads-8651.test.tsx: its one ledger entry was navigation, the key it deferred to this card. That entry is struck. The row that pinned the key UNDECLARED is inverted, not deleted: it now asserts the key is read AND declared.

Pins

  • object-kanban-calendar-navigation-8652.test.ts covers both arms against the installed spec, which it reads in the same run:
    • a valid block parses, and so does every mode;
    • a bad mode is refused at navigation.mode, and a bogus member inside the block is refused;
    • the retired view member is refused;
    • a CONTROL: the same bad block under an undeclared key is still accepted;
    • a parse writes no default;
    • safeValidateSchema agrees with the rows above;
    • on the TS face, an Equal assertion plus @ts-expect-error rows. The zod-mirror-parity ratchet cannot see a TS member that goes missing (objectui#9711), so these rows defend it.
  • kanbanNavigationMembers-8652.test.tsx and calendarNavigationMembers-8652.test.tsx are the member pins. Each drives every member through a real click on the real renderer:
    • an absent key opens a drawer;
    • none and preventNavigation open nothing;
    • new_window and openNewTab open the record page in a new tab;
    • for size and width, the deprecated width wins, a bucket resolves through the size table, and auto gives the default width;
    • precedence against a parent view. The board: a parent's click handler outranks the whole key. The calendar: an overlay mode keeps the click, and any other mode hands it to the parent.

Verification, all on 0c50a196c (the head of this PR)

  • pnpm exec vitest run packages/types/ plus the four pin files and registry-inputs-spec-parity.test.ts: Test Files 303 passed (303), Tests 7760 passed (7760).
  • The dependency closures were built first (pnpm --filter '@object-ui/plugin-kanban^...' --filter '@object-ui/plugin-calendar^...' run build). The rebuilt dist/objectql.d.ts carries one navigation member inside each of the two interface blocks. type-check for @object-ui/types, @object-ui/plugin-kanban and @object-ui/plugin-calendar then ran, with each script name echoed: all Done. --listFilesOnly confirms that each tsconfig.test.json includes the new pin files.
  • pnpm exec vitest run packages/plugin-kanban/ packages/plugin-calendar/: Test Files 123 passed (123), Tests 838 passed | 95 skipped. None of the skips is in a file this change adds or edits.
  • The console closure was built, and @object-ui/console type-check is green. The neighbouring suites that read these two blocks passed: 49 files, 734 tests. They cover console public-contract and public-block-binding-reach, the app-shell block-config previews and PageBlockInspector.retiredBlockProps, sdui-parser, the core registry, and the prompt-keys and handler-key-read-sites script tests.
  • The following gates exit 0:
    • check:designer-field-key-parity, check:component-surface-parity, check:prompt-keys, check:doc-types, check:installed-pin-claims;
    • check:new-line-citations, check:control-bytes, check:changeset-claims (report-only; re-read below), check:pending-changeset-literals, check:handler-key-reads;
    • check:spec-symbols, check:test-path-roots, the three check:vi-mock-*, check:element-data-source-declaration, check:registry-bare-names;
    • check:doc-snippets, check:doc-examples, check:readme-exports, check:sdui-registration-pins and check:eager-closure, each run once its build prerequisite was met;
    • check:comment-mask-corpus, check:unreferenced-sources, type-check:coverage, lint:coverage, and changeset presence, no-major, fixed and overwrite.
  • Lint, as a declared narrowing. eslint --no-inline-config --format json over the 11 changed TS files reports 11 files and 0 errors. The root config enables no type-aware linting (no parserOptions / projectService), and no rule under eslint-rules/ reads another file. So this diff cannot move a verdict on an untouched file. The repo-wide pnpm lint is left to CI.

Ablations, each committed first and restored to HEAD through ablation-replace.mjs

Each ablation was proven landed by anchor count and blob change. Each restore was proven by blob equals HEAD and an empty git diff HEAD, and the tree was clean afterwards.

  • TS member removed from ObjectKanbanSchema: tsc -p tsconfig.test.json exits 2, with TS2344 on the Equal assertion and TS2578 (unused @ts-expect-error) on the bad-mode row. The first attempt was a no-op: the tool refused it because the replacement was a prefix of the anchor. It was re-anchored and re-run.
  • Zod member removed from the kanban arm: 5 failed and 15 passed. The five are the shape, bad mode, bogus member, retired view and safeValidateSchema rows.
  • Renderer read ignores the authored key (kanban): 8 failed and 4 passed. The absent-key control, the no-flag drawer control, size: 'auto' and the parent-handler row stay green, as predicted.
  • Renderer read ignores the authored key (calendar): 9 failed and 4 passed, the same shape.

Acceptance notes

  • ⚠️ page opens nothing on a standalone board or calendar. A block without mode resolves to page, the spec's default. Neither renderer hands useNavigationOverlay an onNavigate, so page has no channel unless a parent view supplies onRowClick. This is measured by mounting the real components, and it is reported as a finding. It is NOT changed here. The published input descriptions state it, and two rows per member pin hold the description to it. A renderer that learns to navigate on page reddens those rows, which is the signal to rewrite the description.
  • openNewTab: true outranks an overlay mode as well as page: { mode: 'drawer', openNewTab: true } opens a tab and no drawer. The spec describes the flag as "applies to page mode". This is shared hook behaviour, the grid's included. It is observed here and not pinned. Carrier: none.
  • ObjectTree.tsx has a comment saying navigation is declared on one ComponentPropsMap entry only (object-grid), and that object-tree has no entry. That is stale since 17.5.0, which gives object-tree an entry declaring navigation: z.unknown().optional(). The tree is outside this claim. Carrier: none.
  • AGENTS.md Add automated testing infrastructure and CI/CD workflows #2 (docs-driven): the docs and READMEs do not document navigation. Superseded by round 2 (161a5c5b4). The seat adopted the at-tier record's ③-3 escalation, and the docs now carry the key (see the round-2 section below). The registry descriptions carry the authoring guidance.
  • .changeset/7322-object-kanban-component-props.md gets an append-only dated note, because its 「navigation is declared on neither face」 goes false here. Its frontmatter is byte-identical. check-changeset-overwrite reports the modification, which is its legitimate-correction case. check:changeset-claims named 41 pending changesets that reference touched files. Of those, only 5903 and 7917 mention navigation, and neither makes a claim this change falsifies.
  • Overlap: objectui#10859 batch 4 holds the ObjectFormSchema region of the same two @object-ui/types files. The regions are disjoint, so whichever PR lands second merges main.

Generated by Claude Code

Patch round 2 (written by the seat)

  • Round 2 (161a5c5b4, AGENTS.md Add automated testing infrastructure and CI/CD workflows #2): navigation is documented on both blocks in packages/plugin-kanban/README.md, packages/plugin-calendar/README.md, content/docs/plugins/plugin-kanban.mdx, content/docs/plugins/plugin-calendar.mdx and the ObjectKanbanSchema table of content/docs/api/schema-reference.md. Each states the spec's NavigationConfig by reference (ViewNavigationConfig), the mode list, the absent-key drawer and the parent-view precedence, plus one sentence on the page caveat pointing at objectui#11293. The schema-reference sentence that called cardTitle and navigation undeclared on this face is corrected (cardTitle since objectui#9606). The doc gates exit 0 on 161a5c5b4: doc-version-claims, doc-types, doc-fences, doc-example-ids, doc-example-readers, readme-exports, doc-snippets, doc-examples, new-line-citations and control-bytes.

…endar arms, by reference to the spec (objectui#8652)

The objectui half of the maintainer ruling on objectui#8652 (verbatim "B"):
`@objectstack/spec` 17.5.0 declares `navigation: NavigationConfigSchema` on
the `object-kanban` and `object-calendar` element entries, and this repo now
mirrors it.

- `@object-ui/types`: `ObjectKanbanSchema.navigation` and
  `ObjectCalendarSchema.navigation` are declared on both faces - the TS face as
  `ViewNavigationConfig`, the zod face as
  `stripImportedDefaults(SpecNavigationConfigSchema).optional()`, the spelling
  the gantt / map / gallery arms use. A bad `mode` is now refused at
  `navigation.mode` and a bogus member inside the block is refused.
- `plugin-calendar`: the `(schema as any).navigation` cast objectui#8651 left
  for this card is gone.
- Both registrations publish `navigation` in `inputs`, each with a member pin
  driving every member through a real click; the two entries the 17.5.0 bump
  booked to this card are struck from the parity ledger.

Claude-Session: https://claude.ai/code/session_01VhxTqosz7wn54ahqyxgERT
Co-authored-by: Claude <noreply@anthropic.com>
…ban entry it falsifies

- `.changeset/8652-kanban-calendar-navigation.md`: `@object-ui/types`,
  `@object-ui/plugin-kanban` and `@object-ui/plugin-calendar`, `minor` (a
  widening of a published face, by reference to the spec).
- `.changeset/7322-object-kanban-component-props.md`: an append-only dated note.
  Its 「`navigation` is declared on neither face」 was true when written and is
  falsified by this change; the frontmatter is byte-identical.
- The types pin reads the spec entry through a narrow parse-result type rather
  than `any`.

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

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

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

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

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

.changeset/10872-container-children-channel.md

  • names objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Also in this change, with no behaviour change: objectql.zod.ts's two public-block arms (object-metric, object-master-detail-form) build their properties member with the same propsBag helper as the other public-block arms, instead of a byte copy of it. The member's description text is unchanged.

.changeset/11068-grid-declared-keys.md

  • names schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    What was wrong. ObjectGridSchema declared eight keys the grid never read. An author who wrote description, emptyState, name, placeholder, rowSpecActions or bulkSpecActions on an object-grid got no type error, no validator refusal and no effect. The reference example in schema-reference.md taught description and showFilters as if they worked. It now authors only keys the grid reads.

.changeset/3917-retire-action-condition-branch.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    • ActionCondition is removed from @object-ui/types (and from the barrel export). - ActionSchema.condition is retyped to the predicate the runtime actually honours: boolean | string | { dialect?: string; source: string } — the same three arms ActionRunner's own ActionDef.condition carries, and the same vocabulary visible and disabled use. - ActionConditionSchema is removed from @object-ui/types/zod (and from the zod barrel); the condition key now validates against that predicate union. - The two teaching sites (content/docs/core/enhanced-actions.mdx Conditional Execution, content/docs/api/schema-reference.md ActionSchema table) are rewritten to the live vocabulary: condition is a gate; a branch is expressed as separate actions with mutually exclusive conditions.

.changeset/5903-objectgantt-declared-keys.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    Both halves move together. The TS declaration (packages/types/src/objectql.ts) and its zod mirror (src/zod/objectql.zod.ts) gain the same ten keys at the same requiredness — all optional — and no KnownDrift entry is added. navigation is taken from @objectstack/spec's NavigationConfigSchema by reference rather than restated, matching ObjectGridSchema.navigation.

  • names src/zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Both halves move together. The TS declaration (packages/types/src/objectql.ts) and its zod mirror (src/zod/objectql.zod.ts) gain the same ten keys at the same requiredness — all optional — and no KnownDrift entry is added. navigation is taken from @objectstack/spec's NavigationConfigSchema by reference rather than restated, matching ObjectGridSchema.navigation.

.changeset/6152-object-form-unmirrored-members.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectFormSchema in @object-ui/types (objectql.ts) declared a set of members that its zod mirror in @object-ui/types/zod had never heard of. Every one of them is read by the object-form renderer (ObjectForm in @object-ui/plugin-form). The two published faces answered differently:

.changeset/6170-retire-timeline-dead-keys.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    Also in this change: the in-repo example packages/types/examples/data-display-examples.json (its timeline node authored all three) is migrated to items / variant; the two content/docs/api/schema-reference.md snippets that authored events: [] now author items: []; and the plugin-timeline docs callout says retired rather than deprecated.

.changeset/6896-retire-chart-inline-data.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    ⚠️ One correction to the record the ruling rests on. The ruling states zero authorship of a populated series[].data outside tests across packages/ / apps/ / examples/. The re-measurement finds one such site inside those roots — packages/types/examples/data-display-examples.json (2 series) — plus four outside them, in documentation: content/docs/api/schema-reference.md (3) and content/docs/core/report-schema.mdx (1).

.changeset/6939-kanban-column-cards.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    Breaking, deliberately. KanbanColumn declared its card list as items in complex.ts and in the zod mirror complex.zod.ts. Every board reads cards. Measured on origin/main 78a3cc238: KanbanImpl.tsx reads .cards on 12 lines, KanbanEnhanced.tsx on 8, and bucketCardsIntoColumns twice more as col.cards || []; .items had zero read sites in either board (a same-shaped .title control on the same two files returns 8 and 3, so those zeros are readings and not a mis-shaped probe). Both catalog entries, the plugin docs and content/docs/api/schema-reference.md all author cards.

.changeset/6940-rowactions-boolean-mirror.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    The list view's same-named rowActions in zod/objectql.zod.ts — z.array(z.string()), the legacy bare-name action list on ObjectGridSchema — is a different key that is correct as it stands, is in parity with its own TS twin (rowActions?: string[]), and is not touched.

.changeset/6951-tree-view-data-retired.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    What was measured, on this branch's base. TreeViewSchema declared two spellings for its one inline-nodes slot — nodes (read second) and data (read third: boundData || schema.nodes || schema.data || [] at renderers/data-display/tree-view.tsx:105), both declared by objectui#6150. data had been REQUIRED until 777e5c6f4 (PR fix(types): tree-view mirror stops requiring the limb it reads third (group 2 of objectui#6939) #7533) made it optional, so this retirement starts from a declared-and-optional member on both faces. The in-repo corpus at the retirement: seven tree-view nodes under examples/schema-catalog and packages/types/examples plus one content/docs fence — six on nodes, two on data (packages/types/examples/data-display-examples.json and content/docs/api/schema-reference.md), both rewritten; no package source authored either spelling.

.changeset/7113-chart-data-model.md

  • names objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    .extend() with a NEW key still works and preserves the fold and the refinement; .optional(), z.discriminatedUnion, z.toJSONSchema and safeValidateSchema are all unaffected. Nothing in this repository calls the throwing combinators on either const, and the published surface already ships refined mirrors (objectql.zod.ts, complex.zod.ts, form.zod.ts, app.zod.ts), so the class is not new — but it is a real behaviour change on a published export and it belongs in the release note rather than in a reviewer's file.

.changeset/7200-object-form-section-style-keys-undeclared.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    The authored-metadata type now agrees with @objectstack/spec, whose FormSectionSchema is a strict object declaring neither key, and with the ruling's rationale (maintainer 2026-09-01, verbatim): "retire the reads … Declaring the keys was weighed and not adopted: it would formally invite free Tailwind strings into authored metadata, the exact class the boundary exists to keep out." A ?: never tombstone was not used: ObjectFormSection has no zod mirror (ObjectFormSchema in zod/objectql.zod.ts does not declare sections), so there is no parse door to refuse at, and a tombstone is still a declaration in completion and in the published .d.ts.

.changeset/7265-types-user-filter-field-derives.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    zod/objectql.zod.ts declared two schemas under names @objectstack/spec/ui already exports. They were triaged separately, by reading their sites, and went different ways.

.changeset/7313-object-calendar-record-source.md

  • names plugin-calendar/src/ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    ObjectCalendar resolves its records through the shared ladder (resolveRecordSourceConfig in @object-ui/core, called from plugin-calendar/src/ObjectCalendar.tsx): data first, then staticData, then objectName. The published TypeScript interface REQUIRED objectName and declared neither data nor staticData; the published Zod mirror did the same. So an object-calendar node authored on staticData — the route the plugin page documents twice — rendered correctly and was refused by safeValidateSchema, and could not be annotated with its own type (TS2741: Property 'objectName' is missing).

  • names content/docs/plugins/plugin-calendar.mdx → content/docs/plugins/plugin-calendar.mdx — edited by this change

    A widening. A node authoring staticData or data without objectName now validates (it always rendered — the read is resolveRecordSourceConfig(schema), keyed on the three). Every document that validated before still validates: objectName alone still parses, an empty one included, because presence is !== undefined. The one shape the refinement refuses (none of the three) was refused before too, at objectName. The two static-data examples in content/docs/plugins/plugin-calendar.mdx are now annotated ObjectCalendarSchema and compile under the doc-snippet gate.

.changeset/7322-object-kanban-group-by-limit.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    Breaking for authored metadata: ObjectKanbanSchema.groupField is RETIRED (objectui#7322, ADR-0049 enforce-or-remove), and the two keys the object-kanban renderer actually reads — groupBy and limit — are now DECLARED and validated on both published faces: the TypeScript interface in objectql.ts and the Zod mirror in zod/objectql.zod.ts.

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Breaking for authored metadata: ObjectKanbanSchema.groupField is RETIRED (objectui#7322, ADR-0049 enforce-or-remove), and the two keys the object-kanban renderer actually reads — groupBy and limit — are now DECLARED and validated on both published faces: the TypeScript interface in objectql.ts and the Zod mirror in zod/objectql.zod.ts.

  • names packages/plugin-kanban/src/ObjectKanban.tsx → packages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    What was measured, on this branch's base (53ded82b). packages/plugin-kanban/src/ObjectKanban.tsx reads schema.groupBy at thirteen sites (lane materialisation at :601 / :625 / :640, card moves at :747 / :865, and their effect deps) and schema.limit at two (:264, $top: schema.limit ?? DEFAULT_KANBAN_LIMIT, and the effect deps at :291). groupField has ZERO read sites anywhere under packages/plugin-kanban/ — against a control of those thirteen groupBy reads in the same query, so the zero is a reading, not a blind grep. Yet the declaration REQUIRED groupField and declared neither groupBy nor limit. Measured from source: the documented, tested, working shape — { type: 'object-kanban', objectName, groupBy, limit } — failed ObjectKanbanSchema.safeParse and safeValidateSchema on the missing groupField, and only ever reached the renderer through BaseSchema's [key: string]: any and .passthrough(), admitted unexamined. An author who followed the declaration wrote groupField and got a board that grouped nothing, with no diagnostic on either face.

.changeset/7352-drill-down-config-mirror.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    DrillDownConfigSchema is the zod mirror of DrillDownConfig, and both declarations that carry drillDown reference it — ChartSchema (zod/data-display.zod.ts) and ObjectDataTableSchema (zod/objectql.zod.ts) — so the published validator under @object-ui/types/zod reads the key for the first time (objectui#7352).

.changeset/7363-objectql-union-arms.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectGallerySchema and ObjectDataTableSchema are members of ObjectQLComponentSchema on both faces — the TS union in objectql.ts and the zod union in zod/objectql.zod.ts — so AnyComponentSchema, and with it validateSchema / safeValidateSchema / objectui validate, has an arm for object-gallery and object-data-table nodes (objectui#7363).

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    ObjectGallerySchema and ObjectDataTableSchema are members of ObjectQLComponentSchema on both faces — the TS union in objectql.ts and the zod union in zod/objectql.zod.ts — so AnyComponentSchema, and with it validateSchema / safeValidateSchema / objectui validate, has an arm for object-gallery and object-data-table nodes (objectui#7363).

.changeset/7632-shared-record-source-config.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    That ladder is published contract on both faces — packages/types/src/objectql.ts and its zod mirror both ship .describe() strings naming getDataConfig's order (77cb489b4, maintainer ruling 2026-09-02), pinned by objectql-record-source-refinement-6939.test.ts — and it was hand-copied into five plugin components with no gate holding them together. A change to the ruled order had five edit sites and nothing that noticed a missed one; that is the AGENTS.md #0.1 drift class.

.changeset/7664-kanban-arm-plugin-dialect.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    Migration. Author boards in the plugin dialect — objectName + groupBy for an object-bound board, or columns[].cards[] with badges for a static one. Replace DeclarativeKanbanSchema imports with KanbanSchema (from @object-ui/types, or the Zod KanbanSchema from @object-ui/types/zod; @object-ui/plugin-kanban re-exports the same KanbanSchema type). Delete draggable (drag-and-drop is always on) and column color (style a lane through className). content/docs/api/schema-reference.md's kanban section now documents this dialect.

.changeset/7712-kanban-calendar-filter-input.md

  • names ObjectKanban.tsx → packages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    ObjectKanban.tsx sends the authored key to the query as $filter: schema.filter and ObjectCalendar.tsx does the same, and @objectstack/spec's ComponentPropsMap declares filter on both blocks (measured: safeParse accepts it, and refuses an undeclared key by name on the same call). But none of the four registrations that publish those two renderers listed filter in inputs, and sdui-parser's validateTree reports unknown-prop for every key no inputs entry claims. So an author writing the one spelling that WORKS was told it was unknown — objectui#6678's shape, where a correct write draws the same diagnostic as a write that does nothing. That is worse than an inert key: it actively punishes the correct behaviour, and the honest response to it is to delete working metadata.

  • names ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    ObjectKanban.tsx sends the authored key to the query as $filter: schema.filter and ObjectCalendar.tsx does the same, and @objectstack/spec's ComponentPropsMap declares filter on both blocks (measured: safeParse accepts it, and refuses an undeclared key by name on the same call). But none of the four registrations that publish those two renderers listed filter in inputs, and sdui-parser's validateTree reports unknown-prop for every key no inputs entry claims. So an author writing the one spelling that WORKS was told it was unknown — objectui#6678's shape, where a correct write draws the same diagnostic as a write that does nothing. That is worse than an inert key: it actively punishes the correct behaviour, and the honest response to it is to delete working metadata.

.changeset/7772-page-block-kanban-group-by-control.md

  • names ObjectKanban.tsx → packages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    What was measured, on this branch's base (0c8dbc49). BLOCK_CONFIG['object-kanban'] offered exactly four controls — objectName / groupField / titleField / cardFields. ObjectKanbanSchema.groupBy is REQUIRED on both published faces (objectql.ts:2765 groupBy: string, no ?; objectql.zod.ts:1001 groupBy: z.string(), no .optional()) and had no control at all, while groupField — the only control able to set grouping — has been a retirementTombstone() on the Zod face and ?: never on the TS face since objectui#7322. ObjectKanban.tsx reads schema.groupBy at thirteen sites and groupField at zero (control: those same thirteen hits in the one query, so the zero is a reading).

.changeset/7773-kanban-adapter-groupfield-write.md

  • names ObjectKanban.tsx → packages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    The object-kanban renderer never read it: groupField has ZERO hits anywhere under packages/plugin-kanban/, against a control of thirteen schema.groupBy read sites in ObjectKanban.tsx from the same query — so the zero is a reading, not a blind grep. The write was inert; the board grouped by groupBy and groupField rode along unread.

.changeset/7780-object-kanban-record-source.md

  • names packages/plugin-kanban/src/ObjectKanban.tsx → packages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    packages/plugin-kanban/src/ObjectKanban.tsx resolves a board's rows in four steps: the pre-fetched data PROP a parent passes (hasExternalData), then bind through useDataScope(schema.bind), then the inline ROW ARRAY on schema.data, and only then a fetch keyed by schema.objectName — rawData = (hasExternalData ? externalData : undefined) || boundData || schema.data || fetchedData, with the fetch itself gated on schema.objectName && !boundData && !schema.data. Every objectName read is guarded. Both published faces nevertheless REQUIRED objectName, so a bind-only or data-only board — one that renders correctly today — was refused by the shipped validator and could not be annotated with its own type.

.changeset/7804-objectql-handler-key-arms.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    The four plain objectql.ts node faces declare the nine handler keys their registered renderers read (the objectql.ts slice): ObjectFormSchema.onCancel / .onError / .onOpenChange / .onStepChange / .onSuccess, ObjectGallerySchema.onCardClick / .onRowClick, ObjectGridSchema.onNavigate and ObjectViewSchema.onNavigate.

.changeset/7804-tree-view-handler-slot.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    'runtime-slot' and not 'retired', measured at this key's own channel. 'retired' publishes "no renderer reads this key, so nothing could ever run it" — true of the two siblings already tombstoned on this arm (onSelectChange, onExpandChange) and flatly false here, since the read is live and INVOKED. ⚠️ No in-repo host builds a tree-view node carrying the key: the channel is wired end to end and only the supplier is absent, which is the same shape as ObjectFormSchema.onStepChange in this card's objectql.ts slice and is not evidence of a dead read. The TypeScript declaration is unchanged and still callable, so a programmatic host supplies it exactly as before.

.changeset/7917-export-breadcrumb-object-tree-zod-schemas.md

  • names objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    AnyComponentSchema declares 107 node component types. 105 of them could be named on the ./zod barrel — ButtonSchema.safeParse(node), which is what a designer, a form builder or a targeted test needs. The arms declaring type: 'breadcrumb' (navigation.zod.ts) and type: 'object-tree' (objectql.zod.ts) could not: both were already export const in their own module, but index.zod.ts — the package's only zod entry point — did not re-export them, so the schemas existed, were maintained, and were applied by the union while no consumer could name them.

.changeset/7963-alert-dialog-footer-keys-retired.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    Nothing else moves. These spellings are overloaded across the tree and every other owner is a live key on a different declaration — FormSchema.cancelLabel, objectql.ts's confirmLabel, plugin-designer's ConfirmDialog React props, plugin-grid's def.confirmLabel, and plugin-form's ModalForm / DrawerForm, which build a local cancelLabel from schema.cancelText. None is an AlertDialogSchema; none is touched, and a pin asserts it. No fixture, catalog schema, example app or doc fence authored any of the three on an alert-dialog node, so no shipped document is stranded.

.changeset/7997-detail-view-related-retired.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    Documentation. packages/plugin-detail/README.md and content/docs/api/schema-reference.md stop teaching the retired array and gain a migration block each.

.changeset/8067-component-input-member-kind.md

  • names apps/console/src/__tests__/registry-inputs-spec-parity.test.ts → apps/console/src/__tests__/registry-inputs-spec-parity.test.ts — edited by this change

    A registration's type: 'array' said a value was a list and stopped there, so a member that drifted from @objectstack/spec was invisible to every layer that reads a declaration. page:header.actions is the measured cost: the contract declares z.array(z.string()) ("Action IDs"), the renderer read the members as ActionDef objects, and the repo-wide parity gate in apps/console/src/__tests__/registry-inputs-spec-parity.test.ts stayed green for the whole life of the drift because both sides carried the key and neither could say what was inside it. What settled it was a maintainer ruling, not a test — and even after the fix, "these are ids" survived only as English in the registration's description.

.changeset/8171-calendar-sort-input.md

  • names ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    objectui#7712's defect, one key over. ObjectCalendar.tsx lowers the authored key onto its own query as $orderby: convertSortToQueryParams(schema.sort), and @objectstack/spec's ComponentPropsMap['object-calendar'] declares sort (measured on 17.2.0: safeParse({ objectName, sort }) returns success: true, while the same strict schema on the same call refuses bogusProp by name — that control is what makes the acceptance a verdict). But neither of the two registrations that publish this renderer — plugin-calendar:object-calendar and view:calendar — listed sort in inputs, and sdui-parser's validateTree reports unknown-prop for every key no inputs entry claims. So an author writing the one spelling that WORKS was told it was unknown — objectui#6678's shape, where a correct write draws the same diagnostic as a write that does nothing.

.changeset/8174-kanban-calendar-filter-sort.md

  • names ObjectKanban.tsx → packages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    filter had four declaration faces and only three of them named it: @objectstack/spec declares it (ComponentPropsMap['object-kanban'] and ['object-calendar']), both plugins' registration inputs publish it, and both renderers read it — ObjectKanban.tsx lowers schema.filter onto $filter, ObjectCalendar.tsx lowers schema.filter onto $filter and schema.sort onto $orderby through convertSortToQueryParams. This package's own published faces (the TypeScript interface and its zod mirror) named none of them, so an authored value reached the renderer only through BaseSchema's index signature and the mirror's .passthrough() — admitted, never examined. That is the same reasoning finding(types,plugin-kanban): ObjectKanbanSchema requires groupField (zero read sites) and declares neither groupBy nor limit — no working object-kanban node is assignable to any declared type #7322 used to move groupBy and limit into this same interface.

  • names ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    filter had four declaration faces and only three of them named it: @objectstack/spec declares it (ComponentPropsMap['object-kanban'] and ['object-calendar']), both plugins' registration inputs publish it, and both renderers read it — ObjectKanban.tsx lowers schema.filter onto $filter, ObjectCalendar.tsx lowers schema.filter onto $filter and schema.sort onto $orderby through convertSortToQueryParams. This package's own published faces (the TypeScript interface and its zod mirror) named none of them, so an authored value reached the renderer only through BaseSchema's index signature and the mirror's .passthrough() — admitted, never examined. That is the same reasoning finding(types,plugin-kanban): ObjectKanbanSchema requires groupField (zero read sites) and declares neither groupBy nor limit — no working object-kanban node is assignable to any declared type #7322 used to move groupBy and limit into this same interface.

.changeset/8268-testid-emitted-as-data-testid.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    The other direction — retiring the promise — was considered and declined. It is what c1fe272ad did for BaseSchema.hidden, but that key had a working behaviour to describe and zero named consumers, and the ruling's decline turned on exactly that. This promise already has carriers outside the type declaration: content/docs/api/schema-reference.md states it as a table row and authors testId in that page's own base-schema example, @object-ui/cli's OBJECTUI_STRUCTURAL_KEYS identifies a file as an ObjectUI schema node by this key, at this change ObjectGridSlotKey / ObjectFormSlotKey pin it, SchemaBuilder.testId() writes it, and ADR-0054 C4 — shipped — reads "the renderer emits data-testid … derived from metadata".

.changeset/8355-retire-calendar-date-aliases.md

  • names calendarUnionReads-8651.test.tsx → packages/plugin-calendar/src/__tests__/calendarUnionReads-8651.test.tsx — edited by this change

    Pinned by calendar-date-alias-refusal-8355.test.ts (@object-ui/types, all five surfaces, the per-surface consequence split, the compile-time face, and the structural guard that listViews stays out of the object's shape), ListView.calendarAliasRefused-8355.test.tsx (@object-ui/plugin-list) and ObjectView.calendarAliasRefused-8355.test.tsx (@object-ui/plugin-view) — both reading the node their producer really emits through a spy registration, which is the only census that can see a key arriving through a spread — and the inverted ledger rows in calendarUnionReads-8651.test.tsx (@object-ui/plugin-calendar).

.changeset/8466-calendar-color-allday-fields.md

  • names ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    ObjectCalendar.tsx's getCalendarConfig reads FIVE flat keys off the node, and packages/plugin-calendar/README.md teaches all five in one sentence — "point titleField / startDateField / endDateField / allDayField / colorField at your own fields when they differ." Only three of the five were declared. The other two reached the renderer through BaseSchema's [key: string]: any on the TypeScript face and its .passthrough() on the zod mirror: admitted, never examined. A misspelling therefore left the calendar silently colourless while every published gate passed.

  • names packages/plugin-calendar/README.md → packages/plugin-calendar/README.md — edited by this change

    ObjectCalendar.tsx's getCalendarConfig reads FIVE flat keys off the node, and packages/plugin-calendar/README.md teaches all five in one sentence — "point titleField / startDateField / endDateField / allDayField / colorField at your own fields when they differ." Only three of the five were declared. The other two reached the renderer through BaseSchema's [key: string]: any on the TypeScript face and its .passthrough() on the zod mirror: admitted, never examined. A misspelling therefore left the calendar silently colourless while every published gate passed.

.changeset/8478-describe-line-addresses.md

.changeset/8653-listview-title-retired-rowactiondefs-pinned.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    title — retired. ListView resolved its export filename through schema.label || (schema as any).title. @objectstack/spec/ui's ListViewSchema refuses title by name (unrecognized_keys: ['title']) while ObjectGridPropsSchema accepts it; packages/types mirrors the platform contract rather than ruling over it, so declaring title on ListViewSchema would have made this repo accept what the platform save gate rejects. That asymmetry is also why objectui#6639 could take the declare branch for ObjectGridSchema.title one package over and this site could not. A parse-based census of apps/ examples/ content/ and packages/ found zero list-view nodes authoring title, so the retirement costs no author a filename. Over that same corpus the instrument reports three object-grid nodes carrying the key: two authored ones, both in content/docs/api/schema-reference.md, plus one that is not authored at all — packages/plugin-view/src/ObjectView.tsx composes title: schema.table?.title onto a grid node it builds, so it is a producer writing the key rather than an author declaring it. ObjectGrid's own title reads are untouched — they remain declared, ruled and read.

.changeset/8735-objectql-mirror-docblocks-not-defaulted.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Correct four zod/objectql.zod.ts docblocks that described the behaviour objectui#8317 removed. Since that change the zod mirrors strip imported @objectstack/spec defaults at this package's import boundary, but the docblocks on HttpRequestSchema, ListColumnSchema, SelectionConfigSchema and PaginationConfigSchema still said, in the present tense, that method, prefix.type, type and pageSize are defaulted on parse — the opposite of what each export does. Each now says the key is declared and accepted but NOT defaulted on parse.

.changeset/8767-object-grid-refuses-string-sort.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    Migration. Write the array: sort: [{ field: 'name', order: 'desc' }]. Both keys are required. SortConfig.order carries no ? in @object-ui/types (packages/types/src/objectql.ts) and no .optional() in its zod mirror, and the protocol's own reusable SortItemSchema requires order as well — measured: that schema refuses [{ field: 'name' }] with invalid_value at 0.order. Do not omit it: this block's array arm interpolates whatever is present, so an omitted order lowers to $orderby: 'name undefined' today. That is pre-existing behaviour on the arm this change does not touch, and it is filed as a successor card rather than widened into here.

.changeset/8801-object-kanban-allow-collapse-retired.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    • the declarations retired here — packages/types/src/objectql.ts and its mirror packages/types/src/zod/objectql.zod.ts; - the pins that assert the retirement — object-kanban-allow-collapse-retired-8801.test.ts and bare-kanban-node-key-retired-8802.test.ts; - a comment in packages/types/src/zod/complex.zod.ts, recording that the deleted retiredZeroReadKanbanKey helper once carried this spelling on the SIBLING arm; - one row of content/docs/api/schema-reference.md; - the .changeset/ release notes that discuss it — this one, the two historical entries covering the sibling arm's own spelling, and objectui#9629's note recording the correction to this paragraph.
  • names packages/types/src/zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    • the declarations retired here — packages/types/src/objectql.ts and its mirror packages/types/src/zod/objectql.zod.ts; - the pins that assert the retirement — object-kanban-allow-collapse-retired-8801.test.ts and bare-kanban-node-key-retired-8802.test.ts; - a comment in packages/types/src/zod/complex.zod.ts, recording that the deleted retiredZeroReadKanbanKey helper once carried this spelling on the SIBLING arm; - one row of content/docs/api/schema-reference.md; - the .changeset/ release notes that discuss it — this one, the two historical entries covering the sibling arm's own spelling, and objectui#9629's note recording the correction to this paragraph.
  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    • the declarations retired here — packages/types/src/objectql.ts and its mirror packages/types/src/zod/objectql.zod.ts; - the pins that assert the retirement — object-kanban-allow-collapse-retired-8801.test.ts and bare-kanban-node-key-retired-8802.test.ts; - a comment in packages/types/src/zod/complex.zod.ts, recording that the deleted retiredZeroReadKanbanKey helper once carried this spelling on the SIBLING arm; - one row of content/docs/api/schema-reference.md; - the .changeset/ release notes that discuss it — this one, the two historical entries covering the sibling arm's own spelling, and objectui#9629's note recording the correction to this paragraph.

.changeset/8802-8257-8008-kanban-gantt-family-retirement.md

  • names content/docs/plugins/plugin-kanban.mdx → content/docs/plugins/plugin-kanban.mdx — edited by this change

    The diagnostic's remedy text moves from a tag to a component. It used to end "render ANGLE-BRACKETS(kanban-ui) from a React host that passes onQuickAdd". That sentence is falsified by this change: kanban-ui is no longer a node type key, so a page written to the old advice draws unknown-component. It now names KanbanRenderer from @object-ui/plugin-kanban — still exported, still forwarding both halves by identity — which is the surviving way to get the pair. content/docs/plugins/plugin-kanban.mdx says the same thing the same way.

.changeset/8827-kanban-empty-state-settled.md

  • names ObjectKanban.tsx → packages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    A genuinely empty board still paints DataEmptyState. The reverse regression — "gating on a truthy definition would leave those boards empty forever", named in ObjectKanban.tsx itself — is what the settle contract exists to prevent, and every exit settles: the query succeeding, the query throwing, no readable source, the non-fetch record sources (external, bound and inline data are settled from the first frame), and the schema-only kanban-ui entry, which has no ObjectKanban and therefore no provider and so takes the context's settled default. Lanes, headers, counts and drop targets keep rendering while the rows are in flight; only the claim is withheld.

.changeset/8885-object-chart-drilldown-title-compareto.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectChart.tsx reads all three off schema, and until now neither published copy declared any of them: not the TS interface (packages/types/src/objectql.ts) and not the zod mirror (packages/types/src/zod/objectql.zod.ts). They rode BaseSchema's index signature / .passthrough() and arrived unvalidated. drillDown was the sharpest case — this component's registry inputs advertise it to the designer palette, and @objectstack/spec publishes ChartDrillDownSchema for exactly this carrier, so an author was offered a key that neither published shape mentioned.

  • names packages/types/src/zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    ObjectChart.tsx reads all three off schema, and until now neither published copy declared any of them: not the TS interface (packages/types/src/objectql.ts) and not the zod mirror (packages/types/src/zod/objectql.zod.ts). They rode BaseSchema's index signature / .passthrough() and arrived unvalidated. drillDown was the sharpest case — this component's registry inputs advertise it to the designer palette, and @objectstack/spec publishes ChartDrillDownSchema for exactly this carrier, so an author was offered a key that neither published shape mentioned.

.changeset/8913-object-kanban-columns-declared.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    What moved. ObjectKanbanSchema gains columns on both halves that move together — the TypeScript interface (objectql.ts) and its Zod mirror (zod/objectql.zod.ts). Retiring the bare kanban node type key (objectui#8802) removed the only face that judged a lane, and object-kanban had never declared the key, so it rode BaseSchema's [key: string]: any / .passthrough(): read by the renderer at three sites, named by no published face.

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    What moved. ObjectKanbanSchema gains columns on both halves that move together — the TypeScript interface (objectql.ts) and its Zod mirror (zod/objectql.zod.ts). Retiring the bare kanban node type key (objectui#8802) removed the only face that judged a lane, and object-kanban had never declared the key, so it rode BaseSchema's [key: string]: any / .passthrough(): read by the renderer at three sites, named by no published face.

.changeset/8990-object-kanban-groupby-optional.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    @objectstack/spec declares the key optional — groupBy: z.string().optional() on ObjectKanbanPropsSchema — while this package required it on the TypeScript declaration (packages/types/src/objectql.ts) and on the Zod mirror (packages/types/src/zod/objectql.zod.ts). objectui was therefore narrower than the protocol on a published key: ObjectKanbanSchema.safeParse and safeValidateSchema refused an object-kanban node the protocol accepts, and such a node could not be annotated with its own type.

  • names packages/types/src/zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    @objectstack/spec declares the key optional — groupBy: z.string().optional() on ObjectKanbanPropsSchema — while this package required it on the TypeScript declaration (packages/types/src/objectql.ts) and on the Zod mirror (packages/types/src/zod/objectql.zod.ts). objectui was therefore narrower than the protocol on a published key: ObjectKanbanSchema.safeParse and safeValidateSchema refused an object-kanban node the protocol accepts, and such a node could not be annotated with its own type.

  • names ObjectKanban.tsx → packages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    What a lane-less board does, measured rather than assumed. Every schema.groupBy read in ObjectKanban.tsx is a guarded early-return, so the board degrades instead of breaking: with no lane key and no columns it renders an empty board; with bare-string columns it draws those lanes, titled by the raw strings; card moves are inert (persistCardMove and the move callback both open if (!groupBy) return). ⚠️ Every lane-less board holds zero cards — bucketCardsIntoColumns returns before distributing records when there is no lane key — so omitting groupBy is not a way to configure a board, it is a board that groups by nothing.

.changeset/8992-user-actions-collapse-and-docblock.md

  • names objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    objectql.zod.ts's UserActionsSchema read stripImportedDefaults(Spec).extend({ group, hideFields, rowColor }), an extension that existed only because @objectstack/spec did not declare those three keys while normalizeListViewSchema folded objectui's legacy showGroup / showHideFields / showColor onto them. The protocol adopted all three in 17.3.0 (objectui#5435's ruling), so the extension is now a second local copy of a protocol declaration — the shape two faces start drifting from — and it collapses into the plain by-reference re-export its own note always said it would become.

.changeset/9092-inline-locale-declared-face.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    • AppComponentSchema.label (app.ts) - ObjectGridSchema.label and .description (objectql.ts) - PageNodeSchema.aria.ariaLabel (layout.ts)

.changeset/9187-record-highlights-layout-two-values.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    ⚠️ The census behind this narrowing covers this repository only, and it found no in-repo authoring to migrate: every in-tree layout: 'grid' belongs to a different component (detail-view in content/docs/api/schema-reference.md and phase2-schemas.test.ts, ai-recommendations in packages/plugin-ai/README.md), and the one in-repo consumer of this interface that writes a layout (p1-spec-alignment.test.ts) writes 'horizontal'. So no document in this repository stops type-checking. A TypeScript consumer outside this repo that wrote grid is not observable from here and gets a compile error (TS2322) naming the key — which is why the FROM/TO is spelled out above.

.changeset/9309-object-gallery-filter-destination-typed.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectGallerySchema.filter is typed as the destination its own docblock names — QueryParams['$filter'] — on both faces, the TS interface in objectql.ts and the zod mirror in zod/objectql.zod.ts (objectui#9309).

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    ObjectGallerySchema.filter is typed as the destination its own docblock names — QueryParams['$filter'] — on both faces, the TS interface in objectql.ts and the zod mirror in zod/objectql.zod.ts (objectui#9309).

.changeset/9511-record-id-is-a-string.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    The three authorable keys, each on BOTH faces. ObjectFormSchema.recordId (objectql.ts + zod/objectql.zod.ts), DetailViewSchema.resourceId (views.ts + zod/views.zod.ts) and DetailSchema.resourceId (crud.ts + zod/crud.zod.ts). ⚠️ The crud pair is DetailSchema, not DetailViewSchema, and it reaches the same renderer — not by symbol but by data flow: plugin-detail registers the 'detail' node type onto DetailView. A read that follows TypeScript symbols alone finds two keys and is incomplete.

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    The three authorable keys, each on BOTH faces. ObjectFormSchema.recordId (objectql.ts + zod/objectql.zod.ts), DetailViewSchema.resourceId (views.ts + zod/views.zod.ts) and DetailSchema.resourceId (crud.ts + zod/crud.zod.ts). ⚠️ The crud pair is DetailSchema, not DetailViewSchema, and it reaches the same renderer — not by symbol but by data flow: plugin-detail registers the 'detail' node type onto DetailView. A read that follows TypeScript symbols alone finds two keys and is incomplete.

.changeset/9549-tree-filter-declared.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectTreeSchema.filter is declared on both faces, in the shape objectui#9309 settled for ObjectGallerySchema.filter: QueryParams['$filter'] by indexed access on the TS interface in objectql.ts, and the same two-arm union (array first) on the zod mirror in zod/objectql.zod.ts (objectui#9549).

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    ObjectTreeSchema.filter is declared on both faces, in the shape objectui#9309 settled for ObjectGallerySchema.filter: QueryParams['$filter'] by indexed access on the TS interface in objectql.ts, and the same two-arm union (array first) on the zod mirror in zod/objectql.zod.ts (objectui#9549).

.changeset/9550-object-tree-root-barrel.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectQLComponentSchema declares the node types an ObjectQL block may be. Every one of its arms was a named export of this package's root barrel except ObjectTreeSchema, which was declared in objectql.ts, applied by the union, and re-exported by the ./zod barrel (objectui#7917) — while no TypeScript consumer could name it. There is no ./objectql subpath to reach around the barrel: the package's exports map is pinned by packages/types/src/__tests__/package-exports-manifest.test.ts, and the root barrel was the only route to this type.

.changeset/9606-object-kanban-card-title.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Both published faces of the object-kanban arm now name the key: the zod mirror ObjectKanbanSchema in zod/objectql.zod.ts and its TypeScript twin, the ObjectKanbanSchema interface in objectql.ts. Both declare it OPTIONAL, at the same requiredness the other face uses, so the two faces accept and refuse the same documents. (Located and cited by SYMBOL: line addresses in zod/objectql.zod.ts have drifted before, and this change is itself about a drifted mirror.)

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    Both published faces of the object-kanban arm now name the key: the zod mirror ObjectKanbanSchema in zod/objectql.zod.ts and its TypeScript twin, the ObjectKanbanSchema interface in objectql.ts. Both declare it OPTIONAL, at the same requiredness the other face uses, so the two faces accept and refuse the same documents. (Located and cited by SYMBOL: line addresses in zod/objectql.zod.ts have drifted before, and this change is itself about a drifted mirror.)

.changeset/9628-kanban-column-collapsed-honoured.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    The key was declared on both published faces of the object-kanban arm — the lane element of ObjectKanbanSchema (objectql.ts and its Zod mirror) and the runtime lane KanbanColumn (complex.ts and its mirror) — and read by KanbanEnhanced alone, a module no production source imports. An authored { "id": "todo", "title": "To Do", "collapsed": true } therefore parsed green on both faces and reached a board that did nothing with it: KanbanImpl's only collapse is the SWIMLANE row's, held in viewer state under objectui:kanban-collapsed:ANGLE-BRACKETS(swimlaneField) and never keyed to a lane's declared value. That is the ADR-0049 declared-but-unhonoured shape.

.changeset/calendar-view-schema-converge.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    Runtime renderer behaviour is unchanged. @object-ui/plugin-calendar's README and content/docs/api/schema-reference.md are repaired to the converged surface in the same change, so no copy of the old contradiction survives.

.changeset/issue-5373-retire-crud-schema.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    crud had four declaration faces and no registered renderer, for the whole life of the key: the TS interface (packages/types/src/crud.ts), the zod mirror (packages/types/src/zod/crud.zod.ts), a dedicated branch in validateSchema that affirmatively PASSED it, and CRUDBuilder in @object-ui/core. A node spelling it painted the OBJUI-001 "Unknown component type" panel, and content/docs/api/schema-reference.md published it as reference material — so a reader (or an AI author) who copied the page got a red panel.

  • names api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    Authoring crud is now REFUSED BY NAME rather than passed or silently ignored. validateSchema returns an error with code: 'RETIRED_TYPE' on schema.type — at any depth, since it is what validateChildren recurses with — so assertValidSchema throws and isValidSchema answers false. The message names the migration: object-grid for the record table with its toolbar, filters, pagination and row/batch actions, object-form for the create/edit form, and detail for the record view. api/schema-reference.md is rewritten around those shapes.

.changeset/object-view-unmirrored-keys-7779.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    listViews stays unmirrored, on the ruling's own fallback clause. The declaration's value is the local NamedListView — 64 declared top-level members (⚠️ re-taken at objectui#8980, which added the seventeen the protocol declares on this surface to the 47 this entry first measured), of which the renderer reads 21 off a named view. data is one of the 21 now: it used to reach the renderer through an as any cast on the named-view config in packages/plugin-view/src/ObjectView.tsx and be declared nowhere, and the objectui#8980 ruling declared it by name — objectui#7928's open half, answered. The spec's ViewSchema.listViews is a record of the STRICT ObjectListViewSchema, which requires columns and refuses options, ObjectQL tuple filters and default — that is, it refused the named views this package's own README and content/docs/api/schema-reference.md taught when this entry was written ({ label: 'All Users' } fails at columns; filter: [["owner", "=", "..."]] fails at filter.0), and objectui#8255 has since rewritten them in the spec shape. Mirroring the spec value would have lost documented behaviour; mirroring the local value would enforce 43 unread members (64 declared, minus the 21 that are both declared and read) into the contract — the very thing ruling B refused for the six local keys. The key therefore stays in the parity ledger with that measurement, pinned, until the maintainer decides its value type. It is not papered over with z.any().

.changeset/table-renderer-declared-column-contract-5350.md

  • names content/docs/api/schema-reference.md → content/docs/api/schema-reference.md — edited by this change

    What makes this site different from its three siblings is that the alias was not merely tolerated, it was published. content/docs/api/schema-reference.md §TableSchema shipped a copyable { "name": "id", "label": "#" } example and a property row reading "Column definitions with name, label, …", while packages/types declared the opposite pair. Docs and type disagreed about one type they both call TableColumn, each internally consistent. Retiring the alias without correcting the page would have turned a documented, working example into a silently broken one, so both halves land together: the page now authors accessorKey/header. The same row also advertised a render property that TableColumn has never declared — the renderer's hook is cell — and that claim is dropped rather than re-spelled.

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

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

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

Angle-bracketed names in the quoted prose above are rewritten as ANGLE-BRACKETS(name): GitHub deletes tag-shaped fragments from a stored body, and a quote that silently loses the identifier it is about is worse than a visible repair.

Compared the checked-out tree with 1563d3e10 (merge-base with origin/main): 16 file(s) changed outside .changeset/, read against 1866 pending declaration(s) that publish a body (2478 pending in total). · run

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3584.5 KB 3607.4 KB
Main entry chunk (gzip) 150.0 KB 350 KB
Entry file index-Dc0hV-oh.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.88KB 6.25KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.17KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 570.17KB 136.43KB
core (index.js) 10.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 228.86KB 63.53KB
fields (index.js) 261.11KB 66.26KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.35KB 9.18KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 41.23KB 11.53KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 52.90KB 15.35KB
plugin-charts (index.js) 84.09KB 22.93KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 139.27KB 37.26KB
plugin-designer (index.js) 216.32KB 44.56KB
plugin-detail (index.js) 244.72KB 64.45KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 173.75KB 44.64KB
plugin-gantt (index.js) 173.03KB 43.07KB
plugin-grid (index.js) 231.61KB 63.61KB
plugin-kanban (index.js) 49.32KB 15.48KB
plugin-list (index.js) 116.63KB 28.97KB
plugin-map (index.js) 23.50KB 7.82KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 33.05KB 9.67KB
plugin-tree (index.js) 11.20KB 3.89KB
plugin-view (index.js) 90.32KB 22.76KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 119.55KB 39.23KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.06KB 2.68KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 21.42KB 7.05KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 3.19KB 1.62KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.26KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 21.59KB 7.71KB
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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 0c50a196cc6ef29eac2090d12afa4076358843b1
Local-runs: none

Read 2026-10-01T00:11Z by the isolated reviewer running inside the adopting seat's session. Inputs: card #8652 (body and all 9 comments — the triage ruling 5619611144, the unlock scans 5818717743 / 5904071743 / 5904136868, the claim 5920939737 and the dev report 5921877806 included), PR #11292 (body, 13-file list, net diff against main), the installed spec source at objectstack 0f6dcac5e9 (component.zod.ts, view.zod.ts), objectui AGENTS.md and the sibling arms at origin/main (read with git show, no checkout), and the 42 check-runs on the head (42 of 42 returned), read last. Nothing was built, run or re-run.

① Derived judgments

  1. Zod face, both arms — RIGHT. ObjectKanbanSchema and ObjectCalendarSchema in objectql.zod.ts gain navigation: stripImportedDefaults(SpecNavigationConfigSchema).optional(). Accept-set change per arm: the key's VALUE is now judged — a bad mode is refused at navigation.mode, a member the spec's strict object does not declare is refused at navigation, the retired view tombstone is refused; an absent key and a block without mode still parse, and no default is written into the document. Before, BaseSchema's .passthrough() admitted any value under the key. This is the mirror catching up with the contract, not leading it: at 0f6dcac5e9 both ObjectKanbanPropsSchema and ObjectCalendarPropsSchema declare navigation: NavigationConfigSchema.optional(), each docblock naming this card's ruling 「B」. The def is taken BY REFERENCE (the spec docblock's own reason: no second dialect for one gesture, no second view tombstone to maintain), and the stripImportedDefaults wrapper is the spelling ObjectMapSchema, ObjectGanttSchema and ObjectGallerySchema already use at origin/main, so the four spec defaults (mode: 'page', preventNavigation: false, openNewTab: false, size: 'auto') stay out of parsed documents on every arm alike. Ceiling stated honestly in the pin's own header: a MISSPELLED key is still admitted by the passthrough base — objectui#7927's ceiling, not this card's.
  2. TS face, both arms — RIGHT. navigation?: ViewNavigationConfig, where ViewNavigationConfig = NavigationConfig (the spec's type) and six interfaces already use it at origin/main; neither ObjectCalendarSchema nor ObjectKanbanSchema carried the member before (their interface spans at origin/main hold no navigation line, while the grid, map, gantt and gallery spans do — the lit control). Defended by an Equal assertion (not extends, which any through the index signature would pass) plus @ts-expect-error rows; the dev's ablation reports TS2344 and TS2578 on removal, and Type Check on the head is still in progress at this read (item ③.9).
  3. Registry public surface — RIGHT, one note. OBJECT_KANBAN_INPUTS and OBJECT_CALENDAR_INPUTS publish navigation as an object input, so the designer offers it — exactly the two entries the 17.5.0 bump BOOKED to this card. OBJECT_CALENDAR_INPUTS is shared with the bare calendar tag, which has no ComponentPropsMap row at 0f6dcac5e9 to be judged against; publishing there is honest about what the same renderer reads, and the sharing predates this card. Each description is a claim about the renderer; every clause is held by a member-pin row except the one carried to ③ item 7.
  4. Parity ledger — RIGHT, shrink-only and by name. The two OWED entries are struck; unpublishedKeys cap 5 to 3; the objectui#8176 backlog ceiling 2 to 0 in all three assertions, with the backlog asserted EMPTY by name so the freed room cannot be spent on another key; the per-owner total for objectui#8652 2 to 0; objectui#11168's 13 untouched; two MEMBER_PINS entries added — the objectui#8212 obligation an object-armed input carries.
  5. calendarUnionReads-8651 — RIGHT. Its ledger held exactly one entry, navigation, deferred to this card by name. The entry is struck (a stale carve-out would exempt a key the population row can now judge) and the UNDECLARED row is inverted — READ and DECLARED and not-ledgered — rather than deleted, so it still fails in both directions.
  6. Renderers — RIGHT, no behaviour change. ObjectCalendar drops the (schema as any) cast objectui#8651 left standing for this card; ObjectKanban changes a comment only. The { mode: 'drawer' } absent-key fallback stays a renderer default that is documented, not declared — which is what the spec's own describe string on both entries says ("documented rather than declared, so a parsed board carries the key only when the author wrote it"). The member pins mount the real components and click.
  7. Changeset 7322 note — RIGHT. Append-only dated note; frontmatter byte-identical; Changeset Overwrite Report is success on the head.
  8. Not touched, rightly: object-timeline (objectui#8654 — but see ③ item 5), the ObjectFormSchema region (objectui#10859 batch 4), the view-level KanbanConfig (objectui#8367), and no governed surface (Governed Surface Queue Guard success).
  9. Nit, not a verdict item: in both plugin index.tsx files the new input row was appended on the SAME source line as the preceding entry, so the diff shows the loading and conditionalFormatting lines as modified. The repo has no formatter gate (AGENTS.md says so by name); cosmetic, the seat's call whether to reflow before ready.

② Semver level

.changeset/8652-kanban-calendar-navigation.md declares @object-ui/types, @object-ui/plugin-kanban and @object-ui/plugin-calendar at minor — matching what the diff publishes: two new optional members on two published TS interfaces and two zod arms (a widening of the declared face, and a narrowing of the accept-set on that key's value, which the changeset body states in as many words), plus two registry inputs rows. All three packages are in the fixed group. No major, as the version-alignment policy requires (additive and breaking alike are minor here; Changeset Bump Policy success). apps/console changed only in src/__tests__/registry-inputs-spec-parity.test.ts — guarded source for the presence gate, which asks for ONE declaration and has it (Changeset Declaration success); the console's published artifact is unchanged and the fixed group bumps it regardless. Changeset Fixed Group Check, Changeset Claim Re-read and Changeset Overwrite Report are success. The PR body carries Clause-②: yes, equal to the claim 5920939737 ("a widening of a published face … the at-tier contract record is owed on the landing head before enqueue") — this record is that artefact. The card body's older line asking for needs:contract-review on card and PR: the label sits on neither today; that is the seat's bookkeeping outside the diff, and the merge-queue guard refuses only when the label is PRESENT, so its absence blocks nothing once this record stands.

③ Boundary flags

open_questions: []. Five declared deviations, three out-of-scope findings and the PR's acceptance notes, each answered or escalated:

  1. Push probe — answered. A plain fast-forward onto the contentless branch tip 85243729 (an ancestor of main), no force push; the reuse was planned in the claim. Compliant with the no-force-push rule.
  2. File surface grew within the claim — answered. The registry rows are the claim's own "any registry inputs row that must name the key"; the two member-pin files are the claim's "Pins" plus objectui#8212's obligation, which the parity test enforces; the calendarUnionReads-8651 edit is forced by this landing (that pin held navigation UNDECLARED by name and would have reddened). Nothing outside the named surface beyond those.
  3. AGENTS.md Add automated testing infrastructure and CI/CD workflows #2 (docs-driven) not executed — ESCALATED to the seat. Measured at origin/main: content/docs/plugins/plugin-grid.mdx and packages/plugin-grid/README.md each carry a navigation row in their props table (the lit control); plugin-kanban.mdx, plugin-calendar.mdx, packages/plugin-kanban/README.md and packages/plugin-calendar/README.md have zero navigation hits while documenting other schema keys. The claim's file surface excluded docs, so the dev's stop is correct boundary discipline, and the published type and the spec agree — the verdict does not turn on this. But Add automated testing infrastructure and CI/CD workflows #2 reads "Not done until docs reflect the code", and this diff publishes a new authorable input on two blocks. The seat owes one of: a docs commit on this branch before ready (the PR is a draft and the seat owns ready and enqueue), or a docs card linked on this PR before enqueue.
  4. Housekeeping slip — answered. A stray untracked file in the shared objectstack checkout, deleted within a minute, porcelain empty; no tracked file touched. Nothing carries.
  5. Dispatch H1 falsified on the timeline — ESCALATED. Read here directly: ObjectTimelinePropsSchema at 0f6dcac5e9 declares navigation: NavigationConfigSchema.optional(), its docblock naming this card's ruling 「B」 and the timeline's (schema as any).navigation read. The claim's exclusion rationale ("the installed spec declares no navigation on ObjectTimelinePropsSchema … so its exit differs") is false: objectui#8654's exit is the same mirror alignment, by reference. The dev left it untouched as ordered — right. The seat should re-read objectui#8654 (held pm:blocked on this card by the triage ruling 5619611144) with this fact and dispatch it in this PR's shape.
  6. Out-of-scope class a: page opens nothing on a standalone board or calendar — ESCALATED for filing. Measured by mounting the real components: a block with mode: 'page', and any block written without mode (the spec defaults it to page), silences the click, because neither renderer hands useNavigationOverlay an onNavigate. This PR's input descriptions turn that into authoring guidance ("write mode whenever the block is written") and pin it with two rows per member pin. Right under AGENTS.md #0.1: the alternative — the renderer re-defaulting a mode-less block to drawer — would fork the spec's default on the renderer side. The gap itself is real and now designer-visible (a spec-valid document that passes os validate can author a dead click), and the spec's own docblock says the element carrier exists for "the standalone placement". No card number was given; the seat files it with the dev's dedupe words, or links the existing card, and names the carrier on this PR.
  7. openNewTab: true outranks an overlay mode too — answered, one-row ask. The published description says it "outranks the mode" (all modes); the pin holds only the page case; the overlay case is reported observed, not pinned, carrier none; the spec's describe reads "applies to page mode". The sentence is true as measured, so not blocking — but a description is a claim about the renderer: either add the overlay row to both member pins or narrow the sentence to page. Whether the shared hook should honour the flag outside page at all is a hook-wide question (grid included) the seat may file; not this card's.
  8. ObjectTree.tsx stale comment — answered. Outside the claim. Confirmed at 0f6dcac5e9: ObjectTreePropsSchema carries navigation: z.unknown().optional(), so the comment's "no object-tree entry" is stale since 17.5.0. A note for objectui#8655's seat; no action on this PR.
  9. Check-runs on the head, recorded not awaited: 31 success, 3 skipped (the coverage-shard matrix placeholder run, Test (coverage), dependabot — condition skips, not failures), 8 in progress at this read: Type Check, Spec Main Shape Gate, Test (shard 1/8), Test (shard 2/8), Test (shard 4/8), Test (shard 5/8), Test (shard 7/8), Test (shard 8/8). Test (shard 3/8), Test (shard 6/8), Test (dist pins), Lint, Line Citation Gate, Build & E2E, Build Docs, README Export Check, Doc Snippet Type Check and every changeset check are success. No failure on the head. The verdict below is on the contract; ready and enqueue still wait on the eight, which is the seat's gate, not this record's.

Implemented-by: claude/issue-8652-kanban-navigation-family
Reviewed-by: session_01VhxTqosz7wn54ahqyxgERT

VERDICT: PASS

…ject-kanban and object-calendar blocks (objectui#8652)

AGENTS.md #2, adopted by the seat as patch round 2 of objectui#8652: the
declaration this card made is documented where the two blocks are documented.

- `packages/plugin-kanban/README.md` and `packages/plugin-calendar/README.md`:
  the typed example blocks carry `navigation`, and a paragraph states the type
  (the spec's `NavigationConfig` by reference, `ViewNavigationConfig`, the type
  `ObjectGridSchema.navigation` uses), its mode list, the absent-key drawer and
  the parent-view precedence the member pins prove.
- `content/docs/plugins/plugin-kanban.mdx` (Properties row) and
  `plugin-calendar.mdx` (Schema API line and paragraph): the same, in the same
  words.
- `content/docs/api/schema-reference.md`: a `navigation` row on the
  `ObjectKanbanSchema` table, and the sentence that called `cardTitle` and
  `navigation` undeclared on this face is corrected - `cardTitle` has been
  declared since objectui#9606 and `navigation` is declared by this card;
  `swimlaneField` and `grouping` are still undeclared.

Each page carries one sentence on the `page` caveat - `page`, and a block
written without `mode`, opens nothing on a board or calendar no parent view
navigates for - pointing at objectui#11293. The renderer is not changed here.

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

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3584.7 KB 3607.4 KB
Main entry chunk (gzip) 150.0 KB 350 KB
Entry file index-Cej8WSpX.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.88KB 6.25KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.17KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 570.17KB 136.43KB
core (index.js) 10.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 229.96KB 63.80KB
fields (index.js) 261.11KB 66.26KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.35KB 9.18KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 41.23KB 11.53KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 52.90KB 15.35KB
plugin-charts (index.js) 84.09KB 22.93KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 139.27KB 37.26KB
plugin-designer (index.js) 216.45KB 44.60KB
plugin-detail (index.js) 244.79KB 64.47KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 173.75KB 44.64KB
plugin-gantt (index.js) 173.03KB 43.07KB
plugin-grid (index.js) 231.61KB 63.61KB
plugin-kanban (index.js) 49.32KB 15.48KB
plugin-list (index.js) 116.63KB 28.97KB
plugin-map (index.js) 23.50KB 7.82KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 33.05KB 9.67KB
plugin-tree (index.js) 11.20KB 3.89KB
plugin-view (index.js) 90.32KB 22.76KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 119.55KB 39.23KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.06KB 2.68KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 21.42KB 7.05KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 3.19KB 1.62KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.26KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 21.59KB 7.71KB
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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 161a5c5b4231bcd31538c15c6ff40a5de16b218c
Local-runs: none

Read 2026-10-01T00:34Z by the isolated reviewer running inside the adopting seat's session, round 2 on this PR. Inputs: card #8652 (body and all 10 comments, the earlier PASS record 5922016342 on this PR thread and the seat's ACCEPT 5922040412 included), PR #11292 (body, 18-file list, net diff against main at this head), the round-2 os-dev-report text read from the seat's scratch file as the dev's claim (it is not on the card yet), objectui AGENTS.md at origin/main, the installed spec source at objectstack 0f6dcac5e9 (component.zod.ts, view.zod.ts), the files at this head read with git show / git grep (no checkout), and the 42 check-runs on the head, read last. Nothing was built, run or re-run. This head is the earlier PASS head 0c50a196c plus one docs commit; the whole diff was re-read, not only the delta.

① Derived judgments

The code face is byte-for-byte the face the earlier record judged, and each of its items re-reads the same on this head. Restated as one-liners so this record stands alone, then the docs face in full.

  1. Zod face, both arms — RIGHT. ObjectKanbanSchema and ObjectCalendarSchema in objectql.zod.ts gain navigation: stripImportedDefaults(SpecNavigationConfigSchema).optional() — the spelling the grid, gantt and map arms carry at this head (three sibling lines found on the same grep). Accept-set change per arm: the key's VALUE is now judged (bad mode refused at navigation.mode, a member outside the spec's strict object refused at navigation, the retired view tombstone refused); an absent key, and a block without mode, still parse with no default written. At 0f6dcac5e9 ObjectKanbanPropsSchema and ObjectCalendarPropsSchema each declare navigation: NavigationConfigSchema.optional(), each docblock naming ruling 「B」 and the spec's own describe string saying the renderer's { mode: 'drawer' } default is documented rather than declared. Mirror catching up, not leading.
  2. TS face, both arms — RIGHT. navigation?: ViewNavigationConfig, where export type ViewNavigationConfig = NavigationConfig is the spec's type imported, inside the ObjectCalendarSchema span and the ObjectKanbanSchema span (measured by the interface's opening line and its first column-0 closing brace, not by a file grep). Equal-assertion plus @ts-expect-error rows defend it; Type Check is still in progress at this read (③.8).
  3. Registry public surface — RIGHT. OBJECT_KANBAN_INPUTS and OBJECT_CALENDAR_INPUTS publish navigation as an object input; the calendar array is shared by the object-calendar and bare calendar registrations, both of which render ObjectCalendarRenderer (two ComponentRegistry.register calls, one inputs array, read at this head), so the calendar tag's row describes a read the same renderer makes. Each description clause is held by a member-pin row except the openNewTab overlay clause carried at ③.5.
  4. Parity ledger — RIGHT. Two OWED entries struck; unpublishedKeys cap 5 to 3; the objectui#8176 backlog ceiling 2 to 0 in all three assertions with the backlog asserted empty BY NAME; owner total for this card 2 to 0; two MEMBER_PINS entries (objectui#8212's obligation); objectui#11168's entries untouched.
  5. calendarUnionReads-8651 — RIGHT. Its one ledger entry struck; the UNDECLARED row inverted into READ and DECLARED and not-ledgered, so it fails in both directions.
  6. Renderers — RIGHT, no behaviour change. The calendar's (schema as any).navigation cast is gone; the board's change is a comment. Both hand the key to useNavigationOverlay; the absent-key { mode: 'drawer' } stays a renderer default.
  7. Changeset 7322 dated note — RIGHT. Append-only, frontmatter byte-identical; Changeset Overwrite Report success on this head.
  8. Docs face (round 2, five files) — RIGHT; every sentence traced. The brief's test: each docs sentence held by the declared type or by a member pin in the diff. Traced clause by clause:
    • "the spec's NavigationConfig by reference, ViewNavigationConfig in @object-ui/types, the type ObjectGridSchema.navigation uses" — held by the type: ViewNavigationConfig = NavigationConfig, and ObjectGridSchema's span at this head carries navigation?: ViewNavigationConfig (no other export opens between the grid interface's first line and that member).
    • "mode (page, drawer, modal, split, popover, new_window or none)" — held by the spec: NavigationModeSchema at 0f6dcac5e9 is exactly that seven-value enum, in that order.
    • "with size, openNewTab and preventNavigation" — held by the spec's NavigationConfigSchema members. The deprecated width and the retired view tombstone are not named; an omission, not a false claim, and both are pinned in the types test (width parses, view is refused).
    • "With the key absent a click opens the record in a drawer" (all five files) — held by the LIT CONTROL row of each member pin.
    • "a click handler from a parent view outranks the whole key" (kanban: README, mdx) — held by the kanban pin's parent-handler row (overlay mode, onRowClick wins) and by the board's externalClick = onRowClick ?? onCardClick handed to the hook unconditionally.
    • "An overlay mode keeps the click from a parent view's onRowClick / onEventClick; any other mode hands it to them" (calendar: README, mdx) — held by the calendar pin's two precedence rows (drawer keeps; page hands to both), and the generalisation to "any other mode" is held by the renderer's branch shape: navIsOverlay is the four-value test and onRowClick: navIsOverlay ? undefined : onRowClick is the only switch, so there is no third branch for the sentence to miss.
    • "page — and a block written without mode, which takes the spec's page default — opens nothing on a board/calendar no parent view navigates for (objectui#11293)" — held by the two page-warning rows in each pin; the spec default mode: 'page' read at 0f6dcac5e9; objectui#11293 exists, open, titled as exactly this finding.
    • plugin-calendar.mdx's pseudo-interface line navigation?: ViewNavigationConfig and plugin-kanban README's "groupBy, columns, navigation and className are optional" — held by the TS member's optionality.
    • The two README typed examples (navigation: { mode: 'modal' } under ObjectCalendarSchema / ObjectKanbanSchema) compile against the built types: Doc Snippet Type Check and README Export Check are success on this head.
    • schema-reference.md's corrected sentence (the one scope growth): "cardTitle (objectui#9606) and navigation (objectui#8652) are declared on this face; swimlaneField and grouping are still undeclared. The renderer reads those two" — measured here on the full ObjectKanbanSchema TS span and the zod arm: cardTitle and navigation present on both faces (the TS docblock names objectui#9606), swimlaneField and grouping absent from both; firing control, grouping IS declared on three other interfaces in the same file, so the absence is a reading. ObjectKanban.tsx reads schema.swimlaneField || schema.grouping?.fields?.[0]?.field. Every clause holds; the old sentence was false on cardTitle already, and rewriting it for navigation alone would have left that half standing.
    • Stale-sentence sweep, clean: every navigation line under content/docs/** and every package README at this head was listed; the only item-click navigation rows outside the five edited files are the grid's own (plugin-grid.mdx, plugin-grid/README.md), which describe the grid. No sentence anywhere says the board or calendar lacks the key.
    • No version literal and no cross-file path:line is added in the five docs files (AGENTS.md [WIP] Update documentation for project #11; Line Citation Gate success).
  9. Not touched, rightly: object-timeline (objectui#8654), the ObjectFormSchema region (objectui#10859 batch 4), the view-level KanbanConfig, no governed surface (Governed Surface Queue Guard success), no renderer change in round 2.

② Semver level

.changeset/8652-kanban-calendar-navigation.md declares @object-ui/types, @object-ui/plugin-kanban and @object-ui/plugin-calendar at minor — matching what the diff publishes: two new optional members on two published TS interfaces and two zod arms (a widening of the declared face, and a narrowing of the accept-set on the key's value, which the body states in as many words), plus two registry inputs rows. Round 2 adds only *.md / *.mdx — excluded from the presence rule by name — so no further declaration is owed and none was added. No major (version-alignment policy; Changeset Bump Policy success). apps/console changed only in a test file; Changeset Declaration, Changeset Fixed Group Check, Changeset Claim Re-read and Changeset Overwrite Report are success on this head. The PR body carries Clause-②: yes, equal to the claim 5920939737 and to the seat's ACCEPT; this record is the at-tier artefact that line owes on the landing head.

③ Boundary flags

Round-2 open_questions: [], two round-2 deviations, and the earlier record's four follow-ups, each answered or escalated:

  1. AGENTS.md Add automated testing infrastructure and CI/CD workflows #2 (docs-driven), the earlier record's ③-3 — ANSWERED. Both package READMEs, both plugin docs pages and the ObjectKanbanSchema table of schema-reference.md now carry navigation, each held per ①.8. On the rule's literal content/docs/guide/*.md: the dev's deviation says the guide holds no block-props surface for either block, and that is a reading — the four guide pages naming object-kanban / object-calendar at this head are a registry example (architecture-overview), a data-binding capability table (data-source), a usage line (react-pages) and a troubleshooting symptom; none is a props table a row could join. The props surface for blocks in this repo is content/docs/plugins/*.mdx (the grid's navigation row lives there, the lit control), which is where the row went. Rule met in substance; no guide row is owed.
  2. schema-reference cardTitle correction, round-2 deviation — ANSWERED. One sentence this round had to edit anyway; its four claims measured true at this head (①.8). Not a sweep.
  3. Timeline (the earlier record's ③-5) — ESCALATED, unchanged. ObjectTimelinePropsSchema at 0f6dcac5e9 declares navigation: NavigationConfigSchema.optional(); the seat owned the correction in its ACCEPT and the pointer on objectui#8654 is the seat's write, outside this diff. Nothing on this PR turns on it.
  4. page opens nothing (the earlier record's ③-6) — ANSWERED. Filed as objectui#11293 (open, title matches the finding); the five docs files and both input descriptions cite it, and the two page-warning rows per pin hold the sentence.
  5. openNewTab outranks an overlay mode (the earlier record's ③-7) — ANSWERED as the seat disposed it, residue noted. The seat ruled it Acceptance notes, hook-wide, no measured reach. The registry descriptions still say the flag "outranks the mode" with only the page case pinned; the round-2 docs deliberately do NOT repeat that clause (they list the members and pin-held precedence only), so no docs sentence rests on it. Non-blocking, as the earlier record said; the one-row ask stands for whoever next touches the descriptions.
  6. PR body stale at this head — ESCALATED to the seat, before ready. The body's Acceptance note still reads that the two .mdx pages and the READMEs "do not document navigation" and are "left to the seat"; this head falsifies it. The dev's report carries a ready pr_body_line and made no body write (0 REST writes, write-pace). The seat appends it when it posts the round-2 report. The body is not a published face, so this does not move the verdict.
  7. Bookkeeping, the seat's: needs:contract-review sits on the PR (not the card); on adoption of this record it is the seat's to clear before enqueue. The round-2 os-dev-report is not on the card yet (post-stamped exit 10); the seat posts it from the file it named.
  8. Check-runs on the head, recorded not awaited (read at 2026-10-01T00:34Z): 42 of 42 returned — 30 success, 3 skipped (the coverage-shard matrix placeholder, Test (coverage), dependabot: condition skips), 9 in progress: Type Check, Spec Main Shape Gate, Test (shard 1/8) through Test (shard 7/8). Success includes Test (shard 8/8), Test (dist pins), Lint, Build & E2E, Build Docs, Doc Snippet Type Check, Doc Component Type Check, Doc Example Id Check, Doc Fence Language Check, Internal Docs Link Check, README Export Check, Line Citation Gate, Control Byte Scan, Governed Surface Queue Guard and every changeset check. No failure on the head. The verdict below is on the contract; ready and enqueue still wait on the nine, which is the seat's gate, not this record's.

Implemented-by: claude/issue-8652-kanban-navigation-family
Reviewed-by: session_01VhxTqosz7wn54ahqyxgERT

VERDICT: PASS

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 1, 2026 00:40
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 1, 2026 00:40
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 1, 2026
Merged via the queue into main with commit d79f525 Oct 1, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-8652-kanban-navigation-family branch October 1, 2026 00:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants