diff --git a/packages/spec/src/system/metadata-form-zod-reconciliation.test.ts b/packages/spec/src/system/metadata-form-zod-reconciliation.test.ts index c3bc2007ee9..cc2c8d5ba6f 100644 --- a/packages/spec/src/system/metadata-form-zod-reconciliation.test.ts +++ b/packages/spec/src/system/metadata-form-zod-reconciliation.test.ts @@ -253,21 +253,21 @@ const LEDGER: ReadonlyArray = [ type: 'object', path: 'fieldGroups', key: 'defaultExpanded', - why: "`[DEPRECATED → collapse]` alias (ADR-0085), deliberately not offered to new authors (ruling record 5861442317, #19332): the parse maps it onto `collapse` only when `collapse` is absent (`true` → 'expanded', `false` → 'collapsed'), this repeater offers the canonical `collapse` select, and a second control beside it would teach the retired spelling", + why: "`[DEPRECATED → collapse]` alias (ADR-0085), deliberately not offered to new authors (ruling record 5861442317): the parse maps it onto `collapse` only when `collapse` is absent (`true` → 'expanded', `false` → 'collapsed'), this repeater offers the canonical `collapse` select, and a second control beside it would teach the retired spelling", }, { kind: 'omit', type: 'object', path: 'fieldGroups', key: 'collapsible', - why: "`[DEPRECATED → collapse]` UI-dialect alias (ADR-0085), one half of the `collapsible` / `collapsed` pair, deliberately not offered to new authors (ruling record 5861442317, #19332): the parse maps the pair onto `collapse` only when `collapse` is absent, this repeater offers the canonical `collapse` select, and the pair can spell the contradictions the enum replaced", + why: "`[DEPRECATED → collapse]` UI-dialect alias (ADR-0085), one half of the `collapsible` / `collapsed` pair, deliberately not offered to new authors (ruling record 5861442317): the parse maps the pair onto `collapse` only when `collapse` is absent, this repeater offers the canonical `collapse` select, and the pair can spell the contradictions the enum replaced", }, { kind: 'omit', type: 'object', path: 'fieldGroups', key: 'collapsed', - why: "`[DEPRECATED → collapse]` UI-dialect alias (ADR-0085), the other half of the `collapsible` / `collapsed` pair, deliberately not offered to new authors (ruling record 5861442317, #19332): the parse maps it onto `collapse` only when `collapse` is absent (`true` → 'collapsed' on its own), and this repeater offers the canonical `collapse` select", + why: "`[DEPRECATED → collapse]` UI-dialect alias (ADR-0085), the other half of the `collapsible` / `collapsed` pair, deliberately not offered to new authors (ruling record 5861442317): the parse maps it onto `collapse` only when `collapse` is absent (`true` → 'collapsed' on its own), and this repeater offers the canonical `collapse` select", }, // ── The `inlineColumns` repeater (ruling record 5861442317, #19332) ── // @@ -280,7 +280,7 @@ const LEDGER: ReadonlyArray = [ kind: 'subset', type: 'field', path: 'inlineColumns', - why: "a curated inline-grid column (ruling record 5861442317, #19332): `name` plus the three keys that apply to a column of any type (`label`, `width`, `defaultHidden`). An entry naming only a field is the shape the key's own describe recommends, because objectui's `hydrateColumns` completes it from the child field, so the rest is authored in source: `type`, since declaring it opts the column out of that hydration; the keys that apply to one cell type only (`options`, `reference`, `displayField`, `idField`, `autofill`, `multiple`, `accept`, `prefix`, `step`, `scale`, `computed`, `expr`), since a column takes its type from the child field at render and a sub-row here cannot be gated on it, so each would be offered on every column; and `required` / `readonlyWhen` / `requiredWhen`, which hydration copies from the child field, where the rule the server enforces lives", + why: "a curated inline-grid column (ruling record 5861442317): `name` plus the three keys that apply to a column of any type (`label`, `width`, `defaultHidden`). An entry naming only a field is the shape the key's own describe recommends, because objectui's `hydrateColumns` completes it from the child field, so the rest is authored in source: `type`, since declaring it opts the column out of that hydration; the keys that apply to one cell type only (`options`, `reference`, `displayField`, `idField`, `autofill`, `multiple`, `accept`, `prefix`, `step`, `scale`, `computed`, `expr`), since a column takes its type from the child field at render and a sub-row here cannot be gated on it, so each would be offered on every column; and `required` / `readonlyWhen` / `requiredWhen`, which hydration copies from the child field, where the rule the server enforces lives", }, // ── The root coordinate (#19333): top-level keys no form may offer ── // @@ -423,35 +423,35 @@ const LEDGER: ReadonlyArray = [ type: 'object', path: ROOT_PATH, key: 'actions', - why: "authored through its own editor — the `action` type (ruling record 5861442317, #19332): each element is that type's own node, the schema `getMetadataTypeSchema('action')` answers and `action.form.ts` edits, and the key's own describe says the list is `auto-populated from top-level actions via objectName`, so an inline editor here would be a second, poorer copy of the action form", + why: "authored through its own editor — the `action` type (ruling record 5861442317): each element is that type's own node, the schema `getMetadataTypeSchema('action')` answers and `action.form.ts` edits, and the key's own describe says the list is `auto-populated from top-level actions via objectName`, so an inline editor here would be a second, poorer copy of the action form", }, { kind: 'omit', type: 'object', path: ROOT_PATH, key: 'listViews', - why: "authored through its own editor — the `view` type (ruling record 5861442317, #19332; per-arm view forms under the #19330 ruling, letter A): each value is the very node the `view` container declares under the same key (`ObjectListViewSchema`), which is where the example apps and HotCRM write their list views (`defineView({ listViews })`), so an inline editor here would be a second list-view editor beside the view type's", + why: "authored through its own editor — the `view` type (ruling record 5861442317; per-arm view forms, ruled: one registered form per view kind): each value is the very node the `view` container declares under the same key (`ObjectListViewSchema`), which is where the example apps and HotCRM write their list views (`defineView({ listViews })`), so an inline editor here would be a second list-view editor beside the view type's", }, { kind: 'omit', type: 'page', path: ROOT_PATH, key: 'slots', - why: 'authored through its own editor — the page designer (ruling record 5861442317, #19332): the Studio page designer writes `slots.NAME` one slot at a time from its block inspector, and each slot holds a component tree (a `PageComponentSchema` or an array of them) that the designer composes block by block, so an inline editor here would be a second, poorer designer', + why: 'authored through its own editor — the page designer (ruling record 5861442317): the Studio page designer writes `slots.NAME` one slot at a time from its block inspector, and each slot holds a component tree (a `PageComponentSchema` or an array of them) that the designer composes block by block, so an inline editor here would be a second, poorer designer', }, { kind: 'omit', type: 'object', path: ROOT_PATH, key: 'external', - why: 'authored through its own editor — the import flow (ruling record 5861442317, #19332): the external-datasource import, which the Studio import dialog and `os datasource introspect` both reach through `POST /datasources/:name/external/tables/:remote/draft`, drafts the binding from the remote table it read, so the binding comes from the remote table rather than from a name typed into this form', + why: 'authored through its own editor — the import flow (ruling record 5861442317): the external-datasource import, which the Studio import dialog and `os datasource introspect` both reach through `POST /datasources/:name/external/tables/:remote/draft`, drafts the binding from the remote table it read, so the binding comes from the remote table rather than from a name typed into this form', }, { kind: 'omit', type: 'field', path: ROOT_PATH, key: 'picklist', - why: "authored through its own editor — the object designer's shared-picklist picker (ruling record 5861442317, #19332; the picker placed there by ruling record 5755653853, #18164 batch #209 item 1 A): the key is enforced, liveness verdict `live` (the server resolves the named picklist onto the served field's `options` and judges a write against that set), and its offer was decided as that picker in the object designer's select-field editor, so a text row in this form would be a second, weaker entry beside it, where an author types a list name instead of picking one", + why: "authored through its own editor — the object designer's shared-picklist picker (ruling record 5861442317; the picker placed there by ruling record 5755653853): the key is enforced, liveness verdict `live` (the server resolves the named picklist onto the served field's `options` and judges a write against that set), and its offer was decided as that picker in the object designer's select-field editor, so a text row in this form would be a second, weaker entry beside it, where an author types a list name instead of picking one", }, // Code-declared platform configuration (ruling record 5861442317, #19332): @@ -467,28 +467,28 @@ const LEDGER: ReadonlyArray = [ type: 'object', path: ROOT_PATH, key: 'tenancy', - why: 'code-declared platform configuration (ruling record 5861442317, #19332): an isolation switch, where `enabled: false` takes the object out of organization scoping (the `isTenancyDisabled` opt-out the SQL driver honours and the security plugin reads), written only by platform objects declared in code (`sys_api_key`, `sys_sso_provider`), so a form row would put organization isolation one click away', + why: 'code-declared platform configuration (ruling record 5861442317): an isolation switch, where `enabled: false` takes the object out of organization scoping (the `isTenancyDisabled` opt-out the SQL driver honours and the security plugin reads), written only by platform objects declared in code (`sys_api_key`, `sys_sso_provider`), so a form row would put organization isolation one click away', }, { kind: 'omit', type: 'object', path: ROOT_PATH, key: 'systemFields', - why: "code-declared platform configuration (ruling record 5861442317, #19332): an isolation switch, where `{ tenant: false }` withholds `organization_id` and reads as the tenancy opt-out on the object's security posture, and `false` withholds every injected column, the audit family included (`resolveInjectedSystemColumns`), written only by a platform object declared in code (`sys_metadata_activation`, `{ tenant: false }`), so a form row would put both one click away", + why: "code-declared platform configuration (ruling record 5861442317): an isolation switch, where `{ tenant: false }` withholds `organization_id` and reads as the tenancy opt-out on the object's security posture, and `false` withholds every injected column, the audit family included (`resolveInjectedSystemColumns`), written only by a platform object declared in code (`sys_metadata_activation`, `{ tenant: false }`), so a form row would put both one click away", }, { kind: 'omit', type: 'app', path: ROOT_PATH, key: 'contextSelectors', - why: 'code-declared platform configuration (ruling record 5861442317, #19332): scope dropdowns, each fetching its options from a REST endpoint through a key mapping (`optionsSource`), written only by an app declared in code (the Studio app, `studio.app.ts`), so offering one needs a designed control for an endpoint mapping, a form-face addition rather than a reconciliation', + why: 'code-declared platform configuration (ruling record 5861442317): scope dropdowns, each fetching its options from a REST endpoint through a key mapping (`optionsSource`), written only by an app declared in code (the Studio app, `studio.app.ts`), so offering one needs a designed control for an endpoint mapping, a form-face addition rather than a reconciliation', }, { kind: 'omit', type: 'action', path: ROOT_PATH, key: 'resultDialog', - why: 'code-declared platform configuration (ruling record 5861442317, #19332): the one-shot reveal of what an API action returns (a TOTP URI, backup codes, a freshly minted OAuth client secret), written only by the actions of identity platform objects declared in code (`sys_user`, `sys_two_factor`, `sys_oauth_application`, `sys_sso_provider`), so offering it needs a designed control for its `fields` list, a form-face addition rather than a reconciliation', + why: 'code-declared platform configuration (ruling record 5861442317): the one-shot reveal of what an API action returns (a TOTP URI, backup codes, a freshly minted OAuth client secret), written only by the actions of identity platform objects declared in code (`sys_user`, `sys_two_factor`, `sys_oauth_application`, `sys_sso_provider`), so offering it needs a designed control for its `fields` list, a form-face addition rather than a reconciliation', }, // No registered widget spells this union (ruling record 5861442317, @@ -504,21 +504,21 @@ const LEDGER: ReadonlyArray = [ type: 'object', path: ROOT_PATH, key: 'stageField', - why: 'no registered widget spells this union (ruling record 5861442317, #19332): a field name or `false` (the status field is non-linear, so the stage heuristics are suppressed), and `false` cannot be an option value while a union renders only its first arm on create, so a control would offer the name and never reach `false`', + why: 'no registered widget spells this union (ruling record 5861442317): a field name or `false` (the status field is non-linear, so the stage heuristics are suppressed), and `false` cannot be an option value while a union renders only its first arm on create, so a control would offer the name and never reach `false`', }, { kind: 'omit', type: 'field', path: ROOT_PATH, key: 'inlineEdit', - why: "no registered widget spells this union (ruling record 5861442317, #19332): `true` / `false` or `'grid'` / `'form'`, and a boolean cannot be an option value while a union renders only its first arm on create, so a control would be a switch that never reaches `'grid'` or `'form'`", + why: "no registered widget spells this union (ruling record 5861442317): `true` / `false` or `'grid'` / `'form'`, and a boolean cannot be an option value while a union renders only its first arm on create, so a control would be a switch that never reaches `'grid'` or `'form'`", }, { kind: 'omit', type: 'field', path: ROOT_PATH, key: 'relatedList', - why: "no registered widget spells this union (ruling record 5861442317, #19332): `true` / `false` or `'primary'`, and a boolean cannot be an option value while a union renders only its first arm on create, so a control would be a switch that never promotes the list to its own tab (`'primary'`)", + why: "no registered widget spells this union (ruling record 5861442317): `true` / `false` or `'primary'`, and a boolean cannot be an option value while a union renders only its first arm on create, so a control would be a switch that never promotes the list to its own tab (`'primary'`)", }, // Measured, and deliberately NOT recorded: seven `view` keys with no @@ -877,13 +877,13 @@ function reconcileRoot(type: string, form: any, root: unknown, ledger: Ledger): * type, and a union-rooted one cannot slip into the direction unexcused. */ const TOP_LEVEL_DEFERRED: Readonly> = { - view: "union-rooted: its four arms declare mutually exclusive keys, so the one registered view form cannot offer them all. It is reconciled per arm, each arm against its own registered form (the #19330 ruling, letter A); until the first arm form exists, the top-level direction covers the object-rooted types only", + view: "union-rooted: its four arms declare mutually exclusive keys, so the one registered view form cannot offer them all. It is reconciled per arm, each arm against its own registered form, as ruled; until the first arm form exists, the top-level direction covers the object-rooted types only", }; /** The types the top-level zod-only direction judges. */ const TOP_LEVEL_TYPES = TYPES.filter((type) => !(type in TOP_LEVEL_DEFERRED)); -describe('metadata form ↔ Zod reconciliation (#3786)', () => { +describe('metadata form ↔ Zod reconciliation — a hand-written form held to its schema by a gate', () => { it('the registry is non-empty and every form resolves a schema', () => { // Without this the per-type assertions below would pass over an empty set — // the failure mode a reconciliation test must not have. @@ -1045,7 +1045,7 @@ describe('metadata form ↔ Zod reconciliation (#3786)', () => { // filters nothing and still reports green. // ──────────────────────────────────────────────────────────────────────────── -describe('retiredKey tombstones are not authoring surface (#5280)', () => { +describe('retiredKey tombstones are not authoring surface', () => { const probe = z.object({ gone: retiredKey('`Probe.gone` was removed in @objectstack/spec 17.0.0. Delete the key.'), live: z.string().optional(), @@ -1107,7 +1107,7 @@ describe('retiredKey tombstones are not authoring surface (#5280)', () => { // control). // ──────────────────────────────────────────────────────────────────────────── -describe('the nested walk reaches every depth (#14327)', () => { +describe('the nested walk reaches every depth', () => { it('the live registry has hand-written lists below depth one, and the walk reaches them', () => { const deep = TYPES.flatMap((type) => nestedLists(METADATA_FORM_REGISTRY[type]) @@ -1497,7 +1497,7 @@ function unspellableArmValuesOf(type: string, key: string): unknown[] | undefine return values; } -describe('the three ruled root reasons admit only the keys ruled into them (#19332)', () => { +describe('the three ruled root reasons admit only the keys ruled into them', () => { const rootRows = LEDGER.filter((e): e is OmitEntry => e.kind === 'omit' && e.path === ROOT_PATH); const rowsOf = (reason: string) => rootRows.filter((e) => e.why.startsWith(reason)); const label = (e: OmitEntry) => `${e.type}.${e.key}`; diff --git a/packages/spec/src/system/metadata-persistence.test.ts b/packages/spec/src/system/metadata-persistence.test.ts index 53f99379591..33521527095 100644 --- a/packages/spec/src/system/metadata-persistence.test.ts +++ b/packages/spec/src/system/metadata-persistence.test.ts @@ -573,7 +573,7 @@ describe('PackagePublishResultSchema', () => { // (`filesystem-loader.ts`, `database-loader.ts`) or writes a literal `0` // (`memory-loader.ts`, `remote-loader.ts`). Milliseconds, integral, non-negative // — which is exactly `DurationMs`. -describe('metadata load/save result durations declare milliseconds (#18124)', () => { +describe('metadata load/save result durations declare milliseconds', () => { it('loadTime refuses a fractional millisecond count and a negative span', () => { const fractional = MetadataLoadResultSchema.safeParse({ data: null, loadTime: 42.5 }); expect(fractional.success).toBe(false); diff --git a/packages/spec/src/system/metrics.test.ts b/packages/spec/src/system/metrics.test.ts index 3890d725227..2a3f205da19 100644 --- a/packages/spec/src/system/metrics.test.ts +++ b/packages/spec/src/system/metrics.test.ts @@ -497,7 +497,7 @@ describe('MetricsConfigSchema', () => { // gate's mechanical `sizeSeconds`: `size` is byte/row-count vocabulary elsewhere // in this spec, and the parent key is already `window`, so `windowSeconds` would // read `window.windowSeconds`. -describe('metrics window and period lengths carry their unit (#15679)', () => { +describe('metrics window and period lengths carry their unit in the key name', () => { const sliBase = { name: 'api_availability', label: 'API Availability', @@ -581,7 +581,7 @@ describe('metrics window and period lengths carry their unit (#15679)', () => { // Three of the five new names are not the mechanical suffix: see the tombstone // prose on each key for why `windowSeconds`, `periodSeconds` and a bare // `intervalSeconds` were rejected. -describe('metrics JSDoc-only durations carry their unit (#15939, #14478)', () => { +describe('metrics JSDoc-only durations carry their unit in the describe and the key name', () => { const sliBase = { name: 'api_availability', label: 'API Availability', @@ -734,7 +734,7 @@ describe('metrics JSDoc-only durations carry their unit (#15939, #14478)', () => // // Both keep the `.positive()` floor they already declared, so the accepted set // narrows only by the integer requirement `DurationSeconds` carries. -describe('metrics duration rows declare seconds through the type (#18124)', () => { +describe('metrics duration rows declare seconds through the type', () => { const window = { durationSeconds: 300, sliding: true }; it('slideInterval refuses a fractional second count', () => { @@ -821,7 +821,7 @@ describe('metrics duration rows declare seconds through the type (#18124)', () = * delete it, because the day it silently stops being true is the day the * retirement stops being audible in one of its two spellings. */ -describe('#18118 ServiceLevelIndicator.successCriteria — the retired CEL arm', () => { +describe('ServiceLevelIndicator.successCriteria — the retired CEL arm', () => { const sli = (successCriteria: unknown) => ServiceLevelIndicatorSchema.safeParse({ name: 'api_latency', label: 'API Latency', diff --git a/packages/spec/src/system/notification-event-migration-retirement.test.ts b/packages/spec/src/system/notification-event-migration-retirement.test.ts index 611d467ec9e..1cf1cb15500 100644 --- a/packages/spec/src/system/notification-event-migration-retirement.test.ts +++ b/packages/spec/src/system/notification-event-migration-retirement.test.ts @@ -121,7 +121,7 @@ const PRE_RETIREMENT_MATRIX = `/** * - \`details.outcome\`: the four-valued result, verbatim. */`; -describe('[#16194] adr-0030-notification-event: the id left the creation-attested set', () => { +describe('adr-0030-notification-event: the id left the creation-attested set', () => { it('CREATION_ATTESTED_MIGRATION_IDS is exactly the TWO surviving ids, in order', () => { // Literal on purpose. A length alone would not notice which member went, // and a `not.toContain` alone would pass on an array that lost everything. @@ -157,12 +157,12 @@ describe('[#16194] adr-0030-notification-event: the id left the creation-atteste }); }); -describe('[#16194] adr-0030-notification-event: the ruled receipt-claim matrix is withdrawn', () => { +describe('adr-0030-notification-event: the ruled receipt-claim matrix is withdrawn', () => { it("the id's docblock no longer states a ledger-claim matrix", () => { const doc = notificationEventDoc(); expect( statesClaimMatrix(doc), - 'a receipt-claim matrix is back on an id no code can write a row for — re-read #16194', + 'a receipt-claim matrix is back on an id no code can write a row for — its runner was retired, with no operator door and no boot-time invoker', ).toBe(false); }); diff --git a/packages/spec/src/system/notification.test.ts b/packages/spec/src/system/notification.test.ts index 38928c51813..e28f95ce841 100644 --- a/packages/spec/src/system/notification.test.ts +++ b/packages/spec/src/system/notification.test.ts @@ -57,7 +57,7 @@ describe('NotificationChannelSchema', () => { // gate that cannot fail. Sabotage-verified in the PR: S1 re-declares a removed // const in notification.zod.ts, S2 re-exports it from another entry under the // bare name (the route a "./system does not export it" assertion would miss). -describe('[#4616] notification-template orphan removal', () => { +describe('notification-template orphan removal', () => { /** Names that must not be exported by ANY public entry point. */ const REMOVED = [ // #4616 — this change. diff --git a/packages/spec/src/system/object-storage.test.ts b/packages/spec/src/system/object-storage.test.ts index 8f3d016ee67..378a0009247 100644 --- a/packages/spec/src/system/object-storage.test.ts +++ b/packages/spec/src/system/object-storage.test.ts @@ -861,7 +861,7 @@ describe('ObjectStorageConfigSchema', () => { // twin mirrors carries no unit token. No gate can catch the twin being renamed // along with this one — the marker exempts it either way — so a find-and-replace // that harmonised the two would land silently. The pin below is the only guard. -describe('object-storage durations carry their unit (#15679)', () => { +describe('object-storage durations carry their unit in the key name', () => { it('REFUSES the retired `AccessControlConfig.maxAge` with the rename in the message', () => { const result = AccessControlConfigSchema.safeParse({ corsEnabled: true, maxAge: 3600 }); expect(result.success).toBe(false); diff --git a/packages/spec/src/system/operation-message.test.ts b/packages/spec/src/system/operation-message.test.ts index 7be876ae3a5..141e2050880 100644 --- a/packages/spec/src/system/operation-message.test.ts +++ b/packages/spec/src/system/operation-message.test.ts @@ -98,7 +98,7 @@ describe('operation message catalog', () => { * `packages/plugins/plugin-security/src/permission-denied-user-copy.test.ts`, * against the real middleware and a real `II18nService`. */ -describe('operation message catalog — permission_denied (#7414)', () => { +describe('operation message catalog — permission_denied, the 403 refusal as localized user copy', () => { /** * The vocabulary a business user must never read in a permission refusal. * `positions` is the internal authorization noun the reporter quoted; the @@ -190,7 +190,7 @@ describe('operation message catalog — permission_denied (#7414)', () => { * capability AND-gate) deliberately reuses it, so its catalog coverage above is * already the coverage for that gate. */ -describe('operation message catalog — the row-level user copy (#7451)', () => { +describe('operation message catalog — the row-level user copy, a sentence per situation', () => { /** * The vocabulary a business user must never read in a row-level refusal. It * is the #7414 list plus the two nouns these particular gates leaked: @@ -303,7 +303,7 @@ describe('operation message catalog — the row-level user copy (#7451)', () => * this catalog block is the only pin the keys have — same battery the #7451 * family keys get. */ -describe('operation message catalog — sharing write denial and approvals recall (#12493)', () => { +describe('operation message catalog — sharing write denial and approvals recall, two keys of their own', () => { /** * The vocabulary a business user must never read in these refusals. It is * the #7451 list plus the exact nouns the two measured raw strings leaked: diff --git a/packages/spec/src/system/registry-config.test.ts b/packages/spec/src/system/registry-config.test.ts index 0b0ecdf2878..c4a9bba8402 100644 --- a/packages/spec/src/system/registry-config.test.ts +++ b/packages/spec/src/system/registry-config.test.ts @@ -212,7 +212,7 @@ describe('RegistryConfigSchema', () => { // lines apart, both bare, and the `min(1000)` bound on the timeout reads as one // second under the right unit and sixteen minutes under the wrong one — both in // range, so no parse could have caught the mistake. -describe('registry duration keys carry their unit (#15679)', () => { +describe('registry duration keys carry their unit in the key name', () => { const url = 'https://registry.example.com'; it('REFUSES the retired `syncInterval` with the rename in the message', () => { diff --git a/packages/spec/src/system/settings-manifest.test.ts b/packages/spec/src/system/settings-manifest.test.ts index 1e2b3d55d36..acab7461a50 100644 --- a/packages/spec/src/system/settings-manifest.test.ts +++ b/packages/spec/src/system/settings-manifest.test.ts @@ -195,7 +195,7 @@ describe('SpecifierSchema — layout-only specifiers', () => { }); }); -describe('SpecifierValueDomainSchema — the closed standard-domain vocabulary (#5933)', () => { +describe('SpecifierValueDomainSchema — the closed standard-domain vocabulary', () => { it('accepts exactly the three domains with measured authoring pull', () => { for (const d of ['iana_time_zone', 'iso_4217_currency', 'iso_3166_alpha2']) { expect(() => SpecifierValueDomainSchema.parse(d)).not.toThrow(); @@ -227,7 +227,7 @@ describe('SpecifierValueDomainSchema — the closed standard-domain vocabulary ( }); }); -describe('Specifier.valueDomain (#5933)', () => { +describe('Specifier.valueDomain — a declared standard domain is the boundary, `options` a UI list', () => { it('SURVIVES the parse — a dropped key is the defect this closes', () => { // #5712's dev measured the current shape by smuggling a `format` key in: // Zod stripped it and `parse()` returned `undefined`, so the manifest had @@ -243,7 +243,7 @@ describe('Specifier.valueDomain (#5933)', () => { expect(parsed.valueDomain).toBe('iana_time_zone'); }); - it('is optional — an undeclared specifier keeps #5131 exhaustive-options semantics', () => { + it('is optional — an undeclared specifier keeps exhaustive-options semantics, enforced at save', () => { const parsed = SpecifierSchema.parse({ type: 'select', key: 'provider', @@ -303,7 +303,7 @@ describe('Specifier.valueDomain (#5933)', () => { }); }); -describe('`visible` — the settings visibility grammar (#7327)', () => { +describe('`visible` — the settings visibility grammar, narrowed to what the save-time evaluator runs', () => { const withVisible = (visible: unknown) => SpecifierSchema.safeParse({ type: 'text', key: 'smtp_host', label: 'Host', visible }); const firstMessage = (visible: unknown): string => { @@ -335,7 +335,7 @@ describe('`visible` — the settings visibility grammar (#7327)', () => { expect(withVisible({ dialect: 'cel', source: "${data.provider === 'smtp'}" }).success).toBe(true); }); - it('REFUSES an `ast`-only envelope — #15811 moved this slot onto the evaluated rule', () => { + it('REFUSES an `ast`-only envelope — an evaluated slot requires a non-blank `source`', () => { // It used to pass: the AST is opaque at this layer and the grammar walk had // nothing to read, so the slot admitted an envelope `evaluateVisibility` // could never run and the refusal arrived at the tenant's next save. Since diff --git a/packages/spec/src/system/stack-server.test.ts b/packages/spec/src/system/stack-server.test.ts index e2a8af2f00e..d61e3c4c118 100644 --- a/packages/spec/src/system/stack-server.test.ts +++ b/packages/spec/src/system/stack-server.test.ts @@ -58,7 +58,7 @@ describe('server: reaches the runtime through defineStack', () => { }); }); -describe('server: carries only keys with a consumer (#4938 stays shut)', () => { +describe('server: carries only keys with a consumer — the retired HttpServerConfig keys stay out', () => { it('declares exactly `security` and `trustProxy`', () => { // The hard constraint from the 2026-08-03 adjudication. If this list grows, // the new key must have arrived with an executor — the whole reason the @@ -90,7 +90,7 @@ describe('server: carries only keys with a consumer (#4938 stays shut)', () => { }); }); -describe('server.security.rateLimit is strict from birth (#4001)', () => { +describe('server.security.rateLimit is strict from birth', () => { it('accepts every declared key', () => { expect(ServerRateLimitConfigSchema.parse({ enabled: true, windowMs: 1000, maxRequests: 3 })) .toEqual({ enabled: true, windowMs: 1000, maxRequests: 3 }); diff --git a/packages/spec/src/system/tenant-provisioning-family-retired.test.ts b/packages/spec/src/system/tenant-provisioning-family-retired.test.ts index 332be5d3764..20391569d26 100644 --- a/packages/spec/src/system/tenant-provisioning-family-retired.test.ts +++ b/packages/spec/src/system/tenant-provisioning-family-retired.test.ts @@ -34,7 +34,7 @@ import { // was a no-op until #5286 (tsconfig excluded `**/*.test.ts`; vitest never enables // `typecheck`), so the load-bearing pin is the export-origins test below, with // anti-vacuity guards. -describe('[#4739 / #16325] the system-side provisioning family stays retired, and `TenantPlan` has left the package', () => { +describe('the system-side provisioning family stays retired, and `TenantPlan` has left the package', () => { it('resolves the export surface: ./system and ./contracts name none of the retired family', () => { // Anti-vacuity: the baseline must cover the real surface (`export-origins/` // IS the resolution, computed at build time and checked in — #4796). diff --git a/packages/spec/src/system/tenant.test.ts b/packages/spec/src/system/tenant.test.ts index 274e1d5ad7e..a825c735b8c 100644 --- a/packages/spec/src/system/tenant.test.ts +++ b/packages/spec/src/system/tenant.test.ts @@ -710,7 +710,7 @@ describe('QuotaEnforcementResultSchema', () => { // reference-page reader could not tell 300 seconds from 300 milliseconds. // Renamed with the unit in the key; the old spellings are retiredKey // tombstones (the nested objects are not strict). -describe('tenant idleTimeout / sessionTimeout → *Seconds (#14478, #14519)', () => { +describe('tenant idleTimeout / sessionTimeout → *Seconds', () => { it('REFUSES `connectionPool.idleTimeout` with a rename naming `idleTimeoutSeconds`', () => { const result = DatabaseLevelIsolationStrategySchema.safeParse({ strategy: 'isolated_db', @@ -747,7 +747,7 @@ describe('tenant idleTimeout / sessionTimeout → *Seconds (#14478, #14519)', () expect(TenantSecurityPolicySchema.parse({ accessControl: {} }).accessControl?.sessionTimeoutSeconds).toBe(3600); }); - it('publishes the unit in the describe — the text the reference pages render (#14519)', () => { + it('publishes the unit in the describe — the text the reference pages render', () => { const pool = DatabaseLevelIsolationStrategySchema.shape.connectionPool.unwrap().shape.idleTimeoutSeconds; const access = TenantSecurityPolicySchema.shape.accessControl.unwrap().shape.sessionTimeoutSeconds; expect(pool.description).toBe('Idle pool timeout in seconds'); @@ -760,7 +760,7 @@ describe('tenant idleTimeout / sessionTimeout → *Seconds (#14478, #14519)', () // so the reference-page reader could not tell 3600 seconds from 3600 // milliseconds. Renamed with the unit in the key; the old spelling is a // retiredKey tombstone (the nested `performance` object is not strict). -describe('tenant schemaCacheTTL → schemaCacheTtlSeconds (#15939, #14478)', () => { +describe('tenant schemaCacheTTL → schemaCacheTtlSeconds', () => { it('REFUSES `performance.schemaCacheTTL` with a rename naming `schemaCacheTtlSeconds`', () => { const result = SchemaLevelIsolationStrategySchema.safeParse({ strategy: 'isolated_schema', diff --git a/packages/spec/src/system/tracing.test.ts b/packages/spec/src/system/tracing.test.ts index 0308ab21584..faaac2eb7c4 100644 --- a/packages/spec/src/system/tracing.test.ts +++ b/packages/spec/src/system/tracing.test.ts @@ -521,7 +521,7 @@ describe('TracingConfigSchema', () => { // never on a bare `toThrow()`. A span is runtime-emitted, so the silent-strip // alternative is the real hazard here: an exporter still writing `duration` // would have lost the measurement without any error at all. -describe('Span.duration carries its unit (#15679)', () => { +describe('Span.duration carries its unit in the key name', () => { const base = { context: { traceId: '0123456789abcdef0123456789abcdef', spanId: '0123456789abcdef' }, name: 'GET /api/users', @@ -562,7 +562,7 @@ describe('Span.duration carries its unit (#15679)', () => { // These shapes are NOT `.strict()`, so `unrecognized_keys` was never the // alternative: a bare deletion would have been a silent strip that lands a // default on an exporter deadline. -describe('the OTel exporter and performance durations carry their unit (#17785)', () => { +describe('the OTel exporter and performance durations carry their unit in the describe and the key name', () => { const otelBase = { exporter: { type: 'console' as const }, resource: { serviceName: 'test' }, @@ -718,7 +718,7 @@ describe('the OTel exporter and performance durations carry their unit (#17785)' * about the other. The negative is pinned too: a value refused for a reason * that is NOT the retirement must not borrow its sentence. */ -describe('#18118 TraceSamplingConfig.composite[].condition — the retired CEL arm', () => { +describe('TraceSamplingConfig.composite[].condition — the retired CEL arm', () => { const parse = (condition: unknown) => TraceSamplingConfigSchema.safeParse({ type: 'composite', composite: [{ strategy: 'always_on', condition }], diff --git a/packages/spec/src/system/translation.test.ts b/packages/spec/src/system/translation.test.ts index 72272194218..120224ed511 100644 --- a/packages/spec/src/system/translation.test.ts +++ b/packages/spec/src/system/translation.test.ts @@ -669,7 +669,7 @@ describe('TranslationItemSchema', () => { expect(message).toContain('apps.'); }); - it('should reject an unknown key the retired-key list never named (#4001)', () => { + it('should reject an unknown key the retired-key list never named', () => { // What the #3778 guard could not do. It enumerated ten keys someone had // thought of; `object` for `objects` was not one of them, and a bundle // written that way saved clean and resolved to nothing. @@ -710,7 +710,7 @@ describe('TranslationItemSchema', () => { expect(item._lock).toBe('no-overlay'); }); - it('should reject the retired shape rather than silently stripping it (#3778)', () => { + it('should reject the retired object-first `o.` shape rather than silently stripping it', () => { // The pre-fix failure mode: Zod strips undeclared keys, so an `o.`-shaped // item saved cleanly and then resolved to nothing. A save that succeeds // must be a save that renders. @@ -764,7 +764,7 @@ describe('TranslationItemSchema', () => { // Unknown-key strictness across the translation groups (#4001) // ============================================================================ -describe('translation unknown-key strictness (#4001)', () => { +describe('translation unknown-key strictness', () => { // The failure this file is closing is unusually cruel: a translation that // resolves to nothing is indistinguishable from a translation nobody wrote. // There is no wrong string on screen to notice — just the source language, @@ -837,7 +837,7 @@ describe('translation unknown-key strictness (#4001)', () => { // ────────────────────────────────────────────────────────────────────────── // #16772 — `dashboards..globalFilters.`, the filter bar's copy // ────────────────────────────────────────────────────────────────────────── - describe('dashboard global-filter copy (#16772)', () => { + describe('dashboard global-filter copy, addressable from a bundle by filter name', () => { const parse = (globalFilters: unknown) => TranslationDataSchema.safeParse({ dashboards: { sales: { label: 'Sales', globalFilters } } }); @@ -898,7 +898,7 @@ describe('translation unknown-key strictness (#4001)', () => { // ────────────────────────────────────────────────────────────────────────── // #6080 — `pages..components.`, the page half of `dashboards.widgets` // ────────────────────────────────────────────────────────────────────────── - describe('page component copy (#6080)', () => { + describe('page component copy, keyed by component id', () => { const parse = (components: unknown) => TranslationDataSchema.safeParse({ pages: { sales_home_page: { label: 'Sales', components } } }); @@ -912,7 +912,7 @@ describe('translation unknown-key strictness (#4001)', () => { expect(result.success).toBe(true); }); - it('refuses `submitLabel` with the retirement prescription (#10926)', () => { + it('refuses `submitLabel` with the retirement prescription', () => { // Flipped, not deleted: until commit d173125fb this case pinned `submitLabel` as // an accepted copy key (latterly on a bespoke component type, after // #9249 retired `element:form`, its only spec-declared carrier). The @@ -1002,7 +1002,7 @@ describe('translation unknown-key strictness (#4001)', () => { // retirement as `guidance` rather than a rename onto a tombstone. A widget // keeps one authored description, `widget.description`. // ────────────────────────────────────────────────────────────────────────── - describe('dashboard widget sub-caption — retired (#21257)', () => { + describe('dashboard widget sub-caption — retired', () => { const parse = (widgets: unknown) => TranslationDataSchema.safeParse({ dashboards: { sales: { widgets } } }); @@ -1079,7 +1079,7 @@ describe('translation unknown-key strictness (#4001)', () => { // ────────────────────────────────────────────────────────────────────────── // #7646 — `flows..screens.`, the screen-flow wizard's copy // ────────────────────────────────────────────────────────────────────────── - describe('screen-flow copy (#7646)', () => { + describe('screen-flow copy — a `flows` bundle group, runner chrome kept out', () => { const parse = (flows: unknown) => TranslationDataSchema.safeParse({ flows }); it('accepts a fully-populated flow entry', () => { @@ -1258,7 +1258,7 @@ describe('translation unknown-key strictness (#4001)', () => { expect(TranslationItemSchema.safeParse({ locale: 'zh-CN', flows: { f: { titel: 'x' } } }).success).toBe(false); }); - it('declares exactly the keys the resolver and the extractor act on (#11287)', () => { + it('declares exactly the keys the resolver and the extractor act on', () => { // `FLOW_SCREEN_COPY_KEYS` / `FLOW_SCREEN_FIELD_COPY_KEYS` drive // `translateFlow`'s overlay and (downstream card) the CLI's skeleton // extraction — the same one-list-both-sides rule the #6080 pin above @@ -1336,7 +1336,7 @@ describe('translation unknown-key strictness (#4001)', () => { // ────────────────────────────────────────────────────────────────────────── // #15178 — `settings` is a PLATFORM group; the per-app door refuses it // ────────────────────────────────────────────────────────────────────────── - describe('per-app `settings` is refused with the platform-only prescription (#15178)', () => { + describe('per-app `settings` is refused with the platform-only prescription', () => { const settings = { mail: { title: 'Mail', keys: { host: { label: 'Host' } } } }; it.each([ @@ -1382,7 +1382,7 @@ describe('translation unknown-key strictness (#4001)', () => { // accepted shape). It used to ACCEPT it — and there it overrode the // platform's copy, not merely filled gaps. // ────────────────────────────────────────────────────────────────────────── - describe('item-door `settings` is refused with the platform-only prescription (#19620)', () => { + describe('item-door `settings` is refused with the platform-only prescription', () => { const settings = { mail: { title: 'Mail', keys: { host: { label: 'Host' } } } }; it.each([ @@ -1700,7 +1700,7 @@ describe('CoverageBreakdownEntrySchema', () => { }); // ── `validationMessages` retired in 17.0.0 (#4667, ADR-0049) ──────────────── -describe('retired translation.validationMessages (#4667)', () => { +describe('retired translation.validationMessages', () => { it('rejects the group at BOTH doors — bundle entry and registered item', () => { // #3778's original guard ran on the item door only, which is exactly how // this key survived in file-authored bundles. It now lives in the shared diff --git a/packages/spec/src/system/validation-message.test.ts b/packages/spec/src/system/validation-message.test.ts index 93b06d173a9..ee502adf085 100644 --- a/packages/spec/src/system/validation-message.test.ts +++ b/packages/spec/src/system/validation-message.test.ts @@ -87,7 +87,7 @@ describe('validation message catalog — completeness', () => { }); }); -describe('renderValidationMessage — English output is unchanged (#3957 no-regression)', () => { +describe('renderValidationMessage — English output is unchanged, the field label in place of the API name', () => { // Byte-for-byte the pre-#3957 strings, with the field's label where the API // name used to be interpolated. const cases: Array<[string, Record | undefined, string]> = [ diff --git a/packages/spec/src/system/worker.test.ts b/packages/spec/src/system/worker.test.ts index dff2a125515..99d8afe526e 100644 --- a/packages/spec/src/system/worker.test.ts +++ b/packages/spec/src/system/worker.test.ts @@ -558,7 +558,7 @@ describe('Worker Integration', () => { // ninety lines up, which is what made the bare `rateLimit.duration` a drift // rather than a convention. A silent strip here would have left a queue // unthrottled with no error. -describe('QueueConfig.rateLimit.duration carries its unit (#15679)', () => { +describe('QueueConfig.rateLimit.duration carries its unit in the key name', () => { it('REFUSES the retired `rateLimit.duration` with the rename in the message', () => { const result = QueueConfigSchema.safeParse({ name: 'rate_limited_queue',