feat(FN-2604): merge fusion/fn-2604 (auto-resolved)
- feat(FN-2604): complete Step 8 — add changeset and delivery docs - test(FN-2604): complete Step 7 — align tests and regenerate extension skill docs - test(FN-2604): complete Step 6 — update dashboard tests for planning statuses - feat(FN-2604): complete Step 5 — update CLI planning terminology - feat(FN-2604): complete Step 4 — update workflow route status strings - feat(FN-2604): complete Step 3 — update settings planning terminology - feat(FN-2604): complete Step 2 — rename replanning actions in column and spec editor - feat(FN-2604): complete Step 1 — update dashboard component status strings
This commit is contained in:
@@ -1946,30 +1946,30 @@ describe("POST /tasks/:id/retry", () => {
|
||||
expect(store.logEntry).toHaveBeenCalledWith("KB-001", "Retry requested from dashboard (stuck kill budget reset)");
|
||||
});
|
||||
|
||||
it("retries a stranded specifying triage task in triage and removes stale prompt", async () => {
|
||||
it("retries a stranded planning triage task in triage and removes stale prompt", async () => {
|
||||
const tempRoot = mkdtempSync(join(tmpdir(), "kb-task-retry-spec-"));
|
||||
const taskDir = join(tempRoot, ".fusion", "tasks", "FN-001");
|
||||
mkdirSync(taskDir, { recursive: true });
|
||||
writeFileSync(join(taskDir, "PROMPT.md"), "# stale spec\n");
|
||||
|
||||
const specifyingTask = {
|
||||
const planningTask = {
|
||||
...FAKE_TASK_DETAIL,
|
||||
column: "triage" as const,
|
||||
status: "specifying",
|
||||
status: "planning",
|
||||
stuckKillCount: 6,
|
||||
recoveryRetryCount: 2,
|
||||
nextRecoveryAt: new Date(Date.now() + 60_000).toISOString(),
|
||||
};
|
||||
const retriedTask = {
|
||||
...specifyingTask,
|
||||
status: "needs-respecify",
|
||||
...planningTask,
|
||||
status: "needs-replan",
|
||||
stuckKillCount: 0,
|
||||
recoveryRetryCount: undefined,
|
||||
nextRecoveryAt: undefined,
|
||||
};
|
||||
|
||||
(store.getTask as ReturnType<typeof vi.fn>)
|
||||
.mockResolvedValueOnce(specifyingTask)
|
||||
.mockResolvedValueOnce(planningTask)
|
||||
.mockResolvedValueOnce(retriedTask);
|
||||
(store.updateTask as ReturnType<typeof vi.fn>).mockResolvedValue(retriedTask);
|
||||
(store.getRootDir as ReturnType<typeof vi.fn>).mockReturnValue(tempRoot);
|
||||
@@ -1981,7 +1981,7 @@ describe("POST /tasks/:id/retry", () => {
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(store.updateTask).toHaveBeenCalledWith("KB-001", {
|
||||
status: "needs-respecify",
|
||||
status: "needs-replan",
|
||||
error: null,
|
||||
worktree: null,
|
||||
branch: null,
|
||||
@@ -1995,9 +1995,9 @@ describe("POST /tasks/:id/retry", () => {
|
||||
expect(existsSync(join(taskDir, "PROMPT.md"))).toBe(false);
|
||||
expect(store.logEntry).toHaveBeenCalledWith(
|
||||
"KB-001",
|
||||
"Retry requested from dashboard (specification retry budget reset)",
|
||||
"Retry requested from dashboard (planning retry budget reset)",
|
||||
);
|
||||
expect(res.body.status).toBe("needs-respecify");
|
||||
expect(res.body.status).toBe("needs-replan");
|
||||
} finally {
|
||||
rmSync(tempRoot, { recursive: true, force: true });
|
||||
}
|
||||
@@ -6916,7 +6916,7 @@ describe("POST /tasks/:id/spec/revise", () => {
|
||||
);
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-001", "triage");
|
||||
expect(existsSync(join(taskDir, "PROMPT.md"))).toBe(false);
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-001", { status: "needs-respecify" });
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-001", { status: "needs-replan" });
|
||||
} finally {
|
||||
rmSync(tempRoot, { recursive: true, force: true });
|
||||
}
|
||||
@@ -6944,7 +6944,7 @@ describe("POST /tasks/:id/spec/revise", () => {
|
||||
|
||||
it("allows spec revision for task already in triage", async () => {
|
||||
const triageTask = { ...FAKE_TASK_DETAIL, column: "triage" as const };
|
||||
const updatedTask = { ...FAKE_TASK_DETAIL, column: "triage" as const, status: "needs-respecify" as const };
|
||||
const updatedTask = { ...FAKE_TASK_DETAIL, column: "triage" as const, status: "needs-replan" as const };
|
||||
const tempRoot = mkdtempSync(join(tmpdir(), "kb-spec-revise-triage-"));
|
||||
const taskDir = join(tempRoot, ".fusion", "tasks", "FN-001");
|
||||
mkdirSync(taskDir, { recursive: true });
|
||||
@@ -6973,7 +6973,7 @@ describe("POST /tasks/:id/spec/revise", () => {
|
||||
);
|
||||
expect(store.moveTask).not.toHaveBeenCalled();
|
||||
expect(existsSync(join(taskDir, "PROMPT.md"))).toBe(false);
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-001", { status: "needs-respecify" });
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-001", { status: "needs-replan" });
|
||||
} finally {
|
||||
rmSync(tempRoot, { recursive: true, force: true });
|
||||
}
|
||||
@@ -7149,7 +7149,7 @@ describe("POST /tasks/:id/spec/rebuild", () => {
|
||||
);
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-001", "triage");
|
||||
expect(existsSync(join(taskDir, "PROMPT.md"))).toBe(false);
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-001", { status: "needs-respecify" });
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-001", { status: "needs-replan" });
|
||||
} finally {
|
||||
rmSync(tempRoot, { recursive: true, force: true });
|
||||
}
|
||||
@@ -7167,7 +7167,7 @@ describe("POST /tasks/:id/spec/rebuild", () => {
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-001", "triage");
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-001", { status: "needs-respecify" });
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-001", { status: "needs-replan" });
|
||||
});
|
||||
|
||||
it("rebuilds spec and moves task from done to triage", async () => {
|
||||
@@ -7186,7 +7186,7 @@ describe("POST /tasks/:id/spec/rebuild", () => {
|
||||
|
||||
it("allows rebuild for task already in triage", async () => {
|
||||
const triageTask = { ...FAKE_TASK_DETAIL, column: "triage" as const };
|
||||
const updatedTask = { ...FAKE_TASK_DETAIL, column: "triage" as const, status: "needs-respecify" as const };
|
||||
const updatedTask = { ...FAKE_TASK_DETAIL, column: "triage" as const, status: "needs-replan" as const };
|
||||
const tempRoot = mkdtempSync(join(tmpdir(), "kb-spec-rebuild-triage-"));
|
||||
const taskDir = join(tempRoot, ".fusion", "tasks", "FN-001");
|
||||
mkdirSync(taskDir, { recursive: true });
|
||||
@@ -7208,7 +7208,7 @@ describe("POST /tasks/:id/spec/rebuild", () => {
|
||||
);
|
||||
expect(store.moveTask).not.toHaveBeenCalled();
|
||||
expect(existsSync(join(taskDir, "PROMPT.md"))).toBe(false);
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-001", { status: "needs-respecify" });
|
||||
expect(store.updateTask).toHaveBeenCalledWith("FN-001", { status: "needs-replan" });
|
||||
} finally {
|
||||
rmSync(tempRoot, { recursive: true, force: true });
|
||||
}
|
||||
@@ -7288,7 +7288,7 @@ describe("POST /tasks/:id/approve-plan", () => {
|
||||
});
|
||||
|
||||
it("returns 400 when task does not have awaiting-approval status", async () => {
|
||||
const triageTask = { ...FAKE_TASK_DETAIL, column: "triage" as const, status: "specifying" as const };
|
||||
const triageTask = { ...FAKE_TASK_DETAIL, column: "triage" as const, status: "planning" as const };
|
||||
(store.getTask as ReturnType<typeof vi.fn>).mockResolvedValue(triageTask);
|
||||
|
||||
const res = await REQUEST(buildApp(), "POST", "/api/tasks/KB-001/approve-plan");
|
||||
@@ -7364,7 +7364,7 @@ describe("POST /tasks/:id/reject-plan", () => {
|
||||
});
|
||||
|
||||
it("returns 400 when task does not have awaiting-approval status", async () => {
|
||||
const triageTask = { ...FAKE_TASK_DETAIL, column: "triage" as const, status: "specifying" as const };
|
||||
const triageTask = { ...FAKE_TASK_DETAIL, column: "triage" as const, status: "planning" as const };
|
||||
(store.getTask as ReturnType<typeof vi.fn>).mockResolvedValue(triageTask);
|
||||
|
||||
const res = await REQUEST(buildApp(), "POST", "/api/tasks/KB-001/reject-plan");
|
||||
|
||||
Reference in New Issue
Block a user