/** * confidenceEngine.test.ts — Unit test S39 ConfidenceEngine * * Copertura (12 test): * 1. score iniziale 0.5 → level=medium * 2. recordSignal tool_success → score aumenta * 3. recordSignal tool_failure → score diminuisce * 4. build_ok → grande aumento score * 5. build_fail_serious → grande calo score * 6. shouldEscalate: true sotto soglia 0.35 * 7. shouldClose: true sopra soglia 0.72 * 8. reset: ritorna a score iniziale * 9. summary: stringa leggibile con score e conteggi * 10. classifyBuildFailure: "cannot find module" → serious * 11. classifyBuildFailure: singolo TS error → trivial * 12. buildFailureSignal mappa correttamente a kind * 13. DI _setTestDeps: now() mock * 14. score clampato tra 0 e 1 * * SESSIONE: S39 — TaskClassifier + ConfidenceEngine + RequestEnhancer */ import { describe, it, expect, beforeEach, afterEach } from "vitest"; import { ConfidenceSession, createConfidenceSession, classifyBuildFailure, buildFailureSignal, getThresholds, _setTestDeps, _resetDeps, } from "@/lib/confidenceEngine"; afterEach(() => { _resetDeps(); }); // ─── ConfidenceSession ──────────────────────────────────────────────────────── describe("ConfidenceSession", () => { it("1. score iniziale 0.5 → level=medium", () => { const s = createConfidenceSession("task-1"); expect(s.getScore()).toBeCloseTo(0.5); expect(s.getLevel()).toBe("medium"); }); it("2. tool_success → score aumenta", () => { const s = createConfidenceSession("task-2"); const before = s.getScore(); s.recordSignal("tool_success"); expect(s.getScore()).toBeGreaterThan(before); }); it("3. tool_failure → score diminuisce", () => { const s = createConfidenceSession("task-3"); const before = s.getScore(); s.recordSignal("tool_failure"); expect(s.getScore()).toBeLessThan(before); }); it("4. build_ok → aumento significativo score", () => { const s = createConfidenceSession("task-4", 0.4); s.recordSignal("build_ok"); expect(s.getScore()).toBeGreaterThan(0.55); }); it("5. build_fail_serious → calo drastico score", () => { const s = createConfidenceSession("task-5", 0.7); s.recordSignal("build_fail_serious"); expect(s.getScore()).toBeLessThan(0.45); }); it("6. shouldEscalate: true dopo segnali negativi gravi", () => { const s = createConfidenceSession("task-6", 0.5); s.recordSignal("build_fail_serious"); s.recordSignal("llm_refusal"); expect(s.shouldEscalate()).toBe(true); }); it("7. shouldClose: true dopo segnali positivi", () => { const s = createConfidenceSession("task-7", 0.6); s.recordSignal("build_ok"); s.recordSignal("user_confirm"); expect(s.shouldClose()).toBe(true); }); it("8. reset: ritorna allo score iniziale e svuota segnali", () => { const s = createConfidenceSession("task-8", 0.5); s.recordSignal("build_fail_serious"); s.recordSignal("tool_failure"); s.reset(); expect(s.getScore()).toBeCloseTo(0.5); expect(s.getState().signals).toHaveLength(0); }); it("9. summary: stringa che include score e conteggi segnali", () => { const s = createConfidenceSession("task-9"); s.recordSignal("tool_success"); s.recordSignal("tool_failure"); const sum = s.summary(); expect(sum).toContain("%"); expect(sum).toContain("+1"); expect(sum).toContain("-1"); }); it("14. score clampato tra 0 e 1 anche con molti segnali negativi", () => { const s = createConfidenceSession("task-14", 0.1); for (let i = 0; i < 10; i++) s.recordSignal("build_fail_serious"); expect(s.getScore()).toBeGreaterThanOrEqual(0); expect(s.getScore()).toBeLessThanOrEqual(1); }); it("14b. score clampato tra 0 e 1 anche con molti segnali positivi", () => { const s = createConfidenceSession("task-14b", 0.9); for (let i = 0; i < 10; i++) s.recordSignal("build_ok"); expect(s.getScore()).toBeGreaterThanOrEqual(0); expect(s.getScore()).toBeLessThanOrEqual(1); }); }); // ─── classifyBuildFailure ───────────────────────────────────────────────────── describe("classifyBuildFailure", () => { it("10. 'cannot find module' → serious", () => { expect(classifyBuildFailure("Error: Cannot find module './foo'")).toBe("serious"); }); it("10b. molti errori → serious", () => { expect(classifyBuildFailure("27 errors found in build")).toBe("serious"); }); it("10c. dipendenza mancante → serious", () => { expect(classifyBuildFailure("Failed to resolve import 'react' from 'src/main.tsx'")).toBe("serious"); }); it("11. singolo errore TypeScript banale → trivial", () => { expect(classifyBuildFailure("TS2345: Argument of type 'string' is not assignable to 'number'")).toBe("trivial"); }); it("11b. errore di variabile non usata → trivial", () => { expect(classifyBuildFailure("warning: unused variable 'foo'")).toBe("trivial"); }); }); // ─── buildFailureSignal ─────────────────────────────────────────────────────── describe("buildFailureSignal", () => { it("12. errore serio → 'build_fail_serious'", () => { expect(buildFailureSignal("Cannot find module './auth'")).toBe("build_fail_serious"); }); it("12b. errore banale → 'build_fail_trivial'", () => { expect(buildFailureSignal("TS1005: ';' expected")).toBe("build_fail_trivial"); }); }); // ─── DI _setTestDeps ───────────────────────────────────────────────────────── describe("DI _setTestDeps", () => { it("13. now() mock è usato in recordSignal", () => { let t = 1000; _setTestDeps({ now: () => t }); const s = createConfidenceSession("task-di"); s.recordSignal("tool_success"); const sig = s.getState().signals[0]; expect(sig.at).toBe(1000); }); }); // ─── getThresholds ──────────────────────────────────────────────────────────── describe("getThresholds", () => { it("ritorna tutte le soglie operative", () => { const t = getThresholds(); expect(t.high).toBeGreaterThan(t.medium); expect(t.medium).toBeGreaterThan(t.low); expect(t.escalate).toBeGreaterThan(0); expect(t.close).toBeGreaterThan(t.escalate); }); });