Filed unassigned by the domain:ui execution seat while working objectui#5861 (session session_01CSoz9uGhaaSgiq3hshtN7L). For PM/maintainer triage — not claimed.
Why this is here and not in objectui
The maintainer ruling of 2026-08-22 on objectui#4869 directed an ADR-0049 enforce-or-remove retirement of table.defaultSort as its own card. That card is objectui#5861. Working it produced a measurement that relocates the work: the key whose retirement is ruled is declared here, not in objectui, and the loud refusal ADR-0049 requires can only be produced here.
ObjectGridPropsSchema (packages/spec/src/ui/component.zod.ts:2164) is a strictObject and declares:
defaultSort: z.unknown().optional()
.describe('Legacy single-sort fallback ({ field, order }), read only when `sort` is absent. Prefer `sort`'),
It is published un-retired as ui/ObjectGridProps:defaultSort in packages/spec/authorable-surface/ui.json:734 — contrast ui/FormView:defaultSort [RETIRED] on line 466, the sibling key already retired in the #3896 close-out.
Measured against the pin objectui consumes (@objectstack/spec@17.2.0)
Probed through @object-ui/test-support's shared tombstone judge, the same one objectui's gates use:
| measurement | result |
|---|
object-grid listed keys / authorable keys | 37 / 37 |
object-grid tombstoned keys | [] |
defaultSort listed / authorable / tombstoned | true / true / false |
tombstoneEvidence('defaultSort') | { listed: true, typedNever: false, describedRemoved: false } |
authored { defaultSort: { field, order } } | accepted by safeParse |
| control: a bogus key | refused — the schema really is strict |
control: blocks in ComponentPropsMap that do carry tombstones | 7 blocks, 16 keys |
Both recognition channels agree the key is live, and the positive control shows the instrument detects tombstones where they exist, so the zero for object-grid is a real zero.
Why the consumer side cannot do it
Measured in objectui on origin/main @ 0c282d979:
- objectui's zod mirror of
ObjectGridSchema (packages/types/src/zod/objectql.zod.ts) is a non-strict BaseSchema.extend(...)consumed only by objectui's own parity tests — nothing parses metadata through it at runtime. Tombstoning it buys zero runtime refusal. - The refusal machinery for an
object-grid node is the strictObject above. That is the only place an authored defaultSort can be refused rather than silently ignored. - If objectui merely stopped reading the key while this schema still accepts it, declared-but-unenforced would become declared-and-silently-dropped — the ADR-0049 failure mode moved, not fixed.
objectui's apps/console/src/__tests__/registry-inputs-spec-parity.test.ts states the ordering itself, in the comment governing the ten ruled object-grid carve-outs of objectui#4648: "They retire only if @objectstack/spec retires the keys upstream."
The precedent, and it is exact
objectstack#6946 retired three zero-reader UI keys the same way — PageHeaderProps.icon, PageCardProps.actions, RecordDetailsProps.layout. Those are three of the 16 tombstones the probe above measured. objectui#3974 then removed the corresponding reads for form.defaultSort once this repo had tombstoned it, and pinned the ordering explicitly in packages/react/src/spec-bridge/__tests__/FormViewRetiredKeys.test.ts: "a dormant read is only safely deletable when BOTH ends are dead: Producer — the contract still rejects the keys. This is what makes the deletion not a capability removal."
Route and cost
Per the spec-property-retirement playbook this is the strict route, not a retiredKey() tombstone: delete the key from the shape and add an entry to the block's *_RETIRED_KEY_GUIDANCE map, plus the ADR-0087 conversion, the exact-key RETIRED_KEYS_BY_MAJOR entry, the D3 chain step, the liveness ledger, the generated baselines, and pin tests.
⚠️ The cost the objectui card did not anticipate: @objectstack/spec is at 17.2.0, and a retirement changeset here is major. This is a release-planning call, which is why this is filed for triage rather than claimed.
No ADR edit is required — ADR-0049 and ADR-0087 already govern; no ADR enumerates this key.
Authored-occurrence measurement
Zero authored occurrences in either repo, re-measured today with a known-present control (searchableFields, found by the identical method in examples/):
- objectstack
examples/apps/packages/qa/ — none - objectui
examples/apps/e2e/ — none authored; the only hits are the carve-out ledger and prose
Related: objectui#5861 (the consumer half, blocked on this), objectui#4869, objectui#4648, objectstack#6946.
Filed unassigned by the
domain:uiexecution seat while working objectui#5861 (sessionsession_01CSoz9uGhaaSgiq3hshtN7L). For PM/maintainer triage — not claimed.Why this is here and not in objectui
The maintainer ruling of 2026-08-22 on objectui#4869 directed an ADR-0049 enforce-or-remove retirement of
table.defaultSortas its own card. That card is objectui#5861. Working it produced a measurement that relocates the work: the key whose retirement is ruled is declared here, not in objectui, and the loud refusal ADR-0049 requires can only be produced here.ObjectGridPropsSchema(packages/spec/src/ui/component.zod.ts:2164) is astrictObjectand declares:It is published un-retired as
ui/ObjectGridProps:defaultSortinpackages/spec/authorable-surface/ui.json:734— contrastui/FormView:defaultSort [RETIRED]on line 466, the sibling key already retired in the #3896 close-out.Measured against the pin objectui consumes (
@objectstack/spec@17.2.0)Probed through
@object-ui/test-support's shared tombstone judge, the same one objectui's gates use:object-gridlisted keys / authorable keysobject-gridtombstoned keys[]defaultSortlisted / authorable / tombstonedtrue/true/falsetombstoneEvidence('defaultSort'){ listed: true, typedNever: false, describedRemoved: false }{ defaultSort: { field, order } }safeParseComponentPropsMapthat do carry tombstonesBoth recognition channels agree the key is live, and the positive control shows the instrument detects tombstones where they exist, so the zero for
object-gridis a real zero.Why the consumer side cannot do it
Measured in objectui on
origin/main@0c282d979:ObjectGridSchema(packages/types/src/zod/objectql.zod.ts) is a non-strictBaseSchema.extend(...)consumed only by objectui's own parity tests — nothing parses metadata through it at runtime. Tombstoning it buys zero runtime refusal.object-gridnode is thestrictObjectabove. That is the only place an authoreddefaultSortcan be refused rather than silently ignored.objectui's
apps/console/src/__tests__/registry-inputs-spec-parity.test.tsstates the ordering itself, in the comment governing the ten ruledobject-gridcarve-outs of objectui#4648: "They retire only if@objectstack/specretires the keys upstream."The precedent, and it is exact
objectstack#6946 retired three zero-reader UI keys the same way —
PageHeaderProps.icon,PageCardProps.actions,RecordDetailsProps.layout. Those are three of the 16 tombstones the probe above measured. objectui#3974 then removed the corresponding reads forform.defaultSortonce this repo had tombstoned it, and pinned the ordering explicitly inpackages/react/src/spec-bridge/__tests__/FormViewRetiredKeys.test.ts: "a dormant read is only safely deletable when BOTH ends are dead: Producer — the contract still rejects the keys. This is what makes the deletion not a capability removal."Route and cost
Per the
spec-property-retirementplaybook this is the strict route, not aretiredKey()tombstone: delete the key from the shape and add an entry to the block's*_RETIRED_KEY_GUIDANCEmap, plus the ADR-0087 conversion, the exact-keyRETIRED_KEYS_BY_MAJORentry, the D3 chain step, the liveness ledger, the generated baselines, and pin tests.@objectstack/specis at 17.2.0, and a retirement changeset here ismajor. This is a release-planning call, which is why this is filed for triage rather than claimed.No ADR edit is required — ADR-0049 and ADR-0087 already govern; no ADR enumerates this key.
Authored-occurrence measurement
Zero authored occurrences in either repo, re-measured today with a known-present control (
searchableFields, found by the identical method inexamples/):examples/apps/packages/qa/— noneexamples/apps/e2e/— none authored; the only hits are the carve-out ledger and proseRelated: objectui#5861 (the consumer half, blocked on this), objectui#4869, objectui#4648, objectstack#6946.