Uh oh!
There was an error while loading. Please reload this page.
feat(spec): retire object-grid's legacy defaultSort fallback (#11805, ADR-0049) - #12256
Conversation
… ADR-0049) Tombstone ObjectGridPropsSchema.defaultSort with retiredKey() — the legacy single-sort second spelling of sort, read only when sort was absent (measured at the .objectui-sha pin 190fbd01d, plugin-grid/src/ObjectGrid.tsx:1244-1246 and :2847). Register ui/ObjectGridProps:defaultSort in RETIRED_KEYS_BY_MAJOR[18], add the D2 conversion object-grid-default-sort-removed (wrap-and-rename to sort: [pair] when sort is absent; pure strip when sort is present) wired into the step-18 chain, regenerate the authorable surface ([RETIRED] mark) and the ui/component reference, and pin the refusal + no-materialize + surviving-sort behaviour in component.test.ts. Changeset ships minor per the maintainer's #11805 ruling (launch-window convention). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDGG54XF5gbTLdQzCtnaVV
…tire-object-grid-default-sort
) gen:migration-registry (byte-identical — main's generated regions already carried the #12191 semantic entries), rebuild restoring the ui/ObjectGridProps:defaultSort [RETIRED] surface mark, gen:docs restoring the retired reference row. Sibling entries and implementation bodies asserted present (field-max/min-length semantic entries, object editMode, minLength). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDGG54XF5gbTLdQzCtnaVV
📓 Docs Drift CheckThis PR changes 1 package(s): 27 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 4 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 785f6526b02617e015a3cc0af31755712d4405a1 && git checkout 785f6526b02617e015a3cc0af31755712d4405a1
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 107bb4ba4b96bb74913e19b46f7756dd30029d4d 9b3dd895fcbc52332d02804a84c8f3981a38a834 && git checkout -B drift-repro 107bb4ba4b96bb74913e19b46f7756dd30029d4d && git merge --no-ff 9b3dd895fcbc52332d02804a84c8f3981a38a834
node scripts/docs-audit/affected-docs.mjs --json 107bb4ba4b96bb74913e19b46f7756dd30029d4d
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#11805
Producer half of objectui#5861 (ADR-0049 enforce-or-remove), per the maintainer ruling of 2026-08-25 (decision-inbox batch 4): 「#11805 退役 defaultSort,不需要major」.
What
ObjectGridPropsSchema.defaultSort— the legacy single-sort fallback ({ field, order }, read only whensortis absent) — is retired from the authoring contract. Authoring it is now a tsc error (neverinput) and a parse error carrying the wrap-and-rename prescription (sort: [{ field, order }]). Zero authored occurrences in either repo's corpora (the card's measurement, re-run at dispatch acrossexamples/,apps/,packages/qa/, spec fixtures,skills/,content/docs— the only doc hit is the generated reference row this PR regenerates).Read points measured at the
.objectui-shapin (190fbd01d):plugin-grid/src/ObjectGrid.tsx:1244-1246(the$orderbyfetch fallback) and:2847(header arrows, which wrap it[schema.defaultSort]— the exact array shapesortcarries). objectui's mirror schema is parity-test-only and parses nothing at runtime, so only this strictObject can refuse the key; objectui#5861 retires the reads as the consumer half after a released spec version reaches the pin.The retirement kit
defaultSort: retiredKey('…')inObjectGridPropsSchema(packages/spec/src/ui/component.zod.ts); the authorable-surface line becomesui/ObjectGridProps:defaultSort [RETIRED].entries/retired-keys/18.ui__ObjectGridProps__defaultSort.ts(RETIRED_KEYS_BY_MAJOR[18], viagen:migration-registry); D2 conversionobject-grid-default-sort-removed(conversions/registry.ts, protocol 18): wrap-and-rename tosort: [pair]whensortis absent, pure lossless strip whensortis present (the renderer's own precedence made it unread then); wired into the step-18 chain (conversionIds+ rationale).component.test.ts: refusal pin asserting the prescription, no-materialize pin, surviving-sortpin.authorable-surface/ui.json([RETIRED], written bygen:schemaduring build; build gate (b) passed against the registered exact key) andcontent/docs/references/ui/component.mdx(gen:docs, the one artifactcheck:generatedproved stale).spec-changes.json/ upgrade guide are green unchanged — protocol-18 entries project at the next major boundary, same as every sibling 18-registered retirement.@objectstack/spec: minorper the ruling's explicit 「不需要major」 (launch-window convention: accept-set narrowings ride minor), body carries BREAKING + FROM→TO + one-line fix +<!-- adr-0087: registered object-grid-default-sort-removed -->.liveness/page.jsonclassifiesPageSchematop-level props only (one drill level, per its own_note); component-props keys have no row to move, andcheck:livenessis green.Route note (deviation from the card's literal wording, declared)
The card (and the playbook's strict-schema row) spells the route "strict deletion + guidance-map entry". The authorable-surface ratchet forbids that spelling here: gate (a) in
packages/spec/scripts/build-schemas.tsis fatal on any key that vanishes from an emitted def ("To retire a key, tombstone it instead of deleting it"), and gate (c) ratchets baseline-line deletions against the merge base for two majors. Thedata/Metric:filtersguidance-route precedent predates its def's arrival in the surface baseline (data/Metric:*first enteredauthorable-surface/data.jsonatdd33bf9, already withoutfilters), so it never met these gates;ui/ObjectGridProps:defaultSortIS in the merge-base baseline, so the only gate-green shape is theretiredKey()tombstone — the exact current shape of every in-repo component-props retirement (#6946 ×3, FormView.defaultSort, #9198, #9220), which the dispatch named as shape authority. Author-visible behaviour is identical to the ruled outcome: authoreddefaultSortflips from accepted to a loud rejection carrying the fix; changeset stays non-major. No semantic entry ships — the migration story is the D2 conversion (mechanical, and required soapplyConversionsToStoredItemheals stored rows the strict parse now refuses), matching the FormView/#6946 wiring.Verification (head
9b3dd89, post-merge of origin/main incl. #12191)pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2—Test Files 426 passed (426)/Tests 11355 passed (11355)(pre-merge head 38577eb); post-merge union re-run on9b3dd89: component.test.ts + conversions + migrations + alias-integrity + migrate-sentence pins —Test Files 8 passed (8)/Tests 575 passed (575). Pin receipts (verbose):✓ object-grid defaultSort is retired (#11805) > rejects the retired defaultSort with the wrap-and-rename prescription / does not materialize / keeps sort.pnpm --filter @objectstack/spec typecheck— exit 0 (tsc + scripts + test layer).pnpm --filter @objectstack/spec check:generated@ 9b3dd89 — "✓ All 14 generated artifacts are up to date."dist/: probe authoringdefaultSortreds (error TS2322: Type '{ field: string; order: string; }' is not assignable to type 'undefined'),sortcontrol compiles exit 0.node scripts/check-adr-0087-registration.mjs@ 9b3dd89 — ".changeset/object-grid-default-sort-retired.md [BREAKING] registered object-grid-default-sort-removed";check-changeset-no-major— "✓ This diff introduces nomajorbump.";check-empty-changeset— pass....@objectstack/spec): the dispatch-named consumer@objectstack/lint(metadata-authoring-lint, consumesComponentPropsMap) — 81 files / 2294 tests + typecheck, green. objectui consumes via the.objectui-shapin; no cross-repo change (ui#5861 follows on pin bump).check-dev-prereqsfails only on the fresh worktree's unbuilt workspace (34/67 packages, an environment precondition CI's lint.yml discharges by building first);check:type-check-debt --re-measureand the fullpnpm lintsweep are CI-owned farm runs; CLImigrate-metae2e not run locally (conversion idempotent by construction — the'defaultSort' in propertiesguard; CI runs it).scripts/pm/os-regen-merge.sh(merge committed before regen), regenerated, then asserted by quoted-exact-name grep that the sibling'sfield-max/min-length-malformed-or-misplaced-refusedentries,object.editMode,minLengthbodies, and this PR's entries all survive.skills/** untouched; no governed surface in the diff; PR stays draft for the needs:contract-review chain (条款②).
Generated by Claude Code
Generated by Claude Code