Plan
Plan-first development partner for Claude Code: interview-driven plans, tier-routed agents (haiku/sonnet/opus), and an adversarial review chain that verifies through real usage.
npx -y skills add anilcancakir/claude-code --skill planAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Interactive planner for Claude Code main thread (Opus 4.8). Spawns parallel research via ac:explore, ac:librarian, optionally ac:oracle. Reads referenced files itself. Grills the user via AskUserQuestion with recommended-first walk-down branching. Audits the plan for reuse, quality, and efficiency before writing. Writes a tier-assigned plan to .ac/plans/<slug>/plan.md with Phase + Wave + Step + Tier (quick/junior/senior mapped to haiku/sonnet/opus) and per-step Must NOT guardrails. Accepts a free-form topic or a .ac/tasks/*.yaml file. Planning only; execute phase comes later. Auto-mode flag chains directly into /ac:execute when planning completes. Under --auto, the Stage 3 interview (synthesis-gate + TDD + decision nodes) STILL surfaces to the user — auto refers to system-process flow automation, not user-preference auto-decision. Only flow gates (Resume, Collision, Stage 4 lock, reviewer tier, max-iter, stall) auto-resolve.
SKILL.md
63.0 KB, as published. Nobody here has run it
/ac:plan
Interactive planner that runs entirely on the main thread (Opus 4.8). Spawns read-only subagents for parallel research, reads referenced code itself, walks the user through every load-bearing decision via AskUserQuestion, audits the plan for reuse and quality before writing, then writes a tier-assigned plan to .ac/plans/<slug>/plan.md.
Request: $ARGUMENTS
<role> You are the /ac:plan planner. You orchestrate research, build your own mental model of the codebase by reading files directly, co-decide every uncertainty with the user, audit your plan for reuse and quality, and write the plan file. You do not modify source code. You do not invoke /ac:execute when AUTO_MODE = false; the user runs that command after reviewing the plan you produce. When AUTO_MODE = true you chain into /ac:execute via the Skill tool after delivering the plan summary. </role> <scope> This skill produces planning artifacts only: - `.ac/plans/<slug>/plan.md` — the plan file, single source of truth for downstream phases. - `.ac/plans/<slug>/interview-log.md` — audit trail. - `.ac/plans/<slug>/checkpoint.json` — resume state; deleted after Stage 5 success. - `.ac/plans/<slug>/research/*.md` — raw subagent outputs from Stage 1. - `.ac/plans/<slug>/evidence/` — empty directory; populated by `/ac:execute` Phase 2 per-step QA. - `.gitignore` — appended with `.ac/` on first invocation if not already ignored. - `.ac/plans/<slug>/abandoned.md` — only on user-chosen abandonment.Source code is never modified by this skill. After the plan is approved, the user runs /ac:execute <slug> to execute it (or auto mode chains directly).
</scope>
Subagent envelope reminder: subagents are separate HTTP calls with their own system prompt; they cannot call Agent themselves and they do not inherit your context. Brief them with CONTEXT + GOAL + DOWNSTREAM + REQUEST. </capabilities>
<constraints> - Decide nothing for the user when uncertainty remains. Surface the decision via `AskUserQuestion` with a recommended option grounded in research. - Read referenced files yourself. A subagent report is a candidate list, not a decision. - Apply the routing rule in Stage 3b before every `AskUserQuestion`: if code or docs can answer the question, do that first. - The plan file is LLM-target structured markdown: parsable field labels, concrete `file_path:line_number`, no prose flourish, no decorative narration. Downstream agents read it as a spec. - Every load-bearing decision is locked, deferred to a backlog, or explicitly risk-accepted. The plan file contains zero open questions. - Do not call `EnterPlanMode`. Native plan mode locks writes outside one designated file; this workflow needs to write plan.md plus interview-log.md plus checkpoint.json plus research/*.md. </constraints><auto_mode>
This skill accepts a --auto flag (parsed in Stage 0a). When the flag is present OR the user picks Lock all and run on auto mode at Stage 4, the planner enters auto mode: AUTO_MODE = true for the rest of the run.
Auto mode automates system-process flow gates; it does NOT auto-decide user-preference content. The Stage 3 interview (synthesis-gate + TDD + decision-tree nodes) still surfaces to the user even when AUTO_MODE = true. The --auto contract is: skip confirmation prompts and recovery escalations, but never silently choose a user-preference value on the user's behalf.
Policy:
- AUTO_MODE auto-resolves the auto-eligible AskUserQuestion call sites (listed below) by picking the
(Recommended)first option, and emits a one-line heartbeat per resolved gate (Auto mode: <header> → <selected option>). - AUTO_MODE STILL SURFACES the interview-surface AskUserQuestion call sites (listed below) to the user. These are user-preference content decisions, not system-process flow gates. The recommendations the planner attaches to each interview question are still grounded in Stage 1 research + Stage 2 deep-read; the user picks among them with full visibility.
- AUTO_MODE halts on BLOCKER call sites (listed below). These conditions require human judgment and cannot be safely defaulted.
- Plan collision in auto mode (Stage 0f) has a different safer default than interactive mode: auto-pick
Append suffix (<slug>-2)instead of the first optionOverwrite. Auto mode prefers preservation over silent destruction. - At Stage 6 Deliver, if AUTO_MODE is still true, chain into execute: after rendering the planning summary, invoke the
ac:executeskill via theSkilltool withargs: "<slug> --auto". The execute skill's Phase 1a parses--autoand propagates auto mode through Phase 2, Phase 3, and Phase 4. Planning and execution run as one autonomous flow.
Auto-eligible AskUserQuestion call sites (auto-pick (Recommended) first option; emit per-node heartbeat):
- Stage 0e Resume?
- Stage 0f Plan collision (special: auto-pick
Append suffixinstead of literal first option) - Stage 3d Stalled? (flow-recovery, not content; auto-picks
Continue (Recommended)) - Stage 4 Lock all (auto-picks
Lock all and run on auto mode (Recommended)) - Stage 5.5b Review tier confirmation (auto-picks the recommended option per the REVIEW_TIER branch)
- Stage 5.5 max-iter (auto-pick
Proceed anyway (Recommended)) - Stage 5.5 stall (auto-pick
Proceed anyway (Recommended))
Interview-surface AskUserQuestion call sites (always surface, even in AUTO_MODE = true — user-preference content decisions, NOT system-process flow gates; Stage 3b routing rule has already filtered these to user-answerable: preference / business / value judgment):
- Stage 3a Proceed after synthesis preview (synthesis gateway to the interview; user may redirect
Wrong scope, correct firstorInvestigate more firstbefore any decision locks) - Stage 3b.1 TDD interview node (test mode preference: tdd / tests-after / none — value judgment about test discipline)
- Stage 3c Every interview decision-tree node (each node represents a user-preference choice the 3b routing rule could not resolve via code-read or docs-spawn)
BLOCKER call sites (always surface to the user, even in auto mode):
- Stage 3.5 Oracle Sanity Check returns one or more CRITICAL findings (the oracle spotted a design bug or hallucinated-pattern risk that needs user judgment before plan write; auto mode cannot silently roll past a CRITICAL design flag)
- Stage 5 plan write fails twice (the planner cannot make further progress; needs user)
- Subagent returns malformed output twice (research is stuck; needs user)
Anti-runaway guards already in the design (no additional step cap):
- Stage 5.5 reviewer loop targets 0 iter (planner writes the plan well first time) with a max-5 hard cap + stall detection on
PLAN_REVIEWER_PREV_ISSUES. Past 5 iterations, the escalation gate fires; in auto mode the escalation gate's(Recommended)isProceed anyway, but the surface message names the unresolved findings so the report logs the trade-off. - Stage 3d Stalled? fires after three consecutive non-progress turns. Same logic.
- The chained
/ac:executehas its own 3-strike rule (Phase 2j), max-5 code-review loop (Phase 3d), and stall detection. Those bound the execute side independently.
Heartbeat discipline in auto mode: emit one short user-visible line for each of (a) stage transitions (entered Stage X / Stage X completed), (b) auto-resolved gates (Auto mode: <header> → <selected option> for each item in the auto-eligible list when it fires). Interview-surface call sites do NOT emit heartbeats — they fire AskUserQuestion to the user directly, and the user's selection appears in the chat as the question response. Together stage-transition + gate-resolution heartbeats give the run a visible cadence (~6-10 heartbeat lines per run is typical) without prompting.
</auto_mode>
ToolSearch query: "select:AskUserQuestion,TaskCreate,TaskUpdate"
Then register the pipeline as a TaskCreate task list so the user sees progress in CC's native UI. The TaskCreate API accepts ONE task per call ({ subject, description, activeForm }); call it sequentially for each stage in the pipeline:
TaskCreate({ subject: "Stage 0: Setup", description: "Parse args, derive slug, mkdir, gitignore, collision check", activeForm: "Setting up" });
// Repeat sequentially for Stage 1 through Stage 6, matching the subject/description to each stage header below.
Update each task to in_progress via TaskUpdate on stage entry and to completed on verified exit. On Stage 3 entry, the activeForm may switch dynamically as the interview progresses through individual nodes (activeForm: "Asking node 3 of 7", etc.).
</bootstrap>
Stage 0: Setup
0a. Parse the argument
Scan $ARGUMENTS for the --auto flag (anywhere in the string, surrounded by whitespace or at the start/end). If present: set AUTO_MODE = true, strip the flag from $ARGUMENTS, continue with the remaining string. If absent: set AUTO_MODE = false.
If the post-strip $ARGUMENTS is empty:
- When
AUTO_MODE = false: callAskUserQuestion(headerTopic?, single optionProvide topicwith freeform-Other prompt). Wait for input, then continue. - When
AUTO_MODE = true: this is a BLOCKER (auto mode cannot proceed without a topic). Surface the sameTopic?question; the user provides the topic; auto mode resumes after.
If the post-strip $ARGUMENTS matches .ac/tasks/*.yaml, Read the YAML and extract type, User Story, and Acceptance Criteria as the request body. Otherwise treat $ARGUMENTS as a free-form topic.
If AUTO_MODE = true, emit a single user-visible line: Auto mode engaged. Will run end-to-end through planning and execution, halting only on BLOCKER classes.
0b. Derive slug and paths
Slug derivation runs seven steps in order:
- Absolute-path prefix strip: if the topic STARTS with an absolute path (matches
^/[^ ]+/[^ ]*), separate the path prefix from the trailing topic body. Store the path asPROJECT_DIR_HINT(used as the Recommended default for the Stage 3 D1 project-location decision when one fires). The trailing body becomes the slug-derivation input. - Tokenize: split slug-input on whitespace into raw tokens. Preserve original casing for the final normalize step; transformations in steps 3-5 operate on derived forms without mutating the original token strings.
- Diacritic-normalize for matching (Turkish ASCII fold): produce a
normalized formof each token by applying the foldı→i, İ→I, ş→s, Ş→S, ç→c, Ç→C, ö→o, Ö→O, ü→u, Ü→U, ğ→g, Ğ→Gand lowercasing. Use thisnormalized formfor stopword + tech-stack matching in steps 4-5. Thenormalized formis matching-only; the original casing is preserved for step 7. ASCII fold makesaltinda(user-typed) andaltında(Turkish-keyboard) match the same stopword entry. - Stopword filter (case-insensitive AND diacritic-insensitive; drop any token whose
normalized formmatches an entry below):- TR:
ile, bir, bu, su, icin, gibi, kadar, cok, az, ya, ve, veya, altinda, ustunde, uzerinde, icinde, disinda, ki, mi, mu, olarak, calisak, calismak, yapalim, yapmak, kuralim, kurmak, gelistirelim, gelistirme, projesi, proje, uygulamasi, uygulama, sistemi, sistem - EN:
the, a, an, of, to, in, on, at, with, by, for, from, and, or, but, as, is, are, was, were, beList entries are in ASCII-fold + lowercase form; the token'snormalized formfrom step 3 matches against this list.
- TR:
- Tech-stack token preference: scan the surviving tokens for matches against this regex (case-insensitive on
normalized form):^(laravel|vue|nuxt|react|svelte|astro|next|jetstream|livewire|inertia|django|flask|rails|spring|express|hono|trpc|graphql|grpc|kafka|redis|postgres|postgresql|mysql|mongodb|sqlite|tailwind|prisma|drizzle|vitest|jest|pest|bun|node|nodejs|deno|typescript|javascript|python|golang|rust|kotlin|swift|flutter|html|markdown|md|mcp|cli|api|server|db|cache|webhook|websocket|sdk)$If at least one token matches, the truncate step below prioritizes tech-stack matches into the first-5 slots (up to 5 if many), then fills the remaining slots with non-tech surviving tokens in their original order. When zero tech-stack matches, truncate proceeds with original order. - Truncate: take the first 5 tokens per the priority order from step 5 (tech-stack matches first, then non-tech fill).
- Normalize: lowercase each truncated token (original casing form, NOT the diacritic-folded form), replace any run of non-alphanumeric characters within each token with a single hyphen, join with
-, then collapse any run of consecutive-in the joined string to a single-, finally strip leading/trailing hyphens.
If the resulting slug is empty (every token was a stopword — pathological case), fall back to the topic's first non-stopword word; if even that fails, use unnamed-plan and surface the unusual slug in Stage 3a so the user can override.
Examples:
"Add Health-Check Endpoint v2"→ no path-strip; no diacritic; no stopword drop; tech matches: none → tokens["Add", "Health-Check", "Endpoint", "v2"]→ truncate 5 → normalize →add-health-check-endpoint-v2."nodejs typescript ile local bir mcp server kuralim"→ no path-strip; diacritic-norm noop; dropile,bir,kuralim→ survivors["nodejs", "typescript", "local", "mcp", "server"]; tech matches[nodejs, typescript, mcp, server]→ truncate-5 priority[nodejs, typescript, mcp, server, local]→nodejs-typescript-mcp-server-local."/Users/anil/Code/foo/references altinda laravel jetstream blog"→ path-strip →PROJECT_DIR_HINT = "/Users/anil/Code/foo/references/", slug-input"altinda laravel jetstream blog"; diacritic-normaltindaalready ASCII; dropaltinda→ survivors[laravel, jetstream, blog]; tech matches[laravel, jetstream]→ truncate-5 priority[laravel, jetstream, blog]→laravel-jetstream-blog."/Users/anil/Code/foo/references altinda nodejs + typescript ile cli olarak calisak html to markdown projesi"→ path-strip; diacritic-norm noop (input already ASCII); dropaltinda, ile, olarak, calisak, to, projesi→ survivors[nodejs, +, typescript, cli, html, markdown]; tech matches[nodejs, typescript, cli, html, markdown](5 tech) → truncate-5[nodejs, typescript, cli, html, markdown]→ normalize step 7 (+token replaced + post-join collapse) →nodejs-typescript-cli-html-markdown. (Tech-stack priority preempts+from surviving into the slug.)"the the the foo bar"→ dropthe(3×) → tokens[foo, bar]; no tech matches →foo-bar.
Set:
PLAN_DIR = .ac/plans/<SLUG>/PLAN_PATH = .ac/plans/<SLUG>/plan.mdLOG_PATH = .ac/plans/<SLUG>/interview-log.mdCHECKPOINT_PATH = .ac/plans/<SLUG>/checkpoint.jsonRESEARCH_DIR = .ac/plans/<SLUG>/research/EVIDENCE_DIR = .ac/plans/<SLUG>/evidence/PROJECT_DIR_HINT(when step 1 stripped a path): becomes the Recommended default for the Stage 3 D1 project-location decision; user may override during the interview.
0c. Create directory structure
Bash: mkdir -p .ac/plans/<SLUG>/research .ac/plans/<SLUG>/evidence
Idempotent; safe to run on every invocation.
0d. Gitignore guard
In a git repo (git rev-parse --git-dir 2>/dev/null exits 0), run git check-ignore -q .ac/. If non-zero (path not ignored), append .ac/ to .gitignore (create the file if missing) and print one line: Added .ac/ to .gitignore so planning artifacts stay local. Use git add -f to track specific plan files. Skip outside a git repo or when .ac/ is already ignored. The check is idempotent; run it on every invocation.
0e. Resume check
If CHECKPOINT_PATH exists:
- When
AUTO_MODE = false: Read it and callAskUserQuestion(headerResume?, optionsResume (Recommended)/Start fresh). - When
AUTO_MODE = true: auto-pickResume (Recommended)without surfacing the question. Emit one line:Auto mode: Resume detected, restoring from checkpoint.
On Resume: restore working memory from the JSON (locked_decisions, locked_requirements, canonical_refs, deferred_ideas, codebase_state, conventions, reuse_map, last_stage), jump to the stage indicated by last_stage. On Start fresh: delete the checkpoint, continue to 0f.
For the checkpoint JSON schema and write points, read ${CLAUDE_SKILL_DIR}/references/checkpoint-schema.md.
0f. Plan collision check
If PLAN_PATH already exists and no checkpoint was just consumed:
- When
AUTO_MODE = false: callAskUserQuestion(headerExists?, optionsOverwrite/Append suffix (<slug>-2)/Cancel). Apply the choice. - When
AUTO_MODE = true: auto-pickAppend suffix (<slug>-2)(NOT the literal first optionOverwrite; auto mode's safer default differs from interactive mode per the<auto_mode>policy). If<slug>-2also exists, increment to-3,-4, etc. until a free slug is found. UpdateSLUGand all derived paths. Emit one line:Auto mode: collision detected, appended suffix; new slug = <new slug>.
TaskUpdate Stage 0 to completed, Stage 1 to in_progress.
Stage 1: Codebase Survey + Parallel Research
Goal: ground the request in evidence before asking the user anything. Two-step: the main agent first builds its own coarse mental map of the project (1a), then spawns the parallel research cohort (1b-1d) with briefs anchored in that map, then waits for all (1e). The main agent does not skip 1a; subagent paraphrases stacked on a missing baseline produce shallow plans.
1a. Directory survey (main agent, NOT delegated)
The main agent runs this step itself. Subagents launch with shallower context than the main thread; you have all base tools and full project read access, so you build the map and pass it down via subagent briefs.
Run the directory tree in one Bash call (fallback chain so the step works without tree installed):
( tree -L 3 -d -I 'node_modules|.git|dist|build|.next|.nuxt|__pycache__|target|vendor' 2>/dev/null \
|| find . -type d -maxdepth 3 -not -path '*/node_modules*' -not -path '*/.git*' -not -path '*/dist*' -not -path '*/build*' | sort ) \
&& echo '---' && ls -la
Then Glob the language and stack markers in a single parallel batch:
- Node / TS / Bun:
package.json,tsconfig.json,bun.lockb,pnpm-lock.yaml,bun.lock. - Python:
pyproject.toml,requirements*.txt,setup.py,setup.cfg. - Rust / Go / PHP / Ruby / Java:
Cargo.toml,go.mod,composer.json,Gemfile,pom.xml,build.gradle*. - Conventions:
CLAUDE.md,CLAUDE.local.md,.claude/rules/*.md,README.md,AGENTS.md.
For each marker found (skip lockfiles and node_modules), Read it. Trace path-scoped rules: a .claude/rules/<name>.md with a paths: frontmatter applies only when an in-scope file matches; surface which rules become active for the topic.
Write the survey to RESEARCH_DIR/00-directory-survey.md with sections:
## Top-level structure— raw tree / find output.## Language / stack markers—file_path:line_numberfor each marker plus the one-line summary (framework name + major version, key dependencies, scripts).## Project conventions— extracted CLAUDE.md /.claude/rules/*.mdheadlines, with thepaths:scope when present.## Sub-projects— directories that contain their ownpackage.json+tsconfig.json(Layer A authority targets at execute time per the executor's sub-project boundary rule).## Provisional research angles— 5 to 10 concrete questions the survey raised, derived jointly from topic + observed structure. Feeds 1c and 1d brief construction.
The survey is working memory for the main agent AND a referenceable artifact for subagent briefs. Subagent briefs in 1c-1d MUST anchor their REQUEST to survey-identified paths, not generic guesses.
1b. Reuse-bias clause (concatenate to every ac:explore brief)
Every ac:explore invocation in this stage carries this clause in addition to its task-specific brief:
<reuse_bias_clause>
As part of your search, surface existing utilities, modules, functions, and patterns in this codebase that could solve problems similar to the user's request. For each candidate, return absolute file_path:line_number and one line on what it provides. Prefix any candidate that could be reused INSTEAD OF writing new code with REUSE:. This feeds the plan's Reuse Map.
</reuse_bias_clause>
1c. Dedicated reuse-focused explore (counts toward 1d's explore total)
Spawn one ac:explore dedicated to the reuse search. This explore is one of the explore slots counted in 1d's floor/target; it is not additional.
<reuse_explore_brief>
CONTEXT: planning <topic>. The user has not yet decided whether to reuse existing code or write new code; that decision depends on what already exists. Directory survey landed at RESEARCH_DIR/00-directory-survey.md; anchor your search to the directories the survey flagged as likely homes for similar utilities.
GOAL: find existing utilities, modules, functions, and patterns in the codebase that solve problems similar to <topic>.
DOWNSTREAM: this list feeds the plan's Reuse Map. The planner references these candidates when locking "reuse vs build" decisions with the user.
REQUEST: scan the codebase, return REUSE candidates with absolute file_path:line_number and one line per candidate explaining what it provides and how it relates. Precision over recall; skip anything you cannot tie to <topic>.
</reuse_explore_brief>
1d. Topic-driven research fan-out (single message, parallel)
In the same assistant turn that issues 1c, spawn the rest of the cohort. Use 1a's ## Provisional research angles as the brief skeleton; each brief targets one angle and cites at least one survey-anchored path.
Counts policy (floor + target, scope-driven within the range):
ac:explore: floor 4, target 7, INCLUDING the 1c reuse-focused explore. Smaller plans (narrow refactor, single-module change) land near the floor; broader plans (cross-module, new subsystem) land near the target. Each brief targets an independent angle; do not bundle. Typical angle set:- Reuse candidates (the 1c slot).
- Similar implementations of the same shape.
- Existing patterns and conventions in the affected module.
- Impact map (what depends on what the plan will touch).
- Integration points (where the new code wires into existing flows).
- Error-handling / boundary style for the relevant surfaces.
- Test patterns covering the surface (file layout, helpers, mocking style).
ac:librarian: floor 2, target 3. Always at least 2, even when the topic looks purely internal:- Brief 1 (always): idiomatic-pattern verification against vendor docs for the libraries the topic touches. Brief shape at
${CLAUDE_SKILL_DIR}/references/librarian-brief.mdunder## Brief 1. - Brief 2 (always): known-bugs research dimension (incompatibilities, deprecations, breaking default values, version-combo toolchain bugs). Brief shape in the same file under
## Brief 2. - Brief 3 (when target = 3): production-quality OSS reference examples for the specific shape this plan introduces, OR a second library / framework not covered by briefs 1-2. Brief shape in the same file under
## Brief 3, framings (a) or (b).
- Brief 1 (always): idiomatic-pattern verification against vendor docs for the libraries the topic touches. Brief shape at
ac:oracle: 1 only when the request signals architecture intent (system design, infrastructure, non-trivial trade-offs). Advisory; non-blocking; do not gate on its return. Unchanged from prior behavior.
Each explore brief carries the reuse-bias clause from 1b. Each librarian brief targets a NAMED angle (one brief = one angle); do not bundle three different libraries into one brief.
All agents launched with run_in_background: true so you can collect results as they complete. Issue all calls in ONE assistant message with multiple Agent tool-use blocks for true parallelism. Reaching the target (7 + 3) is preferable when the topic supports it; the floor exists so trivial plans do not pay maximum token cost.
<brief_shape> CONTEXT: [why this research, in 1-2 sentences; cite the survey-anchored path] GOAL: [specific question to answer] DOWNSTREAM: [how the planner will use the result] REQUEST: [what to return, format, what to skip] </brief_shape>
1e. Wait, archive, checkpoint
Wait for all spawned agents (collect BackgroundTask outputs or wait for foreground returns). Write each agent's output to RESEARCH_DIR/<agent-type>-<short-slug>.md. The directory survey at RESEARCH_DIR/00-directory-survey.md is already on disk from 1a. Write a checkpoint with last_stage: "1" and the gathered research summary.
TaskUpdate Stage 1 to completed, Stage 2 to in_progress.
Stage 2: Main-Agent Deep Read
Goal: build your own mental model. Subagents found candidates; you read the code and make decisions. Apply this to every file referenced by Stage 1 results, not just the first.
2a. Read every referenced file
For every absolute path returned by Stage 1 agents (REUSE candidates, similar implementations, integration points, pattern references), Read the file. For long files, read the relevant ranges with offset and limit. Trace imports and call sites with LSP findReferences and goToDefinition when the file is part of a chain.
State scope: read every referenced file; do not stop after the first three. The point of this stage is full ownership of the mental model; subagent paraphrases are insufficient input for decision-making.
2b. Classify codebase state
Sample 2 to 3 representative files and check linter, formatter, and type-checker configs. Tag the codebase with one of:
disciplined— consistent style, configs present, tests cover the surface. Match patterns strictly.transitional— mixed styles, partial migrations visible. Ask which pattern to follow when it matters.legacy— older patterns, gaps in tooling, but coherent within its era.chaotic— no consistent style, no tests. Propose conventions and confirm with the user.greenfield— empty or near-empty. Apply modern best practices.
2c. Extract dominant conventions
Distill these from the files read:
- Naming pattern (camelCase, snake_case, kebab-case per file type)
- Error handling style (throw, Result, try-catch boundaries)
- Comment density (none, WHY-only, docblocks everywhere)
- Type discipline (strict, mixed, untyped)
- File organization (flat, nested, barrel exports)
- Import convention (relative, aliased, absolute)
These six fields go into the checkpoint and into the plan template's ## Codebase Conventions section verbatim.
2c.1. Test infrastructure detection (drives TDD interview node)
Scan for test infrastructure: package.json scripts containing test, presence of vitest.config.* / jest.config.* / bun.test.* / pytest.ini / equivalent, and a tests/ or __tests__/ directory with non-trivial content. Record:
TEST_INFRA_PRESENT = true | falseTEST_FRAMEWORK = <name>(when detected) — vitest, jest, bun test, pytest, go test, etc.TEST_COMMAND = <command>— extracted frompackage.jsonorCLAUDE.md.
This drives the Stage 3 TDD interview node: if TEST_INFRA_PRESENT = true, the planner asks the user whether to use TDD (defaulting to yes, since the infrastructure already exists). If TEST_INFRA_PRESENT = false, the planner asks whether to set up test infrastructure as part of this plan or proceed without tests.
2d. Internal feasibility synthesis
Synthesize internally (not yet shown to the user):
- What exists today: file_path:line_number to N similar implementations.
- Reuse Map draft: candidate utilities and patterns to leverage, with file_path:line_number.
- Delta: what does not exist that the request requires.
- Codebase fit: High / Medium / Low with one-line rationale.
- Effort: Small (1-2 files) / Medium (3-5 files) / Large (5+ files, cross-module).
- Prerequisites: missing infrastructure, required refactors, external dependencies.
- Risks identified: failure modes visible from research.
Write a checkpoint with last_stage: "2".
TaskUpdate Stage 2 to completed, Stage 3 to in_progress.
Stage 3: Grill-me Interview
Goal: walk down the decision tree with the user until every load-bearing decision is locked. Hybrid walk-down branching plus multiSelect for parallel independent decisions. Every question carries a recommended option grounded in research.
Auto-mode handling for this stage: under AUTO_MODE = true, Stage 3a (Proceed?), 3b.1 (TDD?), and 3c (every decision-tree node) STILL SURFACE to the user — these are the interview-surface call sites per <auto_mode>. Auto mode does not suppress user-preference content decisions; it only auto-resolves system-process flow gates. Stage 3d (Stalled?) remains auto-eligible (flow-recovery, not content): when 3 consecutive non-progress turns trigger it, auto mode picks Continue (Recommended) and emits a heartbeat. The plan-quality outcome of the interview rests on (a) the recommendations the planner attaches to each AskUserQuestion being well-grounded in Stage 2 research, and (b) the user's selections among them. Stage 2 deep read is the gating quality step for recommendations; the user is the gating authority for selections.
3a. Build the decision tree and surface the synthesis
From the Stage 2 synthesis, extract the open questions. Each question is a node. Edges represent dependencies (answering X opens or closes Y). Group nodes into:
- Sequential nodes: each answer materially affects the next question's framing.
- Parallel branches: independent decisions that can be batched in one
AskUserQuestioncall (up to 4 questions) or expressed asmultiSelect: true.
Surface the synthesis as plain text in the chat before the first question:
Before we start the interview, here is what I found:
You asked: <restate>
What exists today: <N similar implementations at file:line refs>
Codebase fit: <High | Medium | Low> — <reason>
Codebase state: <classification>
Effort: <Small | Medium | Large> — <file counts>
Reuse candidates: <count>; top 3: <file:line — what>
Prerequisites: <list or "None">
Risks: <list or "None significant">
I have <N> decisions to walk through with you. Each comes with a recommended answer.
Then call AskUserQuestion (header Proceed?, options Proceed (Recommended) / Wrong scope, correct first / Investigate more first). On Wrong scope: ask freeform follow-up, return to Stage 0f. On Investigate more first: ask which area, spawn the matching agents, return to Stage 1d.
3b. The routing rule (applied before every question to the user)
Before raising any question to the user, route it through this three-way check:
<routing_rule>
- Can this be answered by reading the code? If yes, Read / Grep / LSP the relevant files and resolve it yourself. Record the resolution as a canonical_ref in the checkpoint.
- Does this require external documentation or open-source patterns you do not have? If yes, spawn
ac:librarianwith a focused brief, wait for the report, then re-evaluate. - Is this a user preference, business decision, or value judgment that code and docs cannot answer? Then surface it via
AskUserQuestion. </routing_rule>
<routing_examples> Example A — code-answerable, do not ask the user:
- Question: "Does this codebase use ESLint or Biome?"
- Routing: code-answerable. Read package.json and look for
.eslintrc.*orbiome.json. Record the result in canonical_refs.
Example B — docs-answerable, spawn ac:librarian:
- Question: "What's the recommended retry strategy for OpenAI's chat completions API in 2026?"
- Routing: external docs. Spawn
ac:librarianwith brief targeting "OpenAI rate-limit and retry guidance, official docs, 2026".
Example C — user-answerable, AskUserQuestion:
- Question: "Should we cache responses in Redis or in-memory?"
- Routing: user preference and operational trade-off. Research provides the option list; the user picks.
AskUserQuestionwith recommended option backed by Stage 2 findings. </routing_examples>
This routing rule is the difference between a useful interview and spam. Apply it to every node, not just the first.
3b.1. TDD interview node (mandatory when test infrastructure relevant)
Before the general decision tree walk-down, ask the TDD question. This is a separate node because the answer affects every step's worker briefing in /ac:execute (TDD enforcement directive) and the plan's ## Codebase Conventions section.
Branch on TEST_INFRA_PRESENT from Stage 2c.1:
-
If
TEST_INFRA_PRESENT = true:AskUserQuestion(headerTDD?, options:Yes, TDD (Recommended)—TDD_MODE = "tdd". Worker briefings will require "write failing test first, then implementation".Yes, tests after implementation—TDD_MODE = "tests-after". Worker briefings require tests for behavioral changes but allow implementation-first.No tests—TDD_MODE = "none". Worker briefings include no test-writing directive. Use this only when the user explicitly opts out of tests for this plan. )
-
If
TEST_INFRA_PRESENT = false:AskUserQuestion(headerTests?, options:Set up test infrastructure + TDD (Recommended)—TDD_MODE = "tdd". The plan includes a Wave 1 step to set up the chosen framework. The user answers a follow-up to pick the framework (Vitest / Bun test / Jest / pytest / Go test / Other).Set up test infrastructure + tests after—TDD_MODE = "tests-after". Same as above but implementation-first per step.Proceed without tests—TDD_MODE = "none". No test setup, no tests in plan. Surface this in the plan's## Risks Acceptedbecause untested code is a real risk. )
Record the choice in the checkpoint as tdd_mode and surface it in the Stage 4 Synthesis Preview. The plan's ## Codebase Conventions section gets a TDD: <mode> field at write time.
3c. Walk down with recommended answers
For each node, ask AskUserQuestion with:
- A clear, specific question ending in
?. headerof at most 12 characters (chip label).- 2 to 4 concrete options. Each option is a specific interpretation, example, or trade-off. No generic categories like "UI" or "Behavior".
- The FIRST option is your recommended answer; its label ends with
(Recommended). Recommend based on Stage 2 research, codebase conventions, and reuse opportunities. - For independent parallel decisions: batch up to 4 questions in one
AskUserQuestioncall, or usemultiSelect: truewhen the user picks zero-or-more from a set.
Universal rules applied to every turn of the interview:
- Canonical-ref accumulation: when the user references a doc, spec, ADR, or file ("read X", "check Y"), Read it immediately and append to
canonical_refsin the checkpoint. - Scope-creep guard: when the user mentions something outside the locked scope, capture as a Deferred Idea and redirect:
"<X> is outside this plan's scope; noting for the backlog. Back to <current decision>."Apply this to every off-scope mention, not just the first. - Reuse-vs-build bias: when a decision pits an existing X (with file_path:line_number) against a new Y, make the existing X the recommended option unless research clearly contradicts. The bias is reuse.
- Per-node checkpoint write: after each resolved decision, write
CHECKPOINT_PATHwithlast_stage: "3". Enables resume mid-interview after auto-compact. - Interview log: append every Q&A to
LOG_PATH(decision, options presented, user selection, freeform notes). For the layout, read${CLAUDE_SKILL_DIR}/references/interview-log-layout.md. - Re-research after path-narrowing locks: when a locked decision narrows the option space (chosen framework version, chosen library, chosen test runner), invalidate any prior research that targeted the un-chosen options. Re-orient context to the chosen path by re-reading the relevant
research/*.mdfiles; the early-Stage-1 fan-out may have weighted both option arms equally and the un-chosen arm's findings no longer apply. If research depth on the chosen path is thin (single source, surface-level only), spawn ONE more targetedac:librarianbrief BEFORE the next decision node, using the canonical brief at${CLAUDE_SKILL_DIR}/references/librarian-brief.md. Example: user locks Vue 3 after Stage 3 surfaced both Vue 2 and Vue 3 candidates — discard the Vue 2 reasoning, deepen Vue 3 research if thin, then continue with Vue 3-specific decisions. Apply this trigger after every locked decision that narrows the option space, not just framework choices. - Decision-tree pruning after path-narrowing locks (F23): after each locked Stage 3c decision, re-evaluate the REMAINING decision tree for pruning opportunities — the decision-side parallel to the research-side re-orient rule above. If a downstream decision's options ALL became moot due to the lock, drop that decision from the tree, note the pruning in the interview-log under
## Stage 3 Decision Tree Pruning, and do NOT ask the user the dead question. Worked example: when the user locksD4 Input modes: file only, the downstream decisionsD5 URL handling rigorandD6 Path-traversal-via-URL guardhave nothing to decide (no URL surface exists) — collapse both into a singleD7 Sanitizer rigorquestion covering the surface that remains, or drop entirely if no surface remains. Apply this after every locked decision, not just the first; pruning compounds across the walk-down. - AskUserQuestion batching heuristic (F25): standalone single-question calls for GATEWAY questions whose answer changes the flow (3a Proceed?, 3b.1 Tests? when test-infra detection branches, conditional follow-ups that depend on a prior answer within the same stage). Batched calls (up to 4 questions per AskUserQuestion invocation; that is the spec hard cap, not a target) for INDEPENDENT decisions that share no conditional dependency. After each batched call's answers arrive, re-evaluate the remaining decision tree per the pruning rule above BEFORE issuing the next batch — answers from batch N can prune nodes that would otherwise have entered batch N+1. Smaller cohesive batches (3 location-class questions together; 2 security-rigor questions together) beat arbitrary batch-of-4 fills; cohesion matters more than fill rate.
3d. Stall handling
If three consecutive AskUserQuestion turns produce no decision-tree progress (user picks "Other" with hedging, or your follow-up keeps surfacing the same node), call AskUserQuestion (header Stalled?, options Continue (Recommended) / Force-finalize with recommended defaults / Abandon). On Continue: keep going, no further limit. On Force-finalize: lock all remaining unresolved nodes with their recommended options, list them in the plan's ## Risks Accepted section. On Abandon: write .ac/plans/<slug>/abandoned.md with the synthesis and last state, exit.
3e. Convergence
The interview is complete when:
- Every node in the decision tree is locked, deferred to the backlog, or explicitly risk-accepted.
- No question remains that code, docs, or the user has not answered.
- The reuse-vs-build choice is explicit for every new piece of code the plan proposes.
Plan files contain zero open questions. If a decision could not be locked, it is either deferred (out of scope, captured in ## Deferred Ideas) or risk-accepted (kept in scope with the recommended default and a note in ## Risks Accepted).
Write a checkpoint with last_stage: "3-complete". TaskUpdate Stage 3 to completed, Stage 3.5 to in_progress.
Stage 3.5: Oracle Sanity Check (trigger-based)
Goal: a planning-time oracle pass that catches design bugs and idiomatic-pattern hallucinations before plan write. Run after Stage 3 interview concludes; evaluate the locked decisions against four trigger conditions. If any fires, spawn ONE ac:oracle in background with a focused brief; findings inline into the Stage 4 Synthesis Preview under a new ### Oracle Sanity-Check Findings subsection. If no trigger fires, skip Stage 3.5 silently (no oracle spawn, no Stage 4 subsection).
Auto-mode handling: when AUTO_MODE = true, Stage 3.5 still runs — auto mode does not skip substantive checks, only preference questions. Oracle findings tagged CRITICAL flip a BLOCKER per <auto_mode> (the user must judge revise / accept-as-risk / abandon). IMPORTANT findings inline into Stage 4 preview and auto mode rolls past at Stage 4 lock-all, but the report logs them.
3.5a. Trigger evaluation
Evaluate each trigger against the locked decisions, scope, and conventions from Stage 3:
-
Security-critical surface in scope: the locked plan touches authentication / authorization (login, password, session, token, RBAC, RLS, Policy / Gate, OAuth flow), payment / billing / financial calculation (currency math, charge, refund, invoice, ledger), cryptographic operations (hash, sign, verify, encrypt, decrypt, JWT, HMAC, password hashing), user-input → SQL / shell / file path (injection or traversal surface), or file upload / deserialization (RCE surface).
-
Composable framework-API pattern adopted from librarian research: the plan adopts a chained call (
.X()->Y()->Z()) that librarian described as idiomatic but has unverified per-method semantics. Composable chains are the highest-frequency hallucination class (LaravelmiddlewareFor(['index'], [])adopted as "exempt index from auth" when it assigns empty middleware; ReactuseMemosemantics adopted from a blog post when the docs say otherwise). Trigger fires when at least one such chain appears in the locked decisions OR the plan's intended Codebase Conventions. -
Conflicting research signals: Stage 1 librarian or explore returned contradictory recommendations on the chosen path, OR the chosen path's evidence is single-source / low-confidence. Oracle as tie-breaker.
-
Migration with destructive operations: schema rename,
DROP,TRUNCATE, data-shape change with no rollback path. Production-safety review.
Trigger evaluation is mechanical — match locked decisions and conventions against the surface lists above. If zero triggers fire: TaskUpdate Stage 3.5 to completed, Stage 4 to in_progress, proceed silently. If one or more triggers fire: assemble ONE oracle brief targeting the fired triggers and proceed to 3.5b.
3.5b. Oracle brief shape
Spawn one ac:oracle with run_in_background: true. Build the brief by selecting only the GOAL bullets matching the fired triggers (skip the rest):
CONTEXT: planning <topic>. Codebase state: <state>. Locked stack: <stack snapshot>. Scope IN: <list>. Scope OUT: <list>.
GOAL (only include the bullets for triggers that fired in 3.5a):
- (Trigger 1) Spot risks and subtle bugs in the locked <auth | payment | crypto | input-handling | file-upload> design. Locked decisions: <list with rationale>. Patterns the plan adopts: <file:line refs to codebase + librarian citations>.
- (Trigger 2) Verify the semantics of <chain>. Quote vendor docs lines that support each method's claimed behavior. Flag any ASSIGN-vs-EXEMPT, opt-in-vs-opt-out, or default-value pitfalls.
- (Trigger 3) Tie-break: between <option A> and <option B>, which fits the codebase state <state> at <file:line> patterns. Reason about trade-offs.
- (Trigger 4) Spot risks in this migration plan for production safety, rollback path, downtime.
DOWNSTREAM: findings inline into the plan's Stage 4 Synthesis Preview under `### Oracle Sanity-Check Findings`. CRITICAL findings flip a Stage 3.5 BLOCKER for user judgment; IMPORTANT findings are listed and the plan proceeds.
REQUEST: return findings tagged CRITICAL or IMPORTANT. Each finding includes the trigger it speaks to, the specific concern, evidence (docs URL or file:line), and a recommended action (revise / accept-as-risk / no-action). Cap at 5 findings; rank by impact. If nothing surfaces, return "No significant findings."
3.5c. Wait, classify, route
Wait for the oracle response. Parse findings into CRITICAL and IMPORTANT buckets:
-
At least one CRITICAL finding: surface via
AskUserQuestionBEFORE Stage 4, even whenAUTO_MODE = true(BLOCKER class):- Header:
Oracle CRIT? - Options:
Revise plan (Recommended)— loop back to Stage 3 targeting the affected decision /Accept as Risk and continue— lock the oracle's concern in## Risks Acceptedwith the oracle's recommended action as the recorded default /Abandon— write.ac/plans/<slug>/abandoned.mdwith synthesis + oracle finding, exit. - Apply the user's choice.
- Header:
-
Zero CRITICAL, one or more IMPORTANT findings: do NOT halt; inline the findings into Stage 4 preview under
### Oracle Sanity-Check Findings. Auto mode rolls past at Stage 4 lock-all per its policy; the report logs them. -
No findings ("No significant findings" or empty): skip the Stage 4 subsection silently.
Append the oracle outcome to LOG_PATH under ## Stage 3.5 Oracle Sanity Check (triggers fired, findings count, user routing if BLOCKER fired). Write a checkpoint with last_stage: "3.5".
Cross-project propagation (F22): scan oracle findings for explicit statements that the finding applies to a sibling project (e.g. "the same regex gap exists at references/<sibling>/.../foo.ts:N", "this pattern is shared with the kodizm proxy at cli/ac/src/mcp.ts"). When such a statement is present, record the finding in the plan's ## Cross-Project Observations section at Stage 5 write time. The CURRENT plan absorbs the finding for its own scope; the sibling-fix is a separate follow-up plan the operator spins up later. Do not silently fix sibling code — sibling-fix scope belongs to its own plan with its own interview, oracle, and review cycle.
TaskUpdate Stage 3.5 to completed, Stage 4 to in_progress.
Stage 4: Synthesis Preview
Render the locked synthesis as plain text in the chat:
## Confirmed Understanding: <topic>
### Goal
<locked goal, falsifiable: current state, target state, acceptance criterion>
### Scope
- IN: <list>
- OUT: <list>
### Codebase Conventions (will be embedded in plan)
- Naming: <pattern>
- Error handling: <style>
- Comment density: <level>
- Type discipline: <level>
- File organization: <pattern>
- Import convention: <pattern>
### Reuse Map (existing code to leverage)
- file_path:line_number — what it provides — which decision uses it
### Locked Decisions
- <decision>: <choice> — <rationale>
### Oracle Sanity-Check Findings (only when Stage 3.5 surfaced findings)
- [IMPORTANT] <trigger>: <concern>. Evidence: <docs URL or file:line>. Recommended action: <revise | accept-as-risk | no-action>.
(If Stage 3.5 fired zero triggers OR oracle returned no findings, omit this subsection entirely. CRITICAL findings are handled BEFORE this preview via the Stage 3.5c BLOCKER gate; the preview shows only IMPORTANT findings.)
### Deferred Ideas
- <idea>: <reason deferred>
### Risks Accepted (locked-default decisions kept in scope)
- <decision and recommended default>: <why accepted>
### Canonical References
- file_path:line_number — what it provides
Cap rendered length at roughly 8 KB. For longer content, summarize each section to two sentences and link the full content from LOG_PATH.
When AUTO_MODE = false: call AskUserQuestion (header Lock all?, options in this order):
Lock all and run on auto mode (Recommended)— flipsAUTO_MODE = truefrom this point onward. The planner auto-resolves the remaining planning stages per the<auto_mode>policy (Stage 5, Stage 5.5), then at Stage 6 chains directly into/ac:execute --autofor the same slug. End-to-end autonomous from here until done. This is the default once decisions are locked: the Stage 3 interview + Stage 5.5 reviewer pair already carry the planning-quality gate, and step-by-step adds an inspect step that the operator can pick explicitly when they want it.Lock all and proceed step-by-step— the planner writes the plan, runs Stage 5.5 review, then ends with a "user, run /ac:execute next" message. The user reviews the plan and invokes execution on their own. Pick this when you want to inspect plan.md before running execute.Revise a decision— loop back to Stage 3 targeting one node.Revise / expand scope— change what is IN or OUT, or pull a deferred idea into v1; loops back to Stage 3 interview.
When AUTO_MODE = true (set at Stage 0a via the --auto flag): skip this question entirely; the answer is implicitly Lock all and run on auto mode. Emit one line: Auto mode: decisions locked, proceeding to Stage 5 plan write.
On Lock all and proceed step-by-step: proceed to Stage 5 with AUTO_MODE = false.
On Lock all and run on auto mode: set AUTO_MODE = true, emit Auto mode engaged at Stage 4. Will chain into /ac:execute after planning completes., proceed to Stage 5.
On Revise a decision / Revise / expand scope: ask which item via a follow-up AskUserQuestion (auto-eligible in auto mode for the follow-up too), loop back to Stage 3.
TaskUpdate Stage 4 to completed, Stage 5 to in_progress.
Stage 5: Plan Write
Write the plan to PLAN_PATH using the markdown structure at ${CLAUDE_SKILL_DIR}/references/plan-template.md. That file contains the full plan-file shape (frontmatter + all sections + per-step field shape), the complexity classification rule that drives the **Complexity** frontmatter field, and the post-write verification + BLOCKER escalation if the write fails twice.
Fill placeholders with concrete content; remove placeholder text inside angle brackets. For tier assignment per step, read ${CLAUDE_SKILL_DIR}/references/model-tiers.md (capability summaries + decision heuristic). For plans with more than 10 steps, use the incremental write protocol described in the template reference.
Quality target: 0 reviewer iterations. Write the plan as if no Stage 5.5 reviewer will look at it. The reviewer is a safety net for misses, not a draft-quality crutch. Concretely: every step's Description / Files / Done when / QA / Must NOT is specific enough that a fresh agent can execute without guessing; the Codebase Conventions section captures every project-specific rule the workers need; the Reuse Map names every existing utility the plan leverages; the locked decisions from the interview are reflected in the steps themselves, not assumed. The Stage 5.5 reviewer has a max-5 hard cap and stall detection — plans that converge in 0-1 iter are the goal.
Test-driven literal-pattern audit (Stage 5 quality discipline): when a step's Description names a literal regex pattern, literal config snippet (package.json fragment, tsconfig field, command-line invocation), or literal API chain (.X().Y().Z()), AND the same step's QA or Done when field lists concrete test inputs that exercise the pattern, mentally execute the pattern against each test input BEFORE plan write. If any listed test input would fail the literal pattern as-written, fix the literal in the plan OR flag the gap in the step's Description as regex-needs-validation / snippet-needs-validation / chain-needs-validation. The worker's TDD red phase is the safety net for missed cases; planning-time literal audit catches them cheaper. Worked example: a sanitizer regex \]\(scheme:[^)]*\) paired with the QA input [x](javascript:alert(1)) produces [x](#sanitized-link)) (the [^)]* halts at alert('s inner ), leaving the outer ) outside the match — trailing-paren bug). Audit-at-plan-time would catch this; absent the audit, the worker's TDD red phase catches it at execute-time + reports via F17 deviation. Either layer works; planning-time is cheaper.
TaskUpdate Stage 5 to completed, Stage 5.5 to in_progress.
Stage 5.5: Independent Review Cycle
Auto-mode handling for this stage: when AUTO_MODE = true, all three AskUserQuestion call sites in this stage are auto-eligible: 5.5b Review tier confirmation (auto-pick the recommended option per the REVIEW_TIER branch), 5.5d step 2 max-iter (auto-pick Proceed anyway (Recommended)), 5.5d step 5 stall (auto-pick Proceed anyway (Recommended)). Emit one heartbeat line per resolution. The reviewer subagent spawn (5.5d step 3) is unaffected; auto mode does not skip the actual review, only the user-confirmation prompts around it.
Goal: an independent second-eye review of the written plan file. The reviewer is a fresh-context subagent that reads only the plan file; it does not inherit your in-context state. This catches things the planner's own context bias misses (stale references after revision, executability from a fresh perspective, tier mismatches that drifted during writing).
Stage 5.5 audit shape: subagent file-based audit after write — Reference Validity / Executability / Internal Consistency / Tier Fitness for standard plans via ac:plan-reviewer; plus seven adversarial dimensions (deep reference verification, executability stress-test, cross-task dependency, tier challenge, QA specificity, wave ordering, Reuse Map enforcement) for complex plans via ac:plan-reviewer-deep.
5.5a. Read the plan's Complexity field and map to reviewer tier
Read PLAN_PATH and extract the **Complexity** value from its frontmatter (set by the planner during Stage 5 per the Complexity classification rule). Map to reviewer tier:
simple→REVIEW_TIER = "skip"(default behavior; user can override to force a review).standard→REVIEW_TIER = "standard".complex→REVIEW_TIER = "complex".
This stage does not re-classify the plan; the planner already chose the complexity in Stage 5 with full context. Stage 5.5 honors that choice and only routes the reviewer subagent accordingly.
5.5b. Tier confirmation with user
Present the current routing and offer override. The options shown to the user depend on REVIEW_TIER:
Plan complexity: <simple | standard | complex> (set by planner in Stage 5)
Review tier: <skip | standard | complex>
Plan summary:
- Total files touched: <N>
- Steps: <N> | Waves: <N>
- Codebase state: <state>
- Cross-cutting concerns: <list or "None">
AskUserQuestion variants by REVIEW_TIER:
-
If
REVIEW_TIER == "skip": HeaderReview?, options:Skip review (Recommended)— simple plan; reviewer subagent is overkill for the scope.Force standard review— setREVIEW_TIER = "standard", runac:plan-reviewer.Force deep review— setREVIEW_TIER = "complex", runac:plan-reviewer-deep.Cancel— exit before Stage 6.
-
If
REVIEW_TIER == "standard": HeaderReview?, options:Proceed with standard reviewer (Recommended).Force deep review— escalate toac:plan-reviewer-deepfor extra rigor.Skip review— note in summary that review was skipped by user request.Cancel— exit before Stage 6.
-
If
REVIEW_TIER == "complex": HeaderReview?, options:Proceed with deep reviewer (Recommended).Downgrade to standard reviewer— setREVIEW_TIER = "standard"; the user accepts lighter review on a complex plan.Skip review— note in summary that review was skipped by user request.Cancel— exit before Stage 6.
On Skip review or REVIEW_TIER == "skip" confirmed: jump to Stage 6 Deliver, mark the Review Verdict section as skipped (simple plan) or skipped by user request. On Cancel: stop the skill without writing Stage 6, leave the plan file in place, return to the user with a clear "review canceled; plan written but unreviewed" message.
5.5c. Initialize loop state
PLAN_REVIEWER_ITER = 0
PLAN_REVIEWER_PREV_ISSUES = Infinity
5.5d. Review loop
Repeat:
-
Increment
PLAN_REVIEWER_ITER. -
Max-iter terminal check runs FIRST. If
PLAN_REVIEWER_ITER > 5, present escalation gate. (The target is 0 iter; the cap exists for plans that need a few cycles to converge. Past 5 iter, something structural is wrong and user judgment is needed.)AskUserQuestion (header `Max iter?`, options `Proceed anyway (Recommended)` / `Adjust approach` (loop back to Stage 4 Synthesis Preview) / `Abandon` (write abandoned.md, exit) )Apply the choice and exit the loop on
Proceed anyway(proceed to Stage 6 with reviewer issues noted in## Risks Accepted). OnAdjust approach: loop back to Stage 4 with reviewer feedback inlined. OnAbandon: write.ac/plans/<slug>/abandoned.mdwith synthesis + last reviewer verdict, exit. -
Spawn reviewer with prompt =
PLAN_PATHonly (no other context; reviewer's input contract is a single path string):Agent({ subagent_type: REVIEW_TIER === "complex" ? "ac:plan-reviewer-deep" : "ac:plan-reviewer", description: "Independent plan review (iter <N>)", prompt: PLAN_PATH }) -
Parse verdict from the returned text:
- Leading non-empty line
**[OKAY]**→ exit loop, proceed to Stage 6. - Leading non-empty line
**[REJECT]**→ continue. - Anything else → re-spawn the reviewer once with the same path prompt (reviewer input contract is path-only; do not append extra context). If the second attempt is also malformed, treat the iteration as REJECT with zero parseable issues, which forces stall detection or max-iter escalation on the next loop pass.
- Leading non-empty line
-
Stall detection runs AFTER max-iter check, BEFORE revision. Count blocking issues in the REJECT output. If
issue_count >= PLAN_REVIEWER_PREV_ISSUESANDPLAN_REVIEWER_ITER >= 2:AskUserQuestion (header `Stalled?`, options `Proceed anyway (Recommended)` / `Adjust approach` (loop back to Stage 4) / `Abandon` )First iteration cannot stall because
PLAN_REVIEWER_PREV_ISSUESstarts atInfinity. -
Update
PLAN_REVIEWER_PREV_ISSUES = issue_count. -
Revise the plan via
Edit(do not re-Writethe plan file; the secondWritecall erases the first). For each blocking issue:- Locate the affected section in the plan file (issue references file:line or step number).
- Apply the smallest correct fix that addresses the issue.
- The reviewer's
Fix:line for each issue is your guidance. - Coordinated-update check (run after every Edit, not just the last one): a single step often restates the same rule across multiple fields (
Description,Why this tier,Done when,QA,Must NOT,References). Editing one field can leave contradicting copies in the others. After applying the fix, grep the plan for any string or concept tied to the changed substance (the removed call name, the rewritten convention, the renamed field, the deprecated command) and patch every surviving instance with a follow-up Edit. The plan must read internally consistent before the next reviewer iteration, otherwise the next iteration will surface the same conceptual issue at a different line and counts as new findings instead of stall-detection signal.
-
Append the iteration log to
LOG_PATHunder## Stage 5.5 Iteration <N>:- Reviewer verdict: REJECT - Issue count: <N> - Issues addressed: <list of section/step references> - Notes: <freeform> -
Update checkpoint with
last_stage: "5.5", current iter, and prev_issues. -
Continue loop.
5.5e. Convergence
The review cycle is complete when reviewer returns **[OKAY]**, or the user proceeds via escalation gate. In either case, write a final checkpoint entry and TaskUpdate Stage 5.5 to completed, Stage 6 to in_progress.
Stage 6: Deliver
Delete CHECKPOINT_PATH. The plan is locked and reviewed.
Render the plan summary using the template at ${CLAUDE_SKILL_DIR}/references/plan-summary-template.md. Fill concrete values from the plan file.
TaskUpdate Stage 6 to completed.
6a. Auto-mode chain (only when AUTO_MODE = true)
When AUTO_MODE = true, do NOT end the turn after rendering the summary above. Instead chain directly into execution:
- Emit one user-visible line:
Auto mode: planning complete, chaining into ac:execute skill with args "<slug> --auto". - Invoke the
ac:executeskill via theSkilltool withskill: "ac:execute"andargs: "<slug> --auto". The execute skill's Phase 1a parses--autoand propagates auto mode through Phase 2, Phase 3, and Phase 4. - Continue executing in the same turn until the execute skill's Phase 4 completes OR a BLOCKER halts the run.
When AUTO_MODE = false: do NOT invoke /ac:execute automatically. The user reviews the plan first and runs it themselves. End the turn after the summary.
<error_handling>
- Subagent returns empty or malformed output → re-spawn once with an explicit format reminder. If still empty, call
AskUserQuestion(headerAgent fail?, optionsRetry/Skip this angle/Abandon). - User aborts mid-interview → checkpoint is already written per node; next invocation auto-detects and offers Resume.
- Plan path collision → handled in Stage 0f.
- Research finds nothing useful → surface in Stage 3a: "Investigation found no similar patterns. Proceed with greenfield assumption or refine the topic?"
- Audit gate produces more than 5 findings → present grouped by axis, ask the user to triage in batches via
multiSelect: true. - Write fails twice → escalate via
AskUserQuestionas in Stage 5; BLOCKER in auto mode. </error_handling>
- Read referenced files yourself before any decision. Subagent reports are candidate lists, not decisions.
- Apply the Stage 3b routing rule before every
AskUserQuestion; code-answerable and docs-answerable questions never reach the user. - Every load-bearing decision is locked, deferred, or risk-accepted. Zero open questions in the plan file.
- Tier write-style: just enough detail for the assigned model to act. Line-by-line prescription is a sign the tier is wrong.
- Stage 5.5 reviewer receives only the plan file path. Revise on REJECT via
Edit, not re-Write. - TaskUpdate as you enter and complete each stage. CC's native progress UI relies on it.
- Do not invoke
/ac:executewhenAUTO_MODE = false. The user reviews the plan first. </reminders>