test(reasoning): add customer signing followup fixture
This commit is contained in:
@@ -0,0 +1,126 @@
|
|||||||
|
{
|
||||||
|
"description": "Deterministic pre-anchored product-launch customer-signing follow-up fixture — represents the confirmed state immediately before the material customer-signing answer.",
|
||||||
|
"scenario": "We are evaluating two product-launch timing options: launching the new software product this year or waiting twelve months.",
|
||||||
|
"unresolved_question": "Which option leaves us better off overall?",
|
||||||
|
"selectedQuestion": {
|
||||||
|
"nodeId": "n_enterprise_customer_signing",
|
||||||
|
"question": "What evidence would clarify whether one prospective enterprise customer will sign if we launch this year?",
|
||||||
|
"reason": "decision"
|
||||||
|
},
|
||||||
|
"graph": {
|
||||||
|
"centralStatement": "We are evaluating two product-launch timing options: launching the new software product this year or waiting twelve months.",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "n_product_launch_state",
|
||||||
|
"label": "Product launch timing consideration",
|
||||||
|
"description": "Current state: the organisation is evaluating whether to launch the new software product this year or wait twelve months.",
|
||||||
|
"kind": "state",
|
||||||
|
"status": "provisional",
|
||||||
|
"confidence": "high",
|
||||||
|
"value": null,
|
||||||
|
"unit": null,
|
||||||
|
"evidenceIds": [],
|
||||||
|
"dependsOn": [],
|
||||||
|
"affects": [],
|
||||||
|
"parentId": null,
|
||||||
|
"childIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "opt_launch_this_year",
|
||||||
|
"label": "Launch this year",
|
||||||
|
"description": "Launch the new software product this year. Consequences: £1.2M/year expected additional recurring revenue, £300k one-off launch/support cost.",
|
||||||
|
"kind": "option",
|
||||||
|
"status": "known",
|
||||||
|
"confidence": "high",
|
||||||
|
"value": null,
|
||||||
|
"unit": null,
|
||||||
|
"evidenceIds": [],
|
||||||
|
"dependsOn": [],
|
||||||
|
"affects": [],
|
||||||
|
"parentId": null,
|
||||||
|
"childIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "opt_wait_twelve_months",
|
||||||
|
"label": "Wait twelve months",
|
||||||
|
"description": "Wait twelve months before launching the product. Consequences: avoids the £300k immediate launch/support cost, forgoes approximately £1.2M of first-year revenue.",
|
||||||
|
"kind": "option",
|
||||||
|
"status": "known",
|
||||||
|
"confidence": "high",
|
||||||
|
"value": null,
|
||||||
|
"unit": null,
|
||||||
|
"evidenceIds": [],
|
||||||
|
"dependsOn": [],
|
||||||
|
"affects": [],
|
||||||
|
"parentId": null,
|
||||||
|
"childIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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",
|
||||||
|
"value": null,
|
||||||
|
"unit": null,
|
||||||
|
"evidenceIds": [],
|
||||||
|
"dependsOn": [],
|
||||||
|
"affects": [],
|
||||||
|
"parentId": null,
|
||||||
|
"childIds": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "n_enterprise_customer_signing",
|
||||||
|
"label": "Prospective enterprise customer signing status",
|
||||||
|
"description": "Unknown whether one prospective enterprise customer will sign if we launch this year, because they account for approximately £700,000 of the £1.2 million expected annual revenue.",
|
||||||
|
"kind": "unknown",
|
||||||
|
"status": "unknown",
|
||||||
|
"confidence": "medium",
|
||||||
|
"value": null,
|
||||||
|
"unit": null,
|
||||||
|
"evidenceIds": [],
|
||||||
|
"dependsOn": [],
|
||||||
|
"affects": [],
|
||||||
|
"parentId": null,
|
||||||
|
"childIds": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"edges": [
|
||||||
|
{
|
||||||
|
"id": "e-opt-launch-to-dec",
|
||||||
|
"fromNodeId": "opt_launch_this_year",
|
||||||
|
"toNodeId": "n_product_launch_decision",
|
||||||
|
"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": "opt_wait_twelve_months",
|
||||||
|
"toNodeId": "n_product_launch_decision",
|
||||||
|
"relationship": "contained_in",
|
||||||
|
"confidence": "high",
|
||||||
|
"description": "Wait twelve months option is a candidate for the product launch decision"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "e-customer-signing-to-launch-option",
|
||||||
|
"fromNodeId": "n_enterprise_customer_signing",
|
||||||
|
"toNodeId": "opt_launch_this_year",
|
||||||
|
"relationship": "contained_in",
|
||||||
|
"confidence": "high",
|
||||||
|
"description": "Prospective enterprise customer signing status is material to the launch this year option"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"activeUnknownNodeId": "n_enterprise_customer_signing",
|
||||||
|
"resolvedNodeIds": [],
|
||||||
|
"currentSummary": "Two product-launch timing options evaluated; net-value comparison unresolved; prospective enterprise customer signing remains the active material uncertainty.",
|
||||||
|
"reasoningState": {
|
||||||
|
"comparabilityStatus": null,
|
||||||
|
"relationshipStatus": null,
|
||||||
|
"relationshipAssessed": false,
|
||||||
|
"contradictionReasoningAllowed": true,
|
||||||
|
"reasoningStages": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,11 @@ import { describe, it, expect } from "vitest";
|
|||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
import { situationGraphSchema } from "@/lib/graph/schema.js";
|
||||||
|
import {
|
||||||
|
validateGraphReferences,
|
||||||
|
detectDuplicateNodeIds,
|
||||||
|
} from "@/lib/graph/utils.js";
|
||||||
|
|
||||||
// ── Load committed decision-options fixture directly (60A.7) ─────────────
|
// ── Load committed decision-options fixture directly (60A.7) ─────────────
|
||||||
const DECISION_OPTIONS_FIXTURE_PATH = path.resolve(
|
const DECISION_OPTIONS_FIXTURE_PATH = path.resolve(
|
||||||
@@ -10,6 +15,14 @@ const DECISION_OPTIONS_FIXTURE_PATH = path.resolve(
|
|||||||
);
|
);
|
||||||
const DECISION_OPTIONS_FIXTURE = JSON.parse(fs.readFileSync(DECISION_OPTIONS_FIXTURE_PATH, "utf-8"));
|
const DECISION_OPTIONS_FIXTURE = JSON.parse(fs.readFileSync(DECISION_OPTIONS_FIXTURE_PATH, "utf-8"));
|
||||||
|
|
||||||
|
const PRODUCT_LAUNCH_CUSTOMER_SIGNING_FIXTURE_PATH = path.resolve(
|
||||||
|
path.dirname(fileURLToPath(import.meta.url)),
|
||||||
|
"fixtures/pre-anchored-product-launch-customer-signing.json",
|
||||||
|
);
|
||||||
|
const PRODUCT_LAUNCH_CUSTOMER_SIGNING_FIXTURE = JSON.parse(
|
||||||
|
fs.readFileSync(PRODUCT_LAUNCH_CUSTOMER_SIGNING_FIXTURE_PATH, "utf-8"),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronous simulator of the pre-anchored update-only mode with a custom fixture.
|
* Synchronous simulator of the pre-anchored update-only mode with a custom fixture.
|
||||||
* Mirrors what reproduce-multi-turn-investigation.mjs does when FIXTURE_MODE is set
|
* Mirrors what reproduce-multi-turn-investigation.mjs does when FIXTURE_MODE is set
|
||||||
@@ -1372,6 +1385,62 @@ describe("reproduce-multi-turn-investigation harness: one-shot semantics", () =>
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("pre-anchored product-launch customer-signing fixture", () => {
|
||||||
|
it("parses, validates, preserves identities, and exposes the customer unknown as the active target", () => {
|
||||||
|
const fixture = PRODUCT_LAUNCH_CUSTOMER_SIGNING_FIXTURE;
|
||||||
|
const graph = situationGraphSchema.parse(fixture.graph);
|
||||||
|
const graphReferenceValidation = validateGraphReferences(graph);
|
||||||
|
const duplicateNodeIds = detectDuplicateNodeIds(graph.nodes);
|
||||||
|
|
||||||
|
const decisionNodes = graph.nodes.filter((node) => node.id === "n_product_launch_decision");
|
||||||
|
const launchOptionNodes = graph.nodes.filter((node) => node.id === "opt_launch_this_year");
|
||||||
|
const waitOptionNodes = graph.nodes.filter((node) => node.id === "opt_wait_twelve_months");
|
||||||
|
const customerUnknownNodes = graph.nodes.filter(
|
||||||
|
(node) => node.id === "n_enterprise_customer_signing",
|
||||||
|
);
|
||||||
|
const additionalUnknownIds = graph.nodes
|
||||||
|
.filter(
|
||||||
|
(node) =>
|
||||||
|
node.kind === "unknown" &&
|
||||||
|
![
|
||||||
|
"n_product_launch_decision",
|
||||||
|
"n_enterprise_customer_signing",
|
||||||
|
].includes(node.id),
|
||||||
|
)
|
||||||
|
.map((node) => node.id);
|
||||||
|
|
||||||
|
expect(fixture.selectedQuestion?.question).toBe(
|
||||||
|
"What evidence would clarify whether one prospective enterprise customer will sign if we launch this year?",
|
||||||
|
);
|
||||||
|
expect(fixture.selectedQuestion?.nodeId).toBe("n_enterprise_customer_signing");
|
||||||
|
|
||||||
|
expect(decisionNodes).toHaveLength(1);
|
||||||
|
expect(decisionNodes[0].status).toBe("unknown");
|
||||||
|
|
||||||
|
expect(launchOptionNodes).toHaveLength(1);
|
||||||
|
expect(waitOptionNodes).toHaveLength(1);
|
||||||
|
|
||||||
|
expect(customerUnknownNodes).toHaveLength(1);
|
||||||
|
expect(customerUnknownNodes[0].status).toBe("unknown");
|
||||||
|
expect(customerUnknownNodes[0].kind).toBe("unknown");
|
||||||
|
|
||||||
|
expect(additionalUnknownIds).toEqual([]);
|
||||||
|
expect(graphReferenceValidation.valid).toBe(true);
|
||||||
|
expect(duplicateNodeIds).toEqual([]);
|
||||||
|
|
||||||
|
expect(graph.activeUnknownNodeId).toBe("n_enterprise_customer_signing");
|
||||||
|
expect(customerUnknownNodes[0].id).toBe(graph.activeUnknownNodeId);
|
||||||
|
|
||||||
|
const customerLinkage = graph.edges.filter(
|
||||||
|
(edge) =>
|
||||||
|
edge.fromNodeId === "n_enterprise_customer_signing" &&
|
||||||
|
edge.toNodeId === "opt_launch_this_year" &&
|
||||||
|
edge.relationship === "contained_in",
|
||||||
|
);
|
||||||
|
expect(customerLinkage).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// ── Pre-anchored update-only mode (57J.74) ─────────────
|
// ── Pre-anchored update-only mode (57J.74) ─────────────
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user