--- name: incremental-implementation description: Delivers changes incrementally. Use when implementing any feature or change that touches more than one file. Use when you're about to write a large amount of code at once, or when a task feels too big to land in one step. --- # Incremental Implementation ## Overview Build in thin vertical slices — implement one piece, test it, verify it, then expand. Avoid implementing an entire feature in one pass. Each increment should leave the system in a working, testable state. This is the execution discipline that makes large features manageable. Each increment ends at a **user review gate**, not an auto-commit. The agent presents a standard summary and waits for explicit approval before starting the next slice. Staging and committing are the user's responsibility — the agent never runs `git add` or `git commit` on its own. ## When to Use - Implementing any multi-file change - Building a new feature from a task breakdown - Refactoring existing code - Any time you're tempted to write more than ~100 lines before testing **When NOT to use:** Single-file, single-function changes where the scope is already minimal. ## The Increment Cycle ``` ┌───────────────────────────────────────────────────┐ │ │ │ Implement ─→ Test ─→ Verify ─→ Request Review │ │ ▲ │ │ │ │ ▼ │ │ Revise ◄── (changes requested) ── Gate │ │ │ │ │ (approved) ───┘ │ │ ▼ │ │ Next slice │ │ │ └───────────────────────────────────────────────────┘ ``` For each slice: 1. **Implement** the smallest complete piece of functionality 2. **Test** — run the test suite (or write a test if none exists) 3. **Verify** — confirm the slice works as expected (tests pass, build succeeds, manual check) 4. **Request review** — present the Standard Slice Summary (below) and ask the user to confirm before moving to the next slice. Use the `AskUserQuestion` tool if available; otherwise ask in chat and wait for explicit confirmation. Do **not** stage or commit — the user handles git operations manually after approval. See `git-workflow-and-versioning` for the atomic-commit guidance the user should follow when committing approved slices. 5. **Move to the next slice** only after explicit approval — carry forward, don't restart ## Standard Slice Summary When requesting review, present the slice in this exact shape so the user can scan quickly: - **Slice N: ``** - **Files changed:** bulleted list, each as `path:line-range` with a 3–6 word note - **What it does:** 1–2 sentences describing the behavior delivered - **How it was verified:** tests run, build status, manual checks performed - **Risks / things to double-check:** anything non-obvious, assumptions made, edge cases skipped - **Next slice (if approved):** one-line preview of what comes next Keep it tight. The summary is a review aid, not a report. ## Requesting Approval Prefer the `AskUserQuestion` tool with these options: - **Approve & continue** — slice is accepted; agent proceeds to the next slice (changes remain unstaged for the user to commit) - **Request changes** — user will describe what to change; agent revises within the same slice, re-summarizes, and re-asks - **Compact & continue** *(pi only, when the `compact-and-continue` extension is installed)* — call `request_compaction` with a self-contained `continuationPrompt` summarizing the remaining slices; the turn terminates, pi compacts context, then auto-resumes from the continuation prompt - **Stop here** — end the session without modifying git state If the `request_compaction` tool is not registered (e.g. running outside pi, or the extension is not installed), omit "Compact & continue" — the other three options are the universal fallback. If `AskUserQuestion` is not available, ask the same question in chat and **wait** — do not proceed on silence or ambiguous responses. On "Request changes", revise inside the current slice and re-present the summary. On "Stop here", leave the working tree untouched and end. ## Slicing Strategies ### Vertical Slices (Preferred) Build one complete path through the stack: ``` Slice 1: Create a task (DB + API + basic UI) → Tests pass, user can create a task via the UI Slice 2: List tasks (query + API + UI) → Tests pass, user can see their tasks Slice 3: Edit a task (update + API + UI) → Tests pass, user can modify tasks Slice 4: Delete a task (delete + API + UI + confirmation) → Tests pass, full CRUD complete ``` Each slice delivers working end-to-end functionality. ### Contract-First Slicing When backend and frontend need to develop in parallel: ``` Slice 0: Define the API contract (types, interfaces, OpenAPI spec) Slice 1a: Implement backend against the contract + API tests Slice 1b: Implement frontend against mock data matching the contract Slice 2: Integrate and test end-to-end ``` ### Risk-First Slicing Tackle the riskiest or most uncertain piece first: ``` Slice 1: Prove the WebSocket connection works (highest risk) Slice 2: Build real-time task updates on the proven connection Slice 3: Add offline support and reconnection ``` If Slice 1 fails, you discover it before investing in Slices 2 and 3. ## Implementation Rules ### Rule 0: Simplicity First Before writing any code, ask: "What is the simplest thing that could work?" After writing code, review it against these checks: - Can this be done in fewer lines? - Are these abstractions earning their complexity? - Would a staff engineer look at this and say "why didn't you just..."? - Am I building for hypothetical future requirements, or the current task? ``` SIMPLICITY CHECK: ✗ Generic EventBus with middleware pipeline for one notification ✓ Simple function call ✗ Abstract factory pattern for two similar components ✓ Two straightforward components with shared utilities ✗ Config-driven form builder for three forms ✓ Three form components ``` Three similar lines of code is better than a premature abstraction. Implement the naive, obviously-correct version first. Optimize only after correctness is proven with tests. ### Rule 0.5: Scope Discipline Touch only what the task requires. Do NOT: - "Clean up" code adjacent to your change - Refactor imports in files you're not modifying - Remove comments you don't fully understand - Add features not in the spec because they "seem useful" - Modernize syntax in files you're only reading If you notice something worth improving outside your task scope, note it — don't fix it: ``` NOTICED BUT NOT TOUCHING: - src/utils/format.ts has an unused import (unrelated to this task) - The auth middleware could use better error messages (separate task) → Want me to create tasks for these? ``` ### Rule 1: One Thing at a Time Each increment changes one logical thing. Don't mix concerns: **Bad:** One commit that adds a new component, refactors an existing one, and updates the build config. **Good:** Three separate commits — one for each change. ### Rule 2: Keep It Compilable After each increment, the project must build and existing tests must pass. Don't leave the codebase in a broken state between slices. ### Rule 3: Feature Flags for Incomplete Features If a feature isn't ready for users but you need to merge increments: ```typescript // Feature flag for work-in-progress const ENABLE_TASK_SHARING = process.env.FEATURE_TASK_SHARING === 'true'; if (ENABLE_TASK_SHARING) { // New sharing UI } ``` This lets you merge small increments to the main branch without exposing incomplete work. ### Rule 4: Safe Defaults New code should default to safe, conservative behavior: ```typescript // Safe: disabled by default, opt-in export function createTask(data: TaskInput, options?: { notify?: boolean }) { const shouldNotify = options?.notify ?? false; // ... } ``` ### Rule 5: Rollback-Friendly Each increment should be independently revertable: - Additive changes (new files, new functions) are easy to revert - Modifications to existing code should be minimal and focused - Database migrations should have corresponding rollback migrations - Avoid deleting something in one commit and replacing it in the same commit — separate them Rollback safety now depends on the user committing promptly after approval. If the user defers committing across multiple approved slices, they accept the risk of a larger uncommitted diff — the agent should still not stage or commit on their behalf. ## Working with Agents When directing an agent to implement incrementally: ``` "Let's implement Task 3 from the plan. Start with just the database schema change and the API endpoint. Don't touch the UI yet — we'll do that in the next increment. After implementing, run `npm test` and `npm run build` to verify nothing is broken, then present the Standard Slice Summary and wait for my approval before the next slice. Do not stage or commit — I'll handle git manually after reviewing." ``` Be explicit about what's in scope and what's NOT in scope for each increment. ## Increment Checklist After each increment, verify: - [ ] The change does one thing and does it completely - [ ] All existing tests still pass (`npm test`) - [ ] The build succeeds (`npm run build`) - [ ] Type checking passes (`npx tsc --noEmit`) - [ ] Linting passes (`npm run lint`) - [ ] The new functionality works as expected - [ ] The Standard Slice Summary was presented to the user - [ ] Explicit user approval was received before starting the next slice - [ ] The agent did not run `git add`, `git commit`, `git reset`, or `git restore` during this slice (whatever the user staged or committed between slices is preserved as-is) **Note:** Run each verification command after a change that could affect it. After a successful run, don't repeat the same command unless the code has changed since — re-running on unchanged code adds no information. ## Common Rationalizations | Rationalization | Reality | |---|---| | "I'll test it all at the end" | Bugs compound. A bug in Slice 1 makes Slices 2-5 wrong. Test each slice. | | "It's faster to do it all at once" | It *feels* faster until something breaks and you can't find which of 500 changed lines caused it. | | "These changes are too small to commit separately" | Small commits are free. Large commits hide bugs and make rollbacks painful. | | "I'll add the feature flag later" | If the feature isn't complete, it shouldn't be user-visible. Add the flag now. | | "This refactor is small enough to include" | Refactors mixed with features make both harder to review and debug. Separate them. | | "I'll just stage it to make their life easier" | Don't. The user explicitly controls staging and commits. Do not run any git state-changing command — and do not "tidy up" by unstaging or resetting what the user staged between slices. | | "They didn't answer but it's obviously fine, I'll continue" | No. Silence is not approval. Wait for an explicit response before starting the next slice. | | "Let me run the build command again just to be sure" | After a successful run, repeating the same command adds nothing unless the code has changed since. Run it again after subsequent edits, not as reassurance. | ## Red Flags - More than 100 lines of code written without running tests - Multiple unrelated changes in a single increment - "Let me just quickly add this too" scope expansion - Skipping the test/verify step to move faster - Build or tests broken between increments - Starting the next slice without explicit user approval - Staging or committing changes on the user's behalf - Unstaging, resetting, restoring, or stashing changes the user staged or committed between slices ("enforcing" an unstaged working tree is not the agent's job) - Building abstractions before the third use case demands it - Touching files outside the task scope "while I'm here" - Creating new utility files for one-time operations - Running the same build/test command twice in a row without any intervening code change ## Verification After completing all increments for a task: - [ ] Each increment was individually tested and approved by the user - [ ] The full test suite passes - [ ] The build is clean - [ ] The feature works end-to-end as specified - [ ] The agent performed no git state changes during the task (no `git add`, `git commit`, `git reset`, `git restore`, `git stash`, etc.) — whatever the user staged or committed between slices is preserved ## See Also Per-increment verification is the local check. Before declaring a task done, apply the project-wide Definition of Done as the final gate, the standing bar every increment clears regardless of the task. See `references/definition-of-done.md`.