Files
confidence-engine/tests/fixtures/question-priority-generalisation.js

446 lines
16 KiB
JavaScript

import { makeEdge, makeGraph, makeNode } from "@/lib/graph/schema.js";
function makeScenarioGraph({
scenario,
decisionNode,
answeredContextUnknown,
foundationalUnknown,
consequentialUnknown,
downstreamLeaf,
}) {
const nodes = [
decisionNode,
answeredContextUnknown,
foundationalUnknown,
consequentialUnknown,
downstreamLeaf,
];
const edges = [
makeEdge({
id: `${decisionNode.id}-to-${foundationalUnknown.id}`,
fromNodeId: decisionNode.id,
toNodeId: foundationalUnknown.id,
relationship: "depends_on",
description: `${decisionNode.label} depends on ${foundationalUnknown.label}.`,
}),
makeEdge({
id: `${answeredContextUnknown.id}-to-${consequentialUnknown.id}`,
fromNodeId: answeredContextUnknown.id,
toNodeId: consequentialUnknown.id,
relationship: "depends_on",
description: `${consequentialUnknown.label} was surfaced from resolved context.`,
}),
makeEdge({
id: `${foundationalUnknown.id}-to-${consequentialUnknown.id}`,
fromNodeId: foundationalUnknown.id,
toNodeId: consequentialUnknown.id,
relationship: "depends_on",
description: `${consequentialUnknown.label} depends on ${foundationalUnknown.label}.`,
}),
makeEdge({
id: `${consequentialUnknown.id}-to-${downstreamLeaf.id}`,
fromNodeId: consequentialUnknown.id,
toNodeId: downstreamLeaf.id,
relationship: "depends_on",
description: `${downstreamLeaf.label} depends on ${consequentialUnknown.label}.`,
}),
];
return makeGraph({
centralStatement: scenario,
nodes,
edges,
activeUnknownNodeId: answeredContextUnknown.id,
resolvedNodeIds: [],
currentSummary: "Generalisation fixture graph",
});
}
export const questionPriorityGeneralisationFixtures = [
{
key: "hire-engineer",
scenario: "Should we hire another engineer?",
decisionType: "resourcing decision",
acceptableFoundationalUnknownNodeIds: [
"hire-success-criteria",
"hire-bottleneck",
],
prohibitedFirstTopics: ["salary", "job advert", "programming language"],
acceptableQuestionStrategies: [
"decision_threshold",
"evidence_gathering",
"definition",
],
notes:
"The first question should establish whether more engineering capacity is justified before compensation or implementation details.",
graph: makeScenarioGraph({
scenario: "Should we hire another engineer?",
decisionNode: makeNode({
id: "hire-decision",
label: "Hiring another engineer decision",
description: "Decision about increasing engineering capacity.",
kind: "state",
status: "known",
confidence: "medium",
value: "Deciding whether to hire another engineer",
childIds: ["hire-success-criteria"],
}),
answeredContextUnknown: makeNode({
id: "hire-delays-known",
label: "Delivery delays established",
description:
"Need to confirm whether recent delivery delays are real because this context determines whether a capacity decision is even relevant.",
kind: "unknown",
status: "unknown",
confidence: "high",
value:
"The roadmap is slipping because the current team cannot clear the queue.",
childIds: ["hire-bottleneck"],
}),
foundationalUnknown: makeNode({
id: "hire-success-criteria",
label: "Hiring success threshold",
description:
"Need the success threshold because the hiring decision depends on what improvement would justify adding headcount.",
kind: "unknown",
status: "unknown",
confidence: "high",
parentId: "hire-decision",
childIds: ["hire-bottleneck"],
}),
consequentialUnknown: makeNode({
id: "hire-bottleneck",
label: "Primary delivery bottleneck",
description:
"Need the main bottleneck because the team must know whether another engineer would relieve the limiting constraint.",
kind: "unknown",
status: "unknown",
confidence: "high",
dependsOn: ["hire-success-criteria"],
parentId: "hire-success-criteria",
childIds: ["hire-salary"],
}),
downstreamLeaf: makeNode({
id: "hire-salary",
label: "Engineer salary budget",
description:
"Need the salary range because compensation planning comes after the hiring case is established.",
kind: "unknown",
status: "unknown",
confidence: "medium",
dependsOn: ["hire-bottleneck"],
parentId: "hire-bottleneck",
}),
}),
},
{
key: "replace-vans",
scenario: "Should we replace the delivery vans?",
decisionType: "asset replacement decision",
acceptableFoundationalUnknownNodeIds: [
"van-reliability-threshold",
"van-service-constraint",
],
prohibitedFirstTopics: [
"purchase price",
"paint colour",
"finance provider",
],
acceptableQuestionStrategies: [
"decision_threshold",
"evidence_gathering",
"definition",
],
notes:
"The first question should establish whether the fleet is failing a threshold that justifies replacement.",
graph: makeScenarioGraph({
scenario: "Should we replace the delivery vans?",
decisionNode: makeNode({
id: "van-decision",
label: "Replace delivery vans decision",
description: "Decision about replacing the current delivery fleet.",
kind: "state",
status: "known",
confidence: "medium",
value: "Deciding whether to replace the delivery vans",
childIds: ["van-reliability-threshold"],
}),
answeredContextUnknown: makeNode({
id: "van-breakdowns-known",
label: "Breakdown trend confirmed",
description:
"Need to confirm whether the recent rise in breakdowns is real because that context determines whether fleet replacement is relevant.",
kind: "unknown",
status: "unknown",
confidence: "high",
value:
"Breakdowns and missed deliveries have increased over the last quarter.",
childIds: ["van-service-constraint"],
}),
foundationalUnknown: makeNode({
id: "van-reliability-threshold",
label: "Replacement justification threshold",
description:
"Need the threshold because the replacement decision depends on what level of reliability loss is enough to justify replacing the fleet.",
kind: "unknown",
status: "unknown",
confidence: "high",
parentId: "van-decision",
childIds: ["van-service-constraint"],
}),
consequentialUnknown: makeNode({
id: "van-service-constraint",
label: "Operational service constraint",
description:
"Need the limiting service constraint because the team must know how vehicle unreliability is affecting deliveries before comparing purchasing options.",
kind: "unknown",
status: "unknown",
confidence: "high",
dependsOn: ["van-reliability-threshold"],
parentId: "van-reliability-threshold",
childIds: ["van-price"],
}),
downstreamLeaf: makeNode({
id: "van-price",
label: "Exact replacement purchase price",
description:
"Need the exact purchase price because financing analysis comes after replacement is justified.",
kind: "unknown",
status: "unknown",
confidence: "medium",
dependsOn: ["van-service-constraint"],
parentId: "van-service-constraint",
}),
}),
},
{
key: "launch-country",
scenario: "Should we launch in another country?",
decisionType: "market expansion decision",
acceptableFoundationalUnknownNodeIds: [
"country-customer",
"country-value-threshold",
],
prohibitedFirstTopics: [
"launch date",
"office location",
"advertising channel",
],
acceptableQuestionStrategies: ["definition", "decision_threshold"],
notes:
"The first question should clarify the customer or value case for expansion before rollout logistics.",
graph: makeScenarioGraph({
scenario: "Should we launch in another country?",
decisionNode: makeNode({
id: "country-decision",
label: "Launch in another country decision",
description: "Decision about entering a new national market.",
kind: "state",
status: "known",
confidence: "medium",
value: "Deciding whether to launch in another country",
childIds: ["country-customer"],
}),
answeredContextUnknown: makeNode({
id: "country-interest-known",
label: "Inbound interest confirmed",
description:
"Need to confirm whether inbound interest from another country is real because that context determines whether expansion is relevant.",
kind: "unknown",
status: "unknown",
confidence: "medium",
value:
"Prospective customers from another country are asking for access.",
childIds: ["country-value-threshold"],
}),
foundationalUnknown: makeNode({
id: "country-customer",
label: "Relevant customer in the new country",
description:
"Need the relevant customer because the expansion decision depends on who experiences the problem or receives the value in that market.",
kind: "unknown",
status: "unknown",
confidence: "high",
parentId: "country-decision",
childIds: ["country-value-threshold"],
}),
consequentialUnknown: makeNode({
id: "country-value-threshold",
label: "Expansion value threshold",
description:
"Need the value threshold because the team must know what evidence of demand or value would justify entering the new country.",
kind: "unknown",
status: "unknown",
confidence: "high",
dependsOn: ["country-customer"],
parentId: "country-customer",
childIds: ["country-launch-date"],
}),
downstreamLeaf: makeNode({
id: "country-launch-date",
label: "Country launch date",
description:
"Need the launch date because rollout planning follows once the expansion case is established.",
kind: "unknown",
status: "unknown",
confidence: "medium",
dependsOn: ["country-value-threshold"],
parentId: "country-value-threshold",
}),
}),
},
{
key: "over-budget-project",
scenario: "Should we continue a project that is over budget?",
decisionType: "continuation decision",
acceptableFoundationalUnknownNodeIds: [
"project-benefit-threshold",
"project-remaining-benefit",
],
prohibitedFirstTopics: ["sunk cost", "project logo", "final launch date"],
acceptableQuestionStrategies: ["decision_threshold", "definition"],
notes:
"The first question should establish remaining value or success threshold before sunk-cost framing or launch timing.",
graph: makeScenarioGraph({
scenario: "Should we continue a project that is over budget?",
decisionNode: makeNode({
id: "project-decision",
label: "Continue over-budget project decision",
description:
"Decision about continuing a project that has exceeded budget.",
kind: "state",
status: "known",
confidence: "medium",
value: "Deciding whether to continue the over-budget project",
childIds: ["project-benefit-threshold"],
}),
answeredContextUnknown: makeNode({
id: "project-overrun-known",
label: "Budget overrun confirmed",
description:
"Need to confirm whether the project is materially over budget because that context determines whether a continuation decision is relevant.",
kind: "unknown",
status: "unknown",
confidence: "high",
value: "The project has exceeded its approved budget by 35 percent.",
childIds: ["project-remaining-benefit"],
}),
foundationalUnknown: makeNode({
id: "project-benefit-threshold",
label: "Continuation success threshold",
description:
"Need the threshold because the continuation decision depends on what remaining benefit would still justify completing the project.",
kind: "unknown",
status: "unknown",
confidence: "high",
parentId: "project-decision",
childIds: ["project-remaining-benefit"],
}),
consequentialUnknown: makeNode({
id: "project-remaining-benefit",
label: "Remaining project benefit",
description:
"Need the remaining benefit because the team must know what value is still achievable before deciding whether to continue.",
kind: "unknown",
status: "unknown",
confidence: "high",
dependsOn: ["project-benefit-threshold"],
parentId: "project-benefit-threshold",
childIds: ["project-launch-date"],
}),
downstreamLeaf: makeNode({
id: "project-launch-date",
label: "Final launch date",
description:
"Need the final launch date because scheduling details only matter after remaining value is established.",
kind: "unknown",
status: "unknown",
confidence: "medium",
dependsOn: ["project-remaining-benefit"],
parentId: "project-remaining-benefit",
}),
}),
},
{
key: "paid-support-tier",
scenario: "Should we introduce a paid support tier?",
decisionType: "commercial packaging decision",
acceptableFoundationalUnknownNodeIds: [
"support-customer",
"support-value-threshold",
],
prohibitedFirstTopics: [
"subscription price",
"payment provider",
"tier name",
],
acceptableQuestionStrategies: [
"definition",
"decision_threshold",
"baseline_reconstruction",
],
notes:
"The first question should establish who values paid support or what outcome would justify offering it before pricing details.",
graph: makeScenarioGraph({
scenario: "Should we introduce a paid support tier?",
decisionNode: makeNode({
id: "support-decision",
label: "Introduce paid support tier decision",
description: "Decision about adding a paid support offering.",
kind: "state",
status: "known",
confidence: "medium",
value: "Deciding whether to introduce a paid support tier",
childIds: ["support-customer"],
}),
answeredContextUnknown: makeNode({
id: "support-requests-known",
label: "Support request pattern confirmed",
description:
"Need to confirm whether repeated requests for faster support responses are real because that context determines whether a paid tier is relevant.",
kind: "unknown",
status: "unknown",
confidence: "high",
value:
"Some users are asking for guaranteed response times and escalation help.",
childIds: ["support-value-threshold"],
}),
foundationalUnknown: makeNode({
id: "support-customer",
label: "Customer willing to pay for support",
description:
"Need the customer because the decision depends on who experiences enough support pain or receives enough value to pay for a support tier.",
kind: "unknown",
status: "unknown",
confidence: "high",
parentId: "support-decision",
childIds: ["support-value-threshold"],
}),
consequentialUnknown: makeNode({
id: "support-value-threshold",
label: "Paid support value threshold",
description:
"Need the value threshold because the team must know what outcome would justify introducing paid support before setting packaging details.",
kind: "unknown",
status: "unknown",
confidence: "high",
dependsOn: ["support-customer"],
parentId: "support-customer",
childIds: ["support-price"],
}),
downstreamLeaf: makeNode({
id: "support-price",
label: "Support subscription price",
description:
"Need the subscription price because pricing and payment setup come after the support value case is established.",
kind: "unknown",
status: "unknown",
confidence: "medium",
dependsOn: ["support-value-threshold"],
parentId: "support-value-threshold",
}),
}),
},
];