feat(FN-4124): surface mission interview drafts across mission tooling
- Add dashboard API routes and mission interview store support to list and inspect draft missions - Update Mission Manager UI to surface draft interview sessions with styling and regression coverage - Extend CLI mission commands and extension tools to expose draft listings consistently - Document the draft surfacing behavior and include a changeset for the published CLI package Fusion-Task-Id: FN-4124
This commit is contained in:
@@ -526,7 +526,12 @@ describe("bin command routing and fallbacks", () => {
|
||||
|
||||
it("routes mission list alias", async () => {
|
||||
await runBin(["mission", "ls"]);
|
||||
expect(commandMocks.runMissionList).toHaveBeenCalledWith(undefined);
|
||||
expect(commandMocks.runMissionList).toHaveBeenCalledWith(undefined, { includeDrafts: true });
|
||||
});
|
||||
|
||||
it("routes mission list with --no-drafts", async () => {
|
||||
await runBin(["mission", "list", "--no-drafts"]);
|
||||
expect(commandMocks.runMissionList).toHaveBeenCalledWith(undefined, { includeDrafts: false });
|
||||
});
|
||||
|
||||
it("routes mission show alias", async () => {
|
||||
|
||||
@@ -977,7 +977,6 @@ describe.skipIf(!SHOULD_RUN_LEGACY_EXTENSION_INTEGRATION)("fn pi extension (lega
|
||||
|
||||
describe("fn_mission_list", () => {
|
||||
it("returns formatted list of missions", async () => {
|
||||
// First create a mission
|
||||
const createTool = api.tools.get("fn_mission_create")!;
|
||||
await createTool.execute(
|
||||
"c1",
|
||||
@@ -1000,6 +999,44 @@ describe.skipIf(!SHOULD_RUN_LEGACY_EXTENSION_INTEGRATION)("fn pi extension (lega
|
||||
expect(result.content[0].text).toContain("Missions");
|
||||
expect(result.content[0].text).toContain("Summary:");
|
||||
});
|
||||
|
||||
it("includes mission interview drafts by default and exposes them in details", async () => {
|
||||
const store = new TaskStore(tmpDir);
|
||||
await store.init();
|
||||
store.getDatabase().prepare(
|
||||
`INSERT INTO ai_sessions (id, type, status, title, inputPayload, conversationHistory, currentQuestion, result, thinkingOutput, error, projectId, createdAt, updatedAt, lockedByTab, lockedAt)
|
||||
VALUES (?, 'mission_interview', 'awaiting_input', ?, '{}', '[]', NULL, NULL, '', NULL, NULL, ?, ?, NULL, NULL)`,
|
||||
).run("draft-1", "Draft Mission", "2026-05-12T00:00:00.000Z", "2026-05-12T00:00:00.000Z");
|
||||
|
||||
const listTool = api.tools.get("fn_mission_list")!;
|
||||
const result = await listTool.execute("call-1", {}, undefined, undefined, makeCtx(tmpDir));
|
||||
|
||||
expect(result.content[0].text).toContain("Drafts (1)");
|
||||
expect(result.content[0].text).toContain("draft-1: Draft Mission (draft · interview awaiting_input)");
|
||||
expect(result.details.drafts).toEqual([
|
||||
{
|
||||
id: "draft-1",
|
||||
title: "Draft Mission",
|
||||
status: "awaiting_input",
|
||||
updatedAt: "2026-05-12T00:00:00.000Z",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("suppresses mission interview drafts when includeDrafts is false", async () => {
|
||||
const store = new TaskStore(tmpDir);
|
||||
await store.init();
|
||||
store.getDatabase().prepare(
|
||||
`INSERT INTO ai_sessions (id, type, status, title, inputPayload, conversationHistory, currentQuestion, result, thinkingOutput, error, projectId, createdAt, updatedAt, lockedByTab, lockedAt)
|
||||
VALUES (?, 'mission_interview', 'error', ?, '{}', '[]', NULL, NULL, '', NULL, NULL, ?, ?, NULL, NULL)`,
|
||||
).run("draft-2", "Hidden Draft", "2026-05-12T00:00:00.000Z", "2026-05-12T00:00:00.000Z");
|
||||
|
||||
const listTool = api.tools.get("fn_mission_list")!;
|
||||
const result = await listTool.execute("call-1", { includeDrafts: false }, undefined, undefined, makeCtx(tmpDir));
|
||||
|
||||
expect(result.content[0].text).not.toContain("Drafts");
|
||||
expect(result.details.drafts).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("fn_mission_show", () => {
|
||||
|
||||
Reference in New Issue
Block a user