Skip to content

Teach check_markdown.py to require code-fence info strings #45

Description

@ckrough

Self-check item 8 in scriptorium/skills/docs/SKILL.md ("All code fences carry a language and are complete") is the one item in the nine-item emission gate with no mechanical coverage at all. The skill says so plainly today: the linter "covers part of item 7 and part of item 9, and none of item 8: it never checks whether an info string is present."

Deliberately left out of PR #42 (closing #27), which was a spec change; its ## Out of scope names this as follow-up.

The change is small; the ripple is why it was deferred

scriptorium/skills/docs/scripts/check_markdown.py already captures what it needs. scan_fences stores Fence.info_string, and the only consumer is check_backtick_info_string, which fires on a backtick within an info string and never on its absence. The check is roughly if not fence.info_string.

What makes it more than three lines:

  • LLMS_DESCRIPTION states the linter's coverage by count ("five error-severity checks", "five advisory-severity checks"). A sixth changes both the text and the shape it advertises.
  • The 52-test suite in scripts/test_check_markdown.py asserts against that shape.
  • scriptorium/skills/docs/references/commonmark.md carries a ## Scope note documenting the same coverage, and SKILL.md documents the item-8 gap as permanent. Both need updating, or they become the wrong half of a contradiction.

Decide before implementing

Error or advisory? Error severity makes exit 1 stop emission, which is what item 8 being a gate item implies. Advisory keeps the exit code clean but leaves item 8 effectively unenforced. The repo's own markdown must pass at whichever severity is chosen.

Worth checking against a related finding: the daedalus altitude review noted that self-check items 2 through 5 are all decidable by a program over the file path and the YAML block, and that eval assertions already state some of them as regexes. If a check_frontmatter.py is coming, this check may want to land alongside it rather than alone.

Acceptance Criteria

  • check_markdown.py flags a code fence with no info string, at a severity chosen and stated in the issue thread
  • LLMS_DESCRIPTION reports the new check and its corrected counts
  • test_check_markdown.py covers the new check both ways, and its shape assertions match the new counts
  • references/commonmark.md ## Scope note and SKILL.md's item 7-9 paragraph both describe the new reach; the "none of item 8" claim is removed
  • Every markdown file the repo ships passes at the chosen severity
  • bash scripts/gates/structure.sh and claude plugin validate . both exit 0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions