test(spec): the first api/ file group's test titles state each cited decision in words instead of a tracker number (stage 24) - #21961
Merged
Conversation
…decision in words instead of a tracker number (stage 24) Stage 24 of the spec lane's share of the runtime-string burn-down: the test strings shipped under packages/spec/src, the first name-ordered api/ group (ai-agents-envelope.test.ts through package-lifecycle.test.ts). 100 literals in 27 files (95 test titles and 5 declared expect messages) lose 106 tracker ids: 18 literals (22 ids) now state the cited decision in words, 10 (10 ids) get their subject back in words, and 72 (74 ids) drop a number the title already explains. 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 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 24 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 first name-orderedapi/group: the 27 id-bearing test files directly underpackages/spec/src/api/fromai-agents-envelope.test.tstopackage-lifecycle.test.ts. Those files carried 100 messages and 106 tracker ids, citing 65 records. All 106 now either state what their record decided, in words (form D), or are dropped where the title 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.Census at the base (
a3bd157730)Instruments:
census10.cjs(md59d08602ab972b4b8643c90d64d40fa41),census.cjs(md56e42a45a926d375013c32d62f16a296e),census-wide.cjs(md5c98410a19529c439adb0afbfb00026a2) anddirtable.cjs(md5dda605c54745b4a60cc14c9a686e4eff), byte-identical to the copies stages 10 to 23 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/mainata3bd157730, the claim's base and stage 23's landing. Both instruments read 471 messages / 498 ids in 111 files, the seat's reading and stage 23's head reading.api/(this PR: 27 of the 40 files)system/src/)ui/ai/contracts/The group reads 100 messages / 106 ids in 27 files, the seat's figures file for file:
api/)ai-agents-envelope.test.tsanalytics.test.tsapi-entry-graph.pin.test.tsapi-error-code-type.test.tsapis-publish-gates.test.tsauth-endpoints.test.tsauth.test.tsautomation-api.zod.test.tsbatch.test.tscontract.test.tsdataset-selection.test.tsdiscovery-auth-families.pin.test.tsdiscovery-environment-subset.pin.test.tsdiscovery.test.tsdispatcher.test.tsendpoint.test.tsenvelope-violations.test.tserror-code-ledger.test.tserrors.test.tsexport-job-family-retirement.test.tsexport.test.tsmeta-item-response-shapes.test.tsmetadata.test.tsodata-orderby-dual-declaration.test.tspackage-api.test.tspackage-install-one-authority.test.tspackage-lifecycle.test.tsFive more test files sit in the same name range and carry no id (
documentation.test.ts,error-catalog-docs.test.ts,events.test.ts,http-cache.test.ts,odata.test.ts). The five "other" strings are expect messages, rewritten and declared to the text-only tool:auth.test.ts:155,discovery-environment-subset.pin.test.ts:65(one leaf of a+chain) andexport-job-family-retirement.test.ts:112(a template literal),:158and:349.ui/notification.test.ts(1 id) andapi/protocol.test.ts(50 ids), outside the group, read the same at the base and at the head. Dark:package-api.test.tsreads 0 at the head while 30 of its comment lines still carry a number. Planted in a scratch tree: an id put into apackage-lifecycle.test.tstitle reads 1 / 1 (title:describe), and an id put into abatch.test.tscomment reads 0.#plus digits) reads the same as the gate pattern in all 27 files at the base, and 0 in all 27 at the head.api/reads 89 / 95 in 13 files, and no other file moved.How the area was chosen
api/has no subdirectory, so it is taken in name-ordered file groups near the ~100-id bound, the rule stages 20 to 23 used. Stage 23's cut named this group at 106 ids, and this census reads 106, so no re-cut was needed.Named for the next stages (cut from the head census, 371 / 392):
api/group:plugin-rest-api.handler-status-retirement.test.tsthroughzod-issues-to-fields.test.ts, 13 files, 89 messages / 95 ids (86 / 92 titles, 3 / 3 other),protocol.test.tsalone 46 / 50 andrest-server.test.ts19 / 19. That finishesapi/.system/167, two stages. The files directly insrc/, 120, one.ui/component-props-unknown-members.pin.test.ts:322and stage 22's two. One stage, with an at-tier review. The four colour literals stay, as stage 21 decided.What each id became
Every cited record was fetched with all its comments through REST (357 comments, #4052's included), and its decision was read from its ruling, ACCEPT and landing comments. 65 records are cited: 59 answer 200 and 6 answer 404. Two of the 200s are PRs (#4049 and #20218), read from their bodies. One citation is objectui's and was read from objectui:
objectui#6593. The six that answer 404 were read from what landed, through the commits endpoint (this checkout is shallow), each named by the commit the stage-2 re-anchoring ofapi/comments gave it:preview/trial是 EnvironmentType 的一等成员,但 NODE_ENV_TO_DISCOVERY_ENVIRONMENT 没有条目 —— 靠?? 'development'兜底,折叠方向没被声明 #6287, from84c86fb454(feat(spec): preview/trial 的 discovery 折叠改为显式声明,折叠表对 EnvironmentType 穷尽 (#6287) #6610):previewandtrialfold tosandboxby declaration, and the fold table is typed total overEnvironmentType;ImportRequest.runAutomationsdeclares.default(false)and documents "off by default for bulk", butPOST /data/:object/importdefaults it ON #6704, fromc3f4916266(fix(spec)!:ImportRequest.runAutomationsdeclares the default the import route actually applies (#6704) #7015):ImportRequest.runAutomationsdeclares the default the import route applies;mappingNameis accepted by both import routes but undeclared on ImportRequestSchema — the typed SDK cannot express it #10330, fromb9e9227e36(spec(api): declare mappingName on ImportRequestSchema with the mutual-exclusion refine (#10330) #11316):mappingNamedeclared onImportRequestSchema, with the mutual-exclusion refine;ApiEndpoint.targetis required on every endpoint but read only fortype: 'flow'— anobject_operationauthor must write a value nothing consumes #10338, fromd2619fd0cd(spec(api): make ApiEndpoint.target optional; publish gate holds the flow requirement #11290):ApiEndpoint.targetis optional, and the publish gate holds the flow requirement;f90e820249(feat(spec): register FLOW_INPUT_SCHEMA_INVALID — the never-dispatched ADR-0112 code for the definition-level input-schema refusal #12611):FLOW_INPUT_SCHEMA_INVALIDregistered, the never-dispatched code;door: 'none'(boot-refusal) codes that ship indist— the rest of the #16404 class after #16449 #16649, from613bfbd3db(feat(spec): register the fourteen remaining door:'none' error codes that ship in dist #16879): the fourteen remainingdoor: 'none'codes registered.One citation names a different record.
batch.test.ts:78read "(#3963 follow-up)"; #3963 is theapi.requireAuthretirement. ThevalidateOnlytombstone is #4052's decision, read too: never implemented, so tombstoned rather than half-built. The title already says that ("rejects the retiredvalidateOnlykey with its prescription"), so the number is dropped.Where a record's decision was refined later, the title follows the refined one:
apis:(ApiEndpoint)入站面全链路零执行:元数据装载成功、路由从未挂载、matchEndpoint全仓无实现 #4936 and E7(#5040 执行器):翻转 —— publish 硬拒收窄为「不支持子集 + 命名空间门」,声明式端点随 v17 放行执行 #5111: 声明式apis:(ApiEndpoint)入站面全链路零执行:元数据装载成功、路由从未挂载、matchEndpoint全仓无实现 #4936's ruling refused every non-emptyapis:; E7(#5040 执行器):翻转 —— publish 硬拒收窄为「不支持子集 + 命名空间门」,声明式端点随 v17 放行执行 #5111 narrowed that to per-endpoint gates. The:152title says what held through both: an empty or absentapis:was never refused.rateLimitunwired and tracked under 声明式apis:(ApiEndpoint)入站面全链路零执行:元数据装载成功、路由从未挂载、matchEndpoint全仓无实现 #4936; 声明式apis:(ApiEndpoint)入站面全链路零执行:元数据装载成功、路由从未挂载、matchEndpoint全仓无实现 #4936's ruling then kept it in the vocabulary for the endpoint executor to wire. The title names that destination.enableOnInstallis declared in three schemas and honoured by no handler — an author sets it and the runtime silently ignores it #18605: ruling letter 1 made the request contract the one authority, and [Decision] the package boot seed set is never updated by enable/disable, so a flag-absent re-install durably reverts an operator later enable once #18752 lands — and the obvious producer fix re-opens #18058 F1 pins #18877's later ruling made that key optional so the door sees an absence; the title says only "has ONE authority", which both keep, so only the number goes.Stated in words:
api/)api-entry-graph.pin.test.ts:77./apiis split and the assembled-package declarations move to@objectstack/spec/api-assembled.apis-publish-gates.test.ts:152apis:— never refused, even while a non-empty one was"apis:and keeps the vocabulary; an empty or absent one stays publishable, then and after #5111's narrowing.apis-publish-gates.test.ts:568rateLimitin the vocabulary (ruled: left to the endpoint executor, not the server-level seam)"apis-publish-gates.test.ts:597publishPackagereuses the same gate function, because D6 alone has no runtime counterpart.auth-endpoints.test.ts:112passkeys/magicLinkleave the/api/v1/auth/configpayload.auth.test.ts:88automation-api.zod.test.ts:327status: 'paused'+runId+screenis the trigger contract's third state.discovery.test.ts:1167scopingis declared onDiscoverySchemaas an optional key.discovery.test.ts:1207environmentis mapped into the declared enum.error-code-ledger.test.ts:68error-code-ledger.test.ts:220error-code-ledger.test.ts:234distis registered; #16449 registered the nine.error-code-ledger.test.ts:308613bfbd3dbregistered the fourteen.export-job-family-retirement.test.ts:158,:349(expect messages)package-api.test.ts:603package-lifecycle.test.ts:25/apinamespace"package-lifecycle.test.ts:140Subject back in words (10 literals): "the pre-#4053 bare body" becomes "the bare body from before the envelope relocation" (#4053's end state: both producers relocated the payload under
data); "(#3891 shim dialect)" becomes "(the degraded shim dialect)"; "the duplicate-payload drift #4049 removed" becomes "the duplicate-payload drift the /share-links domain stopped emitting", the PR's own title; "zero holders after #17158" becomes "after the export-job family retirement"; "the #10330 TS2353 repro" becomes "the original TS2353 repro"; the three "since PR #20218" titles become "since the door parses its whole body" (twice) and "so does the door, which parses the whole body", the PR's own title; the#17534title now names "the reverse-domain id rule", that card's ruling A; "the objectui#6593 confusion" becomes "the envelope-vs-payloadsuccessconfusion", the defect objectui#6593 measured.Dropped where already stated (72 literals, 74 ids). A number goes only where the title already says its decision. Examples: the eight
[#5111]describes ("the flip — a well-formedapis:publishes", "gate (a)" to "gate (e)", …),[#5310],[#19920], the two[#21046],[#5676],[#5672],[#5679]and[#6287]prefixes; the four#17551/#17550section prefixes indataset-selection.test.ts, which keep the file's own§1to§5;#5384 —,#5227 —,#5950,#5882,#17518,#18058 —and#18605 —; the four#15677citations on the "→ …Seconds" renames; and the tails(#3878),(#6442),(#19543)x2,(#7359),(#3939),(#18124),(#3842)x3,(#10338),(#6704),(#10330),(#4587),(#17667),(#19116),(#17431),(#19441),(#8211), the five(#12038)and the one(#12038 4A)after "declares the four fixed keys and stays open".(federated ledger, #4805),(ADR-0076 D12, #2462)and(ADR-0112 amendment 2026-08-18, #9266)keep their words and lose the number. The ADR-0087 conversion idapi-endpoint-cache-ttl-to-cache-ttl-secondsstays: it is not a tracker id.No file is renamed.
Readers
error-code-ledger.test.ts(11 ids in 7 titles): no ledger, gate or self-test reads its strings.scripts/check-error-code-casing.mjsnames the file only to exempt it whole ("the ledger admission test"); the ledger's docblock and its generated reference page name the file, never a title; the provenance and dispatcher-vocabulary gates readerror-code-ledger.zod.ts, not the test.expect), none is an expected value, and 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 27 files calls a snapshot matcher.export-job-family-retirement.test.tsis in therepoproject (packages/spec/vitest.repo-tests.json:30); the other 26 run inlocal. The base-versus-head run below takes both projects.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 17 hits are windows that share wording with code comments and one CHANGELOG line: "(ADR-0076 D12, ADR-0076: remaining objectql/protocol layering work (cross-repo window) #2462)" in comments inruntime/http-dispatcher.ts,spec/api/discovery.zod.tsandobjectql/protocol-discovery.test.tsand atpackages/runtime/CHANGELOG.md:14161; "([Decision]@objectstack/spec/api的浏览器体积:真实调用点付的是约一倍而非 +19.4%,而台账对链 zod 的 12 个条目结构性地判不了 —— 加权重规则 / 收窄入口 / 接受现状? #18576 ruling, letter B)" in three comments; "(降级 analytics shim 把 ExecutionContext 丢在门口 ——/analytics/query在没装 service-analytics 的装配里不注入 RLS/租户谓词,契约字段where也被静默忽略 #3891 shim dialect)" inruntime/domains/analytics.ts:41; "is retired ([finding] three sibling list doors declarelimit/cursorand never read them, one reportinghasMore: falseas a literal — REBUILD of #19365, which stopped resolving on 2026-09-21 #19543)" inspec/api/automation-api.zod.ts:645.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 five expect-message lines named above.+and-lines are exactly the 100 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 expect message reverted to base SAME; a declared expect message given a new id VIOLATION; a declared+-chain leaf given a new id VIOLATION; a template-literal message given a new id VIOLATION..eachtitle and no$nameplaceholder changes. The one template literal,export-job-family-retirement.test.ts:112, changes only its text after${name}.Test counts: the 27 files were run at the base, in a separate base worktree, and at the head, with
--project local --project repo. Both sides read 831 tests in 27 files, all passed, with the same count and status sequence per file in 27 of 27. 325 full test names change, and each changed name equals the base name with the planned replacements applied: 0 mismatches once the plan's text is read the way the source writes it (the comparison tool reads the plan's—escape aterrors.test.ts:439literally, so its first pass reports that title's three names as mismatches; decoding the escape, as vitest does, reads 0). No full name repeats on either side.Changeset:
skip-changesetMeasured, not assumed:
npm pack --dry-runof@objectstack/speclists 2068 files. 0 of the 27 touched files are in it, and no*.test.tsat all. The controlssrc/api/package-lifecycle.zod.ts,src/api/error-code-ledger.zod.tsanddist/index.mjsare in it.dist/, a new phrase 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
dffd240655)pnpm turbo run buildover all packages: 71 / 71, through the shared verify lock (VERDICT command-exit 0).@objectstack/spec:vitest run --project local: 619 files, 18471 passed, 1 todo.typecheck: exit 0, includingcheck:test-typecheck(52 files / 246 errors / 135 pinned signatures held). Its program holds all 27 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 80 families: stage 23's 79 pluscheck:error-code-casing, which the two touched files it names bring in. All 80 exit 0.--ranreconciles: 80 derived, 80 run, 0 NOT-MEASURED, 0 UNRUN, every family with its exit code recorded. The same 80 derive fromorigin/main01e0f71ad8with this diff applied. The roster families stage 23 also ran (check:meta-url-spelling,check:spec-changes,check:authz-resolver,check:filter-alias-parity) each exit 0.--no-inline-configover the 27 files reads 0 errors and 0 warnings. The population comes from ESLint's own config: 27 configured, 0 ignored. No file setsparserOptions.projectorprojectService, so no untouched file's verdict can move.check-governed-merges --test: NOT governed, 200 changed lines (+100 / -100).mainsince the baseRe-fetched just before this PR opened,
origin/mainwas two commits past the base (01e0f71ad8: #21940, #21953). They touch 31 files, none of the 27 and none underpackages/spec, somainwas not merged and the census on that tree is the base's.git merge-treeonto01e0f71ad8is clean, and none of the 5 open PRs touches any of the 27 files.Acceptance notes
packages/spec/src, among themapi/protocol.test.ts([#5672]x2,(#12038)x5,(#12038 1C),(#19543, door ③)),api/plugin-rest-api.test.ts,api/router.test.tsandapi/websocket.test.ts((#15677)),stack-json-stage-package-body.test.ts(#17518x4),system/book.test.ts((#12038)) and threesystem/titles citing(#18124).runtime37,rest24,client9,metadata-protocol6,service-automation6,metadata5,cli3,objectql2, and one each inexamples/app-showcase,core,plugin-hono-serverandverify), 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.// package-rollback-response retirement (#12038 3A)banner above its describe, the[#5111 / #5040 E7]and[#5189 / #5040 E7b]headers inapis-publish-gates.test.ts, and the[#17158]header inexport-job-family-retirement.test.ts. Code comments are not this card's share.Generated by Claude Code