Skip to content

test(spec): shared test titles state each cited decision in words instead of a tracker number (stage 12) - #21750

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-20749-test-strings-c
Oct 4, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-20749-test-strings-c

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #20749
Clause-②: no

Stage 12 of this card, and the third area of class (e): the test strings shipped under packages/spec/src, as ruled in 5902360492 on #20513. This stage takes the whole shared/ directory. Its 85 test-title and test-string literals carried 95 tracker ids: 92 cite 49 records, and 3 are a #0000 placeholder that cites none. Each id now either states what its record decided, in words (form D), or is dropped where the title already says it. Text only: no assertion, identifier, test count or code comment changes.

Census at the base (72b6333cd8, the claim's base)

Instrument: stage 10's census10.cjs (md5 9d08602ab972b4b8643c90d64d40fa41) and stage 9's census.cjs (md5 6e42a45a926d375013c32d62f16a296e), both byte-identical to the copies stages 10 and 11 used. A literal counts as a test title when its folded message is argument 0 of a describe / it / test call, .each / .skip / .only chains included. Everything else is an "other" string.

Both instruments read 1594 messages / 1701 ids in 369 files at the base, which is stage 11's reading at its head exactly. shared/ reads 85 / 95, also stage 11's figure.

directory files messages / ids titles other
data/ 95 468 / 501 445 / 475 23 / 26
ui/ 81 392 / 415 374 / 397 18 / 18
api/ 40 189 / 201 181 / 193 8 / 8
system/ 34 154 / 165 128 / 138 26 / 27
(files directly in src/) 30 118 / 120 117 / 119 1 / 1
shared/ (this PR) 21 85 / 95 73 / 81 12 / 14
contracts/ 25 63 / 74 59 / 70 4 / 4
conversions/ 9 34 / 34 34 / 34 0
security/ 8 28 / 28 28 / 28 0
ai/ 9 18 / 20 13 / 15 5 / 5
identity/ 6 15 / 15 14 / 14 1 / 1
integration/ 4 14 / 14 13 / 13 1 / 1
migrations/ 2 9 / 12 9 / 12 0
marketplace/, meta-spelling/, studio/ 5 7 / 7 7 / 7 0
total 369 1594 / 1701 1495 / 1596 99 / 105

How the area was chosen

Stage 10's rule: rank whole first-level directories by ids, and take the busiest one within about 10% of the ~100-id bound. The four busiest each exceed the bound alone: data/ (501), ui/ (415), api/ (201) and system/ (165). The files directly in src/ (120) are 20% over. shared/ (95) is the busiest whole directory within the bound, and its census reads exactly stage 11's 95, so the rule needed no second pass.

Named for the next stages: data/ (about five stages, by subdirectory or file group; data/driver/ alone is 52), ui/ (about four), api/ (two), system/ (two), the files directly in src/ (one, 120), contracts/ with conversions/ (one, 108), and security/, ai/, identity/, integration/, migrations/, marketplace/, meta-spelling/ and studio/ together (one, 96).

What each id became

22 ids now state a decision in words, one per literal. 73 are dropped: 67 where the title already says what a live record decided, 3 dead numbers whose decisions were read from what landed, and the 3 #0000 placeholders. Every cited record was read with its comments through REST. 46 answer 200. Three answer 404, and their decisions were read from their landing commits.

record ids result
#7889 3 of 5 The three synthetic history strings in the reachability self-test read "n/a — planted for the reachability self-test". Nothing reads them: unreachableAliasRows reads only aliases and guidanceSets. Dropped from the 2 titles that state the check.
#6416 1 of 2 "the three hand-written error maps are FOLDED and judged here". Dropped from the expect message that already explains the blind spot.
#6619 1 of 6 "the two maps the first fold MISSED": #6619 folded three maps, and #6805 found two more. Dropped from 5 literals that state the fold.
#7887 1 of 4 "editability lives on fields — the boundary prescription an author actually sees". That is the maintainer's boundary ruling: sections and page components gate visibility only. Dropped from 3 titles.
#5955 1 of 2 "(the fix-first order survives the new set)": the history sentence is emitted last, so the author reads the fix first. Dropped once.
#15811 1 of 2 "evaluated-slot population — no declaring position still mounts the persistence schema". Dropped once, where the title states the rule.
#3278 1 "never re-advertises js, retired in favour of ScriptBody". #3278 retired the js expression dialect as redundant with the L2 ScriptBody.
#7739 1 "EXTERNAL_ERROR_HTTP_STATUS — each external error carries an HTTP status". The title was the symbol alone. Its landing gave the whole family one status table, so none can leak as a bare 500.
#19101 1 of 2 "lazySchema × z.toJSONSchema — a lazy reference keeps its metadata". The ruling fixed the root cause in lazySchema, so descriptions no longer depend on which generator ran. Dropped once.
#8421 1 of 2 "(flipped once unknown type names were refused)", where the title said "#8421 flipped this". Dropped once.
#16845 1 of 2 "ProtectionSchema — unknown-key refusal names the surface and the rename": the block adopted strictObject. Dropped from "accept set is unchanged".
#12840 1 "acceptRetiredDefaultResidue — a retired default parses as inert residue". The title was the symbol alone.
#17109 1 "enumWithRetiredValues — value-level retirement beside retiredKey()": the maintainer chose a generic helper, not a one-enum refinement.
#6414 1 The expect message reads "the prescription must not point at the retired ETL layer": #6414 retired L2 ETLPipeline.
#4001 2 The synthetic widget history reads "Until unknown keys were refused, these were dropped silently". Both copies change together. The test asserts the message ends with that exact constant, so the fixture and its expectation move as one.
#7832 3 of 5 "the reverse-direction alias curation added here", "already curated before the reverse-direction sweep", and "the two visibleWhen shapes the first sweep never enumerated". #7832 was the reverse direction of the action shapes' alias table. Dropped twice.
#7816 1 "the boolean enabled: false first". #7816 noted that the boolean case must point at enabled, or the hint just moves the confusion.
dropped only (live) 49 #4661 (2), #4962, #4964, #4971, #4990, #5389 (3), #5481 (2), #5552, #5593 (2), #6630, #6805 (4), #6856, #7030, #8201, #8202 (2), #8318 (4), #8382 (2), #8424, #9529 (3), #7894 (4), #10096, #10848, #13859 (3), #15028, #15035, #15423, #15430, #16320, #18122. Each title already states the pinned decision.
dropped only (404) 3 #6085 (landing 026101660: the dialect table drops js, adds template and states it IS the enum), #10485 (35ad101: the themes carrier key and ThemeSchema retired, /meta/theme refused), #11166 (735f5c709: SchemaDiffEntry gains a distinct unreachable kind). Each title already carries what landed.
#0000 3 A placeholder in synthetic fixtures (retired-key.test.ts:26, :28; the planted source in retired-key-migrate-sentence.test.ts:342), cited no record. Dropped. The two retired-key.test.ts constants are both input and expectation, so the byte-for-byte assertions move with them. It is the same reasoning by which #17109's patch round took the made-up (ADR-0000) out of these fixtures: a made-up number squats on a real one.

Readers

  • Test-name filters: none. A tracked-tree search for -t and --testNamePattern finds only packages/qa/dogfood/README.md:142 (-t "owner-scoped"), which is unrelated.
  • Snapshots: none. shared/ has no __snapshots__, and no .snap file is tracked under packages/spec.
  • Gates that read a touched file:
    • scripts/check-future-spec-major.mjs keeps a witnessed ledger entry for retired-key.test.ts (witness: /was removed in @objectstack\/spec 99/, covers: 4). The rewritten constants still carry that sentence. check:future-spec-major was derived for this diff and exits 0, "every witness still matching".
    • packages/spec/vitest.repo-tests.json lists retired-key-migrate-sentence.test.ts, so that file runs in the repo project. It was run there at the base and at the head.
  • Titles by substring: every old literal, plus a window around each id (221 needles), was searched across the tracked tree outside its own file. No gate, doc, filter or script reads one. The 21 needle hits land on 8 lines:
    • Sibling titles in other lanes' files: packages/cli/test/format-zod-union.test.ts:301 ([#5389] formatZodErrors …) and packages/metadata-protocol/src/protocol.unrecognised-meta-type.test.ts:171 ([#10485] \theme` …`).
    • A later stage's row in this package: packages/spec/src/ai/knowledge-source.test.ts:97, an it.each row name with "retired at formula: retire the js expression dialect — redundant with L2 ScriptBody; hasDialect also mis-reports the stub as real #3278".
    • A self-test fixture in scripts/check-future-spec-major.mjs:767-768 that copies the two retired-key.test.ts constants with (#0000). It is its own text and does not read the file.
    • Code comments: the strict-object.ts:71 docblock example and suggestions.zod.ts:319.
    • A self-test fixture with a different string in scripts/check-doc-authoring.mjs:2507.

Text-only proof

Stage 10's scratch tool (textonly10.cjs, md5 d5e4801dbb4329ab1984da91e92fc47c) compares base and head file by file on three legs:

  1. Skeleton: the full AST, with string pieces masked. It must be identical.
  2. Comments: every comment, byte-equal.
  3. Strings: each string leaf that changed must sit in a test-call title position, or on one of the 12 declared lines. Each changed leaf must carry a tracker id before and no # plus digits after. The declared lines are:
    • the synthetic history strings at alias-integrity.test.ts:917, :939, :952 and strict-object.test.ts:16, :196;
    • the expect messages at alias-integrity.test.ts:1100 and retry-policy.test.ts:113;
    • the fixture constants at retired-key.test.ts:26, :28 and the planted source at retired-key-migrate-sentence.test.ts:342;
    • the fixture names at union-branch-policy.parity.test.ts:164, :169, which reach it titles through a template.
  • Result: 21 of 21 files SAME, 85 changed (73 title, 12 declared), on all three legs.
  • Diff hunks: exactly the 85 planned lines, with every file keeping its line count.
  • Controls (10 of 10 as predicted, on scratch copies, each anchor hit once): identifier rename DIFF; numeric literal DIFF; comment edit COMMENT DIFF; a non-title string with an id VIOLATION; a rewritten title given a new id VIOLATION; a title that was id-free at base edited VIOLATION; one title reverted to base SAME; a declared string keeping an id VIOLATION; an undeclared expect message changed VIOLATION; a title re-split into a + chain DIFF.

Test counts: the 21 files were run at the base (in a separate base worktree) and at the head, 20 in the local project and one in repo. Both sides read 567 / 567 passed, with the same count and status sequence per file in 21 of 21. 450 full test names change, and each equals the base name with the planned replacements applied.

Changeset: skip-changeset

Measured, not assumed:

  • npm pack --dry-run of @objectstack/spec lists 2068 files under files[]. 0 of the 21 touched files are in it, and 0 *.test.ts at all. The control src/shared/expression.zod.ts is in it.
  • In dist/, four new phrases read in 0 files. Of three old ones, two read in 0, and the third reads only in shared/index.d.ts / .d.mts, from the strict-object.ts docblock comment, not from a test. The control Unrecognized key(s) on reads in 42.

So this PR publishes nothing, and no changeset is added.

Verification (at fd8fd92d13)

  • pnpm turbo run build over all packages: 71 / 71.
  • @objectstack/spec:
    • vitest run --project local: 613 files, 18215 passed, 1 todo.
    • typecheck exit 0, including check:test-typecheck. Its program holds all 21 touched files, counted with tsc --listFilesOnly.
  • Gates: dispatch-gates --commands derived 80 families, and all 80 exit 0. That is stage 11's 79 plus check:future-spec-major. --ran reconciles: 80 derived, 80 run, 0 NOT-MEASURED, 0 UNRUN.
    • Five roster families whose rosters sit under a touched directory were also run, and each exits 0: check:meta-url-spelling, check:spec-changes, check:authz-resolver, check:error-code-casing and check:filter-alias-parity.
  • ESLint, a proven narrowing: --no-inline-config over the 21 files, 0 errors and 0 warnings. The population comes from ESLint's own config: 21 configured, 0 ignored. No parserOptions.project or projectService, so no untouched file's verdict can move.
  • check-governed-merges --test: NOT governed, 170 changed lines.

Acceptance notes


Generated by Claude Code

…tead of a tracker number (stage 12)

Class (e), the third area: the 85 string literals under
packages/spec/src/shared/ that carried a tracker id (95 ids) now carry
none. Where the number stood in for a decision, the literal states it
(for example "the two maps the first fold MISSED", "the fix-first order
survives the new set", "the prescription must not point at the retired
ETL layer"); where the title already says the decision, the number is
dropped. Three placeholder ids (#0000) in synthetic fixtures cite no
record and are dropped.

Text only: 73 test titles and 12 declared non-title strings, one line
per literal. No comment, assertion, identifier or non-test file moves.

Claude-Session: https://claude.ai/code/session_01T9u38rswFp5Rw8DswRUReJ
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the size/m label Oct 4, 2026
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 4, 2026
@github-actions github-actions Bot added the tests label Oct 4, 2026
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 8cbba54491bfc47aa4db7f042c0c24809638ad7c → packageMentionDocs.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 4, 2026 15:08
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 4, 2026 15:08
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 4, 2026
Merged via the queue into main with commit 866b439 Oct 4, 2026
41 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-20749-test-strings-c branch October 4, 2026 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants