feat(docs): aether docs, a Documentation critic, and the sync-docs skill - #10
Merged
Conversation
Every defect in the 1.5.0 documentation audit was found by hand. Three layers
so that does not have to happen again, each catching a class the others cannot,
and all three installed globally so they work in any repo rather than this one.
**aether docs** — the mechanical half. Four families, in order of what they are
worth:
- Prose contradicting [project]. The config already declares how the repo
really runs, so a README saying `pytest` where the config says `uv run
--frozen pytest` is drift, and it is what a new joiner follows on day one.
Resolved per area, so a monorepo command right for web/ and wrong for
backend/ is caught. No generic linter knows your real commands; this is the
family only aether can check.
- Commands that do not exist: npm run X with no such script, make Y with no
such target, bash scripts/z.sh that moved.
- Dead references: relative links, and anchors against real headings.
- aether's own claims: config keys and values against the manifest schema,
subcommands and flags against the engine, retired paths outside a migration
note.
Deliberately narrow — nothing is inferred. A checker that reports
plausible-but-wrong findings gets switched off within a week, so every check
compares a documented string against a declared or on-disk fact. Building it
surfaced five of its own false positives before it shipped: a slug function
that collapsed whitespace runs where GitHub does not, a subcommand regex that
dropped `version|--version|-V`, transcripts read as commands, blocks that `cd`
first, and migration notes read as drift. Each is now a negative assertion.
**A Documentation critic**, on by default, for the half a script cannot reach:
this diff changed a behaviour, so is every sentence describing it still true?
Finding 18 of the audit was exactly that shape — the docs said temper blocks a
push while nothing exits 2 — and no schema check would have found it.
**A sync-docs skill**, so the cheapest moment is covered too: grep for the
string you are changing and fix the prose in the same commit.
Verified against the audit itself. On the pre-audit tree it reports 12 problems
and 8 warnings including both broken critical_paths examples; on current main
it is clean. Run against ~/Code/pimento it passes, and injecting a wrong
command there makes the [project] family fire, so the pass is real rather than
silent.
Also fixed, found by the new check: bonsai's README documented `bonsai
enable-hook` and `disable-hook`, which are not subcommands.
Also fixed, not mine but exposed here: acceptance's spaced-path test asserted
cairn's nudge while the 1.5.0 budget prints only the earliest stage, so it
failed whenever the developer's checkout had an uncritiqued plan. It now runs
from a scratch directory.
32 new assertions in tests/test_docs.sh; 758 across the suite; acceptance 46/46.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every defect in the 1.5.0 documentation audit (#8) was found by hand. Three layers so that does not have to happen again — each catching a class the others cannot, at a different moment, and all three installed globally so they work in any repository rather than only this one.
sync-docsskillaether docsaether checkaether docsA new engine verb beside
doctorandcheck, so the schema and the subcommand list travel with the install rather than coming from the working directory.Four families, in order of what they are worth:
[project]. Your config already declares how the repo really runs. A README sayingpytestwhere the config saysuv run --frozen pytestis drift, and it is what a new joiner follows on day one. Resolved per area, so a monorepo command right forweb/and wrong forbackend/is caught. This is the family only aether can check — no generic markdown linter knows your real commands.npm run Xwith no such script,make Ywith no such target,bash scripts/z.shthat moved.](#anchor)against the headings actually in the file.Wiring it into every review is one line, in any repo:
aether checkruns anycheck.<name>key and both critique commands callaether check. This is also the first time this repo has used the escape hatch its own README advertises.[project]commands are ignored untilaether trust, so without it the first family cannot run — andaether docssays so rather than quietly checking less than the config implies.Verified against the audit itself
That was the plan's stated test, and the commits are right there:
And against a real monorepo,
~/Code/pimento: it passes. I confirmed that is a real pass rather than silence by injecting a wrong command and watching[project:backend] test runs this as uv run --frozen pytestfire, then restoring the file.Not crying wolf was the hard part
The plan named this as the risk: a checker that reports plausible-but-wrong findings gets deleted from the config within a week. Building it surfaced five of its own false positives before it shipped, each now a negative assertion:
#monorepos--projectpathanchoraether versionis not a subcommand[a-z|-]+, soversion|--version|-V)never matchedaether v1.5.0is not a subcommand$ aether status, not a commandbash scripts/setup.shdoes not existcd aether/plugins/bonsaifirstwhetstone.config.mdis a retired pathNothing is inferred: every check compares a documented string against a declared or on-disk fact. Judgement belongs to the critic.
Documentation critic, on by default
[temper] criticsbecomescorrectness, design, risk, coverage, docs. It asks what no script can: this diff changed a behaviour — is every sentence describing that behaviour still true? Finding 18 of the audit was exactly that shape (the docs said temper blocks a push; nothing exits 2), and no schema check would have found it.Two deliberate choices: it is scoped to behaviours this diff changes, not the documentation as a whole, and it is told to say nothing when there is nothing — a critic that manufactures a finding every review is one people learn to skip.
--skip=docsopts out;--only=docsruns it alone. Anyone who has set their owncritics:keeps exactly what they set, since resolution is per key.sync-docsskillInstalled by temper to
~/.claude/skills/, so it fires in every repo. It covers the cheapest moment — while you are editing — and says to grep for the string you are changing rather than the file you expect, then fix the prose in the same commit. Thedescriptiondoes the work of saying it is a rule to follow, not a generator: it never writes documentation.Also fixed
bonsai enable-hookanddisable-hookare documented but are not subcommands. The new check found what the manual audit in docs: correct six READMEs against the code they describe #8 missed.acceptance.sh's spaced-path test was latently broken by v1.5.0. It asserts cairn's nudge, but the budget prints only the earliest lifecycle stage, so it failed whenever the developer's checkout had an uncritiqued plan lying about. Not introduced here, but exposed here; it now runs from a scratch directory.One design constraint worth knowing
The planned
[docs] enabledkey is gone. The manifest format identifies a key by name alone, so a secondconfig.enabled.*collides with temper's own and wins at random — visible immediately as a duplicate row inaether config show docs. An emptypathsis how you turn the check off: one concept rather than two that can disagree.Verification
tests/test_docs.sh; 758 across 11 filesacceptance.sh --full: 46/46, hook cost unchanged at 57ms