Repository navigation
test(spec): the last system/ file group's test titles state each cited decision in words instead of a tracker number (stage 27) - #21997
Merged
Conversation
…d decision in words instead of a tracker number (stage 27) Stage 27 of the spec lane's share of the runtime-string burn-down: the test strings shipped under packages/spec/src, the second and last name-ordered system/ group (metadata-form-zod-reconciliation.test.ts through worker.test.ts). 63 literals in 16 files (45 test titles and 18 declared strings: 17 reconciliation-ledger reasons and one expect message) lose 70 tracker ids: 22 literals now state the cited decision in words, 1 gets its subject back in words, and 40 drop a number the string already explains. The ledger reasons keep every substring the file's own assertions read, the ruling record id included. No needle sits in this group. Text only: one line per literal, no assertion, identifier, test count, code comment or file name changes. Claude-Session: https://claude.ai/code/session_01T9u38rswFp5Rw8DswRUReJ Co-authored-by: Claude <noreply@anthropic.com>
Contributor
📓 Docs Drift CheckNothing 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): |
This was referenced Oct 6, 2026
This was referenced Oct 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #20749
Clause-②: no
Stage 27 of this card: the next area of class (e), the test strings shipped under
packages/spec/src, as ruled in5902360492on #20513. This stage takes the second and last name-orderedsystem/group: the 16 id-bearing test files underpackages/spec/src/system/frommetadata-form-zod-reconciliation.test.tstoworker.test.ts. Those files carried 63 messages and 70 tracker ids. All 70 now either state what their record decided, in words (form D), or are dropped where the string already says it. No needle sits in this group. Text only: no assertion, identifier, test count or code comment changes, and no file is renamed. This finishessystem/for this class.Census at the base (
aa09db58c9)Instruments:
census10.cjs(md59d08602ab972b4b8643c90d64d40fa41),census.cjs(md56e42a45a926d375013c32d62f16a296e),census-wide.cjs(md5c98410a19529c439adb0afbfb00026a2) anddirtable.cjs(md5dda605c54745b4a60cc14c9a686e4eff), byte-identical to the copies stages 10 to 26 used. A literal counts as a test title when its folded message is argument 0 of adescribe/it/testcall,.each/.skip/.onlychains included. Everything else is an "other" string.The worktree was cut from
origin/mainataa09db58c9, the claim's base and stage 26's landing. Both instruments read 191 messages / 200 ids in 53 files, the seat's reading and stage 26's head reading.src/)system/(this PR: all 16)ui/ai/contracts/The group reads 63 messages / 70 ids in 16 files, the seat's figures file for file:
system/)metadata-form-zod-reconciliation.test.tsmetadata-persistence.test.tsmetrics.test.tsnotification-event-migration-retirement.test.tsnotification.test.tsobject-storage.test.tsoperation-message.test.tsregistry-config.test.tssettings-manifest.test.tsstack-server.test.tstenant-provisioning-family-retired.test.tstenant.test.tstracing.test.tstranslation.test.tsvalidation-message.test.tsworker.test.tsFive more test files sit in the same name range and carry no id (
migration,search-engine,security-context,supplier-security,translation-typegen). The 18 "other" strings are declared to the text-only tool: the 17 ledger reasons inmetadata-form-zod-reconciliation.test.ts(LEDGERrows:256,:263,:270,:283,:426,:433,:440,:447,:454,:470,:477,:484,:491,:507,:514,:521, and theTOP_LEVEL_DEFERRED.viewreason at:880), and one expect failure message atnotification-event-migration-retirement.test.ts:165.ai/build-progress.test.ts(2 / 2) and three files directly insrc/(assembled-package-body4 / 4,compose-key-dispositions-export.pin5 / 5,compose-stacks-action-collision-shape3 / 3), outside the group, read the same at the base and at the head. Dark: the 16 files read 0 at the head while 141 of their lines still carry#plus digits, every one of them a comment line. Planted in a scratch tree: an id put into the rewritten "page component copy, keyed by component id" title reads 1 / 1 (title:describe), the base text put back into the:440ledger reason reads 1 / 1 (other), and an id put into ametrics.test.tscomment reads 0.#plus digits) reads the same as the gate pattern in all 16 files at the base, and 0 in all 16 at the head.system/is absent, and no other file moved.How the area was chosen
system/is taken in name-ordered file groups near the ~100-id bound, the rule stages 20 to 26 used. Stage 26 named this group at 70 ids, and this census reads 70, so no re-cut was needed.Named for the next stage (cut from the head census, 128 / 130):
src/: 30 files, 118 messages / 120 ids (117 / 119 titles, 1 / 1 other, atstack-cross-reference-envelope.test.ts). The largest file isstack-inline-action-crossref.test.tsat 13, and no file needs splitting. It fits one PR and one text-only proof at 120, 20% over the ~100 bound. If the seat holds to "within about 10%", the name-order cut is two groups:assembled-package-body.test.tsthroughinline-grid-column-carriers.test.ts(18 files, 61 ids) androot-entry-migrations-split.pin.test.tsthroughstack.test.ts(12 files, 59 ids).What each id became
Every cited record was fetched with all its comments through REST. 37 records are cited, plus one decision-batch number (below): 35 answer 200, and 2 answer 404. The two that answer 404 were read from what landed, through the commits endpoint (this checkout is shallow):
submitLabelcopy key lost its only declared carrier whenelement:formretired (#9249) — decide retire vs re-anchor #10926, fromd173125fb8(feat(spec): retire the component-translation submitLabel copy key (#10926, ADR-0049) #11438): the component-translationsubmitLabelcopy key is retired, option A per the maintainer ruling of 2026-08-22;aa5994e17a(feat(spec): Operation Message Catalog gains refusal-situation keys for approvals recall and sharing write-denial #12626, found through its@objectstack/specCHANGELOG entry): the catalog gains two situation keys,record_write_deniedandapproval_recall_not_submitter, each its own sentence, "deliberately notrecord_access_deniedrestated".The ledger reasons in
metadata-form-zod-reconciliation.test.ts(17 "other" strings). Before any was rewritten, every reader of the ledger and of the file was found:whytext:e.why.startsWith(reason)(the class phrase that leads each ruled root row),toContain('5861442317')(the ruling record id, in every ruled root row),toContain(`the \`${editor.type}\` type`)andtoContain(editor.surface)(the editor names), the unspellable union arms in backticks, andwhy.length > 20. Every rewrite keeps all of them, so no assertion moves: only the card numbers go, and the record id5861442317stays.packages/spec/scripts/lib/zod-graph.ts,zod-graph.test.ts,scripts/pm/check-widening-tells.mjs,metadata-form-declared-rows.pin.test.ts, three*.form.tscomments and the CHANGELOGs name the file. None reads awhystring: they cite the file in prose or comments. No gate, generated artifact, docs table or self-test reads the text. So no non-test file moves.5861442317(batch 🔗 Broken links detected in documentation #229 item 3, A on all five groups). Each reason already states its class and why, so "(ruling record 5861442317, #19188 split: 39 top-level zod-only keys are structured controls needing a designed widget, not a row #19332)" becomes "(ruling record 5861442317)" in 15 rows.:433cited [Decision] isviewreconciled per metadata type or per union arm? 36 keys of the #19188 census cannot be filed until this is settled #19330 too: "(ruling record 5861442317; per-arm view forms, ruled: one registered form per view kind)". [Decision] isviewreconciled per metadata type or per union arm? 36 keys of the #19188 census cannot be filed until this is settled #19330's ruling A (5754204415): "viewis reconciled PER ARM. Each view kind … gets its own registered metadata form".:454cited "spec: a shared picklist (global value set) metadata kind — option lists reused across objects and packages are TypeScript constants today #18164 batch Refactor protocol docs: business value over code examples #209 item 1 A" after the record id5755653853. spec: a shared picklist (global value set) metadata kind — option lists reused across objects and packages are TypeScript constants today #18164's ruling5755653853is decision batch Refactor protocol docs: business value over code examples #209 item 1, letter A, so#209is a batch number, not a citation (Refactor protocol docs: business value over code examples #209 itself is an unrelated 2026 docs PR). The reason already says what was decided ("the picker placed there"; "its offer was decided as that picker in the object designer's select-field editor"), so it now reads "(ruling record 5861442317; the picker placed there by ruling record 5755653853)".:880(TOP_LEVEL_DEFERRED.view) already says "It is reconciled per arm, each arm against its own registered form", so "(the [Decision] isviewreconciled per metadata type or per union arm? 36 keys of the #19188 census cannot be filed until this is settled #19330 ruling, letter A)" becomes ", as ruled"."ruled" appears in two rewritten strings, both on #19330's ruling A (
5754204415)::433and:880above.The same-id titles stage 26 listed:
(#15679)titles (metrics:500,object-storage:864,registry-config:215,tracing:524,worker:561) now say "carry their unit in the key name" / "carries its unit in the key name". [#14478 stack 4/6]system/: the 15 remaining duration keys carry their unit in the key name — ADR-0087 conversions with readers;metrics.zod.tssizeneeds an honest name, not the mechanical one #15679 is spec: duration-shaped number keys carry their unit in describe prose only — twottlkeys with different units in one block, baretimeoutkeys, unit-less tenant timeouts #14478's ruling B (5548763981) forsystem/: the fifteen duration keys carry their unit in the key name. That is stage 25's [#14478 stack 2/6]api/: the 12 remaining duration keys carry their unit in the key name — ADR-0087 conversions with readers,ApiError.retryAfterwith its own BREAKING note #15677 reading and stage 26's form;translation.test.ts's six:#16772and#6080state their decisions (below);#10926,#21257,#11287and#4667drop, because each title already says it (retired, retired, the keys the resolver acts on, retired).Stated in words (22 literals):
system/)metadata-form-zod-reconciliation.test.ts:433metadata-form-zod-reconciliation.test.ts:886metrics.test.ts:500,object-storage.test.ts:864,registry-config.test.ts:215,tracing.test.ts:524,worker.test.ts:561metrics.test.ts:5845564447683, option 2): a key whose JSDoc names a unit its describe does not is a divergence, refused; the unit moves into the describe, where #14478's rule puts it in the key name. Ruling A (5635659224) remediates per file.tracing.test.ts:565notification-event-migration-retirement.test.ts:165(expect message)5582372148, batch #88): retire; no operator door and no platform invoker.operation-message.test.ts:101operation-message.test.ts:193record_access_denied,record_change_not_allowed), not the grant denial restated.operation-message.test.ts:306aa5994e17a, above.settings-manifest.test.ts:230optionsa UI list"valueDomainis declared, the standard domain is the enforcement boundary andoptionsdegrades to a UI convenience list.settings-manifest.test.ts:246selectvalue outside itsoptionsis refused at save. #5933 keeps that for an undeclared specifier.settings-manifest.test.ts:306visible— the settings visibility grammar, narrowed to what the save-time evaluator runs"settings-manifest.test.ts:338ast-only envelope — an evaluated slot requires a non-blanksource"5644350409, batch #122 item 2): every engine-evaluated expression slot requires a non-blanksource.stack-server.test.ts:615173147201): the unreachableHttpServerConfigSchemaand its seven dead keys are retired.translation.test.ts:840dashboards.NAME.globalFilters.KEYbecomes a bundle group, keyed by the filter name.translation.test.ts:901translation.test.ts:1082flowsbundle group, runner chrome kept out"5253154523): aflowssurface for flow, screen and field copy; runner chrome stays in the console's own catalog.validation-message.test.ts:90Subject back in words (1 literal):
translation.test.ts:713"should reject the retired shape …" now names it, "the retired object-firsto.shape". #3778 retired that shape for thetranslationtype.Dropped where already stated (40 literals, 45 ids). A number goes only where the string already says its decision. Examples: the 15 ledger reasons above;
:880's "(the #19330 ruling, letter A)"; the tails(#5280),(#14327),(#19332),(#18124)x2,(#5933),(#4001)x3,(#14478, #14519),(#14519),(#15939, #14478)on "→ schemaCacheTtlSeconds",(#10926),(#21257),(#11287),(#15178),(#19620),(#4667); and the prefixes#18118x2 (before "the retired CEL arm"),[#16194]x2,[#4616]and[#4739 / #16325]. The one 404 number among them (#10926) goes only where the title already states what landed.No file is renamed.
Readers
expect), not an expected value.notification-event-migration-retirement.test.tsreads theNOTIFICATION_EVENT_MIGRATION_IDdocblock for a claim matrix's absence and forRETIRED/os migrate/boot-time invoker/files-to-references, none of them an id. No title or message in the group is matched against a source docblock or another file's text.-t/--testNamePatternto vitest; the one vitest-thit is a README example underpackages/qa/dogfoodfiltering its own fixture.__snapshots__directory is tracked underpackages/spec, and none of the 16 files calls a snapshot matcher.local; none is inpackages/spec/vitest.repo-tests.json. The base-versus-head run below takes both projects anyway.git grepat the base, across the tracked tree outside its own file. No gate, doc, filter, snapshot, QA checklist entry orscripts/check-*.mjsself-test reads one. The 26 hits are 16 published CHANGELOG lines, which quote "form ↔ Zod reconciliation (排查「手抄 spec 清单 + "keep in sync" 注释」模式:一天内确认三例,全部曾静默漂移 #3786)" and "strict from birth (未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001)" as release text, and 10 sibling hits among the five(#15679)titles of this group, all rewritten here.tracing.test.ts:560says "a describe headedSpan.duration carries its unit". The new title keeps that prefix.Text-only proof
Stage 10's scratch tool (
textonly10.cjs, md5d5e4801dbb4329ab1984da91e92fc47c) compares base and head file by file on three legs:#plus digits after. This stage declares the 18 lines named above.+and-lines are exactly the 63 planned lines as multisets, and every file keeps its line count.it.eachrow given an id VIOLATION; an undeclared expect message changed VIOLATION; a title re-split into a+chain DIFF; a declared ledger reason reverted to base SAME; the declared deferral reason given a new id VIOLATION; the declared expect message given a new id VIOLATION; a template-literal title given a new id VIOLATION..eachtitle, no$name/%splaceholder and no table row changes.Test counts: the 16 files were run at the base, before the edit, and at the head, in the same worktree, with
--project local --project repo. Both sides read 747 tests in 16 files, all passed, with the same count and status sequence per file in 16 of 16. 302 full test names change, and each changed name equals the base name with the planned replacements applied: 0 mismatches. One full name repeats on each side, the same one: anit.eachpair under "translation unknown-key strictness" that already printed alike at the base. No head name carries#plus digits (302 base names did). No source escape sits in a planned anchor, so the comparison tool met none.Changeset:
skip-changesetMeasured, not assumed:
npm pack --dry-runof@objectstack/speclists 2068 files. 0 of the 16 touched files are in it, and no*.test.tsat all (files[]shipssrc/**/*.zod.ts, not tests). The controlssrc/system/translation.zod.ts,src/system/metrics.zod.tsanddist/index.mjsare in it.dist/, two new phrases and an old one each read in 0 files. The controlUnrecognized keyreads in 42.So this PR publishes nothing, and no changeset is added.
Verification (at
320cf687c7)pnpm turbo run buildover all packages: 71 / 71, through the shared verify lock (turbo exit 0, recorded to a file).@objectstack/spec:vitest run --project local: 619 files, 18485 passed, 1 todo.typecheck: exit 0, includingcheck:test-typecheck(52 files / 246 errors / 135 pinned signatures held). Its program holds all 16 group files, counted by path withtsc --listFilesOnly -p tsconfig.test.json.check:generated: all 15 generated artifacts up to date, against thedist/the build above wrote.dispatch-gates --commandsderived 79 families, the same 79 as stage 26. All 79 exit 0.--ranreconciles: 79 derived, 79 run, 0 NOT-MEASURED, 0 UNRUN, every family with its exit code recorded. The five roster families marked as sharing a directory with this diff (check:meta-url-spelling,check:spec-changes,check:authz-resolver,check:error-code-casing,check:filter-alias-parity) each exit 0.--no-inline-configover the 16 files reads 0 errors and 0 warnings. The population comes from ESLint's own config: 16 configured, 0 ignored. No file setsparserOptions.projectorprojectService, so no untouched file's verdict can move.check-governed-merges --test: NOT governed, 126 changed lines (+63 / -63).mainsince the baseRe-fetched just before this PR opened,
origin/mainwas one commit past the base (6befe19c6e, #21990). It touches 4 files inpackages/metadata-protocoland.changeset/, none of the 16 and none underpackages/spec/src/system/, somainwas not merged.git merge-treeonto6befe19c6eis clean, and none of the 4 open PRs touches any of the 16 files.Acceptance notes
plugin-security9,lint5,cli4,objectql4,service-settings4,core2,spec/scripts2, and one each inmetadata-protocol,metadata,plugin-approvals,qa/dogfood,sdui-parser,service-automationandservice-i18n), each package's share under the [finding] runtime warnings outside the migration ledger print tracker numbers to authors and operators: theAutomationEngineresumeAuthority boot warning (#3801/#5561/#3823) and two objectql data-event warnings (#4639/#4626) #20513 lane children. Examples:plugin-security/src/permission-denied-user-copy.test.ts's four#7414 —describes andmetadata/src/migrations/notification-event-migration-retirement.test.ts:54's[#16194]twin. No same-id title is left in this card's own census.5861442317(held by the file's owntoContain('5861442317')assertion) and5755653853are GitHub comment ids of ruling records, outside the gate's three-to-five-digit pattern, not tracker numbers.fieldGroups/inlineColumns/ root-coordinate ledger banners inmetadata-form-zod-reconciliation.test.ts(six comment lines still say "5861442317, #19188 split: 39 top-level zod-only keys are structured controls needing a designed widget, not a row #19332"), the// #7646 —banner intranslation.test.tsand the#17785, ruling A on #15939block intracing.test.ts. Code comments are not this card's share.Generated by Claude Code