Nothing in CI checks that an in-page anchor link actually resolves to a real heading, or that a relative file link points at something that exists. README.md alone has around 68 headings and ~29 ](#anchor)-style links, several now living inside <details>/<summary> blocks from the 2.0.10 collapsible-sections refresh - that PR's own description notes "every other anchor this file and others link to still resolves unchanged," but that was manually verified once, not continuously enforced.
A broken anchor or a stale relative link (e.g. to a renamed explainers/*.md, or a file moved during a cleanup like #238's assets reorg) fails silently for a reader clicking the link - nothing about it shows up red in CI the way a broken test does.
Proposed scope: a small script (Python stdlib - re/pathlib is enough, no new dependency needed) that:
- Parses every
#heading in each tracked .md file into its GitHub-slugified anchor form
- Parses every
](#slug) and ](relative/path) link in those same files
- Fails if a link's target isn't in the corresponding file's heading set (for anchors) or doesn't exist on disk (for relative paths)
Wire it into lint.yml alongside the existing check_em_dash.py step, same style.
Nothing in CI checks that an in-page anchor link actually resolves to a real heading, or that a relative file link points at something that exists. README.md alone has around 68 headings and ~29
](#anchor)-style links, several now living inside<details>/<summary>blocks from the 2.0.10 collapsible-sections refresh - that PR's own description notes "every other anchor this file and others link to still resolves unchanged," but that was manually verified once, not continuously enforced.A broken anchor or a stale relative link (e.g. to a renamed
explainers/*.md, or a file moved during a cleanup like #238's assets reorg) fails silently for a reader clicking the link - nothing about it shows up red in CI the way a broken test does.Proposed scope: a small script (Python stdlib -
re/pathlibis enough, no new dependency needed) that:#headingin each tracked.mdfile into its GitHub-slugified anchor form](#slug)and](relative/path)link in those same filesWire it into
lint.ymlalongside the existingcheck_em_dash.pystep, same style.