diff --git a/.planning/phases/01.1-hexagonal-architecture/01.1-01-PLAN.md b/.planning/phases/01.1-hexagonal-architecture/01.1-01-PLAN.md new file mode 100644 index 0000000..7973f70 --- /dev/null +++ b/.planning/phases/01.1-hexagonal-architecture/01.1-01-PLAN.md @@ -0,0 +1,155 @@ +--- +phase: 01.1-hexagonal-architecture +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: [package.json, vitest.config.ts, src/events/types.ts, src/events/bus.ts, src/events/index.ts, src/events/bus.test.ts] +autonomous: true +--- + + +Create the event bus foundation - the backbone of the hexagonal architecture. + +Purpose: Establish extensible event infrastructure that can be swapped for external systems (RabbitMQ, WebSocket forwarding) later. All modules will communicate through this event bus. +Output: Working event bus with typed domain events and full test coverage. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/01.1-hexagonal-architecture/1.1-CONTEXT.md + +@src/index.ts +@src/process/types.ts +@src/logging/types.ts +@src/server/types.ts +@package.json + + + + + + Task 1: Install and configure Vitest test framework + package.json, vitest.config.ts + + Install vitest as dev dependency: `npm install -D vitest` + + Create vitest.config.ts with: + - TypeScript support (uses tsconfig.json automatically) + - Test globals enabled (describe, it, expect without imports) + - Coverage reporter (optional, for future use) + - Test file pattern: **/*.test.ts + + Add npm scripts to package.json: + - "test": "vitest run" + - "test:watch": "vitest" + - "test:coverage": "vitest run --coverage" + + npm test runs successfully (0 tests found is fine at this stage) + Vitest configured, npm test works, test:watch works + + + + Task 2: Create EventBus port interface and EventEmitter adapter + src/events/types.ts, src/events/bus.ts, src/events/index.ts + + Create src/events/types.ts: + - Define EventBus interface (the PORT): + ```typescript + export interface EventBus { + emit(event: T): void; + on(eventType: T['type'], handler: (event: T) => void): void; + off(eventType: T['type'], handler: (event: T) => void): void; + once(eventType: T['type'], handler: (event: T) => void): void; + } + ``` + - Define base DomainEvent interface: + ```typescript + export interface DomainEvent { + type: string; + timestamp: Date; + payload: unknown; + } + ``` + + Create src/events/bus.ts: + - Implement EventEmitterBus class that implements EventBus interface + - Use Node.js EventEmitter internally + - Wrap EventEmitter methods to match EventBus interface + - Add type safety for event emission + + Create src/events/index.ts: + - Export EventBus interface + - Export EventEmitterBus class + - Export DomainEvent type + - Export convenience function: createEventBus() that returns EventEmitterBus instance + + Key design: EventBus interface is the PORT. EventEmitterBus is the ADAPTER. + This allows swapping to RabbitMQ/Kafka/WebSocket later without changing consumers. + + TypeScript compiles: npm run build + EventBus interface defined, EventEmitterBus implemented, exports working + + + + Task 3: Define domain events with typed payloads and write tests + src/events/types.ts, src/events/bus.test.ts + + Add domain event types to src/events/types.ts: + + Process events: + - ProcessSpawned: { processId: string, pid: number, command: string } + - ProcessStopped: { processId: string, pid: number, exitCode: number | null } + - ProcessCrashed: { processId: string, pid: number, signal: string | null } + + Server events: + - ServerStarted: { port: number, host: string, pid: number } + - ServerStopped: { uptime: number } + + Log events: + - LogEntry: { processId: string, stream: 'stdout' | 'stderr', data: string } + + Create union type: DomainEventMap that maps event type strings to payload types. + This enables type-safe event handling. + + Create src/events/bus.test.ts: + - Test emit/on pattern works + - Test once fires only once + - Test off removes handler + - Test multiple handlers for same event + - Test typed event payloads (TypeScript compilation = passing) + - Test events include timestamp automatically + + npm test passes with all event bus tests green + Domain events defined, all tests pass, type safety verified + + + + + +Before declaring plan complete: +- [ ] npm run build succeeds +- [ ] npm test passes (event bus tests) +- [ ] EventBus interface is exported from src/events/index.ts +- [ ] EventEmitterBus implements EventBus correctly +- [ ] All domain events have typed payloads + + + + +- All tasks completed +- All verification checks pass +- Event bus is extensible (interface-based) +- Tests prove the pattern works + + + +After completion, create `.planning/phases/01.1-hexagonal-architecture/01.1-01-SUMMARY.md` + diff --git a/.planning/phases/01.1-hexagonal-architecture/01.1-02-PLAN.md b/.planning/phases/01.1-hexagonal-architecture/01.1-02-PLAN.md new file mode 100644 index 0000000..4889f98 --- /dev/null +++ b/.planning/phases/01.1-hexagonal-architecture/01.1-02-PLAN.md @@ -0,0 +1,123 @@ +--- +phase: 01.1-hexagonal-architecture +plan: 02 +type: execute +wave: 1 +depends_on: [] +files_modified: [package.json, src/trpc/router.ts, src/trpc/context.ts, src/trpc/index.ts, src/trpc/router.test.ts] +autonomous: true +--- + + +Create tRPC foundation for type-safe CLI-server communication. + +Purpose: Establish the tRPC contract that CLI and future WebUI will use to communicate with the server. Same interface for all clients. +Output: Working tRPC router with procedures matching existing HTTP endpoints, fully tested. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/01.1-hexagonal-architecture/1.1-CONTEXT.md + +@src/server/index.ts +@src/server/types.ts +@package.json + + + + + + Task 1: Install tRPC dependencies and create router foundation + package.json, src/trpc/router.ts, src/trpc/context.ts, src/trpc/index.ts + + Install dependencies: + - npm install @trpc/server zod + - npm install -D @trpc/client (for testing) + + Create src/trpc/context.ts: + - Define TRPCContext type containing: + - eventBus: EventBus (from src/events - import the interface type) + - serverStartedAt: Date | null + - processCount: number + - Export createContext function that builds context + - Context will be injected into procedures + + Create src/trpc/router.ts: + - Initialize tRPC with initTRPC.context().create() + - Create base router and procedure helpers + - Export router, publicProcedure + + Create src/trpc/index.ts: + - Export router, context, types + - Export AppRouter type for client usage + + Note: Don't import actual EventBus implementation yet - just the type. + This keeps tRPC foundation independent of event bus implementation. + + npm run build succeeds, no import errors + tRPC initialized, context defined, router foundation in place + + + + Task 2: Define procedures matching HTTP endpoints with tests + src/trpc/router.ts, src/trpc/router.test.ts + + Add procedures to src/trpc/router.ts: + + health procedure (query): + - Input: none + - Output: { status: 'ok', uptime: number, processCount: number } + - Uses context.serverStartedAt to calculate uptime + - Use Zod for output validation + + status procedure (query): + - Input: none + - Output: { server: { startedAt: string, uptime: number, pid: number }, processes: Array } + - More detailed than health + - Use Zod for output validation + + Create appRouter that combines procedures. + Export AppRouter type: typeof appRouter + + Create src/trpc/router.test.ts: + - Use @trpc/server/adapters/standalone for testing (or direct caller) + - Test health procedure returns correct shape + - Test status procedure returns correct shape + - Test with mocked context (no real server needed) + - Verify Zod validation catches bad outputs + + Testing approach: Use createCallerFactory from tRPC for direct procedure calls without HTTP. + + npm test passes with tRPC router tests green + Procedures defined, Zod validation in place, tests pass + + + + + +Before declaring plan complete: +- [ ] npm run build succeeds +- [ ] npm test passes (tRPC router tests) +- [ ] AppRouter type is exported +- [ ] health and status procedures work +- [ ] Zod schemas validate outputs + + + + +- All tasks completed +- All verification checks pass +- tRPC router ready for HTTP adapter integration +- Type-safe contract established + + + +After completion, create `.planning/phases/01.1-hexagonal-architecture/01.1-02-SUMMARY.md` + diff --git a/.planning/phases/01.1-hexagonal-architecture/01.1-03-PLAN.md b/.planning/phases/01.1-hexagonal-architecture/01.1-03-PLAN.md new file mode 100644 index 0000000..d555c2f --- /dev/null +++ b/.planning/phases/01.1-hexagonal-architecture/01.1-03-PLAN.md @@ -0,0 +1,126 @@ +--- +phase: 01.1-hexagonal-architecture +plan: 03 +type: execute +wave: 2 +depends_on: ["01.1-01"] +files_modified: [src/process/registry.test.ts, src/process/manager.test.ts, src/process/manager.ts, src/process/index.ts] +autonomous: true +--- + + +Add test coverage and event emission to the Process module. + +Purpose: ProcessManager is core to agent lifecycle. Events like ProcessSpawned/ProcessStopped will drive coordination logic in later phases. +Output: Fully tested process module that emits domain events via the event bus. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/01.1-hexagonal-architecture/01.1-01-SUMMARY.md + +@src/process/index.ts +@src/process/manager.ts +@src/process/registry.ts +@src/process/types.ts +@src/events/index.ts + + + + + + Task 1: Write unit tests for ProcessRegistry and ProcessManager + src/process/registry.test.ts, src/process/manager.test.ts + + Create src/process/registry.test.ts: + - Test register() adds process to registry + - Test get() retrieves registered process + - Test getAll() returns all processes + - Test updateStatus() changes status correctly + - Test unregister() removes process + - Test get() returns undefined for non-existent process + + Create src/process/manager.test.ts: + - Test spawn() creates process and registers it + - Test spawn() throws if process ID already running + - Test stop() terminates process + - Test stop() throws if process not found + - Test stopAll() stops all running processes + - Test restart() stops and respawns process + - Test isRunning() returns correct state + + Testing approach for ProcessManager: + - Mock the execa module to avoid spawning real processes + - Use vi.mock('execa') with mock subprocess that has controllable behavior + - Create mock registry for isolation + + Focus on behavior, not implementation details. + + npm test passes with process module tests green + ProcessRegistry and ProcessManager have comprehensive test coverage + + + + Task 2: Refactor ProcessManager to emit events via event bus + src/process/manager.ts, src/process/index.ts + + Modify ProcessManager constructor: + - Add optional eventBus parameter: EventBus | undefined + - Store as private readonly property + + Add event emission in spawn(): + - After successful spawn, emit ProcessSpawned event: + { type: 'process.spawned', timestamp: new Date(), payload: { processId, pid, command } } + + Add event emission in exit handler: + - On normal exit, emit ProcessStopped: + { type: 'process.stopped', timestamp: new Date(), payload: { processId, pid, exitCode } } + - On crash (non-zero exit), emit ProcessCrashed: + { type: 'process.crashed', timestamp: new Date(), payload: { processId, pid, signal } } + + Add event emission in stop(): + - After successful stop, ProcessStopped is already emitted by exit handler + - No additional event needed + + Update src/process/index.ts exports if needed. + + Update tests to verify events are emitted: + - Create mock EventBus + - Pass to ProcessManager + - Assert emit() called with correct event shape + + Key: eventBus is optional for backwards compatibility. If not provided, no events emitted. + + npm test passes, events emitted correctly in tests + ProcessManager emits domain events, tests verify event emission + + + + + +Before declaring plan complete: +- [ ] npm run build succeeds +- [ ] npm test passes (all process module tests) +- [ ] ProcessManager accepts optional eventBus +- [ ] ProcessSpawned event emitted on spawn +- [ ] ProcessStopped/ProcessCrashed events emitted on exit + + + + +- All tasks completed +- All verification checks pass +- Process lifecycle events flow through event bus +- Backwards compatible (eventBus is optional) + + + +After completion, create `.planning/phases/01.1-hexagonal-architecture/01.1-03-SUMMARY.md` + diff --git a/.planning/phases/01.1-hexagonal-architecture/01.1-04-PLAN.md b/.planning/phases/01.1-hexagonal-architecture/01.1-04-PLAN.md new file mode 100644 index 0000000..9a6d019 --- /dev/null +++ b/.planning/phases/01.1-hexagonal-architecture/01.1-04-PLAN.md @@ -0,0 +1,124 @@ +--- +phase: 01.1-hexagonal-architecture +plan: 04 +type: execute +wave: 2 +depends_on: ["01.1-01"] +files_modified: [src/logging/manager.test.ts, src/logging/writer.test.ts, src/logging/writer.ts, src/logging/index.ts] +autonomous: true +--- + + +Add test coverage and event emission to the Logging module. + +Purpose: Log events will be forwarded to UI/FSUI for real-time visibility into agent output. Critical for the file system UI in Phase 7. +Output: Fully tested logging module that emits LogEntry events via the event bus. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/01.1-hexagonal-architecture/01.1-01-SUMMARY.md + +@src/logging/index.ts +@src/logging/manager.ts +@src/logging/writer.ts +@src/logging/types.ts +@src/events/index.ts + + + + + + Task 1: Write unit tests for LogManager and ProcessLogWriter + src/logging/manager.test.ts, src/logging/writer.test.ts + + Create src/logging/manager.test.ts: + - Test ensureLogDir() creates directory + - Test ensureProcessDir() creates process-specific directory + - Test getProcessDir() returns correct path + - Test getLogPath() returns correct path for stdout/stderr + - Test listLogs() returns process IDs + - Test listLogs() returns empty array if dir doesn't exist + - Test cleanOldLogs() removes old directories + - Test getBaseDir() returns configured base + + Use temporary directories for file system tests (use os.tmpdir()). + Clean up after each test. + + Create src/logging/writer.test.ts: + - Read src/logging/writer.ts first to understand the API + - Test open() creates log files + - Test writeStdout() writes to stdout.log + - Test writeStderr() writes to stderr.log + - Test close() flushes and closes handles + - Test writing after close throws + + Use temporary directories, clean up after tests. + + npm test passes with logging module tests green + LogManager and ProcessLogWriter have comprehensive test coverage + + + + Task 2: Add event emission to ProcessLogWriter + src/logging/writer.ts, src/logging/index.ts + + Modify ProcessLogWriter constructor: + - Add optional eventBus parameter: EventBus | undefined + - Store as private readonly property + + Add event emission in writeStdout(): + - After writing to file, emit LogEntry event: + { type: 'log.entry', timestamp: new Date(), payload: { processId, stream: 'stdout', data } } + + Add event emission in writeStderr(): + - After writing to file, emit LogEntry event: + { type: 'log.entry', timestamp: new Date(), payload: { processId, stream: 'stderr', data } } + + Update createLogger() convenience function: + - Add optional eventBus parameter + - Pass through to ProcessLogWriter + + Update src/logging/index.ts exports if needed. + + Update tests to verify events are emitted: + - Create mock EventBus + - Pass to ProcessLogWriter + - Assert emit() called with correct LogEntry shape + - Test that events are NOT emitted if eventBus not provided + + Key: This enables real-time log streaming to UI/FSUI in later phases. + + npm test passes, log events emitted correctly + ProcessLogWriter emits LogEntry events, tests verify emission + + + + + +Before declaring plan complete: +- [ ] npm run build succeeds +- [ ] npm test passes (all logging module tests) +- [ ] ProcessLogWriter accepts optional eventBus +- [ ] LogEntry events emitted on stdout/stderr writes +- [ ] Backwards compatible (eventBus is optional) + + + + +- All tasks completed +- All verification checks pass +- Log events flow through event bus +- Ready for real-time log streaming + + + +After completion, create `.planning/phases/01.1-hexagonal-architecture/01.1-04-SUMMARY.md` + diff --git a/.planning/phases/01.1-hexagonal-architecture/01.1-05-PLAN.md b/.planning/phases/01.1-hexagonal-architecture/01.1-05-PLAN.md new file mode 100644 index 0000000..c36fbc4 --- /dev/null +++ b/.planning/phases/01.1-hexagonal-architecture/01.1-05-PLAN.md @@ -0,0 +1,133 @@ +--- +phase: 01.1-hexagonal-architecture +plan: 05 +type: execute +wave: 2 +depends_on: ["01.1-01"] +files_modified: [src/server/index.test.ts, src/server/shutdown.test.ts, src/server/index.ts, src/server/shutdown.ts] +autonomous: true +--- + + +Add test coverage and event emission to the Server module. + +Purpose: Server events (started/stopped) are critical for coordination. The shutdown handler orchestrates cleanup - events enable reactive patterns. +Output: Fully tested server module with event-driven lifecycle. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/01.1-hexagonal-architecture/01.1-01-SUMMARY.md + +@src/server/index.ts +@src/server/shutdown.ts +@src/server/types.ts +@src/events/index.ts + + + + + + Task 1: Write unit tests for CoordinationServer + src/server/index.test.ts + + Create src/server/index.test.ts: + + Test server lifecycle: + - Test start() begins listening on configured port + - Test start() throws if already running + - Test start() throws if PID file exists (another server) + - Test stop() stops the server + - Test stop() is idempotent (no error if not running) + - Test isRunning() returns correct state + + Test HTTP endpoints: + - Test GET /health returns status 'ok' with uptime + - Test GET /status returns server info + - Test GET /unknown returns 404 + - Test POST /health returns 405 (method not allowed) + + Test PID file: + - Test PID file created on start + - Test PID file removed on stop + - Test stale PID file is cleaned up + + Testing approach: + - Create server with random high port to avoid conflicts + - Use temporary directory for PID file + - Create mock ProcessManager and LogManager (they're not used in tests) + - Use fetch() or http.request() to test endpoints + - Clean up after each test (stop server, remove temp files) + + npm test passes with server tests green + CoordinationServer has comprehensive test coverage + + + + Task 2: Add event emission to server and shutdown handler + src/server/index.ts, src/server/shutdown.ts + + Modify CoordinationServer constructor: + - Add optional eventBus parameter: EventBus | undefined + - Store as private readonly property + + Add event emission in start(): + - After server starts listening, emit ServerStarted: + { type: 'server.started', timestamp: new Date(), payload: { port, host, pid: process.pid } } + + Add event emission in stop(): + - Before stopping, emit ServerStopped: + { type: 'server.stopped', timestamp: new Date(), payload: { uptime } } + + Modify GracefulShutdown: + - Add optional eventBus parameter + - Emit events during shutdown sequence if event bus provided: + - Could emit ShutdownInitiated, ShutdownComplete events + - Or rely on ServerStopped from CoordinationServer (simpler) + - Keep it simple: just ensure CoordinationServer emits ServerStopped + + Update tests: + - Add mock EventBus to server tests + - Verify ServerStarted emitted on start + - Verify ServerStopped emitted on stop + + Create src/server/shutdown.test.ts: + - Test shutdown() calls server.stop() + - Test shutdown() calls processManager.stopAll() + - Test signal handlers are installed + - Mock dependencies (server, processManager, logManager) + + npm test passes with all server module tests green + Server emits lifecycle events, shutdown handler tested + + + + + +Before declaring plan complete: +- [ ] npm run build succeeds +- [ ] npm test passes (all server module tests) +- [ ] CoordinationServer accepts optional eventBus +- [ ] ServerStarted event emitted on start +- [ ] ServerStopped event emitted on stop +- [ ] GracefulShutdown has test coverage + + + + +- All tasks completed +- All verification checks pass +- Server lifecycle events flow through event bus +- Shutdown sequence is tested + + + +After completion, create `.planning/phases/01.1-hexagonal-architecture/01.1-05-SUMMARY.md` + diff --git a/.planning/phases/01.1-hexagonal-architecture/01.1-06-PLAN.md b/.planning/phases/01.1-hexagonal-architecture/01.1-06-PLAN.md new file mode 100644 index 0000000..6b85628 --- /dev/null +++ b/.planning/phases/01.1-hexagonal-architecture/01.1-06-PLAN.md @@ -0,0 +1,123 @@ +--- +phase: 01.1-hexagonal-architecture +plan: 06 +type: execute +wave: 3 +depends_on: ["01.1-02", "01.1-05"] +files_modified: [src/cli/trpc-client.ts, src/cli/index.ts, src/server/trpc-adapter.ts, src/server/index.ts, tests/integration/cli-server.test.ts] +autonomous: true +--- + + +Integrate tRPC client into CLI and add HTTP adapter to server. + +Purpose: Complete the tRPC contract by connecting CLI to server. This establishes the pattern for all future client-server communication. +Output: CLI communicates with server via tRPC, with integration tests proving the full flow. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/01.1-hexagonal-architecture/01.1-02-SUMMARY.md +@.planning/phases/01.1-hexagonal-architecture/01.1-05-SUMMARY.md + +@src/cli/index.ts +@src/server/index.ts +@src/trpc/index.ts + + + + + + Task 1: Add tRPC HTTP adapter to server and create CLI client + src/server/trpc-adapter.ts, src/server/index.ts, src/cli/trpc-client.ts, package.json + + Install additional dependency if needed: + - npm install @trpc/client (should already be dev dep, move to regular deps) + + Create src/server/trpc-adapter.ts: + - Create function to handle tRPC requests via node:http + - Use @trpc/server/adapters/fetch or manual handling + - Route /trpc/* requests to tRPC router + - Create context with eventBus, serverStartedAt, processCount + + Modify CoordinationServer: + - In handleRequest(), add routing for /trpc/* paths + - Delegate to tRPC adapter + - Keep existing /health and /status routes for backwards compatibility + - tRPC endpoints: /trpc/health, /trpc/status + + Create src/cli/trpc-client.ts: + - Create tRPC client using @trpc/client + - Configure with httpBatchLink pointing to http://127.0.0.1:{port}/trpc + - Export typed client + - Export helper function: createTrpcClient(port: number) + + Key: The existing HTTP endpoints (/health, /status) remain for curl/debugging. + CLI will use tRPC endpoints for type safety. + + npm run build succeeds + tRPC adapter integrated into server, CLI client created + + + + Task 2: Update CLI status command and write integration tests + src/cli/index.ts, tests/integration/cli-server.test.ts + + Update src/cli/index.ts: + - Modify status command to use tRPC client instead of placeholder + - Create tRPC client with default port (3847) or env var + - Call health procedure and display result + - Handle connection errors gracefully (server not running) + + Keep the placeholder message if tRPC call fails: + ``` + Server not running or unreachable. Start with: cw --server + ``` + + Create tests/integration/cli-server.test.ts: + - Test full flow: start server, call tRPC from client, verify response + - Test health procedure returns correct data + - Test status procedure returns correct data + - Test client handles server not running + + Integration test approach: + - Start CoordinationServer on random port in beforeAll + - Create tRPC client pointing to that port + - Run procedures, verify responses + - Stop server in afterAll + + These are INTEGRATION tests, not unit tests - they test the full stack. + + npm test passes with all tests including integration tests + CLI uses tRPC for status, integration tests prove full flow works + + + + + +Before declaring plan complete: +- [ ] npm run build succeeds +- [ ] npm test passes (all tests including integration) +- [ ] cw status connects to server via tRPC +- [ ] tRPC endpoints work alongside HTTP endpoints +- [ ] Full flow tested: server start → tRPC call → response + + + + +- All tasks completed +- All verification checks pass +- CLI communicates with server via type-safe tRPC +- Integration tests prove the architecture works end-to-end + + + +After completion, create `.planning/phases/01.1-hexagonal-architecture/01.1-06-SUMMARY.md` +