Detail agents define task dependencies in YAML frontmatter but they were silently dropped — never written to the task_dependencies table. This caused all tasks to dispatch in parallel regardless of intended ordering, and the frontend showed no dependency information. - Add fileIdToDbId mapping and second-pass dependency creation in output-handler.ts (mirrors existing phase dependency pattern) - Add task_dependency to changeset entry entityType enum - Add listPhaseTaskDependencies tRPC procedure for batch querying - Wire blockedBy in PhaseDetailPanel and PhaseWithTasks from real data - Clarify dependency semantics in detail prompt
234 lines
10 KiB
Markdown
234 lines
10 KiB
Markdown
# 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:
|
|
|
|
```typescript
|
|
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 |
|
|
| getAgentResult | query | Execution result |
|
|
| getAgentQuestions | query | Pending questions |
|
|
| getAgentOutput | query | Full output from DB log chunks |
|
|
| 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 |
|
|
| createInitiativeTask | mutation | Create task on initiative |
|
|
| createPhaseTask | mutation | Create task on phase |
|
|
| listInitiativeTasks | query | All tasks for initiative |
|
|
| listPhaseTasks | query | All tasks for phase |
|
|
| listPendingApprovals | query | Tasks with status=pending_approval |
|
|
| deleteTask | mutation | Delete a task by ID |
|
|
| listPhaseTaskDependencies | query | All task dependency edges for tasks in a phase |
|
|
| approveTask | mutation | Approve and complete task |
|
|
|
|
### Initiatives
|
|
| Procedure | Type | Description |
|
|
|-----------|------|-------------|
|
|
| createInitiative | mutation | Create with optional branch/projectIds/description, auto-creates root page; if description provided, auto-spawns discuss agent |
|
|
| listInitiatives | query | Filter by status; 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 | mergeRequiresApproval, executionMode, branch |
|
|
|
|
### 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 |
|
|
|
|
### 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 with approval check |
|
|
|
|
### 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 |
|
|
|
|
### 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 |
|
|
|
|
### 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 30+ event types |
|
|
| onAgentUpdate | subscription | agent:* events (8 types) |
|
|
| onTaskUpdate | subscription | task:* + phase:* events (8 types) |
|
|
| onPageUpdate | subscription | page:created/updated/deleted |
|
|
|
|
Subscriptions use `eventBusIterable()` — queue-based async generator, max 1000 events, 30s heartbeat.
|
|
|
|
## 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)`.
|