From 4263c0884e74665875e77ad429a4f2e1aabe6d93 Mon Sep 17 00:00:00 2001 From: Lukas May Date: Sun, 1 Feb 2026 11:55:28 +0100 Subject: [PATCH] feat(12-08): add TestHarness decompose mode helpers - Add setArchitectDecomposeComplete and setArchitectDecomposeQuestions helpers - Add planRepository to harness for plan operations - Add createPlan and getTasksForPlan convenience methods - Import TaskBreakdown and Plan types --- src/test/harness.ts | 75 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/src/test/harness.ts b/src/test/harness.ts index f8bdeed..2a7c1e5 100644 --- a/src/test/harness.ts +++ b/src/test/harness.ts @@ -13,7 +13,7 @@ import { EventEmitterBus } from '../events/bus.js'; import type { AgentManager } from '../agent/types.js'; import { MockAgentManager, type MockAgentScenario } from '../agent/mock-manager.js'; import type { PendingQuestions, QuestionItem } from '../agent/types.js'; -import type { Decision, PhaseBreakdown } from '../agent/schema.js'; +import type { Decision, PhaseBreakdown, TaskBreakdown } from '../agent/schema.js'; import type { WorktreeManager, Worktree, WorktreeDiff, MergeResult } from '../git/types.js'; import type { DispatchManager } from '../dispatch/types.js'; import { DefaultDispatchManager } from '../dispatch/manager.js'; @@ -24,13 +24,15 @@ import type { MessageRepository } from '../db/repositories/message-repository.js import type { AgentRepository } from '../db/repositories/agent-repository.js'; import type { InitiativeRepository } from '../db/repositories/initiative-repository.js'; import type { PhaseRepository } from '../db/repositories/phase-repository.js'; -import type { Initiative, Phase } from '../db/schema.js'; +import type { PlanRepository } from '../db/repositories/plan-repository.js'; +import type { Initiative, Phase, Plan, Task } from '../db/schema.js'; import { DrizzleTaskRepository, DrizzleMessageRepository, DrizzleAgentRepository, DrizzleInitiativeRepository, DrizzlePhaseRepository, + DrizzlePlanRepository, } from '../db/repositories/drizzle/index.js'; import { createTestDatabase } from '../db/repositories/drizzle/test-helpers.js'; import { @@ -207,6 +209,8 @@ export interface TestHarness { initiativeRepository: InitiativeRepository; /** Phase repository */ phaseRepository: PhaseRepository; + /** Plan repository */ + planRepository: PlanRepository; // tRPC Caller /** tRPC caller for direct procedure calls */ @@ -312,8 +316,24 @@ export interface TestHarness { phases: PhaseBreakdown[] ): void; + /** + * Set up scenario where architect completes decomposition with tasks. + */ + setArchitectDecomposeComplete( + agentName: string, + tasks: TaskBreakdown[] + ): void; + + /** + * Set up scenario where architect needs questions in decompose mode. + */ + setArchitectDecomposeQuestions( + agentName: string, + questions: QuestionItem[] + ): void; + // ========================================================================== - // Initiative/Phase Convenience Helpers + // Initiative/Phase/Plan Convenience Helpers // ========================================================================== /** @@ -338,6 +358,20 @@ export interface TestHarness { initiativeId: string, phases: Array<{ number: number; name: string; description: string }> ): Promise; + + /** + * Create a plan through tRPC. + */ + createPlan( + phaseId: string, + name: string, + description?: string + ): Promise; + + /** + * Get tasks for a plan through tRPC. + */ + getTasksForPlan(planId: string): Promise; } // ============================================================================= @@ -374,6 +408,7 @@ export function createTestHarness(): TestHarness { const agentRepository = new DrizzleAgentRepository(db); const initiativeRepository = new DrizzleInitiativeRepository(db); const phaseRepository = new DrizzlePhaseRepository(db); + const planRepository = new DrizzlePlanRepository(db); // Create real managers wired to mocks const dispatchManager = new DefaultDispatchManager( @@ -403,6 +438,7 @@ export function createTestHarness(): TestHarness { coordinationManager, initiativeRepository, phaseRepository, + planRepository, }); // Create tRPC caller @@ -425,6 +461,7 @@ export function createTestHarness(): TestHarness { agentRepository, initiativeRepository, phaseRepository, + planRepository, // tRPC Caller caller, @@ -523,8 +560,30 @@ export function createTestHarness(): TestHarness { }); }, + setArchitectDecomposeComplete: ( + agentName: string, + tasks: TaskBreakdown[] + ) => { + agentManager.setScenario(agentName, { + status: 'decompose_complete', + tasks, + delay: 0, + }); + }, + + setArchitectDecomposeQuestions: ( + agentName: string, + questions: QuestionItem[] + ) => { + agentManager.setScenario(agentName, { + status: 'questions', + questions, + delay: 0, + }); + }, + // ======================================================================== - // Initiative/Phase Convenience Helpers + // Initiative/Phase/Plan Convenience Helpers // ======================================================================== getInitiative: async (id: string) => { @@ -549,6 +608,14 @@ export function createTestHarness(): TestHarness { ) => { return caller.createPhasesFromBreakdown({ initiativeId, phases }); }, + + createPlan: (phaseId: string, name: string, description?: string) => { + return caller.createPlan({ phaseId, name, description }); + }, + + getTasksForPlan: (planId: string) => { + return caller.listTasks({ planId }); + }, }; return harness;