.claude/skills/prd-v07-implementation-loop/SKILL.md
Execute implementation within EPICs following test-first development, continuous SoT updates, and code traceability during PRD v0.7 Build Execution. Triggers on requests to start building, implement an epic, begin coding, or when user asks "start building", "implement epic", "coding", "development", "build execution", "implementation", "write code". Consumes EPIC- (context), TEST- (acceptance criteria). Updates existing IDs and creates code. Outputs working code with @implements traceability tags.
npx skillsauth add mattgierhart/PRD-driven-context-engineering prd-v07-implementation-loopInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Position in workflow: v0.7 Test Planning → v0.7 Implementation Loop → v0.8 Release
This skill requires prior work from v0.7 Epic Scoping and v0.7 Test Planning:
This skill assumes EPIC- and TEST- entries are complete, with all upstream IDs fully specified.
This skill updates/creates:
All implementation outputs are code and live SoT, not confidence-based. They are:
Example code with traceability (from EPIC-01):
// @implements API-001 (POST /users)
// @see BR-001 (email uniqueness), BR-002 (password requirements), DBT-010 (users table)
export async function createUser(req: Request, res: Response) {
// @implements BR-002 (password validation)
const passwordResult = validatePassword(req.body.password);
if (!passwordResult.valid) {
return res.status(400).json({
error: { code: 'INVALID_PASSWORD', message: passwordResult.errors[0] }
});
}
// @implements BR-001 (email uniqueness check)
const existingUser = await db.users.findByEmail(req.body.email);
if (existingUser) {
return res.status(409).json({
error: { code: 'EMAIL_EXISTS', message: 'User already exists' }
});
}
// @implements DBT-010 (users table creation)
const user = await db.users.create({
email: req.body.email,
passwordHash: await hashPassword(req.body.password),
createdAt: new Date(),
});
return res.status(201).json({ data: { id: user.id, email: user.email } });
}
Example Session State update (EPIC-01 mid-session):
## 1. Session State (The "Brain Dump")
- **Last Action**: Completed API-001–003 implementation; all tests passing. Password reset flow complete.
- **Stopping Point**: src/api/auth/reset.ts:85 — need to add rate limiting per BR-005
- **Next Steps**:
1. Add rate limiter middleware to password reset endpoint (BR-005)
2. Update TEST-012 to verify rate limiting (5 attempts per hour)
3. Run full test suite for EPIC-01
4. Move to API-005 (verify email endpoint)
- **Blockers**: None
- **Context**: Decided to implement rate limiting in middleware rather than at function level for reuse across endpoints. Using `express-rate-limit`.
- **Decisions Made**: POST /reset-password should return 429 with retry-after header when limit exceeded (API-001 error response spec). Using Redis for distributed rate limit tracking.
### Resume Instructions
> 1. Load EPIC-01 context (done in previous session)
> 2. Create new branch session if needed
> 3. Begin with Step 3 above (add rate limiter middleware)
> 4. When complete, run: `npm run test -- tests/api/auth.test.ts`
> 5. Update this Session State with new stopping point
┌─────────────────────────────────────────────────────────────┐
│ 1. LOAD CONTEXT │
│ Read EPIC, referenced IDs, Session State │
│ → Can you state this session's goal in one sentence │
│ with specific IDs? If not, clarify before proceeding. │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 2. SELECT FOCUS │
│ Choose a Context Window from Phase C │
│ → Pick the smallest scope that yields a verifiable │
│ outcome. One TEST- passing > three half-implemented. │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 3. WRITE TEST (Red) │
│ Implement TEST- entry, watch it fail │
│ → Assertions must derive from TEST-/API-/BR- specs. │
│ Missing detail = spec gap — flag it, don't guess. │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 4. WRITE CODE (Green) │
│ Implement to pass test │
│ → Minimum code to pass. No TEST- requires it? Don't │
│ build it. No speculative features or error handling. │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 5. TAG CODE │
│ Add // @implements ID comments │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 6. UPDATE SoT │
│ Update specs/ if implementation reveals changes │
│ → Only update specs YOUR implementation changed. │
│ Don't "improve" adjacent specs you happened to read. │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 7. VALIDATE │
│ Run tests, check traceability │
│ → Name the specific TEST- IDs that pass. "It works" │
│ is not validation — cite IDs. │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 8. UPDATE SESSION STATE │
│ Write to Session State before stopping │
└──────────────────────────┬──────────────────────────────────┘
│
└──────────► REPEAT until EPIC complete
Before ending ANY session, update the EPIC Session State section:
## 0. Session State (The "Brain Dump")
- **Last Action**: [What was just completed]
- **Stopping Point**: [Exact file:line or test failure]
- **Next Steps**: [Exact instructions for next session]
- **Context**: [Key decisions, blockers, open questions]
Good Example:
- **Last Action**: Completed API-002 (login endpoint), all tests passing
- **Stopping Point**: src/api/auth/login.ts:47 — need to add rate limiting
- **Next Steps**:
1. Add rate limiter middleware per BR-005
2. Update TEST-008 to verify rate limiting
3. Move to API-003 (logout)
- **Context**: Decided to use Supabase's built-in rate limiting rather than custom middleware
Assumptions & Ambiguities: During implementation, log assumptions and ambiguities in the EPIC's structured table (see EPIC template). This makes "Think Before Coding" persistent across sessions.
Example row during implementation:
| 3 | API-001 | ASSUMPTION | Response includes created_at field | Spec says "user object" but doesn't enumerate fields | Implemented with created_at; needs spec update |
Bad Example:
- **Last Action**: Working on auth
- **Stopping Point**: Somewhere in the code
- **Next Steps**: Continue
- **Context**: N/A
Every major code unit MUST declare which ID it implements:
// @implements API-001 (Create User endpoint)
// @see BR-001 (Email uniqueness)
// @see DBT-001 (Users table)
export async function createUser(data: CreateUserInput): Promise<User> {
// Implementation...
}
| Code Element | Tag Pattern | Example |
|--------------|-------------|---------|
| API handler | @implements API-XXX | API endpoint function |
| Business logic | @implements BR-XXX | Validation, rules |
| Database model | @implements DBT-XXX | Schema definition |
| UI component | @implements SCR-XXX | Screen component |
| Test file | @tests TEST-XXX | Test implementation |
| Cross-reference | @see [ID] | Related specification |
// @implements API-001 (POST /users)
// @see BR-001 (email uniqueness)
// @see BR-002 (password requirements)
// @see DBT-001 (users table)
export async function createUser(req: Request, res: Response) {
// @implements BR-002
const passwordResult = validatePassword(req.body.password);
if (!passwordResult.valid) {
return res.status(400).json({ error: passwordResult.errors });
}
// @implements BR-001
const existingUser = await db.users.findByEmail(req.body.email);
if (existingUser) {
return res.status(409).json({ error: { code: 'EMAIL_EXISTS' } });
}
// @implements DBT-001
const user = await db.users.create({
email: req.body.email,
passwordHash: await hashPassword(req.body.password),
});
return res.status(201).json({ data: user });
}
The Source of Truth (specs/) must stay in sync with implementation:
| Situation | Action | |-----------|--------| | Spec matches implementation | No update needed | | Implementation reveals new constraint | Add BR- entry to specs/ | | API shape changed during build | Update API- entry | | New field needed in schema | Update DBT- entry | | Spec was wrong/incomplete | Fix spec AND code | | Discovered edge case | Add to spec, add TEST- |
Rule: Update specs during implementation, not "later."
Counter-rule: Only update specs that YOUR current work directly affects. If you notice that API-020 has a typo while working on API-001, log it in the Assumptions & Ambiguities table for a future session. Do not fix it now. Unplanned spec changes create invisible scope creep and break traceability for any parallel work.
Work through Context Windows sequentially within an EPIC:
## 4. Context Windows
### Window 1: Database Schema ← CURRENT
- [x] Create users table migration
- [x] Add RLS policies
- [ ] Create sessions table
- [ ] Verify schema in studio
### Window 2: API Endpoints
- [ ] Implement API-001 (signup)
- [ ] Implement API-002 (login)
- [ ] Implement API-003 (logout)
### Window 3: UI Integration
- [ ] Build signup form
- [ ] Build login form
- [ ] Add auth state management
// tests/api/users.test.ts
// @tests TEST-001
describe('POST /api/users', () => {
it('creates user with valid data', async () => {
const response = await request(app)
.post('/api/users')
.send({ email: '[email protected]', password: 'ValidPass123!' });
expect(response.status).toBe(201);
expect(response.body.data.email).toBe('[email protected]');
// Test FAILS because endpoint doesn't exist yet
});
});
Constraint: If the test requires details not in the TEST- spec (response field names, error codes, status codes), look them up in API-/BR- specs. Do not invent them. If the spec lacks the detail, log an AMBIGUITY in the Assumptions & Ambiguities table before proceeding.
Write the minimum code to make the test pass:
// @implements API-001
export async function createUser(req, res) {
const user = await db.users.create(req.body);
return res.status(201).json({ data: user });
}
Constraint: "Minimum code" means literally what makes this one test go green. No additional validation, no extra error handling, no service layer abstractions unless a TEST- requires that behavior. This feels uncomfortable. That is correct.
Now improve the code while tests stay green:
// @implements API-001
// @see BR-001, BR-002
export async function createUser(req, res) {
const validated = validateUserInput(req.body); // Add validation
if (!validated.ok) return res.status(400).json(validated.error);
const user = await userService.create(validated.data); // Extract service
return res.status(201).json({ data: user });
}
Constraint: Refactor only code you just wrote. Do not "improve" existing code that was already working. Do not extract abstractions unless you have 3+ concrete uses (not hypothetical future uses). Do not touch files outside the current focus area. See references/behavioral-examples.md for detailed good/bad comparisons.
If you cannot articulate what this session accomplishes in terms of specific TEST- or API- IDs, you are not ready to build. Refine the goal until it names IDs.
For each Context Window:
@implements tags present in all major code unitsfeat(EPIC-XX): [summary]| Signal | Action | |--------|--------| | Can't write test | Requirement unclear → revisit spec | | Test keeps failing | Implementation wrong OR spec wrong → investigate | | Need code outside EPIC scope | Wrong EPIC boundaries → re-scope | | Lost context mid-session | Load Session State, verify EPIC context | | Spec and code diverging | Stop, update spec to match reality | | Test is testing implementation | Rewrite to test behavior | | Writing code not required by any TEST- | Speculative — remove it, or write the TEST- first | | Editing files outside current Context Window | Scope creep — note in Assumptions & Ambiguities table, defer |
| Anti-Pattern | Signal | Fix | |--------------|--------|-----| | Test-after | Code written, then "add tests" | Write TEST- implementation first | | Spec drift | Code diverges from specs/ | Update SoT during implementation | | Missing traceability | Code has no @implements tags | Add tags as you write | | Session amnesia | No Session State update | ALWAYS update before stopping | | Context switching | Jumping between EPICs | Finish one EPIC before starting another | | One-shot building | No iteration, just code dump | Follow the loop: test → code → tag | | Orphaned code | Code not linked to any ID | Every function serves an ID | | Speculative error handling | try/catch for scenarios no TEST- covers | Remove it. If the scenario matters, write TEST- first. | | Drive-by improvements | "While I was here, I also improved..." | Revert non-essential changes. Note in Assumptions & Ambiguities table. | | Vague completion claims | "Auth is working" without naming IDs | Always cite IDs: "TEST-001 through TEST-005 pass. API-001, API-002 verified." |
Before marking EPIC complete:
Implementation Loop outputs feed into:
| Consumer | What It Uses | Example | |----------|--------------|---------| | v0.8 Release | Completed EPICs ready for deployment | All TEST- pass, SoT current | | Code Review | @implements tags for context | Reviewer knows which BR- to check | | Future Sessions | Session State for continuity | Resume exactly where left off | | Maintenance | Traceability for debugging | "Which BR- does this code implement?" |
references/examples.mdreferences/traceability.mdreferences/session-state.mdreferences/behavioral-examples.mdtools
Make technology decisions for every product capability by discovering existing assets, evaluating vendor-aligned options, and categorizing as Reuse/Extend/Build/Buy/Integrate/Research during PRD v0.5 Red Team Review. Handles both greenfield and brownfield contexts. Triggers on "tech stack", "build or buy?", "what technologies?", "technical decisions", "what do we reuse?", "existing stack", "vendor constraint", "IBM-first", "what tools do we need?", "evaluate solutions", "select tech stack". Consumes FEA- (features), SCR- (screens), RISK- (constraints). Outputs TECH- entries with decisions, rationale, and cross-references. Feeds v0.6 Architecture Design.
development
Define success criteria and tracking setup for launch during PRD v0.9 Go-to-Market. Triggers on requests to define launch metrics, set up tracking, or when user asks "how do we measure launch success?", "launch KPIs", "tracking setup", "success criteria", "analytics", "launch goals". Outputs KPI- entries specialized for launch measurement.
development
Define go-to-market strategy including launch plan, messaging, channels, and timing during PRD v0.9 Go-to-Market. Triggers on requests to plan launch, define GTM strategy, or when user asks "how do we launch?", "go-to-market", "launch plan", "marketing strategy", "messaging", "launch channels", "GTM". Outputs GTM- entries with launch plan components.
development
Establish channels and processes for capturing and processing post-launch feedback during PRD v0.9 Go-to-Market. Triggers on requests to set up feedback systems, capture user input, or when user asks "how do we collect feedback?", "feedback loop", "user research", "post-launch feedback", "customer feedback", "NPS", "voice of customer". Outputs CFD- entries specialized for post-launch feedback capture.