Skip to content

refactor(plugin-view,plugin-grid,types): retire table.defaultSort / object-grid defaultSort (ADR-0049) - #10533

Merged
objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-5861-retire-table-defaultsort
Sep 25, 2026
Merged

objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-5861-retire-table-defaultsort

Conversation

@objectstack-fleet

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

Copy link
Copy Markdown
Contributor

Fixes #5861
Clause-②: yes — this removes the last runtime reads and the declared docs of a key the installed @objectstack/spec 17.4.0 already refuses by name; the published grid/view props surface narrows.

What this does

ADR-0049 enforce-or-remove, remove arm, for object-grid's defaultSort and object-view's table.defaultSort — the "C half" of the maintainer's 2026-08-22 ruling on objectui#4869 (「接受所有」), restart condition measured by triage comment 5808485875.

Every reader is removed in one change, so no path honours the key while another ignores it:

Reader Before After
ObjectGrid fetch path third arm else if (schema.defaultSort) lowered it to $orderby chain reads sort only
ObjectGrid header arrows parseSchemaSort(schemaSort ?? [schema.defaultSort]) parseSchemaSort(schemaSort)
ObjectView non-grid fetch fourth branch lowered table.defaultSort into the sink chain ends at table.sort
ObjectView grid forwarding defaultSort: schema.table?.defaultSort not forwarded
ObjectView delegated renderListView mergedSort wrapped table.defaultSort into an array chain ends at table.sort
plugin-grid registration sort input described defaultSort as its fallback description says it is retired

H1 — the TypeScript declaration goes too, as a tombstone (decided and measured)

ObjectGridSchema.defaultSort becomes defaultSort?: never and the zod mirror member becomes retirementTombstone(...), in lockstep. Not a deletion: ObjectGridSchema extends BaseSchema, whose [key: string]: any absorbs an undeclared key as any, and the mirror's .passthrough() keeps it unexamined, so deleting would let the retired spelling type-check and parse green and do nothing. This is the package's existing convention (ObjectViewSchema.viewTabBar, objectui#7779). Measured on the rebuilt dist: a downstream ObjectGridSchema literal carrying defaultSort fails tsc in plugin-view with TS2322 (reverse check below). Only the defaultSort regions of objectql.ts / objectql.zod.ts were touched; ObjectGridSlotKey keeps listing the key because the member is still declared.

H2 — no live producer (measured, with lit controls)

  • Installed spec 17.4.0: ObjectGridPropsSchema.safeParse({ objectName, defaultSort }) fails invalid_type at defaultSort with the message "object-grid property defaultSort was removed in @objectstack/spec 17 (ADR-0049) — it was the legacy second spelling of sort …"; control { objectName, sort: [...] } parses green.
  • No non-test source outside the edited files reads the key (git grep defaultSort -- packages/ — the remaining hits are plugin-detail's own RelatedList defaultSort prop, a different carrier fed from schema.sort, plus CHANGELOGs). normalize-list-view never mentions it.
  • Authored occurrences — objectui: examples/ 0 files, e2e/ 0, apps/ 1 (the registry parity test's comments, not authoring), content/ 2 (the two pages tombstoned here). objectstack origin/main: examples/ 0, apps/ 0, packages/qa/ 0. Lit control, identical method, searchableFields: objectui examples/ 4 files, content/ 5; objectstack examples/ 2, packages/qa/ 1.
  • ⚠️ One authored occurrence the earlier reads did not flag: the ObjectGridSchema JSON example in content/docs/api/schema-reference.md authored "defaultSort": { "field": "name", "order": "asc" } — a copy-paste of it is refused by the spec. It now authors "sort": [{ "field": "name", "order": "asc" }].

H3 — pins, red on the base and green on the head

The flipped cells were rewritten, not deleted: each now asserts the key is inert on its path, beside a canonical sort control on the same path in the same run.

Red leg: the five source files were put back to the base 59636b3a6 under the committed tests, with a trap restore (blob hashes re-checked against HEAD afterwards, git diff HEAD empty): 19 failed | 97 passed (116), 8 of 9 files red. The only all-green file is gridRetiredStringSort-8767.test.tsx, whose cell was only re-commented. Green leg on the head: 116 passed (116), 9 files.

Flipped or new, each red on base:

  • plugin-view ObjectView.canonicalTableKeys.test.tsx — grid path: no longer forwards a retired table.defaultSort — and does not rescue it into sort; puts the canonical value in the canonical slot… (legacy slot now undefined); keeps the named view sort in force, and a retired table.defaultSort beside it is not forwarded. Non-grid: a retired table.defaultSort alone orders NOTHING. Delegated: hands over NO sort for a retired table.defaultSort alone.
  • plugin-view ObjectView.sortSink.test.tsx — sends no $orderby at all…, a descending legacy default is inert too…, and the tail of keeps the sink STRICT… (the sink-strictness half is unchanged).
  • plugin-view ObjectView.filterSources.test.tsx — the three objectui#6235 wrap cells, flipped.
  • plugin-view ObjectView.namedViewSortArity.test.tsx — through the REAL ObjectGrid: a retired table.defaultSort sorts NOTHING on the real grid path — no $orderby, no arrow, plus a new canonical table.sort control cell.
  • plugin-grid gridArrayArmOrderby-8973.test.tsx — the legacy-arm section, flipped (fully-specified, and order omitted, now send no $orderby).
  • plugin-grid gridDefaultFiltersLowering.test.tsx — a retired defaultSort reaches neither $orderby nor $filter.
  • plugin-grid serverSorting.test.tsx — new: a retired defaultSort lights NO arrow and sends NO $orderby, with a sortable-chrome non-vacuity check.
  • types object-grid-default-sort-tombstone-5861.test.ts — new: refused by name (invalid_type at defaultSort), lit control (unknown key green), remedy text, describe equals message, canonical sort green, upstream re-derivation from the installed pin, and the @ts-expect-error on the ?: never twin (compiled by tsconfig.test.json; --listFiles includes the file).

Canonical sort is asserted on all three ObjectView paths and on bare ObjectGrid in the same runs.

Review rework (head 28b1a4d32)

The contract review at f40819d61 (comment 5828759786) returned FAIL on two items and one nit. All three are addressed in 28b1a4d32:

  1. Required Test was red on scripts/__tests__/doc-version-claims.test.ts ("records every version literal on the scanned surfaces"). The doc tombstones had added unregistered @objectstack/spec version literals in plugin-view.mdx and plugin-view/README.md, plus a third in schema-reference.md split across a line break, which the gate cannot see. The gate's preferred remedy is applied to all three: the literal is deleted, and each page now says the installed protocol refuses the key by name. No KNOWN_CLAIMS entry is added. Reproduced red locally first (Tests 1 failed | 28 passed (29), naming both visible sites), then green (29 passed (29)). No line this PR adds under content/ or packages/plugin-view/README.md carries a version-shaped token.

  2. Pending changesets that would publish "keeps working" beside "no longer read". Following the precedent of PRs docs(changeset): correct six pending changesets whose surrounding claims a later merge falsified (objectui#9065) #9139, docs(changeset): date the two rotted present-tense declaration claims in the kanban pending entries #9723 and docs(changeset,plugin-detail): date the two rotted release-note sentences and correct the born-false parity-test claim (objectui#9637) #9734, the falsified sentence in each is put in the past tense for its own change ("at this change …"), and each now names objectui#5861: four carry a dated note, and 5293 carries an inline citation in docs(changeset): correct six pending changesets whose surrounding claims a later merge falsified (objectui#9065) #9139's form:

    • objectview-sort-sink-4869.md: "both spellings of the pair keep working", and the table.defaultSort sink chain;
    • 6235-mergedsort-wrap.md: the delegated-slot wrap;
    • 8973-grid-orderby-normalize.md: the legacy arm "is fixed with it";
    • grid-default-filters-lowering-4082.md: the legacy leg "needs no change";
    • 5293-view-sort-order-spelling.md: ObjectGridSchema.defaultSort cited as a live order spelling.

    A re-grep of the pending set finds three more defaultSort mentions, all still true and left alone. 7122 says the spec made the key a D2 tombstone. 8767 quotes the spec's retirement text. 6697 concerns RelatedList's own defaultSortKey, a different carrier. The retirement changeset's "supersedes" paragraph now names all five entries.

  3. Nit. The objectui#5270 comment block in ObjectView.tsx no longer quotes the retired defaultSort header and fetch readers in the present tense.

The branch was not merged with main. There was no conflict and CI did not need it; the review reads behind, not dirty.

Gates (code commit 43ab1fd43; rework head 28b1a4d32; full-suite runs at f40819d61, and plugin-view re-run at 28b1a4d32)

  • Build closure: turbo run build --filter='@object-ui/plugin-view^...' --concurrency=2: 15 successful, 15 total; rebuilt packages/types/dist/objectql.d.ts carries defaultSort?: never.
  • pnpm --filter @object-ui/types type-check exit 0 (script echoed @object-ui/types@17.6.0 type-check); @object-ui/plugin-grid exit 0; @object-ui/plugin-view exit 0.
  • Reverse type check through the rebuilt .d.ts: injecting defaultSort: { field: "name", order: "asc" } into ObjectView's gridSchema literal makes plugin-view tsc --noEmit fail with TS2322 … Types of property 'defaultSort' are incompatible … not assignable to type 'undefined'; restored, blob equals HEAD. (A first attempt was a no-op: ablation-replace refused because the replacement contained its own anchor. It changed nothing and ran nothing.)
  • Root-form vitest: packages/types/ 233 files, 5166 tests passed; packages/plugin-grid/ 156 files, 1487 tests passed; packages/plugin-view/ 48 files, 444 tests passed (re-run at 28b1a4d32 together with doc-version-claims: 49 files, 473 tests passed; plugin-view type-check exit 0 again, closure build 15/15 cached); apps/console/src/__tests__/registry-inputs-spec-parity.test.ts (it reads the plugin-grid registration inputs) 199 tests passed.
  • node scripts/check-changeset-presence.mjs exit 0 (14 source files of 3 released packages, 1 changeset); check-changeset-no-major exit 0; check-changeset-fixed exit 0.
  • check:new-line-citations: VERDICT new-cross-file-line-citations: 0 new citation(s); check:control-bytes OK.
  • Doc gates: check-doc-links exit 0; check:doc-types exit 0; check:doc-fences exit 0; check:doc-example-ids exit 0; check-prompt-component-keys exit 0; check-doc-expression-carriage exit 0 (report-only; its one schema-reference.md site, action.condition, predates this branch); check-changeset-claims exit 0 (report-only); check:pending-changeset-literals exit 0.
  • eslint, narrowed to the 14 changed .ts/.tsx files: 14 files in the JSON report, 0 errors. Per-file warnings are equal to the base except three test files (+1, +1, +2 no-explicit-any from as any fixtures, matching those files' existing style). eslint.config.js has no type-aware linting (parserOptions.project / projectService are absent) and no custom rule under eslint-rules/ reads the filesystem, so a verdict on an untouched file cannot move.
  • Governed surface: check-governed-queue-guard --test over all 18 paths says NOT GOVERNED.

Registries and docs

  • Touched: @object-ui/types (ObjectGridSchema member and its zod mirror), the plugin-grid registration (sort description and docblock), content/docs/plugins/plugin-view.mdx, content/docs/api/schema-reference.md, packages/plugin-view/README.md, and a changeset (minor on types / plugin-grid / plugin-view, never major).
  • Not touched, on purpose: the console registry parity ledger apps/console/src/__tests__/registry-inputs-spec-parity.test.ts. Its object-grid.defaultSort carve-out entry was already harvested when spec 17.3.0 tombstoned the key; it keeps only a comment. docs/adr/** is not needed, because no ADR lists the key.
  • schema-reference.md: the CRUDSchema defaultSort / defaultSortOrder sentence is untouched. Only the adjoining ObjectGridSchema sentence ("that key is unaffected"), which this change makes false, was rewritten.

Acceptance notes


Generated by Claude Code

…bject-grid defaultSort reads (ADR-0049)

@objectstack/spec 17.3.0 turned ObjectGridProps.defaultSort into a
retired-key tombstone that the protocol refuses by name. Remove every
renderer read at once: ObjectGrid's fetch arm and header reader, and
ObjectView's non-grid fetch, grid forwarding and delegated mergedSort.
The TypeScript twin becomes a `?: never` tombstone and the zod mirror a
retirementTombstone(), in lockstep, so an authored value is refused by
name instead of absorbed by BaseSchema's index signature.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN
…to assert the retired key is inert

Every cell that pinned table.defaultSort / object-grid defaultSort as a
working alias is rewritten, not deleted: each now asserts the key reaches
no query, slot or header arrow on its path, beside a canonical sort control
on the same path. A new types pin covers the zod tombstone (refused by name,
lit control, remedy, upstream re-derivation) and the `?: never` twin.

Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN
Co-authored-by: Claude <noreply@anthropic.com>
…ect-grid defaultSort, add changeset

The two doc pages and the plugin-view README stop listing defaultSort as a
forwarded / working alias and carry a retirement note with the migration
(rename to sort, wrap in an array). The ObjectGridSchema example in
schema-reference.md authored the retired key; it now authors sort. The
CRUDSchema.defaultSort sentence is untouched; only the ObjectGridSchema
claim beside it changed. Line-address citations in the touched
plugin-view.mdx paragraphs are re-cited by content (AGENTS.md #11).

Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation package: types plugin tests labels Sep 25, 2026
@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 50 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/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/4730-retire-dead-locale-key-batch.md

  • names ObjectGrid.tsx → packages/plugin-grid/src/ObjectGrid.tsx — edited by this change

    • Superseded twin vocabularies. cellRender.* and rowAction.* duplicated a grid.* vocabulary that won. RowActionMenu.tsx is fully i18n-wired and reads grid.openMenu / grid.edit / grid.delete; ObjectGrid.tsx reads grid.empty / grid.yes / grid.no / grid.systemFields. The twins had no reader on either side. - Labels that outlived their control. calendar.agenda labelled a view mode objectui#5740 retired from CalendarViewMode (now 'month' | 'week' | 'day'). home.quickActions.createApp*, layout.systemNav.createApp, actionDialog.defaultActionTitle / .ok and grid.bulk.selectPlaceholder sit in namespaces whose consumers are live and wired but demonstrably read other siblings. - Surfaces that left the product. map.* is the strongest form: @object-ui/plugin-map declares no @object-ui/i18n dependency and contains no t() call at all, so it cannot consume a locale string. home.stats.* and recordDetail.viewersTooltip name surfaces nothing renders.

.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/6597-retire-fieldmeta-referenceto.md

  • names plugin-grid/src/ObjectGrid.tsx → packages/plugin-grid/src/ObjectGrid.tsx — edited by this change

    No authoring story survived the search either. ObjectGrid's own relational-meta pass-through (applyRelationalMeta, plugin-grid/src/ObjectGrid.tsx) copies reference_to / reference / display_field / etc. from the SCHEMA field def only, at all three of its call sites — never from an authored column override. No doc, example, or fixture in this repo shows a table column pinning a lookup's target away from what its schema field already says. Under the maintainer's standing startup-stage rule (2026-08-27: deprecated/alias spellings retire immediately, no transition windows), no measured demand selects withdraw.

.changeset/6726-find-envelope-records-arms.md

  • names plugin-view/src/ObjectView.tsx → packages/plugin-view/src/ObjectView.tsx — edited by this change

    | module | what it does | | --- | --- | | components/src/hooks/related-count-store.ts | related-list tab badge count | | components/src/renderers/basic/data-list.tsx | element:repeater rows | | components/src/renderers/basic/elements.tsx | element:number client-side aggregate | | components/src/renderers/basic/record-picker.tsx | element:record_picker options | | plugin-detail/src/renderers/record-activity.tsx | record:activity self-fetch | | plugin-detail/src/renderers/record-history.tsx | record:history self-fetch | | plugin-view/src/ObjectView.tsx | non-grid (kanban / calendar / gallery / timeline) fetch |

.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 objectui#6939 / 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/7070-no-invented-gantt-date-fields.md

  • names plugin-view/src/ObjectView.tsx → packages/plugin-view/src/ObjectView.tsx — edited by this change

    • app-shell/src/views/ObjectView.tsx — the console object page. The inline branch becomes ganttViewOptions, the sibling of calendarViewOptions and timelineViewOptions: the declared block spread whole, title floored at 'name', no date field invented. - plugin-list/src/ListView.tsx — the render branch AND the capability gate. - plugin-view/src/ObjectView.tsx — generateViewSchema, the authored object-view element route, which bypasses ListView entirely.

.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/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.

.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/7499-gantt-non-axis-floors-omitted.md

  • names plugin-view/src/ObjectView.tsx → packages/plugin-view/src/ObjectView.tsx — edited by this change

    • plugin-list/src/ListView.tsx — the object-gantt render branch. - plugin-view/src/ObjectView.tsx — generateViewSchema, the authored object-view element route, which bypasses ListView entirely.

.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 (objectui#6939, 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/7762-object-grid-export-options-bare-array-refusal.md

  • names ObjectGrid.tsx → packages/plugin-grid/src/ObjectGrid.tsx — edited by this change

    What was measured, on this branch's base. The mirror declared NO exportOptions member at all, and BaseSchema is .passthrough(), so ObjectGridSchema.safeParse({ type: 'object-grid', objectName: 'accounts', exportOptions: ['csv', 'xlsx'] }) returned success: true with the array back VERBATIM — as did { formats: ['csv', 'pdf'], compression: 'gzip' }. Nothing on the render path parses, and ObjectGrid.tsx reads schema.exportOptions?.formats and only that, so the authored array then lost SILENTLY to the ['csv', 'json'] default: the useEffect that warns about dropped formats reads .formats too and returns early when it is absent, while !!schema.exportOptions kept the export button on screen. An author declared ['csv', 'xlsx'] and got csv/json with no error, no warning and no console line. The two authoring faces disagreed in the direction opposite to objectui#6956's: the TypeScript interface already declared the object form only, so TS refused what zod admitted.

.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 (objectui#7804, 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/8221-retire-legacy-string-sort.md

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

    Docs teach the array only: content/docs/plugins/plugin-map.mdx, content/docs/plugins/plugin-view.mdx and packages/plugin-view/README.md.

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

    Docs teach the array only: content/docs/plugins/plugin-map.mdx, content/docs/plugins/plugin-view.mdx and packages/plugin-view/README.md.

.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 objectui#7088 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, ObjectGridSlotKey / ObjectFormSlotKey pin it, SchemaBuilder.testId() writes it, and ADR-0054 C4 — shipped — reads "the renderer emits data-testid … derived from metadata".

.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.

  • names packages/plugin-view/src/ObjectView.tsx → packages/plugin-view/src/ObjectView.tsx — 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/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.

.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/9722-bulk-executor-datasource-face.md

  • names ObjectGrid.tsx → packages/plugin-grid/src/ObjectGrid.tsx — edited by this change

    • ObjectGrid.tsx → RecordDetailPanel: removing it type-checks GREEN. It was paying for nothing — both sides already declare the same DataSource | undefined from @object-ui/types. Removed outright. - ObjectGrid.tsx → BulkActionDialog: removing it reddens, and it was paying for TWO things at once — the optional-vs-required arm (the grid declares dataSource?: DataSource, the dialog demands one) AND the bulk-door contravariance. Only the first still needs erasing, so it is now a non-null assertion: today's runtime behaviour is preserved exactly, and any future drift of the face reddens at that site instead of passing silently.

.changeset/9853-grid-non-positive-page-size.md

  • names ObjectGrid.tsx → packages/plugin-grid/src/ObjectGrid.tsx — edited by this change

    Refuse a non-positive pageSize at all three of ObjectGrid.tsx's read points, instead of giving two different answers for one authored value (objectui#9853).

.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 packages/plugin-view/src/ObjectView.tsx → packages/plugin-view/src/ObjectView.tsx — edited by this change

    What was measured. Every reading was taken on the object-view node renderer (packages/plugin-view/src/ObjectView.tsx, registered by plugin-view/src/index.tsx) with schema.objectName / schema.layout as the positive controls of the same schema.KEY query, so each zero is a reading; the repo-wide census of viewTabBar finds the key in no source file outside @object-ui/types (two doc tables listed it as authorable and are corrected here). The spec side was read through the installed pin (@objectstack/spec@17.2.0, ui entry, 117 exported object schemas walked; control keys objectName / columns / navigation / listViews hit): the three spec-modelled keys are optional slots on ListViewSchema and ObjectListViewSchema; the six local keys have no spec slot anywhere.

  • 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 82bdd3ac9 (merge-base with origin/main): 17 file(s) changed outside .changeset/, read against 1423 pending declaration(s) that publish a body (2005 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3044.6 KB 3104.5 KB
Main entry chunk (gzip) 147.8 KB 350 KB
Entry file index-DmB6OfoS.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.68KB 6.20KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 544.97KB 130.34KB
core (index.js) 9.22KB 3.71KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 223.86KB 62.25KB
fields (index.js) 256.68KB 65.01KB
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 (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.28KB 11.09KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 51.38KB 14.60KB
plugin-charts (index.js) 74.95KB 20.88KB
plugin-chatbot (index.js) 198.36KB 47.20KB
plugin-dashboard (index.js) 133.59KB 35.39KB
plugin-designer (index.js) 216.25KB 44.39KB
plugin-detail (index.js) 232.25KB 61.40KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 146.50KB 37.51KB
plugin-gantt (index.js) 169.37KB 41.83KB
plugin-grid (index.js) 215.37KB 58.92KB
plugin-kanban (index.js) 49.30KB 15.39KB
plugin-list (index.js) 114.55KB 28.29KB
plugin-map (index.js) 23.82KB 7.42KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.55KB 11.99KB
plugin-timeline (index.js) 30.64KB 8.94KB
plugin-tree (index.js) 10.52KB 3.69KB
plugin-view (index.js) 87.85KB 21.96KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 114.58KB 37.60KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.78KB 2.56KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.20KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 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) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
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: f40819d611423af7917e1a05750b1522562d2a3b

① Derived judgments

  • Head verified. git rev-parse refs/review/pr-10533 = f40819d61… (matches). Merge-base 59636b3a6; 4 commits; PR is draft and mergeable_state: behind (main now 6881e9e47).
  • Every runtime read is gone. git grep -n -w defaultSort refs/review/pr-10533 -- packages/ | grep /src/ | grep -v __tests__ = 26 lines, 0 readers: plugin-detail RelatedList defaultSort prop (7 lines; a different carrier, fed from schema.sort in record-related-list.tsx), comments only in ObjectGrid.tsx (2), plugin-grid/index.tsx docblock + sort description (3), ObjectView.tsx comments (8), types tombstone defaultSort?: never + JSDoc (2) + ObjectGridSlotKey member (1, type-level), zod tombstone (2), one app-shell test comment (RelatedList carrier). table\??\.defaultSort repo-wide: comments, tests, doc tombstones, changesets, CHANGELOG only. apps/: 5 lines, all comments in registry-inputs-spec-parity.test.ts. examples/ 0, e2e/ 0, content/ 10 lines in the two tombstoned pages only. Lit control git grep -l -w searchableFields -- examples/ apps/ content/ = 10 files (incl. examples/schema-catalog/src/schemas/plugin-grid/object-grid-columns.json). No wholesale ...schema.table spread in plugin-view/app-shell (grep 0); app-shell ObjectView.tsx (normalize-list-view host) has 0 defaultSort. CRUDSchema prose (schema-reference.md:590, defaultSort/defaultSortOrder … CRUDSchema's own) is a context line, byte-identical base to head; only the adjoining ObjectGridSchema sentence (592-594) was rewritten.
  • No test deleted. it(/test( cells base to head: gridArrayArmOrderby-8973 15/15, gridDefaultFiltersLowering 15/15, gridRetiredStringSort-8767 6/6, serverSorting 12/13, canonicalTableKeys 27/27, filterSources 13/13, namedViewSortArity 4/5, sortSink 12/12, new types pin 0/10. Zero drops. Canonical-sort controls present on all paths: non-grid (sortSink inline control + canonicalTableKeys orders by a canonical table.sort), grid forwarding (canonicalTableKeys inline control; namedViewSortArity new CONTROL — the canonical table.sort still sorts on the same real grid path through real ObjectGrid), delegated (filterSources + canonicalTableKeys hands over a canonical table.sort…), ObjectGrid direct (gridArrayArmOrderby name desc control, gridDefaultFiltersLowering control, serverSorting shows the view's declared sort).
  • Tombstone is consistent with the discriminator (complex.ts KanbanColumn.color: tombstone only on a surviving carrier, when it steers to a named live replacement key or docs taught the key as working). ObjectGridSchema survives; prong 1: sort?: SortConfig[] (objectql.ts:757, zod z.array(SortConfigSchema)); prong 2: base plugin-view.mdx table row listed defaultSort as "still works" and schema-reference.md:748 example authored it. Precedent viewTabBar?: never exists (objectql.ts:2162). Scratch harness (tsx over the PR's own packages/types/src/zod/objectql.zod.ts, zod 4.6.5, spec 17.4.0): well-formed {field,order}, string, array, {}, null all FAIL invalid_type at path defaultSort with "RETIRED (objectui#5861, ADR-0049) … Rename the key to sort and wrap the value in an array: sort: [{ field, order }]"; omitted/explicit-undefined SUCCESS; undeclared zzzUnknown SUCCESS and retained (passthrough); sort array SUCCESS; describe === message true; ObjectViewSchema.table.defaultSort also refused at table.defaultSort (the changeset's "ObjectViewSchema.table inherits the never member" is true: table?: Partial<Pick<ObjectGridSchema, ObjectGridSlotKey>>). Remedy text accurate.
  • H2 holds. Harness: spec 17.4.0 and 17.3.0 refuse defaultSort (invalid_type, "removed in @objectstack/spec 17 (ADR-0049)"); 17.2.0 accepts it, so the "17.3.0" sentence is true. Authored occurrences outside the tombstoned docs: 0.
  • Docs true. Content citations verified at head: if (!dataSource || !schema.objectName) return; ×2 in ObjectView.tsx; meta?.skipFallback ×2 in Registry.ts; const gridSchema: ObjectGridSchema = useMemo ×1; mergedFilters/mergedSort ×2. Line Citation Gate success. README mirrors the mdx. JSON example now "sort": [{ "field": "name", "order": "asc" }] (valid).
  • Serial constraint clear. PR 10278 ObjectGrid.tsx hunks at base lines 45, 1146-1169, 1334, 1771, 2103-2110 ($top/$skip), 2349 (effect deps), 4419, 4494, 5507; this PR's hunks at 2217-2234, 4536-4546, 4557-4565. Disjoint; the fetch effect's dependency list is untouched here.
  • Nit: ObjectView.tsx objectui#5270 comment block (head ~1997-2007) still quotes parseSchemaSort(schemaSort ?? [schema.defaultSort]) and the fetch reader in present tense; both readers no longer exist.

② Semver level

③ Boundary flags

  • CI: red on a required check. All 43 check-runs on the head completed: 38 success, 3 skipped, 2 failure: Test (shard 8/8) and its rollup Test, and Test is a required status check on main (rules API: Lint, Type Check, Build & E2E, Build Docs, Changeset Declaration, Test). Annotation: scripts/__tests__/doc-version-claims.test.ts:2271 "records every version literal on the scanned surfaces" — two unregistered literals this PR added: content/docs/plugins/plugin-view.mdx:140 "@objectstack/spec 17.3.0" and packages/plugin-view/README.md:209 (same). Remedy per the ratchet: delete the literal and point at the truth, or add a KNOWN_CLAIMS entry (precedent: content/docs/guide/layout.md @objectstack/spec 17.0.0, kind unanchored, a tombstone quote). A third instance the gate cannot see: schema-reference.md:787-788 splits "@objectstack/spec" and "17.3.0" across a line break, escaping the line-based FIRST_PARTY + SEP + VERSION recogniser; fix it the same way. The PR body left repo-wide pnpm test to CI; CI caught it.
  • Class-a finding is real at source: schema-reference.md:775 | sort | string \| SortConfig[] | vs objectql.ts:757 sort?: SortConfig[] and zod z.array(SortConfigSchema) "legacy string clause is retired — objectui#8221" (harness: sort: 'name asc' FAIL "expected array, received string"); spec 17.4.0 accepts the string (harness SUCCESS). Out of scope here; no carrier.
  • Trailer: commit 9f3f52823 carries Co-Authored-By: Claude Opus 5.5; repo allows squash merge only with squash_merge_commit_title=PR_TITLE, squash_merge_commit_message=PR_BODY; the PR body carries no model-named trailer, so it never reaches main. AGENTS.md has no trailer rule (grep 0). Not a blocker.
  • Branch is behind main; merge-queue update needed, not a finding.

Implemented-by: claude/issue-5861-retire-table-defaultsort
Reviewed-by: session_014mXUNuFomfj24w7s1pZzhN

VERDICT: FAIL — the required Test check is red on the head because this PR's own doc tombstones add unregistered @objectstack/spec 17.3.0 literals (plugin-view.mdx:140, plugin-view/README.md:209, plus the gate-invisible split at schema-reference.md:787-788); and the changeset's "supersedes" omits #4082 (and #5293) while five pending sentences would publish "keeps working" beside "no longer read" in the same release, which this repo's precedent reconciles in place. Code, tests, tombstone and semver level are otherwise sound.


Generated by Claude Code

… date the pending defaultSort claims this retirement falsifies

Review rework for objectui#5861.

- The three doc tombstones stop naming a spec version (doc-version-claims
  ratchet): they state that the installed protocol refuses the key by name.
- Five pending changesets that will publish in the same release describe
  the legacy key as honoured (objectui#4869, #6235, #8973, the #4082 grid
  filter-lowering entry, #5293). Each falsified sentence is put in the past
  tense for its own change and gains a dated note naming objectui#5861, the
  form PRs #9139 / #9723 / #9734 used. The retirement changeset names all
  five.
- ObjectView's objectui#5270 comment no longer quotes the retired
  defaultSort readers in the present tense.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3045.8 KB 3104.5 KB
Main entry chunk (gzip) 147.7 KB 350 KB
Entry file index-CdMSaCmM.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.68KB 6.20KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 544.97KB 130.34KB
core (index.js) 9.22KB 3.71KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 223.86KB 62.25KB
fields (index.js) 257.02KB 65.07KB
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 (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.28KB 11.09KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 51.38KB 14.60KB
plugin-charts (index.js) 74.95KB 20.88KB
plugin-chatbot (index.js) 198.36KB 47.20KB
plugin-dashboard (index.js) 133.59KB 35.39KB
plugin-designer (index.js) 216.25KB 44.39KB
plugin-detail (index.js) 232.25KB 61.40KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 146.50KB 37.51KB
plugin-gantt (index.js) 169.37KB 41.83KB
plugin-grid (index.js) 215.37KB 58.92KB
plugin-kanban (index.js) 49.30KB 15.39KB
plugin-list (index.js) 114.55KB 28.29KB
plugin-map (index.js) 23.82KB 7.42KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.55KB 11.99KB
plugin-timeline (index.js) 30.64KB 8.94KB
plugin-tree (index.js) 10.52KB 3.69KB
plugin-view (index.js) 87.85KB 21.96KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 114.58KB 37.60KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.78KB 2.56KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.20KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 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) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
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: 28b1a4d3245b746be1fa6323b734a8eba71665f5

① Derived judgments

② Semver level

  • Unchanged from round 1: minor ×3 (types, plugin-grid, plugin-view) with "BREAKING for the legacy spelling, deliberately." in the body; no major. The five edited pending changesets keep their package lists and bump levels byte-for-byte (5293 plugin-view minor; 6235 plugin-view patch; 8973 core minor / plugin-grid patch / types patch; 4082 plugin-grid patch; 4869 plugin-view patch). Changeset Bump Policy, Changeset Fixed Group Check, Changeset Overwrite Report, Changeset Declaration all success on the head.

③ Boundary flags

  • CI on 28b1a4d32 fully concluded (polled 07:58:35Z): 43 check-runs, 40 success, 3 skipped (Test (coverage) ×2, dependabot), 0 failure, 0 in_progress. Test success 07:55:46Z; Test (shard 8/8) success 07:53:52Z; Lint success 07:55:46Z; Bundle Analysis completed after the first poll. The required Test check that was red on f40819d61 is green.
  • PR body vs diff: "No line this PR adds under content/ or packages/plugin-view/README.md carries a version-shaped token" — true (0). "supersedes paragraph now names all five" — true. "reads behind, not dirty" — true. Nit: "a dated note naming objectui#5861 is added" is claimed for all five including 5293, which received an undated inline citation, not a "Dated note" paragraph; since the body becomes the squash commit message, the seat may want "four dated notes and one inline citation". Local red/green counts in the body are the implementer's words; CI is the evidence used here.
  • PR is still a draft; must be marked ready before merge. Branch is behind main; merge-queue update, not a finding. Commit 9f3f52823's model-named trailer never reaches main under squash-with-PR-body (as in round 1).

Implemented-by: claude/issue-5861-retire-table-defaultsort
Reviewed-by: session_014mXUNuFomfj24w7s1pZzhN

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 25, 2026 08:03
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 25, 2026
Merged via the queue into main with commit 0cba1b7 Sep 25, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-5861-retire-table-defaultsort branch September 25, 2026 08:15
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Sep 28, 2026
…i#10793, objectstack-ai#10802 and objectstack-ai#10821 made false (objectui#10877) (objectstack-ai#10891)

Fixes objectstack-ai#10877
Clause-②: no. It is release-text hygiene, and no published type or
behaviour moves.

## What this does

Eight pending changesets each state a contract fact that a later PR in
this same unreleased batch made false: PR objectstack-ai#10793 (objectui#7924,
`densityMode` retired), PR objectstack-ai#10821 (objectui#7928,
`ObjectViewSchema.listViews` mirrored by reference, a named view's
`options` bag refused whole) and PR objectstack-ai#10802 (objectui#10770,
`ObjectChartSchema.series` became two arms). A pending changeset
publishes verbatim into the CHANGELOG at the next release, and the
release PR objectui#5400 is still open. So each false sentence now has a
dated supersession note beside it.

The note form is copied from the landed precedents, PR objectstack-ai#10533 (the
`6235-mergedsort-wrap.md` note) and PR objectstack-ai#10828 (objectui#10801): a bold
headline naming the date and the card whose change supersedes the
sentence, then what holds now, then the superseding entry by file and
PR, then "the text above is kept as the reading of this change".

- Zero lines deleted: `git diff --numstat` against the merge-base
`9f0c84a448` is 168 insertions, 0 deletions, over 8 files. The first
round added 10 notes in 6 files. Patch round 1 added 4 notes in 2 files
(below). Patch round 2 edited the 7779 note and added none, so there are
14 notes.
- The frontmatter is byte-identical in all nine entries the claim and
its addendum `5862987983` name. The md5 of the frontmatter block is
equal at the merge-base `9f0c84a448` and the head `50deccd71a` for each:
7924-retire `ecedb10c`, 8355 `8f322642`, 10321 `564c93d5`, 10584
`84f96a9a`, 8365 `379475b3`, 9242 `acef2a2c`, 8086 `e927372d`, 7779
`ecedb10c`, 7946 `2ffd8635`.
- The seventh entry, `8086-chart-series-type-arm.md`, is untouched
(whole-file md5 `7ea6b544` at base and head). Every sentence in it
measured STILL-TRUE (see the lit control below).
- No new changeset: the diff is `.changeset/` only, and
`check-changeset-presence` says none is owed.

| Entry | FALSE-NOW sentences, quoted | Superseding entry (PR) | Notes |
| --- | --- | --- | --- |
| `7924-named-list-view-retire.md` | "`NamedListView` (one entry of
`ObjectViewSchema.listViews`)"; "Two bucket-③ members are NOT retired"
and "They stay declared as they were." |
`7928-listviews-by-reference-fold.md` (objectstack-ai#10821);
`7924-density-mode-through-fold.md` (objectstack-ai#10793) | 2 |
| `8355-retire-calendar-date-aliases.md` | "it now names the key and the
remedy on all five authoring surfaces", for "a named view's two nestings
under `listViews`"; "plus a `.check()` on `ObjectViewSchema` for a named
view's two nestings"; "`ObjectViewSchema.listViews` stays UNMIRRORED"
and the rest of that paragraph; "`timeline.dateField` stays a live,
accepted alias", on a named view; "the structural guard that `listViews`
stays out of the object's `shape`" |
`7928-listviews-by-reference-fold.md` (objectstack-ai#10821) | 3 |
| `10321-named-view-kanban-groupby-refused.md` |
"`ObjectViewSchema.listViews` is unmirrored"; "and in its legacy
`options.kanban` bag" with the issue path under `options.kanban`;
"reports one issue per written key, naming the key and the replacement";
"Not changed, deliberately: `listViews` stays unmirrored" and the rest
of that paragraph | `7928-listviews-by-reference-fold.md` (objectstack-ai#10821) | 2 |
| `10584-object-chart-series-describe.md` | "It now says the copy is
that `{ dataKey }` arm minus its per-series `type`, and that the
per-series family override on an `object-chart` node is `chartType`";
"taking `type` up would widen a published accept set" |
`10770-object-chart-react-tier-node.md` (objectstack-ai#10802) | 1 |
| `8365-stray-kanban-groupby-refused.md` | "objectui#10321 gives that
route its own door, which refuses the key in either nesting with the
same message" | `7928-listviews-by-reference-fold.md` (objectstack-ai#10821) | 1 |
| `9242-stray-kanban-groupby-lane-second-route.md` | "which refuses the
key in either nesting with the same message"; "(a named view's `kanban`
is typed as the `list-view`'s), but not the key inside the untyped
`options.kanban` bag on either" | `7928-listviews-by-reference-fold.md`
(objectstack-ai#10821) | 1 |
| `object-view-unmirrored-keys-7779.md` (patch round 1) | the table's
"still unmirrored"; "`listViews` stays unmirrored, on the ruling's own
fallback clause."; "The declaration's value is the local
`NamedListView`"; the 21-read / 43-unread figures; "The key therefore
stays in the parity ledger … until the maintainer decides its value
type" | `7928-listviews-by-reference-fold.md` (objectstack-ai#10821) | 1 |
| `objectchart-schema-anchor-7946.md` (patch round 1) | the `series`
half of "value types taken from their READ sites (`ChartRendererProps`
for `xAxisKey` / `series`)" and of "two are INTERNAL, relay-composed
(`xAxisKey`, `series` …)"; "`series` entries must be `dataKey`-shaped.";
"`aggregate` is the exception, and only because the spec's own object is
strict." | `10770-object-chart-react-tier-node.md` (objectstack-ai#10802) | 3 |

**Placement.** Each note sits directly after the paragraph that holds
the false sentence. Where two false paragraphs are adjacent, one note
covers both: the first 10321 note, the 10584 note and the last 8355
note. The 8355 note after the UNMIRRORED paragraph also covers the
matching clause in the `@object-ui/types` bullet above it, because both
describe the same named-view check. No note cites a line address; source
facts are cited by symbol and test name, and `check:new-line-citations`
reads 0 new citations.

## Measured, not inherited (one-time probes, not committed)

The probes ran the worktree sources at base `b2683a2c0e`, with
`@objectstack/spec` 17.4.0 resolved from `packages/types`. The zod face
ran through `tsx`, and the TS face through `tsc --noEmit` against
`packages/types/src/index.ts`. Each probe sits beside a control that
differs only by the key. A named view is `listViews.v` with `columns`
set.

Zod face (`ObjectViewSchema.safeParse`; `safeValidateSchema` gives the
same issues on the two `kanban` rows):

| Probe | Result |
| --- | --- |
| control `kanban: { groupByField, columns }` | parses |
| `kanban.groupBy` | two issues: `unrecognized_keys` at
`listViews.v.kanban` naming `groupBy`, and `custom` at
`listViews.v.kanban.groupBy` |
| `options: { kanban: { groupBy } }` | one issue: `unrecognized_keys` at
`listViews.v` naming `options`; nothing at the `options.kanban.groupBy`
path |
| `calendar.dateField` | `unrecognized_keys` at `listViews.v.calendar`,
and `custom` at `listViews.v.calendar.dateField` |
| `options: { calendar: { dateField } }` | one issue: `options` refused
|
| `timeline.dateField` | `unrecognized_keys` at `listViews.v.timeline`;
control `timeline: { startDateField, titleField }` parses |
| each of the 16 retired `NamedListView` spellings, and `densityMode` |
`unrecognized_keys` at `listViews.v` naming the key (17 of 17); control
`userActions: { search: false }` parses |
| `listViews` in `ObjectViewSchema.shape` | present |
| list-view route: `kanban.groupBy`, `options.kanban.groupBy`,
`calendar.dateField`, `options.calendar.dateField`, `timeline.dateField`
| `invalid_type`, `custom`, `invalid_type`, `custom`, parses: unchanged
|

TS face (`tsc`):

| Probe | Result |
| --- | --- |
| named view `kanban.groupBy` in an `ObjectViewSchema` literal | TS2353,
excess property on the spec's kanban block |
| named view `options` | TS2353, `options` does not exist |
| named view canonical control | compiles |
| `list-view` `kanban.groupBy` | TS2322 (`never`): unchanged |
| `list-view` `options.kanban.groupBy` | compiles: unchanged |
| a `NamedListView` value as a `listViews` entry | TS2322, not
assignable |
| `NamedListView` with `densityMode`; with `allowExport` | TS2322;
compiles |

Chart series (`ObjectChartSchema.safeParse`): `{ name, type: 'line' }`
parses with `type` kept; `{ dataKey, type: 'line' }` parses with `type`
stripped; `{ name, chartType }` is refused (`invalid_union`). The series
`.describe()` string now names both arms.

The runtime fold was read, not probed: `normalizeListViewSchema` still
folds `densityMode` and the eight `show*` flags, and `ListView` still
merges `options.kanban` under `kanban`.

## Lit control: STILL-TRUE, left byte-identical

- `8086-chart-series-type-arm.md`, the whole entry. PR objectstack-ai#10802 changed no
`plugin-charts` source (its one file there is a test).
`ChartRendererProps.schema.series` still declares `type?: string` on
both arms. The `ObjectChartSchema.series` docblock still says the copy
of the internal arm omits `type`, and that internal arm's type is the
same literal as before PR objectstack-ai#10802.
- 8365, "takes the identical message through a check on that untyped
bag", and the distinguishing `options.kanban` fixture. Both are the
`list-view` route, measured unchanged.
- 9242, "a `list-view` document carrying the key, under `kanban` or
under the legacy `options.kanban` bag, is refused by
`safeValidateSchema`". Measured unchanged.
- 8355, the `@object-ui/types` bullet's "on the legacy
`options.calendar` nesting (a check, since an open record declares no
member". This is the list-view surface, measured unchanged.
- 7924-retire, "`densityMode` is folded onto `rowHeight` by
`normalizeListViewSchema`" and "Only the authoring face changes". The
fold still does both.
- 10584, "Wording only. The accepted shape does not move on either
face". This is a statement about that change's own delta, and it is
still true of that change.
- 7779 (patch round 1): `viewTabBar` retired; the eight keys enforced;
"64 declared top-level members"; the spec record requires `columns` and
refuses `options`, tuple filters and `default`; "not papered over with
`z.any()`"; "absent stays valid on all nine"; the ledger move 14/96 →
14/87 (that change's own delta). Each measured true at `0ea55c3701`.
- 7946 (patch round 1): the `xAxisKey` half of the INTERNAL sentence
(its `.describe()` still says all five producers compute it); `type:
'object-chart'` required; `chartType` must be the declared union;
`normalizeChartSchema` translates the `{ name }` arm; `aggregate`
`function` / `groupBy` required with unknown members refused; a
misspelled key on the node itself is not refused; `filter` keeps both
arms. Each measured true at `0ea55c3701`.

## Gates (re-taken at head `50deccd71a`; hand-derived from
`package.json` and `.github/workflows/`; each exit captured by
redirect-then-status)

| Command | Verdict line | Exit |
| --- | --- | --- |
| `pnpm check:pending-changeset-literals` | ✅ No test source names a
pending changeset. | 0 |
| `node scripts/check-changeset-claims.mjs` | ✅ No pending changeset
names a file this change touches. (Self-contradiction reading: every
declared package across the 8 bodies is not negated.) | 0 |
| `node scripts/check-changeset-presence.mjs` | ✅ No source or published
contract of a released package changed in this range, so no changeset is
owed. | 0 |
| `node scripts/check-changeset-no-major.mjs` | ✅ No changeset declares
a `major` bump. | 0 |
| `node scripts/check-changeset-overwrite.mjs` | report-only: this
change touches 8 changesets it did not add. The declared packages are
identical at base and head for all 8, which is the prose-correction
case. | 0 |
| `node scripts/check-changeset-fixed.mjs` | ✅ All workspace packages
are in the changeset fixed group. | 0 |
| `pnpm check:new-line-citations` | VERDICT
new-cross-file-line-citations: 0 new citation(s) | 0 |
| `pnpm check:control-bytes` | ✅ check-control-bytes: OK | 0 |
| `pnpm check:spec-symbols` | ✅ spec member citations: nothing cites a
key its spec symbol does not declare. | 0 |
| `pnpm check:test-path-roots` | ✅ check-test-path-roots: OK | 0 |
| `node scripts/check-installed-spec-pin-claims.mjs` | OK (it excludes
`.changeset/`, so it was run for completeness only) | 0 |
| `node scripts/check-governed-queue-guard.mjs --test` (the 8 paths) | ✅
NOT GOVERNED | 0 |

Tests, from the repo root under the shared verify lock: every
`scripts/__tests__` file that names `.changeset` (derived with `git grep
-l`: 24 test files, plus one fixture that is not a test), and the five
`@object-ui/types` pins that re-derive what the notes state
(`calendar-date-alias-refusal-8355`,
`named-view-kanban-stray-group-by-10321`,
`object-view-listviews-by-reference-7928`,
`object-chart-react-tier-node-10770`,
`object-view-unmirrored-keys-7779`). Result at `f5e0123f4b`: **Test
Files 29 passed (29), Tests 1193 passed (1193)**, lock `VERDICT
command-exit 0`. Re-taken at `0ea55c3701` with the 24
`scripts/__tests__` files and the four pins the new notes rest on
(`object-view-unmirrored-keys-7779`,
`object-chart-react-tier-node-10770`,
`object-view-listviews-by-reference-7928`, `zod-mirror-parity`): **Test
Files 28 passed (28), Tests 1200 passed (1200)**, lock `VERDICT
command-exit 0`. Re-taken at `50deccd71a` (patch round 2): the 24
`scripts/__tests__` files plus `object-view-unmirrored-keys-7779` gave
**25 files / 1146 tests**, and the four other pins
(`calendar-date-alias-refusal-8355`,
`named-view-kanban-stray-group-by-10321`,
`object-view-listviews-by-reference-7928`,
`object-chart-react-tier-node-10770`) gave **4 files / 48 tests**. Both
runs gave lock `VERDICT command-exit 0`.

Not applicable, with the reason:
- `@object-ui/types` type-check, package vitest runs and consumer
sweeps: the diff touches no package source, only `.changeset/`.
- The Spec Main Shape Gate: no touched type.
- ESLint `--no-inline-config` on the touched files: `eslint.config.js`
has no configuration that matches `.md`. All 8 files report "File
ignored because no matching configuration was supplied", so it judged
nothing (NOT MEASURED).

## Acceptance notes

- **Residue in the same family: closed by patch round 1.** The first
round stopped on two files outside the claimed surface,
`object-view-unmirrored-keys-7779.md` and
`objectchart-schema-anchor-7946.md`. Each is named by a superseding PR
itself. The seat extended the file surface (addendum `5862987983`,
option A), and patch round 1 (`80ee15eecb`) added one note to 7779 and
three to 7946, in the same form and measured the same way. `Fixes
objectstack-ai#10877` stays.
- **For the at-tier review.** The last 7946 note also names two changes
outside the three PRs: `drillDown` (objectui#8885, PR objectstack-ai#8895) and `xAxis`
/ `yAxis` (objectui#10518, PR objectstack-ai#10601). Both landed after the 7946 entry,
and both also make its "`aggregate` is the exception" sentence false.
That sentence of the note can be dropped if the review holds it out of
scope; the rest of the note stands without it.
- Not measured: the wider pending population that names `listViews` /
`NamedListView` or `ObjectChartSchema`. Only the entries the superseding
PRs name were read.
- **Source prose. These are observations and were not filed; carrier:
none.**
- The `ObjectChartSchema.series` TS docblock
(`packages/types/src/objectql.ts`) says "A `type` written on this arm
anyway is an excess property on a literal typed by this interface."
Since PR objectstack-ai#10802 that is false. `{ dataKey: 'amount', type: 'line' }`
compiles in an `ObjectChartSchema` literal, because the union's `{ name
}` arm declares `type` (tsc probe above). The zod mirror still strips
it.
- The zod docblock headed "WHERE THIS ARM IS INSTALLED — TWO ROUTES, TWO
NESTINGS EACH, ONE STRING" (`packages/types/src/zod/objectql.zod.ts`)
still says a named view's `listViews` "is unmirrored", and it still
names a `custom` issue under `options.kanban` on that route. The
docblocks of `checkNamedViewKanbanStrayGroupBy` and
`namedViewKindRefusals` are current.
- **A dispatch premise, corrected.** "Each one already states in its own
body that it supersedes the older entry" holds for
`7924-density-mode-through-fold.md` and
`7928-listviews-by-reference-fold.md`.
`10770-object-chart-react-tier-node.md` names no superseded entry. The
supersession is stated in PR objectstack-ai#10802's body ("Superseded pending
changesets"), which names the objectui#10584, objectui#7946-anchor and
objectui#8086 entries.
- **`main` merged, twice.** `origin/main` `4f38f39286` was merged as
`0ea55c3701`: the two merged commits touch none of the probed sources,
and the probes re-ran byte-identical. `origin/main` `9f0c84a448` was
merged as `bade176fff` (patch round 2), which carries `35d68c4c` (PR
objectstack-ai#10884, objectui#10758). That merge moved probed sources
(`objectql.zod.ts`, `objectql.ts`, `ChartRenderer.tsx`); the probes
re-ran at `50deccd71a`, byte-identical to round 1's head outputs.
Neither merge used a rebase or a force-push.
- **Patch round 2 (at-tier record `5864532186`, FAIL on one note).** The
7779 note said the renderer reads 20 members and leaves 44 unread. That
was true at `4f38f39286`, but PR objectstack-ai#10884 re-took the census to 43 / 21 on
`main`. Per the seat's decision (REWORK `5864543090`), the note now
states no figure. It says the split is no longer the 21 / 43 the entry
counted, names both changes that moved it (objectui#7928 and
objectui#10758), and cites the census pin in
`object-view-unmirrored-keys-7779.test.ts`, which re-derives the figures
on every run (`43 read + 21 unread = 64` at the head). No other note
moved.
- **The headline card.** Each note's headline names the card whose
change supersedes the sentence, as the PR objectstack-ai#10533 notes did. PR objectstack-ai#10828's
notes named their own card instead, because the cause there was a spec
release that has no pending entry.
- **Commit trailers are model-free** (`Co-Authored-By: Claude`), per the
dispatch. The harness offered a trailer that carries a model name, and
it was not used.

Implemented by a `domain:spec#1` dispatch (dev subagent). Session:
`https://claude.ai/code/session_014fWVhLzhxR8qrFsJ5o8TYW`.

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

---------

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

Labels

documentation Improvements or additions to documentation package: types plugin tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Follow-up (the "C half" of the 2026-08-22 ruling): ADR-0049 enforce-or-remove retirement of table.defaultSort

2 participants