Implement a user story end-to-end: plan, branch, test-drive, review, and accept
โฑ ~25 min ยท Hands-on
You'll take a single user story from sprint backlog to accepted โ using test-driven development, continuous integration, structured commits, pull requests, and formal acceptance.
Sprint 1 is planned. You're starting with US-001: Add a new task. The acceptance criteria are clear: users can create tasks with a title and optional description, validation rejects empty titles, and each task gets a unique ID. You'll build this feature using the full TDD workflow.
Before anything else, create a properly named feature branch linked to the story:
/agile-code-branch
๐ฟ Branch created: feature/US-001-add-task
Source: main
Convention: feature/[STORY-ID]-[short-description]
Story link: US-001 โ Add a new task
Switched to branch 'feature/US-001-add-task'
Instead of manually running git checkout -b, /agile-code-branch automatically applies your project's branch naming convention (detected during setup), links the branch to the story, and ensures you're branching from the correct base branch. No typos, no convention drift.
Before writing any code, break the story into implementation phases:
/agile-story-plan
๐ Implementation Plan: US-001 โ Add a new task
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Phase 1: Data Model + Repository
โข Create Task model (id, title, description, status, createdAt)
โข Create TaskRepository with insert() and findById()
โข Migration: create tasks table
Files: src/models/task.js, src/repositories/task-repository.js, migrations/
Phase 2: Service Layer
โข Create TaskService with createTask()
โข Input validation (title required, max 200 chars)
โข Business logic: set status="pending", generate timestamp
Files: src/services/task-service.js, src/validators/task-validator.js
Phase 3: API Endpoint
โข POST /api/v1/tasks endpoint
โข Request/response serialization
โข Error handling integration
Files: src/controllers/task-controller.js, src/routes/task-routes.js
Estimated phases: 3
Confidence: 9/10
Risk: Low โ standard CRUD, well-known patterns
โ
Plan approved. Ready to implement.
The plan must reach 9/10 confidence before implementation starts. If confidence is below 9, the AI re-plans with more context โ it never proceeds on hope. Here, 9/10 means the scope is clear, the patterns are known, and there are no unknowns.
This is the heart of the implementation. Run TDD for each phase:
/agile-code-tdd
The AI follows the Red-Green-Refactor cycle:
๐ด RED โ Writing failing test...
// test/services/task-service.test.js
describe('TaskService', () => {
describe('createTask', () => {
it('should_create_task_when_valid_input', async () => {
const input = { title: 'Buy groceries', description: 'Milk, eggs, bread' };
const task = await taskService.createTask(input);
expect(task.id).toBeDefined();
expect(task.title).toBe('Buy groceries');
expect(task.description).toBe('Milk, eggs, bread');
expect(task.status).toBe('pending');
expect(task.createdAt).toBeInstanceOf(Date);
});
it('should_reject_when_title_missing', async () => {
await expect(taskService.createTask({ description: 'no title' }))
.rejects.toThrow('Title is required');
});
it('should_reject_when_title_empty_string', async () => {
await expect(taskService.createTask({ title: '' }))
.rejects.toThrow('Title is required');
});
});
});
Running tests...
โ should_create_task_when_valid_input โ FAILED (TaskService not found)
โ should_reject_when_title_missing โ FAILED (TaskService not found)
โ should_reject_when_title_empty_string โ FAILED (TaskService not found)
3 failing โ This is expected. Tests define what we want to build.
๐ข GREEN โ Implementing to make tests pass...
// src/models/task.js
class Task {
constructor({ id, title, description, status, createdAt }) {
this.id = id;
this.title = title;
this.description = description || null;
this.status = status || 'pending';
this.createdAt = createdAt || new Date();
}
}
// src/validators/task-validator.js
function validateTaskInput(data) {
if (!data.title || data.title.trim() === '') {
throw new AppError('Title is required', 400);
}
if (data.title.length > 200) {
throw new AppError('Title must be 200 characters or less', 400);
}
}
// src/services/task-service.js
class TaskService {
constructor(taskRepository) {
this.taskRepository = taskRepository;
}
async createTask(data) {
validateTaskInput(data);
const task = new Task({ title: data.title, description: data.description });
return this.taskRepository.insert(task);
}
}
Running tests...
โ should_create_task_when_valid_input โ PASSED
โ should_reject_when_title_missing โ PASSED
โ should_reject_when_title_empty_string โ PASSED
3 passing โ All green!
๐ต REFACTOR โ Improving structure without changing behavior...
Refactoring: Extracted validation logic to TaskValidator class
โข Moved from inline function to class with static methods
โข Added validate() entry point for extensibility
โข No test changes needed โ all 3 still pass โ
Running tests after refactor...
โ should_create_task_when_valid_input โ PASSED
โ should_reject_when_title_missing โ PASSED
โ should_reject_when_title_empty_string โ PASSED
โ
TDD cycle complete for Phase 1+2. 3 tests passing.
RED: Write a test that describes what you want. It fails because the code doesn't exist yet. GREEN: Write the minimum code to make the test pass. REFACTOR: Improve the code structure while keeping all tests green. This cycle repeats for every behavior.
Before committing, verify everything passes:
/agile-code-ci
๐ Running CI pipeline locally...
Build:
โ
Compilation successful (0 errors, 0 warnings)
Tests:
โ
12 tests passing (3 unit + 5 integration + 4 edge cases)
โ
Coverage: 94% lines, 100% branches (threshold: 80%)
Lint:
โ
ESLint: 0 errors, 0 warnings
โ
Prettier: all files formatted
Security:
โ
npm audit: 0 vulnerabilities
โ
No hardcoded secrets detected
โ
All CI checks pass. Safe to commit.
Always run /agile-code-ci before committing. Catching a lint error or failing test here saves a failed CI build, a broken PR, and wasted review time. The command runs the same checks your CI pipeline runs.
Create a conventional commit with a clear message:
/agile-code-commit
๐ฆ Commit created:
feat(tasks): add task creation with validation
- Task model with id, title, description, status, createdAt
- TaskService.createTask() with input validation
- TaskRepository.insert() with PostgreSQL integration
- POST /api/v1/tasks endpoint
- 12 tests covering happy path and edge cases
Refs: US-001
Open a PR linked to the story:
/agile-code-pr
๐ Pull Request created: #14
Title: feat(tasks): add task creation with validation
Branch: feature/US-001-add-task โ main
Story: US-001
Description:
Implements the "Add a new task" user story. Users can create tasks
via POST /api/v1/tasks with title (required) and description (optional).
Input validation rejects empty/missing titles.
Changes:
+6 files, 247 additions
src/models/task.js
src/validators/task-validator.js
src/services/task-service.js
src/repositories/task-repository.js
src/controllers/task-controller.js
src/routes/task-routes.js
Test coverage: 94%
CI status: โ
All checks passing
Reviewers: @lead (auto-assigned)
The reviewer examines the PR and provides structured feedback:
/agile-code-pr-review
๐ Code Review โ PR #14
โโโโโโโโโโโโโโโโโโโโโโโ
Findings:
๐ก S2 โ task-service.js:15 โ Parameter naming
Rename `data` to `taskPayload` for clarity
Suggestion: async createTask(taskPayload) { ... }
๐ต S3 โ task-controller.js:8 โ Documentation
Add JSDoc to the controller method describing
request body shape and response format
โ
Architecture: Follows 3-layer pattern correctly
โ
Tests: Comprehensive, covers edge cases
โ
Security: No injection risks, input validated
โ
Conventions: Naming, imports, error handling all match project style
Verdict: CHANGES REQUESTED (2 minor items)
---
After fixes applied:
๐ Re-review โ PR #14
โ
S2 fix verified โ parameter renamed to taskPayload
โ
S3 fix verified โ JSDoc added
Verdict: โ
APPROVED by @lead
๐ด S1: Blocker โ must fix (security, data loss, crashes). ๐ก S2: Should fix โ code quality issues. ๐ต S3: Nice to have โ style, documentation. S1 always blocks merge. S2 and S3 are at the author's discretion but should be addressed.
With the PR approved, merge the feature branch into main:
/agile-code-merge
๐ Merge โ PR #14
โโโโโโโโโโโโโโโโโโโ
Pre-merge checks:
โ
PR approved by @lead
โ
CI passing on branch
โ
No merge conflicts
โ
Branch up to date with main
Merging: feature/US-001-add-task โ main
Strategy: squash merge (project convention)
Merge complete.
Branch feature/US-001-add-task deleted (was 3a7f2c1).
โ
PR #14 merged to main.
/agile-code-merge verifies all pre-merge conditions (approval, CI status, conflicts), applies the merge strategy configured for your project, and cleans up the feature branch. It prevents merging a PR that hasn't passed review or CI.
Walk through every DoD criterion to confirm the story is truly done:
/agile-story-dod
๐ Definition of Done Checklist โ US-001
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
All acceptance criteria met (3/3 scenarios pass)
โ
Code reviewed and approved by @lead
โ
All tests passing (12/12)
โ
Test coverage above threshold (94% > 80%)
โ
No lint errors or warnings
โ
No security vulnerabilities
โ
API documentation updated
โ
Conventional commit message
โ
PR linked to story US-001
โ
Branch merged to main
DoD result: โ
ALL CRITERIA MET (10/10)
The product owner verifies each acceptance criterion against the working software:
/agile-story-accept
๐ฏ Story Acceptance โ US-001: Add a new task
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
AC 1: Given valid title and description โ task created with status "pending"
Test: POST /api/v1/tasks {"title":"Buy groceries","description":"Milk, eggs"}
Result: 201 Created, status="pending", ID assigned
โ
PASS
AC 2: Given missing title โ 400 error returned
Test: POST /api/v1/tasks {"description":"no title"}
Result: 400 Bad Request, message="Title is required"
โ
PASS
AC 3: Given empty string title โ 400 error returned
Test: POST /api/v1/tasks {"title":""}
Result: 400 Bad Request, message="Title is required"
โ
PASS
Verdict: โ
ACCEPTED by @po
Story status: US-001 โ DONE
You've just taken a story from backlog to accepted using 10 commands. Every step has a clear purpose: create the branch, plan the work, prove it works (TDD), verify quality (CI + review), merge cleanly, confirm completeness (DoD), and get sign-off (accept).
In TDD, what do you write FIRST?