Skip to content

Commit 0ef9029

Browse files
test(spec): the second root-level test file group's titles state each cited decision in words instead of a tracker number (stage 29) (#22376)
Part of #20749 Clause-②: no Stage 29 of this card: the next area of class (e), the test strings shipped under `packages/spec/src`, as ruled in `5902360492` on #20513. This stage takes the second name-ordered group of the test files directly in `packages/spec/src/`: 15 files, `root-entry-migrations-split.pin.test.ts` through `stack.test.ts`. 12 of them carried 57 tracker ids in test titles (59 ids), one of which sits in a declared describe label rather than a literal title. All 57 now either state what their record decided, in words (form D), or drop the number where the title already says it. Text only: no assertion, identifier, test count, code comment, file name or non-test file changes. No file directly in `src/` carries an id in a string any more (`type-alias-convention.pin.test.ts`, which sorts after the group, reads 0); the card stays open for the subdirectory files named under Acceptance notes. ## Census (re-taken first) The instrument is stage 28's `census28.cjs`, byte-identical (md5 `31d8488b5194b8d3048e3fcaec0efaed`, the value stage 28 published): an AST walk over the `packages/spec/src` test files, one message per folded string (a lone literal, a template, or a plus chain) that matches the gate's id pattern, a title when the folded root is argument 0 of a describe / it / test / suite / bench call, comments never read. It was run against the three published readings before it was trusted, and all three reproduce exactly: 128 messages / 130 ids in 37 files at stage 27's landing `f7b8a5932b`, 191 / 200 in 53 files (titles 162 / 168, other 29 / 32) at `aa09db58c9`, and 73 / 76 in 24 files at stage 28's landing `b7e01fbbd`. | reading | messages / ids | files | |:--|--:|--:| | the group, base `43fc50051` | 57 / 59 (titles 56 / 58, other 1 / 1) | 12 of 15 | | class (e) whole, base `43fc50051` | 73 / 76 (titles 61 / 64, other 12 / 12) | 24 | | class (e) whole, this head | 16 / 17 (titles 5 / 6, other 11 / 11) | 12 | | the group, this head | 0 / 0 | 0 of 15 | The group reads 57 / 59, stage 28's landing figure: no re-cut. The census at `3f80f1716` (the dispatch base) and at stage 28's landing read the same per file as at `43fc50051`. Per file, messages at base: root-entry-migrations-split.pin 1, stack-artifact-crossref 11 (12 ids), stack-artifact-packages 3, stack-cross-reference-envelope 2 (one title, one declared label), stack-dev-logins 4, stack-email-template-locale-floor 6, stack-inline-action-crossref 13, stack-json-stage-package-body 4, stack-refusal-envelopes 2, stack-requires 4 (5 ids), stack-top-level-strict 5, stack 2. `stack-conversions-record`, `stack-duplicate-action-key` and `stack-provenance` carry no id in any literal. Controls: - Pathspec: the 15 named paths hit the control word `describe(` in 15 of 15 files, and a nonsense word in none; the census scanned 15 of 15. - Lit outside the group, at base and head: `ai/build-progress.test.ts` 2 / 2 and `ui/dashboard.test.ts` 2 / 2. - Lit at base and dark at head, inside the group: `stack-artifact-crossref` 11 / 12, `stack-inline-action-crossref` 13 / 13, `stack-requires` 4 / 5 and `stack-cross-reference-envelope` 2 / 2 each read 0. - Dark at both ends: `stack-conversions-record` has no id anywhere; `stack-duplicate-action-key` and `stack-provenance` carry an id in one comment line each and read 0. The 15 group files read 0 at head while 55 of their comment lines still carry ids (112 id-bearing lines at base, comments included, 14 files). - Planted, in a scratch tree: an id in a describe title, a plus-chain title, an expect message, an it.each row name, a template title and a declared string each read once (6 / 6); a comment, a six-digit number, an HTML entity and a markdown heading read 0. ## What changed 57 literals, one line each, in 12 files: +57 / -57. Every file keeps its line count. - 6 state the decision in words: "a modal target names a page, only" for the inline and the embedded modal-target refusals (stack-inline-action-crossref 133 and 330); "it was never built by a stack producer" for the hand-built stack object composeStacks refuses before either artifact-scoped rule runs (stack-artifact-crossref 380); "compatibility with the multi-package artifact" (stack-artifact-crossref 270); "unchanged from before the dangling-`objectName` refusal" (stack-inline-action-crossref 399); and the declared label "hooks[].object (the hook-ownership rule)", the rule ADR-0130 states as "the split must follow hook ownership" (stack-cross-reference-envelope 91). - 4 get their subject back where the number was the only subject: "the no-floor report: warn-once bookkeeping" and "the floor guard's declared scope boundary" (stack-email-template-locale-floor 159 and 179), "the strict top-level door: the accept side does not move" and "defineStack surfaces the unknown-top-level-key refusal" (stack-top-level-strict 173 and 225). - 47 drop a number the title already explains, with its connector: a `#N — ` or `#N ` prefix, a `[#N] ` prefix, or a trailing `(#N)`. That includes the twin title `stack-artifact-packages.test.ts:355`, which read `does not warn about an undeclared composition rule (#5005 rule 3)` and now reads `does not warn about an undeclared composition rule`, the same text stage 28 gave its copy at `compose-stacks-manifest-preserve.test.ts:308`. ## Cited records 26 distinct ids. 25 answer 200 and were read: the body and the comment thread as the API serves it, with the rulings and landings that the rewritten titles state read in full. #10485 answers 404; its decision was read from its landing commit `35ad101bc` (the `themes` carrier retired under ADR-0049 enforce-or-remove; `app.branding` is the one colour surface) and from the unknown-key strictness ledger, which records the maintainer's 2026-08-21 disposition as retiring the authorable surface, the phrase the title keeps verbatim. The comments counter of four records differs from what the comments endpoint serves (#14122 serves 21 of 22, #17614 5 of 6, #16449 0 of 5, #18056 5 against a counter of 4); everything served was read, and #16449's decision is in its body. What each record decided, as the titles now say it: - #6739, ruling A (2026-08-09): a `type: 'modal'` target names a page, only; the object fallback is consumer leniency and enters retirement. - #20367, ruling B: one authoring shape; `defineStack` and `composeStacks` stamp a provenance mark and `composeStacks` refuses an unmarked input with `STACK_PROVENANCE_MISSING` / 422. - #7456, Option A: the embedded `objectName` gets the registered rule's existence check, and only a dangling name newly refuses. - #19926, ruling A: `packages: null` is malformed, not absent. - #19784, ruling C: a non-array concat key is refused with the envelope. - #5005 (2026-08-04): same value passes, a conflict throws a prescriptive error, an undeclared top-level key warns. - #8687, Shape B: the top-level stack door is strict, and the lint yields to it. - #14122 / #18202: one artifact carries N packages; the artifact-scoped permission and seed references resolve against the artifact, a stack that does not opt in is untouched. - #17518, ruling A prime: the artifact-stage and record-stage package bodies are declared beside the assembled one. - #6889 and #7397: inline page-element actions and object-embedded actions get the registered action rule's target cross-references. - #17063: the `type: 'page'` list-view mount is retired. #17556: an app declares its own `devHint` / `devLogins`. #17614 and #18056: the no-`en-US`-floor report and its declared scope. #14552 and #15963: every `defineStack` refusal carries an ADR-0112 envelope; #16449 registers each shipped code in the ledger. #3265 and #3308: `requires` is validated at the producer and the camelCase aliases are removed. #14153 and #20332: trigger capability validation and its `triggers` without `automation` pair. #20646: the root entry stops carrying the migration registries. #2611: named import mappings are wired into the import path. ## Readers 173 needles (each old literal, a 24-character window around each id, and the text left and right of each id) were searched with `git grep -F` over the tracked tree at the base outside the 15 files, with a lit control (`composeStacks` in `stack.zod.ts`, hit) and a dark control (a nonsense string, no hit). One needle hit, one line: a `//` comment in `packages/qa/dogfood/test/fixtures/override-composite-fixture.ts` that quotes the tail of one title with its id. It is a comment, not a reader. The only reader of the declared label is the file's own `describe(row.label, ...)`. No group file reads a test name (`currentTestName`, `expect.getState`, snapshots: 0). The 15 file names appear elsewhere only in prose and comment lines, in `packages/spec/test-typecheck-debt.json` (keyed by file and error text, not by title) and in two `dispatch-gates.mjs` / `check-changeset-no-major.mjs` fixtures that name a path or a changeset file. Every old literal occurs exactly once across the 15 files (its own site). ## Text-only proof - `textonly28.cjs` (stage 28's, md5 `957eff6b3837d762b8e03d070155930a`), per file, base text against head text: both texts with every string token masked are byte-equal (code and comments), the string-token counts are equal, and every changed token sits in a describe / it / test title position or on a declared line, carried an id at base and carries no `#` plus digits at head. 15 / 15 files SAME; 57 changed tokens, 56 titles and 1 declared label (run with `--declared 91`); per-file counts exactly as predicted in writing at 2026-10-08T22:57Z, before the edit. The 3 untouched files read SAME with 0 changed. - 17 / 17 controls on scratch copies of the head files behave as predicted: an identifier rename, a numeric literal, a comment edit, a non-title string given an id, a rewritten title given a new id, a title that was id-free at base edited, one rewritten title reverted to base (SAME, 0 changed), an it.each title given an id, an expect message changed, a title re-split into a plus chain, a template title given an id, a test added, an id appended to a rewritten title in a many-title file, an untouched file (SAME, 0 changed), the declared label run without `--declared` (refused), the declared line plus another changed string (refused) and the declared line alone (SAME, 2 changed). - `git diff -U0`: 57 plus and 57 minus lines, each the planned line; 0 added lines carry `#` plus digits; control-byte scan of the 12 files and of this body: 0 hits. ## Tests - The 15 files with `--project local --project repo` and the JSON reporter, at the base (same worktree, before the edit) and at the head `65b42b7d1`: 405 / 405 passed in 15 files, 108 suites each side; per-file test count and status sequence identical in 15 / 15; 229 full names changed, 0 mismatches against the plan (each head name equals the base name with the planned replacement applied); 0 duplicate full names either side; names with `#` plus digits 229 at base, 0 at head. - spec `vitest run --project local`: 626 files passed, 18740 tests passed | 1 todo, exit 0. - spec `typecheck`: `VERDICT command-exit 0`; `check:test-typecheck` 52 files / 246 errors / 135 pinned signatures held, unchanged; `tsc --listFilesOnly -p tsconfig.test.json` holds 15 of 15 group files. - turbo build of all packages before the gates: `Tasks: 71 successful, 71 total`. Heavy runs went through `scripts/pm/os-verify-lock.sh` (slot `dev-20749-s29`). - No reverse verification or ablation applies: no assertion, gate or reader moved. ## Gates All at `65b42b7d1`. The dispatch list (77 commands, derived at `3f80f1716`) equals the list re-derived from the real change set at this head, 12 paths against merge base `43fc50051` (114 changed lines): nothing added, nothing dropped. All 77 exit 0 and `dispatch-gates --ran` reads "77 derived, 77 run, 0 NOT-MEASURED, 0 UNRUN". Also run, exit 0: the five roster families that share a directory with the diff (`check:meta-url-spelling`, `check:spec-changes`, `check:authz-resolver`, `check:error-code-casing`, `check:filter-alias-parity`) and `check:generated` ("All 15 generated artifacts are up to date", measured against the dist the full build wrote at this head). ESLint, narrowed and proven: 15 files linted with `--no-inline-config`, 0 errors, 0 warnings; the population read from ESLint's own config is 15 configured, 0 ignored; no file has `parserOptions.project` or `projectService`, so type-aware linting is not enabled and this diff cannot move the verdict of a file it did not touch. ## Packaging and landing - No changeset: `skip-changeset`. `npm pack --dry-run --json --ignore-scripts` in `packages/spec` lists 2069 files, none of the 12 changed files and no `*.test.ts`; controls `src/stack.zod.ts`, `dist/index.mjs` and `package.json` are present; an old and a new title phrase read 0 files in `dist/`, the control `Unrecognized key` reads 42. - Not governed: `check-governed-merges --test` on the 12 paths reads 0 of 12; 114 changed lines. - `git merge-tree` onto `origin/main` `6a53564b9`: clean. None of the 17 open PRs touches any of the 15 files (file lists read; 6 of them touch `packages/spec/src`, so the scan sees spec files). ## Acceptance notes - Class (e) is not finished: 16 messages / 17 ids remain in 12 files, all in subdirectories. By directory: `ui/` 9 / 9 in 7 files, `automation/` 2 / 3 in 1, `ai/` 2 / 2 in 1, and `api/`, `contracts/` and `kernel/` 1 / 1 in 1 each. Their plan is the cutting seat's: stage 27's landing sets the needles stage apart (one stage, with an at-tier review) and keeps `ui/`'s four colour literals as decided, and this stage measured neither. - Regrowth for stage 30's plan: five subdirectory test files carry 6 messages / 7 ids that were added after stage 27's landing. The files are older; the ids entered their strings in three commits. `api/meta-item-response-shapes.test.ts` 1 / 1 (a title, from #22126); `automation/builtin-node-config.test.ts` 2 / 3 (two titles, from #22259, which re-added ids to a title stage 10 had rewritten); `kernel/manifest.test.ts` 1 / 1, `ui/action-description.test.ts` 1 / 1 (titles) and `ui/view-submit-redirect-url.test.ts` 1 / 1 (an `other` string, to be needle-checked there), all three from #22125. Nothing regrew since stage 28's landing: the per-file census at `b7e01fbbd` equals the one at `43fc50051`. Test files are outside `check:doc-authoring`'s ledgered leg, so nothing refused these on arrival. Not edited here. - Code comments in the 15 files still carry live ids (55 lines). Comments are not this card's share. Carrier: none. - `origin/main` moved from `43fc50051` to `6a53564b9` while this ran; one commit touches `packages/spec` (`api/error-code-ledger.zod.ts`, none of the 15 files), so nothing was merged into the branch. --- _Generated by [Claude Code](https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1915434 commit 0ef9029

12 files changed

Lines changed: 57 additions & 57 deletions

‎packages/spec/src/root-entry-migrations-split.pin.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ function valueGraph(entry: string): Set<string> {
140140
return new Set([...seen].map((f) => relative(SRC, f).split('\\').join('/')));
141141
}
142142

143-
describe('the migration chain is `@objectstack/spec/migrations`, not the root (#20646)', () => {
143+
describe('the migration chain is `@objectstack/spec/migrations`, not the root', () => {
144144
it('the root module exports none of the moved values', () => {
145145
expect(MOVED_VALUES.filter((name) => name in root)).toEqual([]);
146146
});

‎packages/spec/src/stack-artifact-crossref.test.ts‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ const SEED_ON_CASE = "Seed data references object 'crm_case' which is not define
142142
const GRANT_ON_NOWHERE = `Permission 'sales_rep' grants on object '${NOWHERE}' which is not defined in objects.`;
143143
const SEED_ON_NOWHERE = `Seed data references object '${NOWHERE}' which is not defined in objects.`;
144144

145-
describe('#18202 — the per-stack pass, without the opt-in', () => {
145+
describe('the per-stack pass, without the opt-in', () => {
146146
it('REFUSES an app-owned grant and seed on a module-owned object — the reported defect', () => {
147147
const refused = refusalOf(() => defineStack(appConfig('crm_case', 'crm_case')));
148148
expect(refused?.code).toBe('STACK_CROSS_REFERENCE_INVALID');
@@ -159,7 +159,7 @@ describe('#18202 — the per-stack pass, without the opt-in', () => {
159159
});
160160
});
161161

162-
describe('#18202 — `artifactObjects` widens exactly the two ARTIFACT-SCOPED classes', () => {
162+
describe('`artifactObjects` widens exactly the two ARTIFACT-SCOPED classes', () => {
163163
it('ACCEPTS the app package once the artifact’s other objects are declared', () => {
164164
const service = serviceStack();
165165
const accepted = refusalOf(() =>
@@ -227,7 +227,7 @@ describe('#18202 — `artifactObjects` widens exactly the two ARTIFACT-SCOPED cl
227227
});
228228
});
229229

230-
describe('#18202 — the ARTIFACT pass: the refusal MOVED, it did not disappear', () => {
230+
describe('the ARTIFACT pass: the refusal MOVED, it did not disappear', () => {
231231
/** The opt-in is a promise about a composition; this is the composition calling it in. */
232232
const composeClaiming = (name: string) => {
233233
const service = serviceStack();
@@ -267,7 +267,7 @@ describe('#18202 — the ARTIFACT pass: the refusal MOVED, it did not disappear'
267267
});
268268
});
269269

270-
describe('#18202 — #14122 §6 compatibility: a stack that does not opt in is untouched', () => {
270+
describe('compatibility with the multi-package artifact: a stack that does not opt in is untouched', () => {
271271
it('a single-package stack still refuses its own dangling grant', () => {
272272
const refused = refusalOf(() =>
273273
defineStack(anyStack({
@@ -303,7 +303,7 @@ describe('#18202 — #14122 §6 compatibility: a stack that does not opt in is u
303303
});
304304
});
305305

306-
describe('#18202 — the object-less leniency the ARTIFACT pass inherits verbatim', () => {
306+
describe('the object-less leniency the ARTIFACT pass inherits verbatim', () => {
307307
/**
308308
* hotcrm#1449's shape: the app package declares NO objects, so
309309
* `validateCrossReferences` early-returns and the ARTIFACT pass skips it for
@@ -340,7 +340,7 @@ describe('#18202 — the object-less leniency the ARTIFACT pass inherits verbati
340340
* it, `collectArtifactCrossReferenceErrors`'s docstring says it, and these
341341
* fixtures hold it.
342342
*/
343-
describe('#18202 — an input that bypassed the strict parse IS checked at composition', () => {
343+
describe('an input that bypassed the strict parse IS checked at composition', () => {
344344
/** The app package as an unparsed stack: `strict: false` skips every validation. */
345345
const unparsedApp = (grantObject: string, seedObject: string) =>
346346
defineStack(appConfig(grantObject, seedObject), { strict: false });
@@ -377,7 +377,7 @@ describe('#18202 — an input that bypassed the strict parse IS checked at compo
377377
expect(refused?.issues).toContain(SEED_ON_NOWHERE);
378378
});
379379

380-
it('REFUSES a hand-built stack object before either rule runs — it was never built (#20367 ruling B)', () => {
380+
it('REFUSES a hand-built stack object before either rule runs — it was never built by a stack producer', () => {
381381
// Since ruling B a hand-built object no longer reaches the artifact pass:
382382
// `composeStacks` refuses an input no stack producer built at its step 0,
383383
// naming the input, so the two rules above never get to run on it. The
@@ -423,7 +423,7 @@ describe('#18202 — an input that bypassed the strict parse IS checked at compo
423423
* before this pass runs — skipping it composed an artifact without that
424424
* stack's grants or seed rows — so those two cases assert the refusal.
425425
*/
426-
describe('#18202 — a malformed collection on an unparsed input is skipped or refused, never a bare TypeError', () => {
426+
describe('a malformed collection on an unparsed input is skipped or refused, never a bare TypeError', () => {
427427
/** Collect `console.warn` for one call, restoring the real one afterwards. */
428428
function warningsDuring(run: () => unknown): { warnings: string[]; thrown: Envelope | null } {
429429
const warnings: string[] = [];
@@ -454,7 +454,7 @@ describe('#18202 — a malformed collection on an unparsed input is skipped or r
454454
const composeWith = (stack: ReturnType<typeof defineStack>) => () =>
455455
composeStacks([serviceStack(), stack], { manifest: 'preserve' });
456456

457-
it('a non-array `permissions` is refused by the concat pass, never a bare TypeError (#19784)', () => {
457+
it('a non-array `permissions` is refused by the concat pass, never a bare TypeError', () => {
458458
// Map format written onto a built stack (only `defineStack` normalizes it). It
459459
// is NOT iterable, which is what makes this the case that distinguishes a
460460
// guard from a bare `TypeError`: a string value would iterate its
@@ -465,7 +465,7 @@ describe('#18202 — a malformed collection on an unparsed input is skipped or r
465465
expect(thrown?.status).toBe(422);
466466
});
467467

468-
it('a non-array `data` is refused by the concat pass, never a bare TypeError (#19784)', () => {
468+
it('a non-array `data` is refused by the concat pass, never a bare TypeError', () => {
469469
const { thrown } = warningsDuring(composeWith(malformed({ data: 42 })));
470470
expect(thrown?.code).toBe('STACK_SCHEMA_INVALID');
471471
expect(thrown?.status).toBe(422);
@@ -511,7 +511,7 @@ describe('#18202 — a malformed collection on an unparsed input is skipped or r
511511
* This block is the fence on that qualifier: if the early return is ever
512512
* removed, the qualifier becomes wrong and these tests say so.
513513
*/
514-
describe('#18202 — a composition of ONE package never reaches the artifact pass', () => {
514+
describe('a composition of ONE package never reaches the artifact pass', () => {
515515
const claiming = () => defineStack(appConfig(NOWHERE, NOWHERE), { artifactObjects: [NOWHERE] });
516516

517517
it('accepts a one-input composition whose claim names an object nothing defines', () => {

‎packages/spec/src/stack-artifact-packages.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ describe('ADR-0130 D4 — each `packages` entry is an OBJECT wrapping its manife
250250
expect(issueAt(result, ['packages'])?.code).toBe('invalid_type');
251251
});
252252

253-
it('refuses `packages: null` — `.optional()` admits `undefined`, not `null` (#19926)', () => {
253+
it('refuses `packages: null` — `.optional()` admits `undefined`, not `null`', () => {
254254
// `null` is a present, non-array `packages`: malformed, not absent. Every
255255
// reader of the key refuses it too (`INVALID_ARTIFACT_PACKAGES`); the rule
256256
// is stated once, beside `AssembledPackageBodySchema`.
@@ -322,7 +322,7 @@ describe('ADR-0130 D4 — `packages` has a declared composition rule', () => {
322322
]);
323323
});
324324

325-
it('refuses `packages: null` on any input when composing two or more stacks (#19926)', () => {
325+
it('refuses `packages: null` on any input when composing two or more stacks', () => {
326326
// The concat pass skips `undefined` alone: `null` is malformed, not
327327
// absent, and is refused with the strict parse's own envelope rather than
328328
// composed as if the stack declared no packages. `strict: false` is the
@@ -352,7 +352,7 @@ describe('ADR-0130 D4 — `packages` has a declared composition rule', () => {
352352
expect(composed.packages.map((p) => p.manifest.id)).toEqual(['com.example.crm.cpq']);
353353
});
354354

355-
it('does not warn about an undeclared composition rule (#5005 rule 3)', () => {
355+
it('does not warn about an undeclared composition rule', () => {
356356
composeStacks([
357357
raw({ manifest: crmManifest, packages: [{ manifest: crmManifest }] }),
358358
raw({ manifest: cpqManifest }),

‎packages/spec/src/stack-cross-reference-envelope.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ const stackWith = (extra: Record<string, unknown>) =>
8888
*/
8989
const rows: Array<{ label: string; config: Record<string, unknown>; message: string }> = [
9090
{
91-
label: 'hooks[].object (#14122 §4 rule R4)',
91+
label: 'hooks[].object (the hook-ownership rule)',
9292
config: {
9393
hooks: [{ name: 'probe_hook', object: MISSING, events: ['afterInsert'], handler: 'noop' }],
9494
},
@@ -135,7 +135,7 @@ const rows: Array<{ label: string; config: Record<string, unknown>; message: str
135135
},
136136
];
137137

138-
describe('#14552 — defineStack cross-reference refusals carry an ADR-0112 envelope', () => {
138+
describe('defineStack cross-reference refusals carry an ADR-0112 envelope', () => {
139139
for (const row of rows) {
140140
describe(row.label, () => {
141141
it('refuses with code STACK_CROSS_REFERENCE_INVALID and status 422', () => {

‎packages/spec/src/stack-dev-logins.test.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ const issuesOf = (verdict: ReturnType<typeof parse>): string[] =>
6868

6969
// ─── GREEN — what is writable now, and was not before ───────────────
7070

71-
describe('#17556 accept — an application may declare its own first-run credentials', () => {
71+
describe('accept — an application may declare its own first-run credentials', () => {
7272
it('accepts a full `devLogins` entry and carries every field through the parse', () => {
7373
const verdict = parse({
7474
...base(),
@@ -113,7 +113,7 @@ describe('#17556 accept — an application may declare its own first-run credent
113113

114114
// ─── RED — the entry is strict from birth, and says so usefully ─────
115115

116-
describe('#17556 refuse — a `devLogins` entry is closed against unknown keys', () => {
116+
describe('refuse — a `devLogins` entry is closed against unknown keys', () => {
117117
it('refuses an undeclared key inside an entry, at the entry`s path', () => {
118118
const verdict = parse({ ...base(), devLogins: [{ email: 'a@b.example', totallyBogus: 1 }] });
119119
expect(verdict.success).toBe(false);
@@ -150,7 +150,7 @@ describe('#17556 refuse — a `devLogins` entry is closed against unknown keys',
150150

151151
// ─── DARK CONTROL — the door did not open, two keys were declared ───
152152

153-
describe('#17556 control — the top-level door is still strict everywhere else', () => {
153+
describe('control — the top-level door is still strict everywhere else', () => {
154154
it('a neighbouring undeclared key still refuses, so the accept above is about these two keys', () => {
155155
// If this went green the reading "devHint/devLogins are now writable" would
156156
// be indistinguishable from "the strict close regressed".
@@ -171,7 +171,7 @@ describe('#17556 control — the top-level door is still strict everywhere else'
171171

172172
// ─── COMPOSITION — both publishers' personas survive; hints refuse ──
173173

174-
describe('#17556 compose — personas concatenate, a contradicting hint is named', () => {
174+
describe('compose — personas concatenate, a contradicting hint is named', () => {
175175
const hiring = () => defineStack({
176176
manifest,
177177
devHint: 'seed first',

‎packages/spec/src/stack-email-template-locale-floor.test.ts‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ afterEach(() => {
6363
vi.restoreAllMocks();
6464
});
6565

66-
describe('#17614 — the floor tag is one named constant, not two spellings', () => {
66+
describe('the floor tag is one named constant, not two spellings', () => {
6767
it('is the schema default for `locale`, so a row that omits the key HAS the floor', () => {
6868
expect(EMAIL_TEMPLATE_FLOOR_LOCALE).toBe('en-US');
6969
const parsed = EmailTemplateDefinitionSchema.parse({
@@ -90,7 +90,7 @@ describe('#17614 — the floor tag is one named constant, not two spellings', ()
9090
// A published declaration promising a loud permanent refusal where the
9191
// runtime performs a silent fill is the defect; both call shapes must stay
9292
// named, so the promise cannot quietly go unconditional again.
93-
it('[#18056] scopes the dead-letter promise to a call that NAMES a locale, and states the other case', () => {
93+
it('scopes the dead-letter promise to a call that NAMES a locale, and states the other case', () => {
9494
const text = String(EmailTemplateDefinitionSchema.shape.locale.description ?? '');
9595
expect(text).toMatch(/NAMES a locale/);
9696
expect(text).toMatch(/lowest locale tag/);
@@ -99,7 +99,7 @@ describe('#17614 — the floor tag is one named constant, not two spellings', ()
9999
});
100100
});
101101

102-
describe('#17614 — defineStack reports a bundle with no `en-US` floor', () => {
102+
describe('defineStack reports a bundle with no `en-US` floor', () => {
103103
it('reports the trap: every supportedLocales tag authored, none of them the floor', () => {
104104
const { warns, value } = warningsOf(stack(['en', 'zh-CN', 'ja-JP', 'es-ES'].map((l) => tpl(l)), THE_TRAP));
105105
const hits = floorWarns(warns);
@@ -130,7 +130,7 @@ describe('#17614 — defineStack reports a bundle with no `en-US` floor', () =>
130130
});
131131
});
132132

133-
describe('#17614 — and stays silent where the bundle HAS a floor (the controls)', () => {
133+
describe('and stays silent where the bundle HAS a floor (the controls)', () => {
134134
// ⛔ Every case in THIS block is a bundle that genuinely carries the floor
135135
// row. The shapes that are floorless and silent anyway are the guard's scope
136136
// boundary and live in their own block below — filing them here read as
@@ -156,7 +156,7 @@ describe('#17614 — and stays silent where the bundle HAS a floor (the controls
156156

157157
});
158158

159-
describe('#17614 — warn-once bookkeeping', () => {
159+
describe('the no-floor report: warn-once bookkeeping', () => {
160160
it('warns once for one bundle, however many times the same stack is defined', () => {
161161
const first = warningsOf(stack([tpl('pt-BR')], { defaultLocale: 'pt-BR', supportedLocales: ['pt-BR'] }));
162162
const second = warningsOf(stack([tpl('pt-BR')], { defaultLocale: 'pt-BR', supportedLocales: ['pt-BR'] }));
@@ -176,7 +176,7 @@ describe('#17614 — warn-once bookkeeping', () => {
176176
// enforce-or-remove question and is not decided here; what is closed is the
177177
// silence being undeclared and unpinned.
178178

179-
describe('#18056 — the guard\'s declared scope boundary', () => {
179+
describe('the floor guard\'s declared scope boundary', () => {
180180
it('early return 1: a stack with no `i18n` block is never examined, floorless or not', () => {
181181
const { warns, value } = warningsOf(stack([tpl('en', 'acme.scope_no_i18n')]));
182182
expect(floorWarns(warns)).toEqual([]);

0 commit comments

Comments
 (0)