Usage
/dev-workflow --init # Project setup (detect check/test commands)
/dev-workflow [-i N | --iterations N] <task> # Execute workflow (default)
/dev-workflow --resume <state-file> [-i N] # Resume next subtask from a decomposition state file
Prerequisites
- Reviewer skill (
reviewersetting, default: ask-peer): Required for plan/code review. Supported: ask-peer, ask-claude, ask-codex, ask-gemini, ask-copilot, ask-agy. If aSkill()call for the configured reviewer fails, attempt once more before declaring unavailable. If still unavailable, present the user with three explicit fallback options, each with its own resume semantics: (a) switch to another supported reviewer from the list — re-invoke the current review step with the new reviewer immediately (the original reviewer is not retried); (b) self-review — perform the review inline and advance past the current step (no later retry of the original reviewer); (c) pause at the current gate until the skill is installed — name the specific step where the original reviewer call will be retried once the skill is available. If the user picks option (a) and the substitute reviewer'sSkill()call also fails, the same retry-once-then-three-options protocol re-applies to the substitute — it is keyed on whichever reviewer is currently selected, not on the originalreviewersetting. Do not silently advance past a review pass without the user knowing their options. - rules-review skill: Required for rules compliance review (Step 7.5). If a
Skill(rules-review)call fails, attempt once more before declaring unavailable. If still unavailable: skip Step 7.5 with a message that names the fallback (Step 8 reviewer as a lightweight backup) and the resume point (re-run rules-review manually after the session or re-run the workflow once the skill is installed). - extract-rules skill: Required for rule update. If a
Skill(extract-rules)call fails, attempt once more before declaring unavailable. If still unavailable: skip Step 11 with a message that names the fallback (no rule updates this run) and the resume point (invoke extract-rules manually after the session to capture rule changes). - Cleanup skill (Step 6 Tidy): The Step 6 cleanup pass prefers the built-in
simplifyskill. InvokeSkill(simplify); if the call fails (skill-not-found or equivalent — a Claude Code version that lacks the built-insimplify), attempt once more, then emit a one-line note naming the fallback (e.g.simplify unavailable — falling back to in-house tidy) and fall back to the bundledSkill(tidy). "Available" is defined by the observable call outcome (a successful call), not by introspecting the in-context skill list — this mirrors the reviewer / rules-review / extract-rules bullets above so the orchestrator follows it deterministically. This bullet is the single source of truth for the simplify→tidy resolution; Step 6 references it rather than restating the definition. The fallback proceeds without a user gate (unlike the reviewer bullet's three-option prompt):tidyis a functionally-equivalent cleanup pass, so swapping it forsimplifydoes not change outcomes materially enough to warrant a user decision — whereas a reviewer swap changes review quality and so warrants one. Aftersimplify(or thetidyfallback) returns, judge the result semantically and proceed per§ No-Stall Principle.
Configuration
Settings files (YAML frontmatter only, merged across layers):
~/.claude/dev-workflow.local.md— User global defaults (lowest priority).claude/dev-workflow.md— Project shared settings (git tracked, team-shared).claude/dev-workflow.local.md— Personal overrides (gitignored, highest priority)
Merge strategy per key type (summary — the canonical operational definition, including the null/empty-clears and absent-inherits rules, is the Step 1: Load Settings "Overlay" procedure; keep the two in sync):
- Scalar (
reviewer,review_iterations,subagent_model,task_decomposition,interactive_commits,compact_rules,visual_plan_review,custom_instructions,language): higher layer wins (replaces) when the key is present; a key absent from a higher layer inherits from lower layers (see the inherit note below). Whenreview_iterationscarries a map value ({plan, code}) it is still a scalar key here — a higher layer's value replaces the lower layer's wholesale, with no per-key cross-layer merge (an absent map key is not back-filled from a lower layer; it falls to default3at resolution time). Thesubagent_modelmap ({<tier>: <model>}) is the same scalar/map class — a higher layer's map replaces the lower layer's wholesale (no per-key cross-layer merge), and an absent tier key falls to its built-in per-tier default at resolution time (sonnetfortrivial/simple, inherit formoderate/complex) - List (
check_commands): append — lower-layer items first, then higher-layer items, duplicates removed (keep first occurrence) - List-replace (
test_commands): higher layer's list replaces lower layer's list as a whole (no item-level merge or dedup). Defaults to["Skill(run-tests)"]when unset hooks: deep-merge at thehookslevel — each sub-key (on_complete) is merged as a list (append, deduplicated)
Keys absent from a higher layer inherit from lower layers. Only specify keys you want to override or extend.
---
reviewer: "ask-peer"
review_iterations: 3
subagent_model:
trivial: sonnet
simple: sonnet
task_decomposition: true
interactive_commits: true
compact_rules: false
visual_plan_review: false
custom_instructions: "Always use TDD. Write tests before implementation."
language: "ja"
check_commands:
- "pnpm run lint:fix"
- "pnpm run format"
- "pnpm run typecheck"
test_commands:
- "Skill(run-tests)"
hooks:
on_complete:
- "Skill(work-complete)"
self_retrospective:
feedback: "owner/repo" # or "/abs/path", "~/rel", "./rel"
workability_retrospective:
enabled: false # opt-in (experimental); Step 11.6 project-tooling retrospective
backlog_dir: ".claude/improvements"
---
- reviewer: Reviewer skill name (default:
ask-peer). Choose from: ask-peer, ask-claude, ask-codex, ask-gemini, ask-copilot, ask-agy. Unsupported values fall back toask-peer - review_iterations: Max iterations for Plan Review (Step 3) and Code Review (Step 8) (default:
3). Two accepted forms: (i) a scalar positive integer applies the same cap to both phases (e.g.review_iterations: 2); (ii) a map{plan: N, code: M}sets the Plan Review cap (Step 3) and the Code Review cap (Step 8) independently (e.g.{plan: 1, code: 3}). Each map key must be a positive integer; an absent or invalid key falls back to default3for that phase only (per-key validation — see Step 1 sub-step 4). Adopting the map form is the user's explicit opt-in; the scalar form and an absent key are fully backward-compatible (both phases default to3). Can be overridden per invocation with-i N/--iterations N, which overrides both phases with the same value regardless of the config form - subagent_model: Optional. A map from difficulty tier (
trivial/simple/moderate/complex) to the model the workflow'sAgent-tool subagent dispatches run on —sonnet/opus/haiku, orinherit(use the session model). It governs (i) the workflow's directAgentdispatches (Step 7's two background launches, and the shared session scan — one dispatch performed at Step 11 / Step 11.5 / Step 11.6, seereferences/session-scan.md) and (ii) the model propagated via theModel:argument to the named callees the workflow dispatches (Step 7.5rules-review; Step 6'stidyfallback dispatch — the bundledSkill(tidy)cleanup callee; the built-insimplifyprimary path takes no model and is unaffected; the Step 3 / Step 8 inline reviewer when the resolved reviewer is Claude-family — see Step 1's reviewer-family classification; external-CLI reviewers are not affected). Resolved once in Step 2 from the assessed tier (see Step 2's Adjust N for the resolution chain and the-i-path handling). Built-in default ={trivial: sonnet, simple: sonnet}(moderate / complex inherit). Behavior change: under this default, Trivial and Simple tasks run their subagent dispatches onsonnetinstead of the session model. To opt out (restore all-inherit on the low tiers), setsubagent_model: {trivial: inherit, simple: inherit}in.claude/dev-workflow.mdor~/.claude/dev-workflow.local.md. Invalid values / unknown tier keys warn and fall back to the built-in per-tier default.hooks.on_completeskill entries' models are independent of this key — the workflow never passesModel:tohooks.on_completecallee skills; each callee's model is set skill-side and is unaffected bysubagent_model. Per-subagenteffortis out of scope — theAgenttool exposes onlymodel. - task_decomposition: Whether Step 1.5 runs the auto-decomposition check in Normal sub-mode (default:
true). Set tofalseto treat Normal sub-mode requests (/dev-workflow <task>) as single tasks — Step 1.5 is omitted from the task list and the decomposition judgment is skipped entirely.--resume <state-file>is unaffected and still executes existing state files. Non-boolean values fall back totruewith a warning - interactive_commits: Whether Step 10 (Interactive Commits) runs after
hooks.on_complete(default:true). Whentrue, after Step 9 (Completion Hooks) the workflow proposes commit groupings and messages, then iterates per-commit with the user; it additionally proposes committing the updates that Step 11 (Update Rules) writes across extract-rules' output directories (rule files underoutput_dir,.examples.mdfiles underexamples_output_dir, and staged candidates understaging_output_dir) — see Step 11's "Commit rule updates" sub-step. Behavior change: previously those rule changes were always left for the user to commit manually (the Completion rule-update reminder); underinteractive_commits: truethe workflow now proposes the commit as an additional gate, and the manual-commit reminders fire only for whatever changes remain uncommitted after that gate (decline the gate to keep the manual-commit behavior). Whenfalse, Step 10 is omitted from the task list and never executes, and the Step 11 rule-update commit is likewise never proposed — the workflow ends with an uncommitted tree (the manual-commit reminder fires as before). Non-boolean values fall back totruewith a warning. To opt out, setinteractive_commits: falsein.claude/dev-workflow.mdor~/.claude/dev-workflow.local.md - compact_rules: Whether Step 11 sub-step 3 (Char-count compaction gate) runs (default:
false). The compaction mode added in v1.38.0 is currently experimental — whenfalse(the default), sub-step 3 is skipped entirely:Skill(extract-rules) --compactis never invoked, the gate is never opened, andcompaction_applied_count/below_threshold_failed_filesstay at their initial values so § Completion's compaction reminder is automatically omitted. Whentrue, the workflow invokesSkill(extract-rules) --compactand may enter the Step 11 compaction approval gate (USER APPROVAL GATE). Non-boolean values fall back tofalsewith a warning. To opt in for a specific project, setcompact_rules: truein.claude/dev-workflow.mdor.claude/dev-workflow.local.md - visual_plan_review: Whether Step 4 (Finalize Plan) launches the browser-based structured review gate in place of the text approval presentation (default:
false). This feature is currently experimental — whenfalse(the default), Step 4 always uses the text path (chat-rendered condensed plan →ExitPlanMode) exactly as before. Whentrue, Step 2 does not enter Plan Mode (plan_mode_active = false) so the gate can fire outside it (see Step 2 sub-step 2'splan_mode_activeresolution for why the gate's non-read-only operations require this); the default (false) keeps the unchangedEnterPlanMode → ExitPlanModeflow. Step 4 then launches the gate only if the local browser is reachable (the agent and the user share a machine — local CLI / Remote Control; detected viaCLAUDE_CODE_REMOTE), and transparently falls back to a no-Plan-Mode chat approval (also outside Plan Mode, noExitPlanMode) otherwise or on any launch failure — seereferences/visual-plan-review.mdfor the reachability check and the fallback contract. On the gate, the user reviews the plan in a structured local-browser view (summary header, collapsible sections, Decision cards, per-element comments) and returnsapprove(proceed to implementation) orrevise(comments applied to the plan, gate re-runs). Non-boolean values fall back tofalsewith a warning. To opt in for a specific project, setvisual_plan_review: truein.claude/dev-workflow.mdor.claude/dev-workflow.local.md. The gate is a local-only feature: on Claude Code on the Web the browser gate never launches (always the no-Plan-Mode chat-approval fallback, since the web UI offers no rich review surface beyond chat) — but enabling it there still takes Step 4 out of Plan Mode, so the approval surface becomes the chat reply rather than theExitPlanModemodal - custom_instructions: Free-form development instructions applied as guiding principles across planning, implementation, review, and tidy phases (e.g., "Always use TDD", "Prefer functional style"). Optional.
.claude/rules/and explicit user requests take precedence if they conflict - language: Optional. Output language code (e.g.
ja,en) for user-facing prose produced by this skill — Step 4 plan body (Overview / Decisions / Design / Test plan / Risks / Unknowns content), user-gate preambles (Step 4 / Step 7.5 / Step 8 / Step 11.6), Step 2 difficulty-assessment log, Step 10 commit-plan / per-commit gate output and the Step 11 "Commit rule updates" gate output (subjects, body, diff blocks framed in the resolved language; verbatim git output and file paths remain English), Completion summary, and Step 11.5 findingDescription/Suggested fix directionparagraphs. Resolution: merged skill config → Claude Code settings (~/.claude/settings.json→languagefield) → defaultja.null/ empty string / non-string values fall through to the next resolution step. For the localization boundary between translated concepts and verbatim identifiers, seereferences/plan-format.md§ Localization granularity. Seereferences/self-retrospective.md§2.1 Language handling / §5 Contract note for the Step 11.5 scope contract. No Step 11.5 output unlessself_retrospective.feedbackis also configured - check_commands: Static checks (lint, format, typecheck, etc.). Always run all in order
- test_commands: Defaults to
["Skill(run-tests)"]. Each entry must be aSkill(<name>)string (no shell commands). Entries run sequentially during Step 7. Run--initto generate or updaterun-tests; additional structural-check skills can be appended in project config (e.g. for bundle-sync drift detection, custom marketplace structure validators, or other repository-specific checks) - hooks: Execute skills/commands at specific workflow timing points
- on_complete: Runs as Step 9 (immediately after Step 8 Code Review). Entry format:
Skill(<name>)or shell command string - Entries not covered by allowed-tools require user approval
- on_complete: Runs as Step 9 (immediately after Step 8 Code Review). Entry format:
- self_retrospective: Optional. Emits sanitized improvement signal for the
dev-workflow-bundleskills (dev-workflow,ask-peer,extract-rules,rules-review) at Step 11.5 (between Step 11 and Completion). Raw conversation stays in-session; only abstracted text leaves- feedback: Destination string. Auto-detected:
- Starts with
/,~/,./, or../→ local directory path → retrospective written as a markdown file under that directory - Matches
^[\w.-]+/[\w.-]+$→ GitHubowner/repo→ retrospective submitted viagh apiPOST to/repos/<feedback>/issues - Any other string (including empty) → warn and skip Step 11.5
- Starts with
- If
feedbackis unset, Step 11.5 is not registered as a task and never executes — the workflow behaves as before - Step 11.5 runs whenever
self_retrospective.feedbackis configured, regardless of the Step 2 difficulty assessment — difficulty gates the review-iteration counts N_plan / N_code (Step 3 / Step 8) and the difficulty-skip matrix (Step 6 Tidy / Step 7.5 Rules Compliance on Trivial / Simple), but not the self-retrospective. Even Simple / Trivial tasks emit a retrospective whenfeedbackis set; when nothing notable surfaced, the retrospective is simply short Agenttool usage: DirectAgent-tool subagent spawns happen at exactly three dispatch sites across two steps per run — Step 7's two concurrent background launches (the per-passrules-reviewlaunch and the per-pass code review;run_in_backgrounddispatches for test-phase overlap — see Step 7's "Concurrent rules-review launch" and "Concurrent code review launch" paragraphs for whyAgentrather thanSkill()), and the shared session scan (one dispatch covering the rule-extraction, self-retrospective, and / or workability axes, performed once by whichever of Step 11 / Step 11.5 / Step 11.6 is the first participating step to dispatch — so the scan's host step varies across runs but the site count does not; seereferences/session-scan.md). Each of the three dispatch sites passes the Step 2-resolvedsubagent_modelas theAgentmodelparameter (omitted when the resolution isinherit). All other steps delegate to named skills (Skill(ask-peer),Skill(run-tests),Skill(rules-review),Skill(simplify)/Skill(tidy), etc.) and must not invokeAgentdirectly. (The Step 3 / Step 8 inline reviewer'ssubagent_modelpropagation rides the namedSkill(<reviewer>)call'sModel:argument, and Step 6'stidyfallback propagation rides the namedSkill(tidy)call'sModel:argument — both are not directAgentspawns and do not count against the three dispatch sites above.) The Step 4 visual plan-review gate (whenvisual_plan_reviewis enabled and the local browser is reachable — see Step 4 andreferences/visual-plan-review.md) launchesserve.mjsvia background Bash (run_in_background), not theAgenttool; it is not a subagent dispatch and does not count against the three dispatch sites here.
- feedback: Destination string. Auto-detected:
- workability_retrospective: Optional. Detects this session's project-tooling workability improvements at Step 11.6 (between Step 11.5 and Completion) and offers a per-candidate disposition gate. Like
self_retrospective, it is a nested map merged as a scalar/map key (a higher layer replaces the lower layer's map wholesale; no per-key cross-layer merge)- enabled: Whether Step 11.6 runs (default:
false). The detection + 4-way disposition feature is experimental (recently added) — whenfalse(the default), Step 11.6 is not registered as a task and never executes. To opt in for a specific project, setworkability_retrospective.enabled: truein.claude/dev-workflow.mdor.claude/dev-workflow.local.md. Non-boolean values fall back tofalsewith a warning - backlog_dir: Directory for the "save to backlog" disposition's markdown files (default:
.claude/improvements). A project that enables this feature should add itsbacklog_dirto.gitignore(the backlog is kept; only commit inclusion is blocked). Non-string / empty values fall back to the default with a warning - Step 11.6 runs whenever
workability_retrospective.enabledistrue, regardless of the Step 2 difficulty assessment (same asself_retrospective— difficulty gates the review-iteration counts and the difficulty-skip matrix, not the retrospective steps). The Step 11.6 detection is served by the shared session scan (seereferences/session-scan.md): Step 11.6 dispatches that scan when no earlier participating step did (Step 11 abstained becauserule-extraction-activewas false, and Step 11.5 was unregistered or pre-flight-aborted), otherwise it consumes the workability block from the already-dispatched scan — see theAgenttool usage bullet above
- enabled: Whether Step 11.6 runs (default:
Mode Detection
--init→ Init Mode (-i/--iterationsis ignored)--resume <state-file>→ Execution Mode (Resume sub-mode; see Step 1.5)- Otherwise → Execution Mode (Normal sub-mode)
Init Mode
Read references/init-mode.md and follow the procedure.
Note: Skills generated by
--init(e.g.run-tests) are recognized from the next session onward. Do not run/dev-workflow <task>in the same session as--init.
Execution Mode
No-Stall Principle
Once the workflow has started (after Step 1.5 resolves the effective task), it must run to Completion without pausing, except at the explicit user-gate points enumerated below. Every other step — including every skill invocation, every no-op outcome, every "nothing to report" result — must be judged semantically by the agent and passed through automatically. Do not rely on exact-phrase matching; if the skill result reads as a successful completion (fixes applied, no changes needed, no violations, no new rules, or any equivalent "success / no-op" outcome regardless of wording), treat it as success and proceed to the next step.
Explicit user-gates (the only permissible pause points):
Each bullet names the gate and points to the authoritative definition site. When editing either the enumeration or the definition, update both together.
- Step 1.5 task-decomposition proposal dialogue —
yes / adjust / noconfirmation (Normal sub-mode; defined in Step 1.5 dispatch andreferences/task-decomposition.md§ B. Normal sub-mode) - Step 1.5 leftover-subtask picker dialogue — selecting which subtask to run when more than one leftover
in_progresssubtask is runnable (Resume sub-mode; defined inreferences/task-decomposition.md§ A. Resume sub-mode) - Step 4 plan approval (defined in Step 4: Finalize Plan)
- Step 4 visual plan-review gate — when
visual_plan_reviewis enabled and the local browser is reachable, the browser-based structured review gate replaces the text approval presentation. The workflow waits for the browser submit, which is a harness-tracked background boundary (proceed on the background process's exit notification — not a "type continue" pause). It returnsapprove/rewrite-approach/fallback; the gate runs outside Plan Mode (Step 2 skipsEnterPlanModewhenevervisual_plan_reviewis enabled), so onapproveit proceeds directly to implementation without callingExitPlanMode, and onfallback(triggers perreferences/visual-plan-review.md§ Fallback contract) it continues with Step 4's no-Plan-Mode chat-approval path (sub-step 2 path (b)'s fallback branch), not theExitPlanModemodal. This gate renders its review surface in the browser, so it emits no § User-gate summary preamble — the preamble's "Applies to" list is intentionally not extended. Defined inreferences/visual-plan-review.md - Step 5 probe → real-implementation user-observation gate — when the Plan explicitly stages a probe / intermediate-artifact step before its real-implementation replacement: hold the workflow at the boundary until the user signals observation completion (defined in Step 5's "User-observable artifact protection gate" paragraph). Fires conditionally per the Plan's content — non-probe-staged plans never enter this gate
- Step 7 pre-execution scope-narrowing stop — when a
check_commandsentry is assessed as a repo-wide auto-fix tool, the working tree has unrelated existing changes, and scope narrowing is not feasible given the tool's interface: stop and ask the user for direction (options: run accepting full-width effect, skip, or provide an alternative scoped invocation) (defined in Step 7: Check / Test) - Step 7 scope-drift stop — when
check_commandswrites non-trivial changes outside the task-scope snapshot (trivial = whitespace-or-comment-only formatting on ≤ 5 lines attributable to the formatter/linter that just ran — those proceed automatically with a one-line note): warn and wait for user direction (defined in Step 7: Check / Test) - Step 7 check/test fail-stop — failure after 3 retries: report the error and stop (defined in Step 7: Check / Test). Note: this is an error-stop, not a pause for user decision
- Step 7.5 persistent-violations decision — rule violations still present after the 2nd review cycle (defined in Step 7.5: Rules Compliance Review)
- Step 8 unresolved-findings decision — reviewer-reported actionable findings still unresolved after the N_code-th iteration (defined in Step 8: Code Review)
- Step 10 commit-plan approval gate — accept the proposed commit grouping (subjects + file lists) for the working-tree changes; fires once on the initial plan and re-fires whenever a
Mid-loop adjustfile-regrouping / split-adding branch rebuilds the un-landed portion of the plan (defined inreferences/interactive-commits.md§ Propose commit plan) - Step 10 per-commit accept gate — accept each individual commit (subject / body / files / diff) before it lands; repeats N times where N is the approved commit count (defined in
references/interactive-commits.md§ Per-commit loop, judged per § Approval token closed list inside Step 10) - Step 10 fold-or-defer gate — after a pre-commit hook auto-modifies the working tree following a zero-exit commit, ask the user whether to amend the just-landed commit (
fold) or leave the changes uncommitted for a later iteration (defer); judged per the dedicated 5-branch →fold/defer/cancel/ re-present-as-adjustclassifier inreferences/interactive-commits.md§ Post-commit auto-modify cycle bound (the 5 input branches extend § Approval token closed list's 4 buckets with an additionaldefer-directionbranch; this gate is not the per-commit-accept-gate enum —cancelroutes viaMid-loop canceland ambiguousadjustresponses re-enter the gate via § Mid-loop adjust branch f, both in the same reference) - Step 10 ambiguous-adjust clarifier — when a
Mid-loop adjustrequest cannot be classified into branches a–e, ask the user a clarifying question and re-enter the gate that issued the request — this gate is itself the disposition for branch f ofMid-loop adjust — closed-list branches(inreferences/interactive-commits.md; categorization vocabulary depends on which gate originated the request) - Step 11 compaction approval gate — when
Skill(extract-rules) --compactreturns top-levelstatus: "compacted", present per-file diff (chars_before / chars_after / iterations_used / applied_edits_count / structural_notes / per_file_status / below_threshold) per § User-gate summary preamble and wait for accept/reject/adjust/cancel per the Step 11 local closed list (defined inreferences/update-rules.md§ Char-count compaction gate).cancelaligns with Step 10'sMid-loop cancelsemantic (no revert; seereferences/interactive-commits.md§ Mid-loop cancel);adjustuses Step 11's own three-case closed list (per-file disposition / clarification / other), not Step 10's branch f - Step 11 rule-update commit gate — when
interactive_commits: trueand Step 11'sSkill(extract-rules)wrote uncommitted changes under any of its three output directories (output_dir/examples_output_dir/staging_output_dir), propose committing them as a single commit (reusing the per-commit Present / accept / adjust / cancel mechanics fromreferences/interactive-commits.md, judged per § Approval token closed list);adjustnarrows the file set by pathspec omission andcancelleaves the changes uncommitted. Because it reusesreferences/interactive-commits.md§ Post-commit auto-modify cycle bound, the same fold-or-defer sub-gate the Step 10 fold-or-defer gate above describes can fire here if a pre-commit hook auto-modifies the tree after the rule commit lands (judged per that reference's 5-branch classifier). Defined in Step 11's "Commit rule updates" sub-step. Like the Step 10 commit gates, it renders the commit data verbatim viagit-shaped output and emits no § User-gate summary preamble - Step 11.6 workability-candidate disposition gate — per-candidate 4-way disposition (act now / make a subtask / save to backlog / reject; ambiguous responses re-present the affected candidate) over the workability candidates detected this run, presented once with a § User-gate summary preamble (defined in
references/workability-retrospective.md§ 4. Disposition gate). Fires only whenworkability_retrospective.enabledistrueand the detection subagent returned ≥ 1 candidate. The backlog-write / state-file-create failure classes are non-fatal (recorded and continued, perreferences/workability-retrospective.md§ 6) - Completion execution-time deferral/exclusion gate — when executing a decomposed subtask, if in-scope work items were excluded / deferred / discovered-unassigned during implementation or testing, ask the user to promote each uncovered item to a tracked subtask entry: (a) add as a new pending subtask (with
depends_onif sequencing matters), (b) fold into an existing pending subtask's scope, or (c) explicitly accept as permanently out of parent-task scope (defined in Completion's "Execution-time deferral/exclusion gate" paragraph). Fires conditionally — only on decomposed-subtask runs that surfaced uncovered items - Completion subtask PR URL prompt — when executing a decomposed subtask, ask for optional PR URL before resuming (defined in Completion)
Fatal errors are out of scope for this principle: configuration-file absence, malformed state file, irrecoverable skill / tool failures, and similar infrastructure-level errors halt the workflow with a diagnostic regardless of whether they appear in the list above. The No-Stall Principle governs successful step outcomes (including no-op successes); it does not force the agent to push through genuine errors.
At any point not listed above — including after Skill(simplify) / Skill(tidy), Skill(rules-review), Skill(extract-rules), Skill(run-tests), and reviewer skills return, and including collecting the background rules-review result (Step 7.5 sub-step 1) and the background code-review result (Step 8 sub-step 1), both launched in Step 7 — the agent must never wait for the user to say "continue" / "続けて". Semantic judgment of the returned result is sufficient. Likewise, when the Step 4 visual plan-review gate is active, its wait for the browser submit is a harness-tracked background boundary — proceed on the background serve.mjs process's exit notification without asking the user to "continue".
No-summary turn at review-return boundaries. When a reviewer or sub-skill returns a result that is semantically "nothing actionable" (no findings, no violations, no changes needed — regardless of the exact wording or the length of the response), the immediately next turn must begin with a tool call (a TaskUpdate to mark the iteration as completed, or the next step's invocation), not with a prose summary of the review outcome. Category-by-category verdict lists, conclusion paragraphs, and "shall I proceed?" sentences are the stall pattern — emit them only in the Completion summary (the ### Completion section that runs after the retrospective steps, Step 11.5 / Step 11.6), never at review-return transition boundaries. This applies to: Skill(ask-peer) / Skill(ask-claude) / Skill(ask-codex) / Skill(ask-gemini) / Skill(ask-copilot) / Skill(ask-agy) returning no actionable findings at Step 3 or Step 8 (at Step 8, whether returned inline or collected from the Step 7 background launch), Skill(simplify) / Skill(tidy) returning no changes, Skill(rules-review) returning no violations (whether returned inline or collected from the Step 7 background launch), Skill(extract-rules) returning no new rules at Step 11, and any other sub-skill whose result is treated as success.
Callee verdict transcription is not a turn boundary. When a sub-skill (Skill(simplify) / Skill(tidy) / Skill(rules-review) / Skill(extract-rules) / Skill(run-tests) / reviewer skills / any other callee) returns a fenced JSON verdict, status token, or structured summary, and the orchestrator's response re-transcribes that block (verbatim or paraphrased) in its own output, the transcribed block does not end the orchestrator's turn. The same agent must immediately issue the next tool call in the same turn — the next sub-step's invocation, the next iteration's dispatch, the next phase's transition, the next Step's first tool call. Specifically forbidden: inserting a "shall I proceed?" sentence after the transcribed verdict; emitting "ここまでで一区切り" / "ここまでで完了です" prose summaries between the verdict and the next action; ending the response on the verdict block and waiting for the user to say "continue" / "続けて". This rule extends the "no-summary turn" rule above to the case where the sub-skill returned an actionable result and the orchestrator's response carries the verdict's content forward — the verdict transcription itself is informational, not terminal. (For skill development this covers Pattern A iteration loop verdict returns where the orchestrator re-renders the JSON before re-dispatching, orchestrator multi-callee chains where one callee's verdict feeds the next callee dispatch, sequential sub-step completion marking, and hook-chain continuations.) Sub-step completion prose ("Step N complete", "(d) verify-diff returned converged") follows the same rule: completion reports in prose are not turn-end signals; the next sub-step's first tool call must follow in the same turn.
Progress Visibility
Before any subagent-backed skill call (Skill(<name>) invocations including run-tests, ask-peer, simplify, tidy, rules-review, extract-rules) or any shell command expected to take ≥ 30 seconds, emit a brief status message naming what is starting — e.g. "Starting test run via run-tests…" or "Calling ask-peer for plan review (iteration 1 of N)…". Emit the message as prose in the same assistant turn that issues the tool call, not as a separate preceding turn. This lets the user distinguish an agent in active progress from one that has stalled. After the step returns, proceed immediately to the next step per the No-Stall Principle — do not emit a separate acknowledgment turn. When Step 7 launches the background rules-review and/or the code review as background Agents, each dispatch is a subagent-backed call and emits its status line here; collecting the background results later (rules-review at Step 7.5 sub-step 1, code review at Step 8 sub-step 1) is a non-stalling return-boundary — proceed without a separate acknowledgment turn.
Mid-chain visibility (chained sub-skill calls or extended interpretation between tool calls). When a workflow phase issues sub-skill calls in a chain or spans extended internal interpretation / preparation across multiple tool calls (for skill development this includes a pre-implementation feasibility-check phase that fires several sub-skill dispatches in sequence, or a routine skill that issues several sub-skill dispatches back-to-back), the single pre-call status message rule above does not fully cover the user-visibility window. Extend the rule with a "current-location" line emitted at semantic checkpoints between dispatches — one short sentence naming the current phase and the next action ("Finished verify-diff for Finding 1; next: skill-review polish on the same file"). To keep the addition from re-introducing stall, three constraints bind its shape: (a) emit the current-location line as prose in the same turn as the next tool call, never as a standalone turn that waits for user input; (b) restrict the content to current phase name and next action only — review-result summaries, decision rationales, and "shall I proceed?" sentences stay out; (c) the rule does not apply to short same-turn chains of a few tool calls that complete inside a single turn — only to phases where the gap between user-visible signals would otherwise span multiple turns. Intent: in chained sub-skill phases (feasibility checks, routine dispatch loops, multi-call interpretation work) the user keeps seeing "this is alive and moving", while the No-Stall Principle's confirmation-prohibition stays intact.
Workflow artifacts (cross-step fixed exclusion)
Files this workflow itself creates and maintains as in-session state — plan documents under .claude/plans/, decomposition state files written by Step 1.5, Step 10, or Step 11.6, backlog files written by Step 11.6 under workability_retrospective.backlog_dir, the Step 4 visual-gate served plan file, its comments file, and its prev snapshot (.claude/plans/<slug>.plan-review.md / .claude/plans/<slug>.plan-review.comments.json / .claude/plans/<slug>.plan-review.prev.md), the Step 11 rule-extraction candidate file passed to extract-rules --apply-conversation-candidates (.claude/plans/<slug>.rule-candidates.md), and other workflow-internal staging artifacts placed under .claude/ by this skill — are cross-step fixed exclusions from any per-step changed-file enumeration (Step 6 Tidy scope, Step 7.5 rules-review diff input, Step 10 Interactive Commits' commit grouping, sub-skill dispatch payloads, scope checks). The exclusion is structural — the workflow owns these files as its own operational substrate — and is not gated on whether the path appears in .gitignore, whether a formatter ignore-file aligns, or whether the user happens to be touching them in this run. Steps that build a changed-file set, a diff-scope set, or a commit grouping must apply this single shared exclusion rather than re-deriving the rationale per step against ad-hoc justifications. If a future change adds another in-session-state path, extend this canonical list once rather than threading the exclusion through per-step prose (for skill development this is the canonical workflow-artifact set; sub-skills the workflow dispatches that maintain their own in-session state under .claude/ follow the same convention).
Step 1: Load Settings
- Read settings from up to three layers and merge (type-aware):
"Overlay" = for each key present in the file:merged = {} if ~/.claude/dev-workflow.local.md exists: overlay its frontmatter onto merged if .claude/dev-workflow.md exists: overlay its frontmatter onto merged if .claude/dev-workflow.local.md exists: overlay its frontmatter onto merged- Scalar keys:
merged[key] = file[key](replace) — this includesreview_iterationswhen its value is a map ({plan, code}): the whole map replaces the lower layer's value with no per-key cross-layer merge (a map key absent from the higher layer is not back-filled from the lower layer) - List keys (
check_commands): appendfile[key]items aftermerged[key], then deduplicate (keep first occurrence) - List-replace keys (
test_commands):merged[key] = file[key]— the higher layer's whole list replaces the lower layer's (no item-level merge or dedup) hooks: deep-merge — for each sub-key (e.g.on_complete), append and deduplicate the listnullor empty ([],{}) explicitly clears the key — lower-layer value is discarded, not inherited- Key absent from the file: left untouched (inherit from lower layers) If a file's YAML frontmatter is malformed (parse error), warn the user naming the file, skip that layer, and continue with remaining layers.
- Scalar keys:
- If none of the three files exist, prompt user to run
/dev-workflow --initand stop - Resolve
reviewerfrom config. If not specified or not in the supported list (ask-peer, ask-claude, ask-codex, ask-gemini, ask-copilot, ask-agy), useask-peer. Reviewer-family classification (the single definition referenced by the Step 3 / Step 8 inline-reviewersubagent_modelpropagation): Claude-family =ask-peer/ask-claude— model-controllable (ask-peervia itsModel:argument applied to its internalAgentdispatch;ask-claudevia theclaude -p --modelflag); external-CLI =ask-codex/ask-gemini/ask-copilot/ask-agy— these run their own non-Claude models and are notsubagent_model-controllable (never receive a propagated model). If the resolvedrevieweris notask-peer(bundle member, always available when dev-workflow is installed), probe availability immediately: attemptSkill(<reviewer>)with a one-word probe request (e.g.,ping); if the call fails, retry once. If still failing, emit the three-option prompt defined in § Prerequisites' "Reviewer skill" bullet — do not block the run, present the options and let the user decide before the first review step begins. - Resolve the review iteration counts — N_plan (Plan Review, Step 3) and N_code (Code Review, Step 8). A scalar config, the
-ioption, and the default all set both values equally; only the map config form makes them differ:- If
-i/--iterationsoption is present and is a positive integer, set both N_plan and N_code to it (the option overrides both phases) - Else if config
review_iterationsis present:- scalar positive integer → set both N_plan and N_code to it
- map (
{plan, code}) → N_plan =planif it is a positive integer else default3; N_code =codeif it is a positive integer else default3(per-key validation, independent per phase; warn on each absent/invalid key) - any other value (non-positive or non-integer scalar, list, string, or any non-map / non-scalar type) → warn and set both to default
3(any map takes the map branch above — an empty map, or a map with no validplan/codekey, already resolves to default3per phase there)
- Else use default
3for both Wherever a later step says "N" without a phase qualifier, Step 3 references resolve to N_plan and Step 8 references to N_code.
- If
- Parse
hooksfrom config. Warn and ignore ifhooks.on_completehas invalid format. Forreview_iterations, emit the invalid-value / invalid-map-key warnings as sub-step 4's resolution defines (sub-step 4 owns the case analysis and the default-3fallback per phase). Parsecustom_instructionsfrom config (optional, string). Warn and ignore if not a string. Parsetask_decompositionfrom config (optional, boolean, defaulttrue). Warn and fall back totrueif present but not a boolean. Parseinteractive_commitsfrom config (optional, boolean, defaulttrue). Warn and fall back totrueif present but not a boolean. Parsecompact_rulesfrom config (optional, boolean, defaultfalse). Warn and fall back tofalseif present but not a boolean. Parsevisual_plan_reviewfrom config (optional, boolean, defaultfalse). Warn and fall back tofalseif present but not a boolean. Parsesubagent_modelfrom config (optional, map of tier → model). Warn and ignore a non-map value (the built-in per-tier default applies); for each tier entry, warn and drop an unknown tier key or a value outside the enumsonnet/opus/haiku/inherit(that tier then falls to its built-in default at resolution time). The merged map is consumed by Step 2'ssubagent_modelresolution. Parselanguagefrom config per the Configuration bullet above. For~/.claude/settings.json, silently accept missing file / absent key /nullvalue; warn once per Step 1 settings-load pass on malformed JSON, non-string, or empty string. The resolved language is available to Step 11.5. Parseself_retrospective.feedbackfrom config (optional, string). Warn and ignore if not a string or if empty string"". Whenfeedbackmatches theowner/repopattern (^[\w.-]+/[\w.-]+$), additionally rungh auth statusas an early warning only — if auth fails, warn but do not block the run. Parseworkability_retrospectivefrom config (optional, nested map):workability_retrospective.enabled(optional, boolean, defaultfalse; warn and fall back tofalseif present but not a boolean) andworkability_retrospective.backlog_dir(optional, string, default.claude/improvements; warn and fall back to the default if present but not a non-empty string). Whenenabledis nottrue, Step 11.6 is not registered (sub-step 7) and never executes - Determine execution sub-mode: Resume if
--resume <state-file>was provided, otherwise Normal. Step 1.5 branches on this - Register all workflow phases with the Task tools, including review iterations — issue one
TaskCreateper phase below (each returns an auto-numberedtaskId). Do NOT skip any phase:- Step 1.5: Task Decomposition (Normal sub-mode only, AND only when
task_decompositionistrue— omit this entry entirely in Resume sub-mode or whentask_decompositionisfalse, since in either case the step has nothing to do at registration time) - Step 2: Create Plan
- Step 3: Plan Review
- Step 3-1 through Step 3-N_plan: Plan Review - iteration 1 through N_plan (generate N_plan items based on resolved N_plan)
- Step 4: Finalize Plan
- Step 5: Implement
- Step 6: Tidy
- Step 7: Check / Test [check: {check_commands} | test: {test_commands}]
- Step 7.5: Rules Compliance Review
- Step 8: Code Review
- Step 8-1 through Step 8-N_code: Code Review - iteration 1 through N_code (generate N_code items based on resolved N_code)
- Step 9: Completion Hooks (only if
hooks.on_completeis configured) - Step 10: Interactive Commits (only if
interactive_commitsistrue; single row — per-commit iteration is handled inline within Step 10 because the commit count is not known until the proposal phase) - Step 11: Update Rules
- Step 11.5: Self-Retrospective (only if
self_retrospective.feedbackis set and parses as a valid destination — see Step 11.5 for detection rules; if unset/invalid, omit this entry) - Step 11.6: Workability Retrospective (only if
workability_retrospective.enabledistrue; if unset/false, omit this entry. Registered regardless of the Step 2 difficulty assessment — see Step 11.6) Tool availability (Task tools vsTodoWrite): these steps name the Task tools (TaskCreate/TaskUpdate/TaskList), the default since Claude Code v2.1.142. Where the Task tools are unavailable (e.g. the VSCode extension, or Claude Code before v2.1.142), use the equivalentTodoWriteoperations instead — the status values (pending/in_progress/completed) and the register-all-upfront semantics are identical, and aTaskList-by-subject status read becomes a read of theTodoWritelist.allowed-toolsgrants both, so use whichever the environment exposes. Registration mechanics (Task tools): issue everyTaskCreatein a single upfront burst (one tool-call batch) so all phases are registered before Step 2 begins. Two conditional cases: (i) conditionally-omitted phases (the list items above carrying a condition) are omitted by not issuing theirTaskCreate; (ii) N-reduced excess iteration tasks (Step 3-x beyond resolved N_plan / Step 8-x beyond resolved N_code) are stillTaskCreated here at the resolved ceiling (Step 3 ceiling = N_plan, Step 8 ceiling = N_code), then markedcompletedviaTaskUpdateby Step 2's Adjust N by difficulty. Mark each taskin_progress(viaTaskUpdate {taskId, status}) when starting andcompletedwhen done. Task-handle resolution convention: every later "mark Step N asin_progress/completed" instruction in this skill is shorthand for resolve that Step's task — by its registration-time capturedtaskId, or by subject viaTaskList— thenTaskUpdate {taskId, status}; the per-step lines name tasks by their human-readable subject and do not restate this resolution path. Registering all phases upfront gives the user visibility into overall progress and prevents steps from being accidentally dropped. Phase-boundary self-audit: at every top-level Step transition (not the iteration sub-rows Step 3-i / Step 8-i, which are governed by the Return-point no-stall reminders below), before issuing the first tool call that advances into a new Step's procedure, name the Step number you are entering, resolve the prior Step's task by subject viaTaskList, and verify it iscompleted— if it is stillpendingorin_progress, return to the unfinished Step first instead of advancing. This guards against silent phase-skipping (e.g. jumping from Step 5 Implement to Step 7 Check / Test without running Step 6 Tidy, only to discover the gap during a later phase) that the task registration alone cannot prevent. Implementation sub-tasks in Step 5 are additions, not replacements. Note: Unless-i/--iterationswas explicitly specified, Step 2 may reduce N_plan / N_code based on task difficulty.
- Step 1.5: Task Decomposition (Normal sub-mode only, AND only when
- Context-compaction recovery: if the session context was compacted (prior turns summarized) before reaching this step in the current turn, re-read the configuration files from disk rather than relying on the summary — verify each step's skip conditions (e.g. whether
self_retrospective.feedbackis set, whetherworkability_retrospective.enabledistrue, whetherhooks.on_completeis configured, whetherinteractive_commitsistrue, whethercompact_rulesistrue) from the actual merged config, not from compacted context. - Interruption re-anchoring: if this invocation is a user-prompted continuation of a prior session that was interrupted (connection error, browser refresh, or similar — distinguished from compaction by the user explicitly asking to resume or continue rather than context being summarized in the same session), and
--resume <state-file>was not provided (that path is handled by Step 1.5 Resume sub-mode), re-establish the run's current position before proceeding: (i) read the task list (TaskList/TodoWriteread) to identify the step currently markedin_progress, (ii) re-read the configuration files from disk (same as the "Context-compaction recovery" sub-step's procedure), and (iii) announce the resumption point to the user ("Resuming from Step N — ") and proceed immediately from thein_progressstep — do not wait for user confirmation. Do not re-execute already-completedsteps.
Step 1.5: Task Decomposition
This step decides whether the user's request should be split into multiple smaller subtasks (each delivered as its own PR), or — in Resume sub-mode — picks the next subtask from an existing state file under .claude/plans/dev-workflow.<slug>.md.
State-file semantics are critical (a malformed or mis-routed file silently corrupts subtask boundaries), so the full procedure lives in a dedicated reference. Dispatch:
- Resume sub-mode (
--resume <state-file>was provided): readreferences/task-decomposition.mdand follow section A. Resume sub-mode from top to bottom. - Normal sub-mode +
task_decomposition: true(the default): readreferences/task-decomposition.mdand follow section B. Normal sub-mode. - Normal sub-mode +
task_decomposition: false: no decomposition work. Set the "effective task" to the original request and proceed to Step 2 without creating a state file. Step 1.5 is not registered as a task in this case (see Step 1), so there is nothing to markcompleted. You do not need to read the reference file.
EnterPlanMode is reserved for Step 2 (and only when plan_mode_active is true — i.e. visual_plan_review: false; on the visual_plan_review: true path Step 2 skips Plan Mode, see § Configuration) — any decomposition proposal in Step 1.5 is a plain yes/no dialogue, not a plan.
After section A or B completes, the "effective task" is set for Step 2 onward: the selected subtask when decomposed, otherwise the original request.
Step 2: Create Plan
-
Record the current commit as base-commit (
git rev-parse HEAD) for later diff comparison. Initialize the difficulty-skip ledger here: setdifficulty_skipped_steps = [](a cross-step list of human-readable records —<step> skipped (<tier> tier)— that § Completion's difficulty-skip reminder renders). This init lives at Step 2 entry, outside the-i-gated Adjust N sub-step below, so the variable is well-defined on every path: when Adjust N is skipped (because-i/--iterationswas given) or no tier qualifies for a skip, the ledger simply stays empty and § Completion omits the reminder. Same purpose as thecompaction_applied_countState-variable contract (well-defined on the skipped path) but a different technique: compaction initializes inside its conditionally-skipped sub-step and relies on a prose contract; this ledger is physically hoisted out of the skippable sub-step instead — do not relocate it into Adjust N expecting prose to cover the-ipath, since the init statement would then not run under-i. Also initialize thesubagent_modelcross-step variable here (same hoist rationale): setsubagent_model = inherit(no model override). The built-in tier → model map (§ Configuration) is consulted only after a tier is assessed in Adjust N; the pre-assessment value — and the value on the-ipath, where Adjust N is skipped and no tier is assessed — is alwaysinherit, so every downstreamAgentdispatch /Model:propagation omits the model (current behavior). Read sites: Step 7's two background launches, Step 7.5's sequentialrules-review, Step 6'stidyfallback dispatch, the shared session scan (one dispatch at Step 11 / Step 11.5 / Step 11.6, seereferences/session-scan.md), and the Step 3 / Step 8 inline reviewer (Claude-family only). Also initialize the shared session-scan cross-step state here (same hoist rationale): setsession_scan_dispatched = falseandsession_scan_result = null, so the state is well-defined on every path — including paths where the earliest participating steps abstain or are unregistered (e.g. rule-extraction inactive andself_retrospective.feedbackunset, leaving only Step 11.6 to dispatch). Lifecycle (perreferences/session-scan.md§ Dispatch-once contract): init = Step 2 entry (here); set = whichever of Step 11 / Step 11.5 / Step 11.6 performs the shared session-scan dispatch (it setssession_scan_dispatched = trueand stores the subagent's raw return insession_scan_result); read = the participating step(s) that consume their axis block fromsession_scan_result. Unlikesubagent_model, this state's set and read sites are confined to Step 11 / Step 11.5 / Step 11.6. -
Resolve
plan_mode_active, then conditionally enter Plan Mode: setplan_mode_active = (visual_plan_review == false)— a derived alias of the run-invariantvisual_plan_reviewsetting (read once, never reassigned — including on a Step 4rewrite-approachre-entry). Whenplan_mode_activeistrue(the default —visual_plan_review: false), callEnterPlanMode. Whenplan_mode_activeisfalse(visual_plan_review: true), do not enter Plan Mode: Step 4's visual gate and its no-Plan-Mode chat fallback perform non-read-only operations (writing the served plan file, launchingnode serve.mjs) that Plan Mode's read-only restriction forbids, so the gate can only fire outside Plan Mode (see § Configuration'svisual_plan_reviewbullet). In this no-Plan-Mode case the sub-step 6 "No code changes in this phase" rule is enforced by agent discipline alone, not by Plan Mode's read-only lock — hold to it through the Step 4 approval gate. -
Analyze the task and codebase, create implementation plan. Apply
custom_instructionsto shape plan priorities and structure. Follow the structure defined inreferences/plan-format.md— Overview / Decisions / Design / Test plan required; Risks / Unknowns optional. When the work is sequential, Design defaults to an ordered, numbered list of implementation steps (seereferences/plan-format.md§ Template, the source of truth). Section-level content rules live in the reference file; do not re-derive them here.- If a state file exists (this run is executing one subtask of a decomposed parent): the "effective task" = the current
in_progresssubtask. Frame the plan around just this subtask while keeping the full parent task and other subtasks as background context so the plan stays consistent with the overall direction. Do not plan work belonging to other subtasks. Seereferences/plan-format.md§ Subtask / Resume handling for how Decisions is scoped in this case - TDD-conflict resolution: if
custom_instructionsincludes a TDD-style requirement (e.g. "Always use TDD", "write tests before implementation") AND the current task is adding tests for existing behavior (characterization tests, coverage tests, or relocating existing tests — keywords: "add tests for", "characterize behavior", "test coverage", "move tests", "固定する", "追加する") rather than driving new implementation, declare explicitly in Plan Overview or Risks that this subtask is TDD-loop-external: tests describe and fix already-implemented behavior, not specification of new behavior. This resolves the apparent conflict: the TDD guideline governs feature-implementation subtasks; characterization and coverage subtasks are outside the TDD loop by design. - Version/identifier string replacement tasks: if the core operation is replacing a specific version string, identifier, or constant across the project (e.g. version bump, rename, migration), grep the entire repository for the old value before drafting the plan. Include the complete list of affected files in the Design section — missing even one location is the primary regression source for this task class
- Task-relevant skill annotation (applies to every plan — unconditional, unlike the two conditional bullets above): scan the skills available in this session's context (their
descriptions are loaded at session start, which is the signal Claude Code uses to decide when to invoke a skill) for any that materially help accomplish this task's own work, and annotate the Design step(s) where each would be used — perreferences/plan-format.md§ Template, a Design step's grammar carries the invoked skill as an optional element. This makes skill use explicit in the plan the workflow executes (Step 5) rather than relying on the model to spontaneously recall the skill mid-implementation. Constraints: (i) target task-domain skills only — exclude any skill the workflow itself already fires at a fixed step (the reviewer, the cleanup pass, rules-review, the test skills, extract-rules are illustrative); judge exclusion by "is this already a fixed-step callee?", not by matching a skill's name against that list — a task-domain skill that merely shares surface vocabulary with a callee still qualifies; (ii) annotate only skills actually present in the available-skills context — never invent a skill name; (iii) the annotation is a recommendation, not a contract — Step 5 may drop a suggested skill that turns out not to fit once implementation starts; (iv) annotate only the step(s) where a skill genuinely applies — most plans annotate few or no steps, and over-annotating bloats the plan
- If a state file exists (this run is executing one subtask of a decomposed parent): the "effective task" = the current
-
Simplicity self-audit: Before proceeding to Step 3, read
references/simplicity-self-audit.mdand audit the plan against its checklist. -
Plan self-check: Run the checklist in
references/plan-format.md§ Step 2 self-check against the plan. This is the author's first-pass judgment on Decisions content; fix any failures before Step 3. -
No code changes in this phase
-
Adjust N by difficulty (skip if
-i/--iterationswas explicitly specified): A typo fix doesn't need 3 rounds of review. Based on the plan just created, assess task difficulty and reduce the iteration counts to avoid unnecessary iterations — the configured value is a ceiling, not a target. The same difficulty cap is applied independently to N_plan and N_code (the two values that may differ only whenreview_iterationsis a map; otherwise they are already equal):- Trivial (a genuinely self-evident change with a single unambiguous solution — a typo fix, a one-line edit, a config value change): N_plan = N_code = 0 — Step 3 (Plan Review) and Step 8 (Code Review) are skipped entirely. Difficulty-skip matrix (Trivial): additionally skip Step 6 Tidy and Step 7.5 Rules Compliance Review — at this tier the cleanup pass and the rules-compliance walk are low-yield, and the Step 4 plan-approval gate plus Step 7
check_commands/test_commandsremain the safety net. Conservative tie-break: classify as Trivial only when the solution is truly unique and obvious; if the change spans more than a trivial edit, the solution is not uniquely determined, or there is any doubt at all, fall to Simple or above so internal review is retained. The same external-library major-bump exception described under Simple applies here too (such a change is never Trivial) - Simple (a straightforward bug fix with an obvious solution, or a localized change spanning a couple of sites — i.e. more than the single self-evident edit that qualifies as Trivial, so a lone typo or one-line config change belongs in Trivial, not here): N_plan = N_code = 1 — unless the change touches an external library's config file or type-level API AND that library had a recent major-version bump (primary check:
git diff <base-commit>of the package manifest; if absent in this run, judge from other context since the bump may predate this run); then classify as at least Moderate. Similar qualitative risks (external config-DSL rewrites, etc.) follow the same rule. Purely cosmetic edits (comments, whitespace, auto-formatting) do not trigger the exception — use judgment. Difficulty-skip matrix (Simple): additionally skip Step 6 Tidy only (a pure quality-cleanup pass, correctness-neutral); Step 7.5 Rules Compliance Review still runs, since rule violations do not correlate with change size - Moderate (multi-file within one module, feature following existing patterns): N_plan = min(2, N_plan), N_code = min(2, N_code) — no step is skipped (difficulty-skip matrix applies to Trivial / Simple only)
- Complex (cross-module, new patterns, API changes, significant refactoring): keep N_plan and N_code — no step is skipped
Step 9 (Completion Hooks) is never skipped by the difficulty-skip matrix at any tier —
hooks.on_completeis a project-configured open list whose callee set varies per project, so difficulty-gating it would make behavior project-dependent; the matrix covers only the whole-step-skippable Step 6 / Step 7.5.File count is a hint, not the sole criterion. If adjusted, mark excess task iteration items (Step 3-x beyond N_plan, Step 8-x beyond N_code)
completedviaTaskUpdate. When Trivial reduces both to 0, mark every Step 3-x / Step 8-x iteration item AND the top-levelStep 3: Plan Review/Step 8: Code Reviewrows ascompleted— both steps are skipped entirely (their entry-point guards in Step 3 / Step 8 recognize this pre-completed state and pass straight through; only Trivial produces 0, and it zeroes both counts together, so the "Trivial → both steps skipped" coupling holds). Difficulty-skip matrix marking (Step 6 / Step 7.5): apply the same pre-completed-mark + entry-point-guard mechanism to the whole-step-skippable quality steps. Keyed on the assessed tier alone (no config flag): for Trivial, mark the top-levelStep 6: TidyANDStep 7.5: Rules Compliance Reviewrowscompleted; for Simple, mark onlyStep 6: Tidycompleted; for Moderate / Complex, mark neither. For each row markedcompletedhere, append one record todifficulty_skipped_steps(e.g.Step 6 Tidy skipped (Trivial tier)/Step 7.5 Rules Compliance Review skipped (Trivial tier)) so § Completion's difficulty-skip reminder can render it (the skip is never silent). Step 9 (Completion Hooks) is never marked here (see the Step 9 note above). Resolvesubagent_modelhere (after the tier is assessed, in the same Adjust N pass): setsubagent_model =the merged-configsubagent_modelmap entry for the lowercased assessed tier name (trivial/simple/moderate/complex) when that key is present and valid, else the built-in default for that tier (sonnetfor Trivial / Simple,inheritfor Moderate / Complex), elseinherit. A resolved value ofinheritmeans downstream dispatches omit themodel(current behavior). This resolution is skipped under-i/--iterations(Adjust N does not run), leavingsubagent_modelat its sub-step 1inheritinit. Log the assessed difficulty and effective N_plan / N_code in the resolvedlanguage(see §Configuration; defaultja). The Step 11.5 and Step 11.6 task rows are not affected by the difficulty assessment — they staypendingregardless, since the self-retrospective is gated only onself_retrospective.feedbackand the workability retrospective only onworkability_retrospective.enabled. - Trivial (a genuinely self-evident change with a single unambiguous solution — a typo fix, a one-line edit, a config value change): N_plan = N_code = 0 — Step 3 (Plan Review) and Step 8 (Code Review) are skipped entirely. Difficulty-skip matrix (Trivial): additionally skip Step 6 Tidy and Step 7.5 Rules Compliance Review — at this tier the cleanup pass and the rules-compliance walk are low-yield, and the Step 4 plan-approval gate plus Step 7
-
Do not present the plan to the user or ask for approval/confirmation — presenting an unreviewed plan wastes user time and risks approval of a suboptimal approach. This prohibition extends to confirmation-seeking transition sentences such as "if this design looks good, I'll proceed to Step 3 (Plan Review)", "shall I move on to Plan Review?", or any equivalent ask-for-go-ahead phrasing — these read as natural conversation but constitute the same approval-gate that wastes user attention on an unreviewed plan. The moment Step 2 ends, advance directly to Step 3 without emitting any user-facing message about the plan or the transition. The user will see the plan in Step 4 (internally reviewed in Step 3, unless the task was assessed Trivial — N_plan=0 — in which case Step 3 is skipped and the plan reaches Step 4 unreviewed).
Step 3: Plan Review
This step is an internal review — the reviewer refines the plan before the user sees it, so the user receives a higher-quality plan in Step 4. Do not present the plan to the user or ask for feedback during this step.
Difficulty exception (Trivial / N_plan=0). When Step 2's difficulty assessment set N_plan = 0 (a Trivial task — Trivial zeroes both N_plan and N_code), this entire step is skipped: its task rows (top-level Step 3: Plan Review and every Step 3-x) were already marked completed by Step 2's Adjust N by difficulty. This skip is gated on task difficulty, not on the presence of user-provided analysis — the analysis-substitution prohibition below still applies in full to every Simple / Moderate / Complex task (N_plan ≥ 1).
Always run (for N_plan ≥ 1). Step 3 is not skippable on the grounds that the user's task prompt contained design analysis, prior-session handoff material, or review-like commentary. User-provided analysis is upstream planning content the user wrote — it is not an independent bias-free peer review pass and does not substitute for the reviewer dispatch. Handling rules (closed list):
- (i) The Step 3 reviewer skill is always invoked.
- (ii) User-provided analysis (long task descriptions that themselves argue for the approach, embedded justification in handoff docs, etc.) is fed into the reviewer skill's dispatch payload as additional context so the reviewer can build on it rather than re-derive it.
- (iii) An explicit user override in the task prompt ("you may skip Step 3 for this run", or equivalent) is the only analysis-driven path to skipping (distinct from the difficulty exception above). When this fires, record a warning in the Completion summary so the user has a visible signal that the bias-free review pass was bypassed.
The existing per-iteration "No actionable findings" semantic-judgment skip continues to work — that is a reviewer-side decision (the reviewer ran and returned no actionable feedback), not a Step-skip.
If N_plan = 0 (Trivial), skip this step entirely — its rows are already completed (see the Difficulty exception above), so do not re-mark them in_progress and proceed directly to Step 4. The following in_progress marking and per-iteration processing apply only when N_plan ≥ 1.
Mark Step 3: Plan Review as in_progress. Process each pending iteration item (Step 3-1 through 3-N_plan) in order:
-
Mark the iteration item as
in_progress. Call the reviewer skill resolved in Step 1 (e.g.Skill(ask-peer)): Review the plan.subagent_modelpropagation (inline reviewer): when the resolved reviewer is Claude-family (per Step 1's reviewer-family classification) andsubagent_modelis a model id, propagate it — passModel: <subagent_model>toask-peer, or include--model <subagent_model>in the dispatch instruction toask-claude. External-CLI reviewers and aninheritresolution carry no model (current behavior). Step 3 is always inline, so there is no background-launch path to double-apply against here. Pre-dispatch dispatch-boundary reminder: Issue theSkill(<reviewer>)call in the same turn as any accompanying status prose — never produce a standalone status turn before theSkill()call, as that creates a stall point. Reading the reviewer's SKILL.md is preparation, not dispatch; theSkill()call is the dispatch.- Instruct reviewer to read all files under
.claude/rules/for project conventions,references/plan-format.mdfor the Decisions (a)+(b) criterion and § Step 3 (f) content-quality rubric,references/simplicity-self-audit.mdfor the Step 2 audit checklist that category (a) below verifies, andreferences/review-categories.md§ Plan review categories for the full per-category rubric of the six categories below (resolve thesereferences/*.mdlinks to concrete readable paths when composing the request — the reviewer lacks the skill-directory context) - Request feedback organized into six categories (labels only — full rubric per the read-instruction above): a. Scope & feasibility b. Approach & alternatives c. Completeness d. Incrementality e. External library primary-source verification f. Presentation & attention allocation (content quality)
- If
custom_instructionsis configured, include the instructions text in the review request and have the reviewer verify alignment and report conflicts - If a state file is active (executing a subtask from a decomposition), include the current subtask's scope in the reviewer request: list the subtask's
titleanddescription, then list what the other subtasks cover (to define out-of-scope). Instruct the reviewer that missing functionality belonging to other subtasks is not an actionable finding for this review — only findings scoped to the current subtask qualify. Omit this when no state file is active (single-task execution has no defined out-of-scope boundary). - Reviewer should only report actionable findings. If none, explicitly state "No actionable findings"
- Instruct reviewer to read all files under
-
Judge the reviewer's response semantically: if the reviewer reports nothing actionable — no actionable findings, no improvements to apply, no review points raised, or any other "nothing to report" outcome regardless of exact wording — mark this and remaining iteration items as
completed(skip). MarkStep 3: Plan Reviewascompletedand proceed to Step 4 automatically. Per the No-Stall Principle, do not wait for user input and do not rely on exact-phrase matching; trust semantic judgment since the reviewer skill's phrasing varies (especiallySkill(ask-peer)and other free-form-prose reviewers whose verdicts are natural-language Markdown rather than a fixed token). -
Otherwise: autonomously apply improvements or reject inapplicable points with reason — do not ask the user for judgment on individual review findings. Mark this iteration item as
completed.- Approach-reconsideration self-audit on high findings count (iter 1 only): at the iter 1 → iter 2 boundary, before applying findings individually for iter 1's output, count the reviewer's findings by severity. If either threshold trips — Critical ≥ 3 OR (Critical + Major) ≥ 10 — additionally scan the findings list for any item that surfaces an approach-level alternative (typical phrasings: "X の方が筋がよい", "existing X と統合できる", "switch to ", "use instead", or any equivalent "the plan should adopt a different overall approach" framing). If at least one such approach-alternative finding is present, do not proceed with mechanical apply-and-iterate — instead, treat the findings cluster as a signal that the plan's Approach selection itself is the root cause. Rewrite the plan with the approach-alternative finding's direction promoted into the Decisions section (Recommendation / Alternative swap or insertion-direction new Decision item, per the rewrite class), add a new review iteration item Step 3-(N_plan+1), and return to Step 3 to re-review the rewritten plan. The remaining iter-1 findings are carried forward as context for the next reviewer. When the threshold trips but no approach-alternative finding is present (mechanical-fix-level findings only), proceed with the usual per-finding apply-and-iterate path. This audit applies only at the iter 1 → iter 2 boundary; later iterations have already exercised one or more apply cycles and approach-reconsideration after that point is the Step 4 user-gate's responsibility (general principle: high finding density paired with an approach-level alternative finding is a structural signal, not a quality signal — keep applying mechanical fixes and the plan still fails at Step 4 user gate).
- Prose-integrity self-check (post-fix): after applying a fix that edits plan prose adjacent to its target line (Decisions / Design / Test plan / Risks / Unknowns paragraphs), re-read the surrounding paragraph as a single unit before continuing — verify no sentence is cut mid-word, no logical connective is broken (the connectives
however/therefore/because/but/ etc. still anchor real clauses), and the paragraph's overall logic still holds. Mechanical fix patches see only the line-level diff and routinely leave the surrounding prose semantically broken in ways the next iteration's reviewer flags as a Major finding, costing an extra iter. - If the plan was modified: continue to the next pending iteration item (back to step 1). Plan modifications often introduce new gaps or ripple effects that the previous reviewer had no chance to see — the re-review round-trip is cheap compared to shipping a plan that looks fine to the author but has an unvetted section. Don't short-circuit even when the fixes feel airtight
- If all points were rejected (no modifications): mark remaining iteration items as
completed(skip — there is nothing new for the next reviewer to look at) Continue to the next pending iteration item with: - the updated plan
- a summary of changes made and rejections with reasons
- an iteration-scope instruction: from iteration 2 onward, the reviewer's primary verification scope is the plan changes applied since the previous iteration (conveyed by the summary of changes above — no separate diff artifact is provided) plus landing confirmation of the previous iteration's findings — the full-coverage pass (re-verifying every plan section, decision, and cited reference from scratch) belongs to iteration 1 only. The reviewer must still escalate back to full re-verification when content outside that primary scope raises a new concern, so coverage is reordered, not reduced
- the same six-category structure (a–f),
.claude/rules/reference, and "No actionable findings" requirement
Return-point no-stall reminder: At each iteration boundary (regardless of reviewer outcome — findings reported, "No actionable findings", any non-error result), the next action — the next iteration's reviewer dispatch when more iteration items remain, or the Step 4 transition when this was the last iteration or "No actionable findings" was returned — must be issued in the next tool call. Do not insert an interstitial summary or acknowledgment turn between iterations; the abstract enumeration in
§ No-Stall Principleis intentionally duplicated here so the rule fires at the decision moment. -
If all N_plan iteration items are completed and actionable feedback still remains, carry the unresolved points forward to Step 4.
Mark Step 3: Plan Review as completed.
Step 4: Finalize Plan (USER APPROVAL GATE)
-
Before presenting, verify via
TaskListthatStep 3: Plan Reviewand every Step 3-x iteration item arecompleted— presenting the plan for approval (the surface chosen in sub-step 2) is the effective end of internal review, so reaching it while any Step 3 item is stillpendingorin_progressskips the review entirely (on path (a) that presentation isExitPlanMode, which is also the Plan Mode exit). If any Step 3 item is notcompleted, emit a one-line inline note to the user naming all incomplete items (e.g.,Plan review found incomplete (Step 3-2 still pending) — running the remaining review pass before presenting the plan., substituting the actual incomplete iteration item label(s)) then return to Step 3 to process it (do not flip the row tocompletedwithout doing the review work). Exception: when Step 2's difficulty assessment set N_plan=0 (a Trivial task) and therefore pre-marked all Step 3 rowscompleted, that completed state is the intended skip — not an unrun-review bug — so proceed to the approval presentation normally. 1.5. Prose-language self-audit: Before presenting the plan for approval (the surface chosen in sub-step 2), verify that explanation prose in the plan body (Overview narrative, Decisions rationale, Design descriptions, Test plan steps, Risks/Unknowns paragraphs) is written in the resolvedlanguage. Schema tokens (Overview/Decisions/Design/Test plan/Risks/Unknowns), step labels, enum values, identifiers, and quoted code strings stay in their original form regardless oflanguage. Audit both directions: (a) if any explanation sentences are in a different language than the resolvedlanguage, and (b) if concept words outside the verbatim-preserve scope — ordinary nouns, adjectives, conjunctions, verb phrases — are over-preserved in the source language rather than rendered in the resolvedlanguage(perreferences/plan-format.md§ Localization granularity's Negative-direction rule). Revise any failures now perreferences/plan-format.md§ Localization granularity before proceeding to sub-step 2. Re-entry coverage: this audit must re-run on every entry into Step 4 — both the initial entry and any re-entry triggered by sub-step 1's "return to Step 3" path or sub-step 3's material-change path — since revisions during Step 3 iteration may introduce prose in a language different from the resolvedlanguage. -
Plan presentation — branch on
plan_mode_active(resolved at Step 2 sub-step 2's conditional Plan-Mode entry). Sub-steps 1, 1.5, and 3 apply to every path unchanged.(a)
plan_mode_active == true(the default —visual_plan_review: false): Plan-Mode text path, unchanged. This is the first time the user sees the plan. Write the full plan body to the Plan Mode plan file with theWritetool (theExitPlanModeapproval modal renders that file's contents), and present a condensed view in chat per the two-tier protocol inreferences/plan-format.md§ Step 4 presentation order — internally reviewed in Step 3 for N_plan ≥ 1 (include any unresolved review points from Step 3); for a Trivial task (N_plan=0) Step 3 was skipped, so present the plan as unreviewed and rely on this user-approval gate as the sole review. Render the chat view in this order: a.## Planheader as a visual boundary. b. The> Review guideline (perreferences/plan-format.md§ Review guide line) followed by the condensed plan body, followingreferences/plan-format.md§ Localization granularity in the resolvedlanguage(see §Configuration; defaultja):Overviewin full (includingHighlightswhen present),Decisionsin full, andDesignas a file-list only (files to change + one line of what-changes each).Test planandRisks / Unknownsare not rendered in chat — they live in the full plan file and surface via the preamble'sverification approach/known risksslots. Section headings render at###level (one below the## Plancontainer); sub-sections (Title, Goal, Scope, Decision N, Implementation, etc.) at####. c. Horizontal rule (---) separator. d. Summary preamble perreferences/plan-format.md§ User-gate summary preamble. e. Guidance line perreferences/plan-format.md§ Step 4 guidance lines (verbatim, no paraphrasing, no concatenation). f. CallExitPlanModein the same turn, immediately after the guidance line.ExitPlanModetriggers the approval modal (which renders the full plan file) — if it is not called, the user sees the plan text but has no way to approve. DelayingExitPlanModeto a subsequent turn is the primary cause of Step 4 appearing stalled.(b)
plan_mode_active == false(visual_plan_review: true): no Plan Mode was entered, so there is no Plan Mode plan file andExitPlanModeis never called on this path (it is invalid outside Plan Mode; the item-fExitPlanModeabove is scoped to path (a)). First establish the no-Plan-Mode plan document: resolve<slug>once per run, then reuse it verbatim on any Step 4 re-entry (same stability asplan_mode_active— arewrite-approachre-entry must not re-resolve it). Reuse the active decomposition state file'sslugwhen a state file is in play, otherwise derive a kebab-case slug from the effective task (transliterate non-ASCII where reasonable, strip punctuation, lowercase; on collision with an existing.claude/plans/<slug>.mdfrom a prior run, suffix-2,-3, … — this collision check applies only to first resolution, never on re-entry against this run's own<slug>.md), mirroringreferences/task-decomposition.md§ B. Normal sub-mode's slug algorithm — then write the full plan body to.claude/plans/<slug>.md(the canonical plan document that work-complete archives and that § Completion's cleanup preserves; on a decomposed parent, successive subtasks reuse the parent slug and overwrite this<slug>.md, which is harmless because the plan document is per-run and the separatedev-workflow.<slug>.mdstate file carries cross-subtask state). Then choose the approval surface:- Local browser reachable → visual gate path: read
references/visual-plan-review.mdand follow it top to bottom (it detects browser reachability, writes the served file from.claude/plans/<slug>.md, launches the browser gate via background Bash, and loops internally on localizedrevise). It returns one of three outcomes:approve→ the gate has written the latest plan back to.claude/plans/<slug>.md, and the browser submit is itself the final confirmation, so proceed directly to implementation (noExitPlanMode);rewrite-approach→ a revise comment requested an approach-level material change; handle it exactly per sub-step 3'srewrite-approachbucket (the gate has written the latest plan to.claude/plans/<slug>.md);fallback→ continue with the chat-approval path below (fallback triggers per the reference's § Fallback contract). The visual path does not emit the chat condensed view / preamble / guidance line — the browser is the review surface. - Browser unreachable or
fallback→ no-Plan-Mode chat-approval path: present the condensed chat view exactly as items a–e above (## Planheader,> Review guide+ condensed body,---separator, preamble, guidance line), then — instead of item f'sExitPlanMode— append a one-line pointer to the full plan document at.claude/plans/<slug>.md(already written above) and wait for the user's chat reply (there is no approval modal). Classify the reply per sub-step 3's four buckets. Do not callExitPlanMode.
Section headings (
Overview/Decisions/Design/Test plan/Risks/Unknowns) and the Step 4 guidance line stay English on every path. - Local browser reachable → visual gate path: read
-
Collaborate with the user to refine the plan as needed (normal Plan Mode interaction on path (a); normal chat / visual-gate interaction on path (b) — a
swap-decisions/rewrite-approachre-presentation re-enters whichever surface this run uses: theExitPlanModemodal on path (a), the relaunched visual gate or the chat re-present on path (b)). Categorize each user response into one of the four buckets below via semantic judgment (per § No-Stall Principle's "do not rely on exact-phrase matching" rule — example phrasings are illustrative, not literal discriminators):- accept: explicit affirmative — "OK" / "approve" / "looks good" / "進めて" / any semantic equivalent. Begin implementation.
- swap-decisions (Decisions Recommendation/Alternative swap on one or more specific items — "Decision 1 を Alternative に", "swap the recommendation on the language flag", "use the alternative for Decision N", "Decision N と M は Alternative で残りはそのまま"): re-render the plan with the specified Recommendation / Alternative pairs swapped on the named Decisions items, leave other items unchanged, run the read-back sub-step below, then re-present the plan (re-enter the gate). When the user names multiple Decisions in one message, list every affected item on the read-back line so partial-coverage misses cannot slip through.
- rewrite-approach (Approach / Design / Scope-level material change — "switch from independent skill to extending sibling mode", "split this into two subtasks", "scope down to only the canonical site", or any change that does not fit a clean Decisions swap): add a new review iteration item (Step 3-(N_plan+1)), run the read-back sub-step below, return to Step 3 to re-review the modified plan, then re-enter Step 4 from sub-step 1 (so sub-step 1's task completion check on the new Step 3-(N_plan+1) item and sub-step 1.5's prose-language re-entry-coverage audit both run before re-presenting at sub-step 2). Trivial (N_plan=0) re-activation: if the task had been assessed Trivial (N_plan=N_code=0) so Step 3 was skipped, an Approach-level material change means the task is no longer trivially self-evident — re-run Step 2's Adjust N by difficulty against the rewritten plan to re-derive the difficulty assessment itself (it will no longer be Trivial) and the effective N_plan / N_code (re-running the independent-cap logic on both values, not a single value). Updating the difficulty assessment — not just the counts — is required because every downstream gate keys on the assessment, not on a bare count: Step 4's unreviewed-plan presentation and the
references/plan-format.mdTrivial conditional both read "the task was assessed Trivial"; leaving the stale Trivial label in place would keep announcing "sole review". Then re-mark the task rows for the re-derived difficulty: register Step 3-1 … Step 3-N_plan (and the Step 8-1 … Step 8-N_code rows) as freshpending, clear the previously-skip-completed top-levelStep 3: Plan Review/Step 8: Code Reviewrows back topending. The difficulty-skip matrix is re-derived in the same pass: resetdifficulty_skipped_steps = []and re-run Adjust N, which recomputes which ofStep 6: Tidy/Step 7.5: Rules Compliance Reviewthe new tier skips and re-populates the ledger from scratch (no find-and-remove of individual records). Clear any previously-skip-completed Step 6 / Step 7.5 row back topendingwhen the higher tier no longer skips it — the same re-pending treatment applied to the Step 3 / Step 8 rows. Without this re-derivation the Step 3 entry-point guard would skip the new review item (it skips whenever N_plan=0), Step 4's completion check would loop on the unprocessed item, and a Step 6 / Step 7.5 row left stale-completedwould silently skip a quality step the higher tier now requires. - withdraw: explicit halt — "stop" / "cancel" / "abort" / "やめる" / "取り下げ". Exit the workflow with no further steps; do not proceed to implementation.
Read-back sub-step (mandatory before applying any
swap-decisions/rewrite-approachinterpretation): emit a one-line summary of the interpreted change in the resolvedlanguage(e.g.Decision 1 を Alternative に切り替え、Decisions 2 と 3 は Recommendation のまま保持します — このまま反映してよろしいですか?) and wait for the user to confirm before re-rendering. The read-back is the gate-of-origin's own resolution branch; do not nest a separate ExitPlanMode call inside it. If the user's confirmation response itself reads as anotherswap-decisions/rewrite-approach/withdrawinstruction, treat the read-back as un-confirmed and re-classify under the four buckets above. The read-back catches multi-Decisions instructions with partial coverage and Approach-level instructions that masquerade as Decisions swaps — both are common failure modes that silently lose user-specified scope when interpreted without read-back.NOT approval (interrogative or non-committal — "look good?" / "How is it?" / "Is this okay?"): treat as ambiguous — ask the user to confirm whether they intended an affirmative or to surface a change request, then re-classify the response under the four buckets above. Do not silently advance.
After the user accepts (
acceptbucket), begin implementation.
Step 5: Implement
-
Plan entry self-check — user-side manual action extraction: before issuing the first implementation tool call, scan the approved Plan body (Overview / Decisions / Design / Test plan / Risks / Unknowns) for embedded user-side manual actions — environment-prerequisite probes the user must run themselves, configuration values the user must add to a config file outside the agent's write surface, external authentications / API keys / hook installations / OS-level changes the user must perform manually, manual verification steps the user must execute against external systems (for general software development this includes "run
<command>and confirm output", "edit~/<config>to set X=Y", "log in to and authorize Z"; for skill development this includes~/.claude/settings.jsonedits, hook installation, external CLI installation, or workspace-level config the user must place outside the repo). When at least one such manual action is present, emit a short independent block at the top of Step 5 — separately from any other implementation prose — listing each manual action verbatim with the Plan section it came from, before proceeding with the first implementation tool call. The block ensures the user sees the manual action items distinctly rather than discovering them buried inside long-running plan execution. When no manual actions are present (purely agent-executable plan), skip this block. The block is informational — Step 5 continues without waiting for user input on the manual actions themselves (the user-side observation gate at the probe → real-implementation boundary handles cases where the workflow needs to wait). -
Follow the plan, track progress with the Task tools (
TaskUpdate). When the Design is an ordered, numbered list of implementation steps (perreferences/plan-format.md§ Template), you MAY register each step as an implementation sub-task and execute them in order, marking eachcompletedas it lands — recommended for long ordered plans, optional for short ones. This is consistent with Step 1's "Implementation sub-tasks in Step 5 are additions, not replacements" rule and does not change the Phase-boundary self-audit (which governs only top-level Step transitions). Applycustom_instructionsthroughout implementation -
Respect prior in-session edits: content the user explicitly removed earlier in this session (comments, guards, logs) must not reappear. Treat deletion as authoritative, not as a gap to fill. This discipline applies when applying plan steps, when applying Step 6 tidy output, and when applying Step 8 review fixes — the reviewer/tidy subagents only see the diff and cannot enforce this themselves
-
Late-stage scaffolding self-audit: when implementation introduces a structural element that was not present in the Step 2 plan — a new sub-step, an additional enum value, a new branch arm, an additional call site that invokes the same callee at a new location, a new recovery / fall-through path (for skill development this includes a new SKILL.md sub-step, an additional
statusenum in a return contract, a new error class, a new disposition mapping row) — re-apply the same Step 2 § Simplicity self-audit rigor to the newly introduced element before moving on. Sub-checks (i)–(iv) fire only when a new structural element is introduced; sub-checks (v), (vi), (vii), and (viii) fire unconditionally for every diff edit: (i) sibling symmetry — when the new element parallels existing sibling elements, verify same fields / same disposition values / same error-class coverage; (ii) error-path symmetry — for any success path introduced, trace its corresponding failure path explicitly (counter increment vs. non-increment, success-only vs. failure-included); (iii) boundary-value coverage — for any predicate, threshold, or count introduced, trace the boundary cases (empty input, all-same-classification, mixed-classification) and verify the predicate truth value matches design intent; (iv) reference-site sweep — if the new element is referenced from prose elsewhere in the file, verify those references use stable phrase anchors (not raw sub-step numbers / branch letters); (v) Markdown block-element structural integrity — for each edited.mdfile (unconditional: applies regardless of whether a new structural element was introduced), scan newly added or changed content for adjacent block elements (list items, paragraphs, code fences, headings, blockquotes) that lack a separating blank line; when a gap is found, insert the missing blank line immediately (in the same Edit call) before moving on; missing blank lines cause the following element to be parsed as a lazy continuation of the preceding block and rendered merged — the gap typically surfaces in skill-review as a mechanical edit (for skill development this includes SKILL.md,references/*.md, and README.md edits); (vi) comment conciseness — for every inline comment introduced or changed in the diff, apply the rule-of-need test: a comment is justified only when the why is non-obvious (a hidden constraint, a subtle invariant, a workaround for a specific bug, behavior that would surprise a reader); a comment that restates what the code does is a deletion candidate; multi-line background explanations belong in rule or design documents, not inline — when a verbose or redundant comment is found, delete or condense it before moving on; (vii) newly-introduced cross-reference stable-anchor form — for every cross-reference (Step / sub-step pointer) the diff newly introduces, verify it carries the stable descriptor alongside the number (the number-plus-stable-descriptor pair form required by project rules) rather than a bare number alone; when a non-conforming form is found, add the stable descriptor before moving on (for skill development this includes newStep N/ sub-step pointers in SKILL.md andreferences/*.md); (viii) closed-list / sibling-set stale-value sweep — when the diff edits one or more entries of a closed list or a set of parallel sibling references (a decision-mapping table row, a numbered list with sibling rows, mirrored cross-references), re-read the entire list / sibling set and confirm no entry was left with a stale value inconsistent with its updated neighbors; grep the remaining entries for the old token before moving on (for skill development this includes decision-mapping rows, return-contract enum value lists, and mirrored step-number references where one token has been renamed or updated). The reviewer / tidy subagents see only the diff and cannot enforce this self-audit, so it must run in the main thread at Step 5 — late-stage scaffolding correctness gaps surfacing first at Step 8 Code Review iter 1 indicate this audit was skipped. -
Final-pass literal-value full-repo grep: at Step 5 completion (after all planned edits are applied and before advancing to Step 6 Tidy), for each literal value the plan replaced or introduced — numeric constants (threshold values, version numbers, magic numbers), token strings (status enum values, config keys, identifiers), file path fragments, or any other literal whose semantics are tied to a specific value —
grepthe entire repository (not just the plan's enumerated sweep targets) for the old value and confirm zero hits. The Plan's Test plan typically enumerates known sweep sites, but narrative examples embedded in prose (illustrative numbers in descriptive text, story-style usage examples in SKILL.md /references/*.md/ README files) routinely sit outside the enumerated list and silently retain the old value through mechanical search-and-replace passes. Multi-stage structure: (i) enumerated sites — the explicit list from the Plan's Test plan, verified one by one; (ii) final-pass full-repo grep —git ls-files | xargs grep -l <old-value>(or equivalent) for any residual hits outside the enumerated list, with each hit reviewed in context and either updated (if it carries the old value's semantics) or marked as out-of-scope (e.g. a different concept that coincidentally uses the same literal); (iii) alias and derived-form sweep — for rename and migration tasks, additionally grep for mechanically-derivable aliases and derived forms of the old value (abbreviated forms, synonyms, or alternate identifiers the codebase uses interchangeably to refer to the same concept); when the derived-form set can be enumerated upfront, list and grep each form before declaring the sweep complete; grepping only the exact old value misses same-concept usages expressed under an alternate spelling (for skill development this includes aliased import names, short-form identifiers referenced in SKILL.md narrative examples, and config-key abbreviations). The reviewer / tidy subagents see only the diff and cannot enforce the full-repo sweep, so it runs as a Step 5 completion gate (for skill development this includes literal numeric thresholds cited inreferences/*.mdnarrative examples, version strings in README usage snippets, and example values in compaction / extract-rules-style descriptive prose). Authoritative-tool cross-check for load-bearing enumeration claims: when the completeness of the enumeration is mechanically verifiable by a downstream authoritative tool — a compiler or type checker reporting all affected call sites for a changed type or interface, a language server returning all references for a renamed symbol (for skill development, when no compiler or language server is available, the authoritative check is a structured manifest audit: e.g.jqagainstmarketplace.jsonto enumerate allskillsarray entries affected by a renamed skill, or a targetedGrepscoped to SKILL.md / plugin.json / marketplace.json for all hook-firing paths or all subagent dispatch routes that a configuration change affects — when no such structured verification is available, the grep-only pass is sufficient) — cross-check the grep results against that tool's output; if the tool reports additional sites that grep missed, treat those as unresolved hits and apply the same two-option disposition defined above for the full-repo grep pass (update if it carries the old value's semantics; mark out-of-scope if it coincidentally uses the same literal for a different concept) — and complete this resolution before presenting the enumeration as confirmed. Search filter prefix/anchor errors can silently drop matches with no error signal; authoritative-tool verification catches these missed cases. When both grep and an authoritative tool are available, treat the tool output as the oracle. Non-literal-replacement tasks skip this audit. -
Pre-write path scope check (Write / Edit / new-file path safety): before every
Write/Edit/ similar file-creation tool call whosefile_pathargument does not match a path that already exists ingit ls-filesoutput (typically: new files generated by Step 5 / Plan rewrite / staging document creation / new test fixtures / new CHANGELOG entries — file paths that the tool will create rather than modify-in-place), run a two-stage path verification before issuing the tool call: (i) repo-root containment — verify the absolute resolved path sits undergit rev-parse --show-toplevel(no../escape from the working directory, no absolute path leading outside the repo); (ii) prefix sanity — verify the path's leading directory matches an expected location for its content class (.claude/plans/for plan documents,skills/<name>/for skill content,src/ortests/or equivalent for code,.triage/ortmp/for staging, etc.). If either check fails, abort the tool call with a fail-loud diagnostic naming the resolved path and the expected prefix set, rather than silently creating the file. Theallowed-toolspermission grant alone does not prevent parent-directory landing (Writeaccepts any stringfile_path), so a procedural pre-check is the only structural defense against typo-induced orphaned files (for general software development this includes accidental migration / config / test-fixture writes landing one directory up; for skill development this includes.claude/plans/<slug>.mdtypos depositing files at../<slug>.md, marketplace.json paired-bump operations writing to the wrong manifest, or staging documents landing outside.triage//.claude/). If a tool call has already created a file in the wrong location, instruct the user to delete it manually — the workflow's auto-mode classifier cannot reach files outside the project scope, so manual cleanup is the only path. -
User-observable artifact protection gate at probe → real-implementation boundary: when the Plan explicitly stages an implementation as probe / intermediate-artifact → real-implementation replacement (e.g. "first emit a debug-instrumented version for user to observe, then replace with the production implementation", "scaffold a placeholder file the user will manually inspect, then overwrite with the final content", "log expected probe output as a verification step, then remove the logging"), do not advance to the real-implementation step until the user has signaled observation completion. The probe-output observation gate is the only user-side wait state permitted inside Step 5 — every other Step 5 sub-step proceeds autonomously per § No-Stall Principle. When the probe is committed to disk and the user has not yet acknowledged observation, hold the workflow at this boundary and emit a one-line wait prompt in the resolved
language(e.g.Probe artifact deployed at <path> — please observe its output before the workflow replaces it with the final implementation. Reply when ready to proceed.). Resume the real-implementation step on any non-empty user reply. When no probe → real sequence is in the Plan (typical case — purely incremental implementation), this gate does not fire (for general software development this includes debug-log-instrumented scaffolds replaced by clean production versions, mock-data fixtures replaced by real-data fetches; for skill development this includes verbose-tracing skill versions replaced by streamlined final versions). The gate exists to prevent the probe artifact from being silently overwritten before the user has had a chance to inspect it — a failure mode the No-Stall Principle's autonomy guarantee otherwise creates.AskUserQuestion option design (applies to the probe gate above and any future user-state-query call in this workflow): when the workflow uses
AskUserQuestion(or any equivalent multi-option user-query tool) to query the user about a plan-derived state — probe-execution outcome, manual-verification result, environment-prerequisite check, or any equivalent state confirmation — the options list MUST include a meta-confusion branch alongside the result enumeration. Concretely, do not present only outcome categories (e.g.success / failure / skipped); also include an option phrased as "the procedure / expected outcome is not yet understood (please re-explain)" in the resolvedlanguage(e.g.language: ja:手順 / 期待結果がまだ把握できていない(要再説明);language: en:the procedure / expected outcome is not yet clear (please re-explain)). The meta-confusion branch absorbs the "I cannot answer the question as posed" state — without it, the user is forced intoOtherfree-text and the workflow consumes an extra clarification turn re-explaining what was already in the Plan. General principle: user-state queries enumerate outcomes AND leave a fallback for the premise-not-conveyed case, never outcomes alone (for general software development this includes deployment-readiness queries, migration-completion confirmations, external-system-state checks; for skill development this includes probe-result queries inside this Step 5 gate, callee-execution-outcome confirmations, manual-config-applied verifications). -
Derived-value claim deferral: when deliverable prose embeds a value derived from content that later phases can still change — a size claim about a generated artifact, an item or step count, or any other body-derived figure (for skill development this includes char-count claims about SKILL.md /
references/*.mdand step-count mentions in CHANGELOG entries or descriptive prose) — do not finalize that value during Step 5. Keep it as a clearly-marked provisional value (e.g. render the figure as<provisional — finalized at Step 10 entry>so the placeholder is grep-able at the application point) and compute + write the final figure exactly once at the last gate where the source content is settled — the plan-deferred bookkeeping application point at Step 10 entry (the deferred-bookkeeping paragraph at the top ofreferences/interactive-commits.md, applied before its § Collect changes step collects the working tree), after Step 6 Tidy, Step 7.5 fixes, Step 8 review fixes, and any Step 9hooks.on_completeworking-tree modifications have all landed. Re-verifying and re-correcting the figure after every downstream phase that touches the body is the anti-pattern this item forbids — each chase is an avoidable rework turn. Wheninteractive_commits: false(Step 10 is omitted and execution proceeds directly from Step 9 to Step 11 — see § Step 10: Interactive Commits), the Step 10 entry gate never occurs: finalize the figure at the same settledness point — immediately after Step 9 completes or is skipped, before proceeding to Step 11 — so the provisional marker never survives into the final tree. -
Implementation diff snapshot: at the conclusion of Step 5 (after all planned edits are applied and the derived-value deferral sub-step above completes), run
git diff <base-commit> --name-onlyand store the result asimplementation_diff_paths— the set of tracked paths changed by this task's implementation, recorded before any post-implementation review hook or automated fix tool runs. This snapshot is consumed by § Step 10's "Post-hook attribution check" paragraph to identify on-disk changes introduced during the review-hook phase (Steps 6–9) that no review hook claimed responsibility for.
Step 6: Tidy
Implementation often introduces unnecessary complexity that's easier to spot in a dedicated pass after the code works.
Difficulty exception (difficulty-skip matrix). When Step 2 marked Step 6: Tidy completed under the difficulty-skip matrix (Trivial or Simple tier — see Step 2's Adjust N by difficulty), the row is already completed: do not re-mark it in_progress; proceed directly to Step 7. The Phase-boundary self-audit (§ Step 1 registration mechanics) treats this pre-completed row as the intended skip exactly as it does the Trivial Step 3 / Step 8 skips, not an unrun-step bug.
The Step 6 cleanup callee is resolved per the Cleanup skill bullet in § Prerequisites (built-in simplify preferred, bundled tidy as fallback). The phase is named "Tidy" after that in-house fallback skill; when simplify is available it — not tidy — is the primary callee.
Cross-layer review handoff ledger. Step 6 (cleanup), Step 7.5 (rules-review), Step 8 (code review), and any review-class hooks.on_complete entries (an entry is review-class when it is a Skill(<name>) entry whose skill reviews or inspects the change and reports findings — judge semantically from the skill's name and purpose; plain shell-command entries are never review-class and receive no ledger) run sequentially against the same deliverable but share no state by default — without a handoff, the same structural concern is re-raised and re-judged independently by each layer, and a finding one layer deferred or applied only partially resurfaces later as scattered per-site fixes. From this step onward, keep a lightweight in-memory ledger of each review layer's dispositions: findings deferred (with the reason), findings applied (with the sites covered), and known leftover sites or residual concerns. Include the ledger as a short context item in each subsequent review layer's dispatch payload (the rules-review dispatch, whether Step 7's background launch or its Step 7.5 sequential fallback; the Step 8 review payload, where it complements that payload's same-layer continuation item; and review-class hooks.on_complete callees). When the ledger has no recorded dispositions yet (no prior layer deferred, applied, or left anything over), omit the ledger item from that payload entirely — do not render an empty placeholder. When a later layer re-surfaces a concern the ledger records as deferred or partially applied, resolve it once: sweep all remaining sibling sites in one pass when they are enumerable and within this task's scope; otherwise (sites outside this task's scope, or a sweep too large for this run) record the leftover explicitly in the plan's Risks — do not let each layer independently re-apply the same structural fix to a different subset of sites.
- Pre-dispatch rename-sweep self-audit: if the Implement diff (since
<base-commit>recorded in Step 2) includes a term-rename operation — a search-and-replace across the project that swapped a step name, callee name, config key, identifier, or domain concept for a new one — sweep the changed-path SKILL.md /references/*.md/ README prose for synonyms and derived forms of the rename target before dispatching the Step 6 cleanup skill (the resolvedsimplifyortidy), and fix any residue inline. General principle: mechanical search-and-replace leaves synonym / derived-form residue that the substitution alone cannot catch — gerund forms when a verb is renamed, nominalizations and related-noun forms when an action is renamed, conceptual paraphrases of the original term in surrounding description text when a step or concept is renamed (for skill development this includes renaming a procedural verb leaving its-ingform in description prose, renaming a step leaving the prior step-concept paraphrase in cross-section reference text, or renaming a callee leaving the old concept noun in doc-comment / SKILL.md narrative). Detect at this Step 6 so the Completion-time integrity check (Step 8 reviewer /hooks.on_complete) remains a backstop rather than the primary detection point. Non-rename diffs skip this audit. - Dispatch the cleanup skill (resolved per § Prerequisites' Cleanup skill bullet): review changed code for reuse, quality, and efficiency, then apply cleanup edits.
- Primary —
Skill(simplify): invokeSkill(simplify). Its argument interface is unverified (built-in skill, no on-disk SKILL.md), so do not assume anytidy-specific field — pass no scope argument (Base ref/--base-commit;simplifyauto-scopes to the changed working-tree code), and whencustom_instructionsis set, pass it only as a short best-effort natural-language hint (simplifymay ignore it; do not name aCustom instructionsfield it may not expose). Omit it entirely whencustom_instructionsis unset or empty (per § Step 2's Sub-skill natural-language argument minimalism note). - Fallback —
Skill(tidy): Do not passBase ref/--base-commit <sha>— tidy's default working-tree mode is the intended scope here (covers tracked + staged + untracked changes per tidy's§ Invocation contract); passingBase refwould switch tidy to committed-history mode and silently drop untracked files from the cleanup scope, even though sibling Steps (Step 7'stest_commands, Step 7.5'sSkill(rules-review)) invoke their callees with--base-commit <sha>. ThisBase refasymmetry rationale is scoped to thetidypath only — thesimplifypath above passes no scope argument regardless. Pass the workflow'scustom_instructionsconfig value through tidy's natural-languageCustom instructionsfield (omit the field entirely whencustom_instructionsis unset or empty — do not render(none)/ empty string / fabricated default). General principles: (i) when a caller-skill dispatch field is driven by an optional config key, state the absent-key behavior inline on the dispatch line rather than relying on cross-reference to the config-parse step; (ii) when a caller depends on a callee's default-mode behavior for scope correctness and sibling steps use a different argument convention, name the asymmetry on the dispatch line as load-bearing rather than implicit — the executor cannot rely on a default-by-omission when sibling steps create an extrapolation pull toward the explicit form.subagent_modelpropagation: passModel: <subagent_model>when the Step 2-resolvedsubagent_modelis a model id (omit wheninherit), whichtidyapplies to its per-iteration reviewerAgentdispatch (seetidy's § Invocation contractModelfield). The built-insimplifyprimary path takes no model — built-in skills expose no argument contract — so the propagation is effective only on thistidyfallback path; the simplify→tidy resolution itself (§ Prerequisites' Cleanup skill bullet, the single source of truth) is unchanged.
- Primary —
- Regardless of the outcome — whether the cleanup skill (
simplify, or thetidyfallback) applied fixes, reported no actionable findings, or returned any other non-error result — markStep 6: Tidyascompletedand proceed to Step 7 automatically. Per the No-Stall Principle, do not wait for user input. - If the cleanup skill result is not observable (e.g. context compaction occurred during or immediately after the call): inspect
git diff <base-commit>. If the diff contains changes clearly attributable to a cleanup pass, treat Step 6 as completed and proceed to Step 7. Otherwise (no cleanup-attributed changes visible, or ambiguous), re-execute the Step 6 cleanup skill once (the resolvedsimplify, ortidyifsimplifyis unavailable) — inspection-and-fix-class skills are idempotent — then proceed to Step 7.
Step 7: Check / Test (max 3 retries)
- Run
check_commandsin order (always run all)- On failure, fix and retry (do not proceed to test execution)
- Pre-execution scope-narrowing: before running each check command, assess whether it is a repo-wide auto-fix tool — a command that writes to files across the repository regardless of which files are in the task scope (e.g. a project-wide formatter, linter with
--fix/--write, or bulk document transformer). If the command is a repo-wide auto-fix tool and the working tree contains files changed outside the task-scope snapshot (unrelated existing changes), narrow the command's scope to the task-scope snapshot files before running (e.g. pass the snapshot file list as explicit path arguments if the tool supports it). If scope narrowing is not feasible given the tool's interface, stop and ask the user for direction before running the command — options: run the command accepting the full-width effect, skip the command, or provide an alternative scoped invocation. The Scope-drift guard below is the second safety net for cases where pre-execution assessment is not feasible. - Scope-drift guard: before each command, record
git diff --name-only <base-commit>as the task-scope snapshot (the file set scoped to this task at the start of Step 7). After the command, re-check — any file newly appearing outside that snapshot was written by the command (auto-fix/write behavior sweeping unrelated drift). If scope drift is detected, classify the out-of-scope changes before acting: if all of the following hold — (i) the out-of-scope diff is whitespace or comment changes only (no code-skeleton changes: no non-blank, non-comment lines added or removed), (ii) the total changed line count across all out-of-scope files is ≤ 5, and (iii) the changes are attributable to the formatter or linter that just ran (the command is a known formatter/linter, e.g.lint:fix,format,prettier,black) — then proceed automatically without a user-direction stop: emit a one-line note (e.g.Scope-drift note: <file>(s) received whitespace-only formatting from <command> — proceeding) and continue to the next command. Otherwise (non-trivial drift): warn the user (list both the in-scope files and the newly-appeared out-of-scope files), do not auto-revert /git checkout/ delete the out-of-scope changes (leave the working tree as the command left it for user inspection), leaveStep 7: Check / Testasin_progress, and wait for user direction. This is a step-internal stop directive — one of two allowed non-completing exits from the check_commands phase (the other being the pre-execution scope-narrowing infeasibility stop above) — and is consistent with the No-Stall Principle, which permits explicit step-defined stops
Two read-only analyses can be launched concurrently here: the Step 7.5 Skill(rules-review) (below) and the Step 8 code review (see the Concurrent code review launch paragraph that follows). Both only return findings — the main thread applies any fixes later (rules-review fixes in Step 7.5, reviewer fixes in Step 8) — so overlapping their analysis with the test phase is a pure wall-clock optimization. test_commands is never backgrounded: a backgrounded callee must have an inline fallback for the nested-Agent-unavailable case, which rules-review (its SKILL.md § 5) and the default reviewer ask-peer (its SKILL.md § Process 1) both have, but run-tests does not. This extends to long-running test entries: do not attempt to offload a Skill(<name>) test command to a one-off background subagent to avoid context accumulation — a subagent that receives a minutes-long command will typically background it internally and return an empty verdict; the main-thread synchronous Skill() invocation is the reliable dispatch path regardless of test duration.
Concurrent rules-review launch (per pass). After check_commands pass and before running test_commands, optionally launch the Step 7.5 Skill(rules-review) concurrently so its read-only analysis overlaps the test phase. A pass here is a Step 7 entry that a Step 7.5 sub-step 1 collect will follow: the initial Step 7 entry, and each full Step 7 → Step 7.5 re-entry triggered by Step 8's post-fix re-run (the "Always re-run Step 7 and Step 7.5" bullet). The Step 7-only re-run inside Step 7.5's fix flow is not a pass: the rules-review call that follows it is the fix flow's direct 2nd-cycle invocation, which has no collect branch — a launch there would be an orphan dispatch with no collector (overlapping that path stays out of scope). This paragraph's pass definition is the single definition the bullets below, the Concurrent code review launch paragraph, the Step 7.5 collect, the Step 8 sub-step 1 collect, and Step 8's "Always re-run Step 7 and Step 7.5" bullet refer to.
- Initialize tracking (at every Step 7 entry — pass or not — unconditionally before the availability branch, so the unavailable / skip / re-run paths never read an uninitialized variable):
rules_review_launched = falseandrules_review_stale = false. Re-initializing on a non-pass entry (the Step 7-only re-run inside Step 7.5's fix flow) is harmless: that entry occurs only after the current pass's Step 7.5 sub-step 1 collect has already consumed the result. Lifecycle: this bullet is the only init site; the only set sites are the If available bullet (rules_review_launched) and the discard bullet below (rules_review_stale); the skip / unavailable paths set neither; Step 7.5 sub-step 1 is the only read site. - Availability detection: inspect the current tool list the same way
rules-reviewSKILL.md § 5 detects Agent availability — do not make a speculative call. The capability gated here is specifically background dispatch (Agentwithrun_in_background), not a bare foregroundAgent. Positive criterion: background dispatch is available when theAgenttool is exposed (top-level or viaToolSearch) AND the session offers anAgentrun_in_backgroundparameter or equivalent async-dispatch mechanism — the common case in a standard interactive session, so default to parallel. Treat it as unavailable only when one of these two signals holds (closed list — if neither holds, choose parallel): (a)Agentis absent (this also covers this skill running inside a non-recursing subagent, surfacing as nestedAgentbeing unavailable); (b)Agentis exposed but the session offers no background/detached dispatch capability (e.g. an older Claude Code). This two-item list is the single definition of "unavailable" the If unavailable branches below refer to. Do not treat "unsure" as "unavailable": if a background-dispatch capability is present, choose parallel. - If available (and this Step 7 entry is a pass per the definition above — note that on a Trivial task Step 2 pre-completes Step 7.5 under the difficulty-skip matrix, so no Step 7.5 sub-step 1 collect follows and the entry is not a pass; skip the launch, same orphan-avoidance as the code-review launch's N_code=0 handling): dispatch a background subagent (
Agentwithrun_in_background: true,subagent_type: general-purpose, plusmodel: <subagent_model>when the Step 2-resolvedsubagent_modelis a model id — omitmodelwhen it isinherit) instructed to runSkill(rules-review) --base-commit <sha>— including the cross-layer review handoff ledger as a short context item (per § Step 6's Cross-layer review handoff ledger paragraph; omit when the ledger has no recorded dispositions) — and return the findings report verbatim, applying no edits (the main thread applies fixes in Step 7.5). On a successful dispatch setrules_review_launched = true. Emit a Progress Visibility status line in the same turn. Include in the dispatch payload a note that nestedAgentis unavailable in this subagent context — executeSkill(rules-review)directly without probing for sub-subagent availability (the § 5 inline fallback applies automatically; no runtime discovery is needed). Collect the report from the background Agent's completion notification (no extra tool needed). - If unavailable (per the Availability detection criterion above): skip the launch (
rules_review_launchedstaysfalse) — Step 7.5 invokesSkill(rules-review)sequentially as before (fully backward-compatible). - If
test_commandsthen fail and you fix them (the diff changes): discard both background results — the rules-review result (setrules_review_stale = true; Step 7.5 sub-step 1 then falls back to a fresh sequentialSkill(rules-review)dispatch) and the code-review result (setcode_review_stale = true; see the next paragraph) — since the prior analyses are now stale. No-op on the no-launch path: settingrules_review_stale = truewhenrules_review_launched == falsehas no effect — Step 7.5 sub-step 1's collect branch is gated onrules_review_launched == true, so the unconditional set is safe on every path. Handle disposition: a stale (or never-collected) background rules-review result is simply ignored at the Step 7.5 collect point — no explicit cancellation of the background subagent is owed.
Concurrent code review launch (per pass). In the same window — after check_commands pass and before running test_commands — optionally launch the Step 8 reviewer (the reviewer skill resolved in Step 1, e.g. Skill(ask-peer)) as a background subagent so its read-only analysis also overlaps the test phase. This is a sibling of the rules-review launch above and shares its mechanics — availability detection, dispatch shape, staleness vocabulary, and the pass definition (the rules-review paragraph above is the single home of that definition).
- Initialize tracking (at every Step 7 entry — pass or not — unconditionally before the availability branch, so the unavailable / skip / re-run paths never read an uninitialized variable):
code_review_launched = falseandcode_review_stale = false. Re-initializing on a non-pass entry (the Step 7-only re-run inside Step 7.5's fix flow) is harmless: it rewinds thecode_review_stale = truethat Step 7.5 sub-step 3.a just set, butcode_review_launchedis also reset tofalse, and the Step 8 collect branch requirescode_review_launched == true— both states route Step 8 sub-step 1 to a fresh sequential dispatch, so the routing is equivalent. Lifecycle: this bullet is the only init site; the only set sites are the If available bullet (code_review_launched) and the staleness set-sites named in the Staleness bullet below (code_review_stale); the skip / unavailable paths set neither; Step 8 sub-step 1 is the only read site. Because every continuation path to a next Step 8 iteration item passes through a Step 7 re-entry (and therefore through this re-initialization), each pass's launch is collected at most once (the Step 8 sub-step 1 collect bullet names which iteration collects). - Availability detection: use the rules-review launch's detection above verbatim — its positive criterion (default to parallel in the common interactive case), its two-item closed list defining "unavailable", and its "do not treat 'unsure' as 'unavailable'" directive all apply here unchanged. The gated capability is background dispatch (
Agentwithrun_in_background), not a bare foregroundAgent. - If available (and this Step 7 entry is a pass per the shared definition): launch only when a pending Step 8 iteration item remains to collect the result after this pass — on the initial pass this means N_code ≥ 1 (iteration 1 collects; when N_code = 0 / Trivial, Step 8 is skipped entirely and no iteration item exists); on a re-run pass it holds only when the fix-applying iteration k satisfies k < N_code (a re-run triggered from the final iteration k = N_code leaves no pending iteration item, so a launch there would be an orphan dispatch with no collector — skip it; same orphan-avoidance vocabulary as the rules-review paragraph's non-pass rationale). Dispatch a background subagent (
Agentwithrun_in_background: true,subagent_type: general-purpose, plusmodel: <subagent_model>when the Step 2-resolvedsubagent_modelis a model id — omitmodelwhen it isinherit) instructed to runSkill(<reviewer>)with the same payload Step 8 sub-step 1 would compose for the next pending iteration item — sub-step 1's review-payload definition (including its rubric-link resolution note and, on a re-run pass, the continuation item and the iteration-scope instruction) is the single parametric source; do not restate its list here. Omitting the continuation item on a re-run pass would hand the reviewer a context-free diff and re-surface already-rejected findings. The reviewer returns its report verbatim, applying no edits. On a successful dispatch setcode_review_launched = true. Emit a Progress Visibility status line in the same turn. Include in the dispatch payload a note that nestedAgentis unavailable in this subagent context — executeSkill(<reviewer>)directly without probing for sub-subagent availability (the reviewer's inline fallback applies automatically; no runtime discovery is needed). The result is collected at Step 8 sub-step 1, not here. The Step 7-only re-run inside Step 7.5's fix flow is not a pass and does not re-fire this launch; the rules-review paragraph's orphan rationale does not transfer here (the code-review collect point is Step 8, where a collector exists even for that path) — overlapping that path simply stays out of scope. - If unavailable (per the Availability detection criterion above): skip the launch (
code_review_launchedstaysfalse) — Step 8 dispatches the reviewer sequentially as before (fully backward-compatible). - Staleness — discard owned by Step 8 sub-step 1: this background result is speculative. The discard decision lives at Step 8 sub-step 1 (it reads
code_review_stale); this paragraph only names the set sites.code_review_staleis settruewhenever an edit lands between this pass's launch and the Step 8 collect point that changes the diff the reviewer analyzed: (i) atest_commandsfailure fix during Step 7 (the discard bullet above), or (ii) any fix Step 7.5 applies (see Step 7.5). Both set-site descriptions are pass-independent and apply to every pass unchanged. The condition is broader than the rules-review launch's (whose collect point is Step 7.5, before Step 7.5's own fixes land); the code-review launch's collect point is Step 8, after Step 7.5's fixes land, so Step 7.5 fixes also count. No-op on the no-launch path: whencode_review_launched == false(the launch was skipped or unavailable), settingcode_review_stalehas no effect — Step 8 sub-step 1's collect branch is already gated oncode_review_launched == true, so the no-launch path dispatches the reviewer fresh regardless of the flag's value; the unconditionalcode_review_stale = trueset-sites are therefore safe to execute on every path. Handle disposition: a stale (or never-collected) background result is simply ignored at the Step 8 collect point — no explicit cancellation of the background subagent is owed.
After launching (or skipping) both, run test_commands in the main thread per sub-step 2 below; the background rules-review and (when launched) the code review proceed concurrently.
- Iterate over
test_commandsin order. For each entry (which must be of the formSkill(<name>)), invoke that skill with--base-commit <sha>(from Step 2) via$ARGUMENTS. Each invocation must return a structured summary with one of three statuses (SUCCESS / TEST_FAILED / EXECUTION_ERROR); a TEST_FAILED or EXECUTION_ERROR from any entry halts the loop immediately and triggers the retry path in sub-step 3 — subsequent entries do not run on the failing pass.- Each test skill handles scope decision and test execution internally via subagent (when applicable)
- Returns structured summary: SUCCESS / TEST_FAILED / EXECUTION_ERROR
- Environment sanity check: before running tests, confirm the actual resolved toolchain versions match the project's expected versions — print the effective runtime and dependency-manager versions to surface version-manager-not-activated cases where the shell resolves an unintended runtime version and the build tool raises errors on version-incompatible code. Also confirm that compiled or bundled artifacts are rebuilt before tests that consume them — stale artifacts from a prior build produce test results that do not reflect current source state (for general software development this includes client-side JavaScript bundles that must be rebuilt after source changes before browser or SSR tests run; for skill development this includes re-running any code-generation step that produces an artifact a verification step reads, rather than testing against a cached artifact from a previous run that predates the current change).
- Bulk-vs-split execution: when the change is cross-cutting (shared components, mirrored services, or parallel handlers) and the test suite includes long-duration categories (E2E, integration tests with external dependencies), prefer passing scoped or split arguments rather than requesting a single bulk run. A single command bundling long-running jobs makes intermediate progress opaque and failure recovery harder — scope-targeted execution lets each category succeed or fail independently.
- Shared-path re-run scope: when a fix touches a shared path — a utility, helper, or function invoked by multiple distinct test suites (for skill development this includes subagent dispatch shared forms, hook wiring, state-file processing, or any cross-suite path) — include all suites that exercise that path in the re-run scope, not just a representative suite. A green representative suite proves only the paths it exercises; when the changed code is on a shared path, every suite that routes through it is a potential regression surface. When running all affected suites is impractical, record the excluded suites explicitly in the Completion summary as uncovered risk rather than treating the representative re-run as sufficient verification.
- Cheap-diagnostic first pass: when a test or check command first fails, read the raw error output as a diagnostic pass before taking any edit action — identify the failure class (missing symbol, type error, assertion, configuration issue) and locate the error source (file, line, test case) from the output alone. This pass consumes no retry budget and modifies no files; its purpose is to avoid misdirected first-fix attempts that burn a retry slot without addressing the root cause. Apply an edit only after the diagnostic confirms the error source and failure class: when the cause is immediately apparent from the error text (typo, missing bracket, misnamed identifier), apply the fix and enter the retry loop; when the failure class is ambiguous or the error points to unfamiliar code paths, read the relevant source files before editing.
- Pre-existing vs regression discrimination: before entering the retry path on
TEST_FAILED/EXECUTION_ERROR, discriminate each reported failure as regression (introduced by this run's changes) or pre-existing (already failing at<base-commit>from Step 2). Two paths: (i) if the invoked test skill's structured summary already classifies failures aspre-existing/regression(recommended return-contract extension for any verification-class skill — lint, test runners, structural checkers, marketplace validators), trust that classification. (ii) Otherwise, re-run the same test skill against<base-commit>: stash the working changes (git stash --include-untracked), check out<base-commit>into a scratch worktree (git worktree add ../base-commit-check <base-commit>) or rely on the test skill's own--base-commitargument if it supports re-evaluating at that ref without working-tree manipulation; compare the failures. Failures reproducing at<base-commit>are pre-existing — record as an informational warning in the summary (pre-existing failure: <skill> / <case>— out-of-scope for this PR) and do not count toward the 3-retry budget and do not auto-fix. Only failures that do not reproduce at<base-commit>are regressions — proceed with the existing retry / fix path. General principle: regression-vs-pre-existing discrimination via base-commit comparison applies to any verification step running a checker against a working tree (lint, test, structural validator — for skill development this includes marketplace structure validation and plugin integrity checks where docs and implementation can disconnect independently of the current change). - Self-contamination discrimination: when tests pass on one Step 7 entry but fail on a subsequent re-entry after the workflow itself applied changes (a Step 6 tidy fix, a Step 7.5 rules-review fix, or a Step 8 code-review fix landed between the two entries), check whether the workflow's own applied changes — not the original implementation — caused the new failure. Before applying another fix, inspect the diff between the last passing Step 7 entry and the current state and verify whether the test-failing path was modified by a workflow fix. When the workflow-applied change is the regression source, revert or correct that specific workflow fix rather than adding a new edit to the user's implementation code — treating a workflow-self-contaminated failure as an implementation regression burns retry budget on the wrong target and may cascade into additional incorrect fixes (for skill development this includes a Step 7.5 rules-review edit that inadvertently rewrote a tested behavior, or a Step 6 tidy pass that removed an expression the test suite asserts on).
- EXECUTION_ERROR + pre-declared degraded procedure: when a test invocation returns
EXECUTION_ERRORAND the approved Plan explicitly pre-declared a degraded procedure for this failure mode (e.g. a Risks entry naming the environmental constraint and a fallback verification path), apply the degraded procedure automatically — execute the fallback, emit a one-line note in the resolvedlanguage(e.g.Step 7: EXECUTION_ERROR — applying pre-declared degraded procedure: <procedure-summary>), and continue without consuming a retry. Pre-declared degraded procedures are user-approved accommodations for predictable environmental constraints; routing them through the retry-and-stop path contradicts the plan's prior approval and violates § No-Stall Principle. When no degraded procedure is pre-declared, treatEXECUTION_ERRORas before (trigger the existing retry / fix path). - Mock/replay-only coverage self-check: when a test invocation returns
SUCCESS, check whether the passing tests exercise actual I/O against the external boundary — real network calls, real serialization into the target system's format, real file writes reaching an external service — or only replay pre-recorded responses (cassette fixtures, mock stubs, HTTP interceptors, seeded response files; for general software development this includes external-API integration tests that replay recorded HTTP interactions, message-bus consumers that replay fixture events, file-transfer tests that stub the remote endpoint). If external boundary behavior is covered exclusively by replay-only tests, do not treat the pass as integration-verified for that boundary. Record such gaps explicitly in the Completion summary asreplay-only coverage: <boundary description> — not integration-verifiedand do not declare the highest-risk behaviors for that boundary resolved on the basis of a replay pass alone. - Downstream-artifact invalidation self-check: when tests pass, ask whether the change invalidates downstream artifacts that were not directly edited — snapshots, golden images, generated code, lock files, schema artifacts, or other outputs derived from the changed sources. Scope-based test selectors key on directly-changed paths and are structurally silent about derived artifacts; a pass from such selectors does not confirm downstream artifacts remain consistent. Verify each potentially-invalidated downstream artifact class explicitly rather than treating a selector-pass as sufficient (for general software development this includes UI changes invalidating visual-regression baselines, schema changes invalidating generated client code or snapshot fixtures, dependency changes invalidating lock files; for skill development this includes structural changes to
references/*.mdinvalidating cited examples or templates in the same SKILL.md or bundle sibling skill files). Record any unverified downstream artifact classes in the Completion summary as uncovered risk. - Red-before / Green-after verification: when tests pass after applying a fix, verify the same test would have failed without the fix — a regression test that stays green both with and without the fix is a strong signal the bug was not reproduced and the wrong code path is being exercised. Run the relevant test without the fix applied (re-run against
<base-commit>from Step 2's initial-state capture, using the same worktree approach as the Pre-existing vs regression discrimination bullet above) and confirm the test now fails; a persistent green result means the test does not exercise the fixed code path. For behaviors sensitive to entry method (state-restoration, client-side routing, lazy initialization, or any mechanism that behaves differently based on how a boundary is crossed), confirm the test traverses the same code path the user traverses rather than a setup shortcut that bypasses the real entry point — seeding state directly, loading a page via a full-page reload rather than in-app navigation, or calling a handler without the dispatch chain the user triggers are common shortcut traps that skip the exact code a fix touches (for general software development this includes integration tests where fixtures pre-populate state the real user action builds incrementally; for skill development this includes smoke tests that call an internal helper directly rather than driving the fullSkill()dispatch path). - Environmental verification fidelity: before treating an automated
SUCCESSas definitive evidence, confirm the test automation's execution path reproduces the actual environmental conditions the behavior depends on — platform-specific input filters, OS-level accessibility layers, system event dispatch paths, and similar runtime factors. Automation that injects synthetic events or runs headless may bypass these layers and reach a green state through a path the user never traverses; the PASS result is then structurally unable to rule out the user-visible failure. When a discrepancy exists between an automated PASS and real-world user observation, treat the real-world observation as ground truth — the automation's coverage gap is the explanatory factor. Record such gaps in the Completion summary asautomated-pass / real-world-fail: <boundary description>(e.g.automated-pass / real-world-fail: OS gesture recognizer bypassed by synthetic pointer injection) so they remain visible for a follow-up fix (for general software development this includes UI automation that dispatches synthetic pointer events bypassing OS-level gesture recognizers, headless browser tests that skip platform accessibility pipelines, and mobile test harnesses that inject touch events below the OS input filter layer; for skill development this includes smoke tests that invoke a tool helper directly via an internal call rather than the fullSkill()dispatch chain, bypassing hook wiring, allowed-tools enforcement, and subagent context injection that the real invocation path exercises).
- After 3 retries, report to user and stop
Coverage note (TypeScript multi-tsconfig): For projects with Project References or multiple
tsconfig*.jsonfiles, a singletsc --noEmitmay miss changed files that belong to other tsconfigs.--initauto-registers a per-tsconfigtsc -p <path> --noEmitin this case (seereferences/init-mode.mdfor detection rules). If coverage still looks incomplete, re-run--initor append the missing command manually.
GATE: Verify Steps 2-7 are completed (check task status via
TaskList; if status is inconsistent, verify actual completion by reviewing work done). Mark Step 7.5 asin_progressunless Step 2 pre-completed it under the difficulty-skip matrix (Trivial tier) — in that case the row is alreadycompleted; do not re-mark itin_progress, skip straight to Step 8 (same already-completed-row handling as the Step 8 GATE's N_code=0 case). (If Step 7 launched a background rules-review, it may still be in flight — Step 7 is "complete" once the test phase passes; Step 7.5 sub-step 1 collects the rules-review result.)
Step 7.5: Rules Compliance Review
Dedicated rules compliance check, separate from code review (Step 8). This ensures rule enforcement gets focused attention rather than competing with correctness and design concerns.
Difficulty exception (difficulty-skip matrix). When Step 2 marked Step 7.5: Rules Compliance Review completed under the difficulty-skip matrix (Trivial tier only — Simple skips only Step 6, not Step 7.5; see Step 2's Adjust N by difficulty), the row is already completed: do not re-mark it in_progress; proceed directly to Step 8. The Phase-boundary self-audit (§ Step 1 registration mechanics) treats this pre-completed row as the intended skip exactly as it does the Trivial Step 3 / Step 8 skips, not an unrun-step bug.
Responsibility scope (so the same rule class is not double-reviewed across passes and no class slips through every pass):
- Step 7.5 owns the mechanical walk of every matched
.claude/rules/rule against the diff — hard rules (explicit prohibitions, naming, reference form, import paths, placement, file structure) are evaluated strictly; intent-style rules (judgment-based principles, prose conventions) are evaluated best-effort with low-confidence markers perrules-reviewSKILL.md. - Step 6 Tidy covers reuse, prose quality, dead code, and redundancy; rule compliance is not its primary responsibility — if the Step 6 cleanup skill (
Skill(simplify)or theSkill(tidy)fallback) surfaces rule findings as a side effect, treat them as bonus and do not extend its reviewer prompt to take on.claude/rules/walks. - Step 8 Code Review covers correctness, edge cases, conventions / consistency lightly (a safety-net pass for files modified after Step 7.5), and simplicity / maintainability — the thorough rules check stays at Step 7.5.
- Step 11 Update Rules owns the rule-doc-drift class: findings where the code under review is internally consistent with itself (and with the broader file's existing pattern across 3+ call sites per
rules-reviewSKILL.md's drift detection criteria) but the rule document describes different behavior — i.e. the rule text has gone stale relative to the code. Step 7.5 surfaces this class via the reviewer'sClassification: rule-doc-driftfinding and does not apply a code fix; the disposition is to route the rule-text update to Step 11 (Skill(extract-rules)) rather than rewriting the code to match a stale rule. Whenrules-reviewreturns a finding taggedClassification: rule-doc-drift, treat it as out-of-scope for Step 7.5's fix loop (noSkill(rules-review)re-run is required to clear it, since the code is the source of truth), record the routing intent so Step 11 picks it up, and continue.
When a rule violation is reported in both passes (Step 7.5 and Step 8), treat Step 7.5 as authoritative and skip the duplicate fix attempt in Step 8 to avoid double-counting in the iteration budget.
- Obtain the rules-review report — collect the Step 7 background launch, or invoke directly. If Step 7's "Concurrent rules-review launch" dispatched a background rules-review this pass and it is still fresh (
rules_review_launched == trueandrules_review_stale == false), collect that background result now (it ran concurrently with the test phase). If the background subagent has not yet reported when you reach this point (the test phase finished first), wait for its completion notification before judging the report — this wait is a non-stalling return boundary (harness-tracked background work), not a user gate, and a not-yet-arrived notification must never be read as "no findings". If the collected background result is itself an error completion — the subagent died or returned something unusable as a rules-review findings report — treat it the same as not-launched and fall back to the fresh sequential dispatch below; this route only redirects (it does not mutate the launch/stale flags, so the lifecycle closed list is unchanged). Otherwise —rules_review_launched == false(background dispatch was unavailable, or the dispatch attempt did not succeed) orrules_review_stale == true(the background result was discarded after a test failure) — invokeSkill(rules-review)with--base-commit <sha>(base-commit recorded in Step 2) — andModel: <subagent_model>whensubagent_modelis a model id (omit wheninherit), whichrules-reviewapplies to its internal per-categoryAgentdispatch — via$ARGUMENTS, including the cross-layer review handoff ledger as a short context item in the dispatch (per § Step 6's Cross-layer review handoff ledger paragraph; omit when the ledger has no recorded dispositions). Either way the report comes from the externalrules-reviewskill: do not substitute an inline rules-walk based on perceived scope, change size, or any other self-judgment of the diff's complexity — small / "obvious" / single-file changes still go through the external skill. The skip-to-fallback path is documented in Prerequisites and fires only on objective skill unavailability (theSkill(rules-review)call itself fails after one retry), never on subjective judgment that an inline equivalent would suffice. The external skill enforces consistent coverage across runs; inline substitution silently degrades that coverage and the user has no visible signal that it happened. - Judge the result semantically: if the skill reports that there is nothing to act on — no actionable violations, no changed files, no applicable rules, no rule files found, or any other "nothing to report" outcome regardless of exact wording — mark
Step 7.5: Rules Compliance Reviewascompletedand proceed to Step 8 automatically. Per the No-Stall Principle, do not wait for user input and do not rely on exact-phrase matching; trust semantic judgment since the skill's phrasing may evolve across versions. - If violations found:
a. Fix all reported violations. Applying these fixes changes the diff that the Step 8 code-review background launch (if any) analyzed, so set
code_review_stale = true— Step 8 sub-step 1 then discards the now-stale background result and dispatches the reviewer fresh against the post-fix diff. b. Re-run Step 7 (Check / Test) to ensure fixes did not break anything (this sequential re-run does not re-fire Step 7's concurrent rules-review or code-review launches) c. Re-runSkill(rules-review)with--base-commit <sha>for verification (2nd cycle). Apply the same semantic judgment as step 2: if the re-run reports nothing actionable, markStep 7.5: Rules Compliance Reviewascompletedand proceed to Step 8 automatically (per the No-Stall Principle). When a 2nd-cycle verdict differs from the 1st on a specific location (a previously-flagged item now passes, or a previously-clean location is now flagged), record the reason inline in the Step 7.5 user-facing summary presented to the user (1–2 lines per drifted location: which location, 1st-cycle verdict, 2nd-cycle verdict, why) before completing — judgment drift between cycles is acceptable but must be explained, otherwise repeat-cycle stability cannot be assessed. d. If violations still persist after the 2nd review cycle, present remaining violations to user for decision. Above the violations list, emit a summary preamble perreferences/plan-format.md§ User-gate summary preamble. Render the violations followingreferences/plan-format.md§ Localization granularity in the resolvedlanguage. Wait for user response before marking completed. (This is one of the explicit user-gates enumerated in the No-Stall Principle.)
Mark Step 7.5: Rules Compliance Review as completed only after all violations are resolved or user has decided on remaining violations.
GATE: Verify Steps 2-7.5 are completed (check task status via
TaskList; if status is inconsistent, verify actual completion by reviewing work done). Mark Step 8 asin_progressonly when N_code ≥ 1; if Step 2 set N_code=0 (Trivial), Step 8 is alreadycompleted— do not re-mark itin_progress, skip straight to Step 9. (If Step 7 launched a background code review, it may still be in flight — Step 8 sub-step 1 collects it.)
Step 8: Code Review
Code review catches bugs, convention violations, and design issues that tests alone miss — skipping it risks shipping preventable defects. Always run this step even when tests pass cleanly.
Difficulty exception (Trivial / N_code=0). When Step 2's difficulty assessment set N_code = 0 (a Trivial task — Trivial zeroes both N_plan and N_code), this entire step is skipped: its task rows (top-level Step 8: Code Review and every Step 8-x) were already marked completed by Step 2's Adjust N by difficulty. As with Step 3, this skip is gated on task difficulty; for any Simple / Moderate / Complex task (N_code ≥ 1) Step 8 always runs.
If N_code = 0 (Trivial), skip this step entirely — its rows are already completed, so do not re-mark them in_progress and proceed directly to Step 9 (Completion Hooks). The following in_progress marking and per-iteration processing apply only when N_code ≥ 1.
Mark Step 8: Code Review as in_progress. Process each pending iteration item (Step 8-1 through 8-N_code) in order:
-
Mark the iteration item as
in_progress. Obtain this iteration's reviewer report — collect the Step 7 background launch when it is fresh, otherwise dispatch the reviewer skill resolved in Step 1 (e.g.Skill(ask-peer)):- Collect the Step 7 background launch when fresh: if
code_review_launched == trueandcode_review_stale == false, the Step 7 "Concurrent code review launch" ran the reviewer in a background subagent concurrently with this pass's test phase — collect that result now as this iteration's reviewer report. Each pass's launch is collected at most once — by the first iteration item processed after that pass (iteration 1 on the initial pass; iteration k+1 on a re-run pass triggered from iteration k; derivation at the Initialize tracking bullet of Step 7's "Concurrent code review launch" paragraph). If the background subagent has not yet reported, wait for its completion notification before judging it, per the same non-stalling wait-boundary rule as Step 7.5 sub-step 1's background collect (a not-yet-arrived notification must never be read as "No actionable findings"). If the collected background result is itself an error completion, apply the same error-completion route as Step 7.5 sub-step 1's background collect — treat it as not-launched and dispatch fresh per the next bullet (the route only redirects; it does not mutate the launch/stale flags). - Otherwise — dispatch fresh: when
code_review_launched == false(background dispatch unavailable, the launch was skipped for this pass, or the dispatch attempt did not succeed), orcode_review_stale == true(the diff changed since this pass's launch so the background result is stale), or when redirected here by the collect bullet's error-completion route, call the reviewer skill (e.g.Skill(ask-peer)) to review the code changes now.subagent_modelpropagation (inline fresh-dispatch only): propagatesubagent_modelexactly as in Step 3 (Claude-family reviewers only). This applies only to this inline fresh-dispatch path — the Step 8 background-launch path already carriessubagent_modelvia the Step 7 launch'sAgentmodel, so the two paths never double-apply. Pre-dispatch dispatch-boundary reminder: Issue theSkill(<reviewer>)call in the same turn as any accompanying status prose — never produce a standalone status turn before theSkill()call, as that creates a stall point. Reading the reviewer's SKILL.md is preparation, not dispatch; theSkill()call is the dispatch. In both paths the collecting iteration is an ordinary iteration (it judges and applies findings per sub-steps 2–3 below); the collect path only substitutes the report's source. The reviewer report addresses the following — this list is the single parametric source for both paths (it is the fresh-dispatch request, and the same payload the Step 7 background launch bakes; the continuation item and the iteration-scope instruction below each apply per their own conditions): - Include
git diff <base-commit>(base-commit recorded in Step 2) to capture all changes since workflow start; before composing this payload, also rungit status --porcelain=v1 --untracked-files=allandReadthe contents of any untracked new files (lines with??prefix), then include those file contents in the review payload labeled as untracked new files — these are task-generated artifacts absent fromgit diff <base-commit>that would otherwise be invisible to the reviewer - Thorough rules compliance has been verified in Step 7.5, but instruct reviewer to also flag any obvious
.claude/rules/violations as a safety net — especially for code modified after Step 7.5 - Request feedback organized into three categories (labels only — the full per-category rubric lives in
references/review-categories.md§ Code review categories; instruct the reviewer to read that section, resolving the link to a concrete readable path when composing the request — the reviewer lacks the skill-directory context): a. Correctness & edge cases b. Conventions & consistency c. Simplicity & maintainability - If
custom_instructionsis configured, include the instructions text in the review request and have the reviewer verify compliance and report conflicts - If a state file is active (executing a subtask from a decomposition), include the current subtask's scope in the reviewer request: list the subtask's
titleanddescription, then list what the other subtasks cover (to define out-of-scope). Instruct the reviewer that missing functionality belonging to other subtasks is not an actionable finding for this code review — only findings scoped to the current subtask qualify. Omit this when no state file is active (single-task execution has no defined out-of-scope boundary). - Include the cross-layer review handoff ledger as a short context item (per § Step 6's Cross-layer review handoff ledger paragraph; omit when the ledger has no recorded dispositions); it complements the same-layer continuation item below.
- If a prior Step 8 iteration completed this run (a re-run pass): include the continuation item — the summary of fixes made and rejections with reasons from the completed iterations, including any class-level sweep record — so the reviewer builds on prior rounds rather than re-raising already-rejected findings (the latest
git diff <base-commit>is already the first item above). Omit this item on the initial pass (no prior iteration). - On a re-run pass, also include an iteration-scope instruction: the reviewer's primary verification scope is the changes applied since the prior iteration (identified via the continuation item's summary of fixes, located within the latest
git diff <base-commit>) plus landing confirmation of the prior iteration's findings — the full-coverage pass (re-verifying every target file in the fullgit diff <base-commit>from scratch) belongs to the initial pass only. The reviewer must still escalate back to full re-verification when content outside that primary scope raises a new concern, so coverage is reordered, not reduced. Omit this item on the initial pass (the initial pass is the full-coverage pass). - Reviewer should only report actionable findings. If none, explicitly state "No actionable findings"
- Collect the Step 7 background launch when fresh: if
-
Judge the reviewer's response semantically: if the reviewer reports nothing actionable — no actionable findings, no bugs / convention violations / design issues raised, or any other "nothing to report" outcome regardless of exact wording — mark this and remaining iteration items as
completed(skip). MarkStep 8: Code Reviewascompletedand proceed to Step 9 (Completion Hooks) automatically. Per the No-Stall Principle, do not wait for user input and do not rely on exact-phrase matching; trust semantic judgment since the reviewer skill's phrasing varies (especiallySkill(ask-peer)and other free-form-prose reviewers whose verdicts are natural-language Markdown rather than a fixed token). -
Otherwise: autonomously fix genuine issues or reject inapplicable points with reason — do not ask the user for judgment on individual review findings. Mark this iteration item as
completed.- Rejection self-question (severity-label override): before rejecting any finding solely because the reviewer labeled it Minor (or any other low-severity bucket), ask "if I rejected this and presented the resulting code to the user, would the user re-raise the same point themselves?" — judging by which areas the user has historically commented on (intent expression, reader-comprehension, placement consistency for test fixtures / helper functions / dependency locality, and other readability concerns where runtime correctness is unaffected but a reader's interpretation is). If the answer is yes or ambiguous, apply the fix instead of rejecting on the Minor label alone; reject on Minor only when you are confident the user would not surface the same point.
- Class-level extension audit (post-Critical/Major-fix): immediately after applying a fix for a Critical-severity finding, or a Major-severity finding whose fix addresses a structural pattern (external I/O boundary conditions, closed enum / form-set networks, shared helper / safety-rail callers, parallel route handlers — for skill development: subagent return-value schemas, shared handler fallback paths, mirrored form-set network audits), and before the modified-vs-rejected branches below, scan the rest of the diff for other instances of the same defect class — same operation, same broken assumption, same side-effect pattern (e.g. shared-resource-destroying API call sequences, direct processing of unverified input, race conditions). Reviewer feedback typically names one instance; the underlying class often spans the diff (cross-construct propagation, shared safety-rail callers, parallel route handlers, etc.). Apply the same fix direction to additional matches found here, then record the sweep outcome (e.g.
class-level sweep for <defect-class>: N additional instances found and fixedorno additional instances found) in the summary passed to the next iteration so the next reviewer does not re-trigger the same audit on already-swept ground, then continue to the modified-vs-rejected branch. - Prose-integrity self-check (post-fix): after applying a fix that edits prose adjacent to its target line (comments, docstrings, paragraph-level documentation — for skill development this includes SKILL.md and
references/*.mdcontent), re-read the surrounding paragraph as a single unit before continuing — verify no sentence is cut mid-word, no logical connective is broken (the connectiveshowever/therefore/because/but/ etc. still anchor real clauses), and the paragraph's overall logic still holds. Mechanical fix patches see only the line-level diff and routinely leave the surrounding prose semantically broken in ways the next iteration's reviewer flags as a Major finding, costing an extra iter. - Natural-language quality self-check (post-fix): when a fix adds new natural-language content that mechanical lint / test cannot verify (code comments, config-file annotations, error messages, UI copy, documentation fragments — for skill development this includes SKILL.md /
references/*.mdprose additions, frontmatterdescriptiontext, log messages), re-read each added fragment as a standalone unit in the resolvedlanguage. Judge it on four axes: concise (no padding or runaway sentences), phrasing natural for the target reader, vocabulary consistent with surrounding text, register and sentence structure not awkward. Revise any fragment that fails. This self-check is the only gate before natural-language content reaches the user-visible commit gate — Step 7 (check_commands/test_commands) and Step 7.5 (rules-review) cannot evaluate natural-language quality. - Comment-verbosity self-check (post-fix): scan all inline code comments visible in the diff — both newly-added (
+lines) and pre-existing comments in context lines — for over-explanation. Remove any comment that (a) describes what the code does when identifiers already express that (e.g.// increment counternext tocount++), (b) narrates obvious control flow, or (c) restates a variable or function name in prose. Retain only comments that explain why: a hidden constraint, a subtle invariant, a workaround for a specific external issue, or behavior a reader would not expect from the identifiers alone. A pre-existing verbose comment brought into the diff's context window is as legitimate a removal target as a newly-added one. This check is distinct from the Natural-language quality self-check above, which covers documentation prose — this check covers inline source code annotations specifically (for skill development: inline rationale phrases within code blocks inreferences/*.md, or comments insidebashfenced blocks in SKILL.md). - If code was modified: re-run Step 7 and Step 7.5 (with same base-commit from Step 2) — this full re-entry is a new pass (per Step 7's "Concurrent rules-review launch" pass definition): both the rules-review launch and the code-review launch re-fire (the code-review launch bakes its payload per sub-step 1's definition, continuation item and iteration-scope instruction included, and only when a pending iteration item remains — see Step 7's "Concurrent code review launch") — then continue to the next pending iteration item (back to step 1). Code fixes routinely introduce fresh bugs, tighten one place while loosening another, or miss a caller the author didn't know about — the next review round is how those leaks get caught. Always re-run Step 7 and Step 7.5 — no exceptions. Do not short-circuit on any rationalization: not on confidence in the fix, not because the diff is small, not because the modified files appear out of scope for the configured
check_commands/test_commands(e.g. edits land entirely under a local-skill directory or a docs-only path), not because re-running "would be a no-op". If a re-run is genuinely a no-op, the no-op outcome is the audit trail; skipping the re-run removes the trail. The only permissible skip is when no code was modified in this iteration (handled by the next bullet). - If all points were rejected (no modifications): mark remaining iteration items as
completed(skip — there is nothing new for the next reviewer to look at) Continue to the next pending iteration item; the next pass's reviewer dispatch (the Step 7 background bake and the fresh-dispatch path alike) composes its payload per sub-step 1's definition, continuation item and iteration-scope instruction included — not restated here.
Return-point no-stall reminder: At each iteration boundary (regardless of reviewer outcome — findings reported, "No actionable findings", any non-error result), the next action — the next iteration's reviewer dispatch when more iteration items remain, or the Step 9 (Completion Hooks) transition when this was the last iteration or "No actionable findings" was returned, or the Step 7 / Step 7.5 re-run when code was modified — must be issued in the next tool call. Do not insert an interstitial summary or acknowledgment turn between iterations; the abstract enumeration in
§ No-Stall Principleis intentionally duplicated here so the rule fires at the decision moment. -
If all N_code iteration items are completed and actionable feedback still remains, present the unresolved points to user for decision. Above the unresolved points, emit a summary preamble per
references/plan-format.md§ User-gate summary preamble. Render the findings followingreferences/plan-format.md§ Localization granularity in the resolvedlanguage.
Mark Step 8: Code Review as completed.
Step 9: Completion Hooks
Skip this step if hooks.on_complete is not configured. Mark Step 9: Completion Hooks as in_progress.
Task-derived-change gate: before executing any entry, check whether the tracked diff since <base-commit> (recorded in Step 2) contains changes produced by this task. When it does not — the tracked diff is empty or every changed path in it is pre-existing work unrelated to this task, and git status --porcelain=v1 --untracked-files=all shows no task-derived untracked files (gitignored paths never appear in that output, so the typical case — the task's only deliverables living under a gitignored directory — still skips) — skip the whole hooks.on_complete list, mark this step completed, and emit one line in the Completion summary naming the skip reason (e.g. hooks.on_complete skipped: no task-derived changes), then proceed to Step 10 (or directly to Step 11 when interactive_commits: false — per § Step 10). When an unrelated pre-existing diff exists, also add a warning line surfacing those paths (e.g. hooks.on_complete skip warning: pre-existing unrelated diff in <path>, <path>) so the user can notice unintended pre-run changes. Review-class hooks dispatched against an unrelated diff bind their findings to content the task never touched — a misleading record rather than a safety net; skipping the non-review entries along with them is likewise intended — with no task-derived changes there is no task output for any hook entry to act on. On any doubt about whether a changed path is task-derived, run the hooks as usual (the gate skips only when the absence of task-derived changes (tracked or untracked) is clear).
- Classify each entry in
hooks.on_completeas review-class (skill invocations that only return findings for the main thread to apply later — no working-tree writes, no ordering dependencies on other entries; the review-class definition from § Step 6's Cross-layer review handoff ledger paragraph applies) or non-review-class (entries that write to the working tree, run state-mutating commands, or require ordering guarantees). When background dispatch is available (same criterion as Step 7's Concurrent rules-review launch paragraph:Agentwithrun_in_backgroundexposed), dispatch all review-class entries concurrently — mirroring Step 7's read-only analysis overlap — then run non-review-class entries sequentially after all concurrent dispatches return. When background dispatch is unavailable, run all entries sequentially in order (fully backward-compatible fallback):Skill(<name>)pattern: invoke the skill — for review-class entries, include the cross-layer review handoff ledger as a short context item (per § Step 6's Cross-layer review handoff ledger paragraph; omit when the ledger has no recorded dispositions)- Other strings: execute as a Bash command (always non-review-class — Bash commands cannot return findings to the ledger)
- If a hook fails, report the error but continue executing remaining hooks. Include as warnings in the Completion summary
- After all hooks complete (or are skipped), mark
Step 9: Completion Hooksascompletedand proceed to Step 10
GATE: Verify Steps 2-9 are completed (check task status via
TaskList; if status is inconsistent, verify actual completion by reviewing work done). Mark Step 10 asin_progress.
Step 10: Interactive Commits
After hooks.on_complete (which may itself modify the working tree, e.g. via auto-formatter or apply-edit hook entries), group the working-tree changes into commits and iterate with the user one commit at a time. Step 10 runs only when interactive_commits: true — Step 1's task registration omits the row otherwise and execution proceeds directly from Step 9 to Step 11. The git push is never performed by this step (or any other step): pushing commits to a remote is the user's responsibility.
On entry to Step 10, initialize landed_count = 0 before running the procedure — so the value is well-defined for the Completion section even when the empty-output skip path in references/interactive-commits.md § Collect changes fires before its § Per-commit loop ever starts.
Post-hook attribution check: Run git diff <base-commit> --name-only to list all currently changed paths (step10_diff_paths). Compute hook_introduced_paths = step10_diff_paths − implementation_diff_paths (captured at § Step 5's "Implementation diff snapshot" paragraph): these are paths that appeared in the working tree during the review-hook phase (Steps 6–9) rather than during implementation. First subtract the § Workflow artifacts (cross-step fixed exclusion) set so workflow-owned in-session state (e.g. a plan file the ledger wrote a leftover into) is never flagged as unattributed. Cross-reference the remaining hook_introduced_paths against the cross-layer review handoff ledger's applied sites (from § Step 6's Cross-layer review handoff ledger paragraph): any path in hook_introduced_paths that is NOT covered by a ledger applied-site is unattributed — a change no review hook claimed responsibility for. When unattributed paths exist, surface each with git diff <base-commit> -- <path> and require explicit resolution before proceeding to commit grouping: (i) confirm as an expected side-effect (an auto-formatter the plan authorized, a file generated by a hook's non-review behavior) and continue, or (ii) revert with git checkout HEAD -- <path>. When no unattributed paths exist (either hook_introduced_paths is empty or every entry is covered by the ledger), proceed directly to references/interactive-commits.md.
Read references/interactive-commits.md and follow the procedure from top to bottom — it is the single canonical home for Step 10's procedure body. The Approval token closed list and Localized summary tokens below stay defined in this file and are referenced from both that procedure and other Steps.
Approval token closed list (per § No-Stall Principle's "do not rely on exact-phrase matching" rule). The example phrases below are illustrative, not literal discriminators — categorize each user response into one of the four buckets via semantic judgment. When presenting an approval gate, include at least one short-form token from the accept bucket (e.g., "OK", "LGTM", "next") so users know brief responses are valid.
- accept: explicit affirmative — "OK" / "approve" / "next" / "LGTM" / "コミットして" / "進めて" / "いいよ" or any semantic equivalent
- adjust: specific revision request — "subject を ... に" / "this file should be in commit 2" / "split this commit" / any other concrete change demand
- cancel / stop: explicit halt — "stop" / "abort" / "やめる" / "中断"
- NOT approval: interrogative or non-committal — "look good?" / "How is it?" / "Is this okay?" / "OK?". Treat as
adjustand re-present (do not silently advance)
Localized summary tokens (per references/plan-format.md § Localization granularity). These tokens are defined here as the single source of truth — § Completion below references the same paired form rather than re-rendering it:
language: ja:Step 10 部分完了: <N>/<total> コミット適用済みlanguage: en:Step 10 partial completion: <N>/<total> commits landed
§ Completion below emits the localized token whenever Step 10 ended via Mid-loop cancel (see references/interactive-commits.md § Mid-loop cancel). On a normal completion path (every commit landed, or the Mid-loop adjust un-landed-drops-to-zero / merge-absorbs-into-landed branches — see references/interactive-commits.md § Mid-loop adjust — closed-list branches), no partial-state line is needed.
Step 11: Update Rules
-
Rule extraction via the shared session scan →
Skill(extract-rules) --apply-conversation-candidates. The prose coding-rule axis (.claude/rules/) is the rule-extraction axis of the shared conversation scan (references/session-scan.md): the shared scan produces a--- RULE-CANDIDATES ---block (the C4-equivalent candidates perreferences/rule-extraction-axis.md), and this sub-step hands that block toextract-rulesConversation Candidate Apply Mode (Step C5 only — dedup / route / write / promote /.examples.md/ Security Self-Check; no jsonl re-parse). This is the apply half of a scan/apply split (the shared scan ingests the large session text once for all axes).rule-extraction-activegate: rule-extraction is inactive if (a) any entry inhooks.on_complete(as resolved in Step 1) contains the stringextract-rules(direct invocation), OR (b) Step 9 executed at least one hook and the output produced by Step 9's hook invocations (visible in this session's context) contains evidence thatextract-rules --from-conversationran this session (sufficient signal: output containsstaged_countorpromoted_count). When inactive, skip the rule-extraction work entirely — do not dispatch the shared scan on rule-extraction's behalf and do not callextract-rules. This single gate suppresses both the conversation-derived extraction paths (the apply-only path below and its standalone fallback), so the staging double-count defense is preserved: running a conversation-derived extraction twice against one session (once via a hook's--from-conversation, once via this sub-step) would make the staged-promotion mechanism (1st-observation → 2nd-observation escalation) miscount one session as two independent observations and prematurely promote staging candidates. When inactive but a retrospective axis is registered, Step 11 abstains from dispatching and Step 11.5 / 11.6 dispatch the shared scan for their own axes (references/session-scan.md§ Dispatch-once contract).- When
rule-extraction-active(Step 11 is the earliest participating step, so this is the shared scan's first dispatch point): resolve the session jsonl via the shared resolution procedure (references/self-retrospective.md§1.4 /references/workability-retrospective.md§1.3 — identical), then followreferences/session-scan.md§ Dispatch-once contract — ifsession_scan_dispatched == false, dispatch the shared scan for the still-active axes (rule-extraction ∪ any registered retrospective axes), setsession_scan_dispatched = true, store the raw return insession_scan_result; then consume the rule-extraction block per § Consuming a block. Thread the Step 2-resolvedsubagent_modeland the resolvedlanguageinto the scan (references/session-scan.md§ Inputs sets the scan subagent'sAgentmodelfromsubagent_model, omitted wheninherit). Disposition of the consumed block:- Well-formed block → write it verbatim to
.claude/plans/<slug>.rule-candidates.md(<slug>= the run's plan slug, the same value § Completion's cleanup resolves; a workflow artifact — see § Workflow artifacts) and invokeSkill(extract-rules) --apply-conversation-candidates .claude/plans/<slug>.rule-candidates.md. - Whole-scan
Status: ERROR(jsonl unreadable / unparseable) → treat rule-extraction as skipped — no fallback, because a standalone re-scan would fail the same parse. - Per-axis malformed / missing block (the jsonl parsed fine — other axes' blocks are present — but the
--- RULE-CANDIDATES ---block is absent or malformed) → fall back to standaloneSkill(extract-rules) --from-conversation(re-extract against the known-readable jsonl; the standalone C1–C5 path is untouched by this change). This per-axis fallback is the one asymmetry vs the retrospective axes' plainskipped(rule-extraction has a standalone fallback worker —references/session-scan.md§ Consuming a block). - Zero candidates (
Candidates: 0) → nothing to apply; proceed (success no-op).
- Well-formed block → write it verbatim to
Return-point no-stall reminder: after
Skill(extract-rules) --apply-conversation-candidates(or the standalone--from-conversationfallback) returns — regardless of outcome (rules applied, nothing to apply, promoted / staged counts, any non-error result) — issue the next action (sub-step 2) in the next tool call. Do not insert an interstitial summary or "shall I proceed?" turn. See § No-Stall Principle. -
Skill(extract-rules)with--update— Skip if any rule-extraction extraction ran this session: if a conversation-derived extraction happened at any point this session — sub-step 1's apply-only path applied a block, its standalone--from-conversationfallback fired, or a hook ranextract-rules --from-conversation(sub-step 1'srule-extraction-activeinactive case (b)) — skip this sub-step. Running--updateimmediately after a conversation-derived extraction risks prematurely promoting staging candidates that were just created before they accumulate a second observation. Trigger (when not skipped): significant structural/pattern changes to application code occurred — new frameworks, libraries, architectural patterns, or API conventions introduced in the diff; prose-only changes to SKILL.md, agent definitions, references, or rule files do not qualify. A dependency major-version bump alone (no implementation code changes in the diff) does not trigger--update; the major-bump signal (detected viagit diff <base-commit>of the package manifest — the same signal used in the Step 2 difficulty assessment) instead triggers the extract-rules Update Mode operational note: surface it to the user as a reminder to run--updateafter the session and to manually review.examples.mdsamples that may have gone stale after the bump. -
Char-count compaction gate:
Skip condition: If
compact_rulesis nottrue(i.e. the defaultfalse, or any non-boolean value that fell back tofalse), skip this entire sub-step — do not invokeSkill(extract-rules) --compact, do not open the Step 11 compaction approval gate, and proceed directly to sub-step 4 (variable initialization is not skipped — it is governed by the State-variable contract below, which covers the skipped case). Emit a one-line informational note in the resolvedlanguageso the user has a visible signal that compaction is intentionally not running:language: ja:Step 11 sub-step 3(圧縮)を skip しました — \compact_rules: true` が設定されていません(実験的機能 / デフォルト無効)`language: en:Step 11 sub-step 3 (compaction) skipped — \compact_rules: true` is not set (experimental feature / disabled by default)`
State-variable contract (cross-step declaration — § Completion reads both variables; the full 4-point lifecycle is specified in
references/update-rules.md§ Char-count compaction gate): at sub-step 3 entry, initializecompaction_applied_count = 0andbelow_threshold_failed_files = []. When the skip condition above fired, both variables simply stay at these initial values (no advance ever runs), so § Completion's reads are well-defined and its compaction reminder is omitted.When not skipped (
compact_rules: true): readreferences/update-rules.mdand follow § Char-count compaction gate from top to bottom — it is the single canonical home for this sub-step's procedure body, including the Step 11 compaction approval gate (USER APPROVAL GATE). -
If extract-rules is unavailable: before skipping, save any reusable patterns or insights that surfaced during the workflow to
.claude/plans/rules-candidates-<YYYY-MM-DD>.md(append if the file already exists) so the knowledge is not silently lost and can be handed off to a later manualSkill(extract-rules)run. Inform the user that extract-rules is unavailable and point to the saved candidates file. -
Commit rule updates (USER APPROVAL GATE): run this only when
interactive_commitsistrueand there are uncommitted changes under any of extract-rules' three output directories —output_dir(default.claude/rules/),examples_output_dir(default.claude/rules-extras/), andstaging_output_dir(default.claude/rules-staging/) — each resolved from.claude/extract-rules.local.md's frontmatter when that field is set, else its default. These are typically the rule files,.examples.mdfiles, and staged 1st-observation candidatesSkill(extract-rules)just wrote in sub-steps 1–3, including any accepted compaction edits from sub-step 3. Detect viagit status --porcelain=v1 --untracked-files=all -zfiltered to the union of the three resolved directories, with the § Workflow artifacts set subtracted (the default dirs are disjoint from the workflow-artifact paths under.claude/plans/and the backlog dir, but subtract explicitly so a non-default config that points an output dir at a workflow-artifact location stays safe; a project that gitignoresstaging_output_dir/examples_output_dirnaturally excludes those, since gitignored paths never appear in the porcelain output). Ifinteractive_commitsisfalseor no such changes exist, skip this sub-step entirely (no-op — the Completion rule-update / examples-dir / staging-dir reminders cover any remaining uncommitted changes). Otherwise propose a single commit of the uncommitted changes across the three directories:- Present / Stage / Commit / retry / post-commit auto-modify follow
references/interactive-commits.md'sPer-commit loopa. Present/c. Stage/d. Commit/e. Non-zero-exit retrysteps and itsPost-commit auto-modify cycle bound, with two scope differences from Step 10's loop: (i) the diff base is HEAD (Step 10 already committed the production code), so render each tracked rule file's diff viagit diff HEAD -- <path>and each untracked rule file viaRead; and (ii) this commit does not incrementlanded_count— that counter tracks Step 10 production commits only, and § Completion's decomposition-resume routing reads it; bumping it here would mis-route a decomposition-subtask run whose Step 10 landed zero production commits into the "already committed by Step 10" branch. Because the pathspec is restricted to the three extract-rules output directories, any production-code changes the user declined at Step 10 stay in the working tree and are not swept into this commit. The gate's user-facing framing (the commit presentation and the accept / adjust / cancel prompt) is rendered in the resolvedlanguage— same as the Step 10 commit gates (see § Configuration'slanguagebullet); the commit subject / body andgitdiff output stay verbatim. - Output-class labeling in
Present: label each proposed file by its extract-rules output class — confirmed rule change, example, or unreviewed 1st-observation candidate — classifying each file by the output-class filename suffix defined canonically at § Completion's "Step 11 extract-rules output reminders" paragraph (so a rule file under a collapsedexamples_output_dir == output_diris labeled a rule change, not an example). Staging candidates additionally carry the note that extract-rules stages them on first observation and normally promotes them tooutput_diron a later re-observation rather than committing them as-is. The label lets the user make an informed accept / adjust(exclude) / cancel choice and is the safeguard — together with the USER APPROVAL GATE itself — against silently committing unreviewed staging candidates. - Draft the subject in the project's conventional commit style (reuse the style deduced at Step 10's
Deduce commit style; if Step 10 was skipped this run, rungit log -n 10 --format=%sto deduce it). - Judge the user response per § Approval token closed list: accept → stage with an explicit pathspec spanning the changed paths across the three resolved directories and commit; adjust → revise the subject/body or narrow the committed file set by omitting paths from the pathspec (e.g. drop the
staging_output_dirfiles to keep them reminder-only) — thegit checkout HEAD -- <path>exclusion remains forbidden across the whole widened pathspec, not justoutput_dir, because it destroys uncommitted changes (perreferences/interactive-commits.md§ Propose commit plan's exclusion rule); then re-present; cancel → leave the changes uncommitted and proceed. - This is a new Step 11 sub-step rather than part of Step 10's commit loop because
Skill(extract-rules)runs after Step 10, so the rule files do not yet exist when Step 10's loop runs.
Return-point no-stall reminder: at the gate decision (accept / adjust resolution / cancel — any non-error result), the next action (sub-step 6) must be issued in the next tool call. Do not insert an interstitial summary or acknowledgment turn. See § No-Stall Principle.
- Present / Stage / Commit / retry / post-commit auto-modify follow
-
After the rule-update commit gate above resolves (or was skipped) — regardless of whether new rules were added, the report indicated nothing changed, or extract-rules was unavailable — mark
Step 11: Update Rulesascompletedand proceed automatically. Per the No-Stall Principle, do not wait for user input.
Step 11.5: Self-Retrospective
Emit a sanitized improvement signal for the dev-workflow-bundle skills (dev-workflow, ask-peer, extract-rules, rules-review) to a user-configured destination. Raw conversation jsonl stays in-session; only abstracted, project-agnostic text leaves.
Skip this step if self_retrospective.feedback is unset/invalid (Step 1 did not register the row). Otherwise read references/self-retrospective.md and follow the procedure from top to bottom — the difficulty assessment does not gate this step. The jsonl scan is performed by the shared session scan: read references/session-scan.md and follow its § Dispatch-once contract. Reaching this dispatch point presupposes Step 11.5's §1 pre-flight (gh-auth / repo accessibility — a runtime gate, distinct from the Step-1 feedback registration gate) already passed; on pre-flight failure Step 11.5 aborts here and Step 11.6 becomes the dispatcher (references/session-scan.md § Dispatch-once contract). At Step 11.5's dispatch point: if session_scan_dispatched is already true (an earlier participating step — Step 11 when rule-extraction-active — already dispatched), consume the self-retrospective block from session_scan_result (§ Consuming a block) — the block Step 11 may have included speculatively before this pre-flight, now validated; if it is false (Step 11 abstained because rule-extraction was inactive), Step 11.5 is the dispatcher — dispatch the shared scan for the still-active axes (self-retrospective ∪ workability when workability_retrospective.enabled), store the return in session_scan_result, and consume the self-retrospective block from it (§ Consuming a block). Thread the Step 2-resolved subagent_model and the resolved language into the shared scan — references/session-scan.md § Inputs sets the scan subagent's Agent model from subagent_model (omitted when inherit).
Step 11.6: Workability Retrospective
Detect this session's project-tooling workability improvements — reusable manual procedures that could become a .claude/skills/<name>/ skill (skill-candidate) and mechanically-enforceable conventions that could become a linter-config / check_commands addition (lint-rule-candidate) — and offer a per-candidate 4-way disposition gate (act now / make a subtask / save to backlog / reject). The detection runs via the shared session scan (references/session-scan.md) — the same single jsonl parse that serves Step 11 (rule-extraction) and Step 11.5; raw conversation stays in-session. This is the project-tooling retrospective axis, distinct from Step 11's prose-rule axis (extract-rules) and Step 11.5's bundle-skill axis (self-retrospective).
Skip this step if workability_retrospective.enabled is not true (Step 1 did not register the row). Otherwise read references/workability-retrospective.md and follow the procedure from top to bottom — the difficulty assessment does not gate this step (mirrors Step 11.5). The jsonl scan is the shared session scan: read references/session-scan.md and follow its § Dispatch-once contract. At this step's dispatch point, if session_scan_dispatched is already true (an earlier participating step — Step 11 and / or Step 11.5 — dispatched the shared scan with the workability axis active), consume the workability block from session_scan_result (§ Consuming a block); if it is false (no earlier participating step dispatched — Step 11 abstained because rule-extraction was inactive, and Step 11.5 was unregistered or pre-flight-aborted), dispatch the shared scan for the workability axis and consume its block. When dispatching, thread the Step 2-resolved subagent_model and the resolved language into the shared scan — references/session-scan.md § Inputs sets the scan subagent's Agent model from subagent_model (omitted when inherit).
Completion
Derived staging artifact cleanup: before reporting summary, delete any per-agent staging documents under .claude/plans/ that dispatched review subagents generated this run (files matching <slug>-agent-*.md, where <slug> is the run's plan slug — on the visual_plan_review: true path, the slug established at Step 4 sub-step 2 path (b); on the default path, the Plan Mode plan file's basename), plus the Step 4 visual-gate served plan file, its comments file, and its prev snapshot (<slug>.plan-review.md / <slug>.plan-review.comments.json / <slug>.plan-review.prev.md) when the visual gate ran this session, plus the Step 11 rule-extraction candidate file (<slug>.rule-candidates.md) when rule-extraction ran this session — all are commit-excluded but, unlike the Web-routine staging artifacts whose workspace is torn down, the visual gate is local-only (persistent working tree) so they would otherwise accumulate as untracked noise. Delete the staging files in two separate rm -f commands — fixed-name files first, the agent-staging glob last: rm -f .claude/plans/<slug>.plan-review.md .claude/plans/<slug>.plan-review.comments.json .claude/plans/<slug>.plan-review.prev.md .claude/plans/<slug>.rule-candidates.md then rm -f .claude/plans/<slug>-agent-*.md || true. Isolating the glob in its own trailing command is load-bearing: under zsh's nomatch an unmatched glob aborts the command it sits in — and -f suppresses only rm's own missing-file error, not the shell's expansion failure — so a single combined rm -f <glob> <fixed-names> would skip every fixed-name deletion whenever no agent file matches. The || true keeps the exit clean when nothing matches (zsh still prints a harmless no matches found; bash passes the unmatched glob through literally). Both commands stay covered by the existing Bash(rm -f .claude/plans/*) permission, so no new tool grant is needed. Do not delete the main plan document (<slug>.md) or any decomposition state file — those are canonical workflow artifacts that Step 1.5 / --resume depend on.
Report summary: tasks completed, files modified, test results, review outcomes, rules updated. Output in the resolved language following references/plan-format.md § Localization granularity.
Difficulty-skip reminder (per references/plan-format.md § Localization granularity): when difficulty_skipped_steps (initialized at Step 2 entry, populated by Step 2's Adjust N by difficulty) is non-empty, surface a line in the resolved language naming the steps the difficulty-skip matrix skipped, so the skip is never silent. Render the recorded steps with their tier; the example below pairs the two language values:
language: ja:難易度判定(<tier> tier)により <steps> を skip しました— e.g.:難易度判定(Trivial tier)により Step 6 Tidy / Step 7.5 Rules Compliance Review を skip しましたlanguage: en:Skipped <steps> per the difficulty-skip matrix (<tier> tier)— e.g.Skipped Step 6 Tidy / Step 7.5 Rules Compliance Review per the difficulty-skip matrix (Trivial tier)
The reminder is omitted when difficulty_skipped_steps is empty (Moderate / Complex tasks, or -i-skipped Adjust N runs — see the Step 2-entry init). The step names (Step 6 Tidy / Step 7.5 Rules Compliance Review) stay verbatim regardless of language.
Step 10 partial-state line: if Step 10 ended via its Mid-loop cancel branch (see references/interactive-commits.md § Mid-loop cancel), emit the localized partial-completion token defined at § Step 10's "Localized summary tokens" paragraph. On a normal completion path, omit this line.
Step 11 extract-rules output reminders (division of labor): Step 11's "Commit rule updates" gate proposes committing changes across all three extract-rules output directories (output_dir / examples_output_dir / staging_output_dir). Resolve those three directories once (per the gate's resolution) and run a single git status --porcelain=v1 --untracked-files=all -z scan at Completion, partitioning its output by directory into uncommitted_rule_changes (output_dir, default .claude/rules/) / uncommitted_examples_changes (examples_output_dir, default .claude/rules-extras/) / uncommitted_staging_changes (staging_output_dir, default .claude/rules-staging/). The scan's scope is the three-dir union (a coarse filter — paths under none of the three resolved dirs are ignored); within that scope, assign each changed path to exactly one set in two stages. (1) By directory membership — a path under exactly one of the three resolved dirs goes to that dir's set; the default (disjoint) config resolves entirely here, identical to prior behavior. (2) Filename-class tie-break, applied only when a path matches more than one resolved dir — possible when two dirs resolve to the same path or one nests under another (extract-rules permits examples_output_dir / staging_output_dir to be set to output_dir to opt into auto-load) — classify by extract-rules' output-class filename suffix, not by directory order: a basename ending in .examples.md → uncommitted_examples_changes; the staging file project.staging.local.md (.staging.local.md suffix — test this before the general .md rule fallback, since it also ends in .local.md) → uncommitted_staging_changes; every other .md → uncommitted_rule_changes. Filename-class decides the tie because once two dirs collapse to one path the directory can no longer tell a rule file from an example / staging file — a directory-order tie-break would misroute a rule file under a collapsed examples_output_dir == output_dir into the examples set and wrongly suppress the rule-update reminder. (extract-rules' examples files always end .examples.md with no .local.md variant, so the three suffixes stay mutually exclusive under this ordering.) Either stage lands every path in exactly one set (no double-count, no doubled reminder). The three reminders below read these partitioned sets, none re-resolves or re-scans. Each fires only for residue in its own directory that the gate proposed but the user left uncommitted (adjust-excluded, cancel-ed, or interactive_commits: false so the gate never ran); since the sets reflect the current working-tree state, an accepted gate commit naturally clears the corresponding reminder.
Step 11 rule-update reminder (per references/plan-format.md § Localization granularity): uncommitted_rule_changes is the partitioned set for output_dir (default .claude/rules/); it is also read by the compaction reminder and the decomposition-resume note below. When uncommitted_rule_changes is non-empty, surface a manual-commit reminder in the resolved language (<N> = number of uncommitted rule files):
language: ja:\.claude/rules/` に未コミットの変更が 件あります — PR を開く前に手動で commit してください`language: en:<N> uncommitted change(s) under \.claude/rules/` remain — please commit manually before opening a PR`
The reminder is omitted when uncommitted_rule_changes is empty — including the case where Step 11's "Commit rule updates" gate already committed the rule changes (interactive_commits: true, gate accepted). When interactive_commits: false the gate never ran, so the rule changes stay uncommitted and the reminder fires as before (backward-compatible).
Step 11 examples-dir reminder: when uncommitted_examples_changes (the partitioned set for examples_output_dir, default .claude/rules-extras/) is non-empty, surface a reminder in the resolved language (<N> = number of uncommitted example files, <examples_dir> = the resolved directory):
language: ja:\<examples_dir>` に未コミットの extract-rules examples が 件あります — PR を開く前に手動で commit してください`language: en:<N> uncommitted extract-rules example file(s) under \<examples_dir>` remain — please commit manually before opening a PR`
The reminder is omitted when uncommitted_examples_changes is empty.
Step 11 staging-dir reminder: when uncommitted_staging_changes (the partitioned set for staging_output_dir, default .claude/rules-staging/) is non-empty, surface a reminder in the resolved language (<N> = number of uncommitted staging files, <staging_dir> = the resolved directory). The message keeps the promote-review framing — staged entries are 1st-observation candidates normally promoted to .claude/rules/ on a later re-observation rather than adopted as-is, and the localized suffix notes they were also committable at the gate:
language: ja:\<staging_dir>` に未レビューの extract-rules 候補が 件あります — 手動で確認し、採用するものを `.claude/rules/` へ promote してください(またはゲートで commit 可能でした)`language: en:<N> extract-rules candidate(s) under \<staging_dir>` await review — inspect and promote accepted files to `.claude/rules/` manually (or commit them at the Step 11 gate)`
The reminder is omitted when uncommitted_staging_changes is empty.
Step 11 compaction reminder (per references/plan-format.md § Localization granularity): this block has two independent clauses.
(i) Commit clause — when compaction_applied_count > 0 (the Step 11 sub-step 3 char-count compaction gate landed user-accepted edits) and uncommitted_rule_changes (the output_dir partition from § Step 11 extract-rules output reminders) is non-empty — i.e. the compaction edits were not committed by Step 11's "Commit rule updates" gate (compaction edits live under .claude/rules/, so an accepted rule-update commit stages them along with the other rule changes) — surface a separate manual-commit reminder in the resolved language (rendered in file-unit count, distinct from the rule-update reminder above which counts uncommitted rule files):
language: ja:Step 11 で <N> 件のルールファイルを圧縮しました — PR を開く前に手動で commit してくださいlanguage: en:Step 11 compacted <N> rule files — please commit manually before opening a PR
This commit clause is omitted when compaction_applied_count == 0 OR uncommitted_rule_changes is empty (the latter means the compaction edits are already committed). The uncommitted_rule_changes-non-empty test is a coarse proxy for "the compaction edits are still uncommitted": a partial adjust at the rule-update gate that committed the compacted files but left other rule files uncommitted can over-fire this clause — a harmless redundant nudge, not a data-loss path.
(ii) Below-threshold follow-up — unconditional on commit state (it concerns re-running compaction, not committing): when below_threshold_failed_files is non-empty, surface a follow-up reminder naming the files that remain over threshold. <files> always renders at the sentence tail so the block-level list never appears mid-sentence:
language: ja:<M> 件のファイルが閾値を超えています。手動で再度 \Run `Skill(extract-rules) --compact`, or edit the file directly:followed by` on the next linelanguage: en:<M> files still exceed the threshold. Re-run \Skill(extract-rules) --compact` manually or edit the files directly:followed by` on the next line
Render <files> as one path per line — verbatim from files_processed[].path (repo-root-relative, e.g. .claude/rules/project.rules.local.md; never rewritten to user-absolute /Users/... form) — each prefixed with - (hyphen + space, no leading indent) directly below the reminder sentence as a top-level markdown bullet list. This applies for any M ≥ 1 — single-element lists render as a one-bullet list, not inline, so the layout is identical across runs and the trailing prose clause never floats after the bullet list.
The compaction reminder block is omitted entirely when both clauses are omitted — i.e. when the commit clause does not fire (compaction_applied_count == 0 OR uncommitted_rule_changes empty) AND below_threshold_failed_files is empty.
If this run was executing a subtask from a decomposition state file, also do the following (all reads/writes target the canonical state-file path recorded in Step 1.5):
Execution-time deferral/exclusion gate: before marking the subtask as completed, check whether any in-scope work items were excluded, deferred, or discovered as unassigned during implementation or testing. Items recorded only in prose (Risks entries, inline notes) are invisible to --resume and will be silently skipped — each such item must be promoted to a tracked subtask entry in the state file before completion is declared. For each uncovered item, get user approval on one of: (a) add as a new pending subtask with a depends_on link if sequencing matters, (b) fold into an existing pending subtask's scope, or (c) explicitly accept as permanently out of parent-task scope. The completion report must confirm that no goal-required items remain in untracked prose form.
- Mark the current subtask's
statusascompletedin the canonical state file and write back - Ask the user for an optional PR URL for this subtask. On a non-empty answer, set the subtask's
prfield and write back; otherwise leave itnull - Refresh the parent-task progress row's
<done>/<total>count - Find the next runnable subtask (smallest-id
pendingwith alldepends_oncompleted) - If a next subtask exists: branch on whether Step 10 actually landed any commits this run (use the landed_count from Step 10 — taking the config flag alone would mis-route the case where
interactive_commits: truemet the Step 10 skip conditions and exited at zero commits):landed_count > 0: tell the user the current subtask's changes have already been committed by Step 10 — open a PR for those commits, then start a new session with/dev-workflow --resume <slug>once the PR is uplanded_count == 0(either becauseinteractive_commits: falseor because Step 10 was skipped): tell the user to commit the current subtask's changes and open a PR before resuming, then start a new session with/dev-workflow --resume <slug>. Explain why this matters: the next run records a fresh base-commit from HEAD, so uncommitted changes would leak into the next subtask's diff In both branches, if any of extract-rules' three output directories (output_dir/examples_output_dir/staging_output_dir) have uncommitted residue (i.e., any of the Step 11 rule-update / examples-dir / staging-dir reminders above fired), tell the user to commit those writes manually before resuming — otherwise they leak into the next subtask's diff the same way uncommitted feature changes would. When Step 11's "Commit rule updates" gate already committed all of them (no residue in any of the three dirs), omit this instruction — the changes are committed and will not leak. (This warning overlaps the per-dir reminders above on the same residue by design — both are prose nudges, no double-count.) The "no push" invariant for both branches is stated at § Step 10's preamble
- If no next subtask exists (all subtasks completed): delete the canonical state file via
rm -f <canonical-path>, remove the parent-task progress row, and include every subtask's title and recordedpr(if any) in the parent-task completion summary