| name | true-the-docs |
| description | Reconcile developer-facing design docs in `docs/` and `docs/private/` against shipped reality (code, commits, post-mortem artefacts). Classifies each doc (A/B/C/D/E/P archetypes), then applies per-archetype edits — preserving historical value where it matters, archiving what's truly superseded. Three modes: `--corpus` (whole-tree triage report), `--topic <theme>` (slice reconciliation), `--doc <path>` (single-doc mode). Use after a checkpoint or release, when code has outrun its design docs.
|
| user-invocable | true |
| allowed-tools | Bash, Read, Write, Edit, Glob, Grep, Agent, AskUserQuestion, TodoWrite |
Reconcile design docs against shipped code. Classify per doc, act per
archetype, preserve historical value.
Principle. Design docs are a different genre from reference docs.
Planning narrative sometimes has value even when superseded. The skill
judges per doc — which sections to rescue, which to rewrite, which to
fossilise as history. Blanket "update all" destroys historical
evidence; blanket "archive all" loses design intent that still guides
current work.
Output quality bar. Fewer well-chosen edits > many cosmetic ones.
Triage by cold-reader impact — "would this mislead a contributor
picking up this doc fresh in six months?" — not by gap count.
Invocation
Four modes, picked by args:
/true-the-docs --corpus — whole-tree triage report (no edits)
/true-the-docs --topic <theme> — reconcile a slice, apply edits
/true-the-docs --doc <path> — reconcile one doc, apply edits
/true-the-docs --claude-pointers — classify just the design docs
that CLAUDE.md (root + siblings) actively points at, then sweep
the CLAUDE.md files informed by the result. Cheaper than --corpus
for the most common "is the orientation layer still honest?" ask,
and the only mode that edits CLAUDE.md. See Phase 5 below.
--dry-run — any mode, writes edits to /tmp/true-the-docs-preview/
instead of real paths
Scope
In scope: docs/design-*.md, docs/private/*.md (excluding session
notes), docs/walkthroughs/*.md as evidence, docs/*.md top-level,
docs/archive/ (public) and docs/private/archive/ (gitignored) for
moves — source-aware: public docs archive public, private docs archive
private. Never cross the boundary.
CLAUDE.md handling. CLAUDE.md is in scope only via
--claude-pointers mode (Phase 5). The other modes never touch
CLAUDE.md — different genre, higher blast radius, always-in-context.
Editing CLAUDE.md without the pointer-classification context is the
trust-by-association failure mode that motivated v2.
Out of scope:
docs/private/*-session-notes.md and docs/walkthroughs/*.md as
edit targets — append-only historical records. Used as evidence only.
- User-facing text — owned by
user-documentation-review agent.
- Marked-historical docs (with "rejected path" or equivalent banner)
— these don't need truing to match reality; they may need a dated
post-script, handled as a separate pass.
The four-phase workflow
Each phase earns its keep. Don't skip.
Phase 1 — Scope orientation (5 minutes, no edits)
git log --since=<window> --oneline — one shot. What shipped?
- List candidate docs: glob + grep by theme keywords (for
--topic)
or all of docs/ (for --corpus).
- Reject "audit everything" up front. For
--topic, pick docs with
actual topic content. For --corpus, do shallow classification
(front-matter + H1 + git log -1), not deep reads.
- Identify tracking docs (status tables, checklists) that need
cross-doc parity checks.
Phase 2 — Parallel audit (agent fan-out)
Launch up to three parallel design-doc-review agents, one per
doc cluster. Same contract for each:
Review these docs: . Mode: deep / shallow. Return tight-bullet
gap list with file:line refs. No prose commentary.
The prose-only constraint is load-bearing. Prose audits dissolve into
paragraphs the skill re-parses. Enforce bullets.
For --corpus, invoke the agent in shallow mode, batch ~25 docs per
call, ~3 calls total.
For --topic, invoke in deep mode, one call per cluster (e.g. "track C
runtime docs", "track C tracking docs", "track C session notes as
evidence only").
For --doc, one deep call.
Phase 3 — Plan consolidation
Write a per-doc edit list into a plan note at
docs/private/truing-<scope>-<date>.md (gitignored via docs/private/
being gitignored, so it's a working scratchpad).
Scope explicitly what's in and what's not:
- In scope: inline edits, changelog headers, banner additions, archive
moves, front-matter.
- Not in scope this pass: session-notes rewrites (never), CLAUDE.md
updates (v1), structural reshuffles without clear framing, cosmetic
phrasing drift.
Sequence edits: biggest / most-cross-referenced docs first, so later
docs can cite them.
For --corpus, the plan note IS the output. No edits. Human reviews
and drills in via --topic / --doc.
Phase 4 — Edit + verify
Apply edits in priority order. After each doc:
- Update front-matter (status, last-trued, trued-against).
- Prepend changelog header (templates/changelog-header.md).
- Apply targeted inline edits.
- Add banners for superseded sections, preserving original content
visibly (never silently delete).
- Handle moves for Archetype D.
After all edits, run the 5-check verification sweep (mechanical,
cheap; catches what re-reading won't):
- Tense sweep: grep edited docs for
will, plan to, pending,
unresolved, TBD, TODO, slated for, to be written. Every
hit that wasn't deliberate preservation is a rot candidate.
- Cross-ref resolution: every
[text](path) in edits — does
path exist?
- Commit anchor spot-check: for each cited commit subject, does
git log --grep=<subject> find it?
- Status-table parity: if tracking docs were edited, grep all
| N | X | ⬜/✅/🟡 | rows and - [ ]/- [x] lines for the same
checkpoint across docs. They must agree.
- Orphan-reference grep: for any doc moved to an archive folder
(
docs/archive/ or docs/private/archive/), grep the rest of
docs/ + CLAUDE.md for references to the old path. Update or flag.
- Boundary check: for every move this pass, verify source-aware
destination — no
docs/private/*.md landed in docs/archive/, no
public doc landed in docs/private/archive/. Privacy ≠ staleness.
Running the checks is cheap. Skipping is where docs re-rot.
Phase 5 — CLAUDE.md sweep (--claude-pointers mode only)
After Phases 1–4 finish for the docs CLAUDE.md points at, sweep the
CLAUDE.md files themselves informed by the per-doc classifications.
This is the only mode that edits CLAUDE.md.
Phase 5a — Extract the pointer set
Find the design-doc paths CLAUDE.md (root + every sibling) actively
points at. One shot:
grep -oE "docs/[a-zA-Z0-9_/-]+\.(md|html)" CLAUDE.md desktop/CLAUDE.md \
bristlenose/*/CLAUDE.md frontend/CLAUDE.md 2>/dev/null \
| awk -F: '{print $2}' | sort -u
Flag any pointer whose target file doesn't exist — those are sweep
wins regardless (broken link or already-archived doc).
Phase 5b — Classify in batches
Fan out 3 parallel design-doc-review agents in shallow mode, batched
by topic affinity (~25 docs per batch). Each agent returns archetype
classifications and especially flags patched-but-aspirational
bodies — see Traps. The classification feeds the sweep, not edits.
Phase 5c — Act on Archetype D before the sweep
Any D-classified doc moves to its archive (source-aware) before
CLAUDE.md is edited. The sweep updates pointers to the new archive
paths. Don't sweep first and archive later — you'll re-edit CLAUDE.md
twice.
Phase 5d — Sweep CLAUDE.md
Concrete cuts to look for (in priority order):
- Wall-of-text "Current status" / version-history blocks. If
CHANGELOG.md exists, replace with one orienting paragraph + a
pointer. Version-history mirrors bitrot fast.
- Pointers to docs the agent flagged D or to files that don't
exist. Drop or redirect to archive.
- Duplicate guidance. A rule in Key Conventions repeated in
Gotchas is dead weight in Gotchas. A topic-pointer in Gotchas that
duplicates the sibling-CLAUDE.md index in Reference Docs is dead
weight. Always prefer the authoritative location.
- Gotchas now enforced by a CI gate / hook / test. The gate is
the fence; the prose is the redundant sign. Borderline: keep prose
if it explains why the gate exists in non-obvious ways.
Do not sweep on autopilot. The third-pass test: "would removing
this make a future session more likely to repeat the mistake?" If
yes, keep.
Phase 5e — Update orphan refs in other docs
When archive moves happen, refs in other design docs and sibling
CLAUDE.md files break. Bulk path updates via gsed are faster than
per-file Edit calls for mechanical substitutions. But watch the
leak-scan trap: if updating a public doc that mentions a leak-pattern
stem (100days, qa-backlog, succession-plan, etc. — see
~/.bristlenose-leak-patterns), the Edit/Write hook will block. Use
indirect rephrasing or leave the existing reference and add a
breadcrumb elsewhere.
Phase 5 verification
In addition to the 6 standard checks, run:
- CLAUDE.md size delta: report
wc -c before and after. Useful
to spot whether the sweep earned its keep (char delta, not lines —
wall-of-text blocks are often one very long wrapped line).
- Sibling-CLAUDE.md drift check: the per-package CLAUDE.md files
should still cohere with the root after the sweep. Spot-check any
pointer that crosses files.
The archetypes (summary)
Full detail in archetypes.md. Quick reference:
- A — fresh, changelog only
- B — one drifted section, targeted edits + changelog
- C — multiple sections triaged, rescue/rewrite/mark-superseded
- D — body is historical, prepend superseded report, move to
docs/archive/
- E — insufficient evidence, escalate to human
- P — pending/aspirational, stays in
docs/, changelog confirms
still-aspirational date
Conventions the skill enforces
Front-matter
Schema: front-matter-schema.md.
---
status: current | partial | pending | mixed | archived-historical | archived-reference
last-trued: 2026-04-21
trued-against: HEAD@<branch> on 2026-04-21
superseded-by: [optional list of current docs that replace this]
supersedes: [optional list of archived docs this replaces]
split-candidate: true
---
Added if absent, never silently overwritten.
Changelog header
Prepended to the doc body for Archetypes B, C, D, and optionally A/P
when there was something to confirm. Template:
templates/changelog-header.md.
Banners
Two kinds, both using blockquote syntax so they render visibly:
- Truing-status banner (Archetypes B, C, D):
templates/stale-banner.md
- Section-superseded banner (inline for specific sections in C
docs):
> **Superseded by X as of YYYY-MM-DD** — see [doc-Y.md].
Archive
Two folders, mirrored: docs/archive/ (public) and
docs/private/archive/ (gitignored). Source determines destination:
a doc moves into the archive that matches its origin tree. Never cross
the boundary — a superseded private doc stays private. Each archive
has a README.md stating "historical interest only, do not consult as
spec." Front-matter status disambiguates
historical vs reference. No subfolders — folder-name-as-editorial-
judgement blurs.
Evidence anchors
Prefer file:line links + commit subject lines over raw SHAs. SHAs
on feature branches get rewritten by squash-merge. Only cite SHAs
when they're reachable from origin/main and you're confident.
Preserve pre-contact content
Never silently delete content that predates shipped reality. Mark
it visibly stale (banner) and keep the body so readers debugging "why
did we pivot?" can trace the delta. Replacing pre-spike guess with
empirical result means both appear — old list preserved as baseline,
new section authoritative.
Integration with existing machinery
/end-session Phase 2 step 6: invoke design-doc-review on any
design doc touched in-session. If B/C, offer /true-the-docs --doc.
Never auto-archive at session-end — fatigue biases "yes" on
prompts; archival requires explicit --doc invocation.
/usual-suspects: add a row to the agent-selection table —
invoke design-doc-review when design docs were touched AND
implementation scope overlaps doc scope.
- Co-trigger with
user-documentation-review: user-facing text changes
(README, man page, help, locales) signal that design docs behind
that code probably drifted too. design-doc-review fires in the
same moments.
- Short-circuit re-firing: if
last-trued front-matter points at
HEAD or within 5 commits of HEAD, skip re-classification to avoid
triple-firing and contradictory banners.
Traps (learned from prior Track C truing pass)
- Prose trap. Agent audits in prose = unusable. Enforce bullets.
- Volume-as-success. Many cosmetic edits ≠ good truing. Few
load-bearing edits > many nit edits.
- Deleting pre-contact wrong things. Preserve the delta. Visible
staleness is a feature.
- Rewriting session notes. Append-only historical record. Never.
- Inventing structure the docs don't warrant. New section needs
multiple shipped things with shared framing. One-off stays inline.
- Trusting your own summary. Re-reading your own edits smells
right even when it isn't. The 5-check verification is mechanical
and catches what re-reading won't.
- "Same subject" two docs. Not duplication — one is canonical, one
is cross-cutting. Cross-reference, don't mirror.
- Patched-but-aspirational bodies. A doc with a recent status
banner at the top but a body that still describes the old or
proposed approach. Surface-trued, substance-stale. The cheap test
("follow the pointer, does it look fresh?") gives a false pass — the
banner reassures, the body misleads. Shallow agent pass must look
past the header and spot-check the body. Flag explicitly in
classification output; don't fold into B or C silently. Inverse
case (header conservative, body shipped) is the same failure mode
in reverse — also flag.
- Leak-scan trap when updating orphan refs. Public-doc Edit/Write
operations that touch a leak-pattern stem (
100days, qa-backlog,
succession-plan, etc.) are blocked by the PreToolUse hook. When
archival creates orphan refs in public docs that mention those
stems, prefer indirect rephrasing or leave the original reference
and add a breadcrumb elsewhere. Don't fight the hook with
--no-verify — the hook is doing its job.
Output
After completing, print a summary:
True-the-docs — <scope>
Mode: <corpus | topic: X | doc: Y>
Docs classified: N (A: a, B: b, C: c, D: d, E: e, P: p)
Edits applied: <doc count> (<file count> files touched)
Moves: <archived-historical: N, archived-reference: M>
Verification: 5/5 checks clean (or list failures)
Plan note: docs/private/truing-<scope>-<date>.md
Next: review git diff; commit when satisfied
Known limitations
- CLAUDE.md truing is supported only via
--claude-pointers mode
(Phase 5). The other modes don't touch CLAUDE.md by design — the
pointer-classification context is what makes the sweep honest.
- Cross-cutting docs (
design-modularity.md, design-i18n.md)
may classify differently under different --topic invocations.
Naive last-write-wins for now. Owning-theme convention is future
work.
- Raw SHA anchors on feature branches are naive — trust user to
not invoke mid-squash-merge.
--claude-pointers mode skips orphan design docs. Docs in
docs/ that no CLAUDE.md points at aren't classified or audited —
that's a separate "orphan audit" pass, run quarterly.
Version history
- v2 (May 2026) — added
--claude-pointers mode + Phase 5
(CLAUDE.md sweep); source-aware archive boundary (public/private);
6th + 7th + 8th verification checks; patched-but-aspirational named
as an explicit trap; leak-scan trap documented.
- v1 (Apr 2026) — initial release:
--corpus, --topic, --doc
modes; A/B/C/D/E/P archetypes; 5-check verification.