feat(14-05): add phase dependency and dispatch procedures
- Import PhaseDispatchManager type from dispatch module - Add requirePhaseDispatchManager helper function - Add createPhaseDependency: creates dependency between two phases - Add getPhaseDependencies: returns phase IDs that a phase depends on - Add queuePhase: queues phase for dispatch - Add dispatchNextPhase: dispatches next available phase - Add getPhaseQueueState: returns phase queue state All procedures follow existing naming conventions and error handling patterns.
This commit is contained in:
@@ -14,7 +14,7 @@ import type { MessageRepository } from '../db/repositories/message-repository.js
|
|||||||
import type { InitiativeRepository } from '../db/repositories/initiative-repository.js';
|
import type { InitiativeRepository } from '../db/repositories/initiative-repository.js';
|
||||||
import type { PhaseRepository } from '../db/repositories/phase-repository.js';
|
import type { PhaseRepository } from '../db/repositories/phase-repository.js';
|
||||||
import type { PlanRepository } from '../db/repositories/plan-repository.js';
|
import type { PlanRepository } from '../db/repositories/plan-repository.js';
|
||||||
import type { DispatchManager } from '../dispatch/types.js';
|
import type { DispatchManager, PhaseDispatchManager } from '../dispatch/types.js';
|
||||||
import type { CoordinationManager } from '../coordination/types.js';
|
import type { CoordinationManager } from '../coordination/types.js';
|
||||||
import type { Phase, Plan, Task } from '../db/schema.js';
|
import type { Phase, Plan, Task } from '../db/schema.js';
|
||||||
import { buildDiscussPrompt, buildBreakdownPrompt, buildDecomposePrompt } from '../agent/prompts.js';
|
import { buildDiscussPrompt, buildBreakdownPrompt, buildDecomposePrompt } from '../agent/prompts.js';
|
||||||
@@ -278,6 +278,19 @@ function requirePlanRepository(ctx: TRPCContext): PlanRepository {
|
|||||||
return ctx.planRepository;
|
return ctx.planRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to ensure phaseDispatchManager is available in context.
|
||||||
|
*/
|
||||||
|
function requirePhaseDispatchManager(ctx: TRPCContext): PhaseDispatchManager {
|
||||||
|
if (!ctx.phaseDispatchManager) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: 'INTERNAL_SERVER_ERROR',
|
||||||
|
message: 'Phase dispatch manager not available',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return ctx.phaseDispatchManager;
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Application Router with Procedures
|
// Application Router with Procedures
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
@@ -855,6 +868,87 @@ export const appRouter = router({
|
|||||||
return created;
|
return created;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a dependency between two phases.
|
||||||
|
* The phase with phaseId depends on the phase with dependsOnPhaseId.
|
||||||
|
*/
|
||||||
|
createPhaseDependency: publicProcedure
|
||||||
|
.input(z.object({
|
||||||
|
phaseId: z.string().min(1),
|
||||||
|
dependsOnPhaseId: z.string().min(1),
|
||||||
|
}))
|
||||||
|
.mutation(async ({ ctx, input }) => {
|
||||||
|
const repo = requirePhaseRepository(ctx);
|
||||||
|
|
||||||
|
// Validate both phases exist
|
||||||
|
const phase = await repo.findById(input.phaseId);
|
||||||
|
if (!phase) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: 'NOT_FOUND',
|
||||||
|
message: `Phase '${input.phaseId}' not found`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const dependsOnPhase = await repo.findById(input.dependsOnPhaseId);
|
||||||
|
if (!dependsOnPhase) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: 'NOT_FOUND',
|
||||||
|
message: `Phase '${input.dependsOnPhaseId}' not found`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await repo.createDependency(input.phaseId, input.dependsOnPhaseId);
|
||||||
|
return { success: true };
|
||||||
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get dependencies for a phase.
|
||||||
|
* Returns IDs of phases that this phase depends on.
|
||||||
|
*/
|
||||||
|
getPhaseDependencies: publicProcedure
|
||||||
|
.input(z.object({ phaseId: z.string().min(1) }))
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const repo = requirePhaseRepository(ctx);
|
||||||
|
const dependencies = await repo.getDependencies(input.phaseId);
|
||||||
|
return { dependencies };
|
||||||
|
}),
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
// Phase Dispatch Procedures
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue a phase for dispatch.
|
||||||
|
* Phase will be dispatched when all dependencies complete.
|
||||||
|
*/
|
||||||
|
queuePhase: publicProcedure
|
||||||
|
.input(z.object({ phaseId: z.string().min(1) }))
|
||||||
|
.mutation(async ({ ctx, input }) => {
|
||||||
|
const phaseDispatchManager = requirePhaseDispatchManager(ctx);
|
||||||
|
await phaseDispatchManager.queuePhase(input.phaseId);
|
||||||
|
return { success: true };
|
||||||
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch next available phase.
|
||||||
|
* Returns dispatch result with phase info.
|
||||||
|
*/
|
||||||
|
dispatchNextPhase: publicProcedure
|
||||||
|
.mutation(async ({ ctx }) => {
|
||||||
|
const phaseDispatchManager = requirePhaseDispatchManager(ctx);
|
||||||
|
return phaseDispatchManager.dispatchNextPhase();
|
||||||
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current phase queue state.
|
||||||
|
* Returns queued, ready, and blocked phase counts.
|
||||||
|
*/
|
||||||
|
getPhaseQueueState: publicProcedure
|
||||||
|
.query(async ({ ctx }) => {
|
||||||
|
const phaseDispatchManager = requirePhaseDispatchManager(ctx);
|
||||||
|
return phaseDispatchManager.getPhaseQueueState();
|
||||||
|
}),
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// Plan Procedures
|
// Plan Procedures
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user