Audit Docs
A read-first audit answering "do the docs still match reality?" Produces a
findings report; it does not silently rewrite docs.
Turn contract
Load and verify the canonical Turn contract (11 boxes) before ending every turn (the --fix path commits and pushes like any editing turn). Skill-specific additions (the → Next: box is canonical-owned and not restated here):
✓ The AUDIT DOCS fixed-format report was printed, ending in `Decision: PASS | FAIL`
✓ No doc was rewritten without explicit --fix / user go-ahead
Missing reference → STOP. About to end the turn with any box unchecked? The
turn is NOT done — complete the missing box first (weak models drop
end-of-document duties; this list is first on purpose).
When to use
- Before a release or milestone, after merging several features/fixes, or
whenever the doc set might have drifted from the code and issues.
Step 0 — Discover the project (always first)
Per the agent guide's Workflow conventions + documentation map, then read
what THIS skill needs: the roadmap, the fix index + template, and the feature
folder layout — the map tells you which links and invariants to check.
Checks
Run these and collect findings (cite paths/lines/issue numbers each):
- Roadmap ↔ feature folders. Every
docs/features/<NN>-<slug>/ is in the
roadmap, and every roadmap entry has a folder (or is explicitly "scheduled").
- Feature dependencies. SPEC
Depends on / Branch fields are valid; no
dependency cycles; ordering is consistent with the roadmap.
- Fix index hygiene. Every entry maps to an open issue and an unmerged
branch; flag entries whose issue is closed or whose PR merged (should have
been removed). Flag open fix branches missing from the index.
- Documentation-map links resolve. Every file the map references exists;
flag "scheduled, not yet authored" items so they aren't mistaken for drift.
- Broken intra-doc links. Relative links/anchors point at real
files/sections.
- Issue references. Acceptance/known-issues lines referencing
#N aren't
pointing at long-closed issues without note.
- Language & naming conventions. Artifacts in the project's docs language
(this repo: English); file/dir naming matches conventions (e.g.
kebab-case TS files, PascalCase components).
- Invariant tags. If the project uses invariant/decision IDs (e.g.
INV-/D-/KI-), spot-check that referenced IDs exist where claimed.
- PR-link integrity on
done rows. Every roadmap row (and fix-index
entry) with status done carries a linked PR reference —
done · [#<pr>](<pr-url>). For each bare done, find its PR in the forge
(gh pr list --state all --head feat/<NN>-<slug> or by title) and propose
the row update; a done with no PR found at all is HIGH severity (the unit
may never have been closed out).
Workflow discipline (checks 10–14) — the executor skills enforce these at
write time; this audit verifies they actually held. Each check is mechanical:
run the command shown, don't infer.
- Phase naming — keyed on the carrier, like check 11.
- lane-era —
bun scripts/phase-lint.mjs <unit-doc> (owner
skills/phase-contract/SKILL.md) must print verdict PASS, and
bun scripts/ceremony.mjs docs check-phase-labels --slug <slug> must
answer valid: true. A S# hit in a lane-era doc is not a phase label:
since #308 S# is the requirement id.
- legacy carriers only —
grep -rnE '\bS[0-9]+\b|\bStep [0-9]' docs/features/*/{PLAN,TASKS,progress}.md
must return nothing: plans use P1, P2, … ("phases") only. Any hit: LOW
(rename), plus check the executor argument still resolves; a hit quoting only
the required Step 0 — Discover the project section is no phase label, and no
count is restated here — the checker's own output enumerates them.
- Per-phase doc discipline — keyed on the unit's own carrier. Pick the
carrier mechanically, never by guess:
TASKS.md in the unit folder means
legacy carriage; its absence means the unit doc's ## Tasks/## Log.
- lane-era —
bun scripts/ceremony.mjs docs check-tasks-ticks --slug <slug>
and bun scripts/ceremony.mjs docs check-progress-entry --slug <slug> must
both report valid: true: every - [x] P<n> has its P<n> line in
## Log, and no task lacks one. Cite those two fields, never check-all
(its commit-format/docs-language fields are checks 14 and 7). A doc with
no ## Tasks section answers n/a (no ## Tasks section — legacy carrier),
so the vacuous case routes to the legacy branch, never to a silent pass.
- legacy — the original assertions on that unit's own files: completed
phases ticked in
TASKS.md, one progress.md entry per completed phase,
the literal close-out tasks in the final phase.
- Severity — a ticked task with no
P<n> log line, or a log naming a task
never ticked: HIGH on a done unit (the doc claims a receipt its carrier
lacks), LOW on an open one (still settling). A done unit written before
the tick grammar (- P<n> bullets, receipts in E lines) is red on
check-progress-entry by construction — LOW, recorded, never repaired
(MIGRATION.md: a closed unit keeps the shape it was written in).
- Close-out is
audit-pr's contract (receipt + ordered gates): cite its
verdict, never re-derive the retired literal tasks here.
- Branch & PR discipline vs the forge. For every
done unit: its PR
exists, targets the default branch, has a non-empty body, and carries
Closes #<n> when the unit is issue-born (SPEC references an issue).
Also scan recent default-branch history (git log --first-parent) for
feature/fix-scoped changes committed directly without a PR: HIGH.
- Generated-docs provenance (only when the documentation map declares a
Docs site block; otherwise state n/a). Scan the declared content dir
for pages carrying the renderer's own header (Generated by scripts/docs-generate.mjs). For each page that also carries
source-unit/updated: (a) its source-unit exists in the roadmap or fix
index — no match is an orphan (low: propose deletion or
re-attribution); (b) the unit's PR merged after the page's updated
date with commits touching the page's subject paths — that page is
stale (LOW: propose bun scripts/docs-generate.mjs to re-render it).
A renderer that emits no provenance fields answers
n/a — no provenance fields, never a silent pass. Cite page path + unit
per finding.
- Commit format & dependency discipline. Sample the unit branches'
commits:
<type>(<scope>): <summary> conventional format (violations:
LOW). Every in-progress/done row's Depends on: closure was merged —
a unit built on unmerged deps is HIGH unless decisions.md records a
user-forced override (--force), which downgrades it to LOW (documented
risk).
- README currency against what shipped. Run each README against the
tree:
rg -n '<a retired name or stale claim>' README.md packages/*/README.md
and every hit that names a surface the tree no longer carries (a retired
skill in an install/uninstall example, a command count or package count the
tree contradicts, a "none yet" beside shipped subcommands) is HIGH —
the claim misleads a reader who acts on it. Its mirror: a shipped,
consumer-facing surface with no README entry at all is HIGH (the
document-or-don't-coin residue read at README scope — product-audit owns
the product-wide sweep, this check is the docs-tree half). Superseded prose
left standing beside its replacement is LOW. Owners: the rule is
AGENTS.md §Working rules, the step is skills/unit-lane/references/DOCS.md.
- Project-charter coverage (issue #435). Applies when the agent guide
declares the charter — a
## Project charter section or a documentation-map
row for the criteria catalogue; an older install that declares neither is
stated n/a (absent structure, never a finding). Mechanical, the
CAPABILITIES pattern — run the commands, never infer:
the declared map row's file exists — a row naming
docs/workflow/VERIFICATION_CRITERIA.md with no such file is HIGH
(the map points at nothing);
the charter section is present when either the section or the row is
declared — a missing ## Project charter section is HIGH (identity
answers with no tier-0 home push agents back to guessing);
no unfilled charter slot survives — a bullet whose entire value is a <…>
placeholder is the raw-template failure. The scan is bounded to the
## Project charter section, because the guide's other honest
placeholders — the Hard-rules stubs init-workspace leaves unfilled by
design — are not the charter's finding, and a guide-wide scan reports them
forever:
awk '/^## Project charter/{f=1; next} f && /^## /{f=0} f && /^- \*\*[^*]+:\*\* `?<[^>]+>`?$/ {print FILENAME":"FNR":"$0}' AGENTS.md → prints nothing
(the template's own file is the positive case — its 11 slots print with
path:line; a legal unresolved — <question> value never matches; an
identity bullet — the five the template names — is HIGH, a domain
bullet LOW);
the catalogue carries no raw placeholder cell — same scan as the
capability seed: rg -n '\| *\?<[^>]+>`? *|' docs/workflow/VERIFICATION_CRITERIA.md must print nothing, and every criterion row's provenance cell is one of the closed set (workflow-generic/project-declared/stamped assumption (dated)`) — a row naming none is LOW (it cannot
be consumed as declared);
Adapt the list to what the project has; skip checks for absent structures and
say so.
Process
Discover, then run the checks with grep, file reads, and the forge CLI
(per Workflow conventions; examples use gh).
Produce the findings report — return exactly (fixed output contract):
AUDIT DOCS — scope: <docs tree / roadmap / fix index / issues checked>
| # | Check (1-16) | Finding | Sev | Evidence | Proposed fix |
|---|-------------|---------|-----|----------|--------------|
| 1 | <which> | <what> | high|low | <path:line / #issue> | <smallest action> |
Checks run: <n>/16 (skipped: <which + why — absent structures only>)
Summary: <1-2 sentences>
Decision: PASS | FAIL (FAIL if any high-severity finding is open)
Sev: high = misleading or broken; low = cosmetic.
Only high and low are defined in this legend
Fix only on request. With explicit --fix (or user go-ahead), apply the
low-risk corrections (remove a merged fix-index row, fix a dead link, register
a missing roadmap entry, add a verified PR link to a bare done row). Leave judgment calls to the user.
Guardrails
- Read-first; never bulk-rewrite docs unprompted.
- Distinguish genuine drift from intentionally "scheduled/deferred" items —
don't report deliberate tradeoffs as errors.
- Keep changes surgical and within docs; no code or behavior changes.
Portability (agents other than Claude Code)
Preamble + no-slash-menu fallback: owned by skills/orchestration-envelope/references/PORTABILITY.md — this section
keeps only its own fallbacks:
- No per-skill
model:/effort: — no skill pins a tier; pick tiers yourself:
these are mostly mechanical cross-document checks — a mid-tier model is
enough; escalate to your strongest only for a deep audit.
Relationship to other skills
- Complements
unit-lane (which creates the docs this audits) and
triage-issue (which keeps the fix index honest).
- Run standalone anytime; no required predecessor.
Done when
A severity-ranked findings report exists, and any approved low-risk fixes are
applied — with genuine deferrals left untouched and labeled as such.
The closing → Next: block is printed:
→ Next: apply the approved low-risk fixes, then re-run /audit-docs to confirm clean
· real drift (not cosmetic) → /triage-issue · a concrete defect → /unit-lane --fix <n>
· already clean → nothing to do
1---2name: audit-docs3user-invocable: true4version: 4.10.05argument-hint: "[--fix]"6author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"7license: MIT8description: >9 Audit cross-document coherence: docs ↔ READMEs ↔ roadmap ↔ code ↔ fix index ↔ issues.10 Finds drift — features in docs/ not in the roadmap (or vice versa), fix-index11 entries already merged/closed, broken documentation-map links, dependency12 cycles, artifacts in the wrong language, naming-convention violations,13 project-charter coverage — and reports them ranked by severity, fixing only14 low-risk items on request.15 Model-agnostic: the skill inherits whatever model and effort your agent16 session is already using.17 Triggers: "check doc consistency", "are the docs in sync", "audit the docs",18 "doc coherence review", "did the docs drift", "validate the roadmap".19metadata:20 source: https://skillmd.com/skills/gtrabanco/audit-docs21---2223# Audit Docs2425A read-first audit answering "do the docs still match reality?" Produces a26findings report; it does not silently rewrite docs.2728## Turn contract2930Load and verify the **canonical** [Turn contract](../orchestration-envelope/references/TURN_CONTRACT.md) (11 boxes) before ending every turn (the `--fix` path commits and pushes like any editing turn). Skill-specific additions (the `→ Next:` box is canonical-owned and not restated here):3132```33✓ The AUDIT DOCS fixed-format report was printed, ending in `Decision: PASS | FAIL`34✓ No doc was rewritten without explicit --fix / user go-ahead35```3637Missing reference → STOP. About to end the turn with any box unchecked? The38turn is NOT done — complete the missing box first (weak models drop39end-of-document duties; this list is first on purpose).4041## When to use4243- Before a release or milestone, after merging several features/fixes, or44 whenever the doc set might have drifted from the code and issues.4546## Step 0 — Discover the project (always first)4748Per the agent guide's **Workflow conventions** + **documentation map**, then read49what THIS skill needs: the roadmap, the fix index + template, and the feature50folder layout — the map tells you which links and invariants to check.5152## Checks5354Run these and collect findings (cite paths/lines/issue numbers each):55561. **Roadmap ↔ feature folders.** Every `docs/features/<NN>-<slug>/` is in the57 roadmap, and every roadmap entry has a folder (or is explicitly "scheduled").582. **Feature dependencies.** SPEC `Depends on` / `Branch` fields are valid; no59 dependency cycles; ordering is consistent with the roadmap.603. **Fix index hygiene.** Every entry maps to an **open** issue and an unmerged61 branch; flag entries whose issue is closed or whose PR merged (should have62 been removed). Flag open fix branches missing from the index.634. **Documentation-map links resolve.** Every file the map references exists;64 flag "scheduled, not yet authored" items so they aren't mistaken for drift.655. **Broken intra-doc links.** Relative links/anchors point at real66 files/sections.676. **Issue references.** Acceptance/known-issues lines referencing `#N` aren't68 pointing at long-closed issues without note.697. **Language & naming conventions.** Artifacts in the project's docs language70 (this repo: **English**); file/dir naming matches conventions (e.g.71 kebab-case TS files, PascalCase components).728. **Invariant tags.** If the project uses invariant/decision IDs (e.g.73 INV-/D-/KI-), spot-check that referenced IDs exist where claimed.749. **PR-link integrity on `done` rows.** Every roadmap row (and fix-index75 entry) with status `done` carries a linked PR reference —76 `done · [#<pr>](<pr-url>)`. For each bare `done`, find its PR in the forge77 (`gh pr list --state all --head feat/<NN>-<slug>` or by title) and propose78 the row update; a `done` with no PR found at all is HIGH severity (the unit79 may never have been closed out).8081**Workflow discipline (checks 10–14)** — the executor skills enforce these at82write time; this audit verifies they actually held. Each check is mechanical:83run the command shown, don't infer.848510. **Phase naming — keyed on the carrier, like check 11.**86 - **lane-era** — `bun scripts/phase-lint.mjs <unit-doc>` (owner87 `skills/phase-contract/SKILL.md`) must print `verdict PASS`, and88 `bun scripts/ceremony.mjs docs check-phase-labels --slug <slug>` must89 answer `valid: true`. A `S#` hit in a lane-era doc is not a phase label:90 since #308 `S#` is the requirement id.91 - **legacy carriers only** — `grep -rnE '\bS[0-9]+\b|\bStep [0-9]' docs/features/*/{PLAN,TASKS,progress}.md`92 must return nothing: plans use `P1, P2, …` ("phases") only. Any hit: LOW93 (rename), plus check the executor argument still resolves; a hit quoting only94 the required `Step 0 — Discover the project` section is no phase label, and no95 count is restated here — the checker's own output enumerates them.9611. **Per-phase doc discipline — keyed on the unit's own carrier.** Pick the97 carrier mechanically, never by guess: `TASKS.md` in the unit folder means98 legacy carriage; its absence means the unit doc's `## Tasks`/`## Log`.99 - **lane-era** — `bun scripts/ceremony.mjs docs check-tasks-ticks --slug <slug>`100 and `bun scripts/ceremony.mjs docs check-progress-entry --slug <slug>` must101 both report `valid: true`: every `- [x] P<n>` has its `P<n>` line in102 `## Log`, and no task lacks one. Cite those two fields, never `check-all`103 (its `commit-format`/`docs-language` fields are checks 14 and 7). A doc with104 no `## Tasks` section answers `n/a` (`no ## Tasks section — legacy carrier`),105 so the vacuous case routes to the legacy branch, never to a silent pass.106 - **legacy** — the original assertions on that unit's own files: completed107 phases ticked in `TASKS.md`, one `progress.md` entry per completed phase,108 the literal close-out tasks in the final phase.109 - **Severity** — a ticked task with no `P<n>` log line, or a log naming a task110 never ticked: HIGH on a `done` unit (the doc claims a receipt its carrier111 lacks), LOW on an open one (still settling). A `done` unit written before112 the tick grammar (`- P<n>` bullets, receipts in `E` lines) is red on113 `check-progress-entry` by construction — LOW, recorded, **never repaired**114 (`MIGRATION.md`: a closed unit keeps the shape it was written in).115 - **Close-out** is `audit-pr`'s contract (receipt + ordered gates): cite its116 verdict, never re-derive the retired literal tasks here.11712. **Branch & PR discipline vs the forge.** For every `done` unit: its PR118 exists, targets the default branch, has a non-empty body, and carries119 `Closes #<n>` when the unit is issue-born (SPEC references an issue).120 Also scan recent default-branch history (`git log --first-parent`) for121 feature/fix-scoped changes committed directly without a PR: HIGH.12213. **Generated-docs provenance (only when the documentation map declares a123 `Docs site` block; otherwise state n/a).** Scan the declared content dir124 for pages carrying the renderer's own header (`Generated by125 scripts/docs-generate.mjs`). For each page that also carries126 `source-unit`/`updated`: (a) its `source-unit` exists in the roadmap or fix127 index — no match is an **orphan** (low: propose deletion or128 re-attribution); (b) the unit's PR merged **after** the page's `updated`129 date with commits touching the page's subject paths — that page is130 **stale** (LOW: propose `bun scripts/docs-generate.mjs` to re-render it).131 A renderer that emits no provenance fields answers132 `n/a — no provenance fields`, never a silent pass. Cite page path + unit133 per finding.13414. **Commit format & dependency discipline.** Sample the unit branches'135 commits: `<type>(<scope>): <summary>` conventional format (violations:136 LOW). Every `in-progress`/`done` row's `Depends on:` closure was merged —137 a unit built on unmerged deps is HIGH unless `decisions.md` records a138 user-forced override (`--force`), which downgrades it to LOW (documented139 risk).14015. **README currency against what shipped.** Run each README against the141 tree: `rg -n '<a retired name or stale claim>' README.md packages/*/README.md`142 and every hit that names a surface the tree no longer carries (a retired143 skill in an install/uninstall example, a command count or package count the144 tree contradicts, a "none yet" beside shipped subcommands) is **HIGH** —145 the claim misleads a reader who acts on it. Its mirror: a shipped,146 consumer-facing surface with no README entry at all is **HIGH** (the147 document-or-don't-coin residue read at README scope — `product-audit` owns148 the product-wide sweep, this check is the docs-tree half). Superseded prose149 left standing beside its replacement is **LOW**. Owners: the rule is150 `AGENTS.md` §Working rules, the step is `skills/unit-lane/references/DOCS.md`.15116. **Project-charter coverage (issue #435).** Applies when the agent guide152 declares the charter — a `## Project charter` section or a documentation-map153 row for the criteria catalogue; an older install that declares neither is154 stated `n/a` (absent structure, never a finding). Mechanical, the155 CAPABILITIES pattern — run the commands, never infer:156 - the declared map row's file exists — a row naming157 `docs/workflow/VERIFICATION_CRITERIA.md` with no such file is **HIGH**158 (the map points at nothing);159 - the charter section is present when either the section or the row is160 declared — a missing `## Project charter` section is **HIGH** (identity161 answers with no tier-0 home push agents back to guessing);162 - no unfilled charter slot survives — a bullet whose entire value is a `<…>`163 placeholder is the raw-template failure. The scan is **bounded to the164 `## Project charter` section**, because the guide's other honest165 placeholders — the Hard-rules stubs `init-workspace` leaves unfilled by166 design — are not the charter's finding, and a guide-wide scan reports them167 forever:168169 ```text170 awk '/^## Project charter/{f=1; next} f && /^## /{f=0} f && /^- \*\*[^*]+:\*\* `?<[^>]+>`?$/ {print FILENAME":"FNR":"$0}' AGENTS.md → prints nothing171 ```172173 (the template's own file is the positive case — its 11 slots print with174 `path:line`; a legal `unresolved — <question>` value never matches; an175 identity bullet — the five the template names — is **HIGH**, a domain176 bullet **LOW**);177 - the catalogue carries no raw placeholder cell — same scan as the178 capability seed: `rg -n '\| *\`?<[^>]+>\`? *\|' docs/workflow/VERIFICATION_CRITERIA.md`179 must print nothing, and every criterion row's provenance cell is one of180 the closed set (`workflow-generic` / `project-declared` /181 `stamped assumption (dated)`) — a row naming none is **LOW** (it cannot182 be consumed as declared);183184Adapt the list to what the project has; skip checks for absent structures and185say so.186187## Process1881891. Discover, then run the checks with `grep`, file reads, and the forge CLI190 (per Workflow conventions; examples use `gh`).1912. Produce the findings report — **return exactly** (fixed output contract):192193 ```194 AUDIT DOCS — scope: <docs tree / roadmap / fix index / issues checked>195196 | # | Check (1-16) | Finding | Sev | Evidence | Proposed fix |197 |---|-------------|---------|-----|----------|--------------|198 | 1 | <which> | <what> | high|low | <path:line / #issue> | <smallest action> |199200 Checks run: <n>/16 (skipped: <which + why — absent structures only>)201 Summary: <1-2 sentences>202 Decision: PASS | FAIL (FAIL if any high-severity finding is open)203 ```204205 Sev: **high** = misleading or broken; **low** = cosmetic.206 Only `high` and `low` are defined in this legend2073. **Fix only on request.** With explicit `--fix` (or user go-ahead), apply the208 low-risk corrections (remove a merged fix-index row, fix a dead link, register209 a missing roadmap entry, add a verified PR link to a bare `done` row). Leave judgment calls to the user.210211## Guardrails212213- Read-first; never bulk-rewrite docs unprompted.214- Distinguish genuine drift from intentionally "scheduled/deferred" items —215 don't report deliberate tradeoffs as errors.216- Keep changes surgical and within docs; no code or behavior changes.217218## Portability (agents other than Claude Code)219220Preamble + no-slash-menu fallback: owned by `skills/orchestration-envelope/references/PORTABILITY.md` — this section221keeps only its own fallbacks:222- **No per-skill `model:`/`effort:`** — no skill pins a tier; pick tiers yourself:223 these are mostly mechanical cross-document checks — a mid-tier model is224 enough; escalate to your strongest only for a deep audit.225226## Relationship to other skills227228- Complements `unit-lane` (which *creates* the docs this audits) and229 `triage-issue` (which keeps the fix index honest).230- Run standalone anytime; no required predecessor.231232## Done when233234- A severity-ranked findings report exists, and any approved low-risk fixes are235 applied — with genuine deferrals left untouched and labeled as such.236- **The closing `→ Next:` block is printed:**237238 ```239 → Next: apply the approved low-risk fixes, then re-run /audit-docs to confirm clean240 · real drift (not cosmetic) → /triage-issue · a concrete defect → /unit-lane --fix <n>241 · already clean → nothing to do242 ```