From 32e1b0176725fbc3196ddde60b6737a6ceeecca5 Mon Sep 17 00:00:00 2001 From: robbond Date: Thu, 3 Sep 2026 06:39:35 +0100 Subject: [PATCH] feat(confidence-engine): separate investigation report routes --- app/investigations/[id]/page.jsx | 50 +++ app/investigations/[id]/report/page.jsx | 109 ++++++ app/page.jsx | 86 ++++- components/reasoning-workspace.jsx | 3 +- components/scenario-form.jsx | 46 ++- docs/current-handoff.md | 75 ++++ portfolio-home.png | Bin 0 -> 71943 bytes tests/ui/investigation-overview-ui.test.jsx | 374 +++++++++++--------- 8 files changed, 567 insertions(+), 176 deletions(-) create mode 100644 app/investigations/[id]/page.jsx create mode 100644 app/investigations/[id]/report/page.jsx create mode 100644 portfolio-home.png diff --git a/app/investigations/[id]/page.jsx b/app/investigations/[id]/page.jsx new file mode 100644 index 0000000..ebd8ce7 --- /dev/null +++ b/app/investigations/[id]/page.jsx @@ -0,0 +1,50 @@ +"use client"; + +import React from "react"; +import { loadInvestigation } from "@/lib/storage/investigation-storage"; +import ScenarioForm from "@/components/scenario-form"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { useEffect, useState } from "react"; + +const INVESTIGATION_ID = "case-1"; + +export default function InvestigationPage() { + const router = useRouter(); + const [existing, setExisting] = useState(null); + + useEffect(() => { + setExisting(loadInvestigation()); + }, []); + + return ( +
+ {/* Page-level navigation — owned by route, not ReasoningWorkspace */} + + +

Confidence Engine

+

+ Experimental prototype: enter a scenario and send it to a local LLM for + evidence-based structured reconstruction. This is a technical vertical + slice — not a production system. +

+ {existing ? ( + router.push(`/investigations/${INVESTIGATION_ID}/report`)} + /> + ) : ( + router.push(`/investigations/${INVESTIGATION_ID}/report`)} + /> + )} +
+ ); +} diff --git a/app/investigations/[id]/report/page.jsx b/app/investigations/[id]/report/page.jsx new file mode 100644 index 0000000..5529d76 --- /dev/null +++ b/app/investigations/[id]/report/page.jsx @@ -0,0 +1,109 @@ +"use client"; + +import React, { useEffect, useState } from "react"; +import { loadInvestigation } from "@/lib/storage/investigation-storage"; +import Link from "next/link"; + +export default function ReportPage() { + const [existing, setExisting] = useState(null); + const [hydrated, setHydrated] = useState(false); + + useEffect(() => { + setExisting(loadInvestigation()); + setHydrated(true); + }, []); + + const report = existing?.investigationReport || null; + const scenario = hydrated ? (existing?.scenario || "") : null; + + const paragraphs = (report?.understanding || "") + .split("\n") + .filter(Boolean); + + return ( +
+

+ Investigation Report +

+ + {/* Situation */} + {scenario && ( +
+

+ Situation +

+

+ {scenario} +

+
+ )} + + {/* What we understand */} + {report ? ( + <> + {paragraphs.length > 0 ? ( + paragraphs.map((p, i) => ( +
+

+ What we understand +

+

{p}

+
+ )) + ) : ( +
+

+ What we understand +

+

{report.understanding || ""}

+
+ )} + + {/* What remains plausible — conditional */} + {report.hasPlausibleInterpretations && report.plausibleInterpretations ? ( +
+

+ What remains plausible +

+

+ {report.plausibleInterpretations} +

+
+ ) : null} + + ) : ( + /* Skeleton / loading state when no persisted report exists */ + <> +
+

+ What we understand +

+

+ Report generation pending. A summary will appear here once the investigation reaches milestone. +

+
+ + )} + + {/* Back to investigation */} +
+ + Back to investigation + +
+ + {/* Back to portfolio */} +
+ + Back to portfolio + +
+
+ ); +} diff --git a/app/page.jsx b/app/page.jsx index fd3b208..5c78630 100644 --- a/app/page.jsx +++ b/app/page.jsx @@ -1,15 +1,87 @@ -import ScenarioForm from "@/components/scenario-form"; +"use client"; + +import React from "react"; +import { loadInvestigation } from "@/lib/storage/investigation-storage"; +import Link from "next/link"; + +const INVESTIGATION_ID = "case-1"; + +function Portfolio() { + const [existing, setExisting] = React.useState(null); + + React.useEffect(() => { + setExisting(loadInvestigation()); + }, []); + + const hasReport = Boolean( + existing?.investigationReport && existing.investigationReport.understanding + ); -export default function Home() { return ( -
+

Confidence Engine

- Experimental prototype: enter a scenario and send it to a local LLM for - evidence-based structured reconstruction. This is a technical vertical - slice — not a production system. + Investigator's notebook — index of persisted investigations.

- + + {/* Existing investigation */} + {existing && ( +
+

+ Investigations +

+ +
+

+ {existing.scenario || "Untitled investigation"} +

+ +
+ {hasReport ? ( + + View report + + ) : null} + + + Open investigation + + + + Create new investigation + +
+
+
+ )} + + {/* No existing investigation */} + {!existing && ( +
+

+ Investigations +

+

No investigations yet.

+
+ )} + + + + Create new investigation +
); } + +export default Portfolio; diff --git a/components/reasoning-workspace.jsx b/components/reasoning-workspace.jsx index dcf3ca4..a27a569 100644 --- a/components/reasoning-workspace.jsx +++ b/components/reasoning-workspace.jsx @@ -1336,6 +1336,7 @@ export default function ReasoningWorkspace({ setOverviewState, overviewLoading, handleRequestOverview, + onNavigateToReport, }) { const [investigationHistory, setInvestigationHistory] = useState([]); const turnCounter = useRef(0); @@ -1956,7 +1957,7 @@ export default function ReasoningWorkspace({