Skip to content

finding(gate): check-doc-links never validates in-page #anchor fragments — a renamed heading orphans every cross-reference to it with the gate green #7644

Description

@claude

Measured while executing #6172's rename (PR #7643) and deliberately not fixed there — the rename's own one-line anchor correction is the thing this gap let through. ⛔ Unassigned, no labels; routing and grading are the triage seat's.

What was measured

scripts/check-doc-links.mjs validates a relative link's target file but never validates an in-page #fragment against the document's own headings. Renaming a heading therefore orphans every [label](#slug) cross-reference on that page, silently, with the gate green.

This is not inferred from reading the script — it is a two-arm control run on one file (content/docs/api/schema-reference.md), each arm proved on disk by anchored count plus git hash-object off the HEAD blob, and each restored with git checkout HEAD -- ABSOLUTE_PATH proved by blob equality and an empty git diff HEAD:

arm mutation node scripts/check-doc-links.mjs
control appended [control probe](./no-such-page-xyz.md) exit 1 — "Relative links must name the target FILE including its real extension"
subject rewrote one existing anchor to (#totally-not-a-heading-xyz) exit 0 — "Links are valid across 17 scan roots."

The control arm is what makes the zero a reading rather than a dead instrument: the same invocation, on the same file, catches a broken file path and misses a broken fragment.

Why it is worth a card

The failure mode is the #6086 class one level up: a page that looks cross-referenced, a gate that reports green, and a reader who clicks into nothing. It is also the exact residue a rename leaves. In PR #7643, ### KanbanSchema became ### DeclarativeKanbanSchema and […](#kanbanschema) one screen away had to be corrected by hand; had that been missed, every gate in the farm would still have been green.

The population is not hypothetical — content/docs/api/schema-reference.md alone carries a **Related:** line of in-page anchors under most of its sections, and those are precisely the links a heading rename breaks.

Reproduce

cd content/docs/api
perl -0pi -e 's/\(#declarativekanbanschema\)/(#totally-not-a-heading-xyz)/' schema-reference.md
node ../../../scripts/check-doc-links.mjs ; echo "exit=$?"   # 0
git checkout HEAD -- schema-reference.md
printf '\n[control probe](./no-such-page-xyz.md)\n' >> schema-reference.md
node ../../../scripts/check-doc-links.mjs ; echo "exit=$?"   # 1
git checkout HEAD -- schema-reference.md

Whether the remedy is resolving fragments against the target document's headings (including the cross-file page.md#frag form, not measured here) or declaring the omission with a reason is a gate-design call, not this seat's.

Refs: #6172 · PR #7643 · #6342 (the other measured check-doc-links population gap — different: that one is about which FILES are scanned, this one about what is checked inside a scanned file).


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatfinding

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions