fix(reasoning): recognise decision in sufficiency question
This commit is contained in:
@@ -2007,7 +2007,6 @@ export function formulateQuestion({ node, graph, context = {} }) {
|
|||||||
// Detected transiently from existing state; no persisted field required.
|
// Detected transiently from existing state; no persisted field required.
|
||||||
if (
|
if (
|
||||||
reasoningPatternSelection.pattern === "decision" &&
|
reasoningPatternSelection.pattern === "decision" &&
|
||||||
node.kind !== "unknown" &&
|
|
||||||
node.status !== "known" &&
|
node.status !== "known" &&
|
||||||
node.status !== "resolved" &&
|
node.status !== "resolved" &&
|
||||||
node.status !== "contradicted" &&
|
node.status !== "contradicted" &&
|
||||||
|
|||||||
@@ -1105,7 +1105,7 @@ describe("formulateQuestion", () => {
|
|||||||
id: "n_product_launch_decision",
|
id: "n_product_launch_decision",
|
||||||
label: "Whether to launch product X",
|
label: "Whether to launch product X",
|
||||||
description: "Launch vs not launch decision for product X.",
|
description: "Launch vs not launch decision for product X.",
|
||||||
kind: "state",
|
kind: "unknown",
|
||||||
status: "unknown",
|
status: "unknown",
|
||||||
confidence: "medium",
|
confidence: "medium",
|
||||||
childIds: [],
|
childIds: [],
|
||||||
@@ -1137,7 +1137,7 @@ describe("formulateQuestion", () => {
|
|||||||
id: "n_product_launch_decision",
|
id: "n_product_launch_decision",
|
||||||
label: "Whether to launch product X",
|
label: "Whether to launch product X",
|
||||||
description: "Launch vs not launch decision for product X.",
|
description: "Launch vs not launch decision for product X.",
|
||||||
kind: "state",
|
kind: "unknown",
|
||||||
status: "unknown",
|
status: "unknown",
|
||||||
confidence: "medium",
|
confidence: "medium",
|
||||||
});
|
});
|
||||||
@@ -1170,7 +1170,7 @@ describe("formulateQuestion", () => {
|
|||||||
id: "n_product_launch_decision",
|
id: "n_product_launch_decision",
|
||||||
label: "Whether to launch product X",
|
label: "Whether to launch product X",
|
||||||
description: "Launch vs not launch decision.",
|
description: "Launch vs not launch decision.",
|
||||||
kind: "state",
|
kind: "unknown",
|
||||||
status: "unknown",
|
status: "unknown",
|
||||||
confidence: "medium",
|
confidence: "medium",
|
||||||
childIds: [factor.id],
|
childIds: [factor.id],
|
||||||
@@ -1201,7 +1201,7 @@ describe("formulateQuestion", () => {
|
|||||||
id: "n_product_launch_decision",
|
id: "n_product_launch_decision",
|
||||||
label: "Whether to launch product X",
|
label: "Whether to launch product X",
|
||||||
description: "Launch vs not launch decision.",
|
description: "Launch vs not launch decision.",
|
||||||
kind: "state",
|
kind: "unknown",
|
||||||
status: "unknown",
|
status: "unknown",
|
||||||
confidence: "medium",
|
confidence: "medium",
|
||||||
});
|
});
|
||||||
@@ -1261,7 +1261,7 @@ describe("formulateQuestion", () => {
|
|||||||
id: "n-decision",
|
id: "n-decision",
|
||||||
label: "Build decision",
|
label: "Build decision",
|
||||||
description: "Decision introduced by the answer.",
|
description: "Decision introduced by the answer.",
|
||||||
kind: "state",
|
kind: "unknown",
|
||||||
status: "known",
|
status: "known",
|
||||||
confidence: "medium",
|
confidence: "medium",
|
||||||
childIds: [unknown.id],
|
childIds: [unknown.id],
|
||||||
@@ -1294,7 +1294,7 @@ describe("formulateQuestion", () => {
|
|||||||
id: "n_product_launch_decision",
|
id: "n_product_launch_decision",
|
||||||
label: "Whether to launch product X",
|
label: "Whether to launch product X",
|
||||||
description: "Launch vs not launch decision.",
|
description: "Launch vs not launch decision.",
|
||||||
kind: "state",
|
kind: "unknown",
|
||||||
status: "unknown",
|
status: "unknown",
|
||||||
confidence: "medium",
|
confidence: "medium",
|
||||||
childIds: [factor.id],
|
childIds: [factor.id],
|
||||||
@@ -1325,7 +1325,7 @@ describe("formulateQuestion", () => {
|
|||||||
id: "n_product_launch_decision",
|
id: "n_product_launch_decision",
|
||||||
label: "Whether to launch product X",
|
label: "Whether to launch product X",
|
||||||
description: "Launch vs not launch decision.",
|
description: "Launch vs not launch decision.",
|
||||||
kind: "state",
|
kind: "unknown",
|
||||||
status: "unknown",
|
status: "unknown",
|
||||||
confidence: "medium",
|
confidence: "medium",
|
||||||
});
|
});
|
||||||
@@ -1342,3 +1342,211 @@ describe("formulateQuestion", () => {
|
|||||||
expect(result.reason).toContain("material factors");
|
expect(result.reason).toContain("material factors");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ── 60B.75 — real decision detection for sufficiency question ────
|
||||||
|
|
||||||
|
describe("60B.75 — real decision detection for sufficiency question", () => {
|
||||||
|
it("Test 1 — actual decision representation reaches State B", () => {
|
||||||
|
const decision = makeNode({
|
||||||
|
id: "n_product_launch_decision",
|
||||||
|
label: "Which option leaves us better off overall?",
|
||||||
|
description:
|
||||||
|
"Uncertainty about which product-launch timing option provides superior net value.",
|
||||||
|
kind: "unknown",
|
||||||
|
status: "unknown",
|
||||||
|
confidence: "medium",
|
||||||
|
});
|
||||||
|
|
||||||
|
const graph = makeGraphFor(decision, { nodes: [], edges: [] });
|
||||||
|
|
||||||
|
expect(hasRemainingMaterialFactors(decision.id, graph)).toBe(false);
|
||||||
|
|
||||||
|
const result = formulateQuestion({
|
||||||
|
node: decision,
|
||||||
|
graph,
|
||||||
|
context: { resolvedValues: [] },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.questionFamily).toBe("decision_threshold");
|
||||||
|
expect(result.selectedQuestionTemplate).toBe(
|
||||||
|
"decision_threshold_sufficiency_confirmation",
|
||||||
|
);
|
||||||
|
expect(result.question).toContain("anything else material");
|
||||||
|
expect(result.reasoningPattern).toBe("decision");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Test 2 — ordinary unknown factor does NOT trigger State B", () => {
|
||||||
|
const unknown = makeNode({
|
||||||
|
id: "n_evidence_unknown",
|
||||||
|
label: "Evidence of demand",
|
||||||
|
description: "Need evidence of demand.",
|
||||||
|
kind: "unknown",
|
||||||
|
status: "unknown",
|
||||||
|
confidence: "medium",
|
||||||
|
});
|
||||||
|
|
||||||
|
const graph = makeGraphFor(unknown);
|
||||||
|
|
||||||
|
const result = formulateQuestion({
|
||||||
|
node: unknown,
|
||||||
|
graph,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.selectedQuestionTemplate).not.toBe(
|
||||||
|
"decision_threshold_sufficiency_confirmation",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Test 3 — genuine decision with remaining factor does NOT trigger State B", () => {
|
||||||
|
const factor = makeNode({
|
||||||
|
id: "n_customer_readiness",
|
||||||
|
label: "Customer readiness level",
|
||||||
|
description: "How ready the customer is to adopt.",
|
||||||
|
kind: "unknown",
|
||||||
|
status: "unknown",
|
||||||
|
confidence: "medium",
|
||||||
|
parentId: "n_product_launch_decision",
|
||||||
|
});
|
||||||
|
|
||||||
|
const decision = makeNode({
|
||||||
|
id: "n_product_launch_decision",
|
||||||
|
label: "Which option leaves us better off overall?",
|
||||||
|
description: "Uncertainty about which product-launch timing option provides superior net value.",
|
||||||
|
kind: "unknown",
|
||||||
|
status: "unknown",
|
||||||
|
confidence: "medium",
|
||||||
|
childIds: [factor.id],
|
||||||
|
});
|
||||||
|
|
||||||
|
const graph = makeGraphFor(factor, {
|
||||||
|
nodes: [decision],
|
||||||
|
edges: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(hasRemainingMaterialFactors(decision.id, graph)).toBe(true);
|
||||||
|
|
||||||
|
const result = formulateQuestion({
|
||||||
|
node: decision,
|
||||||
|
graph,
|
||||||
|
context: { resolvedValues: [] },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.selectedQuestionTemplate).not.toBe(
|
||||||
|
"decision_threshold_sufficiency_confirmation",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Test 4 — explicit confirmation still prevents question path", () => {
|
||||||
|
const decision = makeNode({
|
||||||
|
id: "n_product_launch_decision",
|
||||||
|
label: "Which option leaves us better off overall?",
|
||||||
|
description:
|
||||||
|
"Uncertainty about which product-launch timing option provides superior net value.",
|
||||||
|
kind: "unknown",
|
||||||
|
status: "unknown",
|
||||||
|
confidence: "medium",
|
||||||
|
});
|
||||||
|
|
||||||
|
const graph = makeGraphFor(decision, { nodes: [], edges: [] });
|
||||||
|
|
||||||
|
const result = formulateQuestion({
|
||||||
|
node: decision,
|
||||||
|
graph,
|
||||||
|
context: {
|
||||||
|
resolvedValues: ["no other material uncertainty remains"],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.selectedQuestionTemplate).not.toBe(
|
||||||
|
"decision_threshold_sufficiency_confirmation",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Test 5 — existing decision_threshold case preserved", () => {
|
||||||
|
const unknown = makeNode({
|
||||||
|
id: "n-commercial",
|
||||||
|
label: "Uncertainty regarding the commercial value of the product",
|
||||||
|
description:
|
||||||
|
"Commercial justification remains unclear because the decision depends on it.",
|
||||||
|
kind: "unknown",
|
||||||
|
status: "unknown",
|
||||||
|
confidence: "high",
|
||||||
|
parentId: "n-decision",
|
||||||
|
});
|
||||||
|
|
||||||
|
const decision = makeNode({
|
||||||
|
id: "n-decision",
|
||||||
|
label: "Build decision",
|
||||||
|
description: "Decision introduced by the answer.",
|
||||||
|
kind: "unknown",
|
||||||
|
status: "known",
|
||||||
|
confidence: "medium",
|
||||||
|
childIds: [unknown.id],
|
||||||
|
});
|
||||||
|
|
||||||
|
const graph = makeGraphFor(unknown, {
|
||||||
|
nodes: [decision],
|
||||||
|
resolvedNodeIds: [decision.id],
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = formulateQuestion({ node: unknown, graph });
|
||||||
|
|
||||||
|
expect(result.questionFamily).toBe("decision_threshold");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Test 6 — exact 60B.73-style production-shaped fixture", () => {
|
||||||
|
const optLaunch = makeNode({
|
||||||
|
id: "opt_launch_this_year",
|
||||||
|
label: "Launch this year",
|
||||||
|
description: "New software product launches this year.",
|
||||||
|
kind: "unknown",
|
||||||
|
status: "known",
|
||||||
|
confidence: "high",
|
||||||
|
parentId: "n_product_launch_decision",
|
||||||
|
});
|
||||||
|
|
||||||
|
const optWait = makeNode({
|
||||||
|
id: "opt_wait_twelve_months",
|
||||||
|
label: "Wait twelve months",
|
||||||
|
description: "Defer product launch by twelve months.",
|
||||||
|
kind: "unknown",
|
||||||
|
status: "known",
|
||||||
|
confidence: "high",
|
||||||
|
parentId: "n_product_launch_decision",
|
||||||
|
});
|
||||||
|
|
||||||
|
const decision = makeNode({
|
||||||
|
id: "n_product_launch_decision",
|
||||||
|
label: "Which option leaves us better off overall?",
|
||||||
|
description:
|
||||||
|
"Uncertainty about which of the two product-launch timing options — launch this year or wait twelve months — provides superior net value for the organisation.",
|
||||||
|
kind: "unknown",
|
||||||
|
status: "unknown",
|
||||||
|
confidence: "medium",
|
||||||
|
childIds: [optLaunch.id, optWait.id],
|
||||||
|
});
|
||||||
|
|
||||||
|
const graph = makeGraphFor(decision, {
|
||||||
|
nodes: [optLaunch, optWait],
|
||||||
|
edges: [
|
||||||
|
{ id: "e-opt-launch-to-dec", fromNodeId: optLaunch.id, toNodeId: decision.id, relationship: "contained_in", confidence: "high", description: "Launch this year option is a candidate for the product launch decision" },
|
||||||
|
{ id: "e-opt-wait-to-dec", fromNodeId: optWait.id, toNodeId: decision.id, relationship: "contained_in", confidence: "high", description: "Wait twelve months option is a candidate for the product launch decision" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(hasRemainingMaterialFactors(decision.id, graph)).toBe(false);
|
||||||
|
|
||||||
|
const result = formulateQuestion({
|
||||||
|
node: decision,
|
||||||
|
graph,
|
||||||
|
context: { resolvedValues: [] },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.questionFamily).toBe("decision_threshold");
|
||||||
|
expect(result.selectedQuestionTemplate).toBe(
|
||||||
|
"decision_threshold_sufficiency_confirmation",
|
||||||
|
);
|
||||||
|
expect(result.reasoningPattern).toBe("decision");
|
||||||
|
expect(result.question).toContain("anything else material");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user