From PRD-Driven Context Engineering
Implements EPICs with test-first development, continuous SoT updates, and code traceability. Activates on build/implementation requests.
How this skill is triggered — by the user, by Claude, or both
Slash command
/prd-ce:prd-v07-implementation-loopThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Position in workflow: v0.7 Test Planning → **v0.7 Implementation Loop** → v0.8 Release
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:
status/devgraph.json) — the @implements/@verifies tags you write are harvested into bridge edges, producing the as-built layer that readiness scores (implementation_coverage, architecture_conformance) and the HeartBeat visualizer renders. Schema: docs/DEVELOPMENT_GRAPH.md.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
Each pass leaves a trace: step 5 tags code with @implements, and those tags are exactly what the Development Graph harvests — so this loop literally produces the pulse the HeartBeat visualizer shows (built → 🟢, unbuilt → 🔴, drifted → 🔴). Rerun readiness.py run after a Context Window to watch implementation_coverage move.
┌─────────────────────────────────────────────────────────────┐
│ 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: 'test@example.com', password: 'ValidPass123!' });
expect(response.status).toBe(201);
expect(response.body.data.email).toBe('test@example.com');
// 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:
status/devgraph.json rebuilt; implementation_coverage ≥ threshold (no scoped spec unbuilt, no unbuilt_specs cap) and no architecture_conformance violationsImplementation 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 |
| Readiness (v0.7) | Development Graph build-vs-blueprint | implementation_coverage + architecture_conformance from status/devgraph.json |
| HeartBeat | The Development Graph as a live pulse | Renders built / unbuilt / drifted across the codebase |
| 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.mdnpx claudepluginhub mattgierhart/prd-driven-context-engineering --plugin prd-ceBreaks v0.6 technical specs into context-window-sized EPICs with dependencies, pre-load budgets, and acceptance criteria for v0.7 build execution.
Guides specification-driven AI development workflows by breaking projects into 2-4 hour sessions using 13 commands like /plansession, /implement, /validate, and /phasebuild.