import { afterEach, describe, expect, it, vi } from "vitest"; const ENRICHMENT_FLAG = "FEATURE_ASSISTANT_EVIDENCE_ENRICHMENT_V1"; const ORIGINAL_FLAG_VALUE = process.env[ENRICHMENT_FLAG]; function restoreFlag(): void { if (ORIGINAL_FLAG_VALUE === undefined) { delete process.env[ENRICHMENT_FLAG]; } else { process.env[ENRICHMENT_FLAG] = ORIGINAL_FLAG_VALUE; } } async function normalizeSingleEvidence(flagValue: "0" | "1", evidenceRecord: Record) { process.env[ENRICHMENT_FLAG] = flagValue; vi.resetModules(); const { normalizeRetrievalResult } = await import("../src/services/retrievalResultNormalizer"); return normalizeRetrievalResult("F1", ["R1"], "store_feature_risk", { status: "ok", result_type: "list", items: [], summary: {}, evidence: [evidenceRecord], why_included: [], selection_reason: [], risk_factors: [], business_interpretation: [], confidence: "medium", limitations: [], errors: [] }); } describe.sequential("retrieval evidence enrichment", () => { afterEach(() => { restoreFlag(); vi.resetModules(); }); it("builds deterministic canonical source_ref from pointer/source", async () => { const rawEvidence = { evidence_id: "ev-1", claim_ref: "requirement:R1", source_type: "retrieval_item", pointer: { fragment_id: "F1", route: "store_feature_risk", source: { namespace: "snapshot_2020", entity: "Document", id: "DOC-42", period: "2020-06" }, locator: { field_path: "risk_score", item_index: 0 } }, risk_score: 3 }; const first = await normalizeSingleEvidence("1", rawEvidence); const second = await normalizeSingleEvidence("1", rawEvidence); expect(first.evidence[0].source_ref.canonical_ref).toBe(second.evidence[0].source_ref.canonical_ref); expect(first.evidence[0].source_ref.schema_version).toBe("evidence_source_ref_v1"); expect(first.evidence[0].source_ref.namespace).toBe("snapshot_2020"); expect(first.evidence[0].source_ref.entity).toBe("Document"); expect(first.evidence[0].source_ref.id).toBe("DOC-42"); }); it("uses honest weak-evidence fallback when mechanism is not reliable", async () => { const result = await normalizeSingleEvidence("1", { evidence_id: "ev-weak", source_entity: "DocumentJournal", source_id: "doc-weak-1", risk_score: 2 }); expect(result.evidence[0].mechanism_note).toBeNull(); expect(result.evidence[0].limitation?.reason_code).toBe("missing_mechanism"); expect(result.evidence[0].confidence).toBe("low"); }); it("maps explicit limitation to reason-coded structure", async () => { const result = await normalizeSingleEvidence("1", { evidence_id: "ev-limited", source_entity: "DocumentJournal", source_id: "doc-limited-1", limitation: "Snapshot-only evidence." }); expect(result.evidence[0].limitation?.reason_code).toBe("snapshot_only"); expect(result.evidence[0].limitation?.note).toBe("Snapshot-only evidence."); }); it("keeps legacy inferred mechanism when enrichment flag is OFF", async () => { const result = await normalizeSingleEvidence("0", { evidence_id: "ev-legacy", source_entity: "DocumentJournal", source_id: "doc-legacy-1", risk_score: 2 }); expect(typeof result.evidence[0].mechanism_note).toBe("string"); expect(result.evidence[0].mechanism_note).toContain("Anomaly signal inferred"); expect(result.evidence[0].limitation).toBeNull(); }); });