implement-plan Β· diff

v1.0.0 to v1.0.0

16 added, 44 removed. Audit B to B.

---
name: implement-plan
description:
"Implement approved technical plans from thoughts/shared/plans/. **ALWAYS use when** the user says
'implement the plan', 'start implementing', 'build from the plan', or wants to execute a
previously created implementation plan using TDD (Red-Green-Refactor). Supports team mode for
parallel implementation."
disable-model-invocation: false
allowed-tools: Read, Write, Edit, Grep, Glob, Task, TodoWrite, Bash
version: 1.0.0
---
# Implement Plan
- You are tasked with implementing an approved technical plan from `thoughts/shared/plans/`. These
- plans contain phases with specific changes and success criteria.
+ You are tasked with implementing an approved technical plan from `thoughts/shared/plans/`. These plans contain phases with specific changes and success criteria.
## Prerequisites
```bash
# Check project setup (thoughts, CLAUDE.md snippet, config)
if [[ -f "${CLAUDE_PLUGIN_ROOT}/scripts/check-project-setup.sh" ]]; then
"${CLAUDE_PLUGIN_ROOT}/scripts/check-project-setup.sh" || exit 1
fi
# Auto-discover most recent plan (workflow context + filesystem fallback)
RECENT_PLAN=""
if [[ -f "${CLAUDE_PLUGIN_ROOT}/scripts/workflow-context.sh" ]]; then
RECENT_PLAN=$("${CLAUDE_PLUGIN_ROOT}/scripts/workflow-context.sh" recent plans)
fi
if [[ -n "$RECENT_PLAN" ]]; then
echo "πŸ“‹ Auto-discovered recent plan: $RECENT_PLAN"
else
echo "⚠️ No recent plan found in workflow context or filesystem"
fi
```
## Session Tracking
```bash
SESSION_SCRIPT="${CLAUDE_PLUGIN_ROOT}/scripts/catalyst-session.sh"
if [[ -x "$SESSION_SCRIPT" ]]; then
CATALYST_SESSION_ID=$("$SESSION_SCRIPT" start --skill "implement-plan" \
--ticket "${TICKET_ID:-}" \
--workflow "${CATALYST_SESSION_ID:-}")
export CATALYST_SESSION_ID
"$SESSION_SCRIPT" phase "$CATALYST_SESSION_ID" "implementing" --phase 1
fi
```
## Initial Response
Auto-discovery has already run in Prerequisites above. Check its output and follow this priority:
1. **If user provided a plan path as parameter**: Use the provided path (user override). Skip to
Step 3.
2. **If no parameter provided AND Prerequisites output shows a discovered plan (πŸ“‹)**:
- Show user the discovered plan path
- Ask: "**Proceed with this plan?** [Y/n]"
- If yes: use it and skip to Step 3
- If no: proceed to option 3
3. **If no parameter AND Prerequisites shows no plan found (⚠️)**:
- List available plans from `thoughts/shared/plans/`
- Show most recent 5 plans with dates and ticket numbers
- Ask user which plan to implement
- Wait for user input with plan path
**STEP 3: Read and prepare**
Once you have a plan path:
- Read the plan completely (no limit/offset)
- Check for any existing checkmarks (- [x]) to see what's done
- Read the original ticket and all files mentioned in the plan
- **Extract ticket from plan frontmatter** (`source_ticket` field) and update Linear state
- to `stateMap.inProgress` from config using Linearis CLI (run `linearis issues usage` for syntax).
- If Linearis CLI is not available, skip silently and continue implementation.
- **Skip the status transition when `CATALYST_PHASE` is set** β€” under a phase agent
- (e.g. `phase-implement`, or this skill invoked as a sub-task from `phase-pr` /
- `phase-monitor-merge` during PR resolution / CI fix-up loops) the deterministic
- coordinator (CTL-558) owns the Linear status write-back. A direct write here
- would regress the ticket from `PR` back to `Implement`, producing operator-visible
- state flicker (CTL-601). Mirrors the gate in `create-pr/SKILL.md:227-232`.
+ to `stateMap.inProgress` from config using Linearis CLI (run `linearis issues usage` for syntax). If Linearis CLI is not available, skip silently and continue implementation. **Skip the status transition when `CATALYST_PHASE` is set** β€” under a phase agent (e.g. `phase-implement`, or this skill invoked as a sub-task from `phase-pr` / `phase-monitor-merge` during PR resolution / CI fix-up loops) the deterministic coordinator (CTL-558) owns the Linear status write-back. A direct write here would regress the ticket from `PR` back to `Implement`, producing operator-visible state flicker (CTL-601). Mirrors the gate in `create-pr/SKILL.md:227-232`.
- Think deeply about how the pieces fit together
- Create a todo list to track your progress
- Start implementing if you understand what needs to be done
## Implementation Philosophy
Plans are carefully designed, but reality can be messy. Your job is to:
- **Follow TDD: write tests before implementation code** in each phase
- Follow the plan's intent while adapting to what you find
- Implement each phase fully before moving to the next
- Verify your work makes sense in the broader codebase context
- Update checkboxes in the plan as you complete sections
### TDD Rhythm Per Phase
For each phase, follow **Red β†’ Green β†’ Refactor**:
1. **Red** β€” Write the tests specified in the plan's "Tests First" section. Run them to confirm they
fail.
2. **Green** β€” Implement the minimum code from the plan's "Implementation" section to make tests
- pass. Then **commit the Green result**, and only after that push the draft PR, so a mid-phase
- kill loses at most one Red→Green cycle:
+ pass. Then **commit the Green result**, and only after that push the draft PR, so a mid-phase kill loses at most one Red→Green cycle:
```bash implement-plan-commit-green
# CTL-1490 (Codex round-2, PR #2697): commit BEFORE the draft-pr-push block below β€”
# draft_pr_push (plugins/dev/scripts/lib/draft-pr.sh) is a pure `git push`; it commits
# nothing itself. Without a commit here, this push re-pushes whatever HEAD already
# had (the previous phase's/step's commit) and the just-written Green code sits
# uncommitted in the worktree only β€” a mid-phase kill after this point still loses
# it, defeating the "durable off-disk record" purpose the push exists for. Run
# after EVERY TDD Green step, same gate as the push below (phase-agent mode only;
# interactive runs skip so there's no surprise commit). Fail-open: never blocks the
# phase β€” an empty/failed commit here is not fatal, it just means the upcoming push
# has nothing new to carry (same durability gap as before this fix, not a regression).
if [[ -n "${CATALYST_PHASE:-}" ]]; then
# `git status --porcelain`, not `git diff`/`git diff --cached` alone β€” a
# Green step very often ADDS a new file (new test, new implementation
# module), which is untracked and invisible to both diff forms until
# staged. Checked BEFORE staging so an all-clean tree (nothing changed
# this Green step) skips straight through without an empty commit attempt.
if [[ -n "$(git status --porcelain -- . 2>/dev/null)" ]]; then
git add -A -- . ':!thoughts' 2>/dev/null || true
git -c core.hooksPath=/dev/null commit -m "wip(green): ${TICKET_ID:-${CATALYST_TICKET:-implement}} TDD green step" \
>/dev/null 2>&1 || true
fi
fi
```
```bash implement-plan-draft-pr-early
# CTL-783/CTL-1490: make the PR the durable off-disk work record from the FIRST commit.
# Run after EVERY TDD Green step: first run opens the draft PR, later runs just
# push (draft_pr_ensure is idempotent). Interactive runs (no CATALYST_PHASE)
# skip β€” no surprise pushes. Fail-open: never blocks the phase.
if [[ -n "${CATALYST_PHASE:-}" && -r "${CLAUDE_PLUGIN_ROOT}/scripts/lib/draft-pr.sh" ]]; then
# shellcheck source=/dev/null
source "${CLAUDE_PLUGIN_ROOT}/scripts/lib/draft-pr.sh"
if [[ "$(draft_pr_enabled)" == "true" ]]; then
draft_pr_push || true
draft_pr_ensure "main" "${TICKET_ID:-${CATALYST_TICKET:-}}" >/dev/null 2>&1 || true
fi
fi
```
3. **Refactor** β€” Clean up while keeping tests green. Apply any refactoring notes from the plan.
- This order is non-negotiable. If a phase doesn't have a "Tests First" section, write tests for the
- phase's expected behavior before implementing. The tests serve as executable acceptance criteria.
+ This order is non-negotiable. If a phase doesn't have a "Tests First" section, write tests for the phase's expected behavior before implementing. The tests serve as executable acceptance criteria.
- When things don't match the plan exactly, think about why and communicate clearly. The plan is your
- guide, but your judgment matters too.
+ When things don't match the plan exactly, think about why and communicate clearly. The plan is your guide, but your judgment matters too.
If you encounter a mismatch:
- STOP and think deeply about why the plan can't be followed
- Present the issue clearly:
```
Issue in Phase [N]:
Expected: [what the plan says]
Found: [actual situation]
Why this matters: [explanation]
How should I proceed?
```
## Verification Approach
**Within each phase (TDD cycle):**
- Write tests first β†’ run them β†’ confirm they fail (Red)
- Write implementation β†’ run tests β†’ confirm they pass (Green)
- Refactor if needed β†’ run tests β†’ confirm they still pass (Refactor)
**After completing a phase:**
- Run the full success criteria checks (usually `make check test` covers everything)
- Fix any issues before proceeding
- Update your progress in both the plan and your todos
- Check off completed items in the plan file itself using Edit
- **Check context usage** - monitor token consumption
- **Push + ensure the draft PR (phase-agent mode)** β€” The `implement-plan-draft-pr-early` block
- runs automatically after each Green step (see TDD Rhythm above; CTL-1490). Interactive
- `/catalyst-dev:implement-plan` runs skip it via the CATALYST_PHASE gate.
+ runs automatically after each Green step (see TDD Rhythm above; CTL-1490). Interactive `/catalyst-dev:implement-plan` runs skip it via the CATALYST_PHASE gate.
- Don't let verification interrupt your flow - batch full suite runs at natural stopping points. But
- always run the specific tests you wrote during each Red β†’ Green cycle.
+ Don't let verification interrupt your flow - batch full suite runs at natural stopping points. But always run the specific tests you wrote during each Red β†’ Green cycle.
## Context Management During Implementation
**Monitor context proactively throughout implementation**:
**After Each Phase**:
```
βœ… Phase {N} complete!
## πŸ“Š Context Status
Current usage: {X}% ({Y}K/{Z}K tokens)
{If >60%}:
⚠️ **Context Alert**: We're at {X}% usage.
**Recommendation**: Create a handoff before continuing to Phase {N+1}.
**Why?** Implementation accumulates context:
- File reads
- Code changes
- Test outputs
- Error messages
- Context clears ensure continued high performance
**Options**:
1. βœ… Create handoff and clear context (recommended)
- Use `/create-handoff` to generate properly formatted handoff
- Format: `thoughts/shared/handoffs/{ticket}/YYYY-MM-DD_HH-MM-SS_description.md`
- Includes timestamp for lexical sorting by recency
2. Continue to next phase (if close to completion)
**To resume**: Start fresh session, run `/implement-plan {plan-path}`
(The plan file tracks progress with checkboxes - you'll resume automatically)
{If <60%}:
βœ… Context healthy. Ready for Phase {N+1}.
```
**When to Warn**:
- After any phase if context >60%
- If context >70%, strongly recommend handoff
- If context >80%, STOP and require handoff
- If user is spinning on errors (3+ attempts), suggest context clear
**Educate About Phase-Based Context**:
- Explain that implementation is designed to work in chunks
- Each phase completion is a natural handoff point
- Plan file preserves progress across sessions
- Fresh context = fresh perspective on next phase
**Creating a Handoff**:
When recommending a handoff, guide the user:
1. Offer to create the handoff using `/create-handoff`
2. Or create a manual handoff following the timestamp convention
3. Handoff filename format: `thoughts/shared/handoffs/{ticket}/YYYY-MM-DD_HH-MM-SS_description.md`
4. Include: completed phases, next steps, key learnings, file references
5. Update plan file with checkboxes for completed work
## Quality Gates (After All Phases Complete)
- After all implementation phases pass, run quality gates before marking work as done. These gates
- catch issues that per-phase testing might miss.
+ After all implementation phases pass, run quality gates before marking work as done. These gates catch issues that per-phase testing might miss.
**Gate execution order:**
```
Quality Gates:
β”œβ”€β”€ 1. /validate-type-safety β†’ tsc + reward hacking scan + tsconfig check + tests + lint
β”œβ”€β”€ 2. /security-review β†’ scan for security vulnerabilities (built-in Claude Code skill)
β”œβ”€β”€ 3. code-reviewer agent β†’ style/guideline adherence check
└── 4. pr-test-analyzer agent β†’ test coverage verification
```
### Running the Gates
**Gate 1: Type Safety Validation**
- Invoke `/validate-type-safety`. This runs the full 5-step gate (type check, reward hacking scan,
- test inclusion, tests, lint). If it fails, fix issues and re-run before proceeding.
+ Invoke `/validate-type-safety`. This runs the full 5-step gate (type check, reward hacking scan, test inclusion, tests, lint). If it fails, fix issues and re-run before proceeding.
**Gate 2: Security Review**
- Invoke the built-in `/security-review` skill. Review findings and fix any vulnerabilities before
- proceeding.
+ Invoke the built-in `/security-review` skill. Review findings and fix any vulnerabilities before proceeding.
**Gate 3: Code Review**
Spawn the `code-reviewer` agent:
```
Agent(subagent_type="pr-review-toolkit:code-reviewer",
prompt="Review the uncommitted changes for adherence to project guidelines and style.")
```
Address any findings that violate project conventions.
**Gate 4: Test Coverage**
Spawn the `pr-test-analyzer` agent:
```
Agent(subagent_type="pr-review-toolkit:pr-test-analyzer",
prompt="Analyze test coverage for the uncommitted changes. Identify critical gaps.")
```
If critical gaps exist, write the missing tests.
### File Improvement Findings
- **Recording findings during implementation.** When a phase surfaces friction worth fixing β€”
- a bug noticed in adjacent code, a step that shouldn't need manual intervention, a gap in
- tooling β€” record it the moment it's observed:
+ **Recording findings during implementation.** When a phase surfaces friction worth fixing β€” a bug noticed in adjacent code, a step that shouldn't need manual intervention, a gap in tooling β€” record it the moment it's observed:
```bash
"${CLAUDE_PLUGIN_ROOT}/scripts/add-finding.sh" \
--title "Short imperative title" \
--body "Reproduction + expected + observed + any links" \
--skill implement-plan
```
- Findings go to a shared queue (under orchestrate/oneshot, that skill's queue; direct
- invocations get a per-session queue). The block below files the queue at end-of-run. It's a
- safety net: when `implement-plan` runs under `/orchestrate` or `/oneshot`, the parent's
- filing step drains the same queue first and this block finds an empty file:
+ Findings go to a shared queue (under orchestrate/oneshot, that skill's queue; direct invocations get a per-session queue). The block below files the queue at end-of-run. It's a safety net: when `implement-plan` runs under `/orchestrate` or `/oneshot`, the parent's filing step drains the same queue first and this block finds an empty file:
```bash
FEEDBACK="${CLAUDE_PLUGIN_ROOT}/scripts/file-feedback.sh"
CONSENT="${CLAUDE_PLUGIN_ROOT}/scripts/feedback-consent.sh"
FINDINGS_FILE="${CATALYST_FINDINGS_FILE:-.catalyst/findings/${CATALYST_SESSION_ID:-current}.jsonl}"
if [ -x "$FEEDBACK" ] && [ -f "$FINDINGS_FILE" ] && [ -s "$FINDINGS_FILE" ]; then
COUNT=$(wc -l < "$FINDINGS_FILE" | tr -d ' ')
if [ "$("$CONSENT" check)" != "granted" ] && [ -z "${CATALYST_AUTONOMOUS:-}" ] && [ -t 0 ]; then
read -r -p "File $COUNT improvement tickets now? [Y/n] " yn
case "$yn" in [Nn]*) : ;; *) "$CONSENT" grant >/dev/null ;; esac
fi
if [ "$("$CONSENT" check)" = "granted" ]; then
FILED=0
while IFS= read -r line; do
TITLE=$(jq -r '.title' <<<"$line")
BODY=$(jq -r '.body' <<<"$line")
SKILL=$(jq -r '.skill // "implement-plan"' <<<"$line")
RESULT=$("$FEEDBACK" --title "$TITLE" --body "$BODY" --skill "$SKILL" --json 2>/dev/null || true)
STATUS=$(jq -r '.status // "failed"' <<<"$RESULT")
if [ "$STATUS" = "filed" ]; then
ID=$(jq -r '.identifier // .url // ""' <<<"$RESULT")
echo " filed: $ID ($TITLE)"
FILED=$((FILED + 1))
fi
done < "$FINDINGS_FILE"
[ "$FILED" -eq "$COUNT" ] && rm -f "$FINDINGS_FILE"
fi
fi
```
### End Session Tracking
After all quality gates pass (or are skipped), end the session:
```bash
if [[ -n "${CATALYST_SESSION_ID:-}" && -x "$SESSION_SCRIPT" ]]; then
"$SESSION_SCRIPT" end "$CATALYST_SESSION_ID" --status done
fi
```
### Autofix Behavior
- For gates 1 and 2, attempt to fix issues automatically and re-run the gate. For gates 3 and 4,
- address findings and verify. If a gate fails after 2 fix attempts, report the remaining issues to
- the user and ask how to proceed.
+ For gates 1 and 2, attempt to fix issues automatically and re-run the gate. For gates 3 and 4, address findings and verify. If a gate fails after 2 fix attempts, report the remaining issues to the user and ask how to proceed.
### Skipping Quality Gates
- If the plan or user specifies `--skip-quality-gates`, skip this section entirely. Report that
- quality gates were skipped in the completion summary.
+ If the plan or user specifies `--skip-quality-gates`, skip this section entirely. Report that quality gates were skipped in the completion summary.
## If You Get Stuck
When something isn't working as expected:
- First, make sure you've read and understood all the relevant code
- Consider if the codebase has evolved since the plan was written
- Present the mismatch clearly and ask for guidance
Use sub-tasks sparingly - mainly for targeted debugging or exploring unfamiliar territory.
## Resuming Work
If the plan has existing checkmarks:
- Trust that completed work is done
- Pick up from the first unchecked item
- Verify previous work only if something seems off
- Remember: You're implementing a solution, not just checking boxes. Keep the end goal in mind and
- maintain forward momentum.
+ Remember: You're implementing a solution, not just checking boxes. Keep the end goal in mind and maintain forward momentum.
## Agent Team Mode (Optional)
When invoked with `--team` flag or when the plan spans 3+ independent domains:
### When to Use Team Mode
- Plan has phases that can be implemented in parallel
- Changes span distinct domains (frontend, backend, tests, infra)
- Each domain's changes don't overlap in files
### Team Structure
```
Lead (Opus) β€” Coordinates implementation
β”œβ”€β”€ Teammate 1 (Sonnet) β€” Frontend changes
β”‚ └── Can spawn subagents for research
β”œβ”€β”€ Teammate 2 (Sonnet) β€” Backend changes
β”‚ └── Can spawn subagents for research
└── Teammate 3 (Sonnet) β€” Test changes
└── Can spawn subagents for research
```
### Process
1. **Analyze plan phases** β€” Identify which phases can be parallelized
2. **Assign file ownership** β€” Each teammate gets distinct files (no overlap)
3. **Create task list** β€” Use TaskCreate with dependencies between phases
4. **Launch team** β€” Spawn teammates with focused instructions
5. **Review gates** β€” Lead reviews teammate work via approvePlan/rejectPlan
6. **Integration** β€” Lead verifies all changes work together
7. **Commit** β€” Single atomic commit or per-phase commits
### Important Constraints
- **File ownership is strict** β€” no two teammates edit the same file
- **Sequential phases stay sequential** β€” only parallelize truly independent work
- **Lead reviews all code** β€” use plan approval gates before proceeding
- **Fallback gracefully** β€” if agent teams unavailable, execute sequentially
## Linear Integration
State names (`stateMap.*`) come from the `linearis` skill's single-source transition table β€” not restated here.
If a ticket is detected (from plan document's `source_ticket` frontmatter or from context):
- **At implementation start** (Step 3): Update ticket status to `stateMap.inProgress` from config
using Linearis CLI (run `linearis issues usage` for syntax).
- **Skip the status transition when `CATALYST_PHASE` is set** β€” the deterministic coordinator
- (CTL-558) owns Linear write-back under phase agents. See the gate at Step 3 above for
- details. CTL-601 β€” without this gate, invoking this skill as a sub-task from another phase
- agent (typical in `phase-pr` / `phase-monitor-merge` resolution loops) regresses the ticket
- state to `Implement` and produces operator-visible flicker.
+ (CTL-558) owns Linear write-back under phase agents. See the gate at Step 3 above for details. CTL-601 β€” without this gate, invoking this skill as a sub-task from another phase agent (typical in `phase-pr` / `phase-monitor-merge` resolution loops) regresses the ticket state to `Implement` and produces operator-visible flicker.
- If Linearis CLI not available, skip silently and continue implementation