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 criterion", "constraint"], 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 criterion", "constraint"], 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: ["actor/customer", "decision criterion"], 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 criterion", "objective"], 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: ["actor/customer", "decision criterion"], 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", }), }), }, ];