feat(FN-4041): harden empty rawResponse handling in memory-insights

Hardened empty `rawResponse` handling in the memory insights module by adding defensive checks to prevent errors when the response is empty, accompanied by tests to cover those edge cases (FN-4041 Step 1).

Fusion-Task-Id: FN-4041
This commit is contained in:
Fusion
2026-05-11 17:34:20 -07:00
committed by gsxdsm
parent b92ea7121a
commit 55bcf045eb
4 changed files with 85 additions and 5 deletions

View File

@@ -1623,6 +1623,53 @@ describe("approved triage recovery", () => {
);
});
it("preserves imported GitHub issue titles during planning recovery", async () => {
await writeFile(
join(rootDir, ".fusion", "tasks", "FN-001", "PROMPT.md"),
"# Task: FN-001 - Different AI-generated planning title\n\n**Size:** M\n\n## Review Level: 2\n\nRecovered specification",
);
const store = createMockStore({
getSettings: vi.fn().mockResolvedValue({
maxConcurrent: 2,
maxWorktrees: 4,
pollIntervalMs: 10000,
groupOverlappingFiles: false,
autoMerge: true,
requirePlanApproval: false,
} as Settings),
});
const processor = new TriageProcessor(store, rootDir);
const recovered = await processor.recoverApprovedTask({
id: "FN-001",
description: "Imported from GitHub",
column: "triage",
status: "planning",
title: '"Cannot read properties of undefined (reading \'trim\')" when extracting insights',
sourceType: "github_import",
sourceIssue: {
provider: "github",
repository: "Runfusion/Fusion",
externalIssueId: "70",
issueNumber: 70,
url: "https://github.com/Runfusion/Fusion/issues/70",
},
dependencies: [],
steps: [],
currentStep: 0,
log: [{ timestamp: "2026-01-01T00:00:00.000Z", action: "Spec review: APPROVE" }],
createdAt: "2026-01-01T00:00:00.000Z",
updatedAt: "2026-01-01T00:02:00.000Z",
});
expect(recovered).toBe(true);
expect(store.updateTask).not.toHaveBeenCalledWith(
"FN-001",
expect.objectContaining({ title: "Different AI-generated planning title" }),
);
});
it("clears status and error before moving approved tasks to todo", async () => {
const store = createMockStore({
getSettings: vi.fn().mockResolvedValue({