Skip to content

Build a scripts/ docs linter for the conventions mkdocs build cannot catch #121

Description

@allister-beamable

scripts/sentence_case_headings.py is currently the only detector ever promoted out of a scratch directory. At least five others were written during the 2026 copyediting passes and then discarded — detect2.py, expand_contractions.py, classify_fences.py, flip_and_tag.py, detect_indented.py — so every session that needs a fence audit or a contraction check rebuilds the same tool from scratch.

Codify the settled conventions as executable checks in scripts/ on main, alongside the existing heading script. Each checkbox below is scoped to a single short session; pick one and close it.

The design point: a clean mkdocs build is not evidence of a healthy branch. Every structural defect listed below passed the build, several of them under --strict.

Structural checks — these matter most

  • Fence-token validity. Reject any token that is not a real Pygments lexer. One call to pygments.lexers.get_lexer_by_name per distinct token. Would have caught jsonc (5 blocks rendering unhighlighted on toolkit/v0.4), gradle, yml, and log
  • mkdocs.yml parity across branches. toolkit/v0.4 was cut after the 2026-07-16 convergence but from a pre-convergence template, so it lacked pygments_lang_class and every code block emitted a bare <div class="highlight">. Found only by diffing rendered HTML against another branch. The check is for branch creation from a stale template, not for sync regression
  • abbr snippet target exists. pymdownx.snippets auto_append swallows a missing file silently, so toolkit/v0.4's abbr config was inert for the branch's entire life with no build complaint
  • auto-sync-core.yml invariant. The real workflow belongs on core/v* only; every other live branch carries a byte-identical stub. One md5sum comparison. See AGENTS.md, "Branch mapping". Frozen unity/v4.0 still holds the obsolete merge-based copy and should be allowlisted, not flagged
  • No docs/includes on a branch that is not a sync target. It is a core-owned path, so its presence elsewhere is a silent-overwrite trap waiting to trigger. toolkit/v0.4 has one and is safe only because it appears in no core matrix

Prose checks — all had working prototypes in past sessions

  • Contractions (must be fence- and inline-code-aware)
  • Terminal periods on bullets and table cells
  • Filename-as-alt-text
  • <center> captions
  • Trailing whitespace
  • Standalone 4-space-indented code blocks. Must be fence-, admonition-, and list-aware: the naive grep produced a 524-false-positive artifact
  • Sentence-case headings (already covered by scripts/sentence_case_headings.py; wire it into the same entry point)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bite-sizeClosable in a single ~30-minute docs sessiondocumentationImprovements or additions to documentationenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions