Skip to main content

Task Design Best Practices

Well-designed tasks lead to better AI execution. This guide covers how to write effective tasks.

Task Anatomy

- id: implement-user-service
title: Implement user service
status: todo
phase: 2
depends_on: [create-user-model]
repo: ./repos/backend
worktree: feature/users
agent_name: claude-code
instructions: |
Create UserService in src/services/user.ts with:

Methods:
- createUser(data: CreateUserDTO): Promise<User>
- getUserById(id: string): Promise<User | null>
- updateUser(id: string, data: UpdateUserDTO): Promise<User>
- deleteUser(id: string): Promise<void>

Requirements:
- Use the existing DatabaseService for queries
- Validate email format before create/update
- Throw UserNotFoundError for missing users
- Add unit tests in tests/services/user.test.ts
acceptance_criteria:
- All methods are async and properly typed
- Email validation rejects invalid formats
- getUserById returns null (not throws) for missing
- deleteUser is idempotent
- Tests cover happy path and error cases

Writing Good IDs

Naming Convention

Use kebab-case with action-noun pattern:

# Good
id: create-user-model
id: implement-auth-service
id: add-rate-limiting
id: fix-token-expiry-bug

# Bad
id: task1
id: userStuff
id: do_the_thing

Unique and Descriptive

# Good - unique within project
id: create-user-model
id: create-order-model
id: create-payment-model

# Bad - too generic
id: create-model
id: create-model-2
id: create-model-3

Writing Instructions

Be Specific

# Bad - too vague
instructions: Create the user service.

# Good - detailed and actionable
instructions: |
Create UserService in src/services/user.ts.

Implement these methods:
1. createUser(data)
- Validate email format
- Hash password with bcrypt
- Insert into database
- Return user without password

2. getUserById(id)
- Query by primary key
- Return null if not found
- Exclude password from result

Include Context

instructions: |
Create the authentication middleware.

Context:
- JWT tokens use RS256 algorithm
- Public key is in config.jwt.publicKey
- Tokens have 'sub' claim with user ID

Implementation:
- Export authMiddleware function
- Verify token from Authorization header
- Attach user to req.user
- Return 401 for invalid/missing token

Reference existing middleware in src/middleware/logging.ts
for error handling pattern.

Specify Location

instructions: |
Create password hashing utilities.

File: src/utils/password.ts

Exports:
- hashPassword(plain: string): Promise<string>
- verifyPassword(plain: string, hash: string): Promise<boolean>

Tests: tests/utils/password.test.ts

Acceptance Criteria

Make Them Testable

# Bad - subjective
acceptance_criteria:
- Code is clean
- Works correctly

# Good - verifiable
acceptance_criteria:
- hashPassword returns 60-char bcrypt hash
- verifyPassword returns true for matching password
- verifyPassword returns false for wrong password
- Hashing takes > 100ms (cost factor working)
- Tests achieve 100% coverage

Cover Edge Cases

acceptance_criteria:
- Returns user for valid ID
- Returns null for non-existent ID
- Returns null for malformed ID (not UUID)
- Throws on database connection error
- Handles concurrent requests safely

Include Quality Checks

acceptance_criteria:
- No TypeScript errors
- ESLint passes with no warnings
- All tests pass
- No console.log statements
- Sensitive data not logged

Dependencies

Minimal Dependencies

Only depend on what you actually need:

# Good - specific dependency
- id: implement-login
depends_on: [create-auth-service] # Actually uses AuthService

# Bad - over-specified
- id: implement-login
depends_on:
- create-auth-service
- setup-database # Already done by auth-service
- configure-logging # Not related
- install-packages # Too basic

Parallel Opportunity

Design for parallel execution:

# Good - independent tasks can parallelize
- id: create-user-model
depends_on: []

- id: create-order-model
depends_on: []

- id: create-payment-model
depends_on: []

- id: implement-checkout
depends_on: [create-user-model, create-order-model, create-payment-model]

Avoid Chains

# Bad - forced sequential execution
- id: step-1
- id: step-2
depends_on: [step-1]
- id: step-3
depends_on: [step-2]
- id: step-4
depends_on: [step-3]

# Good - parallel where possible
- id: step-1a
- id: step-1b
- id: step-1c
- id: step-2
depends_on: [step-1a, step-1b, step-1c]

Task Size

Right-Sized Tasks

A good task is:

  • Completable in one session
  • Has clear start and end
  • Produces testable output
# Too small - trivial
- id: create-file
instructions: Create src/services/user.ts

# Too large - unclear scope
- id: implement-backend
instructions: Build the entire backend

# Right size
- id: implement-user-service
instructions: |
Create UserService with CRUD operations.
Include unit tests.

Splitting Large Tasks

If a task is too big, split it:

# Instead of one large task:
- id: implement-auth-system

# Split into focused tasks:
- id: implement-password-hashing
- id: implement-jwt-service
- id: implement-auth-endpoints
- id: implement-auth-middleware
- id: add-auth-tests

Phases

Logical Grouping

tasks:
# Phase 1: Data Layer
- id: create-user-model
phase: 1
- id: create-session-model
phase: 1

# Phase 2: Business Logic
- id: implement-auth-service
phase: 2
depends_on: [create-user-model, create-session-model]

# Phase 3: API
- id: create-auth-endpoints
phase: 3
depends_on: [implement-auth-service]

# Phase 4: Integration
- id: add-auth-to-frontend
phase: 4
depends_on: [create-auth-endpoints]

Phase Guidelines

PhasePurposeExamples
1FoundationModels, configs, setup
2Core LogicServices, utilities
3InterfaceAPIs, UI components
4IntegrationConnecting pieces
5PolishTests, docs, cleanup

Worktrees

Isolation Strategy

# Same feature = same worktree
- id: auth-models
worktree: feature/auth
- id: auth-service
worktree: feature/auth
- id: auth-endpoints
worktree: feature/auth

# Different feature = different worktree
- id: payment-models
worktree: feature/payments

Cross-Repo Coordination

# Matching worktree names across repos
- id: api-auth
repo: ./repos/api
worktree: feature/auth

- id: web-auth
repo: ./repos/web
worktree: feature/auth
depends_on: [api-auth]

Common Patterns

Create + Test Pattern

- id: implement-service
instructions: Create the service with all methods.

- id: test-service
depends_on: [implement-service]
instructions: Write comprehensive tests for the service.
validation_task_id: implement-service

Implement + Document Pattern

- id: create-api-endpoints
instructions: Implement REST endpoints.

- id: document-api
depends_on: [create-api-endpoints]
instructions: Update API documentation with new endpoints.

Refactor Pattern

- id: add-feature
instructions: Add new feature to existing code.

- id: refactor-for-feature
depends_on: [add-feature]
instructions: Clean up code affected by new feature.