Files
Codewalkers/docs/dispatch-events.md
Lukas May fcf822363c feat: Add persistent chat sessions for iterative phase/task refinement
Introduces a chat loop where users send instructions to an agent that
applies changes (create/update/delete phases, tasks, pages) and stays
alive for follow-up messages. Includes schema + migration, repository
layer, chat prompt, file-io action field extension, output handler chat
mode, revert support for deletes, tRPC procedures, events, frontend
slide-over UI with inline changeset display and revert, and docs.
2026-03-04 10:14:28 +01:00

5.2 KiB

Dispatch & Events

apps/server/dispatch/ — Task and phase dispatch queues. apps/server/events/ — Typed event bus.

Event Bus

apps/server/events/ — Typed pub/sub system for inter-module communication.

Architecture

  • Port: EventBus interface with emit(event) and on(type, handler)
  • Adapter: TypedEventBus using Node.js EventEmitter
  • All events implement BaseEvent { type, timestamp, payload }

Event Types (54)

Category Events Count
Agent agent:spawned, agent:stopped, agent:crashed, agent:resumed, agent:account_switched, agent:deleted, agent:waiting, agent:output 8
Task task:queued, task:dispatched, task:completed, task:blocked, task:pending_approval 5
Phase phase:queued, phase:started, phase:completed, phase:blocked 4
Merge merge:queued, merge:started, merge:completed, merge:conflicted 4
Page page:created, page:updated, page:deleted 3
Process process:spawned, process:stopped, process:crashed 3
Server server:started, server:stopped 2
Worktree worktree:created, worktree:removed, worktree:merged, worktree:conflict 4
Account account:credentials_refreshed, account:credentials_expired, account:credentials_validated 3
Preview preview:building, preview:ready, preview:stopped, preview:failed 4
Conversation conversation:created, conversation:answered 2
Chat chat:message_created, chat:session_closed 2
Log log:entry 1

Key Event Payloads

AgentSpawnedEvent    { agentId, name, taskId, worktreeId, provider }
AgentStoppedEvent    { agentId, name, taskId, reason }
  // reason: 'user_requested'|'task_complete'|'error'|'waiting_for_input'|
  //         'context_complete'|'plan_complete'|'detail_complete'|'refine_complete'|'chat_complete'
AgentWaitingEvent    { agentId, name, taskId, sessionId, questions[] }
AgentOutputEvent     { agentId, stream, data }
TaskCompletedEvent   { taskId, agentId, success, message }
TaskQueuedEvent      { taskId, priority, dependsOn[] }
PhaseStartedEvent    { phaseId, initiativeId }
MergeConflictedEvent { taskId, agentId, worktreeId, targetBranch, conflictingFiles[] }
AccountCredentialsRefreshedEvent { accountId, expiresAt, previousExpiresAt? }

Task Dispatch

apps/server/dispatch/ — In-memory queue with dependency-ordered dispatch.

Architecture

  • Port: DispatchManager interface
  • Adapter: DefaultDispatchManager

How Task Dispatch Works

  1. Queuequeue(taskId) fetches task dependencies, adds to internal Map
  2. DispatchdispatchNext() finds highest-priority task with all deps complete
  3. Context gathering — Before spawn, dispatchNext() gathers initiative context (initiative, phase, tasks, pages) and passes as inputContext to the agent. Agents receive .cw/input/task.md, initiative.md, phase.md, context/tasks/, context/phases/, and pages/.
  4. Priority order: high > medium > low, then oldest first (FIFO within priority)
  5. Checkpoint skip — Tasks with type starting with checkpoint: skip auto-dispatch
  6. Planning skip — Planning-category tasks (research, discuss, plan, detail, refine) skip auto-dispatch — they use the architect flow
  7. Summary propagationcompleteTask() reads the completing agent's result.message and stores it on the task's summary column. Dependent tasks see this summary in context/tasks/<id>.md frontmatter.
  8. Approval checkcompleteTask() checks requiresApproval (task-level, then initiative-level)
  9. Approval flow — If approval required: status → pending_approval, emit task:pending_approval

DispatchManager Methods

Method Purpose
queue(taskId) Add task to dispatch queue
dispatchNext() Find and dispatch next ready task
getNextDispatchable() Get next task without dispatching
completeTask(taskId, agentId?) Complete with approval check
approveTask(taskId) Approve pending task
blockTask(taskId, reason) Block task with reason
getQueueState() Return queued, ready, blocked tasks

Phase Dispatch

DefaultPhaseDispatchManager — Same pattern for phases:

  1. QueuequeuePhase(phaseId) validates phase is approved, gets dependencies
  2. DispatchdispatchNextPhase() finds phase with all deps complete
  3. Auto-queue tasks — When phase starts, pending execution tasks are queued (planning-category tasks excluded)
  4. Eventsphase:queued, phase:started, phase:completed, phase:blocked

PhaseDispatchManager Methods

Method Purpose
queuePhase(phaseId) Queue approved phase
dispatchNextPhase() Start next ready phase, auto-queue its tasks
getNextDispatchablePhase() Get next phase without dispatching
completePhase(phaseId) Mark phase complete
blockPhase(phaseId, reason) Block phase
getPhaseQueueState() Return queued, ready, blocked phases