diff --git a/src/resources/extensions/sf/tests/workflow-tool-executors.test.ts b/src/resources/extensions/sf/tests/workflow-tool-executors.test.ts index 28d69b4d3..ef67b4716 100644 --- a/src/resources/extensions/sf/tests/workflow-tool-executors.test.ts +++ b/src/resources/extensions/sf/tests/workflow-tool-executors.test.ts @@ -9,7 +9,7 @@ import { } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { test } from 'vitest'; +import { test } from "vitest"; import type { PlanningMeetingRecord } from "../plan-quality.ts"; import { _getAdapter, @@ -172,6 +172,36 @@ test("executeSummarySave persists artifact and returns computed path", async () } }); +test("executeSummarySave marks RESEARCH artifacts as terminal transitions", async () => { + const base = makeTmpBase(); + try { + openTestDb(base); + const result = await inProjectDir(base, () => + executeSummarySave( + { + milestone_id: "M001", + slice_id: "S01", + artifact_type: "RESEARCH", + content: "# Research\n\nfindings", + }, + base, + ), + ); + + assert.equal(result.details.operation, "save_summary"); + assert.equal(result.details.artifact_type, "RESEARCH"); + assert.equal(result.details.terminal_transition, true); + assert.equal(result.details.unit_type, "research"); + assert.match( + result.content[0]?.text ?? "", + /Research unit terminal transition/, + ); + } finally { + closeDatabase(); + cleanup(base); + } +}); + test("executeTaskComplete coerces string verificationEvidence entries", async () => { const base = makeTmpBase(); try { diff --git a/src/resources/extensions/sf/tools/workflow-tool-executors.ts b/src/resources/extensions/sf/tools/workflow-tool-executors.ts index 498e7d9ab..d1da72d47 100644 --- a/src/resources/extensions/sf/tools/workflow-tool-executors.ts +++ b/src/resources/extensions/sf/tools/workflow-tool-executors.ts @@ -160,6 +160,28 @@ export async function executeSummarySave( }, basePath, ); + + // Terminal transition for research units: After successful RESEARCH artifact save, + // research units must terminate or become unable to call planning/milestone-generation tools. + // This prevents the dr-repo M008/S01 issue where research continued into planning. + if (params.artifact_type === "RESEARCH") { + return { + content: [ + { + type: "text", + text: `Saved ${params.artifact_type} artifact to ${relativePath}\n\nResearch unit terminal transition: this research unit has completed its primary artifact and should terminate. Further planning or milestone-generation tools will be blocked.`, + }, + ], + details: { + operation: "save_summary", + path: relativePath, + artifact_type: params.artifact_type, + terminal_transition: true, + unit_type: "research", + }, + }; + } + return { content: [ {