From d0e9acf512a1847942f9130a48a7f07a62111557 Mon Sep 17 00:00:00 2001 From: Lukas May Date: Sat, 31 Jan 2026 08:15:02 +0100 Subject: [PATCH] docs(07): create phase plan Phase 07: Mock Agent & Test Harness - 2 plans in 2 waves - 1 parallel (07-01), 1 sequential (07-02) - Ready for execution --- .../07-mock-agent-test-harness/07-01-PLAN.md | 136 ++++++++++++ .../07-mock-agent-test-harness/07-02-PLAN.md | 197 ++++++++++++++++++ 2 files changed, 333 insertions(+) create mode 100644 .planning/phases/07-mock-agent-test-harness/07-01-PLAN.md create mode 100644 .planning/phases/07-mock-agent-test-harness/07-02-PLAN.md diff --git a/.planning/phases/07-mock-agent-test-harness/07-01-PLAN.md b/.planning/phases/07-mock-agent-test-harness/07-01-PLAN.md new file mode 100644 index 0000000..922f3b9 --- /dev/null +++ b/.planning/phases/07-mock-agent-test-harness/07-01-PLAN.md @@ -0,0 +1,136 @@ +--- +phase: 07-mock-agent-test-harness +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: [src/agent/mock-manager.ts, src/agent/mock-manager.test.ts, src/agent/index.ts] +autonomous: true +--- + + +Implement MockAgentManager adapter for test scenarios. + +Purpose: Enable E2E testing of dispatch/coordination flows without spawning real Claude agents. The mock adapter simulates configurable agent behaviors (success, crash, waiting_for_input) and emits proper lifecycle events. + +Output: MockAgentManager class implementing AgentManager port with scenario configuration. + + + +@~/.claude/get-shit-done/workflows/execute-plan.md +@~/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md + +@src/agent/types.ts +@src/agent/manager.ts +@src/events/types.ts + + + + + + Task 1: Implement MockAgentManager adapter + src/agent/mock-manager.ts + +Create MockAgentManager class implementing AgentManager interface with configurable scenarios. + +**Scenario configuration interface:** +```typescript +interface MockAgentScenario { + /** How agent completes: 'success' | 'crash' | 'waiting_for_input' */ + outcome: 'success' | 'crash' | 'waiting_for_input'; + /** Delay before completion (ms). Default 0 for synchronous tests. */ + delay?: number; + /** Result message for success/crash */ + message?: string; + /** Files modified (for success) */ + filesModified?: string[]; + /** Question to surface (for waiting_for_input) */ + question?: string; +} +``` + +**Constructor takes:** +- eventBus?: EventBus (optional, for event emission) +- defaultScenario?: MockAgentScenario (defaults to immediate success) + +**Key behaviors:** +- spawn(): Create agent record in internal Map, schedule completion based on scenario +- Use per-agent scenario override via `setScenario(agentName: string, scenario: MockAgentScenario)` +- Emit all lifecycle events: agent:spawned, agent:stopped, agent:crashed, agent:waiting, agent:resumed +- store session IDs (use UUID) for resume capability testing +- stop(): Mark agent stopped, emit agent:stopped event +- resume(): Re-run scenario for resumed agent +- getResult(): Return stored result after completion + +**DO NOT:** +- Use real execa/subprocess - this is all in-memory simulation +- Block on spawn() - completion happens async via setTimeout (even if delay=0) + + npm run build succeeds, TypeScript compiles without errors + MockAgentManager implements AgentManager interface with scenario configuration + + + + Task 2: Write comprehensive tests for MockAgentManager + src/agent/mock-manager.test.ts, src/agent/index.ts + +Create test suite for MockAgentManager covering all scenarios. + +**Test categories:** +1. spawn() with default scenario (immediate success) +2. spawn() with configured delay +3. spawn() with crash scenario - emits agent:crashed, result.success=false +4. spawn() with waiting_for_input - emits agent:waiting, status='waiting_for_input' +5. resume() after waiting_for_input - emits agent:resumed, continues with scenario +6. stop() kills scheduled completion, emits agent:stopped +7. list() returns all agents with correct status +8. get() and getByName() lookups work +9. setScenario() overrides for specific agent names +10. Event emission order verification (spawned before completion events) + +**Pattern to follow:** +Use same createMockEventBus() pattern from dispatch/manager.test.ts +Use async/await with vitest's fake timers for delay testing: +```typescript +vi.useFakeTimers(); +await manager.spawn({ name: 'test', taskId: 't1', prompt: 'do thing' }); +await vi.advanceTimersByTimeAsync(100); +// verify completion happened +vi.useRealTimers(); +``` + +**Export MockAgentManager from src/agent/index.ts** + + npm test passes all MockAgentManager tests, at least 10 test cases + MockAgentManager has comprehensive test coverage for all scenario types + + + + + +Before declaring plan complete: +- [ ] `npm run build` succeeds without errors +- [ ] `npm test` passes all tests including new MockAgentManager tests +- [ ] MockAgentManager implements full AgentManager interface +- [ ] All three outcome scenarios work: success, crash, waiting_for_input +- [ ] Events emitted correctly for each scenario +- [ ] MockAgentManager exported from src/agent/index.ts + + + + +- All tasks completed +- MockAgentManager can simulate any agent lifecycle scenario +- Test suite proves all scenarios work correctly +- No errors or warnings introduced + + + +After completion, create `.planning/phases/07-mock-agent-test-harness/07-01-SUMMARY.md` + diff --git a/.planning/phases/07-mock-agent-test-harness/07-02-PLAN.md b/.planning/phases/07-mock-agent-test-harness/07-02-PLAN.md new file mode 100644 index 0000000..da6c30d --- /dev/null +++ b/.planning/phases/07-mock-agent-test-harness/07-02-PLAN.md @@ -0,0 +1,197 @@ +--- +phase: 07-mock-agent-test-harness +plan: 02 +type: execute +wave: 2 +depends_on: ["07-01"] +files_modified: [src/test/harness.ts, src/test/fixtures.ts, src/test/index.ts, src/test/harness.test.ts] +autonomous: true +--- + + +Create test harness with database fixtures and full system wiring. + +Purpose: Provide reusable E2E test setup that wires MockAgentManager with real DispatchManager and CoordinationManager, plus helpers for seeding database hierarchies (initiative → phase → plan → task with dependencies). + +Output: Test harness module (src/test/) with fixtures and system factory. + + + +@~/.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/07-mock-agent-test-harness/07-01-SUMMARY.md + +@src/agent/types.ts +@src/dispatch/types.ts +@src/coordination/types.ts +@src/db/repositories/drizzle/test-helpers.ts + + + + + + Task 1: Create fixture helpers for database seeding + src/test/fixtures.ts + +Create fixture helpers that seed complete task hierarchies. + +**Fixture interface:** +```typescript +interface TaskFixture { + id: string; + name: string; + priority?: 'low' | 'medium' | 'high'; + dependsOn?: string[]; // names of other tasks in same fixture +} + +interface PlanFixture { + name: string; + tasks: TaskFixture[]; +} + +interface PhaseFixture { + name: string; + plans: PlanFixture[]; +} + +interface InitiativeFixture { + name: string; + phases: PhaseFixture[]; +} +``` + +**seedFixture(db: DrizzleDatabase, fixture: InitiativeFixture): Promise** +- Creates initiative, phases, plans, tasks in correct order +- Resolves task dependencies by name → ID mapping +- Returns SeededFixture with all created IDs: +```typescript +interface SeededFixture { + initiativeId: string; + phases: Map; // name → id + plans: Map; // name → id + tasks: Map; // name → id +} +``` + +**Convenience fixtures:** +- `SIMPLE_FIXTURE`: 1 initiative → 1 phase → 1 plan → 3 tasks (A, B depends on A, C depends on A) +- `PARALLEL_FIXTURE`: 1 initiative → 1 phase → 2 plans (each with 2 independent tasks) +- `COMPLEX_FIXTURE`: 1 initiative → 2 phases → 4 plans with cross-plan dependencies + + TypeScript compiles, fixtures are valid data structures + Fixture helpers create complete task hierarchies with dependency resolution + + + + Task 2: Create test harness with full system wiring + src/test/harness.ts, src/test/index.ts + +Create TestHarness class that wires up the full system for E2E testing. + +**TestHarness interface:** +```typescript +interface TestHarness { + // Core components + db: DrizzleDatabase; + eventBus: EventBus & { emittedEvents: DomainEvent[] }; + agentManager: MockAgentManager; + dispatchManager: DispatchManager; + coordinationManager: CoordinationManager; + + // Repositories + taskRepository: TaskRepository; + messageRepository: MessageRepository; + agentRepository: AgentRepository; + + // Helpers + seedFixture(fixture: InitiativeFixture): Promise; + setAgentScenario(agentName: string, scenario: MockAgentScenario): void; + getEventsByType(type: string): DomainEvent[]; + clearEvents(): void; +} +``` + +**createTestHarness(): TestHarness** +- Creates in-memory SQLite database (createTestDatabase) +- Creates EventEmitterBus (real event bus for event verification) +- Creates MockAgentManager (with eventBus) +- Creates MockWorktreeManager (simple in-memory, creates fake worktrees) +- Creates real DefaultDispatchManager (with mock agent manager) +- Creates real DefaultCoordinationManager (with mock worktree manager) +- Wires all repositories + +**MockWorktreeManager (inline in harness.ts):** +- Simple Map for worktree storage +- create(): returns fake worktree with random path +- get(): lookup by ID +- remove(): delete from map +- merge(): returns success (no actual git operations) + + npm run build succeeds + TestHarness wires full system with mocks for E2E scenarios + + + + Task 3: Write tests proving harness works + src/test/harness.test.ts + +Write tests that prove the test harness enables E2E scenarios. + +**Test cases:** +1. createTestHarness() returns all components +2. seedFixture() creates task hierarchy, returns correct IDs +3. Task dependencies resolved correctly (dependsOn contains actual task IDs) +4. dispatchManager.queue() + dispatchNext() uses MockAgentManager +5. Event capture works (getEventsByType returns filtered events) +6. Agent completion triggers expected events +7. Full dispatch → complete → merge flow works end-to-end + +**Key verification:** +The test should prove this flow works: +```typescript +const harness = createTestHarness(); +const fixture = await harness.seedFixture(SIMPLE_FIXTURE); +await harness.dispatchManager.queue(fixture.tasks.get('Task A')!); +const result = await harness.dispatchManager.dispatchNext(); +// Agent completes (mock scenario) +await harness.dispatchManager.completeTask(fixture.tasks.get('Task A')!); +// Verify events +const events = harness.getEventsByType('task:completed'); +expect(events.length).toBe(1); +``` + + npm test passes harness tests + Test harness proven to work for E2E scenarios + + + + + +Before declaring plan complete: +- [ ] `npm run build` succeeds without errors +- [ ] `npm test` passes all tests +- [ ] createTestHarness() returns fully wired system +- [ ] seedFixture() creates complete hierarchies +- [ ] Task dependencies resolved by name +- [ ] MockWorktreeManager integrated +- [ ] At least one E2E flow test passes + + + + +- All tasks completed +- Test harness enables E2E testing without real Claude agents +- Fixtures seed complex task hierarchies +- Full dispatch → coordination flow works with mocks + + + +After completion, create `.planning/phases/07-mock-agent-test-harness/07-02-SUMMARY.md` +