Skip to content

feat(wiki-lint): mechanical linter for input/wiki/ (#4)

Fabrice deprez requested to merge feat/wiki-lint-mechanical-checks into main

Generalized port of the mechanical linter built for the FYL wiki (fyl-guidelines#8 / MR !34) into this template — config-driven, like the rest of scripts/wiki-site/, not a re-hardcoding of FYL's 5 page types and field names.

Design departs from a from-scratch port: reuses the site build's own config loader, page collector and wikilink resolver (scripts/wiki-site/lib/{config,collect,markdown,resolve-links,badges}.js) rather than re-implementing them, so a link/anchor/reference this script accepts is guaranteed to behave identically in npm run wiki:build. Two small, additive changes to that shared library made this possible without touching its existing behavior:

  • lib/markdown.js: wikilinkRule now also pushes a resolved edge onto an optional ctx.resolvedLinks when the caller asks for it (build.js never sets this field, so its own broken-link warning is untouched).
  • lib/badges.js: ARRAY_CHIP_KEYS exported instead of module-local, so the cross-reference check validates exactly the fields the metadata panel tries to render as links — one definition, not two lists that can drift apart.

Ticket correction: #4 (closed) says required frontmatter fields are "documented in docs/wiki.config.md" — they weren't; only structural/build fields (id, folder, layout, label) were. Added an optional types[].requiredFrontmatter (array of field names) to the config schema instead of hardcoding FYL's field names into the lint script, and documented it in docs/wiki.config.md. Populated it on the shipped default (scripts/wiki-site/wiki.config.default.json) from the fields docs/llm-wiki-schema.md already documents for the 5 default types.

Checks (docs/wiki-lint.md has the full reference):

  1. Frontmatter required-field presence per type + type/folder agreement.
  2. Broken wikilinks (blocking) and unresolved #anchors (warning — see graph.mjs docstring for why not blocking).
  3. Orphan pages: unreachable from any navPages[].slug.
  4. raw/ path citations (body + frontmatter source/source_doc) that don't resolve to a real file under input/raw/.
  5. Cross-references: frontmatter fields (depends_on, related_topics, applies_to, ...) that don't resolve to any real page — invisible today since the renderer silently falls back to an unlinked chip on failure, no warning anywhere. Found via this exact gap while porting: neither anchors nor cross-refs were in FYL's original ticket scope, both are real gaps confirmed while adapting it here.

Verification, not just "doesn't crash":

  • scripts/wiki-lint/fixtures/lint-sample/ — a third fixture alongside the existing default/custom ones, with one deliberate violation planted per check and a valid look-alike case next to each one (a resolving raw/ citation beside a missing one, a valid anchor beside an invalid one, a reachable page beside an orphan) — proves detection fires without also proving it's just flagging everything.
  • Found and fixed one genuine pre-existing orphan in the custom fixture (usecases/uc-001-sample, never linked from anywhere) while building this — linked it from index.md rather than leaving a wiki-lint-detectable defect sitting in a regression fixture.
  • 26 tests (scripts/wiki-lint/wiki-lint.test.mjs): unit-level per module plus one end-to-end test asserting the exact violation count the lint-sample fixture should produce, so a future regression in either the fixture or the checks fails loudly.
  • npm test: 26/26. npm run wiki:build on both existing fixtures: unaffected, still 0 broken links.

Not wired into CI — deliberately scoped out, matching that wiki:build itself isn't gated either (see docs/wiki-lint.md "Wiring it into CI").

Deliberately out of scope (documented in docs/wiki-lint.md): citation grounding (does raw/spec.md actually say what the page claims) and terminology-drift/glossary checks — both need an LLM in the loop, belong to a separate future pass, not this mechanical linter.

Closes #4 (closed)

Merge request reports

Loading