skills/parallel-review-plan/SKILL.md
Independent plan review producing structured findings per review-findings.schema.json
npx skillsauth add jankneumann/agentic-coding-tools parallel-review-planInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Receive plan artifacts as read-only input and produce structured findings conforming to review-findings.schema.json. Designed for vendor-diverse dispatch — any LLM agent can execute this skill.
$ARGUMENTS - OpenSpec change-id to review (e.g., "add-user-authentication")
Optional flags:
--adversarial — Use adversarial review mode: challenges design decisions instead of standard reviewopenspec/changes/<change-id>//parallel-plan-feature or /linear-plan-featurePlan review uses the provider-neutral dispatch adapter/configuration path as the canonical cross-provider mechanism. Claude Code, Codex, and Gemini/Jules are first-class reviewers when configured; provider-specific CLI or harness details stay inside their adapters.
The reviewer receives these artifacts as context but MUST NOT modify them:
openspec/changes/<change-id>/proposal.mdopenspec/changes/<change-id>/design.mdopenspec/changes/<change-id>/tasks.mdopenspec/changes/<change-id>/specs/**/spec.mdopenspec/changes/<change-id>/contracts/ (if present)openspec/changes/<change-id>/work-packages.yaml (if present)Every finding produced by this skill MUST be classified into BOTH dimensions below. The JSON Schema at openspec/schemas/review-findings.schema.json enforces both fields as required — output that omits either is rejected by the validator in Step 4.
axis field)Adopted from the code-review-and-quality reference skill. Pick exactly one:
| Axis | What it covers |
|---|---|
| correctness | Does the plan, when implemented, produce the right answer? Bugs, off-by-one, missing requirements, ambiguous SHALL clauses. |
| readability | Will a future reader understand intent? Naming, structure, spec clarity, ambiguous prose. |
| architecture | Does the design fit the system? Module boundaries, layering, coupling, dependency direction, contract shape. |
| security | Does the plan introduce or fail to prevent security risk? Auth gaps, input-validation holes, secret handling, OWASP categories. |
| performance | Will the implementation be fast and scalable enough? N+1, unbounded queries, missing pagination, hot-path allocations. |
The legacy type enum (spec_gap, contract_mismatch, etc. — see Step 3) is preserved for backward compatibility; axis is the new mandatory categorization that all reviewers — human or vendor — must agree on.
severity field)Every finding's description MUST begin with one of these markers. The severity enum value MUST match the prefix.
| Prefix | Severity value | Meaning |
|---|---|---|
| Critical | critical | Blocks merge. Must be fixed before implementation begins (or before the PR merges). |
| Nit | nit | Should fix but does not block. Quality, naming, minor structure. |
| Optional | optional | Consider it. Author may accept or reject without further discussion. |
| FYI | fyi | Informational. Surfaces context the author may not have known; no action required. |
| none | none | Positive observation. Names what the plan got right so good patterns survive review. |
Example finding (note prefix and matching severity):
{
"id": 1,
"axis": "security",
"severity": "critical",
"type": "security",
"criticality": "high",
"description": "Critical: Requirement R3 admits unauthenticated DELETE on /v1/users/{id} — missing auth precondition.",
"resolution": "Add a SHALL clause requiring an authenticated session with role=admin before the DELETE handler executes.",
"disposition": "fix"
}
Reviewers MUST NOT collapse multiple severities onto one finding (split them). Reviewers MUST NOT use a severity that contradicts the disposition (e.g., severity: critical with disposition: accept is incoherent — escalate instead).
Read all plan artifacts listed above. Build a mental model of:
Evaluate the plan against these dimensions:
Generate findings as a JSON array conforming to review-findings.schema.json:
{
"review_type": "plan",
"target": "<change-id>",
"reviewer_vendor": "<model-name>",
"findings": [
{
"id": 1,
"type": "spec_gap",
"criticality": "high",
"description": "Requirement R3 lacks error handling specification for 429 rate limit responses",
"resolution": "Add a requirement specifying retry-after header handling",
"disposition": "fix"
}
]
}
spec_gap — Missing or incomplete requirementscontract_mismatch — Inconsistency between contracts and specsarchitecture — Design pattern or structural concernsecurity — Security vulnerability or missing protectionperformance — Potential performance issuestyle — Code style or convention violationcorrectness — Logical error in the planobservability — Missing monitoring, logging, or alerting requirementscompatibility — Breaking change to existing API or missing migration planresilience — Missing retry, timeout, or fallback requirementsfix — Author should fix before implementationregenerate — Artifact needs regeneration (e.g., contract schema mismatch)accept — Minor issue, acceptable as-isescalate — Requires human decision or cross-team coordinationValidate the findings JSON against openspec/schemas/review-findings.schema.json:
# Quick validation
python3 -c "
import json, jsonschema
schema = json.load(open('openspec/schemas/review-findings.schema.json'))
findings = json.load(open('<findings-output-path>'))
jsonschema.validate(findings, schema)
print('Valid')
"
Write findings to openspec/changes/<change-id>/review-findings-plan.json.
If CAN_HANDOFF=true, write a review handoff with:
After writing your own findings, dispatch reviews to other vendor CLIs and synthesize consensus.
Write the review prompt to openspec/changes/<change-id>/reviews/review-prompt.md — include instructions to read the plan artifacts and output only valid JSON conforming to review-findings.schema.json.
Adversarial mode: If --adversarial flag was passed, wrap the review prompt with adversarial framing before dispatch:
from adversarial_prompt import wrap_adversarial
prompt = wrap_adversarial(prompt) # Prepends contrarian persona instructions
The dispatch still uses --mode review (unchanged) — only the prompt content differs. Adversarial findings flow through the same consensus pipeline with equal weight (Design Decision D1).
Dispatch to other vendors (excluding the current agent's vendor):
python3 "<skill-base-dir>/../parallel-infrastructure/scripts/review_dispatcher.py" \
--review-type plan \
--mode review \
--prompt-file "openspec/changes/<change-id>/reviews/review-prompt.md" \
--cwd "$(pwd)" \
--output-dir "openspec/changes/<change-id>/reviews" \
--exclude-vendor claude_code \
--timeout 600
This dispatches to all available vendors configured in agents.yaml with cli sections. Each vendor runs independently and writes findings to reviews/findings-<vendor>-plan.json.
Agent discovery resolution chain: The dispatcher resolves agents via the coordination MCP server configured in ~/.claude.json → mcpServers.coordination. It extracts the agent-coordinator/ directory from the MCP server args and runs get_dispatch_configs.py to load agents.yaml. If the coordinator is not configured, pass --agents-yaml <path> explicitly as fallback. Use --list-agents to verify available agents.
Troubleshooting dispatch failures: Run python3 <script> --list-agents to verify agent discovery. Common issues: (1) ~/.claude.json has no mcpServers.coordination entry — run /setup-coordinator, (2) async/remote agents may time out — local agents are more reliable, (3) some vendors may return non-JSON output — check review-manifest.json for error details.
Synthesize consensus from all findings (yours + vendor results):
python3 "<skill-base-dir>/../parallel-infrastructure/scripts/consensus_synthesizer.py" \
--review-type plan \
--target "<change-id>" \
--findings "openspec/changes/<change-id>/review-findings-plan.json" \
"openspec/changes/<change-id>/reviews/findings-"*"-plan.json" \
--output "openspec/changes/<change-id>/reviews/consensus-plan.json"
Present consensus summary to the user:
If no other vendors are available (CLIs not installed), skip this step and proceed with single-vendor findings only.
openspec/changes/<change-id>/review-findings-plan.json — your findingsopenspec/changes/<change-id>/reviews/findings-<vendor>-plan.json — per-vendor findingsopenspec/changes/<change-id>/reviews/consensus-plan.json — synthesized consensusopenspec/changes/<change-id>/reviews/review-manifest.json — dispatch metadataThis skill is intentionally simple and self-contained so it can be dispatched to any LLM agent:
When this skill is dispatched to another vendor by the orchestrator, only Steps 1-5 run (the vendor produces findings). Step 6 (multi-vendor dispatch) only runs when this skill is the primary reviewer — i.e., when invoked directly by the user or the orchestrating agent.
| Rationalization | Why it's wrong |
|---|---|
| "I only found one issue, so I'll skip the axis/severity classification — the description is enough" | The schema rejects findings without axis and severity; cross-vendor consensus relies on these fields to match equivalent findings. Skipping = the dispatcher discards your review. |
| "This finding spans two axes — I'll just pick one" | Pick the dominant axis and split the rest into separate findings. Mashing two axes into one description means consensus matching cannot deduplicate against another vendor who split them. |
| "The plan looks fine — I'll just emit zero findings" | A review with zero findings is suspicious. At minimum, emit severity: none positive observations naming what the plan got right; this signals the review actually happened rather than timed out. |
| "The orchestrator will catch contradictions between severity and disposition" | It won't — the orchestrator routes by disposition. Inconsistent severity/disposition pairs survive into the consensus and confuse downstream automation. Make them coherent at write time. |
review-findings-plan.json file with findings that lack the axis field — the schema validation step (Step 4) was skipped or its output ignored.Critical). A real review covers a spectrum; uniform severity means the reviewer wasn't actually grading.Critical: / Nit: / Optional: / FYI: / nothing-for-none). The prefix is the human-readable signal; if it disagrees with the enum value, the reviewer wrote the JSON without re-reading the prose.security-axis finding with disposition: accept. Security findings are never silently accepted; if the risk is real, the disposition must be fix or escalate.Valid — this proves axis and severity are present on every finding.description text begins with the prefix matching the severity enum value (e.g., severity: critical ↔ description starts with Critical:).axis values appear across the findings array (a single-axis review missed the other four dimensions of the schema).disposition is coherent with severity: critical/nit → fix; optional/fyi → accept; none → accept; mismatches must be escalate with a justification in resolution.reviewer_vendor is populated — anonymous findings cannot participate in consensus.development
Open the artifacts relevant to a review (OpenSpec proposal, branch changes, or explicit paths) in VS Code, in a curated read-order, in the right worktree.
tools
Render and seed coordinator-owned task status block in OpenSpec tasks.md
testing
User-invocable skill that omits the tail block
tools
Missing several required keys