Files
Codewalkers/docs/server-api.md
Lukas May b2f4004191 feat: Persist agent prompt in DB so getAgentPrompt survives log cleanup
The `getAgentPrompt` tRPC procedure previously read exclusively from
`.cw/agent-logs/<name>/PROMPT.md`. Once the cleanup-manager removes
that directory, the prompt is gone forever.

Adds a `prompt` text column to the `agents` table and writes the fully
assembled prompt (including workspace layout, inter-agent comms, and
preview sections) to the DB in the same `repository.update()` call
that saves pid/outputFilePath after spawn.

`getAgentPrompt` now reads from DB first (`agent.prompt`) and falls
back to the filesystem only for agents spawned before this change.

Addresses review comment [MMcmVlEK16bBfkJuXvG6h].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 13:13:01 +01:00

13 KiB

Server & API Module

apps/server/server/ — HTTP server, apps/server/trpc/ — tRPC procedures, apps/server/coordination/ — merge queue.

HTTP Server

Framework: Native node:http (no Express/Fastify) Default: 127.0.0.1:3847 PID file: ~/.cw/server.pid

Routes

Route Method Purpose
/health GET Health check ({ status, uptime, processCount })
/status GET Full server status with process list
/trpc/* POST All tRPC procedure calls

Lifecycle

  • CoordinationServer.start() — checks PID file, creates HTTP server, emits server:started
  • CoordinationServer.stop() — emits server:stopped, closes server, removes PID file
  • GracefulShutdown handles SIGTERM/SIGINT/SIGHUP with 10s timeout

tRPC Adapter

trpc-adapter.ts converts node:http IncomingMessage/ServerResponse to fetch Request/Response for tRPC. Subscriptions stream via ReadableStream bodies (SSE).

tRPC Context

All procedures share a context with optional dependencies:

interface TRPCContext {
  eventBus: EventBus              // always present
  serverStartedAt: Date | null
  processCount: number
  agentManager?: AgentManager     // optional
  taskRepository?: TaskRepository
  // ... all 10 repositories, 3 managers, credentialManager, workspaceRoot
}

Each procedure uses require*Repository(ctx) helpers that throw TRPCError(INTERNAL_SERVER_ERROR) if a dependency is missing.

Procedure Reference

System

Procedure Type Description
health query Health check with uptime
status query Server status with process list
systemHealthCheck query Account, agent, project health

Agents

Procedure Type Description
spawnAgent mutation Spawn new agent (taskId, prompt, provider, mode)
stopAgent mutation Stop agent by name or ID
deleteAgent mutation Delete agent and clean up worktree
dismissAgent mutation Dismiss agent (set userDismissedAt)
resumeAgent mutation Resume with answers
listAgents query All agents
getAgent query Single agent by name or ID; also returns taskName, initiativeName, exitCode
getAgentResult query Execution result
getAgentQuestions query Pending questions
getAgentOutput query Full output from DB log chunks
getAgentInputFiles query Files written to agent's .cw/input/ dir (text only, sorted, 500 KB cap)
getAgentPrompt query Assembled prompt — reads from DB (agents.prompt) first; falls back to .cw/agent-logs/<name>/PROMPT.md for pre-persistence agents (1 MB cap)
getActiveRefineAgent query Active refine agent for initiative
listWaitingAgents query Agents waiting for input
onAgentOutput subscription Live raw JSONL output stream via EventBus

Tasks

Procedure Type Description
listTasks query Child tasks of parent
getTask query Single task
updateTaskStatus mutation Change task status
updateTask mutation Update task fields (name, description)
createInitiativeTask mutation Create task on initiative
createPhaseTask mutation Create task on phase
listInitiativeTasks query All tasks for initiative
listPhaseTasks query All tasks for phase
deleteTask mutation Delete a task by ID
listPhaseTaskDependencies query All task dependency edges for tasks in a phase
listInitiativeTaskDependencies query All task dependency edges for tasks in an initiative

Initiatives

Procedure Type Description
createInitiative mutation Create with optional branch/projectIds/description, auto-creates root page (seeded with description); if description provided, auto-spawns refine agent
listInitiatives query Filter by status and/or projectId; returns activity (state, activePhase, phase counts) computed from phases
getInitiative query With projects array
updateInitiative mutation Name, status
deleteInitiative mutation Cascade delete initiative and all children
updateInitiativeConfig mutation executionMode, branch
getInitiativeReviewDiff query Full diff of initiative branch vs project default branch
getInitiativeReviewCommits query Commits on initiative branch not on default branch
getInitiativeCommitDiff query Single commit diff for initiative review
approveInitiativeReview mutation Approve initiative review: {initiativeId, strategy: 'push_branch' | 'merge_and_push'}

Phases

Procedure Type Description
createPhase mutation Create in initiative
listPhases query By initiative
getPhase query Single phase
updatePhase mutation Name, content, status
approvePhase mutation Validate and approve
deletePhase mutation Cascade delete
createPhasesFromPlan mutation Bulk create from agent output
createPhaseDependency mutation Add dependency edge
removePhaseDependency mutation Remove dependency edge
listInitiativePhaseDependencies query All dependency edges
getPhaseDependencies query What this phase depends on
getPhaseDependents query What depends on this phase
getPhaseReviewDiff query Full branch diff for pending_review phase
getPhaseReviewCommits query List commits between initiative and phase branch
getCommitDiff query Diff for a single commit (by hash) in a phase
approvePhaseReview mutation Approve and merge phase branch
requestPhaseChanges mutation Request changes: creates revision task from unresolved comments, resets phase to in_progress
listReviewComments query List review comments by phaseId
createReviewComment mutation Create inline review comment on diff
resolveReviewComment mutation Mark review comment as resolved
unresolveReviewComment mutation Mark review comment as unresolved

Phase Dispatch

Procedure Type Description
queuePhase mutation Queue approved phase
queueAllPhases mutation Queue all approved phases for initiative
dispatchNextPhase mutation Start next ready phase
getPhaseQueueState query Queue state
createChildTasks mutation Create tasks from detail parent

Architect (High-Level Agent Spawning)

Procedure Type Description
spawnArchitectDiscuss mutation Discussion agent
spawnArchitectPlan mutation Plan agent (generates phases). Passes initiative context (phases, execution tasks only, pages)
spawnArchitectRefine mutation Refine agent (generates proposals)
spawnArchitectDetail mutation Detail agent (generates tasks). Passes initiative context (phases, execution tasks only, pages)

Dispatch

Procedure Type Description
queueTask mutation Add task to dispatch queue
dispatchNext mutation Dispatch next ready task
getQueueState query Queue state
completeTask mutation Complete task

Coordination (Merge Queue)

Procedure Type Description
queueMerge mutation Queue task for merge
processMerges mutation Process merge queue
getMergeQueueStatus query Queue state
getNextMergeable query Next ready-to-merge task

Projects

Procedure Type Description
registerProject mutation Clone git repo, create record. Validates defaultBranch exists in repo
listProjects query All projects
getProject query Single project
updateProject mutation Update project settings (defaultBranch). Validates branch exists in repo
deleteProject mutation Delete clone and record
getInitiativeProjects query Projects for initiative
updateInitiativeProjects mutation Sync junction table
syncProject mutation git fetch + ff-only merge of defaultBranch, updates lastFetchedAt
syncAllProjects mutation Sync all registered projects
getProjectSyncStatus query Returns { ahead, behind, lastFetchedAt } for a project

Pages

Procedure Type Description
getRootPage query Auto-creates if missing
getPage query Single page
getPageUpdatedAtMap query Bulk updatedAt check
listPages query By initiative
listChildPages query By parent page
createPage mutation Create, emit page:created
updatePage mutation Title/content/sortOrder, emit page:updated
deletePage mutation Delete, emit page:deleted

Accounts

Procedure Type Description
listAccounts query All accounts
addAccount mutation Create account
removeAccount mutation Delete account
refreshAccounts mutation Clear expired exhaustion
updateAccountAuth mutation Update credentials
markAccountExhausted mutation Set exhaustion timer
listProviderNames query Available provider names
addAccountByToken mutation Upsert account by email + raw OAuth token

Proposals

Procedure Type Description
listProposals query By agent or initiative
acceptProposal mutation Apply side effects, auto-dismiss agent
dismissProposal mutation Dismiss, auto-dismiss agent
acceptAllProposals mutation Bulk accept with error collection
dismissAllProposals mutation Bulk dismiss

Subscriptions (SSE)

Procedure Type Events
onEvent subscription All event types
onAgentUpdate subscription agent:* events (7 types, excludes agent:output)
onTaskUpdate subscription task:* + phase:* events (8 types)
onPageUpdate subscription page:created/updated/deleted
onPreviewUpdate subscription preview:building/ready/stopped/failed
onConversationUpdate subscription conversation:created/answered

Subscriptions use eventBusIterable() — queue-based async generator, max 1000 events, 30s heartbeat. agent:output is excluded from all general subscriptions (it's high-frequency streaming data); use the dedicated onAgentOutput subscription instead.

Coordination Module

apps/server/coordination/ manages merge queue:

  • CoordinationManager port: queueMerge, getNextMergeable, processMerges, handleConflict, getQueueState
  • DefaultCoordinationManager adapter: in-memory queue, dependency-ordered processing
  • ConflictResolutionService: creates resolution tasks for merge conflicts
  • Merge flow: queue → check deps → merge via WorktreeManager → handle conflicts
  • Events: merge:queued, merge:started, merge:completed, merge:conflicted

Preview Procedures

Docker-based preview deployments. No database table — Docker is the source of truth.

Procedure Type Description
startPreview mutation Start preview: {initiativeId, phaseId?, projectId, branch} → PreviewStatus
stopPreview mutation Stop preview: {previewId}
listPreviews query List active previews: {initiativeId?} → PreviewStatus[]
getPreviewStatus query Get preview status: {previewId} → PreviewStatus

Context dependency: requirePreviewManager(ctx) — requires PreviewManager from container.

Conversation Procedures

Inter-agent communication for parallel agents.

Procedure Type Description
createConversation mutation Ask a question: {fromAgentId, toAgentId?, phaseId?, taskId?, question} → Conversation
getPendingConversations query Poll for incoming questions: {agentId} → Conversation[]
getConversation query Get conversation by ID: {id} → Conversation
answerConversation mutation Answer a conversation: {id, answer} → Conversation

Target resolution: toAgentId → direct; taskId → find running agent by task; phaseId → find running agent by any task in phase.

Context dependency: requireConversationRepository(ctx), requireAgentManager(ctx).

Chat Session Procedures

Persistent chat loop for iterative phase/task refinement via agent.

Procedure Type Description
sendChatMessage mutation Send message: {targetType, targetId, initiativeId, message, provider?}{sessionId, agentId, action}
getChatSession query Get active session with messages: {targetType, targetId} → ChatSession | null
closeChatSession mutation Close session and dismiss agent: {sessionId}{success}

sendChatMessage finds or creates an active session, stores the user message, then either resumes the existing agent (if waiting_for_input) or spawns a fresh one with full chat history + initiative context. Agent runs in 'chat' mode and signals "questions" after applying changes, staying alive for the next message.

Context dependency: requireChatSessionRepository(ctx), requireAgentManager(ctx), requireInitiativeRepository(ctx), requireTaskRepository(ctx).