import { describe, expect, it } from "vitest"; import { chooseNextAutonomyWork, planParallelAutonomyWork } from "../src/services/autonomyScheduler.js"; import { parseRoadmapMarkdown } from "../src/repositories/autonomyRepository.js"; describe("smart autonomy scheduler", () => { it("chooses the independent item that unlocks the most downstream work", () => { const roadmap = parseRoadmapMarkdown("## Delivery\n- [ ] A\n- [ ] B\n- [ ] C\n- [ ] D"); const [a, b, c, d] = roadmap.phases[0].items; c.dependsOn = [a.id]; d.dependsOn = [a.id]; b.priority = 80; const selected = chooseNextAutonomyWork(roadmap.phases, 0); expect(selected?.item.id).toBe(a.id); expect(selected?.downstreamCount).toBe(2); }); it("does not group likely path-conflicting work in parallel", () => { const roadmap = parseRoadmapMarkdown("## Delivery\n- [ ] A\n- [ ] B\n- [ ] C"); const [a, b, c] = roadmap.phases[0].items; a.touchedPaths = ["src/shared/project.ts"]; b.touchedPaths = ["src/shared/project.ts"]; c.touchedPaths = ["src/other.ts"]; const candidates = chooseNextAutonomyWork(roadmap.phases, 0); expect(candidates?.item).toBeTruthy(); const all = roadmap.phases[0].items.map((item) => ({ item, phase: roadmap.phases[0], phaseIndex: 0, score: 1, downstreamCount: 0, conflictKeys: (item.touchedPaths ?? []).map((path) => `path:${path}`) })); const groups = planParallelAutonomyWork(all); expect(groups.some((group) => group.includes(a.id) && group.includes(b.id))).toBe(false); }); it("can deliberately favor downstream impact when a command changes scheduling policy", () => { const roadmap = parseRoadmapMarkdown("## Delivery\n- [ ] A\n- [ ] B\n- [ ] C\n- [ ] D"); const [a, b, c, d] = roadmap.phases[0].items; c.dependsOn = [a.id]; d.dependsOn = [a.id]; b.priority = 100; expect(chooseNextAutonomyWork(roadmap.phases, 0, "downstream-impact")?.item.id).toBe(a.id); }); it("does not claim work while its external dependency is unavailable", () => { const roadmap = parseRoadmapMarkdown("## Delivery\n- [ ] A\n- [ ] B"); roadmap.phases[0].items[0].waitingExternal = true; expect(chooseNextAutonomyWork(roadmap.phases, 0)?.item.id).toBe(roadmap.phases[0].items[1].id); }); });