**Stacked on #3036** (its commit is the parent). That PR fixes a guard that had been red on `main`; this closes the gap it leaves and, in doing so, turned up a second defect in the helper. ## 1. Nested anchors were accepted but never resolved #3036 makes the parser recognise sub-entries — correct, and it fixes the red. But it validates only their link *shape*. Measured on that branch: | corruption | result | |---|---| | **nested** entry → `#kb-nonexistent-anchor` | **passes** | | **top-level** entry → `#kb-nonexistent-anchor` | fails | A TOC guard exists so links resolve. Checking that for one class of entry and not the other leaves a dead sub-link to be found by a reader clicking it. ## 2. Resolving them exposed the slugify bug Adding the check failed immediately — on the **real document**, against a heading that exists: ``` Nested TOC anchor #theming--overlay-layering-for-dashboard-views matches no heading ``` The document is right; the helper was wrong. `slugifyHeading` collapsed whitespace **runs**: ```js .replace(/\s+/g, "-") // theming-overlay-layering-... .replace(/\s/g, "-") // theming--overlay-layering-... ← GitHub, and the doc's own link ``` GitHub emits one hyphen **per space**. `### Theming & Overlay Layering for Dashboard Views` loses the `&` and keeps both spaces, so the true anchor carries a double hyphen. **This was latent, not dormant-and-harmless:** the two spellings differ only when punctuation is stripped from *between* words, and all eighteen numbered section titles are punctuation-free — so every existing use of the helper agreed. The first heading with an `&` in it would have produced a false failure against a correct document, which is the shape most likely to get a guard edited rather than believed. ## Mutations (all four) | mutation | result | |---|---| | clean | 4/4 pass | | nested anchor broken | **fails** ← was green before this PR | | top-level anchor broken | fails | | malformed top-level line | fails | | `slugify` reverted to collapsing | **fails** — the helper fix is load-bearing | Lint clean, FNXC gate exit 0. Test-only. ## Note This is the fifth guard in this batch to ship with a hole found by mutating it rather than reading it, and the second where fixing one class of input revealed the checker had been quietly wrong about another. The pattern is consistent enough to be worth expecting: **when a guard starts examining something it previously skipped, the first thing it finds is usually its own bug.** If #3036 lands first this rebases to a single commit; if taken together the stack applies as-is. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved heading links to match GitHub-style anchors when punctuation separates words. * Enhanced nested table-of-contents validation to confirm links point to headings in the document. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
6.7 KiB
6.7 KiB