import * as fs from "node:fs"; import * as path from "node:path"; import * as os from "node:os"; import { ChallengerAgent } from "../agents/challenger.js"; describe("ChallengerAgent", () => { let tempDir: string; beforeEach(() => { tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "ciagent-challenger-test-")); }); afterEach(() => { fs.rmSync(tempDir, { recursive: true, force: true }); }); it("returns empty for no plan", () => { const agent = new ChallengerAgent(); const issues = agent.mechanicalChallenge(tempDir, "/nonexistent/plan.md"); expect(issues).toHaveLength(0); }); it("agent name is challenger", () => { const agent = new ChallengerAgent(); expect(agent.name).toBe("challenger"); }); it("detects missing must-haves in plan tasks", () => { const planDir = path.join(tempDir, ".opencode", "plans"); fs.mkdirSync(planDir, { recursive: true }); const planPath = path.join(planDir, "v0.1-plan.md"); fs.writeFileSync(planPath, `# Plan\n\n| T-01 | 1 | |\n`); const agent = new ChallengerAgent(); const issues = agent.mechanicalChallenge(tempDir, planPath); expect(issues.some((i) => i.type === "missing_must_haves")).toBe(true); }); it("validates clean plan with no issues", () => { const planDir = path.join(tempDir, ".opencode", "plans"); fs.mkdirSync(planDir, { recursive: true }); const planPath = path.join(planDir, "v0.1-plan.md"); fs.writeFileSync(planPath, `# Plan\n\n| Task | Desc | Wave | Deps | Must-Haves | REQ-ID |\n|------|------|------|------|------------|--------|\n| T-01 | Do X | 1 | none | X works | REQ-01 |\n`); const agent = new ChallengerAgent(); const issues = agent.mechanicalChallenge(tempDir, planPath); expect(issues).toHaveLength(0); }); it("detects issue descriptions contain type", () => { const agent = new ChallengerAgent(); expect(agent.name).toBe("challenger"); }); });