---
name: fp-new-feature
description: Drive a new feature through the full fastpace lifecycle — planning, spec, write-tests, implement, run-tests, document, create-pr, push, extract-learnings. Enforces approval gates from fastpace.config.yaml and persists state to fastpace/watch-cards/ so the feature resumes cleanly across sessions and across models. Triggers on /fp-new-feature "<feature description>".
---

# fp-new-feature

The flagship lifecycle skill. Drives a feature from idea to merged PR through 9 strictly-ordered phases with approval gates, persistent state, and durable artifacts. Any session (any model, any engineer) can resume where this one left off by reading the watch card alone.

## Invocation

```
/fp-new-feature "<short feature description>"
```

The description **must be quoted** — it's parsed as a single argument and used to derive the feature slug (`add credit card validation` → `add-credit-card-validation`). If the user omits quotes, ask them to re-invoke with quotes rather than guessing where the description ends.

**Resume invocation:**
```
/fp-new-feature <slug>
```

If a watch card `fastpace/watch-cards/<slug>.json` exists, load it and resume from its `current_phase` — **do not start over**.

## Preflight

1. `fastpace/fastpace.config.yaml` must exist. If missing, abort with: "Run `fastpace` in your terminal first."
2. `fastpace/context/architecture.md` should exist. If missing, suggest `/fp-discover` but don't block — user may intend a greenfield feature.
3. Read `fastpace.config.yaml` `phases` section. Memorize the approval role per phase.
4. If a watch card for this slug exists:
   - Print its current state + phase progress block.
   - Ask: "Resume from `<current_phase>`? (y/n). If n, tell me what changed so I can update the card."
5. Determine `branch` and `base_branch`:
   - Branch: `feat/<slug>` unless user overrides.
   - Base: current branch if it's a protected branch (per config), else the default branch (`git symbolic-ref refs/remotes/origin/HEAD` → `main` / `master`).
   - Check `guardrails.require_branch_before_changes`: if true and we're on a protected branch, create the feature branch *before* any code phase.

## The 9 phases

| # | Phase | What produces | Gate (default) |
|---|-------|---------------|----------------|
| 1 | `planning` | `fastpace/docs/prd/<slug>.md` (brief or full per risk) | developer |
| 2 | `spec` | `fastpace/docs/erd/<slug>.md` | team_lead |
| 3 | `write-tests` | Failing unit + integration tests | developer |
| 4 | `implement` | Code to make tests pass | developer |
| 5 | `run-tests` | Full green test suite | developer |
| 6 | `document` | README / inline / API docs diffs | developer |
| 7 | `create-pr` | PR draft (title + body from ERD) | developer |
| 8 | `push` | branch pushed + PR opened | team_lead |
| 9 | `extract-learnings` | `fastpace/learnings-inbox/` drafts for human review | skip |

Actual gates come from `fastpace.config.yaml`. Config can only *lower* the bar, never remove gates 2 and 8 (spec + push) from requiring at least developer approval.

## Watch card schema

Create / update `fastpace/watch-cards/<slug>.json` after every phase transition — **not only at the end**. If the user ^C's, the card must still be accurate.

```json
{
  "id": "<slug>",
  "name": "<human feature name>",
  "branch": "feat/<slug>",
  "base_branch": "main",
  "risk": "low | medium | high",
  "status": "in-flight | blocked | completed",
  "created_at": "<iso>",
  "updated_at": "<iso>",
  "current_phase": "planning | spec | write-tests | implement | run-tests | document | create-pr | push | extract-learnings",
  "completed_phases": ["planning", "spec"],
  "progress": { "done": 2, "total": 9, "pct": 22 },
  "artifacts": {
    "prd_path": "fastpace/docs/prd/<slug>.md",
    "erd_path": "fastpace/docs/erd/<slug>.md",
    "plan_path": "fastpace/exec-plans/<slug>.json",
    "pr_url": null
  },
  "approvals": {
    "planning": { "role": "developer", "approver": "<user>", "at": "<iso>" },
    "spec": { "role": "team_lead", "approver": "<user>", "at": "<iso>" }
  },
  "review_findings": [],
  "notes": []
}
```

**This card is load-bearing.** It's the resume contract between sessions.

## Risk classification

Before phase 1, classify the feature:

- **high** — touches auth, payments, data migrations, irreversible external side-effects, protected branches.
- **medium** — non-trivial business logic, new endpoints, new dependencies.
- **low** — UI tweaks, copy changes, internal tooling.

Risk affects:
- High → stricter gates (escalate any `developer` gate to `team_lead`).
- High → spec phase must include an ADR pointer if any substantive decision is made.

## How to display progress

At the start of every phase, and whenever you prompt for approval, print this block *exactly*:

```
  planning  ✓  spec  ✓  write tests  ✓  implement ▸  run tests  document  PR  push
  ████████████████████████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒  implement · 62%   3 of 9
```

Rules:
- **Horizontal chip row** of 8 phases (the `extract-learnings` phase is post-PR and omitted from this row).
- Completed phases prefixed with `✓`; current suffixed with `▸`.
- Bar is 48 chars wide; `█` = completed fraction, `▒` = remaining.
- Right-side label: `<phase> · <pct>%   <done> of 9`.

This mirrors the dashboard's In-flight features view and reads correctly in any terminal.

## Approval gate protocol

Before moving from phase N to N+1:

1. Look up the required role from `fastpace.config.yaml` `phases.<phase-key>`.
2. If `skip`: proceed silently (but log in `audit.log`).
3. Otherwise ask the user: "Approval for `<phase>` requires `<role>` per config. Approve? (y / n / skip-with-reason)."
4. Record in watch card `approvals.<phase>`.
5. Never proceed on a blank/ambiguous response. Re-prompt.

## Per-phase expectations

### 1. planning
- If risk is low: 4-sentence brief is fine.
- If medium/high: produce a proper PRD (lean on `/fp-write-prd`-style sections — but you're writing, not delegating).
- Output: `fastpace/docs/prd/<slug>.md`.

### 2. spec
- Produce an ERD. Cite context per `/fp-prd-to-erd` conventions.
- If the ERD conflicts with a prior decision, stop and suggest `/fp-write-adr` before proceeding.
- Output: `fastpace/docs/erd/<slug>.md`. No code written in this phase.

### 3. write-tests
- Write unit + integration tests that codify the ERD's acceptance criteria.
- Tests must fail. Run them; confirm they fail for the *right* reason (not a syntax error).
- Never weaken tests to make them pass.

### 4. implement
- Make the tests pass — minimum code. Don't add beyond the spec.
- If you find yourself writing something not anticipated by the spec, stop and update the spec first.

### 5. run-tests
- Full test suite, not just the new tests. Must be green.
- If unrelated tests fail, fix them; that's part of the feature.

### 6. document
- Update README / API docs / inline comments — only where a reader would need them.
- Never add "what the code does" comments. Only "why" or non-obvious invariants.

### 7. create-pr
- Draft PR title: match commit style (conventional if configured).
- Draft PR body: pull from ERD. Include a checklist mapping acceptance criteria → commits.
- Check `guardrails.require_pr_description` — body cannot be empty.

### 8. push
- **Never push without explicit user confirmation.** Guardrails can lower the bar but never remove this.
- `git push -u origin <branch>`. If target is protected, refuse.
- `gh pr create` if available; otherwise print the PR creation URL.
- Save `pr_url` to the watch card.

### 9. extract-learnings
- Invoke `/fp-extract-learnings` with the slug. It drafts candidates to `fastpace/learnings-inbox/` for human approval.
- Emit zero drafts if nothing surprising happened. That's a valid outcome.
- Mark watch card `status: completed` only after this phase.

## Hard rules

- **Spec is the new code.** No implementation until the spec phase is approved.
- **Tests before implementation.** Every phase-4 diff must be preceded by a phase-3 test file in the same PR.
- **Never bypass a gate.** Config can change roles; it cannot remove the gates at phases 2 (spec) and 8 (push).
- **Never push or open a PR without explicit approval.** Even if config says `auto_push: true` — that flag is for CI, not interactive sessions.
- **Update the watch card after every phase.** If you crash after phase 3 implementation, the card must already reflect phase 3 done, 4 in progress.
- **Never rewrite `decisions.md` or `learnings.md`.** Append-only. Use `/fp-remember` or `/fp-write-adr`.
- **Respect guardrails in `fastpace.config.yaml`.** If `require_tests: true` and you haven't written tests, don't advance phases.
- **If resuming and the branch doesn't exist** (someone deleted it), stop: "Branch `<name>` is gone. Was this merged? Start over, or recreate?"

## Error recovery

If any phase fails mid-way:

1. Save the partial state to the watch card with `status: blocked` and a `notes[]` entry describing what failed.
2. Report to the user: what was attempted, what failed, what they should do.
3. Do not attempt to auto-recover. The user chooses.

## Exit criteria

- Watch card at `fastpace/watch-cards/<slug>.json` exists and reflects the final state.
- If completed: `status: completed`, all 9 phases in `completed_phases`, PR URL present.
- If paused: `status: in-flight`, current phase clearly set, next command echoed back to user.
- Phase progress block printed at the final state.
