Skip to content
Back to skills

Dev Lead

ASecurity

Orchestrate a feature or PR end-to-end as the lead — dispatch implementation to a delegate family based on task risk, model capability, and remaining quota; run bounded adversarial-review rounds with cross-family reviewers; verify everything independently; and hold the merge gate. Use when the user wants a whole feature/fix delegated and supervised, rather than a single implement or review pass.

  • 3 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added September 19, 2026
developmentpythonrustgoshellbashnodeexpresstestinggitapi

Works with

  • cursor
  • terminal
  • cli
  • api

Security analysis

A100/100

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

Scanned October 4, 2026

npx -y skills add aarontzeng/dev-lead --skill dev-lead --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dev Lead?

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

Security grade badge for Dev Lead
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/aarontzeng-dev-lead/badge)](https://www.skillsdirectory.com/skills/aarontzeng-dev-lead)

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: dev-lead
description: Orchestrate a feature or PR end-to-end as the lead — dispatch implementation to a delegate family based on task risk, model capability, and remaining quota; run bounded adversarial-review rounds with cross-family reviewers; verify everything independently; and hold the merge gate. Use when the user wants a whole feature/fix delegated and supervised, rather than a single implement or review pass.
---

# Dev lead: dispatch → implement → adversarial rounds → merge gate

This is the orchestration layer over the twelve family skills:
`{claude,codex,agy,opencode,grok,cursor}-implement` and
`{claude,codex,agy,opencode,grok,cursor}-adversarial-review`. It adds no new
mechanics —
it decides who does what, how many rounds, and when to stop. Read the
underlying skill before invoking it; every operational gotcha (sandbox
allow-lists, workspace traps, silent-death modes, status commands that lie)
lives there and is not repeated here.

The lead role itself is portable: all six CLIs can read the same skills
directory (symlink the others' skills paths to Claude's), and the
`claude-implement`/`claude-adversarial-review` skills supply the missing
direction — Claude as a worker for a codex or agy lead. A codex-led run has
been completed end-to-end (the interactive codex CLI as lead, briefed by a
pilot doc, ran capability probes first and delivered through the merge gate).
The distinction that makes this work: **capability is a property of the
RUNTIME, not the brand** — a companion's restricted sandbox may be unable to
commit in a worktree while the same vendor's interactive CLI under an
approved elevated runner passes the gate. What does not port automatically is
host-specific tooling (harness-tracked background tasks, subagent APIs) — a
foreign lead substitutes its own process management.

**Host capability gate — check BEFORE accepting the lead role.** The lead
must be able to run the suite and execute mutations ITSELF; that is the
non-delegable half of the job. A host whose sandbox cannot bind the sockets
the tests need, or cannot lock a worktree's shared git index, can still be a
fine implementer — but as lead it would have to delegate its own
verification, which collapses the independence the role exists to provide.
If the host cannot run the repo's tests and mutations natively, it does not
lead that repo. An explicitly approved, scoped, reproducible elevated runner
counts as host capability when it covers the required suite, mutation
commands, and local git checkpoint operations — record the exact command
class and approval scope in the run log; never silently substitute elevation
for a failed default sandbox.

The lead is this session's model — a skill cannot switch it, so the user
picks the tier before invoking. Do not trust a system prompt's "you are
powered by X" line when lead identity matters (attribution, quota
accounting): read the transcript's per-message model field, which is the
source of truth. Lead work splits into long-context bookkeeping/verification
(the wall-clock bulk) and a few concentrated-judgment moments (dispatch,
finding verification, merge verdict); on a mid-tier session, an optional
frontier-tier subagent at the Phase-3 verdict check buys judgment exactly
where it pays.

## Plan mode — fan out a question, not a change

Everything below assumes the deliverable is a **change**. When it is a
**plan** — a spec, a roadmap, a decision that needs facts nobody has yet —
run the same machinery with three substitutions, and read
[`docs/research-briefs.md`](../../docs/research-briefs.md) first: 23 measured
rules, each carrying the failure that produced it.

1. **Split the problem into falsifiable questions, not topics.** "Investigate
   how X works" invites a plausible synthesis with invented citations. "Which
   file and line performs the project comparison?" does not. Name the settled
   decisions in the brief verbatim, or legs will produce findings against
   choices that already have an ADR.
2. **Demand a completeness argument you can re-run.** Not "say what search
   establishes this is exhaustive" but "give the exact command and the number
   of results it returned; we will re-run it." Measured: this single demand,
   not the question's phrasing, is what turned a one-route answer into a
   seventeen-route enumeration from the same leg on the same question. And a
   demanded argument is still only *checkable* — the pilot's own best
   enumeration carried a false completeness claim, self-rated 1.0.
3. **Dispatch through the existing review adapters.** There is no
   `*-research` skill and there should not be: the runtime adapter is the
   expensive part and it is role-independent. Swap the brief, keep the
   containment.

**Prefer a leg that can execute.** Reading legs find where to look; an
executing leg finds what is actually true there. Give it a scratch directory,
forbid commits and tracked-file edits, and require that any test it writes is
shown to fail against unmutated source before it counts.

**Nothing a leg returns enters the plan unverified.** Fan-out saves the lead's
*search* time, not reading time. A false finding in a review gets challenged;
a false premise in a plan gets built on.

Output contract: legs return facts with citations and confidence. **Legs never
write plan prose.** The lead writes the plan.

## Phase 0 — Intake (no delegation yet)

Refuse to dispatch until the task has:

1. **Acceptance criteria** concrete enough to verify mechanically.
2. **Scope**: the files/directories a correct change should touch.
3. **Risk class** — decides everything downstream:
   - **HIGH**: auth, money, concurrency, data loss, notification delivery,
     anything with an offline/partial-failure path.
   - **MEDIUM**: behavior changes with test coverage, bounded refactors.
   - **LOW**: mechanical changes, test-only, docs-adjacent code.
   - **A repo plan's own dated risk assessment overrides this table** when it
     is more specific — the table is a prior; the plan author saw the actual
     change. (Measured: a change touched notification delivery — table says
     HIGH — but the plan's dated assessment said MEDIUM with reasons; the
     plan was right and delegation worked.)

If a `triage.json` exists, run `"$DEV_LEAD/scripts/triage.py" scope --files <planned paths>`
for a risk floor and lenses; it only raises. The tables still decide; record
the suggestion next to the final decision in the run log. `unmatched_files`
means the local rules have a gap worth fixing. This planned-path form has no
commit identity; Phase 2 records the frozen commit before any review launch.

Survey the code yourself first — **premise-check the task's factual claims**.
The measured incident: a task said "remove the duplicate query" about a query
that was a deliberate safety re-check; the delegate faithfully removed it. A
wrong premise dispatched is a wrong feature implemented. If the repo has its
own plan discipline, the plan document precedes dispatch.

**Premortem — for HIGH risk, and for any task that deletes or disables
existing behavior.** Before writing the task brief, run one prompt against
the plan: *"Assume this change shipped and failed — we are in the
postmortem. List the scenarios we forgot to consider."* This is the
premise-check systematized, and it attacks the one axis nothing downstream
covers: every later gate (adversarial review, mutation testing,
cross-family) reads a DIFF, and a diff structurally cannot show what the
plan wrongly left out or wrongly marked deletable. Two measured shapes of
that blind spot:

- A plan marked live code as "dead code, delete" — the diff just shows an
  unreferenced block removed; no reviewer has grounds to object. The
  premortem's top-ranked failure was the exact thing that block handled.
- Two operations each individually correct composed into a broken runtime
  behavior (a credential read and a rotated-credential write, each
  OS-prompt-gated, produced a double biometric prompt per login). Three
  review legs passed it, because the defect lived in the composition at
  runtime, not in any hunk. "Imagine the user's complaint after ship"
  reaches it; reading the diff harder does not.

Deletion-shaped tasks get the premortem even at MEDIUM: removing behavior
is where a wrong premise is most expensive and least reviewable. LOW-risk
mechanical work skips it — this is one prompt, not a new phase.

Premortem output is hypotheses, not findings. Verify each named scenario
against the actual code before it shapes the brief; what cannot be
verified goes into the task brief labeled as an unverified assumption for
the delegate and reviewers to check — never silently absorbed as a
requirement. Skipping that verification step turns this into an anxiety
generator that bloats every brief with speculative hardening.

## Phase 1 — Dispatch

### Read the roster first

The user may name only adapters ("implement with agy, review with codex +
cursor + opencode"). The roster declares the model and effort for each
adapter, role, and round; it is not a launcher default.

```bash
"$DEV_LEAD/scripts/roster.py" plan --round r1 \
  --implement agy --review codex,cursor,opencode
```

`plan` prints each leg's exact `leg-cmd.sh` arguments. A model the user
names for this round overrides the roster for this round only
(`--implement agy=<model>[:<family>]`) and is reported as an override; it
is not written back. A fix round passes `--round fix`.

A collision `plan` reports — the implementer's family equal to a reviewer's,
or two reviewers sharing a family — is a stop. Substitute a leg and report
which leg changed and why. Never drop a leg silently. An unset leg is the
same stop: ask, do not invent a model.

**A fix round's cross-family requirement is relative to who implemented THAT
round, not to r1** (owner ruling, 2026-09-22). `fix.review` inheriting r1's full leg
set is a menu, not a floor. How many of those legs a fix round of the lead's
own change takes is not a judgment either (owner ruling, 2026-10-01):
`triage.py scope --fix-of <the head the last round reviewed>` sizes it by the
fix's delta, on the ladder in Phase 2 step 3 -- documentation only takes the
lead's own read, a small fix with a failing-before test and a killed mutation
per finding takes one leg, anything else takes the range's minimum. Whichever
legs run come from a family other than the fix's author.

**Compose every launch command with the suite's `leg-cmd.sh`, never from recall.**

```bash
"$DEV_LEAD/scripts/leg-cmd.sh" <adapter> <role> --model <model> \
    [--effort <e>] [--target <dir>] [--base <ref>]
```

(`$DEV_LEAD` is resolved by the same snippet Phase 2 uses for
`freeze-target.sh` — the suite's scripts never resolve against the target
repo's cwd.)

It reads [`data/launch.json`](../../data/launch.json), prints the exact command on stdout and the
adapter's gotchas on stderr, and **refuses the spellings that are actually
got wrong** — an `--effort` flag for a family that puts effort in the model
name, a missing `--effort` on codex's review (which takes it per call since
0.6.28), a missing `--variant` for opencode. Every one of those refusals is a
mistake measured in a single session (2026-09-08). Since 0.6.56 it also
refuses a claude effort outside `low`/`medium`/`high`/`xhigh`/`max`, on review
and implement alike: that CLI only warns about an unknown value and runs at
its default. A claude implement leg also needs `--allow-bash '<the repo's test
command>'`, or its delegate cannot run a single test (claude-implement).

Run it once per leg at dispatch and paste what it prints.

Why a script rather than one more paragraph: the paragraph already existed —
each leg skill opens by telling you to read its runtime file, and the wrong
commands were composed anyway. A script also reads the current file from disk,
while **the skill text in your context is frozen at whatever plugin version was
loaded**; the session that produced those five wrong launches had been handed
old copies, and the corrected text existed in the repo without being what the
lead was holding.

> [!warning] This does not close the stale-context hole, and saying otherwise
> would be the same overclaim twice
> The instruction to run `leg-cmd.sh` lives in **this file**, which is exactly
> the thing that gets injected stale. A session given an old copy never learns
> the script exists and composes from recall as before. Raised by the GPT leg
> of the review of this very change, and it is right: the script fixes "the
> lead did not read the runtime file", not "the lead was handed an old one".
>
> The channel that IS re-read fresh every session is the operator's own
> auto-memory, so the four-leg default and the effort spellings live there too.
> Treat that as the load-bearing copy and this file as the explanation.

**Probe availability first, cheaply — and "cheap" means one real call, never
a listing.** Each family's runtime file has its probe: agy has an AUTH_OK
one-liner (stale logs describe past runs; the probe is the only current
answer); codex has no reliable quota API, so attempt and treat a quota error
as "unavailable this run"; opencode needs no credential, but congestion is its
availability axis — a cheap one-liner answering in seconds means go. A
catalogue is not a probe: `opencode models` kept listing all 27 `opencode-go/`
models, both `opencode-go/muse-spark-*-contributor` entries included, after the workspace's
data-for-training switch was turned off — and every call to those two then
failed with "requires explicit opt in" (measured 2026-09-15). The listing
reflects what exists, not what your permissions let you run; a lead who probes
by enumerating gets a green that the first dispatch turns red. Send one
throwaway prompt and read the reply. The same probe catches the model that
answers with an empty string and no error (`opencode-go/glm-5.3-flash`, three
for three that day) — a listing cannot.

Implementer selection (adapt the tiers to your account's catalogue and your
calibration journal — see
[`docs/calibration-journal.md`](../../docs/calibration-journal.md)):

| Situation | Implementer |
|---|---|
| LOW, mechanical sweep, nobody waiting | free pool — zero quota, runs tests natively; congestion makes turnaround unpredictable, so only when wall-clock is cheap |
| LOW, mechanical sweep, time matters | cheapest capable *paid* tier |
| LOW/MEDIUM, spec is clear | cheapest capable paid tier |
| MEDIUM, needs design judgment | a mid/high paid tier; or a second-pool model whose quota is otherwise idle |
| Reasoning-hard delegated work (a fix round failed on reasoning, not integration) | the frontier tier, maximum effort |
| HIGH risk or ambiguous spec | **the lead implements directly** — delegation adds a supervision layer exactly where supervision is hardest |
| Preferred delegate unavailable | another family. All families down → lead implements |

**Switching families mid-run rewrites the task prompt, not just the
command.** The delegates' test policies differ and are not interchangeable:
one family may only be allowed three pinned test-command spellings (any other
spelling silently kills the run with zero output), another runs whatever the
repo needs, a third needs a per-worktree permission config written before
dispatch. Reusing a task file verbatim across a family switch produces a
silent, output-less death that reads like a code problem and is a prompt
problem. Re-read the target skill's task-prompt section on every switch.

**The sharpest version of that: never hand a delegate a scope it cannot
REACH.** A brief names two things independently — what to look at, and what
the delegate is allowed to run — and it is entirely possible to write a pair
that cannot both be true. The self-contradiction does not announce itself;
the run dies, output-less, looking exactly like a model failure.

Measured 2026-09-07, one session, one lead, three separate legs killed by
three different versions of the same mistake:

- A `nl -ba` read instruction in the preamble. Correct and load-bearing for
  one family; in headless mode on another it is an auto-denied shell call, so
  the FIRST tool call killed the run before a file was read.
- The same instruction carried to a third family whose config denies `*`
  except git — same death, different allow-list.
- **A `git diff <base> HEAD` scope in a brief that forbids shell.** The
  delegate did the only thing left: it tried to READ the range, reaching for
  `.git/worktrees/<name>/logs/HEAD` — outside the `--add-dir`ed directory,
  auto-denied, run over. A git range is not a description of files; it is an
  instruction to run git.

The fix is not a longer brief, it is a per-family one: write the scope in
the vocabulary the delegate actually has. Where shell is forbidden, name the
files explicitly — an eight-line list beats a one-line range, and it is the
only form that survives the sandbox. Where a read command is pinned, confirm
it is on THAT family's allow-list before it goes in the preamble.

**The worktree is missing everything the suite needs that git does not
track, and the delegate will not tell you.** The virtualenv, the `.env`, the
built assets, the fixture cache are gitignored, so a pinned test command
naming any of them cannot run in the worktree at all -- and a delegate falls
back to something else and reports that as green (measured: 2511 passed /
137 skipped against a baseline of 2649). Before dispatch, run the pinned
command in the worktree yourself, provision what it needs, and compare every
reported total to your baseline digit for digit. Three rules, each paid for
in [`references/worktree-provisioning.md`](references/worktree-provisioning.md):

- **Re-run the specific tests a round turns on**; matching totals do not
  clear them (a mock left unbound in a sandbox without network passed there
  and failed here).
- **Never symlink the lead's copy of a shared directory** into the worktree;
  a delete goes through the link (645 of 693 `node_modules` entries gutted).
  Give each worktree its own install or a hardlink copy.
- **"Provision" is not "copy the real one."** The delegate gets a sanitized
  minimum and nothing secret; the lead's own verification run uses the real
  file. A suite that cannot start without a real secret is a finding about
  the repo, not a reason to ship the secret into a sandbox.


Reviewer — the cross-family rule is absolute (implementer's family never
reviews its own change). Review is the leverage point, so it gets the
strongest tier available:

| Implementer | Reviewer(s) |
|---|---|
| Gemini family | GPT, Claude, or a named free-pool model |
| GPT family | Gemini, Claude, or a named free-pool model |
| named free-pool model (Nemotron/Meta/…; **NOT DeepSeek** — measured 2026-09-16, it is absent from this account's free pool and consent-gated on the paid one) | GPT, Gemini, or Claude — all cross-family by construction |
| stealth free-pool model (family undisclosed) | cross-family is UNVERIFIABLE — any reviewer might secretly share its family. Prefer a named-family implementer when accounting matters; otherwise take two reviewers from two different KNOWN families |
| the lead itself | any family that is not the lead's. Never review the lead's work with the lead's own family — even through a different CLI |
| HIGH risk, any implementer | **two independent reviewers from two families** — measured: two families independently converging on the same root cause was itself the strongest signal the finding was real |
| MEDIUM risk, when a free leg is available | **take the second reviewer anyway.** Measured: on a MEDIUM change, two families each returned 2 real defects with zero overlap. Convergence is the strong signal when it happens; disjoint coverage is the ordinary case, and a zero-quota second leg costs only wall-clock. Run them concurrently against the same frozen commit |
| Re-review of a prescriptive fix round | a mid tier is enough — the changes follow written findings; save the frontier tier for open-ended hunts |
| **Owner standing ruling (2026-08-30, this account)** | **default WIDE, not minimum**: beyond the accounting leg, take the free/cheap extra legs by default — a Laguna (OpenRouter :free) or free-pool leg, plus a cheap GPT tier (e.g. luna) challenge leg — whenever wall-clock allows. The owner asked "why only two legs" twice in one day; the minimum table above is the floor, not this account's default. Distinct briefs per leg, as always |

**When you spend a second or third leg, change the BRIEF, not just the
model.** The table above is the accounting rule, not the coverage rule.
Measured: three legs over one design ruling, each given a deliberately
different job — one walked execution sequences, one was asked to challenge
whether the approach was right at all, one audited for text that was
superseded but still read as live. Their principal findings overlapped zero
percent, and each leg found the only instance of its own class. The roles
worth splitting, in the order they tend to pay: **sequences**, **challenge**
(never phrased as "find defects"), **consistency**, **is-it-still-true**, and
**falsifiability** — can each test here actually FAIL? Give that last one to a
leg whenever the change ADDS a guard or a gate, because a green suite is
equally convincing whether or not the suite is able to go red (measured: on one
three-leg round it was the only lens that found anything, and it found five;
see [`docs/methodology.md`](../../docs/methodology.md) §2).

**A brief is written PER FAMILY. It is not a template (measured 2026-09-07).**
The lenses above vary the question; the PREAMBLE has to vary with the sandbox,
because the four adapters do not agree on what a delegate may run. A lead
wrote one preamble for a 4-leg round and copied it into all four briefs. It
carried terra's proven operating condition — "read files with `nl -ba <path> |
sed -n`, so every citation carries a real line number" — which is right for
codex and wrong everywhere else:

- **agy** auto-denies an unlisted shell command in headless mode and kills the
  run with ZERO output. The leg died in about 90 seconds having read nothing.
  The runtime file already records this failure shape; the brief walked into it.
- **opencode** was under a config denying `bash: {"*": "deny"}` except five git
  reads. It survived only because a denial comes back to that model as a
  message and it fell back to its own file tools (`auto-rejecting` count 0) —
  luck, not design.
- **codex** and **cursor** were fine, which is exactly why the mistake is easy
  to miss: half the round works.

So: write the lens once, the preamble four times. Say in each what that
delegate may actually run, and say that anything else ends the run. And when a
leg comes back empty in under two minutes, suspect the brief before the model —
`grep -c auto-rejecting` and the agy stderr both name the denied command.

**Rewriting a brief mid-round voids that leg's scaffold bracket.** Same
session: the lead fixed the three broken briefs while one leg was still
running, and re-recorded the digests. The before/after comparison for that leg
then proved nothing, because the "before" had been overwritten. The change was
harmless — it removed an instruction the leg had already consumed from stdin —
but the evidence chain was gone. Kill and relaunch, or record in the run log
that the bracket is void for that leg and why. Silently re-recording the digest
turns a proof into a decoration.

Quota economics: when one model is scarce, spend it on **review**, not
implementation — review leverage is higher, and implementation has more
substitutes.

### The brief's premises are the one thing no reviewer checks (measured 2026-09-05)

Every gate in this suite reads a diff or a spec that the LEAD wrote. A false
sentence in the brief is therefore invisible to all of them at once — and the
more legs you run, the more confident the false sentence looks.

Measured, in a repo where price history feeds portfolio valuation: the lead's
plan asserted that one provider flag returns the raw as-traded price. It does
not; that series is already adjusted for splits. Three families reviewed the
change, fifteen findings were verified and fixed across two rounds, the suite
went from 2936 to 2960 green — and every one of those tests encoded the same
wrong premise, because the fixtures were built from the brief. The defect
(every pre-split position undervalued by the split factor) shipped to main and
was found afterwards, by one query against real data:
`select close, adj_close from stock_prices where symbol='AAPL' and time near the split`.

So, for any brief that rests on what an external system returns:

- **State each premise as a claim with a check next to it**, not as background
  prose: "X returns Y — verified by <command>, <date>". An unverified premise
  goes in labeled as unverified, which at least lets a reviewer aim at it.
- **Run the check before writing the brief**, not after the merge. One query or
  one API call against real data costs a minute and is the only gate that reads
  the world instead of the diff.
- **A green suite built from a wrong premise is evidence of nothing.** Its
  fixtures inherit the error; mutation testing confirms the tests pin the code,
  not that the code is right. When the change is about how an outside system
  behaves, put one assertion against real data in the acceptance criteria.
- Do this even when the premise is "obviously" true. The measured one had been
  stated in a design doc, quoted in three review briefs, and repeated in commit
  messages before anyone looked.

### Parallel implement legs (measured 2026-09-05)

Two write legs can run at once — different families, different slices — but
only when the slices share **zero files**, and the way to get there is not to
hope: the lead writes and COMMITS the shared layer first (types, API contract,
the shared engine), and every delegate worktree branches from that SHA. On the
measured run (backend + shared engine committed by the lead; then a Gemini leg
on `mobile/` and a Grok leg on `frontend/` in parallel) both merges were
conflict-free by construction, not by luck. What changes when there are two:

- **Everything per leg is per leg.** Its own worktree, its own `snapshot-refs`
  baseline, its own baseline suite run *in that worktree*, its own review legs
  (cross-family is decided against THAT leg's implementer: the Gemini slice got
  GPT + free-pool + Grok, the Grok slice got GPT + Gemini + free-pool), and its
  own fix round. Do not share a review brief across slices — the lenses are the
  same, the file lists are not.
- **One waiter per leg**, each backgrounded on its own; a single poll loop
  waiting for "both" cannot tell which finished. And read the family's runtime
  file for what a finished leg looks like: `cursor-agent` buffers its whole JSON
  result until exit, so a 0-byte output file means *running*, not dead — the
  lead misread three legs as dead this way and relaunched duplicates.
- **Merge serially, gate once more.** Land the legs one at a time onto the
  integration branch (`--no-ff`, so each leg's history stays legible), then run
  ALL suites on the merged tree before it touches main — two green legs are not
  a green merge, they are two green legs.
- **The parallel brief carries the lead's premises twice as far.** A wrong
  factual claim in a shared brief lands in both slices before any reviewer sees
  either. Measured: the brief asserted a helper "needs no actions because a
  split never changes which symbols are held"; the delegate complied; the
  Grok review leg falsified it with a three-line counter-example. When the
  reviewer proves the brief wrong, the fix-round brief says so — "this was the
  lead's error, not yours" — because the delegate is about to be told to undo
  work it was ordered to do.

## Phase 2 — Rounds (bounded)

`ROUNDS_MAX = 3` implementation rounds by default (R1 + two fix rounds); the
user can set it at invocation. Each round:

**A review that did not come from an implement round still has rounds.** When
the user simply asks for a two- or four-leg review of work already in the tree —
often work the LEAD wrote — the same cap and the same stop conditions apply, and
nothing else here changes except who is holding the pen. Say the cap out loud at
the start; without it a review-fix-review loop has no defined end and stops when
the lead happens to feel finished, which is not a criterion. Measured
2026-09-01: a standalone two-leg review of a ~130-line lead-written script ran
two rounds and would have run a third on no principle at all.

1. **Implement/fix** in the worktree (same worktree across rounds, new
   commits on top). R2+ task prompts quote each verified finding **verbatim,
   with why it is real and what fix is required** — this shape fixed
   everything first-try in live runs; vague "address the review" has no track
   record.

   **Background the WORK, not the launch.** Whatever the host uses to notify
   you that a background task finished must be wrapped around the thing that
   actually takes the minutes. A foreground CLI (`agy`, `opencode run`,
   `codex exec`) already is that thing — hand it over directly and never add
   an inner `&`/`nohup … &`, which makes the host task exit at launch and
   discards the notification. A launcher that returns immediately (the codex
   companion's `task --background`) needs a second backgrounded step that
   blocks until the job is terminal; each runtime file names its own waiter.

   **A multi-leg round is therefore one backgrounded call PER LEG, not one call
   that starts them all.** This is the operative consequence, and it names the
   reason a lead reaches for the inner `&` at all: wanting four legs running at
   once, `cmd1 & cmd2 & cmd3 &` inside a single foreground call looks like the
   obvious way there, and it is exactly the shape the rule above forbids — that
   call returns in milliseconds, the host marks it complete, and the legs are
   orphaned with nothing tracking them. Measured 2026-09-01, one session: a lead
   who had read this section did precisely that three times; every leg finished
   30-100 minutes before it noticed, each time only because the user asked. The
   same session then dispatched two legs as two separate backgrounded calls and
   was woken by the host on the first one.
   Measured 2026-08-25, one session: three consecutive rounds finished 14, 20
   and 40+ minutes before the lead noticed, every time only because the human
   asked — and two of those were delegate refusals the lead had explicitly
   asked for and should have acted on at once. The delegate was not slow; the
   lead was not listening. In the same session an `agy` leg launched with an
   inner `&` reported "completed" in under a second and had actually died.

   Do not substitute a hand-rolled poll loop between turns. It is a live task
   the user can interrupt, and an interrupted poll is indistinguishable from
   the job ending.

   **Dispatching a leg to a SUBAGENT inverts that last rule — say so in the
   prompt.** A subagent driving an external CLI is a *leaf*: nothing will wake
   it when the CLI exits, because the host's completion notification goes to
   the session that spawned it, not to the spawned one. So a leaf that ends
   its turn to "wait for the monitor" is not waiting — it has silently
   abandoned the run, and only a human noticing gets it back. For a leaf the
   blocking poll the lead must avoid is exactly the right answer, provided it
   lives *inside a single tool call* (`while kill -0 $PID 2>/dev/null; do
   sleep 15; done`, generous per-call timeout, another such call immediately
   if the first times out) rather than across turns. Spell this out in the
   dispatch prompt; the review skills describe how to *launch*, and a leaf
   that follows only that stops one step early.

   Measured 2026-08-31, one session: across three 4-leg rounds this cost five
   manual re-prompts — opencode, codex and cursor legs each ended a turn on
   "waiting for the background monitor", and one leg needed two nudges before
   it stopped reaching for the host's monitor tool and wrote a real loop. Two
   phrases predict the failure and belong in the prompt as explicit
   prohibitions: *"I'll report once the notification arrives"* and *"still
   running, continuing to wait"*. Neither is a valid end state for a leaf.

   **Measured effective 2026-09-01, for SUBAGENT dispatch specifically**: a
   4-leg round run through four subagents, each prompt opening with the leaf
   paragraph above, took **zero** manual re-prompts — every leg blocked to
   completion on its own (160 s to ~14 min). Same lead, same four adapters,
   same host as the five-nudge session. Carry the paragraph into the prompt;
   do not assume the skills alone reach a leaf.

   **But the stronger move is to not create a leaf at all.** A peer lead ran
   two 4-leg rounds the same day with zero re-prompts and no leaf paragraph
   anywhere, because it launched each CLI directly as a backgrounded job from
   its own session: the host's completion notification then comes back to the
   session that can act on it, and this failure mode cannot arise. Reserve
   subagent dispatch for when you actually need the leg's tool-call traffic
   kept out of your context; when you don't, dispatch directly. Do not read
   the measurement above as "the paragraph is what makes 4-leg rounds work" —
   it is what makes them work *once you have already chosen* the shape that
   can strand a leg.
2. **Lead verifies independently** — never from the delegate's self-report.
   Order matters when the work comes back uncommitted (some sandboxes cannot
   commit in a worktree at all): FIRST inspect the working tree itself
   (`git status --short`, `git diff` — a `$BASE...HEAD` range on an
   uncommitted tree is empty and reads as a clean scope check, a measured
   false green), re-run the tests, THEN the lead stages in-scope paths and
   makes the checkpoint commit, and only then do ranged checks,
   commit-message hygiene, and **mutation-proof every new regression test**.

   **Changing a statement OR A PREDICATE? grep for its copies BEFORE you
   edit.** The same sentence usually lives in three places — the implementation
   comment, the header/API doc, and the operator-facing log line — and fixing
   the one you happen to be in leaves the others contradicting it. Measured:
   the same correction was made three times across three review rounds, each
   round catching one more surviving copy. Tests never catch this class.
   `grep -rn` a distinctive phrase from the sentence you are about to change,
   fix every hit in the same edit, and say in the commit how many there were.

   **A wrong test predicate copies exactly the same way, and the rule used to
   miss it because it only said "statement".** Measured, a later round: a probe
   decided its verdict with `"Permissions Violation" not in r`. That is wrong —
   a REJECTED LOGIN also lacks that string, so it reported ALLOWED — and the
   expression appeared four times in one file plus once in a sibling. Fixing
   the two instances review named would have left twelve required-positive
   checks with the same hole. Here the rule's own line, "tests never catch this
   class", was literally true: every suite was green with all four copies
   broken, because the copies WERE the suite.

   So before changing any decision expression — a verdict, a guard, a
   comparison a test's result turns on — `grep -rn` the expression itself, not
   just its surrounding prose. Then prefer collapsing the copies onto one
   function over correcting each: the count is what makes the next occurrence
   impossible, and correcting N copies leaves N places for the next person to
   fix N-1 of.

   **A working-tree restore invalidates every verification behind it,
   including the commit message you already wrote.** Measured 2026-08-30: a
   `git checkout --` (aimed at a concurrent agent's stray edit) also reverted
   the lead's own uncommitted fix; the checkpoint commit then landed with a
   message describing behavior that was no longer in the tree. Nothing
   downstream catches that — review reads the diff, and the diff was honest
   about what it contained; only the prose was wrong. So after ANY restore,
   stash, or reset in the worktree, re-read the diff against the message,
   re-run the suite, and re-run the mutations, all against the **committed**
   tree. Related, from the repo side: never `git checkout` to undo your own
   uncommitted work while another agent shares the checkout.

   **Writing a NEW statement? Name what would make it false.** The grep rule
   above catches a sentence that went stale; it cannot catch one that was false
   on arrival, or one that was true when written and went false because the
   WORLD moved (a vote, "the current patchset", a count of open items). Run
   `python3 "$DEV_LEAD/scripts/claim-audit.py" "$WORKTREE" "$BASE...HEAD"` and
   answer its question per hit: **if this sentence were false, which test goes
   red?** Naming a test that runs nearby is not an answer. It is an attention
   cue, not a control: it exits 0 either way, and a silent run is not evidence
   that claims were checked. Commit what the audit changed before the target is
   frozen, and mutation-proof any test it produced. The three shapes of false
   statement, the monotonicity test for a perishable fact, how to read the
   count, and the two shapes only a cross-family reviewer catches are in
   [`references/claim-audit.md`](references/claim-audit.md).


   Mutation mechanics live in
   **[`references/mutation-runbook.md`](references/mutation-runbook.md)** —
   read it before this step. Every clause in it was paid for with a live
   false result: a harness that reported a mutant killed when it was not, a
   restore that destroyed the implementation, a stale binary that made
   correct code look broken. The three that bite earliest: **commit before
   any mutation** (a restore on an uncommitted tree erases the work),
   **never `&&`-chain the test run into the verdict echo** (a killed mutant
   exits non-zero — that IS the success signal), and **put the marker check
   in its own command** (a timeout kills the restore, and the mutant stays).

3. **Adversarial review** per the reviewer table, against the same immutable
   `$BASE` — which is `git merge-base <target-branch> HEAD`, NOT the target
   branch itself (see [`docs/methodology.md`](../../docs/methodology.md) §7;
   the review skills carry the pre-launch
   `git diff --stat "$BASE" HEAD` guard). **The reviewed directory
   must be FROZEN for the whole run** — a detached worktree at the exact
   commit, that nothing else touches. A reviewer reads the working tree, not
   your commit: a measured round ran mutation testing in the same worktree
   mid-review and the reviewer opened a CRITICAL on a mutated, non-compiling
   file. One directory per reviewer, no lead activity inside it. Use the
   tested helpers rather than hand-rolling this — it is the repo's
   highest-risk shell, and every bug ever found in it was in a hand-rolled
   copy:

   ```bash
   # The helpers live in the SUITE's tree; cwd is the TARGET repo. A bare
   # `scripts/…` resolves against the target and exits 127 — which lands you
   # in the hand-rolled copy this paragraph just warned about.
   DEV_LEAD=${DEV_LEAD_ROOT:-$(ls -d "$HOME"/.claude/plugins/cache/dev-lead/dev-lead/* 2>/dev/null | sort -V | tail -1)}
   for helper in freeze-target.sh verify-target.sh; do
     [ -x "$DEV_LEAD/scripts/$helper" ] || { echo "dev-lead root unresolved (no $helper) — set DEV_LEAD_ROOT to your checkout"; exit 1; }
   done

   REVIEW_HEAD=$("$DEV_LEAD/scripts/freeze-target.sh" "$REPO" "$SHA" "$FROZEN_DIR")
   "$DEV_LEAD/scripts/verify-target.sh" "$FROZEN_DIR" "$REVIEW_HEAD"   # before AND after
   ```

   **Triage the immutable target before launching every review round,
   including fix rounds.** Run
   `"$DEV_LEAD/scripts/triage.py" scope --base "$BASE" --target "$FROZEN_DIR"`
   (or `triage.py change <number>` for a Gerrit change; a fix round of your
   own change adds `--fix-of`, below), then launch at least
   its `min_review_legs` from distinct families using the lenses it lists.
   MEDIUM's minimum of two is unconditional here: take the second reviewer
   anyway -- with one exception, the fix round of the lead's own change.

   **A fix round of your own change adds `--fix-of <the head the previous
   round reviewed>` to `scope`** (that head's triage record must exist;
   `change` has no such option, so a fix of your own Gerrit change is triaged
   with `scope` on its frozen clone), and the record's
   minimum becomes the fix's rung (owner ruling, 2026-10-01, after one change
   took four rounds and another three):

   | the fix's delta | rung | legs |
   |---|---|---|
   | documentation only (`.md`, `.markdown`, `.rst`, `.adoc`, not an agent instruction file -- `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `QUANTA.md`, `SKILL.md` and their variants, `*instructions*` / `*prompt*` files, anything under `.claude/`, `skills/` and the other agent directories README lists; the rules file's `wording_globs`, when set, replaces this default), or only the commit message | wording | none: the lead's own read |
   | within `small_delta_lines`, and every fixed finding has a test that failed before the fix and a mutation the lead killed, stated as `--fix-tested '<which tests, which mutations>'` | tested | one cross-family leg |
   | anything else, or a delta a `delta_triggers` rule raises to HIGH | full | the range's minimum (at least HIGH's for a trigger) |

   A comment inside a code file is not detected as wording: telling a
   comment from code per language is a guess, so such a fix is at least the
   tested rung; a binary, mode or move change has no lines to size and is the
   full rung. `--fix-tested` and `--blocker` are your statements: the record
   and `round-check` carry them verbatim, and nothing checks them. The delta is taken between the two reviewed patches, the way
   `change` compares patch sets, so an amended or rebased fix is sized by
   what it changed and not by the base it moved to. From the third fix round
   on, a full round needs `--blocker '<the finding>'` (Convergence, under the
   stop conditions). `--fix-of` must name the head of the latest round
   recorded for the change; an older head is refused, since the count would
   restart. A head amended before its review keeps its record, and removing
   that record is how to say it was never reviewed. A `scope` without
   `--fix-of` (or a `change`) will not replace a fix-round record. The gate
   binds rounds sized with `--fix-of`: triaging a fix as a change of its own
   takes the full legs and no gate, so the convergence rule there is yours. `round-check` and `leg-cmd.sh` read the same record,
   so a lower minimum here needs no `--no-triage`; the report names the rung.

   `leg-cmd.sh … review` reads the reviewed HEAD from `--target`, or
   from the caller's cwd when the adapter has no `{TARGET}` slot. `--head` is
   only an assertion and must resolve to that same HEAD. Launch cursor-type
   adapters from inside the frozen worktree, because they review their caller
   cwd. When a record has `base`, a launch's `--base` must match it; otherwise
   rerun `triage.py scope --base <this base> --target <frozen dir>` first,
   with the same `--fix-of`, `--fix-tested` and `--blocker` on a fix round
   (leg-cmd.sh prints that command, quoted, from the record; for a
   `change` record it prints `triage.py change <number>`).
   Going below the minimum is `--no-triage '<reason>'` only with the owner's
   word, and records that exception. After the legs return, run `triage.py
   round-check --head "$REVIEW_HEAD" --target "$FROZEN_DIR" --leg
   <adapter>[:<family>]=<log> [--expect <verdict-regex>]` for every leg before
   treating the round as complete.

   A repo that committed CRLF files and later added `eol=lf` shows them as
   ` M` on every fresh checkout. Both scripts excuse exactly those files --
   bytes and mode identical to the commit ([`renorm-only.sh`](../../scripts/renorm-only.sh)) -- and
   freeze prints which. The per-leg skills' raw `git status --porcelain`
   brackets predate that excuse and will show those files; the scripts are
   the authority.

   **Tear the frozen directories down only after every leg has actually
   returned, and read the leg's own exit line rather than the wrapper's.**
   A background launcher usually runs with its cwd inside the frozen
   directory; removing that directory out from under a still-open shell
   makes the wrapper fail on something unrelated — measured, a `pwd` after
   teardown produced `getcwd: cannot access parent directories` and the
   harness reported the task as exit 1, while the leg's own line in the
   same output read `exit=0` and its report was complete. A leg declared
   dead by its wrapper's exit code is the same class of mistake as a leg
   declared empty by one grep: the signal you read was not the signal you
   wanted.

   Findings are
   hypotheses: verify each against the code, reject false ones explicitly,
   record **every** finding in the run log. **A rejection carries evidence of
   the same grade the finding needed** — the `file:line` that refutes it, or
   a command actually run. "I judged it wrong" is not a rejection; it is an
   unaudited veto at the one step where the lead reviews nobody but itself.
   **What the lead fixes directly never gets reviewed, and that is where the
   next defect is.** The fix round runs after the legs have returned, so the
   lead's own edits — the ones the skill explicitly encourages for small,
   precisely diagnosed defects — enter the merge with zero cross-family eyes on
   them. Measured: in one round the only BROKEN verdict any leg returned was
   about a test the LEAD had written after the delegate finished, and it was
   right. So the lead's fixes get a re-review sized by `triage.py scope
   --fix-of` (the ladder above): only a documentation fix goes without a leg, and a code
   fix within `small_delta_lines` gets one leg only when the mutation standard
   you hold the delegate's work to is met and stated. Say in the run log which parts of the final
   diff no leg ever saw.

4. **Route**: no verified HIGH findings → merge gate. Verified findings →
   next round. Small, precisely diagnosed defects (a fake test, a stray
   trailer) the lead fixes directly in-place — a delegation round for a
   one-line fix costs more than it protects.

   **A fix exercised for real may be pushed before its re-review** (owner
   ruling, 2026-10-01): the build, the CI job, the board. It moves the order,
   not the review: the re-review still runs at the rung `--fix-of` gives, and
   the report says that the push came first and what ran.

**Stop conditions** (report instead of looping):

- Cap reached with verified HIGH findings open → keep the worktree, present
  the findings history, let the user decide. Do not merge. (A blocker in a
  fix round of the lead's own change gets another round under Convergence
  below; the run log says the cap was passed and for which finding.)
- **Convergence: after two fix rounds, findings that are not blockers do not
  open another full round** (owner ruling, 2026-10-01: in one change rounds
  two and three each found one real defect and later rounds only corner
  cases, and nothing said when to stop). Fix them under the lower rungs of
  the ladder in step 3, or record them in the commit message as known
  limits, and say which. A blocker always gets another round: `triage.py
  scope --fix-of` refuses a third full fix round without `--blocker '<the
  finding>'`, and records the statement.
- A fix round introduces a **new** HIGH finding (fix churn) → the spec or the
  delegate is wrong for this task; lead takes over or stops.
  **When the lead IS the implementer, that escalation inverts**: "lead takes
  over" is a no-op, and the party making the errors is the one who would take
  over. Delegate the fix round, or stop and hand the findings to the user.
- **Round N's findings land inside round N−1's fixes** → stop patching. This is
  not the same as fix churn: each fix was correct as far as it went, and the
  next reviewer simply found the half of the problem the fix did not reach.
  Measured 2026-09-01, one 130-line script: "do not leave a partial file on
  error" was fixed without covering SIGKILL, which does not raise; a strict
  validator was added for the incoming snapshot and none at all for the
  baseline the same function compares it against. Both were second halves,
  found one round later, by a different family. When the findings start landing
  in the previous round's diff, the change is being grown by accretion — rewrite
  the unit from its requirements instead, and review THAT.
- The same finding survives two fix rounds → the task prompt is failing to
  transmit it; lead fixes it directly.
- The same finding CATEGORY keeps reopening against approximation-shaped code
  → the review property is unbounded, not the code unfixable. Declare the
  approximation's scope in the docstring and re-scope the review to it
  (measured: four rounds of one-more-nesting-level findings converged to a
  real in-scope catch and then an approve, the round after the boundary was
  written). **Write the boundary before the review is FIRED, not after it
  comes back** — the lead always knows the boundary; the reviewer is the one
  who does not. It applies to more than parsers: any check that answers a
  question about the world through a proxy is approximation-shaped and needs
  its scope stated.

## Phase 3 — Merge gate

Assemble the verdict from the run log: rounds used, implementer/reviewers per
round, findings (verified/rejected/fixed) with their fate, final test
results, diff stat against `$BASE`.

**Re-verify the target branch's IDENTITY at the gate, not just its
cleanliness.** Measured: the user rebased the main checkout mid-round; merged
versions of earlier commits came back with new SHAs, `--ff-only` refused —
that refusal is the guard working; never switch to `--no-ff` to get past it.
Rebase the branch onto the moved target and re-run the ff. The human owns the
main checkout; assume it moves.

**Which gate is in force is what `roster.py show` prints, not memory and
not the raw JSON field** (`merge_gate.mode`, added 2026-09-23 on the owner's
ruling; `roster.py gate <user|lead> --why "…"` changes it). Absent means
`user`, and so does any roster `check` would refuse: `show` then prints
INVALID and the person's gate, whatever the field says. Read it at the start of Phase 3 — a lead that assumes the
default lands nothing on a machine configured for `lead`, and a lead that
assumes `lead` merges work the person wanted to see. **Neither mode changes
what counts as green**: a verdict with an unanswered review round, a failing
test, an open blocker or an unverified finding goes to the person in both.
A repo's own contract wins where it is stricter (a team contract, the user's
CLAUDE.md).

- **`merge-gate=user` (default)**: present the verdict and the diff summary;
  merge (fast-forward), push, and tear down the worktree only after the user
  says proceed. The human approves the RESULT — the verdict and the diff —
  not the intention; once approved, landing it is the lead's job in that
  same run, with no second "may I push?" (rule changed 2026-09-11: the ask
  had been answered yes every time and gated nothing the verdict did not).
  Push to the ref the project's contract names — a review ref, a topic
  branch, or the target branch where the contract allows it — never a
  force-push, never someone else's branch — and report the resulting ref,
  change or PR number immediately.
- **`merge-gate=lead`** — the standing form of the same grant, from the
  roster: on a fully green verdict the verdict IS the approval — merge,
  push, tear down, and report what landed and why it qualified. Any
  non-green condition falls back to the user gate. Report says the mode was
  `lead` and names what made the verdict green, so the person reading it
  afterwards can audit the decision they delegated.
- **`auto-merge`** — the per-run version, when the user grants it at
  invocation on a machine configured `user`. Same conditions; the grant is
  per-run, never remembered. A per-run "ask me anyway" likewise overrides a
  configured `lead` for that run: the person can always take the gate back.
- If the session model is not the strongest available, an optional
  independent verdict check: spawn a frontier-tier subagent with the run log
  and the final diff, asking only "does anything here disqualify a merge?" —
  a cheap second judgment exactly at the decision that is hardest to walk
  back.
- Delegates never push, in every mode, no exceptions. How that boundary is
  held varies: a machine allow-list on agy, a machine config on opencode,
  and instruction level on claude, codex, grok and cursor — which is why all
  four carry the fail-closed refs snapshot diffed at handoff as the evidence
  ([workflow.md](../../docs/workflow.md) carries the per-adapter table).
  The lead's push above is the only one, and it happens after the
  approval, never before a green verdict.

## Run log

Keep one per run (`mktemp -d`, e.g. `$RUN_DIR/run-log.md`), appended as
events happen, not reconstructed afterward: dispatch decision and why; per
round — task file path, delegate, commits, test results, review findings with
verified/rejected/fixed status **and, for each rejection, the evidence that
refutes it**; stop-condition hits; the final verdict. The final report to the
user is written from this log. If the run is interrupted, the log plus the
preserved worktree is the resume state.

Record every delegate dispatch as three separate fields, because they
diverge and the cross-family accounting reads only the last one:

- `runtime_adapter`: claude / codex / agy / opencode / grok / cursor — the
  CLI driven
- `served_model`: the model that actually answered — VERIFIED per the
  runtime file (some adapters silently substitute tiers), not the id you
  passed
- `model_family`: the value from [`data/families.json`](../../data/families.json)
  — what the reviewer-pairing rule is checked against. Read it there rather
  than from a list in this file: a partial roster here once omitted nine
  accounting-valid families, and a lead logging a legitimate Grok or Kimi leg
  as `unknown` wrongly concludes a valid cross-family pair is not one, because
  `unknown` (stealth models, `accounting_valid: false`) can never satisfy the
  rule

## What this is not

Not a way to run more agents for their own sake — a task small enough for one
direct implementation should get one (the implement skills say the same). The
workflow earns its cost when the change is big enough that independent
implementation and cross-family review genuinely reduce risk, or when the
user wants the feature produced while the session works on something else.

Files in this skill

  • SKILL.md53.5 KB
  • references/mutation-runbook.md10.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.