Skip to content
Back to skills

Deadly Loop

ASecurity

Iterative TRIO-debate + fix-wave protocol for hardening non-trivial PRs and changes before merge. Spawns a parallel Reviewer + Auditor + Critic trio, dispatches fix waves, loops until convergence (zero NEW P0 or P1 blockers). Use before merging anything with cross-file risk, cross-PR coordination, security-sensitive changes (auth, signing, redaction, prompt-injection defense), schema migrations, production-data touches, shell scripts, CI/workflow YAML, cross-repo coordination, or LLM prompt w...

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 2, 2026
ai-agentspythonrustgoshellbashnodeexpressrailstestinggit

Works with

  • cli

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned October 3, 2026

npx -y skills add talas9/anti-hall --skill deadly-loop --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Deadly Loop?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Deadly Loop
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/talas9-deadly-loop/badge)](https://www.skillsdirectory.com/skills/talas9-deadly-loop)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: deadly-loop
description: Iterative TRIO-debate + fix-wave protocol for hardening non-trivial PRs and changes before merge. Spawns a parallel Reviewer + Auditor + Critic trio, dispatches fix waves, loops until convergence (zero NEW P0 or P1 blockers). Use before merging anything with cross-file risk, cross-PR coordination, security-sensitive changes (auth, signing, redaction, prompt-injection defense), schema migrations, production-data touches, shell scripts, CI/workflow YAML, cross-repo coordination, or LLM prompt work — anywhere a silent failure would be expensive. Born from a real project where 7 iteration rounds caught 30+ bugs that solo review would have missed.
---

# Deadly Loop — Iterative Debate Until Clean

Spend 1-2 hours of agent compute to ship a clean change rather than 1-2 weeks of post-merge incident response.

This skill uses a shared TRIO debate roster defined in `references/MODEL-POLICY.md` (Reviewer = Sonnet `model:"sonnet"` at effort `xhigh`; Auditor = latest Opus `model:"opus"`, divergent regression/coupling lens, effort `high`; Critic = latest OpenAI Codex at `xhigh` reasoning, with an Opus divergent-persona fallback). Read that file before dispatching any round so the model selection, the availability fallback matrix, the round governance, and the spawn mechanics are correct.

## Risk-scaled effort (token savings, 0.117.0)

Match the review rigor to the change's blast radius — don't reflexively spend the
full TRIO on everything. Decide from this table FIRST, before reading further:

| Change touches... | Effort |
| --- | --- |
| Guard/security-sensitive code (auth, signing, redaction, prompt-injection defense), a parser, a schema/production-data migration, CI/workflow YAML, or a shell script | **Full TRIO** (Reviewer + Auditor + Critic, this skill's normal flow below) |
| Normal application/library code with no guard/security/parser/schema/CI/shell surface | **One reviewer** (a single Sonnet-tier review pass is enough — skip the Auditor/Critic seats and the multi-round convergence loop) |
| Text-only or doc-only changes (README, comments, changelog, prose) | **None** — no review lever needed |

No metric is tracked for this lever — it is guidance, not a measured/gated
behavior. When in doubt, or when a change straddles rows (e.g. a doc change that
also edits a shell script), use the heavier row.

## When to use this skill

**Use when ANY of these are true:**
- The change touches multiple files across multiple PRs and merge order matters
- Hand-merges between divergent branches are required
- Serverless / Cloud Function deploy with signature verification (HMAC), IAM, or secret coupling
- Schema migration / production-data touches
- Security-sensitive changes (auth, redaction, signing, prompt-injection defense)
- LLM prompt engineering (tokens, caching, model thresholds — easy to claim works without testing)
- Bash / shell scripts (parameter expansion has subtle parser bugs)
- CI / workflow YAML edits (e.g. GitHub Actions — expression context scoping is tricky)
- Cross-repo coordination (monorepo + submodules, parallel agents working concurrently)
- Anything labeled "non-trivial" by an experienced engineer's gut

**Don't use for:**
- Single-file bug fixes
- Trivial UI tweaks
- Existing-spec implementation with no design ambiguity
- Doc-only changes
- Anything <1 day of work AND <2 files touched

## Pre-requisites

Before invoking the deadly loop, ensure:
1. The changes are **committed and pushed** (the loop audits remote state via `gh pr diff` etc.); local-only work can be audited against the working tree, but remote is preferred.
2. A **loop state record** exists or will be created (e.g., `.anti-hall/history/<date>/<feature>-loop-state.md`; it is not a session handover, which lives only under `.anti-hall/handovers/`).
3. The owner has authorized at least one full iteration (each round is ~5-30 min of agent compute).
4. A verification preamble + branch/SHA check is in effect for every spawned agent (see Phase A3).
5. The debate roster from `references/MODEL-POLICY.md` is resolved — read the `codex-availability` fact (`~/.anti-hall/codex-availability.json`) first; fall back to the live OS-agnostic Node probe in `references/MODEL-POLICY.md` only if that fact is absent/stale — so you know which row of the availability fallback matrix applies. When Codex is available, the Critic seat MUST spawn `agentType:'codex:codex-rescue'`, not degrade to Opus. (Fable routing is RE-ENABLED — see `references/MODEL-POLICY.md` — the Reviewer seat routes to `fable` when `args.fableAvailable === true`, falling back to Sonnet then Opus.)

## The pattern at a glance

```
Round 1 (initial audit, Reviewer + Auditor + Critic trio in parallel)
  └─→ findings → Wave 1 (orchestrator + parallel children)
                  └─→ commits pushed → Round 2 (post-Wave-1 audit)
                                        └─→ findings → Wave 2
                                                       └─→ ...
                                                            └─→ Round N (zero NEW P0/P1s) → GO → owner merge
```

Each round = a Reviewer + Auditor + Critic TRIO (3 agents), dispatched **in parallel in the same message**. Roster, availability fallback matrix, round governance + spawn details: `references/MODEL-POLICY.md`.
Each wave = 1 orchestrator agent + N parallel children for parallel-safe fixes, then serial children for fixes with dependencies.

## Phase A — Initialize the loop

Before Round 1:

### A1. Create / update the loop state record

`.anti-hall/history/<date>/<feature>-loop-state.md` becomes the **authoritative state record**. Every round + wave updates it. Format:

```markdown
# <Feature> — Loop State (<date>)

**Status:** <one-line current state>

## Where we are right now
- Iteration: Round N / Wave M
- Active background agents: <agent IDs>
- Last verified state: <SHA per branch>

## Round 1 findings (P0/P1/P2 with file:line citations)
## Wave 1 work list + commit SHAs after dispatch
## Round 2 findings
## Wave 2 work list + commit SHAs
... (one section per iteration)

## How to continue
<resume prompt for next session>
```

The loop state record is **how every spawned agent gets full prior history**. Without this, Round 7 doesn't know what Round 1 already verified, and re-runs the same audits.

### A2. Snapshot baseline

```bash
git -C <repo> branch --show-current
git -C <repo> rev-parse --short HEAD
gh pr list --state open --json number,headRefName,headRefOid,mergeStateStatus
```

Record these in the loop state record. Compare every round to detect drift.

### A3. Lock the verification preamble

Every spawned agent MUST run this before any read/write. It is pure Node
(`child_process.execFileSync`), so it runs unchanged on macOS and Linux —
no POSIX shell, no `$(...)`, no `[ ... ]`. Save as `verify-branch.js` (or paste into
`node -e`) and run `node verify-branch.js <expected_dir> <branch> <sha>`:

```js
// verify-branch.js — exits 1 on branch/SHA drift, 0 when the worktree matches.
'use strict';
const { execFileSync } = require('child_process');
const [dir, expBranch, expSha] = process.argv.slice(2);
const git = (...a) => execFileSync('git', ['-C', dir, ...a], { encoding: 'utf8' }).trim();
const actualBranch = git('branch', '--show-current');
const actualSha = git('rev-parse', '--short', 'HEAD');
if (actualBranch !== expBranch || actualSha !== expSha) {
  console.error(`BRANCH/SHA MISMATCH: expected=${expBranch}@${expSha} actual=${actualBranch}@${actualSha}`);
  console.error('STOP — surface to orchestrator before proceeding');
  process.exit(1);
}
console.log(`OK ${actualBranch}@${actualSha}`);
```

The orchestrator dispatching the agent fills `<expected_dir>`, `<branch>`, `<sha>` from the moment of dispatch.

> POSIX-only equivalent (Linux/macOS shells), if a Node verifier is unavailable:
> ```bash
> cd <expected_dir>
> [ "$(git branch --show-current)" = "<branch>" ] && [ "$(git rev-parse --short HEAD)" = "<sha>" ] \
>   || { echo "BRANCH/SHA MISMATCH — STOP, surface to orchestrator"; exit 1; }
> ```

## Phase B — Round N debate

A TRIO of three parallel agents dispatched in the **same message** (roster + availability fallback matrix + exact spawn syntax in `references/MODEL-POLICY.md`):

- **Reviewer** — Fable when available (`model:"fable"`) at effort `xhigh`, else Sonnet (`model:"sonnet"`) (Fable routing is RE-ENABLED — see `references/MODEL-POLICY.md`). Correctness / architecture auditor.
- **Auditor** — latest Opus (`model:"opus"`) at full reasoning depth (effort `high`). Divergent: regression & coupling hunter (hunts what broke ELSEWHERE — regressions in unchanged code, wrong cross-module/cross-PR coupling, fixes that undid earlier fixes, merge-order cross-reference breaks).
- **Critic** — latest OpenAI Codex at `xhigh` reasoning **when available** (canonical Codex spawn form in `references/MODEL-POLICY.md`); otherwise an Opus with a divergent adversarial "failure-mode hunter" persona.

See `references/MODEL-POLICY.md` for the OS-agnostic Node probe that checks `fable`/Codex availability and the concrete `Agent(...)` / Codex invocations. Dispatch all three in ONE message so they run truly in parallel.

### B0. Auditor depth requirements (all three seats)

These four requirements bind **all three** seats — the Reviewer, the Auditor, and the Critic. A round that skips them is wasted compute — surface-skimming is exactly how the 30+ bugs in the origin session slipped past solo review.

1. **DIG DEEP, DO NOT SURFACE-SKIM.** Read the ACTUAL implementation of each changed/affected function end to end. Trace control flow and data flow across file boundaries; follow every branch, every error path, every early return. Never judge correctness from a name, a signature, a comment, or a diff hunk alone — open the code it calls and the code that calls it. State what you actually read (`file:line` ranges), not what you inferred.

2. **ENUMERATE & SIMULATE EDGE CASES.** For each changed unit, list the boundary/adversarial inputs — empty, null/undefined, malformed, max-size/huge, unicode, concurrent/interleaved, missing file, permission-denied, clock-skew/future-timestamp, partial/truncated, injection-shaped — and MENTALLY EXECUTE the code for each (or write a quick throwaway harness). Report the predicted outcome per input. Flag any input that produces a wrong/unsafe result, a throw on a fail-open path, or an unbounded operation.

3. **THREE-TIER SEVERITY (heat).** Tag every finding:
   - **P0** — critical/blocker: silent failure, security, data loss, fail-CLOSED, breaks a guard.
   - **P1** — high: wrong behavior on a real path, regression.
   - **P2** — medium: robustness, clarity, perf.
   - **EASY-WIN** — cheap, high-value cleanups worth doing while you're in there.
   Sort by heat, P0 first.

4. **CARRY-FORWARD.** You are given the full prior-round history (loop state record) + the exact fixes applied since. FIRST verify each prior finding's fix actually resolved it WITHOUT regression; THEN hunt genuinely NEW issues. Always distinguish NEW from REDISCOVERED.

### B1. Reviewer prompt skeleton

(Apply the B0 depth requirements: dig deep, simulate edge cases, P0/P1/P2 + EASY-WIN, carry-forward.)

```
You are the Round N Reviewer for <feature>. Verify Wave-(N-1) commits resolve their parent Round-(N-1) findings without regression.

CRITICAL READING:
1. <loop state record path> — covers Rounds 1 through N-1
2. PR diffs via `gh pr diff` and `gh pr view --json files,mergeStateStatus` (or the working-tree diff if not yet pushed)

Wave-(N-1) commits to verify:
- Fix-X: <commit SHA> on <branch> — targets <Round-(N-1) finding>
- Fix-Y: <commit SHA> on <branch> — targets <Round-(N-1) finding>
- ...

Verification grid:
| Fix | Round-(N-1) finding | What to verify |

For each Fix:
- PASS: cite file:line evidence
- FAIL: cite what's still broken
- PARTIAL: cite what's fixed vs what's not

Cross-PR merge order final walkthrough: predict outcome of each merge in the documented order. Identify any conflicts that would surface during interactive merge.

Verdict:
- GO: All Wave-(N-1) fixes resolve Round-(N-1) issues + merge order clean
- HOLD: list specific blockers
- BLOCKED: architectural issue requiring owner decision

Hard rules:
- Read remotely via `gh pr diff` / `gh pr view --json files` (or working-tree diff if unpushed)
- No local checkout mutations, no edits, no pushes
- Cite file:line for every claim
- If you can't verify due to limited tooling, say so — don't pass blindly

Run independently of the Auditor and Critic agents.
```

### B1.5. Auditor prompt skeleton (divergent regression & coupling lens)

(Apply the B0 depth requirements: dig deep, simulate edge cases, P0/P1/P2 + EASY-WIN, carry-forward.)

The Auditor (latest Opus, `model:"opus"`) runs a DIFFERENT Claude generation from the Reviewer, with an orthogonal lens: it does not re-verify the diff the way the Reviewer does — it traces the blast radius OUTWARD to find what the change broke elsewhere.

```
You are the Round N Auditor for <feature>. DIVERGENT lens: regression & coupling hunter. Do NOT duplicate the Reviewer's diff-verification — trace OUTWARD from the change.

CRITICAL READING: same as Reviewer (loop state record + PR diffs / working-tree diff).

Wave-(N-1) commits to trace the blast radius of:
[same list as Reviewer]

Hunt specifically for:
- Regressions in UNCHANGED code that depends on the changed code (callers, importers, downstream consumers) — open the call sites, do not infer.
- Wrong coupling: a contract / schema / shared constant / message shape that the change perturbs but a sibling module/PR still assumes the old form.
- Fix-vs-fix regressions: did a Wave-(N-1) fix silently undo an earlier fix (Fix-K, K<N-1)?
- Merge-order cross-reference breaks: after the documented merge order, does every cross-PR reference still resolve?

Output: P0/P1/P2 + EASY-WIN with file:line citations. Distinguish NEW from REDISCOVERED.

Verdict format same as Reviewer.

Run independently of the Reviewer and Critic agents.
```

### B2. Critic prompt skeleton

Reminder: Codex (`agentType:'codex:codex-rescue'`) is the DEFAULT spawn for this seat; `{model:'opus'}` is the FALLBACK only, used only when Codex is unavailable per the availability check above.

(Apply the B0 depth requirements: dig deep, simulate edge cases, P0/P1/P2 + EASY-WIN, carry-forward.)

```
You are the Round N Critic for <feature>. Adversarial role: hunt where Wave-(N-1) fixes BROKE something or HID a different bug.

CRITICAL READING: same as Reviewer.

Wave-(N-1) commits to attack:
[same list]

Hunt for these specific failure modes for each fix:
- Edge cases the orchestrator didn't test
- Unintended side effects on adjacent code
- Subtle regressions: did Fix-X accidentally undo Fix-K (K<N-1)?
- Cross-PR runtime correctness: do all references still resolve after the fix?
- Validation claims that weren't actually validated (e.g., "merge rehearsal passed" — was the rehearsal target right?)

Specific cross-PR hunts:
[fill in based on this round's PR landscape]

Output: P0/P1/P2 with file:line citations. Distinguish NEW issues from previously-found issues. New issues should be genuinely new (introduced by Wave-(N-1) commits), not re-discovered from earlier rounds.

Verdict format same as Reviewer.

Run independently of the Reviewer and Auditor agents.
```

**Critical: dispatch all three seats in the SAME message** so they run truly in parallel. Don't sequentially.

### B3. Synthesis (you do this on receipt)

All three seats return → **before** you dedup by hand, write their combined findings to a
scratch JSON array (`{id, severity, file, line, text, round, seat}` per finding — `seat` is
`'reviewer'|'auditor'|'critic'`) and run
`node "${CLAUDE_PLUGIN_ROOT}/scripts/finding-dedup.js" --file <scratch findings.json>`.
This is the opt-in Jev `findingDedup` integration (default `on` — 65/65 correct at
confidence ≥0.85 on a 30-day, 3-project offline benchmark; see CHANGELOG 0.108.4 and the
`jev` skill's integrations table): it groups findings the classifier judges to describe
the SAME underlying issue and prints them as advisory lines, e.g. "possible duplicates:
round-2-critic-4 ~ round-1-reviewer-9 (conf 0.93)" — show these to yourself as a hint
("these look like duplicates of round-N finding X; confirm before merging"), **never
auto-collapse**: you still read the actual findings and decide whether they are the same
issue. Jev disabled/unconfigured/off/erroring → the script prints no groups and exits 0
(fail-open) — dedup by hand as before.

Then dedup their findings → categorize, applying the **round governance** in `references/MODEL-POLICY.md`:
- **GO from all three (a non-degraded round)** → proceed to Phase D (merge). A GO requires zero un-adjudicated HOLD blockers AND a full, non-degraded round — a **DEGRADED round (a seat dead after its one retry) can NEVER grant a final GO**; the missing seat must sit in a full follow-up round first.
- **HOLD from any seat** → write Wave N work list, dispatch Phase C.
- **≥2-of-3 agreement on a finding = confirmed-real** → highest priority, definitely real.
- Issues only ONE seat flags → either a deeper bug the other two missed OR a false positive — adjudicate against the actual code.

**Argument outcomes (dissent adjudication):** a **single-seat re-run** is allowed ONLY for evidence-adjudication with NO code/plan change in between (re-run the one dissenting seat to confirm/refute against the current state). **ANY fix wave ⇒ the FULL TRIO re-runs next round** — never a single-seat re-audit after code changed (preserves the anti-pattern below). Evidence-refuted dissent may be overridden, documented in the handoff.

**Apply the round-discipline rules:**
1. Each round has full history (loop state record) AND focuses NEW analysis on the latest delta.
2. If a round's findings RE-DISCOVER prior issues already verified clean, that's a process bug — narrow scope further.
3. **Convergence test**: count of NEW (not rediscovered) confirmed P0s or P1s. Target: 0 → GO. The trend should monotonically decrease.

Append round outputs to the loop state record. Commit + push.

## Phase C — Wave N fix dispatch

One orchestrator agent + parallel children. The orchestrator handles:

### C1. Wave N orchestrator prompt skeleton

```
You are the Fix Wave N orchestrator for <feature>. Round N found <count> P0/P1 issues. Dispatch the fixes, handle sequencing, report back.

CRITICAL READING:
1. <loop state record path>
2. The verification preamble (branch+SHA check, Phase A3)
3. The round-discipline rules (focus NEW analysis on the latest delta; convergence counts NEW not rediscovered P0s/P1s)

HARD CONSTRAINTS:
- Branch+SHA preamble in EVERY child agent prompt
- `git pull --rebase origin <branch>` before push (NEVER force-push UNLESS this fix spec authorizes it as an explicit rebase fix)
- Push rejection or branch mismatch → STOP + report
- VALIDATION REQUIRED before push (per Critic's directive):
  - bash files: `bash -n` syntax check + INVOCATION TEST with expected output
  - JS files: `node --check`
  - YAML files: `yamllint -d relaxed`
  - Python files: `python -m py_compile` + inline regex unit tests if regex changed
  - Force-push fixes: `git merge --no-commit origin/<base>` rehearsal proof BEFORE force-push

The N fixes (Fix-A through Fix-N):
[per-fix table with severity, branch, file, exact patch, validation requirements]

Sequencing:
- Wave NA — parallel-safe (dispatch in one message): [list]
- Wave NB — serial, requires coordination: [list]

Subagent prompt template:
[ROLE / TARGET / FILE / PATCH / VERIFICATION PREAMBLE / VALIDATION / COMMIT+PUSH / REPORT]

Use a fast/cheap model for execution-only fixes (apply specific patch, push). Use a stronger model for fixes requiring investigation, hand-merging, or rebase planning. (Round debate agents always use the full roster in references/MODEL-POLICY.md — never downgrade those.)

Final report (under 800 words):
| Fix | status | commit SHA | branch | validation evidence (paste actual outputs) |

Plus: overall verdict — "Round N+1 ready" or "still blocked on X". Identify if any validation step would have caught a prior wave's bug.
```

### C2. Wave-A vs Wave-B sequencing

- **Parallel-safe fixes**: independent files, no shared state — dispatch in one Agent message.
- **Serial fixes**: rebases, hand-merges, cross-PR moves — must sequence to avoid clobbering. Use a reasoning-capable model for these (investigation required).

### C3. Validation rigor (the hard-won rule)

A real fix wave once declared 10 fixes "DONE" without runtime validation. A later round caught, among others:
- `PAYLOAD_JSON="${5:-{}}"` — bash parses at the first `}`, corrupting JSON when `$5` is set. `bash -n` does NOT catch this; only an invocation test does.
- A rebase claim ("merge rehearsal: Already up to date") that was misleading because the rehearsal target was the current base, not the future post-merge base — so the real rebase never took.

**Mandatory validation per fix type:**

| File type | Required check |
|---|---|
| `*.sh` | `bash -n <file>` AND **invocation test with expected output** (paste in report) |
| `*.js` / `*.cjs` / `*.mjs` | `node --check <file>` |
| `*.yml` / `*.yaml` | `yamllint -d relaxed <file>` |
| `*.py` | `python -m py_compile <file>` AND **inline regex unit tests if regex changed** |
| Rebases / force-pushes | `git merge --no-commit origin/<base>` rehearsal — paste output |
| Hand-merges | After splice, `node --check` or syntax-equivalent for the language |

If validation fails → child agent STOPS, does NOT commit, reports error to orchestrator.

## Phase D — Convergence + merge sequence

When Round N returns GO from ALL THREE seats (a non-degraded round — see the round governance in `references/MODEL-POLICY.md`):

### D1. Confirm convergence

- Count of NEW confirmed P0s or P1s in Round N: should be 0.
- Trend: P0/P1 count per round should monotonically decrease toward 0.
- If Round N finds NEW P0s or P1s genuinely introduced by Wave-(N-1), keep iterating (Wave N → Round N+1).
- If Round N finds REDISCOVERED issues, narrow scope (process bug) — re-emphasize delta-focus discipline in the next prompt.

### D1.5 — Verification gate (a GO is NOT valid without it)

Zero NEW P0/P1s is necessary but NOT sufficient. Before declaring GO, the orchestrator
must independently confirm — with FRESH evidence in the current round, not an agent's
say-so — that every "fixed / passing" claim is real. A clean debate over unverified
fixes is a false GO. This makes the verify-first discipline a hard convergence
requirement, inherited by every workflow that uses the deadly-loop.

For each fix claimed resolved this loop:
1. **IDENTIFY** the exact command/test that proves the claim.
2. **RUN** it fresh THIS round (re-run yourself or via a separate verifier — never trust the fix agent's report; rule L).
3. **READ** the full output + exit code.
4. **VERIFY** the output actually confirms the claim (a green suite ≠ the bug is fixed — check the bug's own assertion).
5. **VACUOUS-TEST GUARD:** any test added/changed to prove a fix MUST be shown to FAIL when the fix is reverted (revert → run → confirm red → restore). A test that passes with the fix removed proves nothing and does not count as resolution.

If any claim fails its check, the issue is NOT resolved — keep it open and iterate, regardless of the debate verdict. GO requires zero NEW P0s or P1s **and** every resolution verified by fresh evidence here.

### D1.6 — Write the advisory audit record (NOT a proof/authorization token)

On convergence (GO from D1 + D1.5 passing), write
`~/.anti-hall/approvals/<repo>@<HEAD-sha>.json` with:

```json
{
  "repo": "<repo>",
  "sha": "<HEAD short SHA>",
  "timestamp": "<ISO-8601>",
  "roundTrend": [/* NEW confirmed P0/P1 count per round, e.g. [5,2,0] */],
  "seatVerdicts": { "reviewer": "GO", "auditor": "GO", "critic": "GO" },
  "proof": false
}
```

**This file is an ADVISORY AUDIT RECORD, never proof of correctness and never an
authorization token.** Label it as such wherever it is referenced. The deadly-loop
is agent-followed guidance, not a hook enforced by the harness — an agent that
fakes convergence (skips D1.5, rubber-stamps a verdict) can just as easily fake
this file. Any reader that consumes it — e.g. a CI push gate or DevSwarm's merge
gate — MUST treat `"proof": false` as load-bearing and enforce its OWN real
gating (fresh test runs, its own review, branch protection) rather than trusting
this record as sufficient evidence on its own. This file is a breadcrumb for
audit trails and telemetry, not a substitute for the reader's own verification.

### Iteration caps (soft 10 / hard 15)

The convergence loop (Reviewer + Auditor + Critic trio debate → fix wave → re-converge, "until zero NEW P0/P1 blockers") MUST be bounded — a loop that never converges is itself a failure signal, not a reason to keep grinding silently.

- **SOFT CAP = 10 rounds.** When you reach round 10 without convergence, STOP and checkpoint with the user via `AskUserQuestion` — present the choice: **continue** (keep iterating), **stop** (accept current state and report outstanding P0s/P1s), or **change scope** (narrow the target / split the work). Do NOT keep looping silently past this point.
- **HARD CAP = 15 rounds.** At round 15, force-stop unconditionally — even if not converged. Report the remaining NEW P0s/P1s, the per-round trend, and why convergence was not reached. No further automatic rounds.

Soft = ask the user what to do; hard = force-stop regardless. If the trend is not monotonically decreasing well before the soft cap, treat that as a process bug (rediscovery / scope too broad) and fix the process rather than burning rounds.

### D2. Owner-action checklist (for the owner, not the agent)

Document in the handoff what the owner must do MANUALLY before / during / after merge — these are explicitly OUT-OF-SCOPE for the agent. Common examples:
- Create secrets in the secret manager / CI secret store
- Mirror or sync repositories if needed
- Grant IAM / access roles
- Deploy serverless functions / containers
- Configure database TTL / indexes
- Seed config documents
- Set workflow / CI env vars
- Enable platform features

### D3. Merge order

Document the strict merge order in the handoff. Common patterns:
1. **Docs PRs first** — no code interaction risk.
2. **Independent-repo PRs second** — repos that have no cross-conflict.
3. **Superset PR before subset PRs** — when one PR owns the canonical merged content, it must merge first so subsets become identical no-ops.
4. **Dependency-source before dependency-consumer** — the PR providing a script/lib before the PR using it.
5. **Audit-emit / audit-store last** — they reference everything else.

For each merge:
- Wait for CI green.
- `gh pr merge --squash --delete-branch=false` (preserve branches for forensics).
- Verify `gh pr view <num> --json mergedAt` after each.
- Move to the next.

### D4. Post-merge validation

After ALL PRs merge, run a real-world test. Define what "actually working in production" looks like for this change and verify it end-to-end (exercise the real path, inspect the real output/data, confirm side effects landed).

If post-merge validation fails → diagnose → potentially Fix Wave N+1 → Round N+1.

## Hard safety boundaries (NEVER bypass)

1. **NEVER auto-merge** — the owner authorizes each merge interactively.
2. **NEVER force-push** without (a) explicit fix-spec authorization AND (b) merge rehearsal proof.
3. **NEVER skip validation** — `bash -n` alone, `node --check` alone, etc. are not sufficient. Runtime invocation tests are required for shell scripts; merge rehearsals are required for rebase fixes.
4. **NEVER delete files unless the fix spec is explicit** — a prior wave deleted a file when the spec said "drop-from-diff", wasting a full round + wave.
5. **NEVER deploy serverless functions / production infra** — owner only.
6. **NEVER push to a protected branch without owner approval** unless project policy explicitly permits.
7. **NEVER ignore a branch+SHA mismatch** in the verification preamble — STOP and surface.
8. **Respect project-specific hands-off files** (security rules, infra config) — read for context, never modify unless the owner explicitly authorizes.

## Anti-patterns

Avoid:

- **Skipping the round debate after a fix wave** — that's how regression bugs slip through. Always run a round AFTER a wave.
- **Recycling broad audit hunts in every round** — narrow scope to the delta. Re-checking the same area in Round 7 because it was in Round 6 is waste.
- **Dispatching the next wave before updating the handoff** — always: handoff update → commit → push → THEN dispatch.
- **Trusting agent claims without runtime validation** — a "merge rehearsal: Already up to date" line can look like proof while the rehearsal target was wrong. Verify the verification.
- **Letting force-pushes happen without rehearsal** — proving the rebase is correct is mandatory.
- **Sending the trio (Reviewer + Auditor + Critic) in separate messages** — they run sequentially that way, tripling wall time. Always dispatch ALL THREE in one message.
- **Single-seat re-audit after a fix wave** — a single-seat re-run is allowed ONLY for evidence-adjudication with no code/plan change in between; ANY fix wave ⇒ the FULL TRIO re-runs next round (per the round governance in `references/MODEL-POLICY.md`).
- **Granting a final GO on a DEGRADED round** — a round where a seat stayed dead after its one retry can drive a fix wave but NEVER grants a final GO; the missing seat must sit in a full follow-up round first.
- **Downgrading debate agents without checking availability** — walk the availability fallback matrix in `references/MODEL-POLICY.md`: if Sonnet is unavailable the Reviewer falls back to Opus; if Codex is unavailable the Critic becomes an Opus with a divergent adversarial persona — NOT a weaker/cheaper model. The floor for every seat is Opus. A weaker model's debate depth is substantially shallower; use cheap models only for wave fix children, never for round debate agents. If a flagship seat is rate-limited, wait and retry rather than silently degrading.
- **Stopping after Round 1 GO** — sometimes Round 1 misses things only Round 2 catches once you have a baseline. The first GO from ALL THREE seats (non-degraded) is the gate, not Round 1.

## Telemetry to track

Per round, record in the handoff:
- Background agent IDs (so output files are recoverable)
- Wall-clock duration
- Token usage (rough)
- P0/P1/P2 count
- Whether findings are NEW or REDISCOVERED
- Convergence trend (P0/P1 count per round)

Per wave:
- Orchestrator agent ID
- Number of child agents dispatched
- Validation outputs (paste actual command results)
- Force-push justifications (with rehearsal proof)

## Origin

This skill was distilled from a real project session that delivered ~10 coordinated PRs across multiple repos, ran 7 debate rounds + 6 fix waves, and caught **30+ distinct bugs** — including a CI `if:` env-context scoping bug that would silently never fire, bash parser corruption in a `${5:-{}}` parameter default, an LLM caching-threshold misinformation, cross-PR delete-modify conflicts, a force-push rebase that didn't take effect despite a "rehearsal passed" claim, a redaction false-positive shredding legitimate text, and an auth-token leak from a regex that required the wrong separator. Each would have been a production incident or owner-time sink. The loop's cost in agent compute was trivial compared to a single one of those incidents.

## How to invoke

When the conditions in "When to use this skill" are met, proactively suggest:

> "This change has [cross-PR coordination / hand-merges / security implications / serverless coupling / shell scripts / CI YAML]. I recommend running the **deadly-loop** skill before merge — it catches subtle bugs that single-pass review usually misses. ~30-90 min of agent compute, ~$5-15 in tokens."

If the owner approves, execute Phase A → B → C → D as documented, using the roster in `references/MODEL-POLICY.md`.

## Swarm mode — the deadly swarm (Workflow execution; swarm-first)

The loop runs **swarm-first** as a Dynamic Workflow via
`references/deadly-loop.workflow.js`. The plain Agent-tool path (Phases A–D
above) stays **fully supported as the documented fallback** for sessions without
Workflow consent — it is not deprecated. Pick swarm mode for multi-round /
multi-roster runs; pick the inline Agent-tool path for small one-off audits or
when Workflow consent is unavailable.

**One workflow run = ONE round + its fix wave.** The COORDINATOR loops: run the
workflow → read the verdicts → update the handoff doc (durable state lives in the
handoff, NOT in workflow memory — there is NO cross-round caching) → decide →
next run. Each round is a fresh workflow process. The soft-cap-10 checkpoint
happens at the coordinator level via `AskUserQuestion` BETWEEN runs (a workflow
cannot prompt mid-run); the hard-15 cap is enforced by the coordinator and
double-guarded by a round-counter arg the script refuses past 15.

**Three-phase architecture (per round):**

1. **CONTEXT AGENT** (`agent(contextBrief, {model:"sonnet"})`, first call) —
   builds the shared context pack so the seats don't each re-read the target. On
   round 1 it assembles a comprehensive pack (target files, prior history via the
   handoff path passed in `args`, scope declaration, line anchors). On round >1 it builds an
   INCREMENTAL pack (prior pack + findings + fixes applied + reinvestigation
   instructions) without re-reading targets in full. Output = a context-pack FILE
   (path in the structured output) — the seats' shared source. The prior pack is
   an INPUT, not a cache (no cross-round caching preserved).

2. **THE DUEL** — *2a independent investigation*: the TRIO runs in parallel over
   the context pack ONLY (`parallel([...])`), each seat anchored to its lens but
   investigating independently (independence is load-bearing — non-anchored
   divergent seats are what catch the late-round P0s). *2b structured argument*:
   each seat receives the other seats' finding arrays and responds per finding
   with `refute` (file:line counter-evidence) / `corroborate` / `escalate`. Two
   `parallel()` waves; Codex participates identically via staged file I/O (no
   live channel).

3. **CONVERGE & CONFIRM** — VERDICT_SCHEMA dedup; the 2b responses feed
   adjudication (≥2-of-3 + argument outcomes, per the round governance).
   **RESPAWN-ON-DRIFT — OBJECTIVE criteria ONLY** (dissent is NEVER drift;
   dissents go to 2b): (1) branch/SHA mismatch vs the `targetSHA` arg; (2) wrong
   scope audited; (3) schema-required `file:line` evidence missing; (4)
   VERDICT_SCHEMA parse failure. A respawned seat gets the corrected pack + a
   drift-reason code + its offending output — NOT peer findings (contamination).
   A respawn counts against the one-retry-per-seat quota.

**Dynamic-formation args** the workflow accepts: `{seats, multiplier,
contextMode, argue, respawnQuota}` (seats = the roster from the availability
matrix; multiplier = 1 for the base loop, ≥2 for deadly-loop-multi; contextMode
= initial|incremental; argue = run phase 2b; respawnQuota = the per-seat retry
budget). deadly-loop-multi is the same script with `multiplier > 1`.

**Trio seats** are spawned per the canonical forms in `references/MODEL-POLICY.md`:
`agent(brief, {model:"sonnet", effort:"xhigh"})` / `agent(brief, {model:"opus"})` /
`agent(brief, {agentType:"codex:codex-rescue"})`. Fable routing is
RE-ENABLED (see `references/MODEL-POLICY.md`) — the Reviewer seat routes to
`model:"fable"` when `args.fableAvailable === true`, falling back to Sonnet
then Opus if Fable is unavailable or returns null/falsy. The script begins with
the codex availability probe (the MODEL-POLICY Node probe) and seats the Opus
adversarial fallback if Codex is absent.

**Workflow consent friction (stated honestly):** each Workflow call may require
harness consent unless pre-allowed — a 7-round loop can mean up to 7 prompts. Use
the skill-invocation opt-in path to pre-allow if running many rounds. If Workflow
consent is unavailable, take the plain Agent-tool path (Phases A–D) — the
coordinator spawns the trio directly and passes the context-pack path in the
briefs. Guard-coverage boundary: whether Workflow-internal `agent()` spawns fire
the Agent/Task PreToolUse hooks is environment-dependent; the script ships
explicit `model` OPTIONS on every brief so routing is correct regardless.

## Reference templates (optional, add incrementally)

A `references/` directory can hold fillable templates as the protocol matures:
- `ROUND-PROMPT-TEMPLATE.md` — fillable Reviewer + Auditor + Critic skeletons
- `WAVE-ORCHESTRATOR-TEMPLATE.md` — fillable orchestrator prompt
- `HANDOFF-DOC-TEMPLATE.md` — initial handoff doc structure
- `VALIDATION-CHECKLIST.md` — by file type
- `MERGE-ORDER-DECISION-TREE.md` — how to determine merge order from PR diff overlap

Files in this skill

  • SKILL.md36.4 KB
  • references/MODEL-POLICY.md29.3 KB
  • references/deadly-loop.workflow.js28.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.