/**
 * no-issues.test.ts — Tests 10-12 for the deterministic no-issues card.
 *
 * D0042: vitest only.
 * AI-SPEC §1b failure-mode #7: sycophancy guard — firing rate ≤30%.
 */
import { describe, expect, it } from "vitest";
import { NO_ISSUES_THRESHOLD, NoIssuesBodySchema, generateNoIssues, } from "../no-issues.js";
// Compile-time gate
const _satisfiesCheck = NoIssuesBodySchema;
const silentLogger = {
    debug: () => { },
    info: () => { },
    warn: () => { },
    error: () => { },
    step: () => { },
    section: () => { },
    table: () => { },
};
const noopProgress = {
    phaseStart: () => { },
    phaseProgress: () => { },
    phaseComplete: () => { },
};
function makeCtx() {
    return {
        llm: undefined,
        model: "anthropic:claude-sonnet-4-6",
        logger: silentLogger,
        progress: noopProgress,
        versions: {
            graderJudgmentsVersion: "1.0.0",
            ensembleVersion: "1.0.0",
            diagnosisVersion: "0.1.0",
            cardVersion: "1.0.0",
        },
        runId: "run-001",
        reportId: "report-001",
    };
}
function makeReportWithScores(scores) {
    return {
        id: "report-001",
        completedAt: "2026-01-01T00:00:00Z",
        durationMs: 1000,
        provenance: {
            runId: "run-001",
            mode: "standard",
            areas: [],
            taskIds: [],
            models: [],
            graderModel: "gpt-4o",
            source: "local",
            evalFingerprint: "",
            trigger: "manual",
            git: undefined,
        },
        summary: {
            belowCritical: [],
            lowestArea: scores.length ? `area-0` : "",
            lowestScore: scores.length ? Math.min(...scores) : 0,
            overall: {
                avgCeilingScore: 90,
                avgScore: scores.length
                    ? scores.reduce((a, b) => a + b, 0) / scores.length
                    : 0,
                avgDocLift: 5,
                avgDocQualityGap: 10,
                avgFloorScore: 80,
                negativeDocLiftCount: 0,
            },
            scores: scores.map((s, i) => ({
                feature: `area-${i}`,
                ceilingScore: 95,
                codeCorrectness: s,
                docCoverage: s,
                docLift: 5,
                docQualityGap: 5,
                floorScore: s - 5,
                negativeDocLift: false,
                taskCompletion: s,
                testCount: 10,
                totalCost: 0.05,
                totalScore: s,
            })),
        },
    };
}
describe("NO_ISSUES_THRESHOLD (Test 10)", () => {
    it("is exported as a const with a numeric value", () => {
        expect(typeof NO_ISSUES_THRESHOLD).toBe("number");
        expect(NO_ISSUES_THRESHOLD).toBeGreaterThan(0);
        expect(NO_ISSUES_THRESHOLD).toBeLessThanOrEqual(100);
        // compile-time gate
        expect(_satisfiesCheck).toBeDefined();
    });
});
describe("generateNoIssues — ready when all areas ≥ threshold (Test 11a)", () => {
    it("returns ready card with thresholdScore when all areas score ≥ threshold", async () => {
        const scores = [
            NO_ISSUES_THRESHOLD,
            NO_ISSUES_THRESHOLD + 5,
            NO_ISSUES_THRESHOLD + 10,
        ];
        const report = makeReportWithScores(scores);
        const card = await generateNoIssues(report, makeCtx());
        expect(card.status).toBe("ready");
        if (card.status === "ready") {
            expect(card.cardType).toBe("no-issues");
            expect(card.meta.cardVersion).toBe("no-issues@0.1.0");
            const body = card.body;
            expect(body.thresholdScore).toBe(NO_ISSUES_THRESHOLD);
            expect(body.summary).toBeTruthy();
        }
    });
});
describe("generateNoIssues — missing when any area below threshold (Test 11b)", () => {
    it("returns missing when at least one area scores below the threshold", async () => {
        const scores = [NO_ISSUES_THRESHOLD - 1, NO_ISSUES_THRESHOLD + 10];
        const report = makeReportWithScores(scores);
        const card = await generateNoIssues(report, makeCtx());
        expect(card.status).toBe("missing");
        if (card.status === "missing") {
            expect(card.cardType).toBe("no-issues");
            expect(card.reason).toContain("below threshold");
        }
    });
});
describe("generateNoIssues — calibration firing rate ≤30% (Test 12)", () => {
    it("fires ≤30% on a 10-report fixture set spanning low to high scores", async () => {
        // 10 reports with scores from 0 to 100 in 10-point increments
        // Only reports where ALL areas are ≥ NO_ISSUES_THRESHOLD should fire
        const fixtureSet = [
            makeReportWithScores([0, 10]), // far below threshold
            makeReportWithScores([20, 30]), // below threshold
            makeReportWithScores([40, 50]), // below threshold
            makeReportWithScores([60, 65]), // likely below threshold (≤85)
            makeReportWithScores([70, 75]), // below threshold if threshold=85
            makeReportWithScores([75, 80]), // below threshold if threshold=85
            makeReportWithScores([80, 82]), // below threshold if threshold=85
            makeReportWithScores([90, 92]), // above threshold
            makeReportWithScores([95, 97]), // above threshold
            makeReportWithScores([98, 99]), // above threshold
        ];
        const ctx = makeCtx();
        let firingCount = 0;
        for (const report of fixtureSet) {
            const card = await generateNoIssues(report, ctx);
            if (card.status === "ready")
                firingCount++;
        }
        const firingRate = firingCount / fixtureSet.length;
        expect(firingRate).toBeLessThanOrEqual(0.3);
    });
});
