feat(confidence-engine): separate investigation report routes

This commit is contained in:
2026-09-03 06:39:35 +01:00
parent 745026f0a0
commit 32e1b01767
8 changed files with 567 additions and 176 deletions
+2 -1
View File
@@ -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({
</p>
<button
onClick={() => {
handleRequestOverview();
onNavigateToReport?.();
}}
disabled={overviewLoading}
style={{ cursor: overviewLoading ? "wait" : "pointer" }}
+40 -6
View File
@@ -271,7 +271,7 @@ export async function executeEpisodeDone({
return { success: true, nextGraph, synthesisResult };
}
export default function ScenarioForm() {
export default function ScenarioForm({ onNavigateToReport }) {
const [scenario, setScenario] = useState("");
const [status, setStatus] = useState("idle"); // idle | loading | error | success
const [result, setResult] = useState(null);
@@ -289,6 +289,9 @@ export default function ScenarioForm() {
const [overviewState, setOverviewState] = useState(null);
const [overviewLoading, setOverviewLoading] = useState(false);
/* ── v0.55 — persisted investigation report (derived artefact) ── */
const [investigationReport, setInvestigationReport] = useState(null);
/* ── in-flight gate for episode reconsideration on Done ──── */
const doneInProgressRef = useRef(false);
@@ -418,8 +421,8 @@ export default function ScenarioForm() {
}
/**
* v0.54b — request investigation overview via the established POST /api/cases/overview seam.
* Transient state only: never persists to SituationGraph or currentUnderstanding.
* v0.54b/v0.55 — request investigation overview via the established POST /api/cases/overview seam.
* Produces a distinct Investigation Report: a derived artefact, not canonical reasoning state.
*/
async function handleRequestOverview() {
if (overviewLoading || !result?.situationGraph) return;
@@ -427,6 +430,9 @@ export default function ScenarioForm() {
setOverviewLoading(true);
setOverviewState(null); // clear any previous overview before new request
const plausibleInput = (result.situationGraph?.reconstruction || {}).plausibleInterpretations ?? [];
const hasPlausibleInput = Array.isArray(plausibleInput) && plausibleInput.length > 0;
try {
const res = await fetch("/api/cases/overview", {
method: "POST",
@@ -434,12 +440,32 @@ export default function ScenarioForm() {
body: JSON.stringify({
situationGraph: result.situationGraph,
findings,
plausibleInterpretations: (result.situationGraph?.reconstruction || {}).plausibleInterpretations ?? [],
plausibleInterpretations: plausibleInput,
}),
}).then((r) => r.json());
if (res?.success && res?.understanding != null) {
setOverviewState(res);
// Persist as a derived artefact of this investigation
const report = {
understanding: res.understanding,
plausibleInterpretations: hasPlausibleInput ? res.plausibleInterpretations ?? "" : "",
hasPlausibleInterpretations: hasPlausibleInput,
};
setInvestigationReport(report);
// Trigger autosave to persist the report
void saveInvestigation({
scenario,
situationGraph: result.situationGraph,
selectedQuestion: result.selectedQuestion,
summary: currentUnderstanding,
updatedAt: new Date().toISOString(),
focusedContributions,
findings,
investigationReport: report,
});
}
// On failure: do not clear existing CU, do not block further attempts
} finally {
@@ -508,6 +534,11 @@ export default function ScenarioForm() {
setFocusedContributions(saved.focusedContributions || []);
setFindings(saved.findings || []);
/* ── v0.55 — hydrate persisted investigation report ─── */
if (saved.investigationReport) {
setInvestigationReport(saved.investigationReport);
}
// Partial sessions (present but no graph) must NOT suppress the
// scenario-entry form. Only promote to success when there is actual
// investigation data to render.
@@ -533,6 +564,7 @@ export default function ScenarioForm() {
updatedAt: new Date().toISOString(),
focusedContributions,
findings,
investigationReport,
});
}, [
scenario,
@@ -541,6 +573,7 @@ export default function ScenarioForm() {
currentUnderstanding,
focusedContributions,
findings,
investigationReport,
]);
/* Restore facilitator dismiss preference (Experiment 05) ─── */
@@ -618,7 +651,7 @@ export default function ScenarioForm() {
setCurrentUnderstanding(data.summary ?? null);
const normalised = normaliseStartResult(data);
setResult(normalised);
saveInvestigation({ 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: [], investigationReport });
} else {
setStatus("error");
setCurrentUnderstanding(data.summary ?? null);
@@ -702,7 +735,7 @@ export default function ScenarioForm() {
setAnswer("");
// Persist after successful update turn — include explicit next state
saveInvestigation({ scenario, situationGraph: nextGraph, selectedQuestion: normaliseUpdateSelectedQuestion(outcome.selectedQuestion), summary: currentUnderstanding, updatedAt: new Date().toISOString(), focusedContributions, findings: nextFindings });
saveInvestigation({ scenario, situationGraph: nextGraph, selectedQuestion: normaliseUpdateSelectedQuestion(outcome.selectedQuestion), summary: currentUnderstanding, updatedAt: new Date().toISOString(), focusedContributions, findings: nextFindings, investigationReport });
} else {
setUpdateStatus("error");
setUpdateError(outcome);
@@ -852,6 +885,7 @@ export default function ScenarioForm() {
setOverviewState={setOverviewState}
overviewLoading={overviewLoading}
handleRequestOverview={handleRequestOverview}
onNavigateToReport={onNavigateToReport}
result={{
...(result || {}),
situationGraph: updateResult?.updatedSituationGraph ?? result?.situationGraph,