Repository navigation
refactor(plugin-view,plugin-grid,types): retire table.defaultSort / object-grid defaultSort (ADR-0049) - #10533
Conversation
…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>
…ent supersedes Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ Console Performance Budget
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
Size Limits
|
Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: FAIL — the required 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>
✅ Console Performance Budget
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
Size Limits
|
Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
…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>
Fixes #5861
Clause-②: yes — this removes the last runtime reads and the declared docs of a key the installed
@objectstack/spec17.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'sdefaultSortandobject-view'stable.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:
ObjectGridfetch pathelse if (schema.defaultSort)lowered it to$orderbysortonlyObjectGridheader arrowsparseSchemaSort(schemaSort ?? [schema.defaultSort])parseSchemaSort(schemaSort)ObjectViewnon-grid fetchtable.defaultSortinto the sinktable.sortObjectViewgrid forwardingdefaultSort: schema.table?.defaultSortObjectViewdelegatedrenderListViewmergedSortwrappedtable.defaultSortinto an arraytable.sortplugin-gridregistrationsortinput describeddefaultSortas its fallbackH1 — the TypeScript declaration goes too, as a tombstone (decided and measured)
ObjectGridSchema.defaultSortbecomesdefaultSort?: neverand the zod mirror member becomesretirementTombstone(...), in lockstep. Not a deletion:ObjectGridSchemaextendsBaseSchema, whose[key: string]: anyabsorbs an undeclared key asany, 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 rebuiltdist: a downstreamObjectGridSchemaliteral carryingdefaultSortfailstscinplugin-viewwith TS2322 (reverse check below). Only thedefaultSortregions ofobjectql.ts/objectql.zod.tswere touched;ObjectGridSlotKeykeeps listing the key because the member is still declared.H2 — no live producer (measured, with lit controls)
ObjectGridPropsSchema.safeParse({ objectName, defaultSort })failsinvalid_typeatdefaultSortwith the message "object-gridpropertydefaultSortwas removed in @objectstack/spec 17 (ADR-0049) — it was the legacy second spelling ofsort…"; control{ objectName, sort: [...] }parses green.git grep defaultSort -- packages/— the remaining hits areplugin-detail's ownRelatedListdefaultSortprop, a different carrier fed fromschema.sort, plus CHANGELOGs).normalize-list-viewnever mentions it.examples/0 files,e2e/0,apps/1 (the registry parity test's comments, not authoring),content/2 (the two pages tombstoned here). objectstackorigin/main:examples/0,apps/0,packages/qa/0. Lit control, identical method,searchableFields: objectuiexamples/4 files,content/5; objectstackexamples/2,packages/qa/1.ObjectGridSchemaJSON example incontent/docs/api/schema-reference.mdauthored"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
sortcontrol on the same path in the same run.Red leg: the five source files were put back to the base
59636b3a6under the committed tests, with a trap restore (blob hashes re-checked against HEAD afterwards,git diff HEADempty): 19 failed | 97 passed (116), 8 of 9 files red. The only all-green file isgridRetiredStringSort-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-viewObjectView.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-viewObjectView.sortSink.test.tsx—sends no $orderby at all…,a descending legacy default is inert too…, and the tail ofkeeps the sink STRICT…(the sink-strictness half is unchanged).plugin-viewObjectView.filterSources.test.tsx— the three objectui#6235 wrap cells, flipped.plugin-viewObjectView.namedViewSortArity.test.tsx— through the REALObjectGrid:a retired table.defaultSort sorts NOTHING on the real grid path — no $orderby, no arrow, plus a new canonicaltable.sortcontrol cell.plugin-gridgridArrayArmOrderby-8973.test.tsx— the legacy-arm section, flipped (fully-specified, andorderomitted, now send no$orderby).plugin-gridgridDefaultFiltersLowering.test.tsx—a retired defaultSort reaches neither $orderby nor $filter.plugin-gridserverSorting.test.tsx— new:a retired defaultSort lights NO arrow and sends NO $orderby, with a sortable-chrome non-vacuity check.typesobject-grid-default-sort-tombstone-5861.test.ts— new: refused by name (invalid_typeatdefaultSort), lit control (unknown key green), remedy text, describe equals message, canonicalsortgreen, upstream re-derivation from the installed pin, and the@ts-expect-erroron the?: nevertwin (compiled bytsconfig.test.json;--listFilesincludes the file).Canonical
sortis asserted on all threeObjectViewpaths and on bareObjectGridin 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 in28b1a4d32:Required
Testwas red onscripts/__tests__/doc-version-claims.test.ts("records every version literal on the scanned surfaces"). The doc tombstones had added unregistered@objectstack/specversion literals inplugin-view.mdxandplugin-view/README.md, plus a third inschema-reference.mdsplit 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. NoKNOWN_CLAIMSentry 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 undercontent/orpackages/plugin-view/README.mdcarries a version-shaped token.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
5293carries 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 thetable.defaultSortsink 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.defaultSortcited as a liveorderspelling.A re-grep of the pending set finds three more
defaultSortmentions, all still true and left alone.7122says the spec made the key a D2 tombstone.8767quotes the spec's retirement text.6697concernsRelatedList's owndefaultSortKey, a different carrier. The retirement changeset's "supersedes" paragraph now names all five entries.Nit. The objectui#5270 comment block in
ObjectView.tsxno longer quotes the retireddefaultSortheader 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 readsbehind, notdirty.Gates (code commit
43ab1fd43; rework head28b1a4d32; full-suite runs atf40819d61, andplugin-viewre-run at28b1a4d32)turbo run build --filter='@object-ui/plugin-view^...' --concurrency=2: 15 successful, 15 total; rebuiltpackages/types/dist/objectql.d.tscarriesdefaultSort?: never.pnpm --filter @object-ui/types type-checkexit 0 (script echoed@object-ui/types@17.6.0 type-check);@object-ui/plugin-gridexit 0;@object-ui/plugin-viewexit 0..d.ts: injectingdefaultSort: { field: "name", order: "asc" }intoObjectView'sgridSchemaliteral makesplugin-viewtsc --noEmitfail withTS2322 … Types of property 'defaultSort' are incompatible … not assignable to type 'undefined'; restored, blob equals HEAD. (A first attempt was a no-op:ablation-replacerefused because the replacement contained its own anchor. It changed nothing and ran nothing.)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 at28b1a4d32together withdoc-version-claims: 49 files, 473 tests passed;plugin-viewtype-check exit 0 again, closure build 15/15 cached);apps/console/src/__tests__/registry-inputs-spec-parity.test.ts(it reads theplugin-gridregistration inputs) 199 tests passed.node scripts/check-changeset-presence.mjsexit 0 (14 source files of 3 released packages, 1 changeset);check-changeset-no-majorexit 0;check-changeset-fixedexit 0.check:new-line-citations:VERDICT new-cross-file-line-citations: 0 new citation(s);check:control-bytesOK.check-doc-linksexit 0;check:doc-typesexit 0;check:doc-fencesexit 0;check:doc-example-idsexit 0;check-prompt-component-keysexit 0;check-doc-expression-carriageexit 0 (report-only; its oneschema-reference.mdsite,action.condition, predates this branch);check-changeset-claimsexit 0 (report-only);check:pending-changeset-literalsexit 0..ts/.tsxfiles: 14 files in the JSON report, 0 errors. Per-file warnings are equal to the base except three test files (+1, +1, +2no-explicit-anyfromas anyfixtures, matching those files' existing style).eslint.config.jshas no type-aware linting (parserOptions.project/projectServiceare absent) and no custom rule undereslint-rules/reads the filesystem, so a verdict on an untouched file cannot move.check-governed-queue-guard --testover all 18 paths says NOT GOVERNED.Registries and docs
@object-ui/types(ObjectGridSchemamember and its zod mirror), theplugin-gridregistration (sortdescription and docblock),content/docs/plugins/plugin-view.mdx,content/docs/api/schema-reference.md,packages/plugin-view/README.md, and a changeset (minoron types / plugin-grid / plugin-view, nevermajor).apps/console/src/__tests__/registry-inputs-spec-parity.test.ts. Itsobject-grid.defaultSortcarve-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: theCRUDSchemadefaultSort/defaultSortOrdersentence is untouched. Only the adjoiningObjectGridSchemasentence ("that key is unaffected"), which this change makes false, was rewritten.Acceptance notes
packages/plugin-view/README.mddescribed the key as a working alias, and it ships in the package'sfiles[]; this change makes it false, so it is repaired here. Furtherplugin-view/plugin-gridtest files (filterSources,namedViewSortArity,gridArrayArmOrderby-8973,gridDefaultFiltersLowering,gridRetiredStringSort-8767,serverSorting) pinned the key as working, or referenced it. They sit next to the landing points.ObjectGrid.tsx's page-size region (draft objectui#10278) is untouched. The two edits sit in the sortifchain and thedeclaredSortexpression; the fetch effect's dependency list is unchanged.mergedSorthandstable.defaultSortto the delegated list view UNWRAPPED, while the non-grid fetch path wraps the same value — the #5270 arity split, one branch short #6235, finding(plugin-grid):object-grid's private array-arm lowering interpolates missing keys into$orderby— aSortConfigwithorderomitted goes out asname undefined#8973, the [finding] ObjectGrid's legacydefaultFiltersleg still reaches$filterwithout thetoFilterNodehop #4082 grid filter-lowering entry, andObjectViewProps.views[].sortdeclaresdirection, but every sort consumer readsorder— a host-supplieddescview silently sorts ascending #5293. Four now carry a dated note naming objectui#5861, and5293an inline citation (see Review rework above).plugin-view.mdxparagraphs this change touched were rewritten to cite by content (AGENTS.md [WIP] Update documentation for project #11). Thedata.ts:63citation in the rewrittengridDefaultFiltersLoweringcell was dropped.defaultSortrenders unsorted. It is not re-routed intosort: that would be the tolerant alias this retirement removes.Generated by Claude Code