# Adversarial Review

> >-

- **Type:** Skill
- **Install:** `agentstack add skill-lunarcommand-claude-skills-adversarial-review`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [LunarCommand](https://agentstack.voostack.com/s/lunarcommand)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [LunarCommand](https://github.com/LunarCommand)
- **Source:** https://github.com/LunarCommand/claude-skills/tree/main/skills/adversarial-review

## Install

```sh
agentstack add skill-lunarcommand-claude-skills-adversarial-review
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Adversarial review skill

Generates review findings from scratch. This is the pre-merge self-review
counterpart to `pr-review` (which triages *existing* comments). Its whole reason
to exist is to catch the defects a diff-scoped bot structurally can't:
whole-system, failure-mode, and consistency bugs. The method's power comes from
**independent lenses** and **adversarial verification** — preserve both.

## Input

`$SCOPE` — free text describing **what to review** and, optionally, **what to focus
on**. The agent interprets it; it is not a rigid parser. Accepted forms:

- **A file or directory** — `app/services/payments.py`, `app/api/`.
- **A PR number** — `PR #123` or `123`. Pull the diff and the changed files.
- **A diff / "the current change"** — the default when nothing is given: the
  uncommitted work, or if that's empty, the branch vs its merge base.
- **A topic or subsystem** — `the upstream fetch retry path`, `cache invalidation`.
  First **resolve which files it means** (grep/explore), then review those; a topic
  is inferred scope, so it's less precise than naming files.
- **Any of the above plus focus instructions** — `app/services/orders.py — focus on
  transaction/rollback semantics`, or `the checkout endpoint; I care most about the
  concurrency angle, skip style nits`.

### Delta mode: reviewing changes made *since* a previous review

When this skill has already reviewed the change and work continued afterwards
(fixes for the findings, a new requirement, a follow-up commit), do **not** review
the whole thing again, and do **not** skip it either. Review the delta:

- Set `args.baseRef` to the **previously-reviewed commit** and `args.reviewRef` to
  the current one, so the scope is literally `git diff  `.
- Say in `args.context` that the baseline was already reviewed and what it
  validated, so the lenses do not re-derive settled ground.
- **List the prior findings and their fixes**, with the instruction: do not
  re-report the original issue, but do check whether each fix is correct,
  complete, and free of new defects. A fix is unreviewed code.
- **Fence off settled design decisions** explicitly ("do not re-litigate X"),
  or a fresh panel will re-argue choices you already worked through.
- Measure the delta first and say how big it is. Post-review fix batches are
  routinely large enough to deserve their own review: signature changes, new
  logic, and relocated call sites all hide in them.

This is worth doing because the reviewed artifact and the merged artifact are not
the same thing. It has found a false negative in a default code path that the
full review of the baseline never reached.

Separate the two parts of whatever you're given:

- The **scope** decides which files to pull into context (Step 1).
- Any **focus / emphasis / exclusion** is threaded into the assembled context so the
  lenses weight their passes accordingly — and on the workflow path it goes into
  `args.context` verbatim so it reaches the lens agents. Honor exclusions ("skip
  nits"), but never let a focus instruction suppress a **blocker** in another area:
  surface those regardless, flagged as outside the requested focus.

## Step 0 — Protect the working tree (do this first, every time)

The strongest protection is **worktree isolation**: when the reviewed state is
committed, every agent runs in its own throwaway checkout (Step 3b), so a stray
mutating git command rewrites a sandbox and can never reach the user's real tree.
It's preventive, not reactive — prefer it whenever it's available. A worktree
only holds committed work; the steps below decide whether isolation is on the
table and keep a git snapshot guard for when it isn't.

> **The worktree is cut from the DEFAULT BRANCH, not from current HEAD.** A
> review commit sitting on a feature branch is therefore *not* checked out inside
> it — the agents see the **pre-change** files. Isolation protects the tree; it
> does **not** deliver the change. So whenever you set `args.isolate: true` you
> MUST also pass `args.reviewRef` (and `args.baseRef`), which the workflow turns
> into a standing instruction to read changed files via `git show :`.
> This has already produced a wrong review: three verifier agents refuted a real
> blocker as "factually false" because the offending entry was absent from
> *their* checkout. Also put the diff itself in `args.context` so the change is
> reachable even without git.

1. **Check whether the tree is dirty:** `git status --porcelain`.
2. **If the reviewed state is already committed** (a PR, or a committed branch vs
   its merge base), set `args.isolate: true` **and `args.reviewRef`** (Step 3b)
   and proceed — the agents run isolated and cannot touch the tree.
3. **If it is dirty and the scope is the local diff**, do not start yet. Offer, in
   order of preference:
   - **(a) commit to a WIP/branch first** — *recommended*: it captures the work
     AND unlocks worktree isolation (set `args.isolate: true` **and pass the new
     commit as `args.reviewRef`** — without it the isolated agents cannot see the
     change at all), the only option that makes the agents physically unable to
     mutate the tree. This commit is
     **scaffolding for isolation, not the final state**: once the review and any
     fixes have landed, restore the uncommitted working state (`git reset --soft
     `, e.g. the branch point or `main`) so the reviewed change +
     fixes remain as uncommitted edits to review in the editor — unless the user
     explicitly wants the commit kept to push/PR immediately.
   - **(b) `git stash`** — noting the review then sees nothing.
   - **(c) proceed in place, uncommitted** — explicitly accepting the risk: agents
     run in the real tree, `args.isolate` stays `false`, and the only guards are
     the read-only mandate and the snapshot below.
   Wait for the user's choice.
4. **Snapshot before the fan-out** (cheap, and the fallback guard when not
   isolated):
   ```bash
   SNAP="${CLAUDE_JOB_DIR:-/tmp}/tmp"; mkdir -p "$SNAP"
   git status --porcelain  > "$SNAP/ar_tree_before.txt"
   git diff HEAD           > "$SNAP/ar_diff_before.txt"
   # UNTRACKED files are invisible to `git diff HEAD`, so copy them too or the
   # snapshot silently fails to cover brand-new files (a new module, a new test).
   # `tar -T -` reads the NUL-separated list on stdin in ONE invocation. Piping
   # through `xargs` instead loses files: past ARG_MAX xargs runs tar repeatedly
   # and `czf` recreates the archive each time, so only the final batch survives
   # (measured: 64 of 3000 files). It also avoids `xargs -r`, which is GNU-only.
   git ls-files --others --exclude-standard -z \
     | tar czf "$SNAP/ar_untracked_before.tgz" --null -T -
   # SUBMODULES are also invisible to `git diff HEAD` (it reports only a changed
   # POINTER, never dirty content inside). Record their state separately.
   git submodule status --recursive > "$SNAP/ar_submodules_before.txt" 2>/dev/null || true
   git submodule foreach --recursive --quiet \
     'git status --porcelain | sed "s|^|$displaypath |"' \
     > "$SNAP/ar_submodule_dirt_before.txt" 2>/dev/null || true
   ```

   If the change adds new files, say so when offering option (c): the snapshot's
   coverage of them is the weakest part of an in-place review.

This step exists because it has already gone wrong: a lens agent ran
`git checkout ` to compare pre-change behaviour and silently reverted a
file holding uncommitted work. Worktree isolation is the *enforcement* that a
prompt rule (`READ_ONLY_MANDATE`) can only request — a sandboxed agent's
`git checkout` rewrites its own throwaway checkout, not the user's file. The
snapshot is the last line for the one case isolation can't cover: a deliberate
in-place review of uncommitted work.

## Step 1 — Assemble context (do this before any reviewing)

Context quality is the single biggest determinant of review quality.

1. **The change itself** — the diff, and the **full text of every changed file**
   (not just hunks).
2. **Collaborators** — for each changed file, pull its callers and callees and any
   config/constants it depends on, *including unchanged files*. Grep for callers;
   read the config. (Defects hide in the interaction between a changed file and an
   unchanged one — e.g. an engine's isolation setting deciding whether a rollback
   in another file even works.)
3. **Invariants** — read the target repo's `CLAUDE.md`, especially an
   "Operational Invariants" section if present. These are non-negotiables; a
   violation is a blocker. If none exist, infer them and note that they're
   unwritten.

## Step 2 — Choose scale (and understand the fidelity tradeoff)

The two paths are **not** equal-fidelity — this is the most important choice here.

- **Inline** (this agent runs the lenses in its own context) — a *quick, lighter*
  structured review. Good for one file, a small focused diff, or a fast sanity
  check. Its limitation: the lenses run in a single context, so they bleed toward
  one averaged review, and the refutation is the same mind that made the finding —
  i.e. it partly reintroduces the single-pass weakness the method exists to fix.
  Cheap and conversational. Go to Step 3a.
- **Workflow** (the bundled multi-agent engine) — the *full-fidelity* path, and the
  one that earns the method its keep. Each lens is a separate agent (genuinely
  independent), findings are merged into distinct defects, then each is verified by
  independent refuters before it surfaces. Use it for a PR, several files, a
  release check, whenever the user asks for "thorough" / "deep" / "adversarial", or
  whenever the answer actually matters. Heavier and slower (runs in the background).
  Go to Step 3b.

When in doubt, prefer the workflow: inline is the convenience, the workflow is the
method.

## Step 3a — Inline lenses

Run **each lens below as its own focused pass** — do not merge them into one
"review everything" prompt. For each pass, the instruction is *"try to break
this,"* never *"review this."* Describe nothing; find the input, state, timing, or
failure that makes it wrong. An empty result for a lens is a valid answer — say so
and move on.

Then run Step 4 (refute) and Step 5 (rank + report).

## Step 3b — Workflow escalation

Two engines ship with this skill. Pick by what is under review:

| Engine | Use it for |
| --- | --- |
| `adversarial-review.workflow.js` | Code, or a mixed code+spec change. The default. |
| `spec-accept-review.workflow.js` | A spec/RFC change — normative prose and conformance fixtures — about to be committed, tagged, or published. |

**Resolve the path first — never guess it and never glob for the file.** More
than one copy of this skill can exist on a machine and they drift independently,
so a glob can hand the Workflow tool a stale engine. Run:

```bash
adversarial_review_path.sh adversarial-review.workflow.js
```

That prints the absolute path of the engine inside the copy of the skill that is
actually loaded. Pass the result verbatim as `scriptPath`.

Then call the Workflow tool with that path and the assembled context as args:

```
Workflow({
  scriptPath: "",
  args: {
    scope: "",
    context: "",
    invariants: "",
    targetKind: "code" | "spec" | "any",  // optional, defaults to "any"
    isolate: true | false,                // Step 0: true when the reviewed state
                                          // is committed, false for in-place work
    reviewRef: "",  // REQUIRED when isolate is
    baseRef: ""        // true — the worktree is at
                                          // the DEFAULT BRANCH, so without these
                                          // the agents never see the change
  }
})
```

Set `targetKind` from what you actually read in Step 1 — you already know whether
the changed files are source or prose:

- **`spec`** — the changed files are specs, schemas, docs, `.md`/`.yaml`/IDL, with
  no meaningful executable logic. Skips the three code lenses.
- **`code`** — source changes with no spec/prose component. Skips the two spec lenses.
- **`any`** *(default, and the right choice whenever unsure)* — mixed changes, or a
  spec repo that also ships a reference implementation, which is exactly where
  spec↔implementation drift lives and where you want both sets running.

The workflow fans the lenses out in parallel, verifies each finding by refutation
(diverse angles, majority survives), dedupes, and returns findings ranked by
severity. Relay its result via Step 5.

### The spec/RFC engine

For a spec or RFC change about to be committed, tagged, or published, use
`spec-accept-review.workflow.js` instead. It carries lenses tuned to normative
prose and conformance fixtures — a fixture that can pass wrongly, a stale
cross-reference, a coverage gap against precedent, a CHANGELOG date that does not
match the tag day. It takes only two args:

```
Workflow({
  scriptPath: "",
  args: {
    scope: "",
    context: ""
  }
})
```

There is no `isolate` option, and that is deliberate: this engine reviews
**uncommitted** work in the real tree, and a git worktree can only hold committed
work. Nothing enforces read-only here except the prompt mandate, so Step 0's
snapshot is not optional on this path — take it before you call.

**On worktree isolation.** Set `args.isolate: true` and the workflow runs every
lens, merge, and verify agent in its own throwaway git worktree — via the
harness's built-in `isolation: 'worktree'`, so there are no shell commands and no
added permissions, and the worktrees are auto-cleaned. A destructive git command
then rewrites a sandbox instead of the user's tree: this is the *enforcement* the
`READ_ONLY_MANDATE` prompt rule can only ask for. It is **not** a substitute for
Step 0's judgement — a worktree holds only **committed** work, so uncommitted
work is invisible inside it. Set it whenever the reviewed state is committed (a
PR, a committed branch, or after a Step 0 commit); leave it `false` only for a
deliberate in-place review of uncommitted work, which then relies on the read-only
mandate and the snapshot guard.

**Isolation does not deliver the change — you must.** The worktree is cut from
the **default branch**, so on a feature branch the agents open pre-change files.
Always pass `args.reviewRef` (+ `args.baseRef`) alongside `isolate: true`; the
workflow turns them into a standing instruction to read changed files with
`git show :` and to never infer absence from the working copy. Put
the diff in `args.context` as well, so the change survives even if an agent
ignores git entirely. Skip this and the run still *looks* healthy — agents
review the old code and report confidently on it.

## Step 4 — Refute every finding (inline path)

Before surfacing anything, try to **refute** each finding — but refute on **validity, not severity**:

- **REFUTE only if the finding is wrong**: the claim is factually false, it describes *intended*
  behavior, or the proposed fix would regress or is unnecessary. A finding that is factually correct but
  low-impact is **not** refuted — it survives as a **nit** (adjust its severity down; don't discard it).
  Do not conflate "minor" with "invalid."
- **"Reproduce it" means different things by target.** For a runtime bug, construct the concrete
  input/state that triggers it — if you can't, it's likely not real. For a **spec / docs / config /
  prose** target, most real defects have *no* triggering input: "reproduction" is showing concretely how
  the artifact **misleads a reader, makes two conforming implementations diverge, contradicts another
  section, or states something false**. Don't drop a real consistency / accuracy / parity defect just
  because it has no runtime repro — that filter is code-calibrated and mis-fires on documentation.
- **No charitable-reading dismissals.** If a claim is false or a reference ambiguous under a *plain*
  reading, that's a real defect even if a generous interpretation exists.
- **Never refute on "I looked an

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [LunarCommand](https://github.com/LunarCommand)
- **Source:** [LunarCommand/claude-skills](https://github.com/LunarCommand/claude-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-lunarcommand-claude-skills-adversarial-review
- Seller: https://agentstack.voostack.com/s/lunarcommand
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
