diff --git a/src/resources/extensions/sf/auto-prompts.js b/src/resources/extensions/sf/auto-prompts.js index 9ae5c08fc..4e9176929 100644 --- a/src/resources/extensions/sf/auto-prompts.js +++ b/src/resources/extensions/sf/auto-prompts.js @@ -1084,7 +1084,7 @@ export function buildSkillDiscoveryVars() { : ` - Note promising skills in your research output with their install commands, but do NOT install them. - The user will decide which to install.` - }`; +}`; return { skillDiscoveryMode: mode, skillDiscoveryInstructions: instructions, diff --git a/src/resources/extensions/sf/tests/skipped-slice-render.test.mjs b/src/resources/extensions/sf/tests/skipped-slice-render.test.mjs index d6fd08f91..a8f585f1e 100644 --- a/src/resources/extensions/sf/tests/skipped-slice-render.test.mjs +++ b/src/resources/extensions/sf/tests/skipped-slice-render.test.mjs @@ -19,7 +19,13 @@ import { openDatabase, } from "../sf-db.js"; import { renderRoadmapCheckboxes } from "../markdown-renderer.js"; -import { mkdtempSync, rmSync, writeFileSync, mkdirSync, readFileSync } from "node:fs"; +import { + mkdtempSync, + rmSync, + writeFileSync, + mkdirSync, + readFileSync, +} from "node:fs"; import { tmpdir } from "node:os"; import { handleReassessRoadmap } from "../tools/reassess-roadmap.js"; @@ -47,10 +53,38 @@ describe("skipped-slice render", () => { const project = makeProject(); openDatabase(join(project, ".sf", "sf.db")); - insertMilestone({ id: "M990", title: "Skipped slice render test", status: "active" }); - insertSlice({ milestoneId: "M990", id: "S01", title: "Done slice", status: "complete", risk: "low", depends: [], demo: "demo" }); - insertSlice({ milestoneId: "M990", id: "S02", title: "Skipped slice", status: "skipped", risk: "low", depends: [], demo: "skipped-demo" }); - insertSlice({ milestoneId: "M990", id: "S03", title: "Pending slice", status: "pending", risk: "low", depends: [], demo: "pending-demo" }); + insertMilestone({ + id: "M990", + title: "Skipped slice render test", + status: "active", + }); + insertSlice({ + milestoneId: "M990", + id: "S01", + title: "Done slice", + status: "complete", + risk: "low", + depends: [], + demo: "demo", + }); + insertSlice({ + milestoneId: "M990", + id: "S02", + title: "Skipped slice", + status: "skipped", + risk: "low", + depends: [], + demo: "skipped-demo", + }); + insertSlice({ + milestoneId: "M990", + id: "S03", + title: "Pending slice", + status: "pending", + risk: "low", + depends: [], + demo: "pending-demo", + }); // Write a minimal ROADMAP.md with all three unchecked const roadmapDir = join(project, ".sf", "milestones", "M990"); @@ -90,7 +124,15 @@ describe("skipped-slice render", () => { insertMilestone({ id: "M991", title: "Uncheck test", status: "active" }); // S01 is now pending (was incorrectly marked done) - insertSlice({ milestoneId: "M991", id: "S01", title: "Was done", status: "pending", risk: "low", depends: [], demo: "demo" }); + insertSlice({ + milestoneId: "M991", + id: "S01", + title: "Was done", + status: "pending", + risk: "low", + depends: [], + demo: "demo", + }); const roadmapDir = join(project, ".sf", "milestones", "M991"); mkdirSync(roadmapDir, { recursive: true }); @@ -116,10 +158,32 @@ describe("skipped-slice render", () => { const project = makeProject(); openDatabase(join(project, ".sf", "sf.db")); - insertMilestone({ id: "M992", title: "Error message test", status: "active" }); + insertMilestone({ + id: "M992", + title: "Error message test", + status: "active", + }); // S01 was skipped (never executed) - insertSlice({ milestoneId: "M992", id: "S01", title: "Done slice", status: "complete", risk: "low", depends: [], demo: "done", sequence: 1 }); - insertSlice({ milestoneId: "M992", id: "S02", title: "Skipped slice", status: "skipped", risk: "low", depends: [], demo: "skipped", sequence: 2 }); + insertSlice({ + milestoneId: "M992", + id: "S01", + title: "Done slice", + status: "complete", + risk: "low", + depends: [], + demo: "done", + sequence: 1, + }); + insertSlice({ + milestoneId: "M992", + id: "S02", + title: "Skipped slice", + status: "skipped", + risk: "low", + depends: [], + demo: "skipped", + sequence: 2, + }); // Try to modify the skipped slice — should get "slice S02 is skipped" not "cannot modify completed slice" const result = await handleReassessRoadmap( @@ -128,7 +192,19 @@ describe("skipped-slice render", () => { completedSliceId: "S01", verdict: "roadmap-confirmed", assessment: "Test assessment", - sliceChanges: { modified: [{ sliceId: "S02", title: "Skipped", risk: "low", depends: [], demo: "" }], added: [], removed: [] }, + sliceChanges: { + modified: [ + { + sliceId: "S02", + title: "Skipped", + risk: "low", + depends: [], + demo: "", + }, + ], + added: [], + removed: [], + }, }, project, ); @@ -143,9 +219,31 @@ describe("skipped-slice render", () => { const project = makeProject(); openDatabase(join(project, ".sf", "sf.db")); - insertMilestone({ id: "M993", title: "Error label test", status: "active" }); - insertSlice({ milestoneId: "M993", id: "S01", title: "Done slice", status: "complete", risk: "low", depends: [], demo: "done", sequence: 1 }); - insertSlice({ milestoneId: "M993", id: "S02", title: "Skipped slice", status: "skipped", risk: "low", depends: [], demo: "skipped", sequence: 2 }); + insertMilestone({ + id: "M993", + title: "Error label test", + status: "active", + }); + insertSlice({ + milestoneId: "M993", + id: "S01", + title: "Done slice", + status: "complete", + risk: "low", + depends: [], + demo: "done", + sequence: 1, + }); + insertSlice({ + milestoneId: "M993", + id: "S02", + title: "Skipped slice", + status: "skipped", + risk: "low", + depends: [], + demo: "skipped", + sequence: 2, + }); // Try to modify both completed and skipped in the same call // The skipped one should have "skipped" in error, not "completed" @@ -157,7 +255,13 @@ describe("skipped-slice render", () => { assessment: "Test", sliceChanges: { modified: [ - { sliceId: "S02", title: "Changed", risk: "low", depends: [], demo: "" }, + { + sliceId: "S02", + title: "Changed", + risk: "low", + depends: [], + demo: "", + }, ], added: [], removed: [], @@ -172,4 +276,4 @@ describe("skipped-slice render", () => { expect(result.error).toContain("S02"); expect(result.error).not.toContain("cannot modify completed slice"); }); -}); \ No newline at end of file +}); diff --git a/src/resources/extensions/sf/tools/reassess-roadmap.js b/src/resources/extensions/sf/tools/reassess-roadmap.js index 783f569d7..eb6b09854 100644 --- a/src/resources/extensions/sf/tools/reassess-roadmap.js +++ b/src/resources/extensions/sf/tools/reassess-roadmap.js @@ -175,10 +175,11 @@ export async function handleReassessRoadmap(rawParams, basePath) { } for (const modifiedSlice of params.sliceChanges.modified) { if (closedSliceIds.has(modifiedSlice.sliceId)) { - const target = existingSlices.find((s) => s.id === modifiedSlice.sliceId); - const statusLabel = target?.status === "skipped" - ? "skipped" - : "completed"; + const target = existingSlices.find( + (s) => s.id === modifiedSlice.sliceId, + ); + const statusLabel = + target?.status === "skipped" ? "skipped" : "completed"; guardError = `slice ${modifiedSlice.sliceId} is ${statusLabel} — cannot apply metadata modifications`; return; } @@ -186,9 +187,8 @@ export async function handleReassessRoadmap(rawParams, basePath) { for (const removedId of params.sliceChanges.removed) { if (closedSliceIds.has(removedId)) { const target = existingSlices.find((s) => s.id === removedId); - const statusLabel = target?.status === "skipped" - ? "skipped" - : "completed"; + const statusLabel = + target?.status === "skipped" ? "skipped" : "completed"; guardError = `slice ${removedId} is ${statusLabel} — cannot remove`; return; }