feat: Make initiative branch and execution mode editable from header
- Execution mode badge toggles between YOLO/REVIEW on click - Branch badge opens inline editor (input + save/cancel) - Branch editing locked once any task has left pending status - Server-side guard rejects branch changes after work has started - getInitiative returns branchLocked flag - updateInitiativeConfig now accepts optional branch field
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
import { TRPCError } from '@trpc/server';
|
||||
import { z } from 'zod';
|
||||
import type { ProcedureBuilder } from '../trpc.js';
|
||||
import { requireInitiativeRepository, requireProjectRepository } from './_helpers.js';
|
||||
import { requireInitiativeRepository, requireProjectRepository, requireTaskRepository } from './_helpers.js';
|
||||
|
||||
export function initiativeProcedures(publicProcedure: ProcedureBuilder) {
|
||||
return {
|
||||
@@ -87,7 +87,13 @@ export function initiativeProcedures(publicProcedure: ProcedureBuilder) {
|
||||
projects = fullProjects.map((p) => ({ id: p.id, name: p.name, url: p.url }));
|
||||
}
|
||||
|
||||
return { ...initiative, projects };
|
||||
let branchLocked = false;
|
||||
if (ctx.taskRepository) {
|
||||
const tasks = await ctx.taskRepository.findByInitiativeId(input.id);
|
||||
branchLocked = tasks.some((t) => t.status !== 'pending');
|
||||
}
|
||||
|
||||
return { ...initiative, projects, branchLocked };
|
||||
}),
|
||||
|
||||
updateInitiative: publicProcedure
|
||||
@@ -107,6 +113,7 @@ export function initiativeProcedures(publicProcedure: ProcedureBuilder) {
|
||||
initiativeId: z.string().min(1),
|
||||
mergeRequiresApproval: z.boolean().optional(),
|
||||
executionMode: z.enum(['yolo', 'review_per_phase']).optional(),
|
||||
branch: z.string().nullable().optional(),
|
||||
}))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const repo = requireInitiativeRepository(ctx);
|
||||
@@ -120,6 +127,18 @@ export function initiativeProcedures(publicProcedure: ProcedureBuilder) {
|
||||
});
|
||||
}
|
||||
|
||||
// Prevent branch changes once work has started
|
||||
if (data.branch !== undefined && ctx.taskRepository) {
|
||||
const tasks = await ctx.taskRepository.findByInitiativeId(initiativeId);
|
||||
const hasStarted = tasks.some((t) => t.status !== 'pending');
|
||||
if (hasStarted) {
|
||||
throw new TRPCError({
|
||||
code: 'PRECONDITION_FAILED',
|
||||
message: 'Cannot change branch after work has started',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return repo.update(initiativeId, data);
|
||||
}),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user