310 lines
8.3 KiB
Markdown
310 lines
8.3 KiB
Markdown
# Task Granularity Standards
|
|
|
|
A task must be specific enough for execution without interpretation. Vague tasks cause agents to guess, leading to inconsistent results and rework.
|
|
|
|
## The Granularity Test
|
|
|
|
Ask: **Can an agent execute this task without making assumptions?**
|
|
|
|
If the answer requires "it depends" or "probably means", the task is too vague.
|
|
|
|
---
|
|
|
|
## Comparison Table
|
|
|
|
| Too Vague | Just Right |
|
|
|-----------|------------|
|
|
| "Add authentication" | "Add JWT auth with refresh rotation using jose library, store in httpOnly cookie, 15min access / 7day refresh" |
|
|
| "Create the API" | "Create POST /api/projects accepting {name, description}, validates name length 3-50 chars, returns 201 with project object" |
|
|
| "Style the dashboard" | "Add Tailwind classes to Dashboard.tsx: grid layout (3 cols on lg, 1 on mobile), card shadows, hover states on action buttons" |
|
|
| "Handle errors" | "Wrap API calls in try/catch, return {error: string} on 4xx/5xx, show toast via sonner on client" |
|
|
| "Add form validation" | "Add Zod schema to CreateProjectForm: name (3-50 chars, alphanumeric), description (optional, max 500 chars), show inline errors" |
|
|
| "Improve performance" | "Add React.memo to ProjectCard, useMemo for filtered list in Dashboard, lazy load ProjectDetails route" |
|
|
| "Fix the login bug" | "Fix login redirect loop: after successful login in auth.ts:45, redirect to stored returnUrl instead of always '/' " |
|
|
| "Set up the database" | "Create SQLite database at data/cw.db with migrations in db/migrations/, run via 'cw db migrate'" |
|
|
|
|
---
|
|
|
|
## Required Task Components
|
|
|
|
Every task MUST include:
|
|
|
|
### 1. Files
|
|
Exact paths that will be created or modified.
|
|
|
|
```yaml
|
|
files:
|
|
- src/components/Chat.tsx # create
|
|
- src/hooks/useChat.ts # create
|
|
- src/api/messages.ts # modify
|
|
```
|
|
|
|
### 2. Action
|
|
What to do, what to avoid, and WHY.
|
|
|
|
```yaml
|
|
action: |
|
|
Create Chat component with:
|
|
- Message list (virtualized for performance)
|
|
- Input field with send button
|
|
- Auto-scroll to bottom on new message
|
|
|
|
DO NOT:
|
|
- Implement WebSocket (separate task)
|
|
- Add typing indicators (Phase 2)
|
|
|
|
WHY: Core chat UI needed before real-time features
|
|
```
|
|
|
|
### 3. Verify
|
|
Command or check to prove completion.
|
|
|
|
```yaml
|
|
verify:
|
|
- command: "npm run typecheck"
|
|
expect: "No type errors"
|
|
- command: "npm run test -- Chat.test.tsx"
|
|
expect: "Tests pass"
|
|
- manual: "Navigate to /chat, see empty message list and input"
|
|
```
|
|
|
|
### 4. Done
|
|
Measurable acceptance criteria.
|
|
|
|
```yaml
|
|
done:
|
|
- "Chat component renders without errors"
|
|
- "Input accepts text and clears on submit"
|
|
- "Messages display in chronological order"
|
|
- "Tests cover send and display functionality"
|
|
```
|
|
|
|
---
|
|
|
|
## Task Types
|
|
|
|
### Type: auto
|
|
Agent executes autonomously.
|
|
|
|
```yaml
|
|
type: auto
|
|
files: [src/components/Button.tsx]
|
|
action: "Create Button component with primary/secondary variants using Tailwind"
|
|
verify: "npm run typecheck && npm run test"
|
|
done: "Button renders with correct styles for each variant"
|
|
```
|
|
|
|
### Type: checkpoint:human-verify
|
|
Agent completes, human confirms.
|
|
|
|
```yaml
|
|
type: checkpoint:human-verify
|
|
files: [src/pages/Dashboard.tsx]
|
|
action: "Implement dashboard layout with project cards"
|
|
verify: "Navigate to /dashboard after login"
|
|
prompt: "Does the dashboard match the design mockup?"
|
|
done: "User confirms layout is correct"
|
|
```
|
|
|
|
### Type: checkpoint:decision
|
|
Human makes choice that affects implementation.
|
|
|
|
```yaml
|
|
type: checkpoint:decision
|
|
prompt: "Which chart library should we use?"
|
|
options:
|
|
- recharts: "React-native, good for simple charts"
|
|
- d3: "More powerful, steeper learning curve"
|
|
- chart.js: "Lightweight, canvas-based"
|
|
affects: "All subsequent charting tasks"
|
|
```
|
|
|
|
### Type: checkpoint:human-action
|
|
Unavoidable manual step.
|
|
|
|
```yaml
|
|
type: checkpoint:human-action
|
|
prompt: "Please click the verification link sent to your email"
|
|
reason: "Cannot automate email client interaction"
|
|
continue_after: "User confirms email verified"
|
|
```
|
|
|
|
---
|
|
|
|
## Time Estimation
|
|
|
|
Tasks should fit within context budgets:
|
|
|
|
| Complexity | Context % | Wall Time | Example |
|
|
|------------|-----------|-----------|---------|
|
|
| Trivial | 5-10% | 2-5 min | Add a CSS class |
|
|
| Simple | 10-20% | 5-15 min | Add form field |
|
|
| Medium | 20-35% | 15-30 min | Create API endpoint |
|
|
| Complex | 35-50% | 30-60 min | Implement auth flow |
|
|
| Too Large | >50% | - | **SPLIT REQUIRED** |
|
|
|
|
---
|
|
|
|
## Splitting Large Tasks
|
|
|
|
When a task exceeds 50% context estimate, decompose:
|
|
|
|
### Before (Too Large)
|
|
```yaml
|
|
title: "Implement user authentication"
|
|
# This is 3+ hours of work, dozens of decisions
|
|
```
|
|
|
|
### After (Properly Decomposed)
|
|
```yaml
|
|
tasks:
|
|
- title: "Create users table with password hash"
|
|
files: [db/migrations/001_users.sql]
|
|
|
|
- title: "Add signup endpoint with Zod validation"
|
|
files: [src/api/auth/signup.ts]
|
|
depends_on: [users-table]
|
|
|
|
- title: "Add login endpoint with JWT generation"
|
|
files: [src/api/auth/login.ts]
|
|
depends_on: [users-table]
|
|
|
|
- title: "Create auth middleware for protected routes"
|
|
files: [src/middleware/auth.ts]
|
|
depends_on: [login-endpoint]
|
|
|
|
- title: "Add refresh token rotation"
|
|
files: [src/api/auth/refresh.ts, db/migrations/002_refresh_tokens.sql]
|
|
depends_on: [auth-middleware]
|
|
```
|
|
|
|
---
|
|
|
|
## Anti-Patterns
|
|
|
|
### Vague Verbs
|
|
**Bad:** "Improve", "Enhance", "Update", "Fix" (without specifics)
|
|
**Good:** "Add X", "Change Y to Z", "Remove W"
|
|
|
|
### Missing Constraints
|
|
**Bad:** "Add validation"
|
|
**Good:** "Add Zod validation: email format, password 8+ chars with number"
|
|
|
|
### Implied Knowledge
|
|
**Bad:** "Handle the edge cases"
|
|
**Good:** "Handle: empty input (show error), network failure (retry 3x), duplicate email (show message)"
|
|
|
|
### Compound Tasks
|
|
**Bad:** "Set up auth and create the user management pages"
|
|
**Good:** Two separate tasks with dependency
|
|
|
|
### No Success Criteria
|
|
**Bad:** "Make it work"
|
|
**Good:** "Tests pass, no TypeScript errors, manual verification of happy path"
|
|
|
|
---
|
|
|
|
## Examples by Domain
|
|
|
|
### API Endpoint
|
|
|
|
```yaml
|
|
title: "Create POST /api/projects endpoint"
|
|
files:
|
|
- src/api/projects/create.ts
|
|
- src/api/projects/schema.ts
|
|
|
|
action: |
|
|
Create endpoint accepting:
|
|
- name: string (3-50 chars, required)
|
|
- description: string (max 500 chars, optional)
|
|
|
|
Returns:
|
|
- 201: { id, name, description, createdAt }
|
|
- 400: { error: "validation message" }
|
|
- 401: { error: "Unauthorized" }
|
|
|
|
Use Zod for validation, drizzle for DB insert.
|
|
|
|
verify:
|
|
- "npm run test -- projects.test.ts"
|
|
- "curl -X POST /api/projects -d '{\"name\": \"Test\"}' returns 201"
|
|
|
|
done:
|
|
- "Endpoint creates project in database"
|
|
- "Validation rejects invalid input with clear messages"
|
|
- "Auth middleware blocks unauthenticated requests"
|
|
```
|
|
|
|
### React Component
|
|
|
|
```yaml
|
|
title: "Create ProjectCard component"
|
|
files:
|
|
- src/components/ProjectCard.tsx
|
|
- src/components/ProjectCard.test.tsx
|
|
|
|
action: |
|
|
Create card displaying:
|
|
- Project name (truncate at 30 chars)
|
|
- Description preview (2 lines max)
|
|
- Created date (relative: "2 days ago")
|
|
- Status badge (active/archived)
|
|
|
|
Props: { project: Project, onClick: () => void }
|
|
Use Tailwind: rounded-lg, shadow-sm, hover:shadow-md
|
|
|
|
verify:
|
|
- "npm run typecheck"
|
|
- "npm run test -- ProjectCard"
|
|
- "Storybook renders all variants"
|
|
|
|
done:
|
|
- "Card renders with all project fields"
|
|
- "Truncation works for long names"
|
|
- "Hover state visible"
|
|
- "Click handler fires"
|
|
```
|
|
|
|
### Database Migration
|
|
|
|
```yaml
|
|
title: "Create projects table"
|
|
files:
|
|
- db/migrations/003_projects.sql
|
|
- src/db/schema/projects.ts
|
|
|
|
action: |
|
|
Create table:
|
|
- id: TEXT PRIMARY KEY (uuid)
|
|
- user_id: TEXT NOT NULL REFERENCES users(id)
|
|
- name: TEXT NOT NULL
|
|
- description: TEXT
|
|
- status: TEXT DEFAULT 'active' CHECK (IN 'active', 'archived')
|
|
- created_at: INTEGER DEFAULT unixepoch()
|
|
- updated_at: INTEGER DEFAULT unixepoch()
|
|
|
|
Indexes: user_id, status, created_at DESC
|
|
|
|
verify:
|
|
- "cw db migrate runs without error"
|
|
- "sqlite3 data/cw.db '.schema projects' shows correct schema"
|
|
|
|
done:
|
|
- "Migration applies cleanly"
|
|
- "Drizzle schema matches SQL"
|
|
- "Indexes created"
|
|
```
|
|
|
|
---
|
|
|
|
## Checklist Before Creating Task
|
|
|
|
- [ ] Can an agent execute this without asking questions?
|
|
- [ ] Are all files listed explicitly?
|
|
- [ ] Is the action specific (not "improve" or "handle")?
|
|
- [ ] Is there a concrete verify step?
|
|
- [ ] Are done criteria measurable?
|
|
- [ ] Does estimated context fit under 50%?
|
|
- [ ] Are there no compound actions (split if needed)?
|