From a7eee9b92eef563a53b052d98c8806b10dc45804 Mon Sep 17 00:00:00 2001 From: JulioMCruz Date: Wed, 22 Jul 2026 08:15:46 -0400 Subject: [PATCH] Persist canonical task lifecycle state --- src/tools/taskStatusPolicy.ts | 7 +++++++ src/tools/updateTaskStatus.ts | 6 +++++- tests/task-status.test.ts | 14 +++++++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/tools/taskStatusPolicy.ts b/src/tools/taskStatusPolicy.ts index 8babf5c..1674b6a 100644 --- a/src/tools/taskStatusPolicy.ts +++ b/src/tools/taskStatusPolicy.ts @@ -2,3 +2,10 @@ export function isTerminalTaskTransition(current: unknown, requested: string): boolean { return current === "Done" && requested !== "Done"; } + +export function dispatchStateForStatus(status: string): "queued" | "working" | "review" | "completed" { + if (status === "In progress") return "working"; + if (status === "Review") return "review"; + if (status === "Done") return "completed"; + return "queued"; +} diff --git a/src/tools/updateTaskStatus.ts b/src/tools/updateTaskStatus.ts index 7273ffb..638861c 100644 --- a/src/tools/updateTaskStatus.ts +++ b/src/tools/updateTaskStatus.ts @@ -33,7 +33,7 @@ import { db } from "../firestore.js"; import { logActivity } from "../activityEvents.js"; import type { Tool } from "./types.js"; import { redactClaimTokens } from "./outputSanitizer.js"; -import { isTerminalTaskTransition } from "./taskStatusPolicy.js"; +import { dispatchStateForStatus, isTerminalTaskTransition } from "./taskStatusPolicy.js"; const ProofSchema = z .object({ @@ -158,7 +158,11 @@ export const updateTaskStatus: Tool = { // Terminal statuses release the worker-protocol flag. if (effectiveStatus === "Done" || effectiveStatus === "Review") { patch.workerProtocol = FieldValue.delete(); + patch.claim = FieldValue.delete(); + patch.nextDispatchAtMs = FieldValue.delete(); + patch.lastDispatchError = FieldValue.delete(); } + patch.dispatchState = dispatchStateForStatus(effectiveStatus); await taskRef.update(patch); diff --git a/tests/task-status.test.ts b/tests/task-status.test.ts index 5bb5e91..e2ba0a7 100644 --- a/tests/task-status.test.ts +++ b/tests/task-status.test.ts @@ -1,6 +1,9 @@ import { describe, expect, it } from "vitest"; -import { isTerminalTaskTransition } from "../src/tools/taskStatusPolicy.js"; +import { + dispatchStateForStatus, + isTerminalTaskTransition, +} from "../src/tools/taskStatusPolicy.js"; describe("isTerminalTaskTransition", () => { it.each(["Backlog", "In progress", "Review"])( @@ -15,3 +18,12 @@ describe("isTerminalTaskTransition", () => { expect(isTerminalTaskTransition("In progress", "Done")).toBe(false); }); }); + +describe("dispatchStateForStatus", () => { + it("maps worker status updates to stable user-facing progress states", () => { + expect(dispatchStateForStatus("Backlog")).toBe("queued"); + expect(dispatchStateForStatus("In progress")).toBe("working"); + expect(dispatchStateForStatus("Review")).toBe("review"); + expect(dispatchStateForStatus("Done")).toBe("completed"); + }); +});