Skip to content
Back to skills

Second Opinion

ASecurity

Get an independent second opinion on work or decisions — either by running a fresh cross-model panel in parallel, or by bringing the same reviewers back for iterative deepening

  • 5 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added October 4, 2026
ai-agentsrustgoshellbashgitapi

Works with

  • cli
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

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

Scanned October 5, 2026

npx -y skills add OpenCairn/OpenCairn --skill second-opinion --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Second Opinion?

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

Security grade badge for Second Opinion
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/opencairn-second-opinion/badge)](https://www.skillsdirectory.com/skills/opencairn-second-opinion)

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: second-opinion
description: Get an independent second opinion on work or decisions — either by running a fresh cross-model panel in parallel, or by bringing the same reviewers back for iterative deepening
---

# Second Opinion - Parallel Panel and Iterative Review

**Shared rules:** read `_shared-rules.md` (core) and `_shared-rules-reviewer.md` §§10, 16, 20 and 23 from the shared skills directory above this SKILL.md before preparing the review. Other supplements load only when their operation is needed, per the core directory.

Get a second opinion on a piece of work — code, writing, an audit pass, a plan, a judgement call — by running reviewers in one of two modes, then synthesising.

## When to use this

**TRIGGER when:**
- High-stakes work is about to ship (publication, merge to main, send to client, deploy to prod) and a single reviewer's confidence feels load-bearing.
- A decision is hard to reverse and the cost of being wrong exceeds the 2–5 minute cost of running the review.
- You just finished a first-pass review (e.g. `$audit`) and want an independent check before acting on the findings. This is *review-of-review* mode — the highest-value use of the skill, and also the most prone to bias-leaking. See Phase 1 step 5.
- You're stuck between two framings of a problem and want non-correlated voices.
- You've already run a panel, applied fixes, and want to verify the fixes against the reviewers who raised the concerns (iterative mode — see below).

**DO NOT use for:**
- Trivial bug fixes, typo corrections, obvious refactors. Running reviewers takes 2–5 minutes and burns model API calls; spending that on a one-line change is theatre, not verification.
- Exploratory questions where you haven't yet committed to a direction. This skill reviews *work*, not open-ended brainstorming.
- Work where you already know the answer and want confirmation. That's sycophancy-shopping — run reviewers only if you're willing to be wrong.

## The two modes

**Mode A — Independent panel (parallel, fresh reviewers).** Reviewers from different model families — Claude, Gemini, Codex, and Grok — each seeing the work for the first time, running concurrently. Maximum non-anchoring; cross-model signal on agreement vs disagreement. Use when the question is "is my understanding of this right?" and you want judgement uncorrelated with the in-session conversation. This is the default mode and the one validated in real use. If a reviewer is unavailable, the panel runs with whoever's present (see Phase 2A step 4) — four families is the target, not a hard requirement.

**Mode B — Iterative deepening (sequential, resumed reviewers) — partially validated (Codex + Gemini legs proven in use; Claude leg's resume mechanics verified, not yet exercised in a full round 2), see Phase 2B warning.** Bring the *same* reviewer(s) back for round 2, 3, or more. They carry their prior context forward — you don't have to re-brief them on the work or the history. Use when:
- You've fixed the thing the reviewer flagged in round 1 and want to know whether the fix actually resolves their concern.
- The reviewer was uncertain in round 1 and you've gathered new evidence (docs, test results, source reads) that should shift the judgement.
- You want to push back on a critique and have the reviewer defend or revise it.
- You want depth on a specific finding the reviewer raised, rather than breadth across new ones.

**They compose.** The canonical workflow is panel-first, then iterate: run Mode A for round 1 to surface candidate findings, act on the findings the tiebreak selects, then run Mode B in round 2 to verify the fixes against the reviewers who raised them. Avoid running a fresh panel in round 2 — you pay the briefing cost again and lose continuity with the specific concerns that produced the fixes.

**Optional: anonymized cross-examination.** Between the round-1 panel and your synthesis, you can run one cross-review pass — feed each reviewer the *other* reviewers' findings with **model identity stripped**, and ask them to challenge, confirm, or rank each one on its merits. Anonymization is the point: a reviewer should engage with the substance, not defer to "the Codex finding" or dismiss "the Gemini one." This surfaces which round-1 claims survive scrutiny by a different model family and which were one-model idiosyncrasies. It runs cheaply by *resuming* each round-1 reviewer and showing it only the findings it **didn't** author — self-recognition can't happen because a reviewer never sees its own findings, so no re-brief is needed. The result is a peer-review matrix: each finding judged by the reviewers who didn't raise it. See Phase 3.5. **Guardrail:** cross-review can manufacture false consensus — a reviewer may cave to a confidently-worded peer claim that's actually wrong. Treat surviving findings as *better-tested*, not *confirmed*; the pass feeds your tiebreak, it never replaces it with a vote count.

**Don't over-iterate.** If you've gone back to the same reviewer three times on the same issue and you still disagree, the problem isn't review cadence — it's a genuine substantive disagreement. Stop iterating, escalate to the user, and present both positions.

## Philosophy

**Fresh context is a tool, not a virtue.** A reviewer who walks in cold catches things the author has normalised — that's Mode A's value. A reviewer who already has context can go deeper on a specific thread without re-briefing cost — that's Mode B's value. But Mode A's freshness is conditional on the brief: if you brief a fresh reviewer with a summary written by the author of the work being reviewed, you've laundered your framing into their context and their judgement is no longer independent. This is the skill's single biggest failure mode; Phase 1 step 5 addresses it directly. Mode B doesn't suffer from this (the reviewer's context is their *own* prior reading, not the author's summary) — one reason Mode B is sometimes the better tool even for first-round questions.

**The tiebreak is the work.** You are not running a committee. You are not counting votes. When reviewers split, investigate the disagreement, decide which side is right, and say *why* — don't hedge, don't average. Correlated agreement is weak evidence, not ground truth: two models trained on similar data can confidently share a blind spot. And running the panel surfaces candidate findings, not verdicts — the user (plus you) decides what to act on. A second opinion that mechanically applies every suggestion is just a slower first pass.

## Instructions

### Phase 1: Identify the target, pick the mode, construct the brief

1. **If the user specified the target, load it.** If not, ask — don't guess. The target can be a file, a PR, a prior audit pass, a decision, or a plan.

2. **Pick the mode.** If this is round 1 on a new question and you want independent judgement: Mode A. If you're iterating on a specific finding from a previous review and want the same reviewer(s) back: Mode B. If you're not sure, default to Mode A. Tell the user which mode you're running so they know what to expect.

3. **Check the target fits.** If it's too large to fit in a reviewer's context window (a multi-file system, a whole repo, an entire knowledge base), scope it in the brief: name the files or sections to focus on, or ask the user to narrow scope. A run that silently skips half the target is worse than a scoped one that's honest about its boundaries.

4. **Write a self-contained brief** that each reviewer can read. For Mode A they read it cold; for Mode B they read it on top of their existing context. Include:
   - **Reviewer-seat execution boundary** — begin the brief with this exact block. It is a role boundary, not supplementary context:
     ```markdown
     ## Reviewer-seat execution boundary

     You are one leaf reviewer inside an already-running review panel. Execute this brief directly and return the requested review. Do not activate or follow any audit, second-opinion, reviewer, or orchestration skill as a workflow; if one is itself in scope, inspect it only as target material. Do not dispatch another reviewer or create another panel. Do not edit files.
     ```
   - What the work product is and where it lives (absolute path if local).
   - What context matters: audience, publication target, constraints, dependencies, the author's situation.
   - **Out-of-band evidence** — every source the work product's claims rest on that the reviewer cannot reach from the work itself, embedded verbatim under an established-fact heading, per **`_shared-rules-reviewer.md` §16** (the single source of truth; no copy here, to avoid drift).
   - The specific question(s) you want judgement on.
   - The output format: structured sections, word cap, explicit "no hedging, disagree where warranted, no sycophancy" directive, and **the evidence attestation each seat owes, per `_shared-rules-reviewer.md` §23** (it is the single source of truth; this file deliberately carries no copy to drift). Paste §23's attestation table into the brief body verbatim rather than cross-referencing it — the reviewer cannot read this directory. §23 carries the receipt enforcement, the spot-check-before-promoting rule, and the evidence-class tiebreak.
   - **A "what the work gets right" section in the output format, capped at ~5 bullets.** Without this, a reviewer who only reports problems leaves the synthesis unable to distinguish "section X was approved" from "section X was not mentioned" — and silence is not endorsement. Forcing reviewers to name what they think works also makes disagreement more visible in Phase 3: if Claude lists something as a strength and Gemini lists the same thing as a problem, that's a load-bearing disagreement you'd otherwise miss.
   - **Severity-stratified output with explicit maxes** (e.g. "load-bearing: max 5 / worth-fixing: max 8 / polish: max 5"). Uncapped lists invite reviewers to pad with shallow observations to look thorough; explicit caps force them to rank and drop the weak ones.

5. **For review-of-review mode in Mode A (second opinion on a prior audit, code review, or decision memo written by the current session), add this explicitly:**
   - **Require the reviewers to read the original work product from source.** The brief gives them the path; their job is to go read it, not to take your word for what it says. Include a sentence like: "Read the work yourself before forming opinions. The summary below is supplementary context, not a substitute — treat it as possibly biassed because it was written by the author of the work being reviewed."
   - List the prior findings and fixes faithfully, but label them as the *author's* claims, not as facts.
   - Ask the reviewer to judge each claim on its own merits after reading the current state.

   Without this, all reviewers inherit your framing and their "agreement" becomes an artefact of the brief rather than genuine independent judgement. This is not optional for review-of-review mode. For Mode B this is less urgent — the continuing reviewer already has their own reading from round 1 — but it's still worth reminding them to re-read sections that changed since round 1.

6. **Strip bias from the brief.** Don't frame the question in a way that telegraphs your preferred answer. Present what was done, not whether it was good. Ask the reviewer to apply their own framework, not to rate yours.

7. **Run §10's shell-denied-seat pre-flight before you finalise the brief.** Which seats lack shell is fixed by the despatch config in §10, not by the Phase 2A availability probe, so you can and should resolve this before the brief is written. If any of them is in the panel and the question turns on something a shell would settle — a flag's behaviour, a config key, whether a path exists — check it yourself now and embed the output under the out-of-band heading per §16. Afterwards is too late: the seat has already guessed and you are adjudicating the guess. → `_shared-rules-reviewer.md` §10.

8. **Open every source the work product cites but the session never read, before you finalise the brief.** Same shape as step 7 and the same deadline, different gap: an unopened citation is closed by opening it, never by disclosing it in the brief. Disclosing aims every seat at one hole, so they converge from the same absent evidence and the synthesis misreads that agreement as corroboration. → `_shared-rules-reviewer.md` §16.

Write the raw brief once to a unique scratch file, e.g. `mktemp -t second-opinion-prompt.XXXXXX` on macOS/Linux or a unique Windows temp path. Record it as `<raw-brief>` for preparation only. Phase 2A resolves `<dispatch-brief>` before creating the run directory; seats consume its copied `<run-dir>/brief.md`, never the raw path when a packet was prepared.

### Phase 2A: Launch a fresh panel (Mode A)

**Before launching: confirm the reviewers are available** — run `claude --version`, `gemini --version`, `codex --version`, and `"{VAULT}/.claude/scripts/xai_client.py" --probe` in the shell. If a CLI errors out, it isn't installed; drop it and note the reduced panel per step 4. The Grok probe has no binary to version-check — it exits 0 when the client resolves `XAI_API_KEY` from the process environment or `~/.claude/settings.json`, 1 otherwise; run it *before* despatch so an unavailable key degrades the panel up front rather than failing mid-run. If Gemini's version is older than 0.40 (no Policy Engine), use the write-capable fallback invocation in step 2 — but note that path has **no read-only enforcement** (the step-6 integrity guard is the *only* protection), so prefer upgrading to gemini ≥ 0.40 and treat findings from a 0.33–0.39 Gemini as lower-assurance.

Send the brief to all reviewers concurrently (parallel shell calls where the harness supports them; otherwise back-to-back despatches in one turn):

**Before creating the run directory or despatching any seat:** follow §10's preparation → create sequence. Prepare `<raw-brief>` into its new `<raw-brief>.packet` sibling and set `<dispatch-brief>` to the returned packet. The create block copies those dispatch bytes to `<run-dir>/brief.md`; every seat uses that copied path. If preparation fails, resolve the inputs or explicitly drop Grok and use the complete raw brief for all remaining seats. Grok's prepared call uses no `--source`; retain read-from-source attestation for seats that can read. For Mode B, prepare the new raw prompt and relevant prior reviews before copying to the new round-N path per §10.

**After §10 creates the actual run directory, before any seat is despatched: baseline the targets.** Copy every target file's bytes into `<run-dir>/baseline/` and record their SHA-256s, taken from the **working tree** as it stands now (not `HEAD`), for git and non-git targets alike. Step 6's integrity guard diffs against this baseline and restores from it; without it a post-panel `git status` cannot separate a reviewer's write from an edit that was already in the tree, and there is nothing to reconstruct afterwards if you skip it. Use the exact run directory printed by that create block; do not create a separate early directory to satisfy this copy.

1. **Fresh Claude** via the `claude` CLI in print mode — `cat <run-dir>/brief.md | claude -p "Follow the instructions in the piped input exactly."` — configured read-only per §10's despatch block (`--output-format json --disallowedTools "Bash,Write,Edit,NotebookEdit"` — verified: no write path, and a spawned sub-agent inherits the restriction). It receives the same payload as the Gemini and Codex calls. Do not paraphrase, summarise, or extract: the brief *payload* must be identical across seats, and seats may differ only in whether they read the target from source or from the inlined appendix. The transport wrappers (the per-CLI `-p` strings) may differ but must add no substantive instructions, or you've re-introduced framing asymmetry. **The Grok seat needs the target inlined**, already present in the materialised packet as a delimited appendix plus manifest; send that exact packet to every seat, and keep the read-from-source instruction for the three that can read — otherwise you either fork the brief (asymmetry) or destroy the read-list evidence for the CLI seats (worse). The brief carries the disagree directive: independent judgement, disagree where warranted, no sycophancy, no "looks good overall" hedging — without it a fresh reviewer defaults to polite confirmation of whatever framing you gave it.

   **After the call completes, capture and surface the Claude session id in your user-visible response text** (`--output-format json` → `.session_id` via jq; `.result` carries the review text). This makes the id recoverable from the conversation transcript even after the raw output scrolls away, which matters for Mode B round 2.

2. **Gemini CLI**, in parallel with the Claude call. **Give the call a five-minute ceiling** and, under Codex, use §10's verified yield-and-poll mechanism so the review can outlive `exec_command`'s initial 10-second window.

   Preferred invocation (gemini ≥ 0.40, which has the Policy Engine): use the **canonical despatch block in `_shared-rules-reviewer.md` §10** — the single source of truth for the read-only policy file, the piped `gemini` call, and the workspace flags for out-of-cwd targets — using `<run-dir>/brief.md`, the copied dispatch input from §10. Why a `--policy` deny-file: it loads Gemini's **Policy Engine** (the non-deprecated successor to `--allowed-tools`) and a `deny` rule strips the named tools from the model's toolset entirely — **verified on gemini 0.40.x** as a *hard* read-only guarantee (the reviewer reports the edit tools "not found" while every read tool stays available). This **replaces `--approval-mode plan`**, which was *not* read-only (plan blocked shell but still exposed the `replace` edit tool, so a reviewer briefed to propose fixes wrote them straight into the target — the contamination that motivated this change). Further operational caveats — portable `mktemp` form, no `~/.gemini/policies/` drop, the post-run denied-tools check, untrusted-directory refusals — live in §10; read it rather than reciting from memory. The integrity guard in step 6 stays as a cheap backstop (and confirms the policy loaded). Gemini also has a real `-s/--sandbox`, but it needs a container runtime, so don't mandate it.

   Fallback if the flags aren't supported by the installed version (write-capable — the step-6 integrity guard is the only protection on this path):
   ```
   cat <run-dir>/brief.md | gemini -p "Follow the instructions in the piped input exactly."
   ```

   **After the call completes, capture and surface the Gemini session index.** Run `gemini --list-sessions | tail -3`; sessions are listed in ascending chronological order, so the **last/highest-numbered row** is the most recent. The leading numeric column (the `N.` before the prompt preview) is the index you want. **Indices are per-project, scoped to the cwd the command runs from** — the same session carries a different number (or is absent entirely) when listed from another directory. Run the listing from the cwd you despatched from, and **record that cwd alongside the index**; Phase 2B's `--resume` must run from the same one. Each row also carries a per-session UUID in brackets — record it too, as it re-locates the row if indices shift, even though `--resume` won't accept it. Surface the index in the user-visible response text alongside the other handles (e.g. `Panel spawned: Claude agent a5abc789, Gemini session #12, Codex session 019e87a8-…`). You'll need this for Mode B round 2, and "latest" is not a safe shortcut (see Phase 2B step 2). Verified against gemini 0.38.2 and 0.40.1; if the output format ever diverges (no header, different column layout, reversed ordering), note what you saw and flag it back to this file — gemini's `--resume` only accepts an index number or the string `"latest"`, so if index parsing breaks, Mode B round 2 isn't recoverable and you fall back to a fresh Mode A panel.

3. **Codex CLI**, in parallel with the Claude and Gemini calls. **Give the call a five-minute window** — same reason as Gemini.

   Invocation: the codex line of the **canonical despatch block in `_shared-rules-reviewer.md` §10**, using `<run-dir>/brief.md`, the copied dispatch input from §10. Rationale: `--sandbox read-only` gives Codex read-only tool access (it can Read files but not edit them), matching the independent-review intent — the analogue of Gemini's `--policy` deny-file (step 2); `--skip-git-repo-check` lets it run outside a git repository (the target often isn't one); the trailing `-` reads the brief from stdin. Output is plain text and pipe-friendly; a benign `failed to refresh available models` line may appear on stderr under flaky networks and can be ignored.

   **Model:** don't pass `-m` — let Codex use its default. On a ChatGPT-account login the default resolves to the supported model for that plan; explicit `-codex`-suffixed models (e.g. `gpt-5.x-codex`) and the very newest point releases are often rejected for ChatGPT-account auth with a `not supported` or `requires a newer version of Codex` error. If the default itself errors, run `codex --version` and upgrade (`npm install -g @openai/codex@latest`) before pinning a model by hand.

   **After the call completes, capture and surface the Codex session id.** The `codex exec` preamble prints a `session id: <uuid>` line; record that UUID and surface it in the user-visible response text alongside the other handles (e.g. `Panel spawned: Claude agent a5abc789, Gemini session #12, Codex session 019e87a8-…`). You'll need it for Mode B round 2; Codex resumes by UUID, which is more robust than Gemini's index.

3b. **Grok**, in parallel with the other three. **Give the call a five-minute ceiling** — xhigh reasoning can think >90 s before the first byte; under Codex, use §10's yield-and-poll mechanism. Invocation per the **canonical block in `_shared-rules-reviewer.md` §10**:

   The Grok line of §10's per-seat block (stdout to `<run-dir>/grok.out`, stderr to `grok.err`, plus `.exit` and `.time`), using `--prepared` and no `--source`; the shared packet already carries every source.

   Unlike the CLI seats, Grok reads nothing — every file it should consider goes into preparation with `--source`, and the prepared packet inlines them as a delimited appendix with a `path | bytes | sha256` manifest. Two failure modes to handle rather than absorb:

   - **Over `MAX_INLINE_BYTES`** the wrapper exits non-zero without calling the API. Drop the seat and announce the reduced panel; never re-run with a trimmed source list to squeeze under the cap, because a seat reviewing a silently-narrowed target produces confident findings about a target nobody else reviewed.
   - **A review that comes back with no manifest and no quoted passages is brief-echo** — discard it per `_shared-rules-reviewer.md` §23, and say so in the synthesis rather than quietly running a three-seat panel labelled as four.

   **There is no Grok session handle.** The wrapper sets `store: false`, which forecloses `previous_response_id` threading — so Mode B round 2 is always replay, never resume. Persist the `--source` list beside the brief in the run directory (`$RUN_DIR/grok-sources.txt`) and surface the run directory path alongside the other handles; round 2 has nothing to resume *from* without them. Grok's output is `$RUN_DIR/grok.out` (§10), deterministic once the run directory is known. Gemini and Codex can be re-found by session index or UUID if you lose the path; Grok cannot, so a run directory path that scrolls out of context makes round 2 unrecoverable. Tag round-2 Grok findings `[Grok r2, fresh-with-replay]`, consistent with the existing fallback vocabulary.

4. **If a reviewer is unavailable** — a CLI not installed, API unreachable, quota hit, a seat despatch erroring or timing out — fall back to the reviewers that are present and **say so explicitly in the synthesis**. Do not silently pretend the full panel ran. A one-reviewer run isn't a panel; it's a single opinion with one extra pair of eyes, and the "cross-model signal" claim weakens with every family you drop.

5. **A passing `--version` doesn't prove a reviewer can authenticate.** A CLI whose auth comes from an API key in an environment variable can report its version yet still fail the actual call — the key must be present in the shell the harness actually runs (Codex invokes `/bin/bash -lc`, which loads the profile; other setups may not, so don't assume a specific file). If a reviewer fails on **auth** rather than launch, set its key where the CLI reads it itself regardless of how the shell was started — the CLI's own config/env file is the portable fix across Linux, macOS and Windows (e.g. Gemini reads `~/.gemini/.env` containing `GEMINI_API_KEY=<key>`). This is distinct from step 4's "not installed": the binary runs fine, the credential just isn't reaching it.

6. **Integrity guard — confirm the panel didn't mutate the target.** With the `--policy` read-only file (step 2) Gemini's edit tools are stripped, so this is now a cheap backstop rather than the primary defence — but keep running it: it confirms the policy loaded, and it's the *only* protection on the no-`--policy` fallback path and for any reviewer whose sandbox leaks. Verify after the panel returns and before synthesising: re-hash every target and compare with the pre-despatch baseline. An unchanged target is clean. A changed target is either a reviewer write or a concurrent writer (another session, the user), and bytes alone cannot tell which — so attribute before touching it. If a reviewer's own output reports an edit attempt on that path, restore that file from the baseline copy (`cp` it back and confirm the hash matches) — **never `git checkout -- <file>`**, which also discards edits that were already in the working tree before the panel. If no reviewer reports an edit, the change is unattributed: leave it, show the baseline-to-current diff, and hand it to the user to reconcile. The contamination is also a synthesis trap: a finding that reads as "proposes text that already exists" usually means the reviewer already applied its own edit, so compare claims against the baseline copy, not the live working tree, before dismissing them. Note every restored or unattributed change in the synthesis.

### Phase 2B: Resume prior reviewers (Mode B)

> ⚠️ **Mode B is only partially validated.** The Codex resume leg has been exercised in anger (7 Jun 2026: round-2 `codex exec resume` round-tripped with prior context; found+fixed the flag-order bug — sandbox flags must precede `resume`, verified codex-cli 0.136.0). The Gemini leg was exercised 12 Jun 2026 (gemini 0.40.1): `gemini --resume <index> -p "<follow-up>" --policy <ro-file> -o text` round-tripped with prior context — the resumed session completed the remaining layers of an audit it had started, read-only policy holding. Caveat: that run resumed by *list index* minutes later with no concurrent gemini sessions; index stability under concurrent use is still unobserved — and while `--list-sessions` prints a per-session UUID, `--resume` accepts only an index or `latest`, so the UUID re-locates the row but can't be resumed directly: record it alongside the index, and under concurrent gemini use match the session by UUID/timestamp before resuming by its current index, or fall back to a fresh Mode A panel. The **Claude leg's resume mechanics are verified** — `claude -p --resume <session_id>` round-trips prior context; capture `.session_id` from `--output-format json`; re-pass the read-only flags on the resume call — but it has not yet carried a full review round 2, and resume across machine or version changes is unobserved. Treat the unvalidated leg as a specification you are helping to validate: when you hit a gap, surface it back to this skill file rather than working around it silently — don't pretend Mode B is production-ready where it hasn't been proven.

Use this phase instead of 2A when you're iterating — the reviewers are already spun up from a previous round.

0. **The Claude leg resumes via the CLI.** Under Codex there is no in-harness handle to a Claude reviewer; the selected round goes back through `claude -p --resume <session-id>` using the id captured in Phase 2A (re-pass `--output-format json` and the read-only `--disallowedTools` set on the resume call). If no session id was captured, choose fresh-with-replay for the Claude call in step 4, after step 2 prepares its copied packet; tag `[Claude rN, fresh-with-replay]`. Do not invoke a seat during this handle check.

1. **Check the Claude session id is still on hand.** Mode B's Claude leg needs the session id captured in Phase 2A; `claude` sessions persist on disk, but resume behaviour across machine or version changes is unverified. If you can't find the id in the conversation transcript, choose fresh-with-replay for step 4 rather than guessing; still complete step 2's shared packet preparation first.

2. **Choose the next unused round N before writing any raw prompt, packet or seat output.** Inspect the run directory and the archive named by its `.archive-path`, when present, under the resolved vault root: copied common/pool packets, seat `.out/.err/.exit/.time/.json` files, syntheses and recorded rounds all occupy their number. Choose a number greater than the highest occupied round; N=2 only when no later round is already present. Record N and its role (fix verification or cross-examination) with the run. Phase 3.5 selects N once for its whole cross-examination and passes that N here for every pool; do not select another number per seat. A later verification or re-audit selects another unused N. This is an operator check, not an automatic selector. Substitute the selected numeric N into every `rN` filename/tag and `<N>` command argument below before running a command; preserve all earlier packets, seat files, syntheses and archive evidence.

**Write the raw round-N prompt to a scratch file**, same pattern as Phase 1 — `mktemp -t second-opinion-followup.XXXXXX` or your OS equivalent. Record this unique raw path for preparation only; it is not `<round-path>`. Keep it narrow: one or two tight questions, not "review the whole thing again." Mode B's value is depth on a specific thread, not breadth. Write the prompt as a continuation: "Round 1 of this review surfaced finding X. The author has now done Y in response. Please re-read [specific sections that changed] and judge whether Y resolves your original concern. If it doesn't, what's still wrong? If it does, say so plainly." Using a scratch file (rather than inline `echo`) avoids shell-escaping problems when the prompt contains backticks, `$`, or quotes — exactly the same reason Phase 2A uses a scratch file.

Before invoking any seat, use §10 to prepare this raw prompt with the persisted source list and relevant prior review outputs. Set `<dispatch-brief>` to that returned packet, or to the complete raw prompt only when Grok is explicitly dropped. Copy the dispatch bytes into the new round-N file:
```bash
cp "<dispatch-brief>" "<run-dir>/brief-rN.md"
```
Bind `<round-path>` to exactly `<run-dir>/brief-rN.md`, never the raw scratch path. Preserve the earlier `brief.md`; retain the packet receipt/source list with the round record. Every resumed or fresh-with-replay seat reads the copied round-N file; no seat rebuilds its payload from the raw prompt. The selected N is shared by its packet, every seat file, synthesis, attribution tag and recording command; do not reset it to 2 after cross-examination.

3. **Look up the Gemini session index deterministically.** If you surfaced the index in Phase 2A (as instructed), use that — and run both the lookup and the `--resume` from the **cwd recorded with it**, since indices are per-project and renumber (or vanish) from a different directory. If not, run `gemini --list-sessions` from that cwd and identify the right session by UUID, timestamp and prompt preview. **Do not use `--resume latest`** — "latest" resolves to the most recent gemini session for the project, so if you or any other process has run gemini for anything in between (even a quick one-shot), `latest` resumes the wrong session. Always resume by numeric index.

4. **Invoke the reviewers in a single message with concurrent tool calls**, same as Phase 2A — parallel, not sequential:

   - **Claude CLI resume**: `cat <round-path> | claude -p --resume <session-id> --output-format json --disallowedTools "Bash,Write,Edit,NotebookEdit"` — the resumed session keeps its prior context; you do **not** re-brief from scratch. If resume fails to round-trip, fall back to fresh-with-replay and tag `[Claude rN, fresh-with-replay]`.

   - **Gemini CLI** with a five-minute window, run from the cwd recorded in step 3. The Phase 2A policy file lives in a different shell call and its variable is gone, so **recreate the read-only policy in the same block** (per `_shared-rules-reviewer.md` §10) rather than referencing a stale one — an empty `--policy` argument is accepted silently and enforces nothing. Substitute `<round-path>` with the copied `<run-dir>/brief-rN.md` bound in step 2, `<index>` with the session index from step 3, and `<root>` with the target's root:
     ```
     RO_POLICY=$(mktemp -t gemini-ro-policy.XXXXXX)
     printf '[[rule]]\ntoolName = ["write_file", "replace", "run_shell_command"]\ndecision = "deny"\npriority = 100\n' > "$RO_POLICY"
     cat <round-path> | gemini -p "Continue the prior review." --resume <index> --policy "$RO_POLICY" -o text --include-directories <root> --skip-trust > <run-dir>/gemini-rN.out 2> <run-dir>/gemini-rN.err; echo $? > <run-dir>/gemini-rN.exit
     ```
     Wrap it in §10's `s=$(date +%s); ...; echo $(( $(date +%s) - s )) > <run-dir>/gemini-rN.time` clock like the round-one line.
     Drop `--include-directories` when the target already sits under the despatch cwd; `--skip-trust` (or `GEMINI_CLI_TRUST_WORKSPACE=true`) is required whenever that cwd is outside your trusted set — headless gemini otherwise refuses to start. If gemini's resume semantics don't round-trip cleanly (session state missing, prompt interpreted as fresh), fall back to running gemini fresh with the same copied round-N packet, including the relevant prior reviewer output verbatim — not ideal, but recoverable. **In the Phase 3 synthesis, annotate this case explicitly** (e.g. `[Gemini rN, fresh-with-replay]`) so the reader can distinguish a true resume from a replayed brief — they're not equivalent signals.

   - **Codex CLI** with a five-minute window — resume by the UUID recorded in Phase 2A, substituting `<round-path>`:
     ```
     cat <round-path> | codex exec --sandbox read-only --skip-git-repo-check resume <SESSION_ID> - > <run-dir>/codex-rN.out 2> <run-dir>/codex-rN.err; echo $? > <run-dir>/codex-rN.exit
     ```
     Same clock wrapper, writing `<run-dir>/codex-rN.time`.
     **Flag order matters:** `--sandbox`/`--skip-git-repo-check` belong to the parent `codex exec` and must come *before* `resume` — `codex exec resume <ID> --sandbox …` errors with `unexpected argument '--sandbox'` (verified codex-cli 0.136.0). The `resume` sub-subcommand only accepts `[SESSION_ID] [PROMPT]` plus its own options (`--last`, `-c key=value`, etc.). Replace `<SESSION_ID>` with the session UUID from round 1 (`codex exec --sandbox read-only --skip-git-repo-check resume --last -` picks the most recent recorded session if you've lost it, but resume by explicit UUID when you have it — `--last` has the same wrong-session risk as Gemini's `latest` if any other codex run happened in between). The resumed session carries its round-1 context. Same fallback as Gemini if resume doesn't round-trip: run codex fresh with the same copied round-N packet, including its prior review output, and annotate `[Codex rN, fresh-with-replay]` in the synthesis.

   - **Grok** with a five-minute window — **always replay, never resume** (the wrapper stores nothing, so there is no session handle). Send `<round-path>`, the packet already prepared and copied in step 2; do not prepare a different packet in this seat call:
     Use §10's Grok line with that same copied `<round-path>` as the brief and `--prepared`, omitting every `--source` argument at send time; write `grok-rN.out/.err/.exit/.time`. All selected seats consume that same packet; include the relevant prior reviews during preparation, not during dispatch.
     Round-N seat files take a `-rN` suffix in the round-one run directory (`gemini-rN.out`, `codex-rN.out`, `grok-rN.out`, `claude-rN.json`/`.out`), so `panel-run-record.sh --round <N>` finds them. Tag every round-N Grok finding `[Grok rN, fresh-with-replay]` — it is replay by construction, not a true resume, and the synthesis must not present it as one. If the persisted `--source` list is gone, the seat can't be replayed faithfully; drop it and say so rather than reconstructing a narrower source set.

5. **If only one reviewer is being iterated** (you only care about one reviewer's finding in the selected round), run that one in Phase 2B and skip the others. Note clearly in the synthesis that round N is single-reviewer.

### Phase 3: Tiebreak and synthesise

Once the reports come back, write the synthesis. **Tag every finding with attribution** — name the reviewers who raised it: `[Claude]`, `[Gemini]`, `[Codex]`, or `[Grok]` for unique finds; the combination for shared ones (`[Claude+Gemini]`, `[Gemini+Codex]`, …), with `[All]` reserved for findings every reviewer on the panel raised; append the selected `rN` for Mode B points (`[Claude rN]`, `[All rN]`), and `xr` for cross-examination verdicts from the Phase 3.5 peer-review matrix, naming raiser then cross-judges (`[F3: Gemini, Claude+Codex xr]`). Attribution is not optional: without it, the panel's provenance is lost and the tiebreak becomes unreviewable. The user can't audit your reasoning if they can't see which reviewer raised what, or which round it came from.

1. **Confirmed by multiple reviewers (`[All]`, `[Claude+Gemini]`, …)** — findings more than one reviewer agrees on; the more families that converge, the higher the confidence. Still *not* ground truth: correlated agreement is weak evidence, especially within a single model family. One line each.
2. **Disputed** — points where the reviewers disagree, or where a round-2 reviewer revised their round-1 position, or where a reviewer's critique contradicts a claim the brief asserted on the author's behalf. For each, state your decision and *why*. Pick a side and justify it. Don't hedge. Don't "both are valid."
3. **Uniquely flagged (`[Claude]`, `[Gemini]`, `[Codex]`, or `[Grok]`)** — issues only one reviewer raised. Judge each on merit: a real issue, or a reviewer idiosyncrasy? Legitimate misses get promoted to the action list; shallow observations get dropped with a reason.
4. **Priority stack** — the full action list ordered by impact (critical → polish), attribution tags preserved. Be explicit about severity so nothing silently rides along on the coat-tails of something important.
5. **"I don't know" items** — if any reviewer flagged something you can't confidently adjudicate without verification (docs, tests, running code, reading source), list it separately. Do *not* act on unverified claims just because they sound plausible. Especially true for claims about tool behaviour, platform quirks, and version-sensitive APIs.

**Failure mode — nothing substantive.** If reviewers return generic praise ("looks good overall", "well-structured", "minor suggestions only"), treat it as weak evidence, not validation. Consider whether the brief was too narrow, whether both models share a training prior that isn't being challenged, or whether a seat defaulted to polite confirmation despite the disagree directive. Options: re-invoke with a sharper prompt, read the work yourself and look for things the reviewers missed, or downgrade confidence and say so.

### Phase 3.5: Anonymized cross-examination (optional)

Run this between round-1 reviews and your final synthesis when the round-1 findings disagree, or when a load-bearing finding came from a single reviewer and you want it stress-tested by a different model family. Skip it for clear-cut runs where the reviewers already converged.

1. **Build a per-reviewer findings pool from your attribution map.** Number every round-1 finding (F1, F2, …). For each reviewer R, assemble the list of findings R did **not** author — pooled from the *other* reviewers, with model names stripped and no label saying which other reviewer raised which (R should not be able to tell Gemini's finding from Codex's, or know either by name). Findings every reviewer already raised in round 1 are consensus — drop them from the pools; they don't need cross-examination. Keep your full attribution map privately for Phase 3; the reviewers never see it.

2. **Use one question template, with a distinct unique raw scratch file per reviewer.** Substitute only that reviewer's anonymous pool in its own file, same `mktemp` pattern as Phase 1: "Here are findings from other independent reviews of the same work. For each, judge it on its own merits — correct, overstated, or wrong? Don't assume a finding is right because it's listed. Flag any you'd actively dispute, and note anything important they all missed." Because R only ever sees findings it didn't write, self-recognition is structurally impossible — no need to ask R to ignore its own.

These pools intentionally differ by reviewer. Before preparing any pool, apply Phase 2B step 2’s next-unused-round check once for the whole cross-examination; record its selected N and role. Use §10's existing preparation for each pool separately, retaining the original target sources and only that reviewer's own prior output if replay needs it; do not inline other reviewers' attributed reports into a blinded pool. Copy each result to `<run-dir>/brief-rN-<reviewer>.md` and use that reviewer's copied file as `<round-path>` in Phase 2B's transport. Do not overwrite the common round packet or claim identical questions across different pools. Substitute that selected N consistently in Phase 2B’s output/time/exit names and record the round with `--round N`; a later fix-verification pass uses another unused round. Preserve earlier seat files and packets.

3. **Resume the round-1 reviewers (Mode B, Phase 2B), in a single message with concurrent calls** — the Claude CLI resume, `gemini --resume`, `codex exec resume <UUID>` — each handed its own copied pool packet from step 2. No re-brief: each reviewer still has its round-1 context, and you're only adding the others' findings. **Grok has no session to resume**: replay it per Phase 2B step 4's Grok bullet, with its copied pool packet as `<round-path>` (sources already inlined during preparation, no `--source` at send time), and tag its verdicts `[… xr, fresh-with-replay]`. If any other reviewer can't be resumed, run it fresh with its own copied pool packet and tag it the same way.

4. **Assemble the peer-review matrix and fold it into Phase 3 with `xr` tags** (cross-review). Each finding now carries verdicts from the reviewers who didn't raise it — e.g. F3 (raised by Gemini) endorsed by both Claude and Codex → `[F3: Gemini, Claude+Codex xr]`, strongly cross-validated; F5 disputed by a cross-judge → `[F5 disputed: Codex xr]`, flag it. A finding that survives challenge from another family is *better-tested*; one that cross-judges push back on is a likely false positive. Per the guardrail above, surviving cross-review makes a finding better-tested, not "confirmed" — silence under cross-review is weaker evidence than an independent raise.

### Phase 4: Decide next steps

Present the verdict and priority stack, then confirm with the user what to act on. Default to asking before applying further fixes unless the user pre-authorised action. A critical finding (silent failure, data loss) may warrant a clearer "I strongly recommend applying X before shipping" nudge — but still the user's call.

After the user acts on findings, **consider Mode B fix verification at the next unused round N, chosen by Phase 2B step 2** to verify the fixes against the reviewer who raised the concern. This is especially worth it for findings where the fix is non-obvious or where "does the fix land?" is itself a judgement call. For trivial fixes, skip that verification pass.

Executing the fixes is outside the scope of this skill. Hand off to direct edits, `$audit`'s fix-and-re-audit loop, or whatever workflow the work product normally lives in.

**Record the run** once next steps are decided, panel mode only, whatever the seat count (a single-reviewer Mode B round still records). For the round being recorded, use N=1 for the initial panel or the N already selected at despatch for a follow-up; never renumber a completed round. Write its synthesis and decision to `<run-dir>/synthesis.md` for N=1 or `<run-dir>/synthesis-rN.md` for N>1 with the Write tool. Resolve the vault (`resolve-vault.sh`, `_shared-rules.md` §1), gate the archive layout with `"{VAULT}/.claude/scripts/check-archive-layout.sh" --enforce "{VAULT}"` (on error record without `--archive` and say so), then run `"{VAULT}/.claude/scripts/panel-run-record.sh" "<run dir>" --skill second-opinion --round <N> --target "<what was reviewed>" --claude-model <model id from claude.json, when that seat ran> --vault "{VAULT}" --archive`. It derives seats, model ids, wall seconds and Grok cost from the seat files, archives the run directory under `06 Archive/OpenCairn/Panel Runs/` and appends one index line to `07 System/Panel Seat Ledger.md` under lock; it records no findings; the archived seat files are the evidence if the seat question is ever reopened, coded then from the files rather than from this synthesis. Record each completed follow-up once with its selected `--round <N>` and matching `-rN` files; a cross-examination and its later fix verification are different rounds. No vault resolvable: run it without `--archive`, quote the line and the run directory, and say the evidence was not archived. A follow-up record lands in the initial round’s archive directory, preserving earlier evidence.

## Guidelines

- **Pick the mode by question type, not by habit.** Fresh panel (Mode A) for "is my understanding right?"; iterative (Mode B) for "does my fix land?" or "defend or revise this critique." Default to Mode A if the question is genuinely open; default to Mode B if you're coming back to a specific thread from a prior review.
- **Surface all session handles (Claude id, Gemini index, Codex UUID) in visible response text after Phase 2A.** Raw outputs scroll out of context; visible transcript text persists. You can't resume a reviewer in Mode B if you can't find their handle.
- **Brief fresh reviewers like colleagues walking in cold.** Mode A reviewers have zero prior knowledge of the task, the conversation, or why this matters. The brief must stand on its own. Mode B reviewers already have context — don't re-send the whole brief, send a tight continuation.
- **Four model families is the default panel.** Claude + Gemini + Codex + Grok — one reviewer per family. Don't add a second reviewer in the same family (e.g. a second Claude); you pay coordination cost for correlated signal. If a reviewer is down, run the panel short and say so rather than backfilling with a same-family duplicate.
- **Cross-model, not cross-instance.** Two fresh Claudes will correlate more than one Claude plus a Gemini and a Codex. Spread across model families — non-correlated error modes is the whole value proposition; a third independent family is exactly why Codex is on the panel.
- **Report disagreement plainly.** When reviewers split, or when a Mode B reviewer revises a round-1 position, say so in the synthesis. That's often more useful than the individual verdicts.
- **Attribution is mandatory.** Every finding in the synthesis names the reviewers who raised it — `[Claude]`, `[Gemini]`, `[Codex]`, `[Grok]`, a combination, `[All]`, or any of these with the selected `rN` or `xr` (cross-examination) suffix. This lets the user audit your tiebreak and catches the laundering failure mode where reviewer claims get presented as your own conclusions.
- **Don't over-iterate in Mode B.** Three rounds on the same thread and still disagreeing means the disagreement is substantive, not procedural. Escalate to the user with both positions clearly stated; don't run round 4.
- **Scope discipline.** This is not `$audit` redone from scratch. Trust the reviewers to bring their own framework; your job is synthesis, not re-review.
- **Verify before acting on unique finds.** A single reviewer confidently flagging a bug is a hypothesis, not a fact. Check it (read the code, test the command, look up the docs, read the source) before editing anything. Especially true for claims about tool behaviour, platform quirks, and version-sensitive APIs — a reviewer that confidently asserts "X doesn't work on Windows" can be wrong, and acting on it without verification means you've shipped a regression to fix a non-issue.
- **Mode B is only partially validated.** The Codex resume and Gemini `--resume` legs are proven in real use; the Claude CLI-resume leg's mechanics are verified (context round-trip), but no full review round 2 has run on it yet. Surface gaps back to this file rather than working around them silently — the skill gets sharper with every real use.

Files in this skill

  • SKILL.md44.6 KB
  • agents/openai.yaml239 B

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.