refactor(confidence-engine): migrate scenario persistence to storage provider

This commit is contained in:
2026-08-27 15:44:58 +01:00
parent ba956eeb3a
commit bc35e05253
2 changed files with 339 additions and 27 deletions
+8 -27
View File
@@ -6,6 +6,7 @@ import DiagnosticsView from "@/components/diagnostics-view";
import ReasoningWorkspace, { LoadingOverlay, ContinueLaterBanner } from "@/components/reasoning-workspace";
import { mockFetch, AVAILABLE_SCENARIOS } from "@/lib/mocks/confidence-engine/mock-client";
import { deriveFindingsFromContributions, normalizeFindings } from "@/lib/graph/finding-helpers";
import { loadInvestigation, saveInvestigation, clearInvestigation } from "@/lib/storage/investigation-storage";
/* Compile-time env resolution — NEXT_PUBLIC_ vars are injected by Next.js at build */
const MOCK_ENABLED = process.env.NEXT_PUBLIC_CONFIDENCE_ENGINE_MOCKS === "true";
@@ -192,26 +193,6 @@ export function UpdateErrorPanel({ updateError }) {
export { INITIAL_MESSAGES, UPDATE_MESSAGES, useLoadingStatus };
// ── Session key ────────────────────────────────────────────────
const SESSION_KEY = "confidence-engine-session";
function getSession() {
if (typeof sessionStorage === "undefined") return null;
try {
const raw = sessionStorage.getItem(SESSION_KEY);
return raw ? JSON.parse(raw) : null;
} catch (_) { return null; }
}
function saveSession(state) {
if (typeof sessionStorage === "undefined") return;
try { sessionStorage.setItem(SESSION_KEY, JSON.stringify(state)); } catch (_) {}
}
function clearSession() {
if (typeof sessionStorage === "undefined") return;
try { sessionStorage.removeItem(SESSION_KEY); } catch (_) {}
}
/**
* Derives whether the current component state represents a valid investigation
@@ -310,10 +291,10 @@ export default function ScenarioForm() {
// Delegated to the exported utility below.
const validCtx = hasValidInvestigationContext(result, status, scenario);
/* Restore persisted session on mount (Phase 3) ─────────── */
/* Restore persisted session on mount ─────────── */
useEffect(() => {
if (typeof window === "undefined") return;
const saved = getSession();
const saved = loadInvestigation();
if (!saved) return;
const hasGraph = Boolean(saved.situationGraph);
@@ -407,7 +388,7 @@ export default function ScenarioForm() {
setCurrentUnderstanding(data.summary ?? null);
const normalised = normaliseStartResult(data);
setResult(normalised);
saveSession({ scenario, situationGraph: normalised.situationGraph, selectedQuestion: normalised.selectedQuestion, summary: data.summary ?? null, updatedAt: new Date().toISOString(), focusedContributions, findings: [] });
saveInvestigation({ scenario, situationGraph: normalised.situationGraph, selectedQuestion: normalised.selectedQuestion, summary: data.summary ?? null, updatedAt: new Date().toISOString(), focusedContributions, findings: [] });
} else {
setStatus("error");
setCurrentUnderstanding(data.summary ?? null);
@@ -480,7 +461,7 @@ export default function ScenarioForm() {
}));
setAnswer("");
// Persist after successful update turn — include findings
saveSession({ scenario, situationGraph: outcome.updatedSituationGraph, selectedQuestion: normaliseUpdateSelectedQuestion(outcome.selectedQuestion), summary: outcome.summary ?? currentUnderstanding, updatedAt: new Date().toISOString(), focusedContributions, findings: newFindings });
saveInvestigation({ scenario, situationGraph: outcome.updatedSituationGraph, selectedQuestion: normaliseUpdateSelectedQuestion(outcome.selectedQuestion), summary: outcome.summary ?? currentUnderstanding, updatedAt: new Date().toISOString(), focusedContributions, findings: newFindings });
} else {
setUpdateStatus("error");
setUpdateError(outcome);
@@ -642,7 +623,7 @@ export default function ScenarioForm() {
onUpdateFindingDisposition={updateFindingDisposition}
onUpdateFindingProposition={updateFindingProposition}
onRestart={() => {
clearSession();
clearInvestigation();
setStatus("idle");
setResult(null);
setAnswer("");
@@ -662,7 +643,7 @@ export default function ScenarioForm() {
{/* ── Continue later banner when session was restored ── */}
{status === "success" && result?.updatedAt && (
<ContinueLaterBanner onRestart={() => { clearSession(); setStatus("idle"); setResult(null); setAnswer(""); setUpdateStatus("idle"); setCurrentUnderstanding(null); setFocusedContributions([]); setFindings([]); }} />
<ContinueLaterBanner onRestart={() => { clearInvestigation(); setStatus("idle"); setResult(null); setAnswer(""); setUpdateStatus("idle"); setCurrentUnderstanding(null); setFocusedContributions([]); setFindings([]); }} />
)}
{/* Reset button after successful analysis */}
@@ -670,7 +651,7 @@ export default function ScenarioForm() {
<div className="text-center">
<button
onClick={() => {
clearSession();
clearInvestigation();
setScenario("");
setStatus("idle");
setResult(null);