Skip to content

Commit 53e1488

Browse files
committed
test(spec,ui): the console twins refuse the aged-out App/Dashboard keys on their own; the kits' readers follow the one-major rule
The contract review of 93505c9 found the readers of the removed 16.x kits that the removal had not been shipped with: the spec package's own repo tests, the console's derived twins and their pins, and a react test pin on the ActionDef mirror. Spec repo tests (`test:repo`, Test Core 1/8): - Three surviving-kit tests asserted a major-17 ledger row this change deletes (`integration/ConnectorFieldMapping:transform`, `ui/PageHeaderProps:icon`); they now assert the one-major rule — the 17 table is gone and the row with it. - The check-mode leaf-collision fixtures lost their premise: the `data.query.distinct` clause left with the 16.x conversions and the `data/Index:type` tombstone with the 16.x tombstones. Re-picked to `api/PackageInstallManifest:capabilities` against the registered `manifest.capabilities` (kernel/Manifest's row, inherited through `ManifestSchema.extend`) and `system/BookGroup:translations` against `manifest.contributes.translations`. - Five tree-scoped absence kits found the fixtures this change moved onto surviving 17.x keys (migrate-meta-write, migrations.test, view-union-retirement-prescription, lint-liveness-properties); each kit's EXCLUDED set names the file with its reason. Console twins (`@object-ui/types`): `AppComponentSchema` and `DashboardComponentSchema` derive from the spec shapes by reference over a `.passthrough()` base, so the ten tombstones that aged out of `AppSchema` / `DashboardSchema` (version, homePageId, objects, apis, sharing, embed, mobileNavigation, aria; aria, performance) stopped being refused and were kept in silence. A new `agedOutSpecKeyRefusal` helper (`zod/tombstone.zod.ts`) declares each as the console's own refusal: `invalid_type` at the key's path, opening with the spec's unknown-key sentence and the guide sentence (a copy pinned equal to the spec's export, since the mirrors' import boundary admits no spec string), then where the value went. The TS twins carry `?: never`; the parity, twins-by-reference and dashboard-aria pins assert the refusal on both faces with the spec's unknown-key verdict as the control. The strict `DashboardWidgetSchema` needs no arm: its five aged-out keys meet the `.strict()` door, and the report-chart pins now read zod's `unrecognized_keys` there with the spec's guide-naming refusal as the contract leg. driver-sql: the storage/presentation classification of FieldSchema keys drops its `conditionalRequired` row (the test beside it refuses a classification the spec no longer declares). Console pins: the layout conversion-coverage row for `page:card → properties.body[]` is gone with the conversion; the react useActionEngine fixture keeps its stale `shortcut` on an entry of its own (an object literal with a mistyped member is not also checked for excess members, so the directive reported unused once `shortcut` left the mirror). The SDUI manifest is re-recorded for the moved source digests. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
1 parent 93505c9 commit 53e1488

40 files changed

Lines changed: 802 additions & 229 deletions

File tree

‎packages/drivers/driver-sql/src/builtin-column-collision.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,10 @@ export const FIELD_KEY_STORAGE_CLASS: Readonly<Record<string, FieldKeyClass>> =
119119
visibleWhen: 'presentation',
120120
readonlyWhen: 'presentation',
121121
requiredWhen: 'presentation',
122-
conditionalRequired: 'presentation',
122+
// `conditionalRequired` (the pre-17 spelling of `requiredWhen`) was a row
123+
// here while the spec carried its tombstone; the tombstone aged out of
124+
// `FieldSchema` at spec 18.2 (objectstack#25767, ADR-0087 one major on), and
125+
// the test beside this map refuses a classification the spec does not declare.
123126
dueLike: 'presentation', // declares a date a deadline (#22227) — read by the renderer's date cells, never by `createColumn`: the column is the date the type already sizes
124127
settledWhen: 'presentation', // the deadline's settle predicate (#22227), display only like `visibleWhen` — no DDL reads it
125128
conditionalFormatting: 'presentation', // a field's cell formatting rules (#22228), display only — no DDL reads it

‎packages/spec/scripts/build-schemas-check-mode.retired-keys.test.ts‎

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,27 @@ const ROOT_SCRIPTS = fileURLToPath(new URL('../../../scripts', import.meta.url))
5757
useSharedSandbox(ROOT_SCRIPTS);
5858

5959
/** Retired keys whose ONLY registered clause names a DIFFERENT def — the defect. */
60-
const LEAF_COLLIDER_A = 'api/HttpFindQueryParams:distinct';
60+
const LEAF_COLLIDER_A = 'api/PackageInstallManifest:capabilities';
6161

62-
/** …matched by this clause, which registers `data/Query`'s key, not this one. */
63-
const LEAF_COLLIDER_A_CLAUSE = 'data.query.distinct';
62+
/**
63+
* …matched by this clause, which registers `kernel/Manifest`'s key, not this
64+
* one: `PackageInstallManifestSchema` extends `ManifestSchema`, so the same
65+
* tombstone sits on a second def with no row of its own. Re-picked at spec 18.2
66+
* (#25767): the fixture was `api/HttpFindQueryParams:distinct` against
67+
* `data.query.distinct` until that clause left with the 16.x conversions.
68+
*/
69+
const LEAF_COLLIDER_A_CLAUSE = 'manifest.capabilities';
6470

65-
/** The issue's own `.type` shape: an index type dated by a flow node rename. */
66-
const LEAF_COLLIDER_B = 'data/Index:type';
71+
/**
72+
* A book group's i18n block: a surviving tombstone (`book.zod.ts`, no row of
73+
* its own) whose leaf a manifest retirement also spells. Re-picked at spec
74+
* 18.2 (#25767) with A: the issue's own fixture, `data/Index:type` against
75+
* `flow.node.type`, aged out with the 16.x tombstones.
76+
*/
77+
const LEAF_COLLIDER_B = 'system/BookGroup:translations';
6778

68-
/** …registered at protocol 11 by `flow-node-http-callout-rename`. Unrelated. */
69-
const LEAF_COLLIDER_B_CLAUSE = 'flow.node.type';
79+
/** …registered by `plugin-manifest-contributes-dead-members-retired` for the manifest's `contributes` block. Unrelated. */
80+
const LEAF_COLLIDER_B_CLAUSE = 'manifest.contributes.translations';
7081

7182
/** A key no build emits: the aged-out steady state a stale entry decays into. */
7283
const AGED_OUT_KEY = 'data/Object:zzAgedOutTombstone4659';
@@ -242,7 +253,7 @@ describe('build-schemas.ts — check (b) matches the exact retired key, not its
242253
'registering one key registers exactly that key — its neighbour with the same leaf still fails',
243254
{ timeout: SPAWN_TIMEOUT_MS },
244255
() => {
245-
// `data.query.distinct` covered A only by leaf; now even a REAL entry for
256+
// `manifest.capabilities` covered A only by leaf; now even a REAL entry for
246257
// B cannot cover A. This is the whole change in one run: membership is per
247258
// key, and nothing radiates from one registration to another.
248259
seedRetiredKeys({ [CURRENT_MAJOR]: [LEAF_COLLIDER_B] });

‎packages/spec/src/ai/agent-lifecycle-retirement.test.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,10 @@ describe('tree-scoped absence: nothing inside the declared radius still authors
296296
const EXCLUDED = new Set([
297297
// This pin authors the key to assert its refusal and its conversion.
298298
THIS_FILE,
299+
// The CLI write door's pin (#25767): its fixture authors the pre-retirement
300+
// agent on purpose, to assert `os migrate meta --from 17 --write` rewrites
301+
// it through this kit's D2 conversion — the kit's fixture at the CLI door.
302+
'packages/cli/test/migrate-meta-write.test.ts',
299303
]);
300304
const EXCLUDED_PREFIXES = [
301305
// The D2 conversion's fixture authors the pre-retirement agent on purpose.

‎packages/spec/src/data/object-external-sharing-model-retirement.test.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,12 @@ describe('tree-scoped absence: nothing inside the declared radius still authors
357357
'packages/lint/src/runtime-gate.datasource-writes.test.ts',
358358
'packages/lint/src/runtime-gate.inert-type-writes.test.ts',
359359
'packages/cli/test/i18n-flow-liveness-gate.test.ts',
360+
// The CLI write door's pin and the chain's own replay pin (#25767): each
361+
// authors the pre-retirement object on purpose, to assert the D2
362+
// conversion strips the key at `--from 17` — this kit's fixtures at the
363+
// two doors that replay it.
364+
'packages/cli/test/migrate-meta-write.test.ts',
365+
'packages/spec/src/migrations/migrations.test.ts',
360366
]);
361367
const EXCLUDED_PREFIXES = [
362368
// The D2 conversion's fixture authors the pre-retirement object on purpose.

‎packages/spec/src/integration/connector-sync-retirement.test.ts‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,10 +289,13 @@ describe('connector sync retirement — ADR-0087 registration', () => {
289289
]) {
290290
expect(RETIRED_DEFS_BY_MAJOR[18], `${def} must be declared`).toContain(def);
291291
}
292-
// The earlier `transform` retirement's key-grain row stays: its def left
293-
// whole, which is the steady state gate (b3) exempts — deleting the row
294-
// would erase the record that the key was ever retired.
295-
expect(RETIRED_KEYS_BY_MAJOR[17]).toContain('integration/ConnectorFieldMapping:transform');
292+
// The earlier `transform` retirement (17.0.0) was a key-grain row under
293+
// major 17. That whole table aged out at 18.2 (objectstack#25767, ADR-0087
294+
// amended 2026-10-26: a row lives one major past its tombstone, and the
295+
// record that the key was ever retired is the previous major's release
296+
// tag, not this registry). The row must not come back by itself.
297+
expect(RETIRED_KEYS_BY_MAJOR[17]).toBeUndefined();
298+
expect(Object.values(RETIRED_KEYS_BY_MAJOR).flat()).not.toContain('integration/ConnectorFieldMapping:transform');
296299
});
297300

298301
it('wires the D2 conversion into the step-18 chain as a retired, stamped, lossless strip', () => {

‎packages/spec/src/ui/page-header-breadcrumb-retirement.test.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,10 @@ describe('page:header breadcrumb retirement — the ADR-0087 ledger row', () =>
275275
it('declares ONE key under major 18', () => {
276276
expect(RETIRED_KEYS_BY_MAJOR[18]).toContain(REGISTERED_KEY);
277277
const all = Object.values(RETIRED_KEYS_BY_MAJOR).flat();
278+
// `ui/PageHeaderProps:icon` (17.0.0) stood first in this list until spec
279+
// 18.2: the major-17 table aged out one major on (objectstack#25767,
280+
// ADR-0087), so the row's surviving keys are the two 18 rows.
278281
expect(all.filter((k) => k.startsWith('ui/PageHeaderProps:'))).toEqual([
279-
'ui/PageHeaderProps:icon',
280282
REGISTERED_KEY,
281283
// #23650 retired the row's third key the same way.
282284
'ui/PageHeaderProps:showStar',

‎packages/spec/src/ui/page-header-show-star-retirement.test.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,12 +278,14 @@ describe('page:header showStar retirement — the D2 conversion', () => {
278278
});
279279

280280
describe('page:header showStar retirement — the ADR-0087 ledger row', () => {
281-
it('declares ONE key under major 18, beside the two this row lost before it', () => {
281+
it('declares ONE key under major 18, beside the one this row lost before it', () => {
282282
expect(RETIRED_KEYS_BY_MAJOR[18]).toContain(REGISTERED_KEY);
283283
const all = Object.values(RETIRED_KEYS_BY_MAJOR).flat();
284+
// `ui/PageHeaderProps:icon` (17.0.0) was the third key here until spec
285+
// 18.2: the major-17 table aged out one major on (objectstack#25767,
286+
// ADR-0087), leaving the two 18 rows.
284287
expect(all.filter((k) => k.startsWith('ui/PageHeaderProps:')).sort()).toEqual([
285288
'ui/PageHeaderProps:breadcrumb',
286-
'ui/PageHeaderProps:icon',
287289
REGISTERED_KEY,
288290
]);
289291
});

‎packages/spec/src/ui/view-item-owner-hidden-retirement.test.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,10 @@ describe('tree-scoped absence: no ViewItem record or flattened overlay inside th
308308
'packages/spec/src/ui/view-overlay-owner-hidden-retirement.test.ts',
309309
// This pin names the keys to assert their absence.
310310
THIS_FILE,
311+
// [#25767] The view union's prescription pin authors `owner` on a view
312+
// record on purpose, to assert the branch-typed refusal names this kit's
313+
// prescription.
314+
'packages/spec/src/ui/view-union-retirement-prescription.test.ts',
311315
]);
312316
const EXCLUDED_PREFIXES = [
313317
// The D2 conversion's fixture authors the pre-retirement record on purpose.

‎packages/spec/src/ui/view-list-filterable-fields-retirement.test.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,13 @@ describe('tree-scoped absence: no list-view payload inside the declared radius s
361361
// The `os lint` twin of that pin: `os lint` never parses, so the lint
362362
// rule reports the key by name, and this file authors it to assert that.
363363
'packages/lint/src/list-view-filterable-fields-retired.test.ts',
364+
// [#25767] The view union's prescription pin authors the key at the
365+
// container and overlay doors to assert the branch-typed refusal names this
366+
// kit's prescription, and the liveness advisory's witnesses author it on an
367+
// UNPARSED intake to prove the ledger's `dead` verdict still warns there —
368+
// both took this key over from `striped` when its 16.x tombstone aged out.
369+
'packages/spec/src/ui/view-union-retirement-prescription.test.ts',
370+
'packages/lint/src/lint-liveness-properties.test.ts',
364371
]);
365372
const EXCLUDED_PREFIXES = [
366373
// The D2 conversion's fixture authors the pre-retirement payload on purpose.

‎packages/spec/src/ui/visibility-alias-keys-retirement.test.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ describe('tree-scoped absence: nothing inside the declared radius still authors
250250
'packages/spec/src/ui/component.test.ts',
251251
// The view write door's generic moved-key projection, modelled on the old fold.
252252
'packages/metadata-protocol/src/protocol.project-storable-view-body.test.ts',
253+
// [#25767] The view union's prescription pin authors `visibleOn` on a form
254+
// overlay to assert the branch-typed refusal names the alias prescription.
255+
'packages/spec/src/ui/view-union-retirement-prescription.test.ts',
253256
]);
254257
const EXCLUDED_PREFIXES = [
255258
// The D2 conversions' fixtures and the stored-row replay pins author the pre-18 shapes on purpose.

0 commit comments

Comments
 (0)