Files
Codewalkers/docs/tasks.md
2026-02-07 00:33:12 +01:00

11 KiB

Tasks Module

Beads-inspired task management optimized for multi-agent coordination. Unlike beads (Git-distributed JSONL), this uses centralized SQLite for simplicity since all agents share the same workspace.

Design Rationale

Why Not Just Use Beads?

Beads solves a different problem: distributed task tracking across forked repos with zero coordination. We don't need that:

  • All Workers operate in the same workspace under one cw server
  • SQLite is the single source of truth
  • tRPC exposes task queries directly to agents and dashboard
  • No merge conflicts, no Git overhead

Core Agent Problem Solved

Agents need to answer: "What should I work on next?"

The ready query solves this: tasks that are open with all dependencies closed. Combined with priority ordering, agents can self-coordinate without human intervention.


Data Model

Task Entity

Field Type Description
id TEXT Primary key. Hash-based (e.g., tsk-a1b2c3) or UUID
parent_id TEXT Optional. References parent task for hierarchies
initiative_id TEXT Optional. Links to Initiatives module
phase_id TEXT Optional. Links to initiative phase (for grouped approval)
project_id TEXT Optional. Scopes task to a project
title TEXT Required. Short task name
description TEXT Optional. Markdown-formatted details
type TEXT task (default), epic, subtask
status TEXT open, in_progress, blocked, closed
priority INTEGER 0=critical, 1=high, 2=normal (default), 3=low
assigned_to TEXT Agent/worker ID currently working on this
assigned_at INTEGER Unix timestamp when assigned
metadata TEXT JSON blob for extensibility
created_at INTEGER Unix timestamp
updated_at INTEGER Unix timestamp
closed_at INTEGER Unix timestamp when closed
closed_reason TEXT Why/how the task was completed

Task Dependencies

Field Type Description
task_id TEXT The task that is blocked
depends_on TEXT The task that must complete first
type TEXT blocks (default), related

Task History

Field Type Description
id INTEGER Auto-increment primary key
task_id TEXT The task that changed
field TEXT Which field changed
old_value TEXT Previous value
new_value TEXT New value
changed_by TEXT Agent/user ID
changed_at INTEGER Unix timestamp

SQLite Schema

CREATE TABLE tasks (
  id TEXT PRIMARY KEY,
  parent_id TEXT REFERENCES tasks(id),
  initiative_id TEXT,
  phase_id TEXT,
  project_id TEXT,

  title TEXT NOT NULL,
  description TEXT,
  type TEXT NOT NULL DEFAULT 'task' CHECK (type IN ('task', 'epic', 'subtask')),

  status TEXT NOT NULL DEFAULT 'open' CHECK (status IN ('open', 'in_progress', 'blocked', 'closed')),
  priority INTEGER NOT NULL DEFAULT 2 CHECK (priority BETWEEN 0 AND 3),

  assigned_to TEXT,
  assigned_at INTEGER,

  metadata TEXT,

  created_at INTEGER NOT NULL DEFAULT (unixepoch()),
  updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
  closed_at INTEGER,
  closed_reason TEXT
);

CREATE TABLE task_dependencies (
  task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
  depends_on TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
  type TEXT NOT NULL DEFAULT 'blocks' CHECK (type IN ('blocks', 'related')),
  PRIMARY KEY (task_id, depends_on),
  CHECK (task_id != depends_on)
);

CREATE TABLE task_history (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
  field TEXT NOT NULL,
  old_value TEXT,
  new_value TEXT,
  changed_by TEXT,
  changed_at INTEGER NOT NULL DEFAULT (unixepoch())
);

CREATE INDEX idx_tasks_status ON tasks(status);
CREATE INDEX idx_tasks_priority ON tasks(priority);
CREATE INDEX idx_tasks_assigned ON tasks(assigned_to);
CREATE INDEX idx_tasks_project ON tasks(project_id);
CREATE INDEX idx_tasks_initiative ON tasks(initiative_id);
CREATE INDEX idx_tasks_phase ON tasks(phase_id);
CREATE INDEX idx_task_history_task ON task_history(task_id);

-- The critical view for agent work discovery
-- Tasks are ready when: open, no blocking deps, and phase approved (if linked)
CREATE VIEW ready_tasks AS
SELECT t.* FROM tasks t
LEFT JOIN initiative_phases p ON t.phase_id = p.id
WHERE t.status = 'open'
  AND (t.phase_id IS NULL OR p.status IN ('approved', 'in_progress'))
  AND NOT EXISTS (
    SELECT 1 FROM task_dependencies d
    JOIN tasks dep ON d.depends_on = dep.id
    WHERE d.task_id = t.id
      AND d.type = 'blocks'
      AND dep.status != 'closed'
  )
ORDER BY t.priority ASC, t.created_at ASC;

Status Workflow

     ┌──────────────────────────────────────┐
     │                                      │
     ▼                                      │
  [open] ──claim──▶ [in_progress] ──done──▶ [closed]
     │                    │
     │                    │ blocked
     │                    ▼
     └───────────── [blocked] ◀─────unblock───┘
Transition Trigger Notes
openin_progress Agent claims task Sets assigned_to, assigned_at
in_progressclosed Work completed Sets closed_at, closed_reason
in_progressblocked External dependency Manual or auto-detected
blockedopen Blocker resolved Clears assignment
openclosed Cancelled/won't do Direct close without work

CLI Reference

All commands under cw task subcommand.

Core Commands

Command Description
cw task ready List tasks ready for work (open + no blockers)
cw task list [--status STATUS] [--project ID] List tasks with filters
cw task show <id> Show task details + history
cw task create <title> [-p PRIORITY] [-d DESC] Create new task
cw task update <id> [--status STATUS] [--priority P] Update task fields
cw task close <id> [--reason REASON] Mark task complete

Dependency Commands

Command Description
cw task dep add <task> <depends-on> Task blocked by another
cw task dep rm <task> <depends-on> Remove dependency
cw task dep tree <id> Show dependency graph

Assignment Commands

Command Description
cw task assign <id> <agent> Assign task to agent
cw task unassign <id> Release task
cw task mine List tasks assigned to current agent

Output Flags (global)

Flag Description
--json Output as JSON (for agent consumption)
--quiet Minimal output (just IDs)

Agent Workflow

Standard loop for Workers:

1. cw task ready --json
2. Pick highest priority task from result
3. cw task update <id> --status in_progress
4. Do the work
5. cw task close <id> --reason "Implemented X"
6. Loop to step 1

If cw task ready returns empty, the agent's work is done.


Integration Points

With Initiatives

  • Tasks can link to an initiative via initiative_id
  • When initiative is approved, tasks are generated from its technical concept
  • Closing all tasks for an initiative signals initiative completion

With Orchestrator

  • Orchestrator queries ready_tasks view to dispatch work
  • Assignment tracked to prevent double-dispatch
  • Orchestrator can bulk-create tasks from job definitions

With Workers

  • Workers claim tasks via cw task update --status in_progress
  • Worker ID stored in assigned_to
  • On worker crash, Supervisor can detect stale assignments and reset

tRPC Procedures

// Suggested tRPC router shape
task.list(filters)      // → Task[]
task.ready(projectId?)  // → Task[]
task.get(id)            // → Task | null
task.create(input)      // → Task
task.update(id, input)  // → Task
task.close(id, reason)  // → Task
task.assign(id, agent)  // → Task
task.history(id)        // → TaskHistory[]
task.depAdd(id, dep)    // → void
task.depRemove(id, dep) // → void
task.depTree(id)        // → DependencyTree

Task Granularity Standards

A task must be specific enough for execution without interpretation. Vague tasks cause agents to guess, leading to inconsistent results.

Quick Reference

Too Vague Just Right
"Add authentication" "Add JWT auth with refresh rotation using jose, httpOnly cookie, 15min access / 7day refresh"
"Create the API" "Create POST /api/projects accepting {name, description}, validates name 3-50 chars, returns 201"
"Handle errors" "Wrap API calls in try/catch, return {error: string} on 4xx/5xx, show toast via sonner"

Required Task Components

Every task MUST include:

  1. files — Exact paths modified/created
  2. action — What to do, what to avoid, WHY
  3. verify — Command or check to prove completion
  4. done — Measurable acceptance criteria

See task-granularity.md for comprehensive examples and anti-patterns.

Context Budget

Tasks are sized to fit agent context budgets:

Complexity Context % Example
Simple 10-20% Add form field
Medium 20-35% Create API endpoint
Complex 35-50% Implement auth flow
Too Large >50% SPLIT REQUIRED

See context-engineering.md for context management rules.


Deviation Handling

When Workers encounter unexpected issues during execution, they follow deviation rules:

Rule Action Permission
Rule 1: Bug fixes Auto-fix None needed
Rule 2: Missing critical (validation, auth) Auto-add None needed
Rule 3: Blocking issues (deps, imports) Auto-fix None needed
Rule 4: Architectural changes ASK Required

See deviation-rules.md for detailed guidance.


Execution Artifacts

Task execution produces artifacts:

Artifact Purpose
Commits Per-task atomic commits
SUMMARY.md Record of what happened
STATE.md updates Position tracking

See execution-artifacts.md for artifact specifications.


Future Considerations

  • Compaction: Summarize old closed tasks to reduce DB size (beads does this with LLM)
  • Labels/tags: Additional categorization beyond type
  • Time tracking: Estimated vs actual time for capacity planning
  • Recurring tasks: Templates that spawn new tasks on schedule