import { describe, expect, it } from "vitest"; import { formulateQuestion, formulateTieResolutionQuestion, } from "@/lib/graph/question-formulator.js"; import { explainUnknownSelection, selectActiveUnknownCandidate, } from "@/lib/graph/utils.js"; import { ambiguityGeneralisationFixtures } from "@/tests/fixtures/ambiguity-generalisation.js"; function neutraliseUnknownLabels(graph) { let counter = 0; return { ...graph, nodes: graph.nodes.map((node) => { if (node.kind !== "unknown") return { ...node }; counter += 1; return { ...node, label: `Unknown ${String.fromCharCode(64 + counter)}`, description: `Unknown factor ${counter}.`, }; }), }; } function isSingleQuestion(question) { return (question.match(/\?/g) || []).length === 1; } describe("ambiguity generalisation", () => { it("preserves ambiguity across contradiction scenarios without favouring one explanation", () => { const summary = ambiguityGeneralisationFixtures.map((fixture) => { const explanation = explainUnknownSelection(fixture.graph, []); const selection = selectActiveUnknownCandidate(fixture.graph, []); const neutralExplanation = explainUnknownSelection( neutraliseUnknownLabels(fixture.graph), [], ); const tieQuestion = formulateTieResolutionQuestion({ graph: fixture.graph, }); const representativeUnknown = fixture.graph.nodes.find( (node) => node.kind === "unknown", ); const fallbackQuestion = formulateQuestion({ node: representativeUnknown, graph: fixture.graph, }); const lowerQuestion = tieQuestion.question.toLowerCase(); for (const term of fixture.disallowedQuestionTerms) { expect(lowerQuestion).not.toContain(term.toLowerCase()); } expect(explanation.status).toBe("ambiguous"); expect(selection.status).toBe("ambiguous"); expect(selection.selectedNode).toBeNull(); expect(explanation.selectedNodeId).toBeNull(); expect(explanation.candidates).toHaveLength(2); expect(explanation.summary.selectedReason).toBe( "No justified distinction between leading unknowns.", ); expect(explanation.alphabeticalUsedAsReasoning).toBe(false); expect(neutralExplanation.status).toBe("ambiguous"); expect(isSingleQuestion(tieQuestion.question)).toBe(true); expect(tieQuestion.question.toLowerCase()).not.toContain(" or "); return { scenario: fixture.scenario, candidateCount: explanation.candidates.length, ambiguityStatus: explanation.status, tieReason: explanation.summary.selectedReason, investigationStrategy: tieQuestion.strategy, question: tieQuestion.question, explanationFavoured: explanation.selectedNodeId !== null, }; }); expect(summary).toMatchInlineSnapshot(` [ { "ambiguityStatus": "ambiguous", "candidateCount": 2, "explanationFavoured": false, "investigationStrategy": null, "question": "Were these figures measured on the same basis and at the same scale?", "scenario": "Revenue increased by 18%, but cash in the bank fell over the same period.", "tieReason": "No justified distinction between leading unknowns.", }, { "ambiguityStatus": "ambiguous", "candidateCount": 2, "explanationFavoured": false, "investigationStrategy": null, "question": "Were these figures measured over the same period and at the same scale?", "scenario": "Customer satisfaction scores increased, but complaints also increased.", "tieReason": "No justified distinction between leading unknowns.", }, { "ambiguityStatus": "ambiguous", "candidateCount": 2, "explanationFavoured": false, "investigationStrategy": null, "question": "Were these figures measured over the same period and at the same scale?", "scenario": "Average delivery time decreased by 25%, but order cancellations increased.", "tieReason": "No justified distinction between leading unknowns.", }, { "ambiguityStatus": "ambiguous", "candidateCount": 2, "explanationFavoured": false, "investigationStrategy": null, "question": "Were these figures measured over the same period and at the same scale?", "scenario": "Website traffic doubled, but sales remained unchanged.", "tieReason": "No justified distinction between leading unknowns.", }, { "ambiguityStatus": "ambiguous", "candidateCount": 2, "explanationFavoured": false, "investigationStrategy": null, "question": "Were these figures measured over the same period and at the same scale?", "scenario": "Production output increased by 30%, but quality defects also increased.", "tieReason": "No justified distinction between leading unknowns.", }, ] `); }); });