بنقرة واحدة
create-spec
Interview the user to produce a feature spec, then run multi-model generator and spec review gate
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Interview the user to produce a feature spec, then run multi-model generator and spec review gate
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | create-spec |
| disable-model-invocation | true |
| description | Interview the user to produce a feature spec, then run multi-model generator and spec review gate |
| argument-hint | [--mode <name>] [--max-rounds <N>] <feature description> |
Before running any Bash snippet in this skill, run the shared Cerberus resolver below. It lazily builds and executes bin/cerberus from the configured plugin root.
# --- shared resolver (canonical body; identical across all callers) ---
set +u
if [ -n "${CODEX_THREAD_ID:-}" ] || [ -n "${PLUGIN_ROOT:-}" ]; then
host=codex
elif [ -n "${CLAUDE_SESSION_ID}" ] || [ -n "${CLAUDE_PLUGIN_ROOT}" ] || [ -n "${CLAUDE_SKILL_DIR}" ]; then
host=claude
else
host="${CERBERUS_HOST:-}"
if [ "$host" = claude-code ]; then
host=claude
fi
fi
root="${CERBERUS_ROOT:-}"
if [ -z "$root" ] && [ "$host" = codex ]; then
root="${PLUGIN_ROOT:-}"
fi
if [ -z "$root" ] && [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then
cache_home="${HOME:-}"
[ -n "$cache_home" ] || cache_home="${USERPROFILE:-}"
if [ -n "$cache_home" ]; then
cache_file="$cache_home/.codex/cerberus/sessions/$CODEX_THREAD_ID/plugin-root"
if [ -r "$cache_file" ]; then
IFS= read -r root < "$cache_file" || true
fi
fi
fi
if [ -z "$root" ] && [ "$host" != codex ]; then
root="${CLAUDE_PLUGIN_ROOT}"
[ -n "$root" ] || root="${PLUGIN_ROOT:-}"
fi
if [ -z "$root" ] && [ "$host" != codex ]; then
skill_dir="${CLAUDE_SKILL_DIR}"
if [ -n "$skill_dir" ]; then
root="$(cd "$skill_dir/../.." && pwd)"
fi
fi
[ -n "$root" ] || { echo "cerberus: plugin root not set; set CERBERUS_ROOT and retry" >&2; exit 127; }
bin="$root/bin/cerberus"
export CERBERUS_ROOT="$root"
claude_session="${CLAUDE_SESSION_ID}"
if [ "$host" = claude ]; then
export CERBERUS_HOST=claude
elif [ "$host" = codex ]; then
export CERBERUS_HOST=codex
fi
if [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then
export CERBERUS_HOST=codex CERBERUS_SESSION_ID="$CODEX_THREAD_ID"
elif [ "$host" = claude ] && [ -n "$claude_session" ]; then
export CERBERUS_HOST=claude CERBERUS_SESSION_ID="${CERBERUS_SESSION_ID:-$claude_session}"
fi
command -v make >/dev/null 2>&1 || { echo "cerberus: make not found on PATH; install make and retry." >&2; exit 127; }
if ! make -q -C "$root" build >/dev/null 2>&1; then
command -v go >/dev/null 2>&1 || { echo "cerberus: Go >= 1.22 not found on PATH; install Go and retry." >&2; exit 127; }
echo "cerberus: building... (this happens once after clone or upgrade)" >&2
start=$(date +%s)
make -C "$root" build >&2 || exit $?
end=$(date +%s)
echo "cerberus: build complete in $((end-start))s" >&2
fi
# --- shared resolver above; per-caller exec below (allowed to diverge) ---
exec "$bin" "$@"
Use bin/cerberus through the configured plugin root when invoking Cerberus commands below.
Transform a vague feature idea into a complete, reviewable specification by combining codebase research, a targeted interview, multi-model generation, and a spec review gate.
Specs scale with complexity. Start minimal and expand as signals emerge.
| Tier | Use Case | What's Required |
|---|---|---|
| S | Bug fix, tiny tweak | Problem, change summary, scope boundary, UX impact, 2-5 acceptance bullets, validation method, open questions |
| M | Small feature, single flow | S + Goal, success criteria, non-goals, primary flow, key states, 3-7 requirements with MUST + verification examples, basic instrumentation |
| L | Multi-flow, high-risk project | M + Constraints, alternate flows, full Given/When/Then, edge cases per requirement, detailed instrumentation, launch checklist |
Canonical field mapping:
Score these signals during the interview. Suggest tier upgrade if score exceeds threshold.
| Signal | Points |
|---|---|
| New user-facing flow or screen | +2 |
| Changes to data model / schema | +2 |
| Involves auth, security, payments, compliance | +2 |
| Impacts multiple user flows or personas | +2 |
| Integrates with external or multiple internal services | +1 |
| Needs new analytics or A/B experiment | +1 |
| Requires feature flags or data migration | +1 |
| Multiple teams or owners involved | +1 |
Score → Tier: 0-1 = S, 2-4 = M, 5+ = L
If detected tier differs from apparent scope, confirm with user:
"This looks like it touches multiple flows and data models. Should we expand to a fuller spec? (yes/no)"
If user declines an upgrade:
If user requests a downgrade:
Reviewers and tier overrides:
Modes only select a model panel from config.yaml. Mode names do not alter interview depth, tier, priority scope, or refinement policy, so custom modes behave exactly like built-in modes.
Interview depth follows the selected spec tier and the user's stop signals. Override: --max-rounds <N> sets the review round cap explicitly, overriding defaults.max_rounds. Accepts any integer >= 0; 0 runs the initial review once and disables refinement respawns.
The user provides a brief feature description inline, e.g.:
Before Phase 1, parse command arguments:
MODE only when an explicit --mode <name> flag is present; otherwise leave it unset so config.yaml can supply defaults.mode.--mode <name> and --max-rounds <N> from the feature description before writing the spec.--max-rounds <N> separately as MAX_ROUNDS for the review gate.Before asking any questions, understand the existing codebase:
Document findings internally—these inform the skeleton and your questions.
Goal: Identify codebase-aware constraints on WHAT to build, not HOW to build it.
This phase prevents specs that imply new infrastructure when stakeholders/architecture require extending existing systems. The spec captures constraints and expectations; the plan makes detailed integration decisions.
Identify existing mechanisms relevant to this feature:
Document integration expectations as constraints:
Capture in spec (Constraints, Non-goals, or Open Questions):
Important: The spec should avoid binding to specific modules/file paths unless they are product-level constraints. Detailed extend-vs-new decisions belong in the plan.
Create a skeleton based on your research. Start with Tier S fields; expand as complexity signals emerge.
IMPORTANT: When you finish Phase 1b:
docs/YYYY-MM-DD-FEATURE-spec.md) — this becomes the canonical doc[TBD] placeholders — fill them only after user answers in Phase 2AskUserQuestionPHASE 2 GATE: After sending Interview Batch 1, end your turn immediately. Do not proceed to Phase 3+ until the user answers or issues a stop signal. This gate is mandatory.
# [Feature Name]
**Tier:** S / M / L (auto-detected, confirm with user)
**Owner:** [TBD or pre-fill from research]
**Target ship:** [TBD]
**Links:** [Figma, ticket, related docs]
## 1. Outcome & Scope
**Problem / context** *(S/M/L)*
[TBD: What's broken/missing today? Who is impacted?]
**Change summary** *(S only — omit for M/L)*
[TBD: What are we changing and why?]
**Goal** *(M/L)*
[TBD: "Enable <user> to <do X> so that <benefit>."]
**Success criteria** *(M/L)*
- [TBD: Metric + threshold + timeframe]
**Non-goals** *(M/L)*
- [TBD or inferred from research]
**Constraints** *(L only)*
- Compatibility: [TBD: Any existing clients/integrations affected?]
- [Other constraints: performance, security, environment]
**Scope boundary** *(S only — omit for M/L)*
[TBD: "Only affects X; does not change Y/Z."]
## 2. User Experience & Flows
**UX impact** *(S only)*
- User-visible? (yes/no): [TBD]
- If yes: [TBD: "When user does A, they now see B instead of C."]
**Primary flow** *(M/L)*
1. [TBD]
2. [TBD]
3. [TBD]
**Key states** *(M/L)*
- Empty state: [TBD]
- Loading state: [TBD]
- Success state: [TBD]
- Error state(s): [TBD]
**Alternate flows** *(L only)*
- [TBD: What if user cancels? Lacks permission? Partial completion?]
## 3. Requirements + Verification
*(Tier S: Use simple acceptance bullets)*
*(Tier M/L: Use numbered requirements with MUST statements)*
**Acceptance criteria** *(S)*
- [TBD: When user does X in situation Y, Z happens]
- [TBD: Also verify these still work: ...]
**R1 — [Short name]** *(M/L)*
- **Requirement:** The system MUST [TBD]
- **Verification:** *(M: example or single GWT; L: full GWT)*
- Given [TBD], When [TBD], Then [TBD]
- **Edge cases:** *(L only)* [TBD]
**R2 — [Short name]** *(M/L)*
- **Requirement:** The system MUST [TBD]
- **Verification:**
- Given [TBD], When [TBD], Then [TBD]
- **Edge cases:** *(L only)* [TBD]
## 4. Instrumentation & Release Checks
**Validation after release** *(S)*
- How to confirm this worked: [TBD: "Try scenario X in env Y"]
- Known risks / blast radius: [TBD]
**Instrumentation** *(M/L)*
- Events to track: [TBD: feature entry, completion, failure reasons]
**Launch checklist** *(L only)*
- [ ] All MUST requirements verifiable
- [ ] Key error states covered
- [ ] Metrics available to confirm success criteria
- [ ] Rollback condition defined
**Decisions made** *(S/M/L)*
- [Record "you decide" / "whatever's standard" resolutions here]
**Open questions** *(S/M/L)*
- [List unknowns from research]
Skeleton rules:
[TBD] or [TBD: hint about what's needed]Load the interview engine: Read ${CLAUDE_PLUGIN_ROOT}/prompts/interview-engine.md for the full mechanism. Key principles below.
IMPORTANT: Use the AskUserQuestion tool for ALL interview questions. Put coverage + numbered questions + off-ramp in a single tool call. Plain text questions are not interactive.
Ask questions in order of priority (P0-P3) and depth (L0-L3), with breadth across topics before depth in any single topic.
| Priority | What | Examples |
|---|---|---|
| P0 | Blockers / correctness | Scope boundaries, acceptance criteria, backwards compatibility |
| P1 | Major design | Primary flow, testing strategy, success criteria |
| P2 | Edge cases | Alternate flows, failure modes, observability |
| P3 | Polish | Ergonomics, minor UX improvements |
| Depth | Scope | Examples |
|---|---|---|
| L0 | Vision / outcome | What problem? Who? Definition of done? |
| L1 | Behavior / approach | Primary flow, key states, acceptance criteria shape |
| L2 | Decomposition | Requirement breakdown, GWT examples, test layers |
| L3 | Implementation details | Exact event schemas, precise error codes, rollout mechanics |
Anti-deep-dive rule: Don't ask L2 for Topic A until all P0 topics have L1 coverage.
| Signal Type | Trigger Phrases | Action |
|---|---|---|
| Global stop | "enough detail", "that's enough", "stop here", "we're good", "ship it" | End interview, remaining TBDs → Open Questions |
| Depth cap | "keep it high-level", "stop at L1", "no deep dive", "details later" | Set max_depth, continue within cap |
| Priority cap | "skip P2/P3", "just blockers", "P0/P1 only" | Set max_priority, lower items → Open Questions |
| Per-topic stop | "enough about testing", "park observability", "skip auth" | Mark topic capped, continue others |
| Per-question skip | "skip this one", "next question" | Mark TBD as Open Question, no follow-ups |
| Delegation | "you decide", "whatever's standard" | Pick safe default, record in Decisions |
| Uncertainty | "I don't know" | Offer 2-3 options; if declined → Open Question |
Present questions with context and an explicit off-ramp:
**Interview Batch [N]** (Priority: P0, Depth: L0)
Current coverage: [P0 in progress at L0]
Questions (answer any, skip any):
1. [Topic: Scope] What's explicitly out of scope?
- Options: [A] Exclude X and Y, [B] Exclude only X, [C] You decide
2. [Topic: Requirements] What MUST the system guarantee?
- Evidence: Similar features use [pattern] — should we follow that?
3. [Topic: Verification] How will we validate this works?
- Options: [A] Manual QA, [B] E2E tests, [C] Both
---
Reply using `1: <answer> 2: <answer>` format (skip numbers to leave as Open Questions).
Or say "enough detail" to stop, "keep it high-level" to cap depth.
Tier S (P0/L0-L1):
Tier M (add P1/L1-L2):
Tier L (add P2/L2-L3):
Tier upgrade prompt: When complexity signals accumulate:
"This touches [signals]. Want to expand to Tier M/L for [additional coverage]?"
| User says... | You should... |
|---|---|
| "You decide" | Pick safe default, record in Decisions, stop deeper |
| "I don't know" | Offer 2-3 options with tradeoffs |
| "Whatever's standard" | Use codebase conventions, record decision |
| "Skip this" | Record as Non-Goal or Open Question |
| Stop signal | End interview or cap depth immediately |
Create a compact context block for generators:
Context Checklist by Tier:
Tier S:
Tier M (add to S):
Tier L (add to M):
Create, populate, and remember a temporary prompt file for concatenating the base prompt with your context:
CRITICAL: Tool/Bash calls do not share exported variables. Do not create PROMPT_TMP in one Bash call and then use $PROMPT_TMP in a later Bash call unless you explicitly re-export the printed literal path in that same later call. Prefer the single Bash block below, which keeps creation and population in one shell process.
CRITICAL: The command MUST start with an executable, NOT a bare variable assignment. Variable assignments trigger permission prompts.
env bash -lc 'set -euo pipefail
PROMPT_TMP="$(mktemp "${TMPDIR:-/tmp}/create-spec-prompt-XXXXXX")"
test -f "$PROMPT_TMP"
set +u
if [ -n "${CODEX_THREAD_ID:-}" ] || [ -n "${PLUGIN_ROOT:-}" ]; then host=codex; elif [ -n "${CLAUDE_SESSION_ID}" ] || [ -n "${CLAUDE_PLUGIN_ROOT}" ] || [ -n "${CLAUDE_SKILL_DIR}" ]; then host=claude; else host="${CERBERUS_HOST:-}"; if [ "$host" = claude-code ]; then host=claude; fi; fi; root="${CERBERUS_ROOT:-}"; if [ -z "$root" ] && [ "$host" = codex ]; then root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then cache_home="${HOME:-}"; [ -n "$cache_home" ] || cache_home="${USERPROFILE:-}"; if [ -n "$cache_home" ]; then cache_file="$cache_home/.codex/cerberus/sessions/$CODEX_THREAD_ID/plugin-root"; if [ -r "$cache_file" ]; then IFS= read -r root < "$cache_file" || true; fi; fi; fi; if [ -z "$root" ] && [ "$host" != codex ]; then root="${CLAUDE_PLUGIN_ROOT}"; [ -n "$root" ] || root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" != codex ]; then skill_dir="${CLAUDE_SKILL_DIR}"; if [ -n "$skill_dir" ]; then root="$(cd "$skill_dir/../.." && pwd)"; fi; fi; [ -n "$root" ] || { echo "cerberus: plugin root not set; set CERBERUS_ROOT and retry" >&2; exit 127; }
cat "$root/prompts/generators/create-spec.md" > "$PROMPT_TMP"
cat >> "$PROMPT_TMP" <<'"'"'EOF'"'"'
## Context
EOF
printf "PROMPT_TMP=%s\n" "$PROMPT_TMP"'
This creates a unique temp file like /tmp/create-spec-prompt-abc123. Do not use a top-level PROMPT_TMP=$(mktemp ...) assignment, and do not add a suffix like .md; BSD/macOS mktemp only replaces trailing X characters.
Record the printed PROMPT_TMP=... value. In subsequent Bash calls, substitute the actual printed path (for example /tmp/create-spec-prompt-abc123) or start that same call with export PROMPT_TMP='/tmp/create-spec-prompt-abc123' && .... Never assume $PROMPT_TMP still exists from an earlier tool call.
Now append the Phase 3 context (skeleton + findings + answers) to the actual prompt file path printed above. Substitute the printed path in this same Bash call:
: "${PROMPT_TMP:=<paste the printed /tmp/create-spec-prompt-... path here>}" && export PROMPT_TMP && cat >> "$PROMPT_TMP" <<'EOF'
[Paste Phase 3 context here]
EOF
Spawn generators with the mode flag. The cerberus generate subcommand resolves the selected panel from config.yaml and manages provider execution internally.
CRITICAL: The command MUST start with an executable, NOT a variable assignment. Variable assignments trigger permission prompts.
: "${PROMPT_TMP:=<paste the printed /tmp/create-spec-prompt-... path here>}" && export PROMPT_TMP && export OUTPUT_PARENT="${REVIEW_DIR:-${TMPDIR:-/tmp}}" && mkdir -p "$OUTPUT_PARENT" && export OUTPUT_DIR="$(mktemp -d "$OUTPUT_PARENT/create-spec-drafts-XXXXXX")" && test -d "$OUTPUT_DIR" && printf 'OUTPUT_DIR=%s\n' "$OUTPUT_DIR" && MODE_ARGS=() && if [ -n "${MODE:-}" ]; then MODE_ARGS=(--mode "$MODE"); fi && set +u; if [ -n "${CODEX_THREAD_ID:-}" ] || [ -n "${PLUGIN_ROOT:-}" ]; then host=codex; elif [ -n "${CLAUDE_SESSION_ID}" ] || [ -n "${CLAUDE_PLUGIN_ROOT}" ] || [ -n "${CLAUDE_SKILL_DIR}" ]; then host=claude; else host="${CERBERUS_HOST:-}"; if [ "$host" = claude-code ]; then host=claude; fi; fi; root="${CERBERUS_ROOT:-}"; if [ -z "$root" ] && [ "$host" = codex ]; then root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then cache_home="${HOME:-}"; [ -n "$cache_home" ] || cache_home="${USERPROFILE:-}"; if [ -n "$cache_home" ]; then cache_file="$cache_home/.codex/cerberus/sessions/$CODEX_THREAD_ID/plugin-root"; if [ -r "$cache_file" ]; then IFS= read -r root < "$cache_file" || true; fi; fi; fi; if [ -z "$root" ] && [ "$host" != codex ]; then root="${CLAUDE_PLUGIN_ROOT}"; [ -n "$root" ] || root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" != codex ]; then skill_dir="${CLAUDE_SKILL_DIR}"; if [ -n "$skill_dir" ]; then root="$(cd "$skill_dir/../.." && pwd)"; fi; fi; [ -n "$root" ] || { echo "cerberus: plugin root not set; set CERBERUS_ROOT and retry" >&2; exit 127; }; bin="$root/bin/cerberus"; export CERBERUS_ROOT="$root"; claude_session="${CLAUDE_SESSION_ID}"; if [ "$host" = claude ]; then export CERBERUS_HOST=claude; elif [ "$host" = codex ]; then export CERBERUS_HOST=codex; fi; if [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then export CERBERUS_HOST=codex CERBERUS_SESSION_ID="$CODEX_THREAD_ID"; elif [ "$host" = claude ] && [ -n "$claude_session" ]; then export CERBERUS_HOST=claude CERBERUS_SESSION_ID="${CERBERUS_SESSION_ID:-$claude_session}"; fi; command -v make >/dev/null 2>&1 || { echo "cerberus: make not found on PATH; install make and retry." >&2; exit 127; }; if ! make -q -C "$root" build >/dev/null 2>&1; then command -v go >/dev/null 2>&1 || { echo "cerberus: Go >= 1.22 not found on PATH; install Go and retry." >&2; exit 127; }; echo "cerberus: building... (this happens once after clone or upgrade)" >&2; start=$(date +%s); make -C "$root" build >&2 || exit $?; end=$(date +%s); echo "cerberus: build complete in $((end-start))s" >&2; fi; "$bin" generate "$OUTPUT_DIR" --type create-spec "${MODE_ARGS[@]}" --prompt-file "$PROMPT_TMP"
Record the printed OUTPUT_DIR=... value, then read the draft.md paths cerberus generate prints to stdout — one line per drafter that succeeded. The panel comes from the selected mode in config.yaml (falling back to claude + codex + gemini), so the set of directories is dynamic: each drafter writes to $OUTPUT_DIR/<label>/draft.md, where <label> is the provider name, with additional same-provider instances suffixed (for example codex and codex-2). Use exactly the paths printed; do not assume a fixed list. Do not pass literal $OUTPUT_DIR/... paths to a subagent unless you have replaced $OUTPUT_DIR with the actual printed directory.
IMPORTANT: The tool result contains only file paths, not the full draft content. This preserves your context window.
You MUST use a subagent (Task tool) to synthesize drafts. This preserves your main context for the review gate phase.
Use the Task tool with a prompt like:
Synthesize the following generator drafts into the spec file.
Draft files to read:
[Paste the actual draft.md paths printed by `cerberus generate` — one per successful drafter. The panel is whatever the selected `config.yaml` mode resolves to; the example shape below may differ from your run.]
- /actual/output/dir/claude/draft.md
- /actual/output/dir/codex/draft.md
- /actual/output/dir/codex-2/draft.md
Spec file to update: docs/YYYY-MM-DD-FEATURE-spec.md
Tier: [S/M/L]
Synthesis rules:
1. Use the existing spec file as canonical structure — don't invent new sections
2. Identify common conclusions across drafts for each section
3. Resolve conflicts by checking the codebase and user answers
4. Fill remaining [TBD] placeholders with synthesized content or mark as Open Questions
5. Include only sections required for the tier (see tier requirements below)
6. Tier-specific verification:
- Tier S: Simple acceptance bullets, no formal requirements
- Tier M: Requirements with MUST + verification examples (GWT optional)
- Tier L: Requirements with MUST + full Given/When/Then + edge cases per requirement
7. Include alternatives considered and risk analysis when the selected tier or feature complexity requires them
Update the spec file in place with the synthesized content.
Return a summary of key decisions made during synthesis.
The subagent will:
Delegate draft reading to the subagent — reading drafts yourself would consume your context. The subagent reads drafts, synthesizes, and returns a summary.
The subagent updated the spec file in Phase 5. Confirm the [TBD] placeholders have been filled.
Spawn external reviewers on the spec file. Forward --max-rounds only when the user supplied an explicit command-level override:
--max-rounds <N> was passed to this command, forward that N.config.yaml and the CLI defaults remain authoritative for built-in and custom modes.set +u; if [ -n "${CODEX_THREAD_ID:-}" ] || [ -n "${PLUGIN_ROOT:-}" ]; then host=codex; elif [ -n "${CLAUDE_SESSION_ID}" ] || [ -n "${CLAUDE_PLUGIN_ROOT}" ] || [ -n "${CLAUDE_SKILL_DIR}" ]; then host=claude; else host="${CERBERUS_HOST:-}"; if [ "$host" = claude-code ]; then host=claude; fi; fi; root="${CERBERUS_ROOT:-}"; if [ -z "$root" ] && [ "$host" = codex ]; then root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then cache_home="${HOME:-}"; [ -n "$cache_home" ] || cache_home="${USERPROFILE:-}"; if [ -n "$cache_home" ]; then cache_file="$cache_home/.codex/cerberus/sessions/$CODEX_THREAD_ID/plugin-root"; if [ -r "$cache_file" ]; then IFS= read -r root < "$cache_file" || true; fi; fi; fi; if [ -z "$root" ] && [ "$host" != codex ]; then root="${CLAUDE_PLUGIN_ROOT}"; [ -n "$root" ] || root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" != codex ]; then skill_dir="${CLAUDE_SKILL_DIR}"; if [ -n "$skill_dir" ]; then root="$(cd "$skill_dir/../.." && pwd)"; fi; fi; [ -n "$root" ] || { echo "cerberus: plugin root not set; set CERBERUS_ROOT and retry" >&2; exit 127; }; bin="$root/bin/cerberus"; export CERBERUS_ROOT="$root"; claude_session="${CLAUDE_SESSION_ID}"; if [ "$host" = claude ]; then export CERBERUS_HOST=claude; elif [ "$host" = codex ]; then export CERBERUS_HOST=codex; fi; if [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then export CERBERUS_HOST=codex CERBERUS_SESSION_ID="$CODEX_THREAD_ID"; elif [ "$host" = claude ] && [ -n "$claude_session" ]; then export CERBERUS_HOST=claude CERBERUS_SESSION_ID="${CERBERUS_SESSION_ID:-$claude_session}"; fi; command -v make >/dev/null 2>&1 || { echo "cerberus: make not found on PATH; install make and retry." >&2; exit 127; }; if ! make -q -C "$root" build >/dev/null 2>&1; then command -v go >/dev/null 2>&1 || { echo "cerberus: Go >= 1.22 not found on PATH; install Go and retry." >&2; exit 127; }; echo "cerberus: building... (this happens once after clone or upgrade)" >&2; start=$(date +%s); make -C "$root" build >&2 || exit $?; end=$(date +%s); echo "cerberus: build complete in $((end-start))s" >&2; fi; MODE_ARGS=(); if [ -n "${MODE:-}" ]; then MODE_ARGS=(--mode "$MODE"); fi; ROUND_ARGS=(); if [ -n "${MAX_ROUNDS:-}" ]; then ROUND_ARGS=(--max-rounds "$MAX_ROUNDS"); fi; "$bin" spawn-spec-review "${MODE_ARGS[@]}" "${ROUND_ARGS[@]}" docs/YYYY-MM-DD-FEATURE-spec.md
CRITICAL: After running the spawn command, STOP IMMEDIATELY. Do NOT poll, sleep, wait, or run any further commands. The Stop hook will automatically wait for reviewers and present their findings when you stop. Any attempt to manually check reviewer status will fail.
IMPORTANT: Use the AskUserQuestion tool for ALL clarifying questions during review. Put findings + options in a single tool call. Plain text questions are not interactive.
Treat reviewer findings as a queue, just like interview questions. Process them in priority-first, breadth-first order:
Priority definitions:
**Review Findings Batch [N]** (Priority: P0)
Reviewers found 2 P0 issues and 3 P1 issues. Let's address P0s first:
1. [Section: Scope] Unclear what happens when user cancels mid-flow
- Options: [A] Rollback to last save, [B] Discard changes, [C] You decide
2. [Section: Requirements] R2 has no verification method
- Options: [A] Add unit test, [B] Add E2E test, [C] Manual validation
---
Reply "enough detail" to stop drilling into fixes, or "skip P2/P3" to focus only on blockers.
| Signal | Action |
|---|---|
| "enough detail" / "that's good" | Stop asking about remaining issues, mark as Open Questions |
| "skip P2/P3" / "just fix blockers" | Only address P0/P1, leave rest as future improvements |
| "you decide" | Pick safe fix, record in Decisions Made |
DO:
Always ask for user input on:
OK to silently fix: Typos, formatting, and purely mechanical issues.
Use the gate's resolved round cap from explicit --max-rounds <N> or config.yaml/CLI defaults. Process findings in priority order regardless of mode name. If the cap is reached, record unresolved findings as Open Questions or future improvements. --max-rounds 0 runs the initial review once, records its unresolved findings, and performs no refinement respawn.
When the spec passes review, summarize the final spec and offer to proceed with implementation.
Ask the Cerberus model panel an arbitrary question
Produce a technical implementation plan (design-focused), optionally interviewing the user, then run multi-model generator and plan review gate
Iterative code review with external reviewers
Iterative plan review with external reviewers
Iterative spec review with external reviewers
Verify epic acceptance criteria against the codebase with multi-model consensus