diff --git a/src/tests/cli-status.test.ts b/src/tests/cli-status.test.ts new file mode 100644 index 000000000..b51a8f12e --- /dev/null +++ b/src/tests/cli-status.test.ts @@ -0,0 +1,68 @@ +import assert from "node:assert/strict"; +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { afterEach, test } from "vitest"; +import { renderLiveStatus } from "../cli-status.ts"; + +const tempDirs: string[] = []; + +function makeProject(): string { + const dir = mkdtempSync(join(tmpdir(), "sf-cli-status-")); + tempDirs.push(dir); + return dir; +} + +afterEach(() => { + for (const dir of tempDirs) rmSync(dir, { recursive: true, force: true }); + tempDirs.length = 0; +}); + +function snapshot() { + return { + state: { + activeMilestone: { id: "M001", title: "Milestone" }, + activeSlice: { id: "S01", title: "Slice" }, + activeTask: { id: "T01", title: "Task" }, + phase: "executing", + nextAction: "execute", + }, + next: { + action: "dispatch", + unitType: "execute-task", + unitId: "M001/S01/T01", + }, + cost: { total: 0, workers: [] }, + }; +} + +test("renderLiveStatus_when_solver_state_exists_includes_solver_line", () => { + const project = makeProject(); + const solverDir = join(project, ".sf/runtime/autonomous-solver"); + mkdirSync(solverDir, { recursive: true }); + writeFileSync( + join(solverDir, "active.json"), + `${JSON.stringify({ + unitType: "execute-task", + unitId: "M001/S01/T01", + iteration: 3, + maxIterations: 12, + latestCheckpoint: { + outcome: "continue", + summary: "Implementation remains.", + remainingItems: ["Finish enforcement", "Run build"], + }, + })}\n`, + ); + + const rendered = renderLiveStatus(snapshot() as any, { + basePath: project, + model: null, + recentEvents: [], + }); + + assert.match(rendered, /Solver:/); + assert.match(rendered, /execute-task M001\/S01\/T01/); + assert.match(rendered, /iter 3\/12/); + assert.match(rendered, /2 remaining/); +});