/**
 * failure-mode-summary.test.ts — Tests 5-9 for deterministic failure-mode-summary card.
 *
 * D0042: vitest only.
 * D-05: schema must reject cross-dimension (dimension, failureMode) pairs.
 */
import { describe, expect, it } from "vitest";
import { FailureModeSummaryBodySchema, generateFailureModeSummary, } from "../failure-mode-summary.js";
import { failureModesForDimension } from "../../../../grader/failure-modes/index.js";
// Compile-time gate
const _satisfiesCheck = FailureModeSummaryBodySchema;
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 makeReport(failureModes) {
    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: "groq",
            lowestScore: 50,
            overall: {
                avgCeilingScore: 80,
                avgScore: 70,
                avgDocLift: 5,
                avgDocQualityGap: 20,
                avgFloorScore: 65,
                negativeDocLiftCount: 0,
            },
            scores: [
                {
                    feature: "groq",
                    ceilingScore: 80,
                    codeCorrectness: 70,
                    docCoverage: 65,
                    docLift: 5,
                    docQualityGap: 20,
                    floorScore: 65,
                    negativeDocLift: false,
                    taskCompletion: 70,
                    testCount: 10,
                    totalCost: 0.05,
                    totalScore: 70,
                },
            ],
            failureModes,
        },
    };
}
describe("FailureModeSummaryBodySchema — field structure (Test 5)", () => {
    it("includes dimension, failureMode, count, sampleSize, summary fields", () => {
        const canonicalMode = failureModesForDimension("task-completion")[0];
        const result = FailureModeSummaryBodySchema.safeParse({
            summary: "test summary",
            dimension: "task-completion",
            failureMode: canonicalMode,
            count: 5,
            sampleSize: 20,
        });
        expect(result.success).toBe(true);
        // compile-time gate
        expect(_satisfiesCheck).toBeDefined();
    });
});
describe("FailureModeSummaryBodySchema — D-05 refine rejects cross-dimension (Test 6)", () => {
    it("rejects mcp-tool-not-found for task-completion dimension", () => {
        // "mcp-tool-not-found" doesn't exist in the taxonomy but we want to test
        // cross-dimension hallucination. Use a valid MCP mode in a literacy dimension.
        const mcpOnlyMode = "spec-mismatch"; // valid for mcp-behavior, not task-completion
        const result = FailureModeSummaryBodySchema.safeParse({
            summary: "test",
            dimension: "task-completion",
            failureMode: mcpOnlyMode,
            count: 1,
            sampleSize: 5,
        });
        expect(result.success).toBe(false);
    });
});
describe("FailureModeSummaryBodySchema — accepts canonical pair (Test 7)", () => {
    it("accepts a valid (dimension, failureMode) pair from the taxonomy", () => {
        const canonicalMode = failureModesForDimension("task-completion")[0];
        const result = FailureModeSummaryBodySchema.safeParse({
            summary: "test summary about missing docs",
            dimension: "task-completion",
            failureMode: canonicalMode,
            count: 3,
            sampleSize: 15,
        });
        expect(result.success).toBe(true);
    });
});
describe("generateFailureModeSummary — happy path (Test 8)", () => {
    it("returns a ready card with the dominant failure mode for a report with failure modes", async () => {
        const canonicalMode = failureModesForDimension("task-completion")[0];
        const report = makeReport({
            counts: { "task-completion": 7 },
            topTitles: [
                {
                    id: `task-completion::${canonicalMode}`,
                    category: canonicalMode,
                    severity: "high",
                    title: canonicalMode,
                    count: 7,
                },
            ],
            totalJudgments: 20,
            classificationRate: 0.35,
        });
        const card = await generateFailureModeSummary(report, makeCtx());
        expect(card.status).toBe("ready");
        if (card.status === "ready") {
            expect(card.cardType).toBe("failure-mode-summary");
            expect(card.meta.cardVersion).toBe("failure-mode-summary@0.1.0");
            const body = card.body;
            expect(body.count).toBeGreaterThan(0);
        }
    });
});
describe("generateFailureModeSummary — empty failure modes (Test 9)", () => {
    it("returns missing card when report has no failure modes", async () => {
        const report = makeReport(undefined);
        const card = await generateFailureModeSummary(report, makeCtx());
        expect(card.status).toBe("missing");
        if (card.status === "missing") {
            expect(card.cardType).toBe("failure-mode-summary");
            expect(card.reason).toContain("no failure modes");
        }
    });
});
describe("generateFailureModeSummary — cross-cutting mode resolution", () => {
    // `missing-docs` appears in both LITERACY_FAILURE_MODES and MCP_FAILURE_MODES.
    // Before the per-EvalMode preference table, linear scan of CANONICAL_DIMENSIONS
    // always resolved it to task-completion, mislabelling MCP-only runs.
    function withMode(report, mode) {
        return {
            ...report,
            provenance: { ...report.provenance, mode },
        };
    }
    it("resolves 'missing-docs' to mcp-behavior on an mcp-server report", async () => {
        const base = makeReport({
            counts: { "mcp-behavior": 7 },
            topTitles: [
                {
                    id: "mcp-behavior::missing-docs",
                    category: "missing-docs",
                    severity: "high",
                    title: "missing-docs",
                    count: 7,
                },
            ],
            totalJudgments: 20,
            classificationRate: 0.35,
        });
        const report = withMode(base, "mcp-server");
        const card = await generateFailureModeSummary(report, makeCtx());
        expect(card.status).toBe("ready");
        if (card.status === "ready") {
            const body = card.body;
            expect(body.dimension).toBe("mcp-behavior");
            expect(body.failureMode).toBe("missing-docs");
        }
    });
    it("resolves 'missing-docs' to task-completion on a literacy report", async () => {
        const base = makeReport({
            counts: { "task-completion": 7 },
            topTitles: [
                {
                    id: "task-completion::missing-docs",
                    category: "missing-docs",
                    severity: "high",
                    title: "missing-docs",
                    count: 7,
                },
            ],
            totalJudgments: 20,
            classificationRate: 0.35,
        });
        const report = withMode(base, "literacy");
        const card = await generateFailureModeSummary(report, makeCtx());
        expect(card.status).toBe("ready");
        if (card.status === "ready") {
            const body = card.body;
            expect(body.dimension).toBe("task-completion");
            expect(body.failureMode).toBe("missing-docs");
        }
    });
});
