Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | 11x 4x 4x 4x 4x 4x 4x 4x 15x 15x 15x 4x 15x 11x 11x 12x 12x 12x 4x | /**
* Phase Dispatch Router — queue, dispatch, state, child tasks
*/
import { TRPCError } from '@trpc/server';
import { z } from 'zod';
import type { Task } from '../../db/schema.js';
import type { ProcedureBuilder } from '../trpc.js';
import { requirePhaseDispatchManager, requireTaskRepository } from './_helpers.js';
export function phaseDispatchProcedures(publicProcedure: ProcedureBuilder) {
return {
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 };
}),
dispatchNextPhase: publicProcedure
.mutation(async ({ ctx }) => {
const phaseDispatchManager = requirePhaseDispatchManager(ctx);
return phaseDispatchManager.dispatchNextPhase();
}),
getPhaseQueueState: publicProcedure
.query(async ({ ctx }) => {
const phaseDispatchManager = requirePhaseDispatchManager(ctx);
return phaseDispatchManager.getPhaseQueueState();
}),
createChildTasks: publicProcedure
.input(z.object({
parentTaskId: z.string().min(1),
tasks: z.array(z.object({
number: z.number().int().positive(),
name: z.string().min(1),
description: z.string(),
type: z.enum(['auto', 'checkpoint:human-verify', 'checkpoint:decision', 'checkpoint:human-action']).default('auto'),
dependencies: z.array(z.number().int().positive()).optional(),
})),
}))
.mutation(async ({ ctx, input }) => {
const taskRepo = requireTaskRepository(ctx);
const parentTask = await taskRepo.findById(input.parentTaskId);
Iif (!parentTask) {
throw new TRPCError({
code: 'NOT_FOUND',
message: `Parent task '${input.parentTaskId}' not found`,
});
}
Iif (parentTask.category !== 'detail') {
throw new TRPCError({
code: 'BAD_REQUEST',
message: `Parent task must have category 'detail', got '${parentTask.category}'`,
});
}
const numberToId = new Map<number, string>();
const created: Task[] = [];
for (const taskInput of input.tasks) {
const task = await taskRepo.create({
parentTaskId: input.parentTaskId,
phaseId: parentTask.phaseId,
initiativeId: parentTask.initiativeId,
name: taskInput.name,
description: taskInput.description,
type: taskInput.type,
order: taskInput.number,
status: 'pending',
});
numberToId.set(taskInput.number, task.id);
created.push(task);
}
for (const taskInput of input.tasks) {
if (taskInput.dependencies && taskInput.dependencies.length > 0) {
const taskId = numberToId.get(taskInput.number)!;
for (const depNumber of taskInput.dependencies) {
const dependsOnTaskId = numberToId.get(depNumber);
Eif (dependsOnTaskId) {
await taskRepo.createDependency(taskId, dependsOnTaskId);
}
}
}
}
return created;
}),
};
}
|