Immutable. This exact content is served forever at /api/v1/blob/9b80ad3f0afe9607.
---
name: cf-plan-review
description: >
Review a saved /cf-plan folder with a fresh reviewer before implementing; triggers "review the plan", "plan review", "second opinion on the plan", "check the plan before implementing", "cf-plan-review"; does NOT review code (use /cf-review).
created: 2026-09-05
updated: 2026-09-05
---
# /cf-plan-review
> **CLI Requirement:** NONE — Works without `coding-friend-cli`. Reads the plan folder and writes `review.md` directly; optional external reviewers are headless CLIs already on PATH. See [CLI requirements](../../../docs/cli-requirements.md) for the full matrix.
Review the plan: **$ARGUMENTS**
## Purpose
Review a saved `/cf-plan` folder (not application code) with a fresh, clean-context subagent of the host that is running this skill. Optionally add external reviewers in parallel. Write `review.md` into the plan folder, then offer to apply Critical/Important findings.
- Unlike `/cf-review`: that skill reviews a code diff. This skill reviews the plan document before implementation.
- Unlike `cf-reviewer-plan`: that agent compares implemented code against the plan. This skill checks the plan itself before any code is written.
## Workflow
### Step 0: Custom Guide
Custom guide — auto-loaded below (if the raw command shows instead of its output, run it yourself):
```!
bash "<plugin-root>/lib/load-custom-guide.sh" cf-plan-review
```
If output is not empty, integrate returned sections: `## Before` → before first step, `## Rules` → apply throughout, `## After` → after final step.
### Step 1: Resolve the plan and flags
Read `docsDir` from `.coding-friend/config.json` (default: `docs`). Prefer `CF_DOCS_ROOT` from bootstrap (`$MAIN_REPO_ROOT/{docsDir}`).
**External reviewer flags:**
- Parse `--codex`, `--gemini`, `--claude`, `--cursor`, `--grok` (and `--with-<agent>` aliases) into `agents=[…]`; strip them from `$ARGUMENTS`.
- **Host-match no-op:** skip a matching flag only when a `HOST:` line exists **and** equals the flag (the flag matching the current host is skipped). Drop that agent and print:
> ⚠ `--<host>` skipped: <Host> is already the in-session reviewer.
No `HOST:` line or a different value → do **NOT** skip. When in doubt, run it.
What remains is `<plan>`.
If `<plan>` is empty: list folders in `{docsDir}/plans/` newest first (`ls -t`) and ask which plan to review using a direct user question.
**Resolve the plan entry file** (same rules as `/cf-plan-resume`):
1. **Resolve the plan entry file**:
- Full path to a folder → use `<folder>/README.md`. Full path to a file → use it directly. Validate the target is within the current working directory or `{docsDir}`; report error and stop if outside.
- Name only (`<slug>`) → first, reject the argument outright if it contains `/`, `\`, or `..` (report: "Invalid plan name — slugs cannot contain path separators or `..`." and stop). This must happen BEFORE constructing any candidate path, since the candidates below are built by directly interpolating `<slug>` — a slug containing `../` would otherwise escape `{docsDir}/plans/`. Once the slug passes this check, resolve in this order, using the first that exists: `{docsDir}/plans/<slug>/README.md` (current layout) → `{docsDir}/plans/<slug>.md` (legacy single-file) → `{docsDir}/plans/<slug>` (append `.md` if it is a bare file).
- If none found → report error and stop.
Read `README.md`, every `phase-N-*.md`, and `brief.md` when present. If `brief.md` is missing, print:
> ℹ️ No brief.md — reviewing README.md and phase files only.
### Step 2: Build the review prompt
```bash
mkdir -p "${CF_DOCS_ROOT}/reviews" && \
bash "<plugin-root>/skills/cf-plan-review/scripts/build-plan-review-prompt.sh" \
<entry-file> <docsDir> \
> "${CF_DOCS_ROOT}/reviews/<slug>-plan-prompt.md"
```
### Step 3: Spawn external reviewers (only when agents non-empty)
Skip when `agents=[]`.
For each agent, spawn one background Bash. Do **not** wait; the harness reports when each finishes. No poll/sleep.
```
run_in_background: true
bash "<plugin-root>/skills/cf-review/scripts/run-agent-review.sh" <agent> "${CF_DOCS_ROOT}/reviews/<slug>-plan-result-<agent>.md" "${CF_DOCS_ROOT}/reviews/<slug>-plan-prompt.md"
```
Proceed immediately to Step 4.
### Step 4: In-session review
Use the `invoke_subagent` with a fresh subagent. Do **not** set `context: fork`. Do **not** pass a `subagent_type`. A fresh default-type subagent inherits this skill's model.
Prompt = the contents of `${CF_DOCS_ROOT}/reviews/<slug>-plan-prompt.md`, plus:
- Spot-check the repo read-only (Read / Glob / Grep). Do not run verify steps. Do not edit files.
- Return exactly the four sections: 🚨 Critical Issues / ⚠️ Important Issues / 💡 Suggestions / 📋 Summary.
Call this result **Source 1**.
### Step 5: Collect external results
Skip when `agents=[]` at spawn time.
Wait for each agent (harness notify — no polling). Read the `CF_AGENT=` line on stderr:
- `ok` → keep the result file.
- `unavailable` → print `> ⚠ <Agent> CLI not found — proceeding without it.` Drop it.
- `timeout` → print `> ⚠ <Agent> review timed out (>Ns) — proceeding without it.` Drop it. (N = `review.agentTimeout`, default 300.)
- `error` → print `> ⚠ <Agent> review failed — proceeding without it.` Drop it.
- `empty` → print `> ⚠ <Agent> returned empty output — proceeding without it.` Drop it.
Never block on an external reviewer — failures degrade gracefully.
### Step 6: Merge
**When no external source survived:** use Source 1 as-is. Do not reformat.
**When any external source survived:** merge via **cf-reviewer-reducer** (`invoke_subagent` with agent `cf-reviewer-reducer`). Source 1 is the in-session report; each surviving external review is a numbered source:
> Merge these review reports into one unified, deduplicated, severity-ranked report.
>
> **Source 1 — in-session plan review:**
> [the full report from Step 4]
>
> **Source K — \<Agent\> review:** (for each surviving external source)
> [raw result file]
>
> Tag each external finding with `[\<Agent\>]` (codex → `[Codex]`, gemini → `[Gemini]`, etc.). Same file:line + same issue → one finding (highest severity) and note agreement. Output 🚨/⚠️/💡/📋.
End the merged report with a banner suffix when any external source contributed:
`· Reviewed by: <in-session label from HOST> + <Agents>`
Label from `HOST` (capitalized); if no `HOST:` line, use `In-session AI`. Omit the suffix when only the in-session reviewer ran.
### Step 7: Save review.md
Write (overwrite on re-run) `{plan-folder}/review.md` with frontmatter `slug`, `date`, `type: plan-review`, `reviewed_by`, then the 4-section report.
Legacy single-file plan → `{docsDir}/plans/<slug>-review.md`.
Delete `${CF_DOCS_ROOT}/reviews/<slug>-plan-prompt.md`. Keep `*-plan-result-*.md` and `.log` sidecars.
### Step 8: Offer to apply findings
If any 🚨 or ⚠️ findings exist, ask with a direct user question: "Apply Critical/Important findings to the plan?"
If the user agrees, edit `README.md` / `phase-N-*.md` yourself (do **not** dispatch cf-implementer). For a legacy single-file plan, edit `<slug>.md`.
**MUST guardrails:**
- Apply only 🚨 Critical and ⚠️ Important findings.
- Never touch `✅ DONE` rows.
- Never touch frontmatter (`slug` / `auto` / `status`).
- Never touch the `## AUTOPILOT` block.
- New tasks are added as `⬜ TODO` rows in Progress **and** numbered entries in Tasks.
- If a finding adds or changes files and `{docsDir}/context/<slug>.json` exists, update its `relevant_files`.
💡 Suggestions are listed only — do not apply them.
After applying (or if the user declines / nothing to apply), print a short summary and:
- Plan already has progress → `> Next: /cf-plan-resume <slug>`
- Plan not yet in execution → remind the user to return to `/cf-plan` Step 7.
## Completion Protocol
- **DONE** — Review saved to `review.md`. Show the 4-section report.
- **DONE_WITH_CONCERNS** — Review saved but 🚨 findings remain unapplied.
- **BLOCKED** — Could not resolve the plan (invalid slug, path outside cwd/`{docsDir}`, or no matching plan).
## Rules
- Do not edit application code. This skill reviews plans, not diffs.
- Do not run verify steps. Reviewers spot-check existence only (files / functions / commands named in tasks).
- Do not review a code diff — send the user to `/cf-review`.
- External reviewers always run sandboxed read-only.
- Never block because an external reviewer is unavailable, timed out, errored, or empty.
- Keep wording host-neutral: the flag matching the current host is skipped; the in-session label comes from `HOST:`.