Problem
Substrate-PR review churn from dangling references. When a skill section is collapsed/renamed/deleted, sibling skills that inherited from its sub-anchors (§N.x) or pointed at the file are left dangling — and no mechanical check catches it, so reviewers find them manually, one per cycle.
Empirical (this session): PR #12488 collapsed pr-review-guide §10; that orphaned §10.4 / §10.5 / §9.4 anchors inherited by review-response-protocol.md, structural-pre-flight-workflow.md, and pr-review/SKILL.md+manifest. They were caught and repointed one anchor per review cycle → ~3 cycles before all were clean. lint-skill-manifest (budgets / manifest parity / downstreamDocs) and lint-agents (<a id> HTML anchors) cover neither dangling §-anchors nor broken ./*.md pointers.
Prescription
A CI lint (lint-skill-references, or a check folded into lint-skill-manifest) that, over the changed .agents/skills/** surface, flags:
- Dangling
§N / §N.x section-anchor refs — a ref like pr-review-guide §10.4 whose target file has no matching ## 10. / ### 10.4 / §10.4 heading. (Distinguish legit live sections from removed ones by parsing the target's headings.)
- Broken relative file-pointers — a
./<name>.md (or references/<name>.md) link to a file that does not exist.
- Refs to a file deleted in the same diff — any surviving reference to a path removed by this PR.
Fail with <source-file:line> → <dangling target> so the author repoints in one pass, not N review cycles.
Out of scope (the harder, non-deterministic class)
- Count / byte-size drift (e.g. "7 miss-dimensions" vs 8;
wc -c 1818 vs 2713) and ticket-ledger-vs-shipped-surface drift — these need diff/state comparison, not pure reference resolution. Candidate follow-on; not this lint.
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
lint-skill-references (new CI lint) |
this ticket + #12488 churn evidence |
flag dangling §-anchors / broken file-pointers / deleted-file refs across changed .agents/skills/** |
warn-only first run if false-positive rate unknown; then gate |
yes (lint output + skill-authoring note) |
the lint catches the #12488 dangling-anchor class in one pass |
Acceptance Criteria
Decision Record impact
none — additive mechanical guard; consumes the #11319 Map-vs-Atlas substrate lineage.
Refs #11319
Problem
Substrate-PR review churn from dangling references. When a skill section is collapsed/renamed/deleted, sibling skills that inherited from its sub-anchors (
§N.x) or pointed at the file are left dangling — and no mechanical check catches it, so reviewers find them manually, one per cycle.Empirical (this session): PR #12488 collapsed
pr-review-guide §10; that orphaned§10.4/§10.5/§9.4anchors inherited byreview-response-protocol.md,structural-pre-flight-workflow.md, andpr-review/SKILL.md+manifest. They were caught and repointed one anchor per review cycle → ~3 cycles before all were clean.lint-skill-manifest(budgets / manifest parity / downstreamDocs) andlint-agents(<a id>HTML anchors) cover neither dangling §-anchors nor broken./*.mdpointers.Prescription
A CI lint (
lint-skill-references, or a check folded intolint-skill-manifest) that, over the changed.agents/skills/**surface, flags:§N/§N.xsection-anchor refs — a ref likepr-review-guide §10.4whose target file has no matching## 10./### 10.4/§10.4heading. (Distinguish legit live sections from removed ones by parsing the target's headings.)./<name>.md(orreferences/<name>.md) link to a file that does not exist.Fail with
<source-file:line> → <dangling target>so the author repoints in one pass, not N review cycles.Out of scope (the harder, non-deterministic class)
wc -c 1818vs 2713) and ticket-ledger-vs-shipped-surface drift — these need diff/state comparison, not pure reference resolution. Candidate follow-on; not this lint.Contract Ledger
lint-skill-references(new CI lint).agents/skills/**Acceptance Criteria
§N.xref to a non-existent section in the cited skill file../*.md/references/*.mdpointer to a non-existent file (incl. files deleted in the same diff).§9.0,§9.1) and external/ticket refs (#12488) are NOT flagged (no false positives on real anchors)..agents/skills/**changes (sibling tolint-skill-manifest/lint-agents);--base origin/devscoping consistent with the existing lints.Decision Record impact
none— additive mechanical guard; consumes the #11319 Map-vs-Atlas substrate lineage.Refs #11319