plan-task · diff

git:20260911.6fce28d to git:20260912.f731445

2 added, 2 removed. Audit A to A.

---
name: plan-task
description: Plans a task or feature - loads context, optionally clarifies requirements, spawns Plan agent, persists plan to the project-scoped .groundwork-plans/
requires: understanding-feature-requests
argument-hint: "[task-number-or-description] [--project name]"
---
# Task Planning Skill
Plans a task or feature by loading context, optionally clarifying requirements, spawning a Plan agent, and persisting the validated plan to the project-scoped `.groundwork-plans/` directory.
## Explicit Project Input
If arguments include `--project <name>`, resolve that project directly from the repository's `.groundwork.yml` for this invocation. Treat it as authoritative; do not depend on or change persisted project selection. In runner mode, `GROUNDWORK_PROJECT` and `GROUNDWORK_PROJECT_ROOT` provide the same invocation-local selection.
## Runner Mode
If session context contains `GROUNDWORK_RUNNER_MODE=true`:
- Skip the model recommendation pre-flight.
- Treat `GROUNDWORK_BATCH_MODE=true` as authoritative: do not call `AskUserQuestion`.
- When information or a decision is missing, return `RESULT: FAILURE` instead of asking.
- Do not modify `.gitignore`; the runner keeps `.groundwork-plans/` out of Git state.
- Keep the existing terminal `RESULT: PLANNED` contract unchanged.
## Token Discipline
This skill orchestrates planning workflows. Every turn re-reads the full context window, so unnecessary turns are expensive.
1. **No narration turns.** Do not output text-only turns like "Let me load the task" or "Now I'll spawn the plan agent." Combine text with a tool call in the same turn, or skip the text entirely.
2. **Batch tool calls.** When multiple tool calls are independent, issue them all in one turn.
3. **No waiting updates.** Do not output "Waiting for results..." turns. Wait silently until results arrive.
4. **Keep context lean.** Do not read file contents you won't use directly. Pass file paths to subagents and let them read in their own context windows.
## Pre-flight: Model Recommendation
**Your current effort level is `{{effort_level}}`.**
Skip this step silently if effort is `high`, `xhigh`, or `max` (the scale is `low` < `medium` < `high` < `xhigh` < `max`, so `xhigh` and `max` are already above `high`) AND you are Sonnet or Opus.
If effort is `low` or `medium` (i.e. below `high`), you MUST show the recommendation prompt — regardless of model.
If you are not Sonnet or Opus, you MUST show the recommendation prompt — regardless of effort level.
Otherwise → use `AskUserQuestion`:
```json
{
"questions": [{
"question": "Planning benefits from consistent multi-domain reasoning.\n\nTo switch: cancel, run `/effort high` (and `/model sonnet` if on Haiku), then re-invoke.",
"header": "Effort check",
"options": [
{ "label": "Continue" },
{ "label": "Cancel — I'll switch first" }
],
"multiSelect": false
}]
}
```
If the user selects "Cancel — I'll switch first": output the switching commands and stop. Do not proceed with the skill.
## Step 0: Resolve Project Context
**Before loading specs, ensure project context is resolved:**
1. **Monorepo check:** Does `.groundwork.yml` exist at the repo root?
- If yes → Is `{{project_name}}` non-empty?
- If empty → Invoke `Skill(skill="groundwork:select-project")` to select a project, then restart this skill.
- If set → Project is `{{project_name}}`, specs at `{{specs_dir}}/`.
- If no → Continue (single-project repo).
2. **CWD mismatch check (monorepo only):**
- Skip if not in monorepo mode or if the project was just selected in item 1 above.
- If CWD is the repo root → fine, proceed.
- Check which project's path CWD falls inside (compare against all projects in `.groundwork.yml`).
- If CWD is inside the selected project's path → fine, proceed.
- If CWD is inside a different project's path → warn via `AskUserQuestion`:
> "You're working from `<cwd>` (inside **[cwd-project]**), but the selected Groundwork project is **[selected-project]** (`[selected-project-path]/`). What would you like to do?"
> - "Switch to [cwd-project]"
> - "Stay with [selected-project]"
If the user switches, invoke `Skill(skill="groundwork:select-project")`.
- If CWD doesn't match any project → proceed without warning (shared directory).
3. Proceed with the resolved project context. All `{{specs_dir}}/` paths will resolve to the correct location.
## Step 1: Detect Input Mode
Parse the input from the caller's conversation context. Three modes:
- **Task ID** (numeric like `4`, or full format like `TASK-004`): Set `mode=task`, `task_id=TASK-NNN` (zero-padded to 3 digits).
- **Blurb** (free text, no task ID): Set `mode=feature`, `blurb=<text>`.
- **Task ID + blurb** (both present): Set `mode=task+blurb`, `task_id=TASK-NNN`, `blurb=<text>`.
- **Neither** (no argument, no context): Output `RESULT: FAILURE | No task ID or feature description provided.` and stop.
## Step 2: Load Context (mode-dependent)
### Task ID mode (`mode=task` or `mode=task+blurb`)
1. **Locate task file:**
- Single file: `{{specs_dir}}/tasks.md`
- Directory: `{{specs_dir}}/tasks/`
Search for `### TASK-NNN:` pattern.
**Error:** Task not found → Output `RESULT: FAILURE | TASK-NNN not found in {{specs_dir}}/tasks/` and stop.
2. **Read task definition** — only the `### TASK-NNN:` section (goal, action items, acceptance criteria, dependencies, status). Do NOT read full specs/architecture/design files.
3. **Validate task is workable:**
- Status `Complete` → Output `RESULT: FAILURE | TASK-NNN is already Complete.` and stop.
- Blocked by incomplete tasks → Output `RESULT: FAILURE | TASK-NNN is blocked by: [list].` and stop.
4. **Verify spec paths exist** (use Glob, not Read):
- `{{specs_dir}}/product_specs.md` or `{{specs_dir}}/product_specs/`
- `{{specs_dir}}/architecture.md` or `{{specs_dir}}/architecture/`
- `{{specs_dir}}/design_system.md`
- Tasks file (already found above)
**If specs missing:** Report which are missing and suggest running `/groundwork:design-product` or `/groundwork:design-architecture` first. In runner mode, return `RESULT: FAILURE` instead of asking. Otherwise use `AskUserQuestion` to confirm proceeding without them.
**If design system missing:** Proceed without it.
5. Set `identifier=TASK-NNN`, `branch_prefix=task`.
### Blurb mode (`mode=feature`)
1. **Load existing specs** (check for and read if they exist):
- `{{specs_dir}}/product_specs.md` (or `{{specs_dir}}/product_specs/` directory) → `PRD_CONTEXT`
- `{{specs_dir}}/architecture.md` (or `{{specs_dir}}/architecture/` directory) → `ARCHITECTURE_CONTEXT`
- `{{specs_dir}}/design_system.md` → `DESIGN_CONTEXT`
For each, check single file first, then directory. If a directory, aggregate all `.md` files.
If none exist, that's fine — proceed without them.
2. **Clarify requirements:** Call `Skill(skill="groundwork:understanding-feature-requests")`
Do NOT attempt to gather requirements yourself. The skill handles this.
If existing specs were loaded, provide them as context so the clarification skill can:
- Detect contradictions with existing PRD requirements
- Identify overlap with existing features
- Understand architectural constraints
Follow the skill to gather: problem being solved, target user/persona, expected outcome, edge cases and scope boundaries. Continue until requirements are clear and internally consistent.
3. **Generate feature identifier:**
- Format: `FEATURE-<slug>`
- Slug rules: lowercase, hyphen-separated, 2-4 words max, derived from core functionality
- Examples: "Add user login" → `FEATURE-user-login`, "Export reports to PDF" → `FEATURE-pdf-export`
4. Set `identifier=FEATURE-<slug>`, `branch_prefix=feature`.
## Step 3: Spawn Plan Agent
Spawn a Plan agent with mode-appropriate context:
### Task ID mode
```
Agent(
subagent_type="Plan",
description="Plan TASK-NNN",
prompt="Plan the implementation of a task.
TASK DEFINITION:
[Paste the task section read in Step 2 — goal, action items, acceptance criteria]
[If mode=task+blurb, add:]
ADDITIONAL CONTEXT FROM USER:
[blurb text]
SPEC PATHS (read these yourself for full context):
- Product specs: [path or 'not found']
- Architecture: [path or 'not found']
- Design system: [path or 'not found']
- Tasks file: [path]
CONSTRAINTS:
- 1. Work happens in an isolated git worktree (.worktrees/TASK-NNN)
+ 1. Work happens in an isolated git worktree — the plan must instruct the implementer to resolve it with `node ${CLAUDE_PLUGIN_ROOT}/lib/worktree-identity.js <task-id>` and use the returned `path` and `branch` verbatim (never hand-derived `.worktrees/TASK-NNN` paths)
2. Implementation must follow TDD — write failing tests first, then make them pass
3. Plan covers implementation only — validation and merge are handled separately by the caller
4. If a design system is present, the plan must reference design tokens, colors, and component patterns from it
"
)
```
### Blurb mode (feature)
```
Agent(
subagent_type="Plan",
description="Plan FEATURE-slug",
prompt="Plan the implementation of a feature.
FEATURE DEFINITION:
- Identifier: [FEATURE-slug]
- Description: [1-2 sentence summary from clarification]
REQUIREMENTS:
[Bulleted list of clarified requirements]
ACCEPTANCE CRITERIA:
[Bulleted list of acceptance criteria]
OUT OF SCOPE:
[Bulleted list of exclusions, or 'None specified']
SPEC PATHS (read these yourself for full context):
- Product specs: [path or 'not found']
- Architecture: [path or 'not found']
- Design system: [path or 'not found']
CONSTRAINTS:
- 1. Work happens in an isolated git worktree (.worktrees/FEATURE-slug)
+ 1. Work happens in an isolated git worktree — the plan must instruct the implementer to resolve it with `node ${CLAUDE_PLUGIN_ROOT}/lib/worktree-identity.js <feature-id>` and use the returned `path` and `branch` verbatim (never hand-derived `.worktrees/FEATURE-slug` paths)
2. Implementation must follow TDD — write failing tests first, then make them pass
3. Plan covers implementation only — validation and merge are handled separately by the caller
4. If a design system is present, the plan must reference design tokens, colors, and component patterns from it
"
)
```
**Validate the plan:**
- [ ] Plan states work happens in a worktree
- [ ] Plan includes TDD cycle
**If ANY unchecked:** Reject plan, state what's missing, re-invoke Plan agent.
## Step 4: Persist Plan
After the plan is validated, persist it to disk in the **same turn** as receiving the Plan agent's output:
1. Create the plans directory and ensure it's gitignored:
```bash
mkdir -p {{plans_dir}}
grep -qxF '.groundwork-plans/' .gitignore 2>/dev/null || printf '.groundwork-plans/\n' >> .gitignore
```
`{{plans_dir}}` resolves inside the selected project's root (mirroring `{{specs_dir}}`), so overlapping identifiers across monorepo projects cannot collide. The `.gitignore` pattern is unanchored, so it covers plan directories at any project depth.
Set `plan_file_path={{plans_dir}}/{identifier}-plan.md` (substitute the actual identifier). One plan per identifier — re-running planning on the same identifier overwrites the previous plan, which is intentional. The `.gitignore` append is idempotent so it is safe to run on every invocation.
2. Use the `Write` tool to save the plan. Format the file as:
```markdown
# Implementation Plan: {identifier} [Title]
## Context
- Mode: task | feature | task+blurb
- Identifier: {identifier}
- Branch prefix: {branch_prefix}
- Specs dir: {{specs_dir}}
- Tasks path: {path to tasks file, or N/A for features}
## Requirements (blurb/feature mode only)
[Clarified requirements, acceptance criteria, out-of-scope — omit this section in task mode]
## Plan
<verbatim Plan agent output>
```
This is the **only** turn where the plan content appears in orchestrator context.
3. Output exactly:
```
RESULT: PLANNED | plan_file_path={plan_file_path} | identifier={identifier} | branch_prefix={branch_prefix}
```
4. Do NOT restate, summarize, or re-quote the plan in any subsequent turn. Refer to `plan_file_path` only.
**DO NOT proceed past this step. The caller handles implementation.**