Parallel Audit Skill

SkillFiles & storage

Runs a broad, multi-dimension codebase audit by fanning out parallel read-only subagents (one per dimension x file-area), independently confirms their findings, then groups the survivors into one fix plan with partitioned commits, on as few PRs as the footprint bound allows, and self-critiques it before delivery. Activate when the user asks to "find dozens of issues", "audit the codebase", "find security/ robustness/testing/UX deficiencies", "use subagents to audit and confirm", "find bugs and missed opportunities", or "make a plan to fix all of these". Distinct from peer-review (which reviews a pending diff) and security-review (single-pass, current branch): this audits the WHOLE codebase along several axes at once and ends in a vetted fix plan, not edits.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Parallel Audit Skill skill

What this skill tells your AI

The instructions your AI receives, as published by alexandermattturner/agent-glovebox in .claude/skills/parallel-audit/SKILL.md and read by ahel’s review.

The "fan out, confirm, plan, critique" pattern for a wide audit of an existing codebase along multiple quality axes (security, robustness, real-vs-stubbed test coverage, UX, missed opportunities). Output is an audit report + a fix plan on as few PRs as the footprint bound allows, with partitioned commits, + a critique of that plan — no code changes beyond scaffolding the user explicitly asks for.

Hunt ELIMINATORS, not spot fixes

A finding earns its place by naming the property that was violated and the change that closes it. One wrong line patched in place is worth almost nothing at audit scale when it belongs to a class: the same property is violated at the helper's other callers, at the enumeration's other members, and in the next file added to that directory. So each finding carries the property and the change that closes it — the structural change that closes every site at once when a class exists (an SSOT the duplicates collapse into, a type with no invalid arm, one seam every caller must cross, a value the caller passes instead of re-deriving), else a plain FIX that says why this site is genuinely the only one. Prefer the fix that deletes the second implementation over the fix that corrects it.

Four shapes to hunt by name, because a per-dimension prompt finds none of them on its own:

  • Fix-sinks — one rule with N implementations, where each bug gets patched into whichever copy the symptom pointed at. The tell is a comment in one copy explaining how it differs from another.
  • A shipped defense that does not run — a registered leg nothing dispatches, a gate that returns before its enforcement, a matcher the tests import and the runtime does not. Grep for the runtime importer, never for the definition.
  • A published number that is not a measurement — a rate rendered without the denominator it was computed over, an ungraded sample counted as a zero, a count reconstructed by rounding a float.
  • UX antipatterns — a degrade path that withholds the whole output rather than a flawed part of it, an error that names no remedy, a guard that refuses without saying which input to change.
  • A defense that fails open, or covers only part of the set it names — an error arm that allows where the header says it denies, a timeout whose fallback is the permissive verdict, a deny list that refuses two members of a class its own rationale covers entirely. Enumerate the class from its SSOT, then check each member against the defense; the tell is a rule naming one instance of a class in a file that has no rule for the instance beside it. (Worked example: user-config/settings.json denied GLOVEBOX_DANGEROUSLY_SKIP_MONITOR while seven sibling launch-weakeners — the firewall skip, the allowlist repoint, both cosign trust anchors — had no rule at all.)

When to use

  • Breadth ("dozens", "be creative", "across the whole thing"), not a review of one diff, and the deliverable is a plan rather than immediate edits.
  • Not this: a pending diff before a PR → peer-review/code-review; a single-pass look at the current branch → security-review; a trivial single-file question → just read the file.
  • A security finding this audit confirms as exploitable leaves through the vuln-research skill, not through the fix plan. That skill owns reproduce-before-report, scoring against SECURITY.md's stated threat model, and the rule that a human sees a finding before anyone outside does.

Workflow

1. Map the territory (main session, fast)

Get a lay of the land so agent scopes are disjoint: directory tree, file-type counts, key subsystems. Read the last 500 non-merge commits by path and subject; flag a subsystem when corrective commits repeatedly repair one property, and give that history to its agent. List the open PRs with gh pr list --json number,title,headRefName,files, which answers number, title, head branch and changed paths in one call. Hand each agent the number and title of every open PR whose changed paths overlap its file list. Prior audit and fix branches are prior art, and an audit that ignores them re-finds what they already fix. Step 5 fetches only the heads it must diff, with git fetch origin refs/pull/<N>/head. Skim CLAUDE.md/CONTRIBUTING.md/SECURITY.md — their stated invariants ("fail closed", "post-condition not exit code", "host code runs on BSD too") become the lenses you hand each agent. An audit that checks the project's doctrine and corrective history finds fix-sinks; a generic audit re-discovers lint.

2. Fan out — one agent per (dimension x area), all in ONE message

Pick axes from the request (typical: security, robustness/error-handling, e2e-test realness, UX/DX, supply-chain, config-SSOT/CI). Give each general-purpose agent a non-overlapping file list and launch them concurrently (multiple Agent calls in one response). They are read-only — forbid edits; every path is theirs to audit, and you make the edits yourself in step 7 — never a sub-agent, and never a human.

Each agent prompt MUST demand, per finding: TITLE · FILE:LINE (exact) · SEVERITY · EVIDENCE (quote 1-5 real lines) · WHY IT'S A DEFECT (a concrete failure: specific input → wrong/leaked outcome) · PROPERTY VIOLATED (one sentence, in words a sibling subsystem would search for) · OTHER SITES (every present and future place that can violate it — the helper's other callers, the enumeration's other members) · HISTORY (the corrective commits that repaired this property, or "first occurrence") · STATE OWNER (the one component that should decide it) · ELIMINATOR or FIX (the structural change that closes the whole class, else a plain FIX for a defect that is genuinely single-site). And MUST instruct:

  • Ground every finding in real lines read — never speculate. Skip anything you can't quote.
  • An ELIMINATOR that reads "fix this line" is unfinished only when a class exists. Name the class it belongs to and the change that closes it, or state in one line why this site is genuinely the only one — then it is a FIX, finished as it stands. Do not dress a single-site fix as a class eliminator.
  • Mark a finding an open PR plausibly already fixes LIKELY COVERED BY #N — report it, never silently skip it; step 5 settles whether the PR's diff really covers it.
  • Self-flag non-findings: state what you checked and found correct. An honest self-flagger earns lighter scrutiny in step 4.
  • Rank by severity; aim for a target count (e.g. 6-12) so they prioritize over dumping noise.

3. Survive the rate limit — resume, don't restart

A big fan-out often trips a transient rate limit; an agent returns 0 tokens after having already done real reading. Resume it with SendMessage to its agentId ("continue where you left off and emit your final findings") to reuse its accumulated context instead of paying for the reads again. Fully restart only an agent that died before doing any work (≈≤3 tool calls).

4. Confirm — independently, at least the high-severity items

Do not rubber-stamp. For every high/critical finding (and a sample of the rest), open the cited file at the cited lines yourself and check the claim holds. Watch for: off-by-a-few line numbers, a comment that already addresses the concern, a guard one function up the agent missed, severity inflation. Drop or downgrade anything that doesn't survive your read; record "confirmed by independent read" per kept finding. For very large audits this pass can itself be a second fan-out of code-reviewer agents, each adversarially trying to refute one finding — keep the survivors.

5. Dedupe and cluster into partitioned commits (as few PRs as the footprint bound allows)

Merge duplicates across agents (the same bug often surfaces from two lenses). Then settle each LIKELY COVERED BY #N flag against that PR's actual diff (git fetch origin refs/pull/<N>/head first): a finding the diff fixes enters the report as covered by #N. Its fix-plan entry takes that diff at execution time with git diff $(git merge-base <sha> HEAD) <sha> -- <paths> | git apply -3 instead of re-deriving the fix. A flag the diff does NOT fix, or whose PR you could not read, goes back into the survivor pool as an ordinary finding — never dropped. Group survivors into as few PRs as the footprint bound allows, each PR's commits partitioning the work by concern — one commit per subsystem (firewall, monitor, redaction, lifecycle, …), bundling that subsystem's findings. Write no ## Partitions section — git log answers it, and root CLAUDE.md bans the heading; the lead says in one sentence what else the diff moves. Within one branch, file-overlap between partitions is not a landing constraint; order the commits so any real dependency (e.g. an SSOT change others build on) comes first. A broad audit is the canonical branch that passes the bound, so plan for more than one PR. For each partition: scope, the findings it closes, the test that would have caught the class (assert the invariant, not today's symptom), and a rough size. Carve a finding out into its own PR when the consolidated branch would pass the pr-creation skill's footprint bound, when it must land or iterate on its own timeline, or when the consolidated diff would be too large to review coherently — then sequence any such extra PRs in waves of ≤6, per step 7 below. Extra PRs that depend on each other chain instead, wired by hand per the pr-creation skill and never as a native GitHub stack; the wave bound governs independent PRs only.

6. Critique the plan, then deliver

Attack it first, starting with the eliminator test: for each partition, does the fix make the class unrepresentable, or does it correct the one site that failed? Where it corrects one site, either widen it or say in the delivered plan which sites stay reachable — a per-site fix stands only when it says so. Then: is any partition carved into its own PR actually justified (footprint bound / own timeline / too-big-to-review), or should it fold back into the consolidated PR? Is a "high" really reachable, or gated behind an opt-in/off-by-default flag (lower it)? Does any fix need a design decision (flag it in the delivered plan with a recommended default — never stop mid-audit to ask)? Any findings with no good test? Are the partition boundaries clean, or does one commit sprawl across unrelated concerns? Deliver the plan with this critique attached. Plan delivery is the ONE moment to batch every open question; concentrate them there.

7. Executing the plan (when asked)

The whole plan is in scope — implement every partition without checkpointing, keeping each branch under the footprint bound and opening a second PR when a branch would pass it; never ask "should I move on to the next partition?" (the answer is always yes). Any question belongs in the batch delivered with the plan (step 6), before the first commit. A design choice that surfaces only mid-implementation gets a sensible default and a ## Decisions made entry in the PR description (what came up, the default chosen, what would change under the alternative). Maintain a partition checklist and tick each off as its commit lands. Open each PR once (per the pr-creation skill) and drive its CI green.

If the critique (step 6) justified splitting a few findings into their own PRs, sequence those extra PRs in waves of ≤6 in flight at once — never dispatch them all simultaneously. Every PR fires the full workflow fan-out on one shared, account-wide runner pool, so floating a dozen at once makes each PR's required checks queue behind the others' long jobs. This caps only in-flight independent PRs — dependent splits ride one hand-wired chain of PRs outside the bound — and keep saturating sub-agents to PREPARE the work; just hold the number running CI concurrently to ≤6.

Re-tighten the bound on evidence, not on feel. The signal is a required check that sits queued for many minutes behind another PR's long job — the KVM legs and the cross-platform shards are the ones that hold a slot. When you see that on a wave you launched, say so in chat with the PR numbers and the observed queue time, run the next wave smaller, and propose lowering the number here — an observation that only lands in chat dies with the session and never tightens the bound.

Signals

GitHub stars
63
Forks
11
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
parallel-audit
Source
github.com/alexandermattturner/agent-glovebox