TestDocsRelativeLinks walked only docs/developer; widening it to all of
docs/ immediately surfaced the same class of rot the gate was built
for, outside its old reach:
- docs/index.md was the old monolith's landing page: linked the deleted
api-reference.md, 10 directory-style area links, and escaped the docs
tree to README/AGENTS/.env/compose. Rewritten as a portal whose every
link resolves, with one representative endpoint doc per API area and
pointers to the new writing-ui-docs.md standard.
- directory-style links in user stubs (devices/, ../operations/)
- case-mismatched links (Development.md) in contributing.md
- monolith-era pointer (API_REFERENCE.md, TROUBLESHOOTING.md) and
escaped AGENTS.md links in contributing/development.md
- docs/development/calibre-opf-implementation.md double-up escapes, a
link to the removed repo-root plan file (absorbed here), and a
source-code hyperlink the docs site can't serve (now inline code)
- operations/operations.md linked three never-written guide pages as
aspirational links - they stay plain text until pages exist
HANDS-OFF (project owner, 2026-11-02): docs/user/filters/** and
docs/user/searching-and-filtering.md are exempt as link sources so no
future checker failure can force edits to the filter documentation.
Files linking INTO them remain checked.
Three problems, one root cause each:
1. Sidebar jump: the server rendered its own default (current section
open, rest collapsed) and restoreDocsNav corrected it after paint —
open-then-close. Fix: persistence moved server-side. toggleCollapsible
now writes a docs_nav cookie (strictly-necessary UI state, no
identifiers, SameSite=Lax); ApplyNavOverrides merges it into the nav
before render, so first paint IS the visitor's state. The post-paint
restore is deleted.
2. Arrows out of sync / double-click: two visibility mechanisms
disagreed. There was NO data-collapsed CSS at all — collapsed sections
were only ever hidden by JS after paint, and the arrow rotation came
from a different (server) state. Now: style.css hides on
[data-collapsed=true] (single source of truth, server-rendered),
applyCollapsed sets only the attribute, arrows rotate from the same
merged value. Live check: 37/37 collapsibles arrow-consistent.
3. api-reference.md links: all 20+ quick links were directory-style
(authentication/ etc.) that 404 on the docs site, plus stale targets
(books/, ../collections-api.md, websocket 'coming soon'). Rewritten to
real per-file links — all 9 unique targets return 200 live. Same rot
fixed in admin/hash-conflicts.md, development.md, android-app.md,
create_media_item.md, koreader-protocol.md; docs/index.md redirected
from the deleted collections-api monolith (stale 530-line duplicate of
the gated api/collections docs — deleted, per the WO2 doctrine).
New gate: TestDocsRelativeLinks walks docs/developer/** and fails make
test on any relative link that is directory-style or unresolvable —
overview links can never silently rot again.