--- name: doctrine-audit description: Use when the user asks for a bug hunt or deep code audit of the codebase done with the doctrine: finding drift, feature gaps, logic issues, over-engineering, and bugs with parallel finder waves, red-teaming, and looping until dry. --- # Doctrine Audit Codebase audit under the doctrine: find real issues, verify them, fix the confirmed ones. **REQUIRED BACKGROUND:** Read the `doctrine` skill first. Designated review skill for fix phases: `matts-code-review`. **Pin its fixed point yourself — the SHA that fix phase started from** (`git rev-parse HEAD` before the phase's first edit), never `main` or the merge-base: with no fixed point it stops and asks the user, twice a phase, every phase; with a branch ref it re-reviews every fix phase already closed and re-files their findings, which doctrine step 5 counts as outstanding against the pass you are in, so no pass can ever come clean. Give it a **spec source** too — the confirmed-list entries this phase is fixing (step 3's file), or the tracker issues you filed for them — or its Spec sub-agent skips with "no spec available" and the gate's designated review runs one axis of two. Issue references resolve only where Matt's `docs/agents/issue-tracker.md` exists; without it, pass the path. ## Flow 1. Ask the user the scope questions their request didn't already answer: target area, fix-as-we-go vs report-first, and the severity/effort line above which issues get filed instead of fixed. **Report-first and read-only are two questions, so ask both**: report-first says don't fix, read-only says don't write — and a user who said "report only, don't touch the repo" gets a report file committed into the repo if you conflate them. Where the answer is read-only, or you have no write authority there, build the report in the scratchpad per doctrine step 7 and hand it over; read-only means the working tree too. **Write every answer down** (doctrine step 1) in the same file the confirmed list goes in (step 3), before wave 1 — **and put the rulings that bind a seat's conduct (report-first, read-only, scope) in every finder, fixer and reviewer prompt**: the hub hands the anchor to judging seats only, a finder is not one, and a lens never told the tree is read-only produces the diff the user forbade with no gate downstream that inspects authorization. 2. **Find**: parallel finder waves, each with a distinct lens: simplicity (over-engineering, dead code: apply /ponytail-audit's posture if installed, scoped to the target area, not the whole repo — **resolved by you into the lens prompt**: a dispatched lens cannot load a skill by name, so it gets the posture's content or, absent ponytail, the hub table's report-only substitute, whose changes-nothing clause must reach the one seat that could mutate), logic/correctness, drift (docs/config vs code), feature gaps, security-sensitive paths. Every finding needs file:line evidence. Dedupe across waves. 3. **Verify**: every finding is confirmed from source before it counts. Hunt-style findings have a high false-positive rate; a finding nobody traced to a line is noise. PLAUSIBLE-only items don't get fixed; they go to the report's appendix (or a tracker issue marked unverified). **Write the confirmed list to a file as you verify** — the report's own path where step 1 settled one, else a run-state file beside the work or in the scratchpad, named in the report. One line per issue: an id, `file:line`, severity, the evidence that confirmed it, and its state (confirmed / red-teamed / fixed / filed / declined). Steps 4, 5 and 6 all consume this list and nothing else produces it. **A separate orchestrator-only file beside it carries the counters** (doctrine step 5: the list is the deliverable or the spec handed by path, so nothing orchestrator-only goes in it) — the dry-round count this wrapper runs, plus whatever doctrine step 5 puts in that section for whichever fix phase is open — because a long audit compacts between rounds, and a list and a count that lived only in context come back empty: round 3's finders then re-file everything round 1 already fixed, and the dry count silently restarts at zero with nothing announcing it. 4. **Red team**: hand the confirmed list to the red team (doctrine step 4) to refute and to extend. Verify anything it adds. 5. **Fix — in fix-as-we-go mode only. In report-first mode nothing in this step edits the repo and step 6 opens no fix phase — the run answers the question and changes no code — but this step's filing rule below still runs, because filing is a tracker write and not a fix. Where the tracker named lives inside the repo, filing there is a repo write and step 1's read-only ruling governs it: forbidden, those items go in the report as unfiled, said plainly.** Editing anyway delivers a report of fixes nobody authorised, and every other guard here misses it — the hub's audit-lens substitute for ponytail covers only the finder lens, not this step. In fix-as-we-go: confirmed issues in phases, highest severity first, each phase under the doctrine gate (step 5's exit condition for that phase). Use Matt Pocock's `diagnosing-bugs` for anything with a non-obvious root cause. File the rest on the project's tracker (whatever its AGENTS.md or CLAUDE.md names) rather than letting them rot in a report — "the rest" being everything above step 1's severity/effort line, and in report-first mode everything confirmed. **Where there is no tracker to file on** — its AGENTS.md and CLAUDE.md name none, `gh` or the tracker CLI isn't authenticated, or the user hasn't said where issues go — check the project's conventions and ask if none exist, exactly as step 7 does for the report; failing that, carry the full list in the report and **say plainly that nothing was filed**. Never invent an issue number, and never drop a finding because it had nowhere to go. 6. **Loop until dry**: repeat find→verify with fresh lenses until two consecutive rounds surface **no new confirmed issue** (post-verification). "Nothing new" is the right test *here and only here* — this is the outer loop doctrine step 5 names by hand and blesses; outstanding findings live inside the fix phases below, which carry doctrine step 5's gate as written, where "no *new* findings" is forbidden. New round findings start new fix phases in fix-as-we-go mode, and new report entries in report-first; they don't reopen closed ones. If you run out of meaningful lenses before two dry rounds, say so and stop; don't invent junk lenses to satisfy the counter. 7. Deliver per doctrine step 7. Report-first mode: write the report where the project keeps them (check its conventions; ask if none exist) — **or, where step 1 established you may not write to the repo, in the scratchpad, handed over rather than committed.** Deliver the report, the confirmed list and anything filed together, and name what was left unfiled. **In report-first mode the report is the deliverable and carries the hub's gate**: one phase, under the hub's prose-deliverable exit adopted here by name (the report is prose, and fix phases keep doctrine step 5's gate as written), counters in step 3's orchestrator-only file; the designated-review slot is a fresh-context review of the finished report against the anchor and the confirmed list (`matts-code-review` reads a diff and report-first produces none, which is why the line above designates it for fix phases only); step 4's red team is handed the finished report as well as the list; and native checks take the hub's docs-only form — every claim in the report re-verified against source, plus a path check. Bigger architectural refactors surfaced along the way go through Matt Pocock's `improve-codebase-architecture` (read its SKILL.md from your host's skill directory, which the hub's host reference names, if installed; otherwise file them as tracker issues), not ad-hoc rewrites mid-audit. ## Red flags - The user said report-first and the repo has a diff beyond the report and what was filed. - A report file written into a repo the user told you not to touch. - The confirmed list living only in context: round 3 re-files what round 1 fixed, and every round looks productive. - The dry-round count restarted by a compaction, so "two dry rounds" was one. - An issue number in the report that was never filed anywhere. - A finding dropped because the project named no tracker. - A PLAUSIBLE item fixed as though it were confirmed — hunt findings have a high false-positive rate and a fix is a change to working code. - Lenses invented to reach two dry rounds. - `matts-code-review` pointed at `main`, re-filing findings from fix phases that already closed.