Repository navigation
feat(check-docs): assert every relative Markdown link resolves - #1193
Merged
Merged
Conversation
check_adr_numbers checks that ADR files are numbered right; nothing checked that a link to one lands. Two broken links shipped in a week — a template naming a mis-typed ADR file, and docs/observability.md using ../adr/ from docs/ (which resolves to a nonexistent repository-root /adr/). This adds a twelfth assertion: every inline Markdown link in every tracked file resolves to a file in the tree, and its anchor, if any, to a heading, the way check_runbook_urls already checks a critical alert's runbook_url. It runs over records too, since a dead link is a structural fault rather than a claim about now. Also fixes the two ../adr/ links in docs/observability.md the new check caught, and bumps README's assertion count to twelve. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4769sNhNE79DH3SBN4YXx
CI runs ruff format --check under --require-all; the if condition it wanted collapsed to one line. No behaviour change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4769sNhNE79DH3SBN4YXx
There was a problem hiding this comment.
🟡 Changes recommended
The checker misses existing reference and nested links, scans untracked files, and permits targets outside the repository.
6 open findings
Parser misses reference-style and nested Markdown links · New Add regression tests for relative-link validation · New Scan only Git-tracked Markdown files · New Reject link targets outside the repository · New Update README check count and list · New Correct documentation for records-wide link scanning · New
What changed in this PR
Adds repository-wide Markdown link validation and fixes two broken ADR links.
Changes:
- Adds relative file and heading-anchor checks.
- Updates documentation assertion counts.
- Corrects observability ADR paths.
| File | Description |
|---|---|
scripts/check_docs.py |
Adds link validation. |
README.md |
Updates assertion count. |
docs/observability.md |
Fixes ADR links. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…-repo Copilot's review of #1193: - Parse reference definitions ([label]: target) and the outer target of a linked badge [](target), both of which the repo uses and the first cut missed. Footnotes ([^x]:) and label lines followed by unquoted prose are not link definitions, per CommonMark. - Extraction and resolution move into markdown_link_targets and relative_link_problems, which --self-test now exercises with fixtures for every form and for missing files, missing anchors and out-of-repo targets. - Discover files with git ls-files, not rglob, so untracked scratch files and the .claude/worktrees copies are not scanned (the check_image_pins.py convention). - Reject a target that resolves outside the repository: GitHub cannot render a link that leaves the checkout, so an absolute path or an escaping ../ is as broken as a missing file. - README's assertion list and the module docstring now name the relative-link check and its records-wide scope. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4769sNhNE79DH3SBN4YXx
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.


What changed
Adds a twelfth assertion to
scripts/check_docs.py:check_relative_links(). Every inline Markdown link and image, in every tracked.mdfile, must resolve to a file in the tree, and its anchor (if any) to a heading in that file — the same waycheck_runbook_urlsalready checks a critical alert'srunbook_url.changelog.mdand the ADRs included, because a dead link is a structural fault, not a claim about now. (The ADR-0095 and exercise-template links that slipped past review this week were both in records/templates.)http(s),mailtoandteltargets are not reached out to; pure#anchorlinks are checked against the file's own headings. Links inside fenced code are skipped, the same fence rulemarkdown_anchorsuses.docs/observability.mdlinked../adr/0070-…and../adr/0088-…, which fromdocs/resolve to a repository-root/adr/that does not exist (the ADRs are underdocs/adr/). Both are corrected toadr/….check_countsverifies README matches.Why
check_adr_numberschecks that ADR files are numbered correctly, but nothing checked that a link to a doc lands. Two broken relative links shipped in a week and were caught only by a review bot. This closes that gap in CI.Blast radius
None at runtime. This is a CI/validation script and three docs; it changes no deployed service.
secrets/*.sops.yamlVerification
scripts/check_docs.pypasses:docs OK — 158 Prometheus + 20 Loki rules, 8 dashboards, 156 panels, 12 assertionsruff check scripts/check_docs.py: All checks passed--self-teststill passes (the anchor rules it covers)markdownlint-cli2reports 0 errors on the changed Markdown🤖 Generated with Claude Code
https://claude.ai/code/session_01A4769sNhNE79DH3SBN4YXx
Generated by Claude Code