From 72ef1759714ff7c458d71d8f3cac4f8bfd9bce24 Mon Sep 17 00:00:00 2001 From: robbond Date: Sun, 2 Aug 2026 10:30:59 +0100 Subject: [PATCH 1/6] feat: surface new unknowns after graph updates --- components/graph-update-view.jsx | 21 +- components/scenario-form.jsx | 58 +++++- components/situation-graph-view.jsx | 26 ++- lib/graph/apply-proposal.js | 207 +++++++++++++++++++ lib/graph/orchestrator.js | 1 + lib/graph/prompt-builder.js | 41 ++-- lib/graph/schema.js | 18 +- lib/graph/update-proposal.js | 19 ++ tests/app/api/cases-update-route.test.js | 3 + tests/graph/apply-proposal.test.js | 244 +++++++++++++++++++++++ tests/graph/orchestrator.test.js | 61 ++++++ tests/graph/prompt-builder.test.js | 10 + tests/graph/schema.test.js | 100 ++++++++-- tests/graph/update-proposal.test.js | 30 ++- tests/smoke.test.js | 8 +- tests/ui/scenario-form.test.jsx | 104 +++++++++- 16 files changed, 910 insertions(+), 41 deletions(-) diff --git a/components/graph-update-view.jsx b/components/graph-update-view.jsx index 78f9bcd..23a0109 100644 --- a/components/graph-update-view.jsx +++ b/components/graph-update-view.jsx @@ -23,12 +23,17 @@ export default function GraphUpdateView({ updateResult }) { affectedNodeIds, previousActiveUnknownNodeId, newActiveUnknownNodeId, + selectedQuestion, changesApplied, proposal, previousSituationGraph, updatedSituationGraph, } = updateResult; + const newlySurfacedUnknownNodeIds = (proposal.addedNodes || []) + .filter((node) => node.kind === "unknown") + .map((node) => node.id); + const previousNodesById = new Map( (previousSituationGraph?.nodes || []).map((node) => [node.id, node]), ); @@ -123,10 +128,15 @@ export default function GraphUpdateView({ updateResult }) { {resolveActiveUnknown(newActiveUnknownNodeId)} )} - {!newActiveUnknownNodeId && previousActiveUnknownNodeId && ( + {selectedQuestion?.question && (
- Next question status: No next - question selected yet. + Next question:{" "} + {selectedQuestion.question} +
+ )} + {!selectedQuestion?.question && !newActiveUnknownNodeId && previousActiveUnknownNodeId && ( +
+ Next question status: No next question selected yet.
)} @@ -137,6 +147,11 @@ export default function GraphUpdateView({ updateResult }) { items={resolvedUnknownNodeIds} renderItem={resolveNodePresentation} /> + )} @@ -192,7 +200,12 @@ export default function ScenarioForm() { setResult((current) => ({ ...current, situationGraph: outcome.updatedSituationGraph, - selectedQuestion: null, + selectedQuestion: normaliseUpdateSelectedQuestion( + outcome.selectedQuestion, + ), + newlySurfacedNodeIds: (outcome.proposal?.addedNodes || []) + .filter((node) => node.kind === "unknown") + .map((node) => node.id), diagnostics: outcome.diagnostics, })); setAnswer(""); @@ -208,9 +221,14 @@ export default function ScenarioForm() { const canRenderAnswerForm = status === "success" && + updateStatus === "idle" && Boolean(result?.situationGraph) && Boolean(result?.selectedQuestion); + const canRenderDisabledFollowUpForm = + updateStatus === "success" && + Boolean(updateResult?.selectedQuestion?.question || result?.selectedQuestion); + return (
@@ -277,8 +295,44 @@ export default function ScenarioForm() { {updateStatus === "success" && updateResult && ( <>
- No next question selected yet. + {updateResult.selectedQuestion?.question + ? updateResult.selectedQuestion.question + : "No next question selected yet."}
+ {canRenderDisabledFollowUpForm && ( + +
+

Selected Question

+

+ {updateResult.selectedQuestion?.question || result?.selectedQuestion} +

+
+
+ +