# Plan

> Create a structured implementation plan in docs/plans/. Activates on "make a plan", "create a plan", "plan this feature", "write a plan", or when the user wants to document implementation steps before coding.

- Skill: `parmaster/plan` (Agent Skill)
- Install (CLI): `npx skillmds@latest add parmaster/plan`
- Raw SKILL.md: https://api.skillmd.com/api/skills/parmaster/plan/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: parMaster (https://skillmd.com/u/parmaster)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/parmaster/plan

---


# Implementation Plan Creation

Create an implementation plan in `docs/plans/yyyy-mm-dd-<task-name>.md`. Write as if the engineer implementing it has zero context about the codebase — document everything they need: which files to touch, actual code to write, exact commands to run, how to test it. Assume they are skilled but know nothing about this toolset or problem domain.

## Step 0: Parse intent and gather context

Before asking questions, understand what the user is working on:

1. **Parse user's arguments** to identify intent:
   - "add feature Z" / "implement W" → feature development
   - "fix bug" / "debug issue" → bug fix plan
   - "refactor X" / "improve Y" → refactoring plan
   - "migrate to Z" / "upgrade W" → migration plan
   - generic request → explore current work

2. **Gather relevant context quickly** — use direct tool calls (Read, Glob, Grep), NOT an Agent. Keep discovery under 30 seconds in the default mode; deep-discovery mode below lifts both this budget and the file cap.

   **for feature development:**
   - glob for files matching the feature area
   - read 1-3 most relevant files to understand existing patterns
   - check project structure with a quick `ls` of key directories

   **for bug fixing:**
   - grep for error messages or function names mentioned in the request
   - read the specific file(s) involved
   - check `git log --oneline -5` for recent changes

   **for refactoring/migration:**
   - glob for files matching the area being refactored
   - read 2-3 key files to understand current structure
   - grep for imports/references to identify dependencies

   **for generic/unclear requests:**
   - check `git status` and `git log --oneline -5`
   - read README.md or CLAUDE.md for project overview
   - `ls` the top-level directory structure

   **CRITICAL: do NOT launch an Agent or read more than 5 files in this step.** This cap is on *discovery* only — Step 2's "Read what you will modify" pass is separate and uncapped.

   **Deep-discovery mode** — the 5-file cap and 30-second budget above are the default, not a hard ceiling. Switch to deep mode when any of these become true:
   - `docs/plans/` (including `completed/`) already contains a sibling plan for the same feature (checkable right here at Step 0)
   - the user states, at any point, that this plan is part of a larger, multi-plan effort (a feature broken into slices, a WBS/parent doc)
   - Step 1's scope/constraints answers reveal multi-plan or large-feature scope that wasn't apparent yet at Step 0

   The first condition can be checked now. The other two usually can't be known until after Step 1 — when either fires there, go back and run the deep pass below before Step 2, rather than proceeding with shallow discovery just because the trigger came late.

   In deep mode: read as many files as it takes to understand the actual call chains the plan's tasks depend on — no fixed file count, no 30-second budget. This is still a discovery pass, not a full audit, so keep it targeted to what the plan's tasks will actually call or touch.

   **for Go repos — resolve the real test command, don't assume `go test ./...`:**
   - check `Makefile` for a `test` target → use `make test`
   - else check `.github/workflows/*.yml` / `.gitlab-ci.yml` for the test step → mirror that exact invocation
   - else fall back to `go test ./...`

   Use whichever command this resolves to everywhere the plan references "run full test suite."

3. Synthesize findings into a brief context summary (3-5 bullet points)

## Step 1: Present context and ask focused questions

Show the discovered context, then ask questions **one at a time** — a separate AskUserQuestion tool call per question, never multiple questions batched into one call's `questions` array:

1. **Plan purpose**: "what is the main goal?" — multiple choice with suggested answer based on discovered intent
2. **Testing approach**: "TDD or regular?" — options: "TDD (tests first)" / "Regular (code first, then tests)". Ask this early because it shapes the task structure throughout the plan.
3. **Scope**: "which components/files are involved?" — multiple choice with discovered files. The tool requires ≥2 options per question — if discovery turned up only one file/component, do not force a second fabricated option; ask this one as free text instead.
4. **Constraints**: "any specific requirements or limitations?"
5. **Plan title**: "short descriptive title?" — suggest based on intent

## Step 1.5: Explore approaches

Once the problem is understood, propose implementation approaches:

1. **Propose 2-3 different approaches** with trade-offs
2. **Lead with recommended option** and explain reasoning
3. **Present conversationally** — not a formal document yet

Example format:
```
I see three approaches:

**Option A: [name]** (recommended)
- how it works: ...
- pros: ...
- cons: ...

**Option B: [name]**
- how it works: ...
- pros: ...
- cons: ...

Which direction appeals to you?
```

Use AskUserQuestion to select the preferred approach before creating the plan.

**Skip this step** if the approach is obvious, user specified it, or it's a clear bug fix.

## Step 2: Create plan file

Check `docs/plans/` for existing files, then create `docs/plans/yyyy-mm-dd-<task-name>.md` (use current date).

### File structure first

Before defining tasks, map out which files will be created or modified and what each one is responsible for. This is where decomposition decisions get locked in.

- Design units with clear boundaries and well-defined interfaces — each file should have one clear responsibility
- Prefer smaller, focused files; you reason best about code you can hold in context at once
- Files that change together should live together; split by responsibility, not by technical layer
- In existing codebases, follow established patterns; if a file is unwieldy, a split in the plan is reasonable

This structure informs task decomposition — each task should produce self-contained changes that make sense independently.

### Read what you will modify

Before writing a task, read **in full** every file that task lists under `Modify`, and every file it lists under `Create` that already exists. Not a grep for the symbol, not the first 50 lines — the whole file. This is not part of Step 0's discovery budget and is not capped by it: discovery decides *what* the plan touches, this pass establishes *what is actually there* in the files it has already decided to touch.

Two things go wrong when this is skipped, and both produce a plan that cannot compile:

- **Helpers and fixtures.** A task writes `newFakeClientBuilder()` when the real signature is `newFakeClientBuilder(t, scheme)`, or declares a helper that already exists in the same package. Before writing any test code, read the existing test files in that same package — the ones the new tests will sit beside — and reuse their real fixture and helper names, with their real parameter lists.
- **Existing assertions.** A task changes behavior that an existing test already pins (a returned `Result{}`, a status reason, an error string) and never lists the assertion as needing an update. Any test currently asserting on behavior a task changes is itself a `Modify` target — find those assertions while reading, and give each one an explicit checklist item.

If a file is genuinely too large to hold, that is a signal to narrow the task's scope, not to skim the file.

### Dependency contract check

**Skip this step** if the plan introduces net-new code with no existing dependencies to verify.

Otherwise, before writing tasks: identify every external function, method, or API the plan's correctness depends on — things the plan will CALL, not things it will CREATE. For each one:

1. Read its body (not just its name or signature)
2. Record what it actually guarantees: privileges granted, errors returned and how they're wrapped, side effects, state left behind after it runs
3. Flag any gap between the name's implied behavior and the body's actual behavior — these are the places plans silently go wrong

This is a focused pass — typically 3–6 functions, not broad exploration. Record findings in the "Verified Dependency Behaviors" section of the plan.

In deep-discovery mode (Step 0), widen this to every dependency any task actually calls — not a fixed 3–6 count. A function reused across several tasks needs verifying once; a wrong assumption about it otherwise silently reproduces itself into every task that calls it.

Test-only helpers count as dependencies. A fixture, builder, or assertion helper the plan's test code calls is a function the plan's correctness depends on, even though it never ships — and it is the single most common place plans go wrong. It does not need a "Verified Dependency Behaviors" entry (that section is for shipped behavior), but its real signature does need to be right in every task that calls it.

### Plan structure

```markdown
# [Plan Title]

**Goal:** [one sentence describing what this builds]

**Architecture:** [2-3 sentences about the approach]

**Tech Stack:** [key technologies/libraries involved]

---

## Context (from discovery)
- files/components involved: [list from step 0]
- related patterns found: [patterns discovered]
- dependencies identified: [dependencies]

## Verified Dependency Behaviors
*External functions/APIs this plan calls — verified by reading their bodies, not inferred from names. Omit if plan is net-new with no existing dependencies.*

- `FunctionName` (`path/to/file.go:NN`): [what it actually does — privileges granted, errors returned/wrapped, side effects, state left behind]
- ...

## Development Approach
- **testing approach**: [TDD / Regular - from user preference]
- complete each task fully before moving to the next
- make small, focused changes
- **CRITICAL: every task MUST include new/updated tests** for code changes
- **CRITICAL: all tests must pass before starting next task**
- **CRITICAL: update this plan file when scope changes during implementation**
- **CRITICAL: single summary commit at the end** — no per-task commits; one commit covers all implementation + plan move when complete
- **CRITICAL: run `golangci-lint run ./...` before committing** — fix all linter issues first
- run tests after each change
- maintain backward compatibility

## Technical Details
- key design decisions and rationale
- data structures and changes
- parameters and formats
- processing flow

## Progress Tracking
- mark completed items with `[x]` immediately when done
- add newly discovered tasks with ➕ prefix
- document issues/blockers with ⚠️ prefix

## Implementation Steps

### Task 1: [specific name]

**Files:**
- Create: `exact/path/to/new_file`
- Modify: `exact/path/to/existing`

**If TDD:**

- [ ] **Write failing tests** — happy path + error cases + edge cases

```go
func TestFunctionName_HappyPath(t *testing.T) { ... }
func TestFunctionName_InvalidInput(t *testing.T) { ... }
func TestFunctionName_EmptyResult(t *testing.T) { ... }
```

- [ ] **Run tests to verify they fail**

  Run: `go test ./path/... -run TestFunctionName -v`
  Expected: FAIL

- [ ] **Write minimal implementation**

```go
func FunctionName(input Type) ReturnType {
    // implementation
}
```

- [ ] **Run tests to verify all pass**

  Run: `go test ./path/... -run TestFunctionName -v`
  Expected: PASS

**If Regular:**

- [ ] **Write implementation**

```go
func FunctionName(input Type) ReturnType {
    // implementation
}
```

- [ ] **Write tests** — happy path + error cases + edge cases

```go
func TestFunctionName_HappyPath(t *testing.T) { ... }
func TestFunctionName_InvalidInput(t *testing.T) { ... }
func TestFunctionName_EmptyResult(t *testing.T) { ... }
```

- [ ] **Run tests to verify all pass**

  Run: `go test ./path/... -run TestFunctionName -v`
  Expected: PASS

### Task N-1: Verify acceptance criteria
- [ ] verify all requirements from Goal are implemented
- [ ] run full test suite: `<command resolved in Step 0, e.g. `make test` or `go test ./...`>`
  - if failures look like shared-state flakiness — an assertion fails against a resource another test seems to have touched, failures aren't reproducible when the same test is run alone (`-run`), or which tests fail changes between runs — retry once with `-p=1` before treating it as a regression
- [ ] run `golangci-lint run ./...` — fix all issues before proceeding
- [ ] verify test coverage meets project standard

### Task N: [Final] Wrap up and commit
- [ ] update README.md if needed
- [ ] update CLAUDE.md if new patterns discovered
- [ ] move this plan to `docs/plans/completed/` — use `mkdir -p docs/plans/completed && mv <plan> docs/plans/completed/` (plain `mv`, not `git mv`: the plan is usually untracked, and the final `git add -A` stages the move either way)
- [ ] single summary commit: all implementation changes + plan move in one commit
- [ ] open draft PR — invoke `planning:pr`

## Post-Completion
*Items requiring manual intervention or external systems*
```

### No placeholders

Every step must contain the actual content an engineer needs. These are plan failures — never write them:
- "TBD", "TODO", "implement later", "fill in details"
- "Add appropriate error handling" / "add validation" / "handle edge cases" (without showing the code)
- "Write tests for the above" (without actual test code)
- A single happy-path test when error cases or edge cases clearly exist — always enumerate: what inputs cause errors? what are the boundary values? what does the function return when there's nothing to return? Each scenario that can fail Sonar coverage gets its own named test function.
- "Similar to Task N" (repeat the code — the engineer may read tasks out of order)
- Steps that describe what to do without showing how — if a step changes code, show the code
- References to types, functions, or methods not defined in any task

### Code comment rules

Comments inside example code shown in tasks must be self-contained — never a pointer to something else:

- No ticket IDs, no links to Confluence/Jira/PRs, no commit SHAs
- No `(Slice N)` markers or "see ... in Technical Details" pointers back into this plan
- No `docs/specs/...` references — inline the one clause of context a reader needs, don't point at the spec
- At most 1-2 lines; if it needs more than that to justify itself, the content belongs in this plan's prose, not in a code comment
- State only the "why" a future reader needs at the call site to not re-break the thing — never restate what the code obviously does

This applies to comments in the code itself. Plan-level cross-references (a WBS/slice note, "this plan supersedes the approach in `<prior-plan>`") stay in the plan's own prose sections — this rule doesn't touch those.

## Step 2.5: Self-review

After writing the complete plan, check it yourself before offering next steps. All 8 checks below are internal reasoning, not an announced procedure — where a check is faster with a tool call (a grep, a read) than by eyeballing, make the call and act on the result, but don't narrate it as its own step or report a "clean" pass; only surface something if you actually find and fix an issue.

1. **Spec coverage** — skim each requirement. Can you point to a task that implements it? Add tasks for any gaps.
2. **Placeholder scan** — search for any patterns from the "No placeholders" section above. Fix them.
3. **Type consistency** — do method signatures and names used in later tasks match what's defined in earlier tasks? A function called `ParseConfig()` in Task 3 but `LoadConfig()` in Task 7 is a bug. Then check the same names against the real files: every helper, fixture, and function a task *calls* rather than creates must match the signature in the file you read, and no task may declare something that already exists in that package.
4. **Dependency behavior check** — for each entry in "Verified Dependency Behaviors": does the plan's logic actually hold given what that function does? A function that grants USAGE+DML but not CREATE is not "full access" even if named that way.
5. **Error/status tracing** — skip if the plan asserts no error outcomes or status codes. Otherwise, for every one asserted, trace it end-to-end: where the sentinel/error originates, every `%w` re-wrap on the way, and what the handler that receives it actually returns. Fix any task whose expected outcome doesn't match what the trace shows.
6. **Test setup preconditions** — skip if the plan has no test setup steps. Otherwise walk each task's test setup in execution order against the API's actual state-transition/creation-order rules. Fix any step that would be rejected because it violates an ordering requirement.
7. **Multi-phase state** — skip if the plan touches no migration, workflow, or staged operation. Otherwise check what earlier phases actually leave in place before a later task asserts on that state. Fix any assumption of absent state that an earlier phase already establishes.
8. **Comment hygiene** — same as the other seven: check the plan's code blocks for ticket IDs (`[A-Z]{2,}-[0-9]+`), links (`https?://`), commit SHAs (`\b[0-9a-f]{7,40}\b`), `Slice [0-9A-Z]`, `see .* Technical Details`, and `docs/specs`. Skip a match that's actually a standard name, not a reference — `UTF-8`, `SHA-256`, `RFC-7231`, `AES-256`, `ISO-8601` and the like aren't ticket IDs. Rewrite any real hit per "Code comment rules" above.

Fix issues inline. No need to re-review after fixing.

These checks mirror what the separate `plan-review` agent verifies. Catching them here means fewer review rounds, not weaker review — the reviewer still runs the same checklist independently.

## Step 3: Next steps

After self-review, tell the user: "created plan: `docs/plans/yyyymmdd-<task-name>.md`"

Before building this menu, check availability: `[ "$AGTERM_ENABLED" = "1" ] && command -v agtermctl >/dev/null 2>&1`. Only include the "Implement in a Separate Session" option below when that check succeeds; omit it otherwise (the other four options are always shown).

Then use AskUserQuestion:

```json
{
  "questions": [{
    "question": "Plan created. What's next?",
    "header": "Next step",
    "options": [
      {"label": "Auto-review", "description": "Run structured agent review — checks correctness, over-engineering, test coverage"},
      {"label": "Review with revdiff", "description": "Open plan in revdiff for inline annotations"},
      {"label": "Implement in a Subagent", "description": "Hand off implementation to a background subagent — reports back when done, keeps this session clean"},
      {"label": "Implement in a Separate Session", "description": "Hand off implementation to a fresh agterm session, in the same workspace as this one — runs interactively, you can watch and drive it directly"},
      {"label": "Done", "description": "Stop here"}
    ],
    "multiSelect": false
  }]
}
```

- **Auto-review**: invoke the `planning:review-plan` skill on the plan file — it handles the review/fix loop internally. When it returns, stop completely. Do NOT proceed to implementation.
- **Review with revdiff**: invoke the `revdiff:revdiff` skill on the plan file — it handles the full annotation and revision loop internally. When it returns, stop completely. Do NOT proceed to implementation.
- **Implement in a Subagent**: first ask which model the implementer should run on, using AskUserQuestion:

  ```json
  {
    "questions": [{
      "question": "Which model should the implementer subagent use?",
      "header": "Model",
      "options": [
        {"label": "Inherit", "description": "Use the same model as this session (default)"},
        {"label": "Opus", "description": "Most capable — best for complex or subtle implementations"},
        {"label": "Sonnet", "description": "Faster and cheaper — good for straightforward plans"},
        {"label": "Haiku", "description": "Fastest and cheapest — for simple mechanical changes"}
      ],
      "multiSelect": false
    }]
  }
  ```

  Then use the Agent tool with `subagent_type: general-purpose` and `run_in_background: true` to dispatch the plan below. Pass `model` set to the chosen tier (`opus`, `sonnet`, or `haiku`); for **Inherit**, omit the `model` parameter entirely. Do NOT add task-by-task review scaffolding or extra process — this is a plain hand-off, matching what a fresh session would get:

  ```
  You have a new implementation plan to execute: PLAN_FILE

  Read it fully, then implement every task in order, following its stated
  testing approach. Run the project's tests and linter before treating any
  task as done. When the whole plan is implemented, report a concise
  summary of what changed, and flag any deviations from the plan or open
  concerns.
  ```

  Tell the user implementation has been handed off to a background subagent (noting the chosen model) and they'll be notified when it completes. Stop completely — do NOT continue.
- **Implement in a Separate Session**: hand off to a fresh agterm session in this same workspace. First ask which model it should run on, using the same AskUserQuestion as the Subagent option above (`Inherit`/`Opus`/`Sonnet`/`Haiku`); lower-case the chosen label for `MODEL` (empty string for Inherit).

  Run: `bash "${CLAUDE_PLUGIN_ROOT}/scripts/agterm-handoff.sh" "PLAN_FILE" "" "MODEL"` (substitute the real plan path for `PLAN_FILE` and the chosen model for `MODEL`).

  On success (exit 0), the script's last stdout line is the new session's display name (e.g. `Implement: foo`) — tell the user implementation has been handed off to a new agterm session with that name, in this same workspace (noting the chosen model, unless Inherit), and they can switch to it to watch or drive it directly. On failure (non-zero exit), tell the user the handoff failed, quoting the script's stderr output. Do not fall back to a subagent silently. Either way, stop completely.
- **Done**: stop.

## Key principles

- **Zero context** — write as if the implementer knows nothing about this codebase; show the code, show the commands, show expected output
- **One question at a time** — do not overwhelm with multiple questions
- **Multiple choice preferred** — easier than open-ended when possible
- **YAGNI ruthlessly** — minimal scope, no unnecessary features
- **Lead with recommendation** — have an opinion, explain why, but let user decide
- **Explore alternatives** — always propose 2-3 approaches before settling
- **Single summary commit** — never commit per task; one commit at the end covers everything
- **Complete code in every step** — if a step changes code, include the actual code block

