Security Fleet
Autonomous security backlog sweep — enumerate risk-ranked code areas plus the resolved dependency tree, discard every candidate that cannot produce concrete evidence, confirm one ranked batch with the human in a single up-front round, then route each survivor by a bounded-fix test: a safe bounded fix is built through the real pipeline into an independently verified PR, while a risky or structural finding is filed with its evidence packet instead of force-fixed. The fleet never auto-merges, never closes a finding by suppression, and never reports a secret's value.
A security backlog is the worst kind of attention slog. The signal is loud — a mechanical scanner emits dozens of findings, a dependency audit emits dozens more, a judgment-based critique emits dozens beyond that — and most of it is noise. Someone has to decide, per finding, whether the flagged sink is actually reachable, whether the advisory's affected code path is actually imported, whether the trust-boundary concern is real or theoretical; then, for the survivors, whether this is a two-line fix or an auth-model redesign. The scanners are fast; the human triage in the middle is the bottleneck, and it is the step most often skipped — which is how a repo ends up with "40 vulnerabilities" on its default branch that nobody has read. security-fleet is a quality-queue member of the -fleet family, sweeping the security backlog of the standing codebase alongside the core conveyor (intake → decide → build → land). Two things make it a distinct member rather than a re-skin of a build-stage fleet. It is evidence-gated: a candidate enters the batch only when it carries a named evidence class, and one that carries none is discarded rather than reported at low confidence. And its terminal act is tiered: not every real finding should become a PR, because a sweep that quietly redesigns an auth model is more dangerous than the vulnerability it was closing. The shared, stage-agnostic scaffolding it builds on is documented in the -fleet family spine reference (docs/reference/fleet-family.md).
When to Use
- A noisy security backlog — scanner findings, audit findings, and critique findings together — needs autonomous triage plus one bulk review instead of per-finding babysitting
- Clearing accumulated security debt where reading, reproducing, and routing each finding by hand does not scale
- Turning a code scan plus a dependency audit into a small batch of evidence-backed outcomes — reviewable fix PRs and filed structural findings — in a single session
- When the findings are largely independent — each one's remedy lands on its own and does not require another finding's fix first
- NOT for auditing a single file or one dependency on request — invoke
harness-security-scanorharness-supply-chain-auditdirectly; a fleet's overhead only pays off across a backlog - NOT for general correctness bugs — the boundary against the build pipeline is by domain; a non-security defect found incidentally is parked and handed off, never fixed inside the security sweep
- NOT for exploit development, live-system probing, or penetration testing — analysis is static plus advisory-based over the standing codebase, and producing a working exploit is explicitly out of scope
- NOT for reporting speculative "hardening opportunities" — a candidate with no evidence class is discarded, because a sweep that emits maybes is the problem it exists to solve
- NOT for converging one module's security posture to done through repeated rounds — that is a pipeline (it loops on one target), not a fleet (which fans out across many independent findings into many outcomes)
Flags
| Flag | Effect |
|---|---|
--concurrency |
Cap concurrent fix subagents (default 2, max recommended 3 — the machine-storm cap) |
--report-only |
Enumerate, gate on evidence, tier, and present the ranked finding batch; do not dispatch fix subagents or file issues |
--dry-run |
Run SELECT and CONFIRM only; stop before fan-out |
Process
Iron Law
A finding enters the batch only when it carries a named evidence class, and a fix PR is "merge-ready" only after independent confirmation that the branch carries the real pipeline's artifact, that the original evidence no longer reproduces, that the branch introduces no new security finding, and that CI is green across all OS. The fleet never auto-merges, never closes a finding by suppression, and never accepts a subagent's self-report as proof.
Security tooling's failure mode is not missing findings — it is volume. A scanner that emits sixty maybes and three real problems has not helped anyone; a human who learns the queue contains maybes stops reading the queue. So the gate has to be a mechanism, not a hope: named evidence classes, applied before an item ever costs a human a second of attention, with the discards counted so the gate itself stays auditable. The same logic runs the other way at the end. "The scanner is quiet now" is not proof a vulnerability is closed — a suppression makes a scanner quiet, and so does deleting the test that reached the sink. The only proof is that the original evidence no longer reproduces: the sink is unreachable, the advisory is clear, the boundary control is present. Everything between those two gates is machinery.
Phase 1: SELECT --> Phase 2: CONFIRM --> Phase 3: DISPATCH
|
v
Phase 5: REPORT <-- Phase 4: VERIFY
| Phase | Purpose | Exit Condition |
|---|---|---|
| 1. SELECT | Enumerate both halves of the queue, apply the evidence gate, cross-check, tier | Ranked SecurityFinding[] with evidence classes, tiers, cross-check verdicts, forks, and a discard count |
| 2. CONFIRM | One up-front human round: approve/trim, re-tier, answer forks, set concurrency | Human-approved batch with answered forks, confirmed tiers, agreed concurrency |
| 3. DISPATCH | FIX-tier worktree fan-out through the real pipeline; FILE-tier evidence packets | Every confirmed item returned a branch, an evidence packet, parked, re-tiered, or dropped as a false positive (all recorded) |
| 4. VERIFY | Independent artifact + evidence-cleared + no-new-finding + all-OS-CI check | Each item marked with its tier-appropriate verdict (verified / filed-and-verified / rejected / retry / parked) |
| 5. REPORT | One-row-per-item batch summary with the discard count; never merge | Report delivered with the aggregate discard count; nothing merged |
The five-phase spine, the concurrency governor, the artifact + all-OS-CI verification discipline, the worktree fan-out with its push-path caveat, and the never-silent-merge invariant are the family-shared scaffolding — stated once in docs/reference/fleet-family.md. This skill states only what is specific to the security stage: the evidence-gated two-sourced queue, the tiered terminal act, the security-shaped verification (evidence cleared plus no new finding, not just an artifact), and the secret-handling rule no other member needs.
Phase 1: SELECT — Enumerate Both Halves, Gate on Evidence, Cross-Check, Tier, Score
Enumerate from both halves of the security surface. The queue is two-sourced and merged into one ranked list. On the code side, compose
harness-security-scan(mechanical detection) withsecurity-craft(LLM-judgment trust-boundary and least-authority critique) over the areas the graph ranks as highest-exposure — entry points, trust boundaries, critical paths — withharness-security-reviewsupplying the OWASP/CWE finding taxonomy so findings are named in a vocabulary a reviewer already reads. On the supply-chain side, composeharness-supply-chain-audit's 6-factor dependency risk evaluation with advisory matching over the resolved dependency tree (the lockfile's actual versions, not the manifest's ranges). A project with no lockfile, a missing scanner, or an unavailable advisory source degrades to the remaining half and is recorded — a half queue is never presented as a complete one.Apply the evidence gate — a hard filter, not a confidence score. Assign each candidate exactly one of four named evidence classes, or discard it:
reachable-sink— an untrusted source reaches a dangerous sink along a path that actually exists in the code. "This function looks dangerous" is not a reachable sink; the path is the evidence.exploitable-path— a trust boundary is crossed without the control that boundary requires, with the crossing named concretely: which entry point, which missing control. "Exploitable" here means the path is demonstrated in the code — building a working exploit is an explicit non-goal.advisory-match— a resolved dependency version falls inside an advisory's affected range. The range match is the class: a resolved version inside a published affected range is a concrete fact, not a guess. Reachability is a strength modifier, not a second gate — recordevidenceStrengthasreached(the vulnerable API surface is actually called from this codebase) orlockfile-only(present in the resolved tree, no call path found). Strength feeds the score and the tier; alockfile-onlymatch ranks below areachedone and is never inflated to look reached.exposed-credential— a live-shaped secret literal is present in tracked source, evidenced by file, line, and credential type. The value itself is never recorded, quoted, or transported (see the secret rule in DISPATCH). A placeholder, an obvious test fixture, or a documented example value is not a live-shaped secret.
A candidate with no class is discarded — not downgraded, not carried into CONFIRM as an FYI, not reported at low confidence. Keep an aggregate discard count and report it, so the gate itself stays auditable and a reviewer can see how much noise it absorbed.
Cross-check every survivor against what is already resolved or in flight. Check each finding against already-fixed or superseded state on the default branch (an advisory already remediated there), against in-flight security PRs, and against existing open security issues. A duplicate is flagged for closure or dropped, never re-filed — duplicate security issues are actively corrosive to a triage queue, because they make the queue look larger than the risk.
Tier each survivor by the bounded-fix test. FIX = the remedy is safe, bounded, and mechanically verifiable: a dependency bump within a compatible range, an input-validation or output-encoding patch at identified call sites, removal of a hardcoded credential from source. FILE = the remedy is risky or structural: an authentication/authorization model change, a trust-boundary redesign, a cryptographic scheme replacement, or any remedy whose blast radius crosses module boundaries or changes a security contract. The tier is decided here and confirmed in CONFIRM — it is never chosen mid-flight, because a tier chosen while already editing code is a tier chosen by sunk cost.
Route each FIX-tier survivor by item type (§Item-type routing in
docs/reference/fleet-family.md, ADR 0103), so a bounded vulnerability is diagnosed by the skill built for it rather than forced through the design-first pipeline. The bounded-fix test that made it FIX already means the structural, design-requiring remedies are FILE, not FIX — so a FIX-tier item isroute = bugwhen it has a known, mechanically-verifiable remedy (a dependency bump, a validation/encoding patch at identified sinks, a credential removal — the common case), androute = featureonly when the fix is bounded yet still carries a genuine design decision a builder would otherwise guess. FILE-tier items open no branch and are not routed. RecordrouteSignal(which signal chose the route).Score and order by severity × evidence strength × exposure. Do not rank ad-hoc, and do not rank by scanner severity alone. Reuse
harness-roadmap-pilot-style impact scoring with the graph supplying the exposure term. The worked comparison that makes this concrete: a high-severity advisory on an unreached dev-only dependency ranks below a moderate reachable injection sink at a public entry point — because severity describes the weakness in the abstract, while evidence strength and exposure describe what it means here.Build the
SecurityFindingrecord for each survivor, and detect known decision forks without answering them:SecurityFinding { id, // stable finding id title, source, // "code-scan" | "craft-critique" | "supply-chain" | "advisory" evidenceClass, // "reachable-sink" | "exploitable-path" | "advisory-match" | "exposed-credential" evidence, // the concrete trace: sink path, boundary crossing, advisory id + range, or file/line/credential-type evidenceStrength, // "reached" | "lockfile-only" — advisory-match only; feeds score and tier severity, cweOrAdvisory, // taxonomy reference exposure, // graph-derived exposure weight score, // severity x evidence strength x exposure tier, // "fix" | "file" route, // FIX tier only: "bug" | "feature" (item-type routing, §fleet-family / ADR 0103) routeSignal, // which signal chose the route crossCheck, // "novel" | "already-fixed" | "duplicate-issue" | "in-progress-elsewhere" locations, forks, // detected known decision forks, surfaced in CONFIRM (may be empty) // populated after DISPATCH: branch, regressionTest, evidenceCleared, assumptions, parkedForks, reTieredTo, }
Phase 2: CONFIRM — The Single Up-Front Human Gate [checkpoint:human-verify]
Present the ranked finding batch in one round. This is the only guaranteed human touchpoint before review — everything downstream runs autonomously. Present, together, in a single surface:
- The ranked findings (highest score first), each with its evidence class, its concrete evidence trace, its score, its proposed tier, and — for FIX-tier findings — the routed fix pipeline (
bug→harness-debugging,feature→harness-brainstorming→harness-autopilot), presented as an overridable decision alongside the tier. Re-routing a FIX item is recorded like the re-tier below and fed into its DISPATCH brief. - The aggregate evidence-gate discard count — how many candidates the gate absorbed and why in summary. The reader needs to see the noise that did not reach them; that is what makes the short list credible.
- Duplicates and already-remediated findings flagged for drop or closure, each with the citation (the resolving PR, the existing issue) — never re-filed.
- Every detected known decision fork as a multiple-choice question with a recommended default (e.g. "the version that clears this advisory is outside the compatible range — accept a major bump as a bounded fix, or file it as structural?").
- The proposed concurrency (default 2, capped at ~3).
- The ranked findings (highest score first), each with its evidence class, its concrete evidence trace, its score, its proposed tier, and — for FIX-tier findings — the routed fix pipeline (
The human approves or trims once, and may re-tier. Batch approval, fork answering, drop confirmation, and tier confirmation all happen in this same gate. The human may re-tier any item in either direction — FIX → FILE when a proposed fix looks riskier than it reads, or FILE → FIX when a structural-looking finding is bounded in this codebase. Answered forks are recorded and fed into each item's DISPATCH brief so no subagent re-asks a settled question.
From here it is autonomous. After this gate the fleet does not pause per-finding. The only things that re-surface before REPORT are a genuinely unforeseen fork and a mid-flight re-tier — each of which parks a single item without blocking the batch (see DISPATCH). Under
--dry-runthe skill stops at the end of this phase; under--report-onlyit presents the gated, tiered, ranked batch and dispatches nothing.Degraded terminal act is named here, not discovered later. If
ghis unauthenticated the fleet still runs SELECT and CONFIRM in full: it opens no PRs and files no issues, and it reports the ranked queue with the blocked terminal act named explicitly. A queue delivered without its terminal act is a useful outcome; a queue delivered as though it had shipped is not.
Phase 3: DISPATCH — Tiered Fan-Out With a Concurrency Governor
FIX tier: one worktree-isolated subagent per finding, briefed to run four steps in order.
(a) Re-confirm the evidence reproduces in its own worktree before changing anything — inherited evidence is not evidence, and a finding that will not reproduce is a false positive to be dropped and reported, never fixed on faith.
(b) Run the item's routed real fix pipeline (§Item-type routing, ADR 0103) to author the fix — this is the family's dogfooding invariant, and the routed pipeline is what leaves the artifact VERIFY checks for.
route = bug(the common FIX case — a known, bounded remedy) runsharness-debugging(investigate → fix), leaving astages=[debugging]provenance rather than a plan directory.route = feature(a bounded fix that still carries a genuine design decision) runsharness-brainstorming→harness-autopilot, leaving the plan directory plus autopilot-state. Either way the fix is authored through a real pipeline, never hand-patched.(c) Where the finding is code-side, add a regression test that fails before the fix and passes after — the security analogue of a behavior-asserting test, and the only proof the vulnerability is closed rather than merely unscanned.
(d) Run the OWASP/CWE reviewer (
harness-security-review) over its own diff before pushing, so obvious new weaknesses are caught before the branch is pushed. Self-review is a first pass, not the verdict — VERIFY re-scans independently precisely because a subagent reviewing its own work is the weakest link in the chain.The
advisory-matchdegradation is narrow and named. For a dependency bump with no code-side sink, step (c) degrades to the advisory clearing plus all-OS CI green (no behavior regression) — a version bump has no call site of its own to characterize. This is the only degradation, and it is not a general licence: a code-sidereachable-sinkorexploitable-pathfinding always needs a regression test that fails before the fix. "It's just a small patch" is not anadvisory-match.FILE tier: an evidence packet, not a build. A FILE-tier item opens no branch and runs no build pipeline. Its work product is a filed issue containing the evidence class and its concrete trace, the affected locations, the advisory or CWE reference, why the remedy is structural, and the options a human would need to decide between. It is filed through the project's configured security-disclosure channel when one exists, otherwise the normal issue tracker. A filed item with no evidence is exactly the speculative flag the gate exists to reject — the evidence packet is the deliverable.
Re-tier and park; never grow the fix. A FIX-tier item that proves structural mid-flight — the bounded patch turns out to require an auth-model change, or the sink cannot be closed without moving a trust boundary — re-tiers to FILE and parks, carrying everything it learned into the evidence packet. It does not grow the fix to fit the finding. Separately, an item whose only available remedy is a suppression, ignore rule, advisory mute, or scanner exclusion re-tiers to FILE with that constraint stated — it is never closed by suppression, because suppression closes a count, not a vulnerability. Any other unforeseen fork parks that one item; the rest of the batch continues uninterrupted.
Never publish a secret's value. A leaked-credential finding is the one case where the evidence is the secret. Report the file, the line, and the credential type — never the value — in every surface: PR description, issue body, report row, and commit message alike. A sweep that publishes the secrets it found has converted a contained leak into a broadcast one. State plainly in the outcome that rotation is a required human action the fleet does not perform: removing a credential from source does not un-leak it, and a fix PR that removes the string without rotation is a half-closed finding.
Domain boundary: park correctness defects, do not fix them. A non-security correctness defect discovered incidentally — a crash, a wrong result, a race — parks and is reported for the build pipeline. It is never fixed inside the security sweep, even when the subagent is already in the file. Two fleets fixing the same file from different queues produce conflicting PRs; the clean domain split is what keeps the batches independent.
Concurrency governor and push path. Cap concurrent subagents at the confirmed governor (default 2, max ~3) — the machine-storm limit shared across the family, beyond which compound load produces flaky failures indistinguishable from real ones. Never raise the cap to "go faster." A worktree created under a
.claude/-nested path breaks the local pre-pushcheck-docsgate (it self-excludes and scans zero files); subagents push via the GitHub API or from a non-.claudethrowaway worktree. Never--no-verify— bypassing the gate defeats the verification the whole fleet depends on.
Worker handoff — return the canonical FleetHandoffRecord. When a worker finishes its item it hands the orchestrator exactly one FleetHandoffRecord (from @harness-engineering/types) — the ONE bounded envelope every -fleet member emits, so fleet-command parses any fleet's worker output uniformly instead of special-casing an ad hoc per-worker report shape. The record carries status (done | parked | blocked | failed), fleet, item, a one-line summary, an evidence[] of verifiable pointers (branch, PR, artifact path, CI check — exactly the references VERIFY re-checks), next_steps[], and, for any non-done status, a blocker. The orchestrator validates it with validateFleetHandoffRecord; a malformed or unknown-keyed record is rejected, never silently misread. See the canonical handoff record in docs/reference/fleet-family.md.
Phase 4: VERIFY — Independent Confirmation, Never Self-Report
Never accept a subagent's self-report as verification. "Fixed, scanner is clean, CI green" is a claim to be checked, not a result. For each returned FIX-tier branch the orchestrator independently confirms all four checks below; failing any one of them is a rejection, not a discount.
Pipeline artifact — matched to the FIX item's route. Confirm the artifact the route implies exists committed on the branch: for
route = feature, a plan directory underdocs/changes/<slug>/plans/plus autopilot-state; forroute = bug, astages=[debugging]provenance and the reproducing test from step (c) — a debugging run leaves noplans/directory, so its absence is not a defect and a bug-routed item is never rejected for lacking one. A branch with neither its route's artifact nor any pipeline trace did not run the real pipeline — it is a hand-patch, regardless of what the report says, and hand-patched security fixes are exactly the scanner-silencing edits this fleet exists to prevent.Evidence cleared. Confirm the original evidence no longer reproduces on the branch: the sink is unreachable, the advisory is clear, the boundary control is present, or the credential literal is gone from tracked source and rotation is recorded as still outstanding (removing a secret from source does not un-leak it, so an unrotated credential is half-closed, not cleared) — whichever class the finding carried. This is the security analogue of a coverage delta, and it is the check that distinguishes a fix from a mute. Re-run the evidence, do not re-read the report.
No new finding. Re-scan the branch and confirm it is not worse than the base. A fix that clears its own evidence while introducing a new weakness is rejected, not reported as merge-ready — trading one vulnerability for another is not a fix, and the fact that the original ticket can now be closed is not a reason to ship it.
All-OS CI green. Confirm the pushed branch is green on all operating systems plus the project's required checks, with the full test suite passing — not just the new regression test. Green on one OS is not green, and a mixed result is never averaged into "mostly green." Base freshness (spine clause): all-OS green is trusted as
verifiedonly when it ran against currentmain— the branch is up to date withmain, or branch protection enforces strict / up-to-date-before-merge. Green gathered against a base thatmainhas since moved past is stale: downgrade the item todegraded, not verified, and report the stale tested base SHA vs currentmain. Seedocs/reference/fleet-family.md§ Base freshness (classifyBaseFreshness).FILE-tier items are verified differently, but they are still verified. Confirm the issue exists, carries a named evidence class with its concrete trace, and is not a duplicate of an existing open item. A filed issue with no evidence packet is the speculative flag the gate rejected upstream, re-entering through the back door.
Classify each item with a tier-appropriate verdict. A FIX-tier item is
verified(all applicable checks passed),rejected(missing artifact, evidence still reproduces, a new finding introduced, or definitively red CI), orretry(transient, retried at most once). A FILE-tier item isfiled-and-verified(the issue exists, carries its evidence class and trace, and is not a duplicate) orrejected(missing, evidence-free, or a duplicate). An item that never reached VERIFY — parked on an unforeseen fork, re-tiered mid-flight, or dropped as a false positive — is recorded asparkedwith its reason. No item reaches REPORT as merge-ready without passing every check that applies to its tier.
Phase 5: REPORT — Batch Summary, Discard Count, Never Merge
Emit a one-row-per-item batch summary for bulk human review:
Finding Evidence class Tier Verdict PR / Issue Assumptions made Parked / re-tiered Every verified row carries its PR or issue link, the assumptions-made note from DISPATCH, and any parked fork or mid-flight re-tier. Rejected items are listed with the reason (no artifact, evidence still reproduces, new finding introduced, subset-red CI) — a rejection is a result the reviewer needs, not a failure to hide.
Print the aggregate evidence-gate discard count alongside the table. State how many candidates were enumerated, how many carried a named evidence class, and how many were discarded. The batch is only credible when the reader can see the volume the gate absorbed.
Annotate duplicates and already-remediated findings with a citation — the resolving PR or the existing open issue — recorded as dropped or closed. Never re-filed, never re-fixed.
Report secrets by location and type only. Restated here because REPORT is the surface where it is most tempting to be helpful: file, line, and credential type — never the value. Name rotation as the required human action the fleet did not perform.
Never merge. The fleet delivers verified, reviewable fix PRs and filed evidence packets; the human lands them. The never-silent-merge invariant applies with extra force here — a security PR that merges without a human read is the failure mode the whole batch-review model exists to prevent.
Degrade gracefully. A missing scanner, unavailable advisory data, missing
ghauth, or a single item's failed fix is reported while the batch continues, with the gap named. One bad item never sinks the batch, and a partial queue is never presented as a complete one.
Harness Integration
harness skill run security-fleet— Run the full five-phase batch sweep.harness-security-scan— Composed in SELECT for mechanical code-side enumeration, and again in VERIFY to re-scan each branch for new findings; the fleet does not reimplement scanning.harness-supply-chain-audit— Composed in SELECT for 6-factor dependency risk evaluation and advisory matching over the resolved dependency tree.security-craft— The LLM-judgment trust-boundary and least-authority critique that supplies the code-side findings a mechanical scanner cannot see.harness-security-review— Supplies the OWASP/CWE finding taxonomy in SELECT, and is run by each FIX-tier subagent over its own diff in DISPATCH before pushing.harness-roadmap-pilot— Its impact scoring is reused in SELECT to order findings by severity × evidence strength × exposure.harness-brainstorming→harness-autopilot— The real fix pipeline afeature-routed FIX-tier subagent runs (a bounded fix that still carries a genuine design decision); it is the source of the plan-directory and autopilot-state artifact VERIFY requires for that route.harness-debugging— The real fix pipeline abug-routed FIX-tier subagent runs (the common case: a bounded vulnerability with a known, mechanically-verifiable remedy). Per §Item-type routing (ADR 0103) it is chosen in SELECT, confirmed/overridable in CONFIRM, and leaves astages=[debugging]provenance plus the reproducing test in place of a plan directory.- The knowledge graph — Supplies the exposure weighting (entry points, trust boundaries, critical paths) that turns a flat finding list into a risk-ranked queue.
gh— Cross-check in-flight security PRs and open security issues (SELECT), readgh pr checksfor all-OS CI (VERIFY), and open fix PRs and file evidence packets (REPORT).docs/reference/fleet-family.md— The shared-fleetspine this skill builds on (five-phase skeleton, the §Item-type routing rubric the FIX tier applies, concurrency governor, artifact + all-OS-CI verification discipline, worktree fan-out, never-silent-merge).harness skill validate security-fleet— The authoring-time gate for this skill's own structure and schema.
Success Criteria
- Given a confirmed batch of N findings, the fleet produces up to N outcomes — FIX-tier PRs each independently verified for pipeline artifact, cleared evidence, no new findings, and all-OS-green CI; FILE-tier issues each carrying a named evidence class with its trace.
- Every item in the batch carries a named evidence class — candidates without one are discarded before CONFIRM and reported only as an aggregate count.
- There is exactly one up-front human decision round; no per-item interactive pauses except a genuinely-new fork or a mid-flight re-tier parked to its own item.
- No structural remedy is applied autonomously — an auth-model or trust-boundary change is filed with evidence, never patched inside the sweep.
- Every FIX-tier PR carries an "assumptions made" note and, where the finding is code-side, a regression test that fails before the fix.
- Every FIX-tier item is routed by type (§Item-type routing / ADR 0103): a bounded vulnerability with a known remedy runs
harness-debugging(verified onstages=[debugging]provenance + the reproducing test, not a plan directory), and a bounded fix carrying a genuine design decision runsharness-brainstorming→harness-autopilot. The route is shown and is human-overridable in CONFIRM. - No secret value appears in any PR description, issue body, report row, or commit message — secrets are reported by location and type only, with rotation named as a human action.
- No finding is closed by suppression — an ignore rule, advisory mute, or scanner exclusion added to clear an item is rejected.
- Duplicates and already-remediated findings are dropped or closed with a citation, never re-filed or re-fixed.
- The skill never auto-merges a security PR.
- It degrades gracefully — a missing scanner, unavailable advisory data, missing
ghauth, or a single item's failed fix is reported while the batch continues. - Concurrency never exceeds the confirmed governor (default 2, max ~3).
- No item is marked fixed on a subagent self-report — every verdict is backed by independently-checked evidence.
Gates
- No item in the batch without a named evidence class. No evidence, no item — discarded and counted, never downgraded to "low confidence" and never carried into CONFIRM as an FYI. Presenting an ungated candidate to the human is a gate violation.
- No "merge-ready" without the original evidence cleared. A branch whose sink is still reachable, whose advisory still matches, or whose boundary control is still missing is not a fix — however green its CI is.
- No "merge-ready" when the branch introduces a new security finding. A re-scan worse than the base is a rejection, not a trade. Clearing one weakness while adding another does not net out.
- No "merge-ready" without the pipeline artifact and all-OS CI green. A branch with no plan directory and autopilot-state did not run the real pipeline; green on a subset of operating systems is not green.
- Never close a finding by suppression. An ignore rule, advisory mute, or scanner exclusion added to clear an item is a gate violation — re-tier the item to FILE with the constraint stated. Suppression closes a count, not a vulnerability.
- Never apply a structural remedy autonomously. Auth-model changes, trust-boundary redesigns, and cryptographic-scheme replacements are filed with evidence, never patched inside the sweep. A sweep that redesigns an auth model is a larger risk than the finding it was closing.
- Never publish a secret's value. Location and type only, in every surface — PR description, issue body, report row, commit message. Rotation is a human action the fleet names and does not perform.
- Never fix a non-security defect inside the sweep. Park it and report it for the build pipeline; the domain split is what keeps two fleets from producing conflicting PRs on the same file.
- Never auto-merge, never exceed the concurrency governor, never
--no-verify, and a self-report is never verification.
Escalation
- The project has no lockfile: the supply-chain half has no resolved tree to read — sweep the code side only and say so in CONFIRM and REPORT.
- A scanner or the advisory source is unavailable: build the queue from the remaining half, record the gap in CONFIRM and REPORT, and never present the partial queue as complete. If neither half is available, stop and report — there is no queue to sweep.
ghis unauthenticated: run SELECT and CONFIRM, open no PRs and file no issues, and report the ranked queue with the blocked terminal act named.- A finding's evidence does not reproduce in the subagent's own worktree: drop it as a false positive and report it as such. Never fix on inherited evidence — a fix for a finding that does not reproduce is a change with no justification.
- A FIX-tier item proves structural mid-flight: re-tier it to FILE and park it, carrying what the subagent learned into the evidence packet. Never grow the fix to fit.
- A fix clears its evidence but the re-scan shows a new finding: reject the item with both findings named. Do not report it merge-ready and do not "note the follow-up" in the PR body.
- The only available remedy is a suppression: re-tier to FILE with that constraint stated explicitly, so the human decides whether to accept the risk. Never close the item by adding the suppression.
- A non-security correctness defect surfaces: park that item and report the defect with its context for the build pipeline. The other in-flight items continue.
- CI is red on a subset of operating systems: report the item failed with the failing OS and check named. Never average a mixed result into "mostly green," and never mark it merge-ready pending a re-run.
- The batch appears coupled (several findings share one fix, or one fix must land first): stop fanning out those items — the coupling means they are a pipeline, not a fleet. Escalate to the human to sequence them.
Rationalizations to Reject
| Rationalization | Reality |
|---|---|
| "The scanner flagged it, so it goes in the batch" | A scanner flag is a candidate, not a finding. No named evidence class, no item — volume is the exact failure mode the gate exists to stop, and a queue full of maybes stops being read. |
| "It's probably reachable — I'll include it at low confidence" | "Low confidence" is not an evidence class. Either the path exists in the code or it does not; discard it and count it, rather than spending the human's attention on a maybe. |
| "Adding an ignore rule clears the finding" | Suppression closes a count, not a vulnerability. Re-tier the item to FILE with the constraint stated and let a human accept the risk explicitly — never silently, and never as a "fix." |
| "The auth model is the real problem — I'll redesign it while I'm in here" | An autonomous sweep that redesigns an auth model is a larger risk than the finding it was closing. File it with the evidence packet and the options; the decision belongs to a human. |
| "The subagent says the fix works and CI is green" | A self-report is a claim. Independently confirm the original evidence no longer reproduces and that the re-scan is not worse than the base — a clean scanner can also mean a muted one. |
| "The bump clears th |
…(truncated)