feat(12-04): add Plan tRPC procedures
- Import PlanRepository type - Add requirePlanRepository helper - Add createPlan procedure (auto-assigns number if not provided) - Add listPlans procedure (returns plans ordered by number) - Add getPlan procedure (throws NOT_FOUND if not found) - Add updatePlan procedure (name, description, status)
This commit is contained in:
@@ -13,9 +13,10 @@ import type { TaskRepository } from '../db/repositories/task-repository.js';
|
||||
import type { MessageRepository } from '../db/repositories/message-repository.js';
|
||||
import type { InitiativeRepository } from '../db/repositories/initiative-repository.js';
|
||||
import type { PhaseRepository } from '../db/repositories/phase-repository.js';
|
||||
import type { PlanRepository } from '../db/repositories/plan-repository.js';
|
||||
import type { DispatchManager } from '../dispatch/types.js';
|
||||
import type { CoordinationManager } from '../coordination/types.js';
|
||||
import type { Phase } from '../db/schema.js';
|
||||
import type { Phase, Plan } from '../db/schema.js';
|
||||
import { buildDiscussPrompt, buildBreakdownPrompt } from '../agent/prompts.js';
|
||||
|
||||
/**
|
||||
@@ -264,6 +265,19 @@ function requirePhaseRepository(ctx: TRPCContext): PhaseRepository {
|
||||
return ctx.phaseRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to ensure planRepository is available in context.
|
||||
*/
|
||||
function requirePlanRepository(ctx: TRPCContext): PlanRepository {
|
||||
if (!ctx.planRepository) {
|
||||
throw new TRPCError({
|
||||
code: 'INTERNAL_SERVER_ERROR',
|
||||
message: 'Plan repository not available',
|
||||
});
|
||||
}
|
||||
return ctx.planRepository;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Application Router with Procedures
|
||||
// =============================================================================
|
||||
@@ -841,6 +855,79 @@ export const appRouter = router({
|
||||
return created;
|
||||
}),
|
||||
|
||||
// ===========================================================================
|
||||
// Plan Procedures
|
||||
// ===========================================================================
|
||||
|
||||
/**
|
||||
* Create a new plan for a phase.
|
||||
* Auto-assigns the next plan number if not provided.
|
||||
*/
|
||||
createPlan: publicProcedure
|
||||
.input(z.object({
|
||||
phaseId: z.string().min(1),
|
||||
number: z.number().int().positive().optional(),
|
||||
name: z.string().min(1),
|
||||
description: z.string().optional(),
|
||||
}))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const repo = requirePlanRepository(ctx);
|
||||
const number = input.number ?? await repo.getNextNumber(input.phaseId);
|
||||
return repo.create({
|
||||
phaseId: input.phaseId,
|
||||
number,
|
||||
name: input.name,
|
||||
description: input.description ?? null,
|
||||
status: 'pending',
|
||||
});
|
||||
}),
|
||||
|
||||
/**
|
||||
* List plans for a phase.
|
||||
* Returns plans ordered by number.
|
||||
*/
|
||||
listPlans: publicProcedure
|
||||
.input(z.object({ phaseId: z.string().min(1) }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const repo = requirePlanRepository(ctx);
|
||||
return repo.findByPhaseId(input.phaseId);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Get a plan by ID.
|
||||
* Throws NOT_FOUND if plan doesn't exist.
|
||||
*/
|
||||
getPlan: publicProcedure
|
||||
.input(z.object({ id: z.string().min(1) }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const repo = requirePlanRepository(ctx);
|
||||
const plan = await repo.findById(input.id);
|
||||
if (!plan) {
|
||||
throw new TRPCError({
|
||||
code: 'NOT_FOUND',
|
||||
message: `Plan '${input.id}' not found`,
|
||||
});
|
||||
}
|
||||
return plan;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Update a plan.
|
||||
* Returns the updated plan.
|
||||
*/
|
||||
updatePlan: publicProcedure
|
||||
.input(z.object({
|
||||
id: z.string().min(1),
|
||||
name: z.string().min(1).optional(),
|
||||
description: z.string().optional(),
|
||||
status: z.enum(['pending', 'in_progress', 'completed']).optional(),
|
||||
}))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const repo = requirePlanRepository(ctx);
|
||||
const { id, ...data } = input;
|
||||
return repo.update(id, data);
|
||||
}),
|
||||
|
||||
// ===========================================================================
|
||||
// Architect Spawn Procedures
|
||||
// ===========================================================================
|
||||
|
||||
Reference in New Issue
Block a user