pan-peer-review · git:20260725.e40081f · 2026-07-25 · sha256 9ba3e0850d405ad7

pan-peer-review git:20260725.e40081fA

Immutable. This exact content is served forever at /api/v1/blob/9ba3e0850d405ad7.

---
name: pan-peer-review
description: "Workflow: spawn an independent adversarial reviewer on a different model to verify or refute your own findings. EXPENSIVE — invoke only when the operator explicitly asks for a peer/second-opinion review."
triggers:
  - peer review my findings
  - get independent feedback
  - second opinion from another model
  - have another model review this
  - adversarial review of my analysis
allowed-tools:
  - Bash
  - Read
  - Write
---

# pan peer-review — independent second opinion from another model

Spawn a conversation on a **different model family** to adversarially verify or
refute an analysis you produced, then read its findings back. Use it when a
conclusion is expensive to get wrong: a root-cause diagnosis about to become a
PRD, a refactor plan, a security claim, a "this is safe to merge" call.

## ⚠️ Operator-invoked only — never launch this on your own initiative

**Do not start a peer review because you think your work would benefit from
one.** A peer review spawns a second full agent that reads source, burns a
frontier-model context, and runs for many minutes. That cost is the operator's
call, not yours.

Launch only when the operator explicitly asks — "get a second opinion", "run
this by another model", "have K3 review it", "peer review this". If you believe
a review is warranted and they have not asked, say so in one sentence and let
them decide.

Corollary: never chain reviews. One reviewer, one pass. If the reviewer
disagrees with you, bring the disagreement back to the operator rather than
spawning a third model to break the tie.

## Why a different model, and what "independent" buys you

A reviewer on the same model as the author tends to agree — it reconstructs the
same reasoning from the same priors. The value comes from a different family
reading the same source: Opus/Fable reviewing GPT work, K3 reviewing Claude
work, GPT reviewing Claude work.

Pick the reviewer by contrast with whoever produced the analysis:

| Author | Good reviewer |
| --- | --- |
| Claude (Opus/Fable/Sonnet) | `k3` (Kimi), `gpt-5.6-sol` |
| GPT | `claude-opus-5`, `k3` |
| Kimi | `claude-opus-5`, `gpt-5.6-sol` |

Never pass `--harness`. Harness routing is config-owned and the operator sets it
deliberately; `--model` is the only routing flag this workflow uses, and only
because the operator asked for a specific reviewer.

Leave reasoning effort alone. It inherits `high`, which is the right tier —
never raise it to `xhigh`/`max` for a review.

## The workflow

### 1. Write the brief to a file — never into the focus

The `pan handoff` focus is hard-capped at 500 characters. A real review brief is
thousands. Write it to a file in the reviewer's future cwd and let the focus
point at it.

A brief that produces a useful review has these parts:

- **Adversarial framing, stated first.** "Assume each claim may be wrong. A
  claim that survives refutation is worth more than agreement. Do not soften
  findings to be agreeable." Without this you get a politeness echo.
- **Read-only rules.** No edits to source, no commits, no `pan` commands, no
  POST/DELETE. The reviewer writes exactly one file: its findings.
- **A glossary** of every term of art before you use it — the reviewer has none
  of your conversation's context.
- **Absolute paths for evidence outside the worktree** — live workspaces, logs,
  config, API endpoints. The reviewer cannot find them otherwise.
- **Each claim stated separately**, with the exact file:line it rests on, the
  evidence you used, and the fix you propose.
- **Per-claim questions that invite refutation** — "does the fix actually
  terminate the loop?", "what is the blast radius?", "would this regress the
  monorepo path?". Generic "please review" produces generic output.
- **Cross-cutting questions**, including at least one that asks for things you
  did *not* find: "search for every other site with this pattern and report any
  beyond the ones named here."
- **An explicit output contract** — a verdict vocabulary (CONFIRMED /
  PARTIALLY CONFIRMED / REFUTED / CANNOT VERIFY), where to write findings, and
  a request to also summarize in-conversation.

### 2. Create a detached worktree

The reviewer needs the source, isolated from your working tree. Spawned agents
must never get the primary worktree as their cwd.

```bash
git worktree add --detach /home/eltmon/Projects/hoff-<slug> main
```

`--detach` is required: a plain `git worktree add <path> main` fails with
`fatal: 'main' is already used by worktree at ...` whenever main is checked out
somewhere, which on a dev machine is always. Detached HEAD is correct here —
the reviewer never commits.

Then write the brief into that worktree.

### 3. Launch the handoff

```bash
pan handoff --model <reviewer-model> --cwd /home/eltmon/Projects/hoff-<slug> self \
  "Read REVIEW-BRIEF.md in your cwd FIRST and follow it exactly. You are an INDEPENDENT ADVERSARIAL reviewer — verify or refute each claim against real source and critique each proposed fix. Read-only. Write findings to FEEDBACK-<model>.md."
```

`self` must come before the focus text. Omitting it makes the CLI read your
focus as a conversation name and fail with `Conversation not found`.

**The command can exceed a two-minute tool timeout while the handoff document is
authored — that is normal and does not mean it failed.** Either run it with
`run_in_background: true`, or let it time out and verify the spawn afterwards:

```bash
tmux -L overdeck list-sessions | grep conv-
```

### 4. Correct the frame — the step everyone skips

`pan handoff` seeds the new conversation with an **authored handoff document
describing your session's state and open work**. It does not deliver your focus
as an instruction. The reviewer therefore wakes up believing it is *you,
continuing your work* — and if your open-work list said "launch a peer review",
it will try to launch one, recursively.

Check what it actually received before assuming it is reviewing:

```bash
tmux -L overdeck capture-pane -t <conv-id> -p -S -30
```

If it is acting as a continuation rather than as a reviewer, correct it with
`pan tell` (never raw tmux keystroke injection):

```bash
pan tell <conv-id> "STOP. You are NOT continuing that conversation's work. You ARE the independent reviewer it wanted to spawn. Read <brief path> and follow it exactly. Read-only. Begin now."
```

Budget for this step every time. Treat the handoff document as context the
reviewer happens to have, and your `pan tell` as the actual task assignment.

### 5. Wait on the artifact, not the pane

Poll for the findings file rather than watching output scroll:

```bash
until [ -s /home/eltmon/Projects/hoff-<slug>/FEEDBACK-<model>.md ]; do sleep 20; done
```

Run that in the background so you can keep working.

### 6. Read the findings critically, then report

The reviewer is not an oracle. Treat REFUTED verdicts as claims to check, the
same way you asked it to treat yours — a reviewer that misreads a call site can
be confidently wrong. Verify anything that would change what you do next.

Report back to the operator with: what the reviewer confirmed, what it refuted
and whether you agree, what it found that you missed, and where you still
disagree after checking. Never launder its output as consensus.

### 7. Clean up

```bash
git worktree remove /home/eltmon/Projects/hoff-<slug>
```

Keep the findings file if it is going into an issue or PRD — copy it out before
removing the worktree.

## Failure modes and what they mean

| Symptom | Cause | Fix |
| --- | --- | --- |
| `fatal: 'main' is already used by worktree at ...` | `git worktree add` without `--detach` | Add `--detach` |
| `Conversation not found` | Focus text passed without `self` first | `pan handoff ... self "<focus>"` |
| `Focus is N characters — the limit is 500`, no conversation created | Brief crammed into the focus | Put the brief in a file, point the focus at it |
| Handoff command times out at 2 minutes | Handoff document authoring is slow | Normal — verify the spawn with `tmux -L overdeck list-sessions` |
| Reviewer starts doing your open-work list, or tries to spawn its own review | It received the handoff doc, not your focus | `pan tell` it the real task (step 4) |
| Reviewer agrees with everything | Brief lacked adversarial framing, or reviewer shares the author's model family | Rewrite the framing; pick a different family |
| `state.json has no issueId` on `pan tell` | Informational — conversations have no issue | Ignore; the message still delivers |

## Related

- `/pan-handoff` — the underlying command and its full semantics
- `/pan-code-review` — reviewing a *diff*; this skill reviews an *analysis*
- `/pan-tell` — the sanctioned way to message a running conversation