Skip to content

docs(spec): re-anchor the dead tracker citations in ui/ and two freed sites to the commits that decided them (stage 5) - #20576

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

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

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #20234
Clause-②: no

What changed

This is stage 5 of the staged sweep: the ui/ area (packages/spec/src/ui/**, 133 files), plus two sites freed since stage 4: data/filter-subtree-provenance.ts (PR #20460 landed without touching it) and meta-spelling/manifest-collection-spelling.ts (the census hand-over, comment 5882628946 on #20234). ui/view-grouping-query.ts is excluded because #20446's claim holds it; it carries 4 citations and none of them is dead, so the exclusion removes nothing. Later stages cover the other areas, so this PR says Part of.

Every comment and docblock site in that population that cites a tracker number answering 404 has been rewritten in ruling C+D's form C (comment 5749154545 on #19123). That is 87 comment sites: 84 re-anchored and 3 respelled.

  • 84 re-anchored, over 25 numbers. Each rewritten line now cites the commit in origin/main history that decided what the line describes, and says in its own words what that commit decided. One line (ui/dashboard.zod.ts:686) quotes ADR-0087 itself; it keeps ADR-0087 as its citation and paraphrases the amendment heading instead of quoting its number.
  • 3 respelled, so each number of a sibling pair carries its own qualifier: ui/view.zod.ts:3634 now reads objectui#6110 + objectui#6111, and ui/component.zod.ts:3479 and :4140 now read objectui#8221's PR objectui#8758. Each second number answers 404 here, and the sentence attributes it to objectui (objectui REST: issues/6111 200, pulls/8758 200, merged 2026-09-09).

Only comments changed, plus the one generated reference page they project into and a patch changeset. Every source file keeps its line count (90 lines out, 90 in, over 25 files). Three of the 90 lines held no dead number; each is the other half of a rewritten sentence: ui/action.zod.ts:400, ui/action-param-carryover.test.ts:13 and ui/expression-bindable-text-keys.test.ts:119. No code token moves (see the guard below).

No tracker number is added. Every tracker number on an added line was already on the lines it replaces, and no PR #N is added.

Census: before and after

Instrument. This is the instrument of stages 1 to 4, rebuilt for this stage. It sends REST GET /repos/objectstack-ai/objectstack/issues/N without following redirects, for every distinct number cited in the population. The population is:

  • the citation gate's own exported CITATION_RE and NON_CITATION_HEADS at the base, kept when the qualifier is none, objectstack, objectstack-ai/objectstack, framework, pre- or post-;
  • matched case-insensitively (Pre-, POST-, Framework);
  • N of 100 or more, excluding summon heads.

A qualifier covers only the number it is joined to. Each site is classified by the TypeScript parser as a line comment, a docblock, a block comment 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: 18 of 18 lit (200) and 18 of 18 dead (404) over 6 checkpoints in the base run, and 15 of 15 and 15 of 15 over 5 checkpoints in the head run.

reading tree numbers probed 200 404 301 or other dead sites lines files of which comments of which strings
before base 487a7846df, probed 2026-09-29T02:57:01Z to 02:59:36Z 400 372 28 0 111 110 26 90 21
after head 83e39641d0, probed 2026-09-29T03:15:00Z to 03:18:06Z 383 372 11 0 24 23 8 3 21

The head probe found no number newly dead since the base probe: the same 372 numbers answer 200. The head was probed at 83e39641d0; every census file is byte-identical at the final head.

Cross-check under the grammar that landed during this stage. PR #20554 (199002b3e4) landed the closed qualifier set while this stage ran, and it reads objectui PR #8758 as objectui's number. Re-run with that gate's own extractCitations and namesThisRepository, the same population reads 108 dead sites before and 21 after, all 21 test strings. The difference is exactly the three objectui PR #8758 prose sites below, which that PR's own header measured as "census deaths here that are not deaths at all".

Per file. Cited sites are every in-repo citation the population reads, live or dead.

file cited sites (base) dead before by class dead after
data/filter-subtree-provenance.ts 9 3 3 docblock 0
meta-spelling/manifest-collection-spelling.ts 8 2 2 line comment 0
ui/action-param-carryover.test.ts 5 3 2 line comment, 1 string 1
ui/action.test.ts 39 3 3 line comment 0
ui/action.zod.ts 90 7 5 docblock, 2 line comment 0
ui/bulk-action.test.ts 9 4 2 line comment, 2 string 2
ui/bulk-action.zod.ts 9 3 2 docblock, 1 line comment 0
ui/component-element-navigation-17987.test.ts 8 5 1 docblock, 4 string 4
ui/component-type-vocabulary.test.ts 8 2 2 docblock 0
ui/component-type-vocabulary.ts 2 1 1 docblock 0
ui/component.test.ts 190 22 11 line comment, 11 string 11
ui/component.zod.ts 265 20 16 docblock, 4 line comment 0
ui/dashboard.zod.ts 52 1 1 docblock 0
ui/expression-bindable-text-keys.test.ts 3 2 2 line comment 0
ui/expression-bindable-text-keys.zod.ts 4 2 2 docblock 0
ui/form-select-option.test.ts 3 1 1 docblock 0
ui/index.ts 15 2 2 line comment 0
ui/interaction-config-retirement.test.ts 19 1 1 docblock 0
ui/react-blocks.test.ts 9 2 1 docblock, 1 string 1
ui/react-blocks.ts 17 4 2 docblock, 2 line comment 0
ui/view-form-features-root.test.ts 4 1 1 line comment 0
ui/view-metadata-schema.test.ts 31 3 2 line comment, 1 string 1
ui/view-submit-redirect-url.test.ts 8 1 1 line comment 0
ui/view.test.ts 136 2 1 docblock, 1 string 2
ui/view.zod.ts 331 13 10 docblock, 3 line comment 2
ui/widget-i18n-retirement.test.ts 17 1 1 line comment 0

ui/ alone went from 106 dead sites in 24 files to 24. The other 107 ui/ files carry no dead site.

Per-number table

Anchors are 9-hex commit abbreviations. "Wrote" means the commit's own diff added the line being rewritten.

number comment sites / files anchor: what it decided
#5970 4 / 2, action.zod.ts:819, action.test.ts:268, :304, :354 97e7e3caa: ActionSchema.visible / disabled speak one condition shape; visible gains its boolean arm. Stage 1's anchor for the same number
#6276 7 / 1, component.zod.ts:34, :165, :568, :2455, :2546, :2554, component.test.ts:2126 78f0be872: declares element:record_picker's flat sort / limit on the #5611 rule (maintainer ruling 2026-08-08, direction A). It wrote :34, :2455 and the "enumerate by the renderer's read pattern" lesson
#8794, #8836 3 / 1, filter-subtree-provenance.ts:130, :131, :156 1850ebbb0: corrects the reuse-safety claim from the survey and pins the invariant. It wrote :131 itself. Stages 1 and 3 gave both numbers this anchor
#9933 7 / 2, view.zod.ts:2517, :5060, :5086, :5118, :5513, view-metadata-schema.test.ts:398, :410 d5552ca13: admits columnState as an explicitly runtime-only view-overlay key, rejected by name at every authoring door. It wrote "explicitly out of #9933's scope"
#9972 3 / 2 (+1 unread), component.zod.ts:2213, component.test.ts:382, :3565; also :3612's #9881/#9972, a slash-joined spelling the grammar does not read 60e0f900a: records the live read point of page:tabs items[].icon and its accept-pin. It wrote the :382 header
#10194 1 / 1, manifest-collection-spelling.ts:71 (pre-#10194) 2306a765c: /meta/theme and /meta/analytics_cube stop storing any JSON as success and validate at the write door. The line now says "the store-anything branch from before commit 2306a76". Stage 1's anchor
#10274 6 / 2, component.zod.ts:2304, component.test.ts:308, :405, :3591, :3603, :3612 d1ba685ec: re-measures the four pin citations and gates the class. Its gate header records that the re-measure found two anchors wrong since they were written, which is why a refresh re-reads. Stage 3's anchor
#10485 4 / 4, index.ts:51, interaction-config-retirement.test.ts:116, widget-i18n-retirement.test.ts:112, manifest-collection-spelling.ts:67 35ad101bc: retires the themes carrier and ThemeSchema whole (ruled B, 2026-08-21; ADR-0049 stays cited). Stage 1's anchor
#11284 5 / 2, react-blocks.ts:39, :94, :109, :295, react-blocks.test.ts:139 5383fa670: the react tier converges on the metadata-tier vocabulary, deprecate-first. Its changeset heads "(#11284, maintainer ruling 2026-08-23)"
#11350 1 / 1, index.ts:105 ece4dad31: records the maintainer ruling of 2026-08-23 that a type in an entry's public declarations must be nameable from that entry. Same wording as stage 1's kernel/index.ts:53
#11507 2 / 2, component.zod.ts:1465, component.test.ts:2726 88b9d749a: declares sys_activity.type an open, author-extensible vocabulary (maintainer ruling 2026-08-24, direction 4). Stage 3's anchor
#11658 2 / 2, component.zod.ts:1464, component.test.ts:2725 1a6a19c31: opens RecordActivityProps.types to author-contributed kinds, executing that ruling. Stage 3's anchor
#11703 3 / 2, action.zod.ts:399 to :400, :460, action-param-carryover.test.ts:12 to :13 5cb62d88b: clone_permission_set carries all five copied facets; its params list had silently dropped three. The lines now name "the silent-drop shape commit 5cb62d8 fixed"
#11753 5 / 2, action.zod.ts:66, :390, :398, :409, action-param-carryover.test.ts:1 0e4e51b0a: ActionParamSchema.carryOver, the spec half of the 2026-08-25 maintainer ruling (recommendation A). It wrote every one of these lines, and its changeset records the visible: false measurement :398 names
#12194 1 / 1, view.zod.ts:4838 311433f6b: declares the metadata item-name grammar (QUALIFIED_ITEM_NAME_PATTERN among it) and refuses it at the publish door. Stage 2's anchor
#12868 5 / 2, view.zod.ts:2938, :2966, :3179, :7087, form-select-option.test.ts:4 c459da6bc: narrows the per-option default key out of the form-view options vocabulary. Its changeset records the ruled census :2966 cites ("measured ZERO occurrences"). Stages 3 and 4's anchor
#12950 3 / 2, component-type-vocabulary.ts:4, component-type-vocabulary.test.ts:4, :101 225e7690f: created component-type-vocabulary.ts; its message records the readiness read :101 pins (global:search and global:notifications stay declared)
#13156 2 / 2, view-form-features-root.test.ts:70, view-submit-redirect-url.test.ts:110 fd289be45: strips tracker ids from function-declaration-built refusal prose. It wrote both lines. Stage 3's wording ("commit fd289be's strip")
#13670 1 / 1, expression-bindable-text-keys.zod.ts:72 8c6a7fc0b: records text.value as deliberately omitted; its message states the ruling that text's evaluation channel is content alone
#13672 3 / 2, expression-bindable-text-keys.zod.ts:89, .test.ts:65, :118 e854a531a: narrows the button row to the spelling its key reaches, and records action:button and ui:button as deliberately out
#16626 1 / 1, component.test.ts:2336 30b099078: the objectui pin bump to 53ded82bf7a4 that ships objectui#7754's array-analytics lowering, the door the family waited on. The association is PR #16788's body (it names #16626 as the card it lands), and 30b099078 is that PR's merge commit; neither its message nor its diff names #16626 (the stage-3 #11065 precedent)
#17987 9 / 2, component.zod.ts:10, :4014, :4062, :4153, :4193, :5068, :5226, :5457, component-element-navigation-17987.test.ts:4 e233db9db: declares element-level navigation on object-kanban / object-calendar and gives object-timeline its ComponentPropsMap row, executing the objectui#8652 ruling (verbatim B)
#18003 1 / 1, dashboard.zod.ts:686 ADR-0087, the rung above a commit. The line quoted the ADR's own amendment heading, number included. It now reads "(ADR-0087, its 2026-09-13 amendment, 「the level half」)": the ADR stays the citation and the fragment it quotes is verbatim
#18177 5 / 2, bulk-action.zod.ts:51, :169, :262, bulk-action.test.ts:61, :307 adabccf5f: BulkActionParamSchema is strict and declares dependsOn, executing decision batch #146 item 4, letter A
#6111 1 / 1, view.zod.ts:3634 respelled objectui#6111 (not re-anchored): it is objectui's number
#8758 2 / 1, component.zod.ts:3479, :4140 respelled PR objectui#8758 (not re-anchored): objectui's PR #8758, merged 2026-09-09

No ADR or ruling-record file in docs/adr/ or scripts/adr-anchors/ records the decision behind any of the 25 re-anchored numbers except #18003. ADR-0126 mentions #11703 and #11753 only as references ("permission-set precedent"), not as the record of either decision.

Anchor checks. Every sha on an added line is one of 23, and none is on a removed line. At the base 487a7846df:

Wordings to check, each true of its commit:

  • filter-subtree-provenance.ts:130 and :156 read 「survey commit 1850ebb records」: the survey was the card's, and the commit's message records its measurement. It is stage 3's wording for the same relation (「from the survey it records」).
  • component.zod.ts:1465 and component.test.ts:2726 read 「maintainer ruling commit 88b9d74 declared」: that commit landed the ruling (direction 4) as the sys_activity.type declaration.
  • manifest-collection-spelling.ts:71 reads 「the store-anything branch from before commit 2306a76」: before that commit, PUT /meta/theme/:name stored any JSON as success.

Mechanical guard: no code token moves

The check compares leaf tokens with comments stripped, base 487a7846df against the head. It uses the TypeScript parser's leaf tokens from the head's lockfile, so template literals are scanned in context, and it excludes JSDoc nodes. It ran over all 25 touched .ts files, and every control mutates the head text in memory only.

  • Real run: 101,836 base tokens, 0 files with a token change (exit 0).
  • Comment-insertion control (ui/index.ts): 0 files changed (exit 0).
  • Positive control (a declaration inserted into ui/view.zod.ts): 1 file reads DIFFER at token 19222 (exit 1).
  • Positive control (one digit changed in a component.test.ts test title): 1 file reads DIFFER at token 14972 (exit 1).

Line balance holds in every file, 90 out and 90 in over the 25, and every line count is equal at base and head. Tracker numbers: added-not-removed is empty in every file. The net-removed numbers are the 25 in the table, 85 sites: the census's 84 comment sites, plus the slash-joined #9972 at component.test.ts:3612.

Generated page

check:generated proved one artifact stale: content/docs/references/ui/expression-bindable-text-keys.mdx, the projection of expression-bindable-text-keys.zod.ts's module docblock. check:generated --fix regenerated only that page, and a re-run read All 15 generated artifacts are up to date. Its two changed lines are the :72 and :89 substitutions verbatim. No other docblock here projects into a reference page, and nothing under skills/** moved.

Changeset

This change ships bytes, so a patch changeset for @objectstack/spec is included. It says only that the provenance comments were re-anchored. Clause-②: no: no export, key, value or type moves (the guard above).

Measured on the head's built package: 6 touched sources are src/**/*.zod.ts, which files[] ships verbatim. The rewritten comments also reach dist:

  • c459da6bc appears in 32 bundled .js files and 2 .d.ts;
  • adabccf5f in 24 .js and 2 .d.ts; d5552ca13 and 0e4e51b0a in 24 .js each; e233db9db and 78f0be872 in 2 .js and 2 .d.ts each;
  • the positive control, the pre-existing sentence 「the object-field face enforces」, appears in 32 files.

Gates (head 1b885d3c27)

  • Citation judging pass, run as CI runs it: pnpm check:issue-citations && node scripts/check-issue-citations.mjs, both under the grammar PR fix(scripts): check-issue-citations reads a qualifier only when it names a known repository, so pre-#N / post-#N are judged and framework#N is this repository #20554 landed, exit 0. The self-test passes 114 cases in 8 batteries. The live, diff-scoped run judged 13 citations across 11 files: 3 resolve and 10 are declared cross-repo references. It reads "every citation this change adds resolves".
  • Doc authoring: pnpm check:doc-authoring exits 0. Its 16,759 customer-facing strings across 1,174 spec sources carry no internal issue id, and the sibling-package prose-id baseline holds with no growth.
  • Derived gates: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at this head derived 112 families, and all 112 exit 0. --ran reports 112 run, 0 NOT MEASURED, 0 unrun. A full turbo run build of ./packages/* at this head ran first, under the shared verify lock: 71 of 71 tasks, VERDICT command-exit 0. So no gate met an unbuilt prerequisite.
  • Five roster gates the derivation flags for this diff (their rosters sit in .changeset/ or packages/, so their silence proves nothing): node scripts/check-changeset-fixed.mjs, pnpm --filter @objectstack/spec run check:spec-changes, pnpm check:authz-resolver, pnpm check:error-code-casing and pnpm check:filter-alias-parity. All exit 0.
  • pnpm --filter @objectstack/spec run check:generated (derived) reads All 15 generated artifacts are up to date, and check:docs reads 226 generated files in sync.
  • Tests and typecheck, under the lock:
    • pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/ui src/meta-spelling: Test Files 98 passed (98), Tests 3452 passed (3452), VERDICT command-exit 0 (the chain held the lock 142s on a shared box).
    • The 16 spec suites outside src/ui that read the touched files' source text or pin their lines: Test Files 16 passed (16), Tests 489 passed (489). They are scripts/{export-origins,file-description,root-index,schema-closure,skill-map-guards,strictness-ledger}.test.ts, src/ai/tool-confirmation-prescription-tense.pin.test.ts, src/api/api-entry-graph.pin.test.ts, src/contracts/scoped-context.test.ts, src/data/filter-subtree-provenance.test.ts, src/shared/{alias-integrity,evaluated-slot-population,retired-key-migrate-sentence,union-author-message-pins}.test.ts, src/system/constants/platform-object-names.test.ts and src/type-alias-convention.pin.test.ts. Three more suites matched the reader scan and are not run here: scripts/build-schemas-check-mode.test.ts only imports ViewItemSchema (code the guard proves unchanged) and rebuilds schemas in a temp tree; scripts/def-key-collisions.test.ts names ui/view.zod.ts only in a comment; scripts/published-projection-choke-point.test.ts matched on build-react-blocks-contract.ts, not a touched file. They are left to CI.
    • pnpm --filter @objectstack/spec typecheck: exit 0, including check:test-typecheck (53 files, 251 errors, 138 pinned signatures held). The same three runs also passed, with the same counts, on the pre-merge tree.
  • Lint, as a proven narrowing: eslint --no-inline-config --format json over the 25 touched .ts files gives 25 files, 0 errors and 0 warnings. All 25 are in eslint's own population (isPathIgnored is false for each, read through eslint's API). eslint.config.mjs never enables type-aware linting (no parserOptions.project, which its own lines 327 to 328 state), so a comment edit here cannot move the verdict on any untouched file. The repo-wide pnpm lint is CI's run.
  • Merge probe: a merge-tree of the head onto origin/main f572a7eb3c, from a bare shared clone with no merge driver registered, exits 0 (2026-09-29T04:15Z).

Acceptance notes


Generated by Claude Code

… sites to the commits that decided them (stage 5)

Comment and docblock lines only. Each line that cited a tracker number
answering 404 now cites the commit on main that decided what the line
describes, or ADR-0087's own amendment where the line quotes it. Two
sibling pairs are respelled so each number carries its own qualifier
(objectui#6110 + objectui#6111, objectui#8221's PR objectui#8758).
No code token moves; every file keeps its line count.

Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx
Co-authored-by: Claude <noreply@anthropic.com>
…e-anchored docblock

Generated by `pnpm --filter @objectstack/spec check:generated --fix`, which
proved only this page stale; never hand-edited.

Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx
Co-authored-by: Claude <noreply@anthropic.com>
Brings in the landed citation-qualifier grammar (scripts/check-issue-citations.mjs) so the derived gates run against it; no file of this diff moved on main.

Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 19 documentable anchor(s). ⚠️ 5 changed file(s) yielded no anchor (packages/spec/src/data/filter-subtree-provenance.ts, packages/spec/src/ui/component-type-vocabulary.ts, packages/spec/src/ui/dashboard.zod.ts, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

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

  • content/docs/protocol/objectui/layout-dsl.mdx (via ComponentPropsMap (symbol, a top-level const object), FormSectionSchema (symbol, a top-level const))
  • content/docs/ui/react-pages.mdx (via REACT_BLOCKS (symbol, a top-level const object))

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

  • content/docs/releases/v15.mdx (via FormSectionSchema (symbol, a top-level const))
  • content/docs/releases/v16.mdx (via ActionParamSchema (symbol, a top-level const))
  • content/docs/releases/v17/17-0.mdx (via ActionParamSchema (symbol, a top-level const))
  • content/docs/releases/v17/17-1.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/releases/v17/17-3.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/releases/v17/17-4.mdx (via ComponentPropsMap (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
  • 5 changed file(s) yielded no anchor (packages/spec/src/data/filter-subtree-provenance.ts, packages/spec/src/ui/component-type-vocabulary.ts, packages/spec/src/ui/dashboard.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 — 137 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 f572a7eb3c272a5be85e3ec64d2516c944c3b243 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 5282ad8d830a1f5006264885f9baff5802cc5a5a — the merge of head 1b885d3c277b668ac4d9c1533b65dc436204ed2a into base f572a7eb3c272a5be85e3ec64d2516c944c3b243, 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 5282ad8d830a1f5006264885f9baff5802cc5a5a && git checkout 5282ad8d830a1f5006264885f9baff5802cc5a5a
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin f572a7eb3c272a5be85e3ec64d2516c944c3b243 1b885d3c277b668ac4d9c1533b65dc436204ed2a && git checkout -B drift-repro f572a7eb3c272a5be85e3ec64d2516c944c3b243 && git merge --no-ff 1b885d3c277b668ac4d9c1533b65dc436204ed2a

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

⚠️ 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 f572a7eb3c272a5be85e3ec64d2516c944c3b243 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 1b885d3c277b668ac4d9c1533b65dc436204ed2a
Local-runs: none

Read: card #20234 (body; every comment: triage 5856637615 and the ruling it points at, 5749154545 on #19123; the seat-2 pointer 5858331362; stage 1's claim 5859418643, report 5860236501, ACCEPT 5860414140 and landing 5860571318; stage 2's claim 5860586561, report 5861177436, record 5861396181, ACCEPT 5861418146 and landing 5861600944; stage 3's claim 5876941555, report 5881236928, record 5881413052 on PR #20533, ACCEPT 5881425268 and landing 5881658422; stage 4's claim 5881696480, report 5882273687, record 5882405617 on PR #20548, ACCEPT 5882433819, the census hand-over 5882628946 and landing 5882686893; the stage-5 claim 5882723856 and report 5883647445), PR #20576 (body, its one comment 5883617608, the 27-file list, the four commits and the net diff against the merge base dee9b26f6c, read from the local ref at the head above with -U0 and the head blobs for enclosure), the 23 cited commits (message and stat for all; the diff wherever the message does not name the number or the line claims more than the subject), PR #16788 for the #16626 association, docs/adr/0087-metadata-protocol-upgrade-contract.md:380-400, docs/adr/**, docs/NORTH-STAR.md and scripts/adr-anchors/ for the 25 numbers, the landed citation grammar in scripts/check-issue-citations.mjs on origin/main (KNOWN_REPOSITORIES, PROSE_QUALIFIER_RE, CITATION_RE, namesThisRepository, the judged and deferred surfaces), lint.yml's job roster, pr-automation.yml's WHICH LEVEL, packages/spec/package.json files[], and content/docs/references/** at the head for the removed fragments. Nothing was built, run or re-run: the diff was read with git, the anchors with git show, the numbers with grep, and the tracker numbers with REST GET against this repository and objectui (a GitHub read, not a local run). The check-runs were read for judgment once, at 2026-09-29T04:31Z.

① Derived judgments

(a) Scope and file surface: right. 27 files: 23 .ts files under packages/spec/src/ui/**, packages/spec/src/data/filter-subtree-provenance.ts, packages/spec/src/meta-spelling/manifest-collection-spelling.ts, the generated content/docs/references/ui/expression-bindable-text-keys.mdx (+2/-2) and the new .changeset/spec-ui-provenance-anchors.md (+14). Every .ts file is on the claim's surface; the claim's one exclusion, ui/view-grouping-query.ts, is byte-identical base to head (blob 3923dc3c1). The dev deviation at manifest-collection-spelling.ts:67 (#10485) is inside the surface: the claim's file surface is "comment and docblock lines that cite a tracker number answering 404" in the files it names, and it names this file; the hand-over's :71 is the site the census found, not a fence around the other lines of the same seven-line comment (:67-:73); #10485 answers 404 here; the rewrite takes stage 1's anchor for that number (35ad101bc, whose message says it dropped exactly this PLURAL_TO_SINGULAR fold), the same anchor this PR gives ui/index.ts:51, interaction-config-retirement.test.ts:116 and widget-i18n-retirement.test.ts:112; no other claim holds the file. Leaving :67 dead beside a re-anchored :71 would have been the deviation. origin/main (f572a7eb3c) is one commit past the merge base and moves none of the 27 files, so the net diff judged here is the diff against current main; GitHub reads mergeable: true. No governed surface is touched; 198 changed lines; the head repository is the base repository; first line Part of #20234, no closing keyword; Clause-②: no on the body's second line.

(b) Comment-only, no test string or code token moves: right. git diff -U0 over the 25 .ts files: 90 lines added, 90 removed, and every one of the 180 begins with //, * or /**. Enclosure read on the head blobs: each * line sits under an open /** with no */ between, and each // line stands outside any template literal. One backtick-parity flag, component.zod.ts:5457, traces to backtick pairs split across the // comments at :5336-5337 and :5351-5352; :5457 itself is the // run between the object-tree and object-timeline rows of ComponentPropsMap. Every file keeps its line count, 25 of 25. So no string literal, it/describe title, .describe() text or code token is on any changed line; the 21 dead-number test titles the dev lists stay as strings, which is the claim's rule. Three changed lines held no dead number and are the second half of a rewritten sentence (action.zod.ts:400, action-param-carryover.test.ts:13, expression-bindable-text-keys.test.ts:119), all comment text inside the 90-for-90 balance. The dev's parser-level token comparison is not re-run and not needed for that verdict.

(c) Numbers: right. Over the whole diff, added-minus-removed tracker numbers is empty for every one of the 27 files; net-removed is exactly the dev's 25 numbers, 87 sites (85 in the .ts files, the dev's 84 comment sites plus the slash-joined #9972 at component.test.ts:3612, and the two objectstack#13670 / objectstack#13672 lines in the mdx). No PR #N stands on any added line; the three objectui# joined spellings are the only qualified citations added. REST issues/N without redirects, 2026-09-29T04:38Z: all 25 numbers answer 404 here, and so do #6111, #8758 and pulls/8758; lit control #16862 200, dead control #16714 404. The this-repository numbers that stand on added lines answer 200: #12183 (component-type-vocabulary.ts:4) and #9397 (component.zod.ts:2213) in judged files, #15828, #9881, #11992 and #2555 in deferred test files; #146 is a decision-batch ordinal (NON_CITATION_HEADS). The dev's census over 400 numbers is otherwise not re-run.

(d) Anchor truth: right, 23 of 23. 23 distinct sha-shaped tokens stand on added lines and none on removed lines (the 82a94170c on both sides of component.test.ts:3612 is the former objectui pin in unchanged text, not an anchor). git rev-parse --disambiguate answers exactly one object for each; git merge-base --is-ancestor exits 0 for all 23 against origin/main f572a7eb3c; every one is a single-parent commit; the repository is not shallow. 22 of 23 name the number they replace in their own message or diff (the message for 17; the diff alone for e854a531a, 0e4e51b0a, 225e7690f, c459da6bc and 5383fa670; #8836 through 1850ebbb0's diff beside #8794 in its message). Read beyond the subject, against the line each now anchors:

(e) dashboard.zod.ts:686, ADR-0087 as the citation: right. The removed line quoted the ADR's own heading, 「Amended 2026-09-13 (#18003) — the level half」; docs/adr/0087-metadata-protocol-upgrade-contract.md:390 on origin/main reads **Amended 2026-09-13 (#18003) — the level half.**. The added line, (ADR-0087, its 2026-09-13 amendment, 「the level half」), is true of that text: the amendment is dated 2026-09-13, "the level half" is its verbatim title fragment, and the paragraph it introduces says what the docblock claims (the npm level is a second axis; every "major" in that section is a protocol major; the level a changeset declares is the npm version of the lockstep group). Form C's first rung is "the ADR or ruling record when one exists"; the record exists and stays the citation, and the dead number leaves. The ADR's own heading still carries #18003, a governed surface and #20556's carrier, not this card's.

(f) The three respellings: right. view.zod.ts:3634 objectui#6110 + objectui#6111: #6111 answers 404 here and objectui's #6111 (200) is "Authored FormSection.visibleWhen is dropped by all four plugin-form layouts", the section-level current_user scope question the docblock's heading names, beside objectui#6110 (200, the evaluators passing an undefined scope). component.zod.ts:3479 and :4140 objectui#8221's PR objectui#8758: #8758 answers 404 here as an issue and as a pull; objectui's PR 8758 (200) is "retire the legacy string sort clause — one spelling, the array (objectui#8221)", merged 2026-09-09T05:21Z, which is what both sentences say it does. Under the landed grammar the old spellings were this repository's: PROSE_QUALIFIER_RE matches only a known name followed by whitespace and an optional PR / issue ending immediately before the #, so objectui#8221's PR #8758 (with #8221's between) and the bare second number of + #6111 fall to CITATION_RE as bare and are judged here, dead (the self-test at :1341 pins the pair case). The joined objectui#N form resolves through KNOWN_REPOSITORIES to objectui, so each respelled number now names its board, and PR #20554 made the same fix at data/field.zod.ts:370. The three prose sites left as they stand (view.zod.ts:2354, :2579, view.test.ts:426, each objectui PR #8758) are read by that grammar as objectui's: PROSE_QUALIFIER_RE names them, the header's own measurement calls exactly these three "census deaths here that are not deaths at all", and the self-test at :1333-1336 pins objectui PR #N as cross-repo. Leaving them is right.

(g) The generated page: right. content/docs/references/ui/expression-bindable-text-keys.mdx:77 and :94 are the expression-bindable-text-keys.zod.ts:72 and :89 substitutions verbatim with the * prefix stripped; the surrounding 25 lines of the module docblock and the page agree line for line except the generator's own {@link expressionBindableTextKeysFor} rendering on an unchanged line, so the page reads as generator output, not a hand edit. No other page under content/docs/references/ at the head carries any of the 25 numbers or a removed fragment. check:docs runs in Type Check · source gates (lint.yml, the artifact-gate steps beside check:authorable-surface and the spec pin-citation check), success at the read, which is the generator's own verdict that the committed page equals its output at this head.

(h) Form C over the whole diff: right. Each rewrite leads with commit 9-hex (or [commit 9-hex] where the marker form stood) and says in words what was decided; the one ADR site keeps the ADR; no tracker number or PR #N is added. The citation gate judges packages/**/src/**/*.ts as comment prose and defers packages/**/*.test.ts, so the 11 non-test files (action.zod.ts, bulk-action.zod.ts, component-type-vocabulary.ts, component.zod.ts, dashboard.zod.ts, expression-bindable-text-keys.zod.ts, index.ts, react-blocks.ts, view.zod.ts, filter-subtree-provenance.ts, manifest-collection-spelling.ts) are in its population and the 14 test files are not; the added-minus-removed count in (c) covers the 14. Nothing author-shown is touched (no .describe(), refusal or migration-entry text), so form D does not arise.

② Semver level

patch for @objectstack/spec is right and Clause-②: no is right. The package ships bytes from this diff: files[] carries dist and src/**/*.zod.ts, so the six touched .zod.ts sources (action, bulk-action, component, dashboard, expression-bindable-text-keys, view) ship verbatim with their rewritten comments, and the other docblocks reach dist through the bundle. (b) shows no export, key, value or type moves, so nothing widens or narrows: WHICH LEVEL (pr-automation.yml, the 2026-09-04 ruling on #15294) keeps a change that moves no public surface at patch, the level stages 1 (21ab410417), 2 (5cf58eb164), 3 (03b19d9cfd) and 4 (6154165484) took for the same act. The changeset names one package, describes only the comment re-anchoring, carries no tracker number and no model identifier, and Check Changeset is success at the read.

③ Boundary flags

Blocking: none.

Dev deviations, each answered:

  1. manifest-collection-spelling.ts:67 beyond the hand-over's :71: inside the surface, judged in (a); the PR body names it.
  2. The objectui#8221's PR #8758 shape read as a pair and respelled, the three prose objectui PR #8758 sites left: right, judged in (f) against the landed grammar.
  3. [Decision] 两条裁决援引同一个 launch-window convention,却给出相反的 changeset 等级(minor vs major)—— 退役一个可写键到底发哪一级? #18003 kept as ADR-0087 with the heading paraphrased: right, judged in (e).
  4. chore(console): bump the objectui pin past 53ded82b — the shipped console refuses every array analytics where, which blocks the ruled #15442/#15449 filter converge #16626's anchor 30b099078 naming no chore(console): bump the objectui pin past 53ded82b — the shipped console refuses every array analytics where, which blocks the ruled #15442/#15449 filter converge #16626: a true anchor, judged in (d); the PR-body tie is stated in the PR and here.
  5. The slash-joined #9972 at component.test.ts:3612 beyond the census count: reconciled in (c), 85 net-removed in the .ts files.
  6. One merge of origin/main (1b885d3c27, merging dee9b26f6c) after PR fix(scripts): check-issue-citations reads a qualifier only when it names a known repository, so pre-#N / post-#N are judged and framework#N is this repository #20554 moved the gate script: the net diff against the merge base is the 27 files, GitHub's file list agrees, and the one commit main has since gained touches none of them. Right.
  7. The shared scratchpad overwrite of stage 3's census.mjs / probe.sh: a dev-side incident in a scratch directory, not in the diff and not this diff's.
  8. Tests narrowed to src/ui + src/meta-spelling and 16 reader suites, three suites left to CI: the head's Test Core shards are the verdict and are read under CI below.
  9. The verify-lock queue timeout and the setsid PID reads: not a verdict; no other process was signalled.
  10. Commit trailers: all three non-merge commits carry Claude-Session plus Co-authored-by: Claude, no model identifier; the PR body ends with the session-URL footer.
  11. Four commits including the merge, no force-push: the branch shows exactly those four.
  12. Worktree cleanup: not observable from here, not this diff's.
    Open questions: the report lists none. Out-of-scope findings: the rot outside packages/spec/src (ADR-0087's own heading, ADR-0126, scripts/strictness-ledger.test.ts, check-objectui-pin-citations.ts, consumer tests) has its carrier, [finding] dead tracker citations outside packages/spec/src have no carrier: #20234 sweeps only the spec tree, and PR #20554 makes 26 more visible (pre-#N / Pre-#N) in cli, drivers, metadata, objectql, plugins, runtime and types #20556; the 21 ui/ test-title strings and react-blocks.test.ts:140's "recorded on-card" (no number) go to a later stage of this card; the 11 sibling pairs whose second number answers 200 here belong to the [finding] check-issue-citations reads the pre- in pre-#N (and post- in post-#N) as a repository qualifier, so a dead number in that spelling is classed cross-repo and never judged #20330 / PR fix(scripts): check-issue-citations reads a qualifier only when it names a known repository, so pre-#N / post-#N are judged and framework#N is this repository #20554 grammar family. Carriers named; right.

Non-blocking, each true of its commit: (1) component.test.ts:2336 could carry PR #16788 beside commit 30b099078 as the convenience link ruling C allows, since the commit's own text names no card and the association lives on the PR; the line is true without it. (2) filter-subtree-provenance.ts:130 and :156 read "the survey commit 1850ebb records", stage 3's wording for the same relation; dense but exact, the commit's message records the #8794 survey's measurement. (3) component.zod.ts:2213 reads "which is why #9881 and commit 60e0f90 recorded", a card and a commit in one pair; both are true records of the read points. (4) component-element-navigation-17987.test.ts keeps #17987 in its file name; a file name is neither comment nor string and the sweep does not reach it. (5) Rung: several anchored retirements also have ADR-0087 D3 entries (stack-themes-carrier-retired for #10485, form-view-option-default-removed for #12868, ui-bulk-action-param-unknown-keys-refused for #18177, the item-name-grammar semantic entry for #12194); this PR takes the commit rung as stages 1 to 4 did, precedent-consistent, and the D3 id is the more durable in-repo record if the ruling's first rung is later read to include those entries. (6) The docs-drift comment 5883617608 lists two hand-written pages via ComponentPropsMap, FormSectionSchema and REACT_BLOCKS: a symbol-anchored advisory on a comment-only diff; Flag docs affected by code changes is success.

Escalated: none.

CI at this head, the judging read at 2026-09-29T04:31Z: 32 check-runs, 16 success, 2 skipped (Console Pin Gate, Packed-tarball smoke (opt-in)), 0 failure, 14 not concluded. In progress: Lint & Repo Gates, Build Core, Temporal Conformance (live PG + MySQL), Test Core (1/6) through (6/6), Dogfood Regression Gate (1/3) and (2/3), Dogfood Verify CLI, Type Check · workspace and Type Check · consumer gates; the Test Core, Dogfood Regression Gate and TypeScript Type Check aggregates had not yet been created. So six of the seven required contexts are NOT presumed green here and must be read concluded before the PR is armed: Lint & Repo Gates (the diff-scoped citation judging pass, check:doc-authoring, pnpm lint and the repo check:* steps), TypeScript Type Check (its workspace and consumer lanes), Test Core, Dogfood Regression Gate, Build Core and Temporal Conformance (live PG + MySQL). Success at the read: Governed Surface Queue Guard (the seventh), Type Check · source gates (the spec artifact gates: check:docs, check:authorable-surface, check:generated --reconcile-only, the pin-citation check and siblings), Type Check · debt ledger, Check Changeset, Spec property liveness, Build Docs, Dogfood Regression Gate (3/3), Check PR Size, Check Documentation Links, Flag docs affected by code changes, the three claim and closing guards, Auto Label and filter. No red run exists to attribute. Of the 112 families the dev derived, the head's runs answer the changeset, generated-artifact, debt-ledger, liveness, docs-build and governed-surface families now; the citation pass, doc-authoring, lint, typecheck, build, test, dogfood and temporal families are the runs still open above. PR is a draft; mergeable: true, mergeable_state: blocked (draft); assignee os-tesla; no auto-merge armed.

Implemented-by: claude/issue-20234-dead-citations-ui
Reviewed-by: session_014EJ1ED8X4MMrT18BhVx4tx

VERDICT: PASS


Generated by Claude Code

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants