- Empty Done immediate transition now sets node.status to resolved
alongside resolvedNodeIds/doneForNowIds — same canonical parked
shape as populated Done (no server call required)
- Clarified-question Re-open removes target from doneForNowIds so
the question visibly returns to Open Questions
- Immediate graph mutation creates new node objects immutably
(React state semantics), touching only the target node
Adopt executeEpisodeDone orchestration as the canonical path for
'Done for now' activity boundary: one user Done triggers exactly
prepareCompletedEpisode -> reconsiderCompletedEpisode -> applyValidatedProposal
-> Current Understanding synthesis -> leave focused workspace.
Production changes (components/scenario-form.jsx):
- Add prepareCompletedEpisode, reconsiderCompletedEpisode, applyValidatedProposal imports
- Export executeEpisodeDone({params}) with all 4 domain functions as named
parameters (defaults to module exports) for deterministic test wiring
- Rewrite handleDoneForNowPromotion(targetNodeId) as async: delegates to
executeEpisodeDone pipeline; CU synthesis installed only on success
- Add doneInProgressRef useRef(false) for exactly-once Done enforcement
- On synthesis failure: KEEP updated graph, KEEP Findings, KEEP existing CU
- Retire produceFindingInformedSummary from ScenarioForm (legacy CU writer)
- Remove legacy idempotence guard and Evidence:[] regex dedup
Test changes (tests/ui/scenario-form-episode-done.test.jsx):
- 9 tests verifying orchestration pipeline correctness:
1. Successful path order: prepare -> reconsider -> apply -> synthesis
2. Correct prepared episode input parameters
3. Structured application evidence (no answer fields in context)
4. nextGraph used for synthesis (not stale result state)
5. Reasoning failure: apply not called, CU synthesis not called
6. Application failure: CU synthesis not called, graph not replaced
7. Synthesis failure: nextGraph remains installed (no rollback)
8. Exactly-once per call for each domain function
9. Legacy Done writer retired (pipeline does not produce deterministic summary)
Architecture: after successful /api/cases/update, derive explicit nextGraph +
nextFindings, call synthesizeFromFindings exactly once, replace Current
Understanding with reconstruction result.
Key invariants:
- outcome.summary retired as final CU authority → always synthesis reconstruction
- Explicit derived state (no React-state reread) for graph and findings
- Previous CU preserved on synthesis failure (no fallback to outcome.summary)
- Graph and Findings NOT lost on synthesis failure
- saveInvestigation persistence uses currentUnderstanding, not outcome.summary
Deterministic regression: 7 tests (Cases A-E + 2 edges) covering all rules.
Files: components/scenario-form.jsx, tests/ui/scenario-form-case-update-synthesis.test.jsx
Verified: deriveFindingsFromContributions() exists with passing tests but
is never called in production. The contributions → findings seam is un-wired:
1. handleDeconstructSubmit() sends contribution to ScenarioForm
2. appendFocusedContribution() stores it in focusedContributions[]
3. findings state stays [] — no derivation ever runs
4. empty findings sent to /api/cases/update (which only echoes them back)
5. nothing renders from the findings surface
Fix: call deriveFindingsFromContributions after contribution is appended.
- Add focusedContributions state + appendFocusedContribution callback in ScenarioForm
- Contributions persist through session lifecycle (save/restore/restart)
- Pass onFocusedContribution and focusedContributions to ReasoningWorkspace
- Call onFocusedContribution on successful deconstruct with full result shape
- Test: contribution sequence, field preservation, same/different target coexistence
Emphasise the active investigation card through stronger elevation,
clearer borders, and improved spacing. Quiet supporting panels by
reducing border opacity, softening heading weight, and lowering
text contrast — making them available without competing for attention.
Facilitator card receives a warm surface tint to read as a briefing
card rather than a generic panel.
Documentation: close experiment 05 with findings, add experiment 06
to the design evolution log, add Attention Hierarchy to UX guidelines,
defer dark mode to a future Investigation Mode experiment.
Presentation changes only — no reasoning, prompts, graph, API, or
backend modifications.
Phase 2: Recovery state components (ProviderUnavailableCard,
MalformedResponseCard, UnexpectedStateCard, ContinueLaterBanner) with
automatic error detection for provider/network/malformed/unexpected states.
Phase 3: Session persistence via sessionStorage — save after each
successful turn, restore on mount, clear on restart/reset. Continuelater banner shown when session is restored.
Phase 4: InvestigationSummaryPanel component displaying current status,
understanding summary, questions answered/remaining, investigation timestamps.
Phase 5: docs/reasoning-contract-backlog.md documenting all mocked
fields (60+ rows across 7 categories) with feature/UI need/mock/desired
output/stage/notes columns.
Also: wired onRestart through ReasoningWorkspace → ScenarioForm, fixed
getErrorType scope issues, removed broken window.__restartInvestigation.