Files
confidence-engine/tests/graph/reasoning-pattern-selection.test.js

202 lines
6.6 KiB
JavaScript

import { describe, expect, it } from "vitest";
import {
formulateQuestion,
formulateTieResolutionQuestion,
selectReasoningPattern,
} from "@/lib/graph/question-formulator.js";
import { makeGraph, makeNode } from "@/lib/graph/schema.js";
function makeGraphFor(node, extra = {}) {
return makeGraph({
centralStatement: extra.centralStatement || "Decision context",
nodes: [node, ...(extra.nodes || [])],
edges: extra.edges || [],
activeUnknownNodeId: node.id,
resolvedNodeIds: extra.resolvedNodeIds || [],
currentSummary: "Test summary",
reasoningState: extra.reasoningState,
});
}
describe("reasoning pattern selection", () => {
it("commercial-method scenario selects the decision pattern and rejects explanation family", () => {
const unknown = makeNode({
id: "n-commercial-method",
label:
"Whether the method addresses a genuine, high-priority problem for a specific audience",
description:
"Need to know whether this solves a real problem for a clear audience before continuing development.",
kind: "unknown",
status: "unknown",
confidence: "high",
});
const graph = makeGraphFor(unknown, {
centralStatement:
"Before investing significant time and money, we need to know whether continuing development is commercially justified.",
});
const result = formulateQuestion({ node: unknown, graph });
expect(result.reasoningPattern).toBe("decision");
expect(result.questionFamily).not.toBe("explanation");
expect(result.allowedQuestionFamilies).toContain("decision_foundation");
expect(result.rejectedQuestionFamilies).toContain("explanation");
});
it("revenue and cash relationship scenario allows the explanation family", () => {
const unknown = makeNode({
id: "n-revenue-cash-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.",
kind: "unknown",
status: "unknown",
confidence: "medium",
});
const graph = makeGraphFor(unknown, {
centralStatement:
"Revenue increased by 18%, but cash in the bank fell over the same period.",
nodes: [
makeNode({
id: "n-revenue-observation",
label: "Revenue increased by 18%.",
description: "Revenue increased by 18%.",
kind: "observation",
status: "supported",
confidence: "high",
}),
makeNode({
id: "n-cash-observation",
label: "Cash in the bank fell over the same period.",
description: "Cash in the bank fell over the same period.",
kind: "observation",
status: "supported",
confidence: "high",
}),
],
});
const result = formulateQuestion({ node: unknown, graph });
expect(result.reasoningPattern).toBe("explanation");
expect(result.allowedQuestionFamilies).toContain("explanation");
});
it("duplicate observations reject explanation family during tie resolution", () => {
const graph = makeGraph({
centralStatement: "The same figure was repeated twice.",
nodes: [
makeNode({
id: "n-obs-1",
label: "Revenue increased by 10%.",
description: "Revenue increased by 10%.",
kind: "observation",
status: "supported",
confidence: "high",
}),
makeNode({
id: "n-obs-2",
label: "Revenue increased by 10%.",
description: "Revenue increased by 10%.",
kind: "observation",
status: "supported",
confidence: "high",
}),
],
edges: [],
activeUnknownNodeId: null,
resolvedNodeIds: [],
currentSummary: "Duplicate observation fixture",
});
const result = formulateTieResolutionQuestion({ graph });
expect(result.questionFamily).not.toBe("explanation");
expect(result.rejectedQuestionFamilies).toContain("explanation");
});
it("definition scenario selects the definition pattern", () => {
const unknown = makeNode({
id: "n-definition-pattern",
label: "Definition of justified confidence",
description: "The term needs clearer boundaries.",
kind: "unknown",
status: "unknown",
confidence: "medium",
});
const result = selectReasoningPattern({
node: unknown,
graph: makeGraphFor(unknown),
});
expect(result.pattern).toBe("definition");
});
it("comparison scenario selects the comparison pattern", () => {
const unknown = makeNode({
id: "n-comparison-pattern-2",
label: "How the two observations were measured",
description:
"Need evidence about the measure used for each observation before comparing them.",
kind: "unknown",
status: "unknown",
confidence: "medium",
});
const graph = makeGraphFor(unknown, {
centralStatement: "Traffic increased, but sales stayed flat.",
nodes: [
makeNode({
id: "n-traffic-2",
label: "Traffic increased.",
description: "Traffic increased.",
kind: "observation",
status: "supported",
confidence: "high",
}),
makeNode({
id: "n-sales-2",
label: "Sales stayed flat.",
description: "Sales stayed flat.",
kind: "observation",
status: "supported",
confidence: "high",
}),
],
reasoningState: {
comparabilityStatus: "uncertain",
relationshipStatus: "insufficient_information",
},
});
const result = selectReasoningPattern({ node: unknown, graph });
expect(result.pattern).toBe("comparison");
});
it("question family stays compatible with the reasoning pattern", () => {
const unknown = makeNode({
id: "n-decision-family-compatibility",
label: "Who experiences this problem",
description:
"Need to know who experiences this problem before continuing development.",
kind: "unknown",
status: "unknown",
confidence: "medium",
});
const graph = makeGraphFor(unknown, {
centralStatement:
"We need to know whether continuing development is commercially justified.",
});
const result = formulateQuestion({ node: unknown, graph });
expect(result.reasoningPattern).toBe("decision");
expect(result.allowedQuestionFamilies).toContain(result.questionFamily);
expect(result.rejectedQuestionFamilies).not.toContain(
result.questionFamily,
);
});
});