feat: surface answer impact after update
This commit is contained in:
@@ -250,6 +250,89 @@ function LoadingOverlay({ isLoading, elapsed, currentMessage, variant }) {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Update acknowledgement ────────────────────────────────────
|
||||
function UpdateAcknowledgement({ answer, updateResult }) {
|
||||
if (!updateResult || !answer?.trim()) return null;
|
||||
|
||||
const hasResolvedNodes =
|
||||
updateResult.resolvedUnknownNodeIds && updateResult.resolvedUnknownNodeIds.length > 0;
|
||||
const hasAffectedNodes =
|
||||
updateResult.affectedNodeIds && updateResult.affectedNodeIds.length > 0;
|
||||
const graph = updateResult.updatedSituationGraph;
|
||||
|
||||
function getNodeText(nodeId) {
|
||||
if (!graph?.nodes) return String(nodeId);
|
||||
const node = graph.nodes.find((n) => n.id === nodeId);
|
||||
if (node) {
|
||||
const parts = [node.label];
|
||||
if (node.status !== "resolved") {
|
||||
parts.push(node.status);
|
||||
}
|
||||
return parts.join(" ");
|
||||
}
|
||||
return String(nodeId);
|
||||
}
|
||||
|
||||
let changedText;
|
||||
if (hasResolvedNodes || hasAffectedNodes) {
|
||||
const items = [];
|
||||
if (hasResolvedNodes) {
|
||||
for (const id of updateResult.resolvedUnknownNodeIds.slice(0, 5)) {
|
||||
items.push(getNodeText(id));
|
||||
}
|
||||
if (updateResult.resolvedUnknownNodeIds.length > 5) {
|
||||
items.push(`and ${updateResult.resolvedUnknownNodeIds.length - 5} more resolved`);
|
||||
}
|
||||
}
|
||||
if (hasAffectedNodes && !hasResolvedNodes) {
|
||||
for (const id of updateResult.affectedNodeIds.slice(0, 5)) {
|
||||
items.push(getNodeText(id));
|
||||
}
|
||||
if (updateResult.affectedNodeIds.length > 5) {
|
||||
items.push(`and ${updateResult.affectedNodeIds.length - 5} more affected`);
|
||||
}
|
||||
}
|
||||
if (items.length === 0 && updateResult.changesApplied) {
|
||||
const parts = [];
|
||||
const ca = updateResult.changesApplied;
|
||||
if (ca.addedNodeCount) parts.push(`${ca.addedNodeCount} node(s) added`);
|
||||
if (ca.updatedNodeCount) parts.push(`${ca.updatedNodeCount} node(s) updated`);
|
||||
if (ca.resolvedUnknownCount) parts.push(`${ca.resolvedUnknownCount} unknown(s) resolved`);
|
||||
changedText = parts.join(", ");
|
||||
} else {
|
||||
changedText = items.join(". ") + ".";
|
||||
}
|
||||
} else if (updateResult.changesApplied) {
|
||||
const ca = updateResult.changesApplied;
|
||||
const parts = [];
|
||||
if (ca.addedNodeCount) parts.push(`${ca.addedNodeCount} node(s) added`);
|
||||
if (ca.updatedNodeCount) parts.push(`${ca.updatedNodeCount} node(s) updated`);
|
||||
if (ca.addedEdgeCount) parts.push(`${ca.addedEdgeCount} edge(s) added`);
|
||||
if (ca.removedEdgeCount) parts.push(`${ca.removedEdgeCount} edge(s) removed`);
|
||||
changedText = parts.length > 0 ? parts.join(", ") : null;
|
||||
}
|
||||
|
||||
const summary = updateResult.summary || null;
|
||||
const displayChanged = summary || changedText || "Your answer has been added to the investigation.";
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border border-blue-200 bg-blue-50 px-5 py-4 space-y-3">
|
||||
<div>
|
||||
<h3 className="mb-1 text-xs font-medium uppercase tracking-wide text-blue-700">
|
||||
You told us
|
||||
</h3>
|
||||
<p className="text-sm leading-relaxed text-blue-900">{answer}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="mb-1 text-xs font-medium uppercase tracking-wide text-blue-700">
|
||||
What changed
|
||||
</h3>
|
||||
<p className="text-sm leading-relaxed text-blue-900">{displayChanged}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// ── Developer details disclosure ──────────────────────────────
|
||||
function DeveloperDetails({ graph, selectedQuestion, diagnostics, newlySurfacedNodeIds, updateResult }) {
|
||||
return (
|
||||
@@ -340,11 +423,16 @@ export default function ReasoningWorkspace({
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{/* Completion or holding state (only when there is no next question) */}
|
||||
{/* ── Post-update acknowledgement ─────────────── */}
|
||||
{updateStatus === "success" && graph && (
|
||||
<UpdateAcknowledgement answer={answer} updateResult={result} />
|
||||
)}
|
||||
|
||||
{/* Completion state (only when there is no next question and nothing remains) */}
|
||||
{status === "success" && !canAnswer && graph && genuineCompletion && (
|
||||
<InvestigationCompleteMessage noQuestionReason={noQuestionReason} />
|
||||
)}
|
||||
{status === "success" && !canAnswer && graph && unresolvedRemaining && (
|
||||
{status === "success" && !canAnswer && graph && unresolvedRemaining && updateStatus !== "success" && (
|
||||
<div className="rounded-lg border border-gray-200 bg-gray-50 px-5 py-4 text-center">
|
||||
<p className="text-sm text-gray-600">There is no further question the engine can justify at the moment.</p>
|
||||
<p className="mt-1 text-xs text-gray-500">More evidence may be needed before a next step is clear.</p>
|
||||
|
||||
Reference in New Issue
Block a user