43 lines
2.5 KiB
TypeScript
43 lines
2.5 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { normalizeAutonomyState, parseRoadmapMarkdown, retryAutonomyBlockerIfDue } from "../src/repositories/autonomyRepository.js";
|
|
import { addDiscoveredTasks, isAutonomyItemReady, orderAutonomyRepairs, workPrompt } from "../src/services/autonomyWork.js";
|
|
|
|
describe("autonomous repair sequencing", () => {
|
|
it("runs an existing prerequisite before retrying a priority user assignment", () => {
|
|
const phase = parseRoadmapMarkdown("## CI\n- Gate Ruff\n- Fix Ruff errors").phases[0];
|
|
const [gate, repair] = phase.items;
|
|
gate.source = "user_assignment";
|
|
expect(addDiscoveredTasks(phase, ["Fix Ruff errors"])).toEqual([]);
|
|
expect(orderAutonomyRepairs(phase, gate, ["Fix Ruff errors"])).toBe(true);
|
|
expect(isAutonomyItemReady(phase, gate)).toBe(false);
|
|
expect(isAutonomyItemReady(phase, repair)).toBe(true);
|
|
repair.status = "completed";
|
|
expect(isAutonomyItemReady(phase, gate)).toBe(true);
|
|
});
|
|
|
|
it("rejects circular repair dependencies and does not duplicate discovered work", () => {
|
|
const phase = parseRoadmapMarkdown("## CI\n- Gate\n- Repair").phases[0];
|
|
orderAutonomyRepairs(phase, phase.items[0], ["Repair"]);
|
|
expect(() => orderAutonomyRepairs(phase, phase.items[1], ["Gate"])).toThrow("AUTO_MODE_DEPENDENCY_CYCLE");
|
|
expect(addDiscoveredTasks(phase, ["Repair", " repair ", "New test"])).toEqual(["New test"]);
|
|
});
|
|
|
|
it("recovers historical technical human blockers with a bounded retry time", () => {
|
|
const roadmap = parseRoadmapMarkdown("## CI\n- Repair");
|
|
roadmap.status = "blocked";
|
|
roadmap.phases[0].status = "blocked";
|
|
const state = normalizeAutonomyState({ enabled: true, roadmap, maxRecoveryMinutes: 120, blocker: { kind: "human", at: "2026-09-01T23:00:00Z", recoveryStartedAt: "2026-09-01T23:00:00Z", reason: "CI validation failed. No approval is required." } });
|
|
expect(state.blocker?.kind).toBe("retryable");
|
|
expect(retryAutonomyBlockerIfDue(state, Date.parse("2026-09-02T00:00:00Z")).status).toBe("running");
|
|
});
|
|
|
|
it("resumes the recorded delivery through merge rather than suggesting a new branch", () => {
|
|
const phase = parseRoadmapMarkdown("## Build\n- Feature").phases[0];
|
|
phase.items[0].deliveryId = "existing-delivery";
|
|
const prompt = workPrompt("implement", phase, phase.items[0]);
|
|
expect(prompt).toContain("Resume delivery 'existing-delivery'");
|
|
expect(prompt).toContain("merge_feature_delivery");
|
|
expect(prompt).toContain("Always report delivery_id");
|
|
});
|
|
});
|