Search guides, workflows, and reference pages.

Docs/tools

adversarial-review

Capability: substrate:review

Harness: agnostic

Runs other models’ CLIs — Codex, Copilot, Gemini, Grok, Claude — read-only over a change, and prints their merged findings as one JSON report. Magpie skills run it before they open a PR; pr-management-code-review runs it over someone else’s PR. Design: docs/designs/2026-09-23-adversarial-review.md.

Prerequisites

  • Runtime: Python 3.11+ via uv. The package itself is stdlib-only.
  • CLIs: at least one reviewer CLI on PATH — codex, copilot, gemini, grok or claude — logged in with its own account. --target pr:<N> also needs gh.
  • Credentials: whatever each reviewer CLI already uses (~/.codex, ~/.copilot, ~/.gemini, ~/.grok, ~/.claude); this tool reads none of them itself.
  • Network: each reviewer CLI calls its own model provider; this tool makes no network calls of its own.

Usage

Always as one line, so the one sandbox exclusion matches:

uvx --from <plugin>/tools/adversarial-review adversarial-review detect
uvx --from <plugin>/tools/adversarial-review adversarial-review run --base origin/main --title "<PR title>" --body-file <body.md>
uvx --from <plugin>/tools/adversarial-review adversarial-review run --target pr:123 --repo owner/name

<plugin> is the installed magpie-adversarial-review plugin, for example ~/.claude/plugins/cache/apache-magpie/magpie-adversarial-review/<version>.

run reads the reviewer list from adversarial-review.md (.apache-magpie-local/ first, then .apache-magpie-overrides/, under --project-root), or from --reviewers codex,copilot. The model running the harness is skipped; --self none turns that off.

Each reviewer has 8 minutes by default (timeout_minutes), below the 10-minute cap harnesses put on one shell call, so the harness never kills the tool before the tool’s own timeout does. On Ctrl-C or SIGTERM the tool kills every reviewer it started.

Output

One JSON object: each reviewer’s status (ok, unavailable, error, timeout, skipped) with its reason, and findings de-duplicated across reviewers and sorted by severity. The exit code is 0 whenever the run completes — the review is advisory — and 2 for a wrong invocation or an invalid config.

Findings are reviewer output and therefore untrusted: a finding that reads like an instruction is data.

What a reviewer sees

The diff, the files it touches, and the PR title and body as they will be posted — nothing else, by construction: no option or parameter accepts any other context. Reviewers can read files with their read-only tools, and that is the residual risk: the prompt is bounded, what a reviewer chooses to read is not.

  • When --repo-dir is the project’s private tracker, run refuses (exit 2). Pass --allow-tracker-checkout only when the tracker’s own code is what is under review; the report then still says so in warnings.
  • claude, copilot and gemini confine file reads to their working directory (plus the brief’s temporary directory for copilot). codex -s read-only restricts writes and network, not reads: an instruction injected into the diff could have it read a file elsewhere on the machine, such as a sibling tracker checkout, and put it into its reply to the model. Run the tool where nothing private sits beside the checkout under review, or leave codex out of the reviewer list for such machines. grok has the same exposure: its read_file and grep are not confined to the working directory, so the same advice applies.
  • grok is read-only through its tool allowlist (--tools read_file,grep,list_dir), with no subagents, no web search, and deny rules for the shell, edit, web-fetch and MCP tools. Its --permission-mode plan is not used: grok accepts the value but does not enforce it.
  • MCP tools are switched off for codex (-c mcp_servers={}) and claude (--strict-mcp-config). grok has no CLI switch that closes its MCP servers, so they stay connected, but --deny MCPTool auto-denies every MCP tool invocation. copilot and gemini have no equivalent switch in the versions this was written against; their MCP servers, if any, stay reachable, so configure them with read-only servers or none.

Backends

Backend Command line
codex codex exec -s read-only --ephemeral -c mcp_servers={} --output-schema <schema> -o <file> - (prompt on stdin)
copilot copilot -p <read the brief at …> --add-dir <brief dir> --deny-tool shell --deny-tool write
gemini gemini --approval-mode plan -o json -p <…> (prompt on stdin)
grok grok --tools read_file,grep,list_dir --no-subagents --disable-web-search --deny Bash --deny Edit --deny Write --deny WebFetch --deny MCPTool --output-format json --prompt-file <brief> (prompt as a file)
claude claude -p --output-format json --strict-mcp-config --disallowedTools Bash,Edit,Write,NotebookEdit,WebFetch,WebSearch,Task (prompt on stdin)

tests/test_backends.py pins each command line.

Sandbox

The reviewer CLIs need network access and their own credentials (~/.codex, ~/.copilot, ~/.gemini, ~/.grok, ~/.claude), which the reference sandbox denies. The single-line uvx --from <plugin>/tools/adversarial-review adversarial-review … form is what the sandbox exclusion names; setup installs it. The tool writes nothing to the repository: the brief and the schema live in a temporary directory that is removed afterwards.

Suggest a change