From 6cb99b380f332d11ac0a3e453886d53ef503bad3 Mon Sep 17 00:00:00 2001 From: Janni Turunen Date: Fri, 20 Feb 2026 14:55:24 +0200 Subject: [PATCH] fix(taskctl): add allowImmutable=true to verdict command Store.updateTask (#267) --- packages/opencode/src/tasks/tool.ts | 2 +- packages/opencode/test/tasks/tool.test.ts | 67 +++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/tasks/tool.ts b/packages/opencode/src/tasks/tool.ts index 00a36123c9bc..0ee23954bb2a 100644 --- a/packages/opencode/src/tasks/tool.ts +++ b/packages/opencode/src/tasks/tool.ts @@ -980,7 +980,7 @@ if (params.command === "start") { adversarial_verdict: verdictData, stage: "reviewing", } - }) + }, true) await Store.addComment(projectId, taskId, { author: "adversarial-pipeline", diff --git a/packages/opencode/test/tasks/tool.test.ts b/packages/opencode/test/tasks/tool.test.ts index 910213007b7e..233c80f9bbe0 100644 --- a/packages/opencode/test/tasks/tool.test.ts +++ b/packages/opencode/test/tasks/tool.test.ts @@ -179,4 +179,71 @@ describe("tool.ts - taskctl commands", () => { expect(updated?.pipeline.stage).toBe("done") }) }) + + describe("verdict command", () => { + test("verdict records APPROVED verdict without throwing", async () => { + const worktreePath = path.join(testDataDir, "worktree-verdict") + await fs.mkdir(worktreePath, { recursive: true }) + + const task: any = { + id: TEST_TASK_ID, + job_id: TEST_JOB_ID, + status: "in_progress", + priority: 1, + task_type: "implementation", + parent_issue: 123, + labels: [], + depends_on: [], + assignee: "ses-session789", + assignee_pid: 98765, + worktree: worktreePath, + branch: "feature/test-verdict", + title: "Test task", + description: "Test", + acceptance_criteria: "Test", + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + close_reason: null, + comments: [], + pipeline: { + stage: "adversarial-running", + attempt: 1, + last_activity: new Date().toISOString(), + last_steering: null, + history: [], + adversarial_verdict: null, + }, + } + + await Store.createTask(TEST_PROJECT_ID, task) + + await expect(async () => { + await Store.updateTask(TEST_PROJECT_ID, TEST_TASK_ID, { + status: "review", + pipeline: { + ...task.pipeline, + adversarial_verdict: { + verdict: "APPROVED", + summary: "All checks passed", + issues: [], + created_at: new Date().toISOString(), + }, + stage: "reviewing", + } + }, true) + + await Store.addComment(TEST_PROJECT_ID, TEST_TASK_ID, { + author: "adversarial-pipeline", + message: "Verdict: APPROVED — All checks passed", + created_at: new Date().toISOString(), + }) + }).not.toThrow() + + const updated = await Store.getTask(TEST_PROJECT_ID, TEST_TASK_ID) + expect(updated?.status).toBe("review") + expect(updated?.pipeline.stage).toBe("reviewing") + expect(updated?.pipeline.adversarial_verdict?.verdict).toBe("APPROVED") + expect(updated?.pipeline.adversarial_verdict?.summary).toBe("All checks passed") + }) + }) }) \ No newline at end of file