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
+75
View File
@@ -419,8 +419,83 @@ The overview did not merely duplicate Current Understanding. It added operationa
**One-sentence judgement:** The overview provides a genuinely distinct investigation-level synthesis with operational framing beyond Current Understanding; the empty plausible interpretations section was due to missing graph data in this session, not an implementation defect.
### v0.55 — Route architecture: Portfolio / Investigation / Investigation Report separation (verified)
**Objective:** Make one bounded architectural change — can Portfolio, Investigation, and Investigation Report become three separate page/route concepts, with report presentation removed from ReasoningWorkspace? Zero live-model-call implementation increment.
**Product decision established:**
```
/ → Portfolio / notebook index
/investigations/:id → working Investigation (ScenarioForm + ReasoningWorkspace)
/investigations/:id/report → Investigation Report (persisted derived artefact)
Investigation Report
→ Back to investigation → /investigations/:id
```
**Files created:**
- `app/page.jsx` — Portfolio page. Shows existing investigation card when one exists; "View report" button (only when `investigationReport` present); "Open investigation" and "Create new investigation" links pointing to `/investigations/case-1`. No multi-investigation management, search, or filters.
- `app/investigations/[id]/page.jsx` — Investigation route. Loads persisted snapshot via `loadInvestigation()` and renders `ScenarioForm`. Working behaviour fully preserved: graph reasoning, focused investigation, Done/Re-open, Current Understanding, synthesis triggers.
- `app/investigations/[id]/report/page.jsx` — Report page. Renders persisted `investigationReport` with Situation, "What we understand" (paragraph-split), conditional "What remains plausible", and skeleton loading state when no report exists.
**Files edited:**
- `components/reasoning-workspace.jsx` — Removed: InvestigationReport component definition, hasReport gate/early return, `investigationReport`/`setInvestigationReport`/`reportViewMode`/`setReportViewMode` props. ReasoningWorkspace now owns only working Investigation presentation. Milestone button text restored to always "Review current understanding".
- `components/scenario-form.jsx` — Removed: `reportViewMode` state (obsolete — routing now owns page selection). Prop plumbing to ReasoningWorkspace no longer includes report mode switching. `investigationReport` persistence/hydration semantics preserved (still persisted into canonical snapshot via `saveInvestigation`).
- `tests/ui/investigation-overview-ui.test.jsx` — Rewritten from component-level report presentation tests (16 tests) to route-level assertions (12 tests): Portfolio rendering with investigation card, conditional View report button, Report page rendering persisted data, conditional What remains plausible, skeleton loading state, Back to investigation link, and ReasoningWorkspace no longer rendering investigation-report.
**Verification:**
- Exact Vitest command: `npx vitest run tests/ui/investigation-overview-ui.test.jsx` — 12/12 PASS
- Build: `npm run build` — compiles successfully, zero errors
- Live Portfolio verification (Playwright): persisted investigation visible, "No investigations yet." absent, Open investigation link functional, Investigation page opens with full persisted state retained
- No live model calls made (0)
**Persistence boundary fix (v0.55):**
- `app/page.jsx` was a React Server Component calling `loadInvestigation()` at render time — `window` undefined on server → `null` returned → "No investigations yet." always displayed
- Added `'use client'` directive to `app/page.jsx` so Portfolio hydrates from localStorage client-side
- Canonical `loadInvestigation()` remains the persistence owner; no new storage mechanism introduced
- Investigation visibility does not depend on report existence (card always renders when investigation exists; "View report" is conditional)
- Temporary route identity remains `case-1`; multi-investigation identity/storage remains future work
**Route build output:**
```
/ → static
/investigations/[id] → dynamic (server-rendered)
/investigations/[id]/report → static/dynamic
```
**Limitations documented for later increments:**
- Portfolio currently supports only the one canonical persisted investigation (`confidence-engine-investigation` localStorage key).
- "Create new investigation" routes to `/investigations/case-1` (the Investigation page) but true multi-investigation creation/storage is not yet implemented — it navigates to the single existing workspace.
- The investigation identity for this increment is `case-1` — deliberately simple, no UUID generation or multi-investigation identity system.
- Report generation/loading lifecycle still requires live verification in the next increment.
- Portfolio expansion, multi-investigation identity/storage, report freshness, and export remain future work.
**Persistence:** Existing `investigationReport` persistence preserved via canonical snapshot storage (`saveInvestigation` includes `investigationReport`). Report stored as derived artefact of investigation — not as separate storage mechanism. No new report localStorage introduced.
## Open defects
- Empty Done `no_episodic_content`: choosing Done without episodic content can produce `{ success: false, stage: "preparation", error: "no_episodic_content" }` — separate future increment (empty-Done orchestration guard now prevents the 400 in practice by skipping episode processing entirely)
### v0.55 — Live report hydration verification (verified 2026-09-03)
**Objective:** Answer whether `View report` opens the persisted Investigation Report rather than the pending placeholder after Portfolio client hydration.
**Playwright result: PASS**
- Portfolio page loaded at `http://localhost:3000/`; hydration waited via semantic control `page.getByRole('link', { name: 'View report' })` — became visible within 10s
- Persisted investigation card rendered (pre-hydration "No investigations yet." is expected transient state, not evidence of missing storage)
- Clicked `View report` → URL navigated to `/investigations/case-1/report`
- Report page: "Investigation Report" heading — present ✅
- Report page: "What we understood" heading — present ✅
- Persisted understanding content rendered (non-placeholder, substantive findings about 25% premium product sales decline, competitive pricing pressure, unquantified variables) ✅
- Does NOT show placeholder text "Report generation pending. A summary will appear here once the investigation reaches milestone." ✅
- "Back to investigation" link — visible ✅
- "Back to portfolio" link — visible ✅
- Model calls during verification: 0
**Key insight for future work:** Portfolio's initial pre-hydration empty state (`No investigations yet.`) ≠ absence of persisted investigation. Client hydration is part of the product behaviour — wait for the hydrated semantic control before classifying state.
**Next restart point:** The empty-Done `no_episodic_content` 400. Implement and verify that a Done action taken when no episodic evidence exists produces the same user-facing state (CU refresh with appropriate messaging) without a 400 error.