feat(confidence-engine): v0.60e route investigation identity

Migrate the Investigation page route to own durable investigation identity
via its route [id] segment, passing that ID through to ScenarioForm for
hydration and persistence.

- Remove hardcoded INVESTIGATION_ID constant from page.jsx
- Use params.id as routeId; loadInvestigation(routeId) loads by identity
- Pass investigationId prop into ScenarioForm in both branch paths
- Session restore calls loadInvestigation(investigationId)
- All 4 save call sites include id: investigationId in snapshot
- Missing identified Investigation starts clean (no singleton fallback)
- Legacy singleton is not migrated/fallback-loaded
- Portfolio remains unmigrated; Report remains unmigrated; Restart untouched

Deterministic tests: 34/34 pass (scenario-form-persistence + investigation-storage)
Build: PASS
Live Playwright: all criteria verified at /investigations/v060e-live
This commit is contained in:
2026-09-03 19:02:37 +01:00
parent 827411f254
commit 01e141aa66
3 changed files with 52 additions and 13 deletions
+6 -4
View File
@@ -271,7 +271,7 @@ export async function executeEpisodeDone({
return { success: true, nextGraph, synthesisResult };
}
export default function ScenarioForm({ onNavigateToReport }) {
export default function ScenarioForm({ investigationId, onNavigateToReport }) {
const [scenario, setScenario] = useState("");
const [status, setStatus] = useState("idle"); // idle | loading | error | success
const [result, setResult] = useState(null);
@@ -476,6 +476,7 @@ export default function ScenarioForm({ onNavigateToReport }) {
// Trigger autosave to persist the report
void saveInvestigation({
id: investigationId,
scenario,
situationGraph: result.situationGraph,
selectedQuestion: result.selectedQuestion,
@@ -543,7 +544,7 @@ export default function ScenarioForm({ onNavigateToReport }) {
/* Restore persisted session on mount ─────────── */
useEffect(() => {
if (typeof window === "undefined") return;
const saved = loadInvestigation();
const saved = investigationId ? loadInvestigation(investigationId) : null;
if (!saved) return;
const hasGraph = Boolean(saved.situationGraph);
@@ -580,6 +581,7 @@ export default function ScenarioForm({ onNavigateToReport }) {
if (!result?.situationGraph) return;
void saveInvestigation({
id: investigationId,
scenario,
situationGraph: result.situationGraph,
selectedQuestion: result.selectedQuestion,
@@ -678,7 +680,7 @@ export default function ScenarioForm({ onNavigateToReport }) {
setResult(normalised);
/* ── v0.59a — provenance: first meaningful change sets revision to 1 ── */
setInvestigationRevision(1);
saveInvestigation({ scenario, situationGraph: normalised.situationGraph, selectedQuestion: normalised.selectedQuestion, summary: data.summary ?? null, updatedAt: new Date().toISOString(), focusedContributions, findings: [], investigationReport, investigationRevision: 1 });
saveInvestigation({ id: investigationId, scenario, situationGraph: normalised.situationGraph, selectedQuestion: normalised.selectedQuestion, summary: data.summary ?? null, updatedAt: new Date().toISOString(), focusedContributions, findings: [], investigationReport, investigationRevision: 1 });
} else {
setStatus("error");
setCurrentUnderstanding(data.summary ?? null);
@@ -765,7 +767,7 @@ export default function ScenarioForm({ onNavigateToReport }) {
/* ── v0.59a — provenance: meaningful change advances revision ── */
const nextRev = (investigationRevision ?? 0) + 1;
setInvestigationRevision(nextRev);
saveInvestigation({ scenario, situationGraph: nextGraph, selectedQuestion: normaliseUpdateSelectedQuestion(outcome.selectedQuestion), summary: currentUnderstanding, updatedAt: new Date().toISOString(), focusedContributions, findings: nextFindings, investigationReport, investigationRevision: nextRev });
saveInvestigation({ id: investigationId, scenario, situationGraph: nextGraph, selectedQuestion: normaliseUpdateSelectedQuestion(outcome.selectedQuestion), summary: currentUnderstanding, updatedAt: new Date().toISOString(), focusedContributions, findings: nextFindings, investigationReport, investigationRevision: nextRev });
} else {
setUpdateStatus("error");
setUpdateError(outcome);