# Test Inventory Comprehensive catalog of every test in the suite, what it verifies, and where coverage is weak or redundant. **41 test files** | **33 unit** | **7 E2E** | **3 integration (mocked)** | **5 integration (real providers)** Last audited: 2026-03-02 --- ## Coverage Matrix Subjective 0–10 scores. 0 = no coverage, 5 = happy paths only, 10 = comprehensive with edge cases. | Module | Happy Path | Error/Edge | Integration | Race/Concurrency | Notes | |--------|:---------:|:----------:|:-----------:|:----------------:|-------| | Agent Manager | 8 | 6 | 6 | 9 | Missing: `getResult` with actual result, multi-provider spawn | | Agent OutputHandler | 6 | 4 | 5 | 8 | Missing: `processAgentOutput` with error status, no-result-line case | | Agent FileIO | 8 | 7 | 8 | — | Missing: round-trip write→read, `writeInputFiles` content verification | | Agent ProcessManager | 6 | 4 | 3 | 0 | Heavy mocking; missing: `killProcess`, `cleanupWorktree`, error paths | | Agent Lifecycle | 8 | 7 | 3 | 0 | Missing: controller integration, `analyzeError→shouldRetry` chain | | DB Repositories | 9 | 7 | 9 | — | task.test.ts thin: missing `findByParentTaskId`, approval, category queries | | DB Cascades | 10 | — | 10 | — | Excellent: full graph verified | | Dispatch Manager | 7 | 5 | 8 | 0 | "dependency scenario" test is misleading (deps not implemented) | | Phase Dispatch | 9 | 7 | 8 | 0 | Best dependency tests (diamond pattern, blocking propagation) | | Coordination/Merge | 7 | 5 | 7 | 0 | Overlap with ConflictResolutionService | | Git Manager | 9 | 7 | 9 | 0 | Real git repos, no mocks. Excellent. | | Git BranchManager | 6 | 5 | 6 | — | Only `remoteBranchExists` tested. Other methods untested. | | Process Manager/Registry | 8 | 6 | — | 0 | Registry is pure and clean. Manager has mock fragility. | | Logging | 8 | 6 | 8 | 0 | Real filesystem. Good. | | Events Bus | 8 | 3 | — | 0 | Missing: handler-throws, handler ordering | | Server/HTTP | 8 | 6 | 9 | 0 | Real HTTP + real PID files | | Shutdown | 5 | 2 | — | 0 | Missing: signal→handler→shutdown chain, error resilience | | tRPC Router | 3 | 1 | 3 | 0 | **Only `health` and `status` tested. All domain procedures untested.** | | Preview | 7 | 5 | 4 | 0 | Missing: `discoverConfig`, `docker-client`, `health-checker` unit tests | | E2E Workflows | 8 | 6 | 8 | 0 | Good lifecycle coverage. Output parsing never tested E2E. | --- ## Test Files — Detailed Inventory ### Agent Module (`src/agent/`) #### `manager.test.ts` — MultiProviderAgentManager | Test | Verifies | |------|----------| | spawn / creates agent record with provided name | `repository.create` called with name | | spawn / rejects duplicate agent names | Unique name constraint enforced | | spawn / emits AgentSpawned event with name | Event has agent name in payload | | spawn / writes diagnostic files for workdir verification | `spawn-diagnostic.json` written with metadata | | spawn / uses custom cwd if provided | `child_process.spawn` gets custom cwd | | stop / stops running agent and updates status | DB updated to `stopped` | | stop / kills detached process if running | Status update after spawn+stop (does NOT verify kill) | | stop / throws if agent not found | Error on missing ID | | stop / emits AgentStopped event | Event has `user_requested` reason | | list / returns all agents with names | `findAll` returns correct data | | get / finds agent by id | `findById` returns agent | | get / returns null if not found | `findById` returns null | | getByName / finds agent by name | `findByName` returns agent | | getByName / returns null if not found | `findByName` returns null | | resume / resumes agent waiting for input | Spawn called with `--resume` + session args | | resume / rejects if not waiting for input | Error on wrong status | | resume / rejects if no session | Error on null sessionId | | resume / emits AgentResumed event | Event has sessionId | | getResult / returns null when no result | Agent result is null | | delete / deletes agent and clears active state | `repository.delete` called | | delete / emits agent:deleted event | Event has agent name | | delete / throws if not found | Error on missing ID | | delete / handles missing workdir gracefully | No error when workdir absent | **Mocking**: 5 `vi.mock()` calls (child_process, git/manager, node:fs, node:fs/promises, file-tailer). Brittle. **Gaps**: No test for `getResult` with actual result. No multi-provider tests. `findByTaskId`/`findBySessionId` mocked but never exercised. --- #### `output-handler.test.ts` — OutputHandler | Test | Verifies | |------|----------| | processAgentOutput / parse questions from Claude output | `waiting_for_input` status + questions stored | | processAgentOutput / handle malformed questions | Falls to `crashed` status | | processAgentOutput / handle "done" status | No `waiting_for_input` set | | getPendingQuestions / retrieve stored questions | JSON round-trip from DB | | getPendingQuestions / return null when none | Null for no questions | | formatAnswersAsPrompt / format normal answers | String formatting correct | | formatAnswersAsPrompt / instruction-enhanced answers | `__instruction__` prepended | | formatAnswersAsPrompt / instruction with whitespace | Trimmed correctly | | formatAnswersAsPrompt / only instruction, no answers | Instruction + header only | | formatAnswersAsPrompt / empty answers | Header with no entries | **Gaps**: No test for `processAgentOutput` with `"error"` status. No test for output with no result line. Uses real provider registry (fragile). --- #### `mutex-completion.test.ts` — handleCompletion mutex | Test | Verifies | |------|----------| | prevent concurrent completion | Same agentId blocked | | allow sequential completion | Same agentId allowed after first finishes | | clean up on exception | Lock released on error | | per-agent mutex isolation | Different agentIds run concurrently | **Excellent focused design.** 4 complementary scenarios. Uses real timers (50ms delays). --- #### `file-io.test.ts` — File I/O utilities | Test | Verifies | |------|----------| | generateId / non-empty string | Returns truthy | | generateId / unique values | 100 unique IDs | | writeInputFiles / initiative.md | File created | | writeInputFiles / phase.md | File created | | writeInputFiles / task.md | File created | | writeInputFiles / pages | Files in pages/ subdir | | writeInputFiles / empty options | No crash | | readSummary / with frontmatter | Parsed correctly | | readSummary / missing file | Returns null | | readSummary / no frontmatter | Body only | | readSummary / empty files_modified | Empty array | | readPhaseFiles / from phases/ dir | Parsed with frontmatter | | readPhaseFiles / missing dir | Returns [] | | readPhaseFiles / no dependencies | Defaults to [] | | readTaskFiles / from tasks/ dir | Parsed with frontmatter | | readTaskFiles / defaults category/type | `execute`/`auto` defaults | | readTaskFiles / missing dir | Returns [] | | readDecisionFiles / from decisions/ dir | Parsed | | readDecisionFiles / missing dir | Returns [] | | readPageFiles / from pages/ dir | Parsed with pageId | | readPageFiles / missing dir | Returns [] | | readPageFiles / ignores non-.md | Filter works | **Real filesystem, no mocks. Good.** Gaps: `writeInputFiles` only checks `existsSync`, not file content. No write→read round-trip test. --- #### `process-manager.test.ts` — ProcessManager | Test | Verifies | |------|----------| | getAgentWorkdir | Path computation | | createProjectWorktrees | Worktree creation for initiative projects | | createProjectWorktrees / throws on failure | Error propagation | | createStandaloneWorktree | Path returned | | createStandaloneWorktree / throws on failure | Error propagation | | spawnDetached / validates cwd exists | existsSync called | | spawnDetached / throws if cwd missing | Error thrown | | spawnDetached / passes correct cwd | spawn args verified | | spawnDetached / writes prompt file | PROMPT.md written | | buildSpawnCommand / native prompt mode | Command+args assembled | | buildSpawnCommand / flag prompt mode | Command+args assembled | | buildResumeCommand / flag style | Resume args assembled | | buildResumeCommand / no resume support | Error thrown | **6 `vi.mock()` calls.** Most brittle test file. Missing: `killProcess`, `cleanupWorktree`. --- #### `mock-manager.test.ts` — MockAgentManager (testing the test double) 43 tests covering: default scenario, configured delay, error/questions scenarios, resume, stop, list, get/getByName, scenario overrides, event emission order, name uniqueness, constructor options, agent modes (execute/discuss/plan/detail), structured questions. **Thorough.** --- #### Agent Lifecycle (`src/agent/lifecycle/`) **`error-analyzer.test.ts`** — 20 tests. Auth failure (4), usage limit (4), timeout (2), missing signal (3), process crash (4), unknown (2), context preservation (2). Pure behavioral classification tests. **`instructions.test.ts`** — 6 tests. Constant content verification + `addInstructionToPrompt` pure function tests. Appropriate for 28-line module. **`retry-policy.test.ts`** — 12 tests. Config (2), shouldRetry per error type (8), backoff delays (2). Clean decision-function tests. Missing: `AgentExhaustedError`/`AgentFailureError` class tests. **`signal-manager.test.ts`** — 18 tests. clearSignal (2), checkSignalExists (2), readSignal (7), waitForSignal (3), validateSignalFile (4). Real filesystem, no mocks. `waitForSignal` has real-timer flakiness risk. --- ### DB Repositories (`src/db/repositories/drizzle/`) All use real in-memory SQLite via `createTestDatabase()`. No mocks. Integration tests against real SQL. **`agent.test.ts`** — 20 tests. Full CRUD + findByStatus, findByTaskId, findBySessionId. Gap: never tests `initiativeId` field. **`cascade.test.ts`** — 4 tests. **High value.** Validates entire FK cascade graph: initiative→phases→tasks→pages→junction rows. Verifies SET NULL on agents/conversations. Before/after assertions prove setup correctness. **`initiative.test.ts`** — 12 tests. Standard CRUD + findByStatus. Simplest repo, clean. **`message.test.ts`** — 22 tests. **Most comprehensive repo test.** Covers sender/recipient polymorphism, threading (parentMessageId), status lifecycle (pending→read→responded), filtering (findPendingForUser, findRequiringResponse, findReplies). **`phase.test.ts`** — 21 tests. CRUD + 12 dependency tests (createDependency, getDependencies, getDependents, findDependenciesByInitiativeId). Direct-only (not transitive) verified. Cross-initiative scoping verified. **`task.test.ts`** — 12 tests. **Thinnest relative to feature surface.** Missing: `findByParentTaskId`, `findByInitiativeId`, `findPendingApproval`, category filtering, `requiresApproval` behavior. **Shared pattern**: 8 tests use `setTimeout(resolve, 10)` for timestamp differentiation (~80ms total delay). --- ### Dispatch (`src/dispatch/`) **`manager.test.ts`** — 13 tests. Queue, getNextDispatchable (priority, queuedAt ordering), completeTask, blockTask, dispatchNext (no tasks, no agents, success), getQueueState, dependency scenario. Real DB + mock event bus + mock agent manager. Gap: "dependency scenario" test admits dependencies aren't implemented — just retests priority ordering. **`phase-manager.test.ts`** — 17 tests. queuePhase (status validation, deps), getNextDispatchablePhase (dependency blocking), dispatchNextPhase, completePhase, blockPhase, diamond dependency scenario. **Best dependency tests**: full diamond pattern (A→B, A→C, B→D, C→D) with step-by-step verification. Gap: mock DispatchManager never asserted (task-level dispatch not verified). --- ### Coordination (`src/coordination/`) **`manager.test.ts`** — 14 tests. queueMerge, getNextMergeable (priority ordering), processMerges (success path, conflict detection, resolution task creation, message creation), getQueueState, handleConflict, error handling (undefined repos). **`conflict-resolution-service.test.ts`** — 10 tests. handleConflict (resolution task properties, original task blocking, agent message, event emission, optional deps, error cases, multiple conflicts, parentTaskId preservation). **Overlap**: 5+ tests in `manager.test.ts` duplicate conflict-handling logic from `conflict-resolution-service.test.ts`. --- ### Git (`src/git/`) **`manager.test.ts`** — 22 tests. create, remove, list, get, diff (clean/added/modified/deleted), merge (success/conflict/abort/cleanup), edge cases. **Real git repos on filesystem. No mocks. Excellent.** Most confident test file in the suite. **`simple-git-branch-manager.test.ts`** — 4 tests. `remoteBranchExists` only. Real git with bare repo + clones. Gap: only one method tested; other methods untested. --- ### Process (`src/process/`) **`manager.test.ts`** — 18 tests. spawn, stop, stopAll, restart, isRunning (live/dead/stopped), event emission. Uses mocked `execa`. Good separation of event bus concern. **`registry.test.ts`** — 14 tests. **Pure unit tests, no mocks.** register, get, getAll, updateStatus, unregister, getByPid, clear, size. Exemplary. --- ### Logging (`src/logging/`) **`manager.test.ts`** — 13 tests. getBaseDir, ensureLogDir, ensureProcessDir, getProcessDir, getLogPath, listLogs (filtering), cleanOldLogs (retainDays). Real filesystem. **`writer.test.ts`** — 17 tests. open, writeStdout/writeStderr (string/Buffer, timestamps, multi-line), close (flush, idempotent), write-after-close, append mode, event emission, backwards compatibility. Real filesystem + real EventBus. --- ### Events (`src/events/`) **`bus.test.ts`** — 10 tests. emit/on, event isolation, once, off, multiple handlers, typed events, timestamp preservation, factory. Pure behavioral tests. Gap: no handler-throws test, no handler ordering test. --- ### Server (`src/server/`) **`index.test.ts`** — 16 tests. Lifecycle (start/stop/double-start/PID conflict/idempotent stop/isRunning), HTTP endpoints (health/status/404/405), PID file management (create/remove/stale cleanup), event emission. Real HTTP server + real fetch. Gap: no port-already-in-use test. **`shutdown.test.ts`** — 6 tests. shutdown() call order (server.stop before processManager.stopAll), signal handler installation (SIGTERM/SIGINT/SIGHUP). Gap: **doesn't verify signal→handler→shutdown chain**. Doesn't test error resilience (what if server.stop() throws). --- ### tRPC Router (`src/trpc/`) **`router.test.ts`** — 14 tests. health procedure (shape, Zod, uptime calc, null startedAt, processCount), status procedure (shape, Zod, startedAt, pid, uptime), Zod schema validation. **Major gap**: **Only `health` and `status` are tested.** All domain procedures untested: initiatives, tasks, phases, agents, pages, proposals, accounts, conversations, previews. --- ### Preview (`src/preview/`) **`compose-generator.test.ts`** — 10 tests. Pure function tests. YAML generation, build config handling, Caddy deps, Caddyfile routing (single/multi/internal/specificity), labels. No mocks. Strong. **`config-reader.test.ts`** — 6 tests. `parseCwPreviewConfig` only. Minimal/multi-service, validation errors, internal services, build normalization. Gap: `discoverConfig` (filesystem discovery) is untested — always mocked in manager.test.ts. **`manager.test.ts`** — 20 tests. start (full lifecycle, phaseId, Docker unavailable, project not found, compose-up failure, health-check failure, no healthcheck), stop (cleanup, missing labels), list (all/filtered/skip non-preview/skip incomplete), getStatus (running/failed/stopped/building/null), stopAll (all/error resilience/empty). 6 `vi.mock()` calls. **`port-allocator.test.ts`** — 4 tests. Base port, skip used ports, gap filling, real TCP port contention. One real TCP server test. Gap: no upper-bound/exhaustion test. --- ### E2E Tests (`src/test/e2e/`) All use `createTestHarness()` with in-memory DB, MockAgentManager, MockWorktreeManager, real dispatch/coordination managers. **`happy-path.test.ts`** — 6 tests. Single task flow, sequential deps, parallel dispatch, full merge flow, complex dependency flow (diamond), fixture dependency DB verification. Gap: merge flow requires manual agent+worktree bridging (harness not fully integrated). **`architect-workflow.test.ts`** — 8 tests. Discuss mode (complete, pause/resume), plan mode (complete, persist phases), plan conflict detection (reject dup, auto-dismiss stale, different initiatives), full discuss→plan→phases workflow. Gap: architect output is never parsed — mock discards structured data. **`decompose-workflow.test.ts`** — 10 tests. Detail mode (complete, pause/resume, multiple questions), detail conflict detection (3 tests), task persistence (create, all types, dependencies), full workflow. Gap: filename says "decompose" but describe says "Detail". Task dependency rows never verified in DB. **`phase-dispatch.test.ts`** — 7 tests. **Cleanest E2E file.** Independent parallel dispatch, sequential deps, diamond dependency (A→B,C→D), approval gate (pending/in_progress rejection), blocked phase (no dispatch, downstream blocking). No fake timers, no agent involvement. **`recovery-scenarios.test.ts`** — 9 tests. Queue state in DB, in-progress task recovery after crash, blocked state persistence, merge queue recovery, agent Q&A (question/resume, structured questions, status transitions, multiple questions). **`edge-cases.test.ts`** — 12 tests. Agent crash (events, task status, error message), agent waiting (1 test), task blocking (4 tests), merge conflict handling (4 tests). **`extended-scenarios.test.ts`** — 6 tests. Conflict hand-back round-trip (full lifecycle, context preservation, sequential conflicts), multi-agent parallel work (parallel completion, merge ordering, mixed outcomes). --- ### Integration Tests (`src/test/integration/`) **`agent-workdir-verification.test.ts`** — 2 tests. Skipped by default (`REAL_WORKDIR_TESTS`). Spawns real Claude agent, verifies working directory path via diagnostic files and agent-created files. **`crash-race-condition.test.ts`** — 3 tests. Always runs. Tests signal.json-based completion detection vs crash marking. Covers questions, no-signal crash, and slim-wildebeest scenario. Accesses private methods via `as any`. **`real-claude.test.ts`** — 3 tests. Skipped by default. Direct Claude CLI contract tests: done/questions/error status outputs validated against Zod schema. ~$0.10. --- ### Real Provider Tests (`src/test/integration/real-providers/`) All skipped by default. ~$0.50 total per full run. **`claude-manager.test.ts`** — 7 tests. Output parsing (text_delta, init/session, result), questions flow, session resume (2 tests), error handling. Resume test accepts `crashed` as valid (too lenient). **`codex-manager.test.ts`** — 3 tests. Spawn, output parsing, provider config. **All accept `crashed` as valid** — pass vacuously when Codex isn't installed. **`conversation.test.ts`** — 1 test. **Most ambitious**: two real Claude agents doing actual coding while communicating via `cw ask`/`listen`/`answer`. Verifies 2 conversations, file creation, content, and interleaved coding+conversation. ~$0.30, 5min timeout. **`crash-recovery.test.ts`** — 4 tests. Server restart simulation (resume streaming, mark dead agent, process output for dead agent), event idempotency (no duplicate events on restart). **`schema-retry.test.ts`** — 9 tests. Valid output (done, questions, multiple questions), retry logic (bad→good, code blocks, surrounding text), mode-specific schemas (discuss, plan, detail). Tests 5-6 have conditional assertions (silently pass on crash). --- ## Remaining Redundancy Tests covering the same scenario multiple times. | Scenario | Tests | |----------|-------| | Task blocking (DB status) | `edge-cases.test.ts`, `recovery-scenarios.test.ts` | | Merge conflict → resolution task | `edge-cases.test.ts`, `extended-scenarios.test.ts` (full round-trip) | | Conflict resolution task creation | `coordination/manager.test.ts` (5 tests), `conflict-resolution-service.test.ts` (10 tests) | --- ## Coverage Gaps (Priority Order) ### Critical 1. **tRPC domain procedures entirely untested** — initiatives, tasks, phases, agents, pages, proposals, accounts, conversations, previews. Only `health`/`status` have tests. This is the single largest gap. 2. **Agent output parsing never tested E2E** — Architect helpers (`setArchitectPlanComplete`, `setArchitectDetailComplete`) discard structured output. The pipeline from agent output → DB persistence is exercised nowhere. 3. **`task.test.ts` thin relative to feature surface** — Missing: `findByParentTaskId`, `findByInitiativeId`, `findPendingApproval`, `approveTask`, category filtering, `requiresApproval` field behavior. These features exist in production but have zero direct unit test coverage. ### Important 4. **`discoverConfig` (preview config discovery) untested** — The filesystem walk logic (.cw-preview.yml → docker-compose.yml → Dockerfile) is always mocked away. 5. **`docker-client.js` and `health-checker.js` have no unit tests** — Always mocked. No verification of the Docker shell-out layer. 6. **Signal handler → shutdown chain untested** — `shutdown.test.ts` verifies listeners are installed and `shutdown()` works when called directly, but never tests signal → handler → shutdown. 7. **No concurrent dispatch/merge tests** — For a multi-agent system, racing `dispatchNext()` or concurrent merges are never exercised. 8. **`processAgentOutput` missing error status test** — "done" and "questions" tested, "error" not tested. ### Minor 9. **EventBus handler-throws behavior untested** — Does emit swallow or propagate handler errors? 10. **Port allocator upper-bound/exhaustion untested** — What happens when all ports 9100-9200 are taken? 11. **`error-analyzer` → `retry-policy` integration untested** — Each tested independently but the chain (`analyzeError` output fed to `shouldRetry`) is never verified end-to-end. 12. **Git `BranchManager` incomplete** — Only `remoteBranchExists` tested. Other methods (if any) untested. 13. **`ProcessManager.killProcess` and `cleanupWorktree` untested** — No unit test for these methods. --- ## Fragility Assessment ### High Fragility (refactoring will break tests) - **`agent/process-manager.test.ts`** — 6 `vi.mock()` calls. Any import restructuring breaks tests. - **`agent/manager.test.ts`** — 5 `vi.mock()` calls. Same concern. - **`preview/manager.test.ts`** — 6 `vi.mock()` calls. Same concern. - **`crash-race-condition.test.ts`** — Accesses private `handleCompletion` via `as any`. ### Low Fragility (behavioral tests) - **DB repository tests** — Real in-memory SQLite, test public API only. - **`git/manager.test.ts`** — Real git repos, no mocks. - **`file-io.test.ts`** — Real filesystem, pure function tests. - **`process/registry.test.ts`** — Pure unit tests, no mocks. - **`preview/compose-generator.test.ts`** — Pure function tests. - **`events/bus.test.ts`** — Pure behavioral tests. - **E2E tests** — Test through public harness API. --- ## Mock Style Inconsistencies The test suite uses 4 different mocking patterns with no shared convention: | Pattern | Files | Concern | |---------|-------|---------| | `vi.mock()` module-level | manager.test.ts, process-manager.test.ts, preview/manager.test.ts | Import-structure coupled | | Factory function (`createMockX()`) | output-handler.test.ts, coordination/*.test.ts, server/*.test.ts | Cleaner but copy-pasted | | Inline const object | mutex-completion.test.ts | Simple but mutated per-test | | Hand-rolled class | harness.ts (MockWorktreeManager, CapturingEventBus) | Best for shared infrastructure | `createMockEventBus()` is independently defined in 5+ files. Should be extracted to shared test utility.