From 39d92d5de985a67f031cc7573696cb8332f25005 Mon Sep 17 00:00:00 2001 From: Lukas May Date: Thu, 5 Mar 2026 21:35:14 +0100 Subject: [PATCH] fix: Add changeset reconciliation to deleteTask and fix missing invalidation Same orphaned-changeset pattern as deletePhase: manually deleting all tasks from a detail changeset now marks it reverted. Also added deleteTask to the invalidation map (was missing entirely). --- apps/server/trpc/routers/task.ts | 24 ++++++++++++++++++++++++ apps/web/src/lib/invalidation.ts | 2 ++ 2 files changed, 26 insertions(+) diff --git a/apps/server/trpc/routers/task.ts b/apps/server/trpc/routers/task.ts index 534f7d7..1f21074 100644 --- a/apps/server/trpc/routers/task.ts +++ b/apps/server/trpc/routers/task.ts @@ -10,6 +10,7 @@ import { requireInitiativeRepository, requirePhaseRepository, requireDispatchManager, + requireChangeSetRepository, } from './_helpers.js'; export function taskProcedures(publicProcedure: ProcedureBuilder) { @@ -152,6 +153,29 @@ export function taskProcedures(publicProcedure: ProcedureBuilder) { .mutation(async ({ ctx, input }) => { const taskRepository = requireTaskRepository(ctx); await taskRepository.delete(input.id); + + // Reconcile any applied changesets that created this task. + // If all created tasks in a changeset are now deleted, mark it reverted. + if (ctx.changeSetRepository) { + try { + const csRepo = requireChangeSetRepository(ctx); + const affectedChangeSets = await csRepo.findAppliedByCreatedEntity('task', input.id); + for (const cs of affectedChangeSets) { + const createdTaskIds = cs.entries + .filter(e => e.entityType === 'task' && e.action === 'create') + .map(e => e.entityId); + const survivingTasks = await Promise.all( + createdTaskIds.map(id => taskRepository.findById(id)), + ); + if (survivingTasks.every(t => t === null)) { + await csRepo.markReverted(cs.id); + } + } + } catch { + // Best-effort reconciliation — don't fail the delete + } + } + return { success: true }; }), diff --git a/apps/web/src/lib/invalidation.ts b/apps/web/src/lib/invalidation.ts index e318aef..d0c767f 100644 --- a/apps/web/src/lib/invalidation.ts +++ b/apps/web/src/lib/invalidation.ts @@ -65,6 +65,8 @@ const INVALIDATION_MAP: Partial> = { createChildTasks: ["listTasks", "listInitiativeTasks", "listPhaseTasks"], queueTask: ["listTasks", "listInitiativeTasks", "listPhaseTasks"], + deleteTask: ["listTasks", "listInitiativeTasks", "listPhaseTasks", "listChangeSets"], + // --- Change Sets --- revertChangeSet: ["listPhases", "listPhaseTasks", "listInitiativeTasks", "listPages", "getPage", "listChangeSets", "getRootPage"],