import { describe, expect, it } from "vitest"; import { assessUnknownAtomicity } from "@/lib/graph/question-formulator.js"; import { makeGraph, makeNode } from "@/lib/graph/schema.js"; function makeGraphWithUnknown(centralStatement, unknown, observations = []) { return makeGraph({ centralStatement, nodes: [unknown, ...observations], edges: [], activeUnknownNodeId: unknown.id, resolvedNodeIds: [], currentSummary: "Atomicity test graph", }); } describe("assessUnknownAtomicity", () => { it("classifies denominator-style unknowns as atomic", () => { const unknown = makeNode({ id: "n-denominator", label: "Complaint rate denominator", description: "Need the denominator because it directly determines the complaint rate.", kind: "unknown", status: "unknown", confidence: "high", }); const result = assessUnknownAtomicity({ node: unknown, graph: makeGraphWithUnknown( "Production increased while complaints increased.", unknown, ), }); expect(result.atomicity).toBe("atomic"); expect(result.reason.toLowerCase()).toContain("directly"); }); it("classifies relationship explanation unknowns as composite", () => { const unknown = makeNode({ id: "n-explanation", label: "Explanation for why revenue increased by 18%, but cash in the bank fell over the same period", description: "Need to understand what change or event could explain why these observations differ, because that is needed to investigate their relationship.", kind: "unknown", status: "unknown", confidence: "medium", }); const graph = makeGraphWithUnknown( "Revenue increased by 18%, but cash in the bank fell over the same period.", unknown, [ makeNode({ id: "n-revenue", label: "Revenue increased by 18%.", description: "Revenue increased by 18%.", kind: "observation", status: "supported", confidence: "high", }), makeNode({ id: "n-cash", label: "Cash in the bank decreased over the same period.", description: "Cash in the bank decreased over the same period.", kind: "observation", status: "supported", confidence: "high", }), ], ); const result = assessUnknownAtomicity({ node: unknown, graph }); expect(result.atomicity).toBe("composite"); expect(result.decompositionKind).toBe("relationship_explanation"); }); it.each([ [ "Customer satisfaction rose, but complaints also rose.", "Explanation for why customer satisfaction rose, but complaints also rose", ], [ "Delivery time fell, but cancellations increased.", "Possible causes of why delivery time fell, but cancellations increased", ], [ "Traffic increased, but sales stayed flat.", "Broad explanation for why traffic increased, but sales stayed flat", ], [ "Production increased, but defects also increased.", "Factors behind why production increased, but defects also increased", ], ])( "classifies broad divergence unknowns as composite: %s", (scenario, label) => { const unknown = makeNode({ id: `n-${label.length}`, label, description: `${label} because the current unknown is too broad to ask directly.`, kind: "unknown", status: "unknown", confidence: "medium", }); const result = assessUnknownAtomicity({ node: unknown, graph: makeGraphWithUnknown(scenario, unknown), }); expect(result.atomicity).toBe("composite"); }, ); });