Skip to content

docs(spec): re-anchor the dead tracker citations in api/ to the commits that decided them (stage 2) - #20342

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-20234-dead-citations-api
Sep 28, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-20234-dead-citations-api

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Part of #20234
Clause-②: no

What changed

This is stage 2 of the staged sweep. It covers packages/spec/src/api/** and nothing else, and it leaves out packages/spec/src/api/rest-server.zod.ts, which seat 2's #20295 claim holds. Later stages cover the other areas, so this PR says Part of.

Every comment or docblock site in scope that cited a tracker number answering 404 has been rewritten in ruling C+D's form C (comment 5749154545 on #19123). That is 107 sites on 105 lines in 22 files, covering 30 numbers. Each rewritten line now cites the commit in origin/main history that decided what the line describes, and it says in its own words what that commit decided. No ADR or ruling-record file in docs/adr/ or scripts/adr-anchors/ names any of the 32 dead numbers, so every anchor is a commit. Nothing was dropped: every number in scope had a deciding commit. One more comment site is left on purpose, because its number belongs to another repository (see Acceptance notes).

Only comments changed. Every source file keeps its line count (112 lines out, 112 in), so no line citation into these files moves. Seven of those 112 lines carry no number; they are the second half of a sentence that had to be reflowed. No code token moves (see the guard below). The 34 string-literal sites that carry a dead number are tokens, so they are left as they were and listed below.

No citation number is added. Every tracker number on an added line was already on the line it replaces. No PR number stands beside a sha.

Two more kinds of file change, both mechanical:

  • Regenerated reference pages. Five of the rewritten docblock lines project into content/docs/references/api/ (dispatcher.mdx, error-code-ledger.mdx, plugin-rest-api.mdx). check:docs proved those three pages stale, and pnpm --filter @objectstack/spec check:generated --fix regenerated only them. The diff is five lines, each the same substitution as its source line.
  • A patch changeset for @objectstack/spec (see Changeset below).

Census: api/, before and after

Instrument. This is stage 1's instrument. It sends REST GET /repos/objectstack-ai/objectstack/issues/N without following redirects, for every distinct in-repo number cited in packages/spec/src/api. The population is:

  • the citation gate's own CITATION_RE, kept when the qualifier is none, objectstack, objectstack-ai/objectstack, framework, pre- or post-;
  • N of 100 or more;
  • excluding the ordinal heads the gate declares, and summon.

Each site is classified by the TypeScript parser as a line comment, a docblock or a string.

Controls. The lit controls were #16862, #16847 and #17698. The dead controls were #16714, #16715 and #16697. They were probed at the start, after every 100 numbers and at the end, which is 5 checkpoints per run. They read 15 of 15 lit (200) and 15 of 15 dead (404) in both runs.

reading tree numbers probed 200 404 301 or other dead sites, all of api/ in scope rest-server.zod.ts in-scope lines in-scope files dead numbers in scope
before base 21ab41041, probed 2026-09-27T22:56Z to 22:58Z 351 319 32 0 153 142 11 140 23 31
after head 22a00c42d, probed 2026-09-27T23:10Z to 23:12Z; .ts sources identical at the final head 334 319 15 0 46 35 11 35 9 14

Before, in scope, by class. 34 non-test docblock sites and 30 non-test line comments. 7 test docblock sites and 37 test line comments. 33 test string sites (describe and it titles). 1 non-test string.

After, in scope. 34 string sites and 1 comment site remain. The comment site is export-job-family-retirement.test.ts:25, which names an objectui PR (see Acceptance notes). The head probe found no number newly dead since the base probe: 319 numbers answer 200 in both runs.

PR #20226's area table read api 153 at an earlier base, and this census reads the same 153 at 21ab41041. Of those, 11 sites sit in rest-server.zod.ts (#14369 twice and #14691 nine times, all comments). They wait for #20295 to land. pre-#N spellings do occur in api/: the at-tier review measured 15 sites on 15 lines in 13 files at the head, for example discovery.zod.ts:913 pre-#4828. All 15 numbers answer 200, so the gate's blind spot for that spelling (#20330) hides no dead site in this stage. (Corrected by the domain:spec seat 4 at 2026-09-28T00:48Z, from the at-tier review record 5861396181. The draft said that no such spelling occurs.)

Per-number table

The counts are in-scope sites and files. rewritten / left gives comment sites rewritten and string sites left. Every anchor was read in its diff or message, not only in its subject: it is the commit that made the change the line now describes, never a later refactor or a commit that merely mentions the number.

number sites / files rewritten / left anchor: what it decided
#6037 5/2 3/2 18189983d: declares DataProtocol.validateData, the validate-only operation, under #4633 ruling D
#6239 4/2 3/1 f549a0d4a: retires ViewProtocol and its ten request/response schemas (ADR-0049, route 3)
#6287 18/2 17/1 84c86fb45: preview and trial fold to sandbox by declaration, and the fold table is typed total over EnvironmentType
#6306 1/1 1/0 fec784863: the direct-mount routes read the one API base
#6361 5/3 4/1 90bbf2510: the notification-list cursor is retired on both halves (maintainer ruling 2026-08-07, Option A)
#6363 3/2 3/0 17d095413: unreadCount counts the whole inbox, not the window
#6704 4/1 3/1 c3f491626: runAutomations declares the default the import route applies, with the agreement pin
#8885 2/1 2/0 30b1c636a: registers the nine REST wire codes that sweep found
#9740 3/1 2/1 11b779e0f: declares getMetaItemLayered. The two cross-references to its test block now name the block by member
#9741 23/2 16/7 2a29caa53: records the 2026-08-18 maintainer ruling. previewDrafts and state are declared, and environmentId stays transport-level
#9934 4/4 4/0 79c46da90: the producer-side userMessage channel
#10264 (objectui) 1/1 0/0 not this repository's number: see Acceptance notes
#10330 3/1 1/2 b9e9227e3: declares mappingName on ImportRequestSchema
#10338 4/2 3/1 d2619fd0c: ApiEndpoint.target is optional, and the publish gate holds the flow requirement
#10726 2/2 2/0 bc56e1881: retires contributes.routes, ruled Option B (stage 1's anchor too)
#11006 12/2 10/2 cccbe51bf: declares publishMetaItem under the 2026-08-22 maintainer ruling, option B
#11453 1/1 1/0 1a47a5368: ack() refuses a row that is not in_flight
#11504 4/2 2/2 f90e82024: registers FLOW_INPUT_SCHEMA_INVALID, the contract half (stage 1's anchor too)
#11846 1/1 1/0 0c2334f6c: the preview-mode retirement, whose test states the same assertion-set reasoning (stage 1's anchor too)
#11858 (a PR) 1/1 1/0 1a47a5368, its squash commit: ack() takes the shared DELIVERY_NOT_ELIGIBLE spelling
#11859 2/1 2/0 d9cf78eaa: ack() binds the claim credential in its compare-and-set
#12194 1/1 1/0 311433f6b: declares the item-name grammar and refuses it loudly at the publish door
#13135 3/2 3/0 9e0ba21a1: retires the paper metadata-customization protocol (stage 1's anchor too)
#13197 1/1 1/0 56c093c4d: the in-memory driver enforces field-level unique
#14474 1/1 1/0 df657d9df: the install-time namespace conflict refusal carries an ADR-0112 envelope
#14691 16/1 4/12 b3a63d32c: retires the ten inert RestServerConfig keys. All 16 sites are in rest-server.test.ts; the 9 in rest-server.zod.ts are out of scope
#14723 1/1 1/0 65846bc46: lands the 2026-09-03 maintainer ruling, so a unique-constraint refusal has one wire spelling, UNIQUE_VIOLATION, on every route
#14748 2/2 2/0 92b5d7f00: registers NAMESPACE_CONFLICT (its diff wrote the row this line glosses)
#16649 12/2 11/1 613bfbd3d for 9 sites: registers the fourteen remaining door: 'none' codes. 44c917a47 for 2 sites: widens the vocabulary gate's face to every published package and retires boot-refusal (each of its diffs wrote the line it now anchors)
#17058 1/1 1/0 94c930248: parses the dataset-query selection at the door, with its leniency sweep
#19307 1/1 1/0 8f6d83147: the sys_permission_set duplicate-name refusal carries UNIQUE_VIOLATION

Every cited sha resolves to exactly one commit (git rev-parse --disambiguate, count 1), and every one is an ancestor of the base (merge-base --is-ancestor, exit 0). That is 30 distinct shas.

Two wordings to check, both true of their commit:

The 34 string sites left as tokens

  • Test titles (33 sites). protocol.test.ts 12, rest-server.test.ts 12, export.test.ts 3, error-code-ledger.test.ts 2, validate-data.test.ts 2, and 1 each in discovery.test.ts and endpoint.test.ts.
  • Non-test string (1 site). error-code-ledger.zod.ts:1692, the reason of the FLOW_INPUT_SCHEMA_INVALID row in the exported PROVENANCE_WAIVERS table (it cites #11504). It ships in the package as data. The one reader, scripts/check-error-code-provenance.ts, checks the table and never prints a reason to an author. So it is neither a comment nor author-shown text in the form D sense, and it is not rewritten here.

No author-shown text was found in api/: nothing here is #20233's form D.

Mechanical guard: no code token moves

The check is a comments-stripped token comparison, base 21ab41041 against head 22a00c42d (the later commits add only the changeset and the regenerated pages). It uses the TypeScript parser's leaf tokens, so template literals are scanned in context, and it excludes JSDoc nodes. It ran over all 22 touched .ts files.

  • Real run: 88,201 base tokens, 0 files with a token change (exit 0).
  • Comment-insertion control: 0 files changed, as expected (exit 0).
  • Positive control (a declaration appended): 1 file reads DIFFER (exit 1).
  • Positive control (one digit changed inside a rest-server.test.ts test-title string): 1 file reads DIFFER (exit 1).

Changeset

This change ships bytes, so a patch changeset for @objectstack/spec is included. It says only that the provenance comments were re-anchored.

Measured on the built package: 8 of the touched sources are src/**/*.zod.ts, which files[] ships verbatim. The rewritten docblocks also reach dist: 2a29caa53, cccbe51bf, 84c86fb45, 613bfbd3d and 90bbf2510 each appear in 1 declaration file, and 613bfbd3d and 79c46da90 each appear in 6 bundled .js files. The positive control, a pre-existing protocol.zod.ts docblock sentence, appears in dist/api/index.d.ts.

Gates (head 24d9fba68)

Acceptance notes


Generated by Claude Code

…ts that decided them

Comment and docblock lines under packages/spec/src/api (rest-server.zod.ts
excluded) that cited a tracker number answering 404 now cite the commit in
this repository that decided what the line describes, and say so in words.
Every file keeps its line count; no code token moves; string literals are
left as tokens.

Claude-Session: https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ
Co-authored-by: Claude <noreply@anthropic.com>
… of the shared ack/redeliver spelling

Claude-Session: https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ
Co-authored-by: Claude <noreply@anthropic.com>
…ovenance comments

The rewritten docblocks ship: src/**/*.zod.ts is in files[], and the
comments reach dist .d.ts and .js.

Claude-Session: https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ
Co-authored-by: Claude <noreply@anthropic.com>
…ten docblocks project into

Generated by `check:generated --fix` (gen:docs only, the one artifact it
proved stale); five lines, each the same substitution as its source line.

Claude-Session: https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Sep 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 10 documentable anchor(s). ⚠️ 2 changed file(s) yielded no anchor (packages/spec/src/api/dispatcher.zod.ts, packages/spec/src/api/metadata.zod.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

7 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/api/client-sdk.mdx (via ERROR_CODE_LEDGER (symbol, a top-level const object))
  • content/docs/api/error-catalog.mdx (via ApiErrorSchema (symbol, a top-level const), ERROR_CODE_LEDGER (symbol, a top-level const object))
  • content/docs/api/error-handling-server.mdx (via ERROR_CODE_LEDGER (symbol, a top-level const object))
  • content/docs/api/index.mdx (via ApiErrorSchema (symbol, a top-level const))
  • content/docs/kernel/contracts/data-engine.mdx (via DataProtocol (symbol, a top-level interface), ERROR_CODE_LEDGER (symbol, a top-level const object))
  • content/docs/kernel/services-checklist.mdx (via DataProtocol (symbol, a top-level interface), MetadataProtocol (symbol, a top-level interface))
  • content/docs/permissions/system-context.mdx (via DataProtocol (symbol, a top-level interface))

⛔ 4 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v15.mdx (via DataProtocol (symbol, a top-level interface), MetadataProtocol (symbol, a top-level interface))
  • content/docs/releases/v17/17-0.mdx (via ApiErrorSchema (symbol, a top-level const), DataProtocol (symbol, a top-level interface), ERROR_CODE_LEDGER (symbol, a top-level const object), MetadataProtocol (symbol, a top-level interface))
  • content/docs/releases/v17/17-1.mdx (via ApiErrorSchema (symbol, a top-level const), ERROR_CODE_LEDGER (symbol, a top-level const object), EnhancedApiErrorSchema (symbol, a top-level const))
  • content/docs/releases/v17/17-4.mdx (via ERROR_CODE_LEDGER (symbol, a top-level const object))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 2 changed file(s) yielded no anchor (packages/spec/src/api/dispatcher.zod.ts, packages/spec/src/api/metadata.zod.ts) — pages documenting those are invisible to this run
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 136 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 d3958bac6b41f128ac269e0dbe8f9cb49f9bc17f → packageMentionDocs.

Which tree this was computed on

This run read content/docs from b54babc701d040e17f27e6cf724c55170b279cf5 — the merge of head 24d9fba6853632e578426586682669ebfb9d253a into base d3958bac6b41f128ac269e0dbe8f9cb49f9bc17f, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin b54babc701d040e17f27e6cf724c55170b279cf5 && git checkout b54babc701d040e17f27e6cf724c55170b279cf5
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin d3958bac6b41f128ac269e0dbe8f9cb49f9bc17f 24d9fba6853632e578426586682669ebfb9d253a && git checkout -B drift-repro d3958bac6b41f128ac269e0dbe8f9cb49f9bc17f && git merge --no-ff 24d9fba6853632e578426586682669ebfb9d253a

node scripts/docs-audit/affected-docs.mjs --json d3958bac6b41f128ac269e0dbe8f9cb49f9bc17f

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs d3958bac6b41f128ac269e0dbe8f9cb49f9bc17f → pass the list as
args.docs, on the commit named under Which tree this was computed on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants