feat(FN-4146): append verification subtask to planning flow

FN-4146 adds workspace verification to the planning system, including a new verification subtask in the planning module and reconciling the corresponding route tests. The bulk of the work is in `planning.ts` and its test files, with a minor adjustment to the merger overlap guard test.

Fusion-Task-Id: FN-4146
This commit is contained in:
Fusion
2026-05-12 10:23:28 -07:00
committed by gsxdsm
parent 6c1cb40c35
commit 046c534dcc
5 changed files with 123 additions and 19 deletions

View File

@@ -2214,6 +2214,7 @@ export function getSummary(sessionId: string): PlanningSummary | undefined {
/**
* Generate subtasks from a completed planning summary.
* Uses the planning session's summary to create a SubtaskItem[] for multi-task creation.
* Always appends a final end-to-end verification subtask, regardless of deliverable count.
*
* @param sessionId - The planning session ID
* @returns Array of SubtaskItem with titles derived from keyDeliverables, or fallback
@@ -2244,6 +2245,10 @@ export interface PlanningSubtaskDraft {
dependsOn?: string[];
}
/**
* Generate planning subtasks from a completed planning summary.
* Always appends a final end-to-end verification subtask, regardless of deliverable count.
*/
export function generateSubtasksFromPlanning(sessionId: string): SubtaskItem[] {
const session = sessions.get(sessionId);
if (!session) return [];
@@ -2252,9 +2257,9 @@ export function generateSubtasksFromPlanning(sessionId: string): SubtaskItem[] {
const { summary } = session;
const qaSection = formatInterviewQA(session.history);
// If key deliverables exist, create one subtask per deliverable
// If key deliverables exist, create one subtask per deliverable plus a final verification subtask.
if (summary.keyDeliverables.length > 0) {
return summary.keyDeliverables.map((deliverable, index) => {
const deliverableSubtasks = summary.keyDeliverables.map((deliverable, index) => {
const id = `subtask-${index + 1}`;
const dependsOn = index > 0 ? [`subtask-${index}`] : [] as string[];
return {
@@ -2270,6 +2275,21 @@ export function generateSubtasksFromPlanning(sessionId: string): SubtaskItem[] {
dependsOn,
};
});
deliverableSubtasks.push({
id: `subtask-${summary.keyDeliverables.length + 1}`,
title: "Verify end-to-end",
description: buildPlanningSubtaskDescription({
taskGuidance: "Verify the full plan end-to-end now that all deliverables are implemented. Exercise the integrated behavior described in the plan, confirm acceptance criteria hold, run the project test suite, and capture any follow-ups as new tasks rather than expanding scope.",
summaryDescription: summary.description,
qaSection,
}),
suggestedSize: "S",
priority: summary.priority ?? DEFAULT_TASK_PRIORITY,
dependsOn: [`subtask-${summary.keyDeliverables.length}`],
});
return deliverableSubtasks;
}
// Fallback: 3 subtasks
@@ -2302,7 +2322,7 @@ export function generateSubtasksFromPlanning(sessionId: string): SubtaskItem[] {
id: "subtask-3",
title: "Verify and polish",
description: buildPlanningSubtaskDescription({
taskGuidance: "Verify the implementation end-to-end, then polish quality items like tests, docs, and edge-case handling.",
taskGuidance: "Verify the implementation end-to-end, then polish quality items like tests, docs, and edge-case handling before closing out the plan.",
summaryDescription: summary.description,
qaSection,
}),