- 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
- FocusedQuestionBody derives thread-local contribution subset using
targetNodeId || originatingTargetNodeId matching
- hasCompletedContext, latest completed contrib, and all effective
presentation fallbacks use scoped collection only
- scenario-wide focusedContributions history preserved in memory
- Fresh Question B no longer bleeds Question A's content across
every presentation surface (Previously answered, What this tells us,
Still unclear, Questions this raises, Assumptions, Connections)
- Reopening or revisiting Question A still uses its own history
- Targeted regression: 3 new Vitest cases pass
- Handoff docs updated with v0.52 correction record
Move the milestone invitation from after Clarified Questions to occupy
the same spatial position as Open Questions — between Current Understanding
and Questions we have clarified. Uses ternary: openUnknowns > 0 ? OpenQuestionsUI : milestoneAllowed ? MilestoneInvitation : null, followed by ClarifiedQuestionsUI unconditionally. No duplication of clarified cards or Re-open controls.
Repair LOCATION-A defect where processing feedback rendered near the
completed narrative instead of inside the active follow-up block.
Changes:
- components/reasoning-workspace.jsx: three targeted edits using a single
spinner component with conditional rendering; hasActiveFollowUp routes
ownership to the correct container
- tests/open-questions-vs-assumptions.test.jsx: regression test confirming
exactly one indicator, DOM child of follow-up-block, ownership separation
Accepted criteria met:
✅ Exactly one processing indicator during follow-up processing
✅ Indicator is a DOM child of follow-up-block
✅ Top-level indicator suppressed when follow-up active
✅ Initial answer flow preserved (top-level when no follow-up)
✅ Successful follow-up promotion intact
✅ All existing context retained
✅ No new state/lifecycle changes/error redesign
Two presentation fixes (no reasoning-engine changes):
A. Follow-up answer continuity — selectFollowUpQuestion clears focused.answer,
which previously caused the completed-narrative framing ('Previously answered'
and 'Your response') to disappear mid-investigation. The guard now treats
a non-null result as sufficient evidence of a completed-context state, so the
user's verbatim answer and derived findings remain visible while a follow-up is
being formulated.
B. Prior-contributions chronology — display order in 'Previous learning' panels
has been reversed at the presentation boundary (newest → oldest). This means
users see the most recently learned evidence first, without modifying data-order
anywhere else. Applies to both PriorContributionsSummary and
SecondaryPreviousLearning.
When a reopened completed turn is displayed, distinguish it from an active question:
- 'PREVIOUSLY ANSWERED' + 'YOUR RESPONSE' headings for completed turns (hasAnswer=true)
- Bare 'QUESTION' heading preserved for active follow-ups (answer=null)
- Verbatim user answer rendered under its own heading — never conflated with Engine-derived findings
- Causal narrative: Question → Your response → What this tells us
Gate results:
- 102 tests passed (78 existing + 24 new v0.49 provenance narrative tests)
- Clean production build
- Live verification on localhost:3000 confirmed correct rendering
ThreadContributionsBadge, PriorContributionsSummary, and
SecondaryPreviousLearning all filtered contributions via
c.targetNodeId === nodeId. Multi-turn follow-up Contributions carry a
different immediate targetNodeId while the canonical origin remains on
Findings (originatingTargetNodeId).
Repaired: all contribution filters now match on EITHER
c.targetNodeId === nodeId || c.originatingTargetNodeId === nodeId.
handleDeconstructSubmit carries originatingTargetNodeId from
focusedPresentationItemId as provenance for cold-return recovery.
- ThreadContributionsBadge (rendered per-node on OpenQuestionsPanel
cards and Done-for-now cards) now shows an amber INVESTIGATING
indicator when the node has matching contributions via targetNodeId
identity match.
- UNCLEAR and INVESTIGATING cues coexist independently on the same
card — UNCLEAR is epistemic state, INVESTIGATING is activity cue.
- Deterministic test suite added: focused-investigation-history (11
tests) covering identity matching, zero-contrib edge cases,
multiple-contrib coalescing, done-for-now retention, and uncoupling
from UNCLEAR state.
- All 57 tests pass.
Intentional changes in this checkpoint:
- Deconstruct route: use body.targetNodeId (client identity) over raw.model-invented ID
- ThreadContributionsBadge: compact per-thread contribution indicator with expandable history
- Reopen continuation: resume from accumulated contributions instead of reformulating
- showEvidenceLimit gate: hide evidence-limit card during active investigation paths
- Evidence-limit visibility correction in rendering pipeline
- Section ordering: assumptions and connections after 'Still unclear' in focused result
- Prompt v0.3: preserve user-stated alternatives as separate unknowns; no count inflation
- 3 durable regression tests (target identity, contribution persistence, reopen state)
- evidence-limit card visibility gate test suite
Temporary residue removed:
- test-analysis.mjs (scratch diagnostic)
- 5 diagnostic console.log blocks from reasoning-workspace.jsx
- Enhance Current Understanding prominence with subtle teal/teal border
gradient, stronger heading, larger body text, more internal spacing
- Restore Situation panel as right-hand column in initial reflection view;
uses OriginalSituation when graph exists, scenario text fallback otherwise
- Stacks layout on narrow screens via grid-cols-1/gap-6/lg:grid-cols-3
- Apply teal styling to normal-state CurrentUnderstandingCard and
PlainLanguageCard (was flat gray border with bg-transparent)
- Surface assumption nodes alongside unknowns in Open Questions; add
Unclear / Plausible interpretation tags
- Wire up follow-up question buttons in deconstructed results
The successful focused deconstruct calls onFocusedContribution which
updates parent state, but never persisted the new collection to
sessionStorage. This meant an immediate reload would lose the
contribution.
Fix: add a useEffect in ReasoningWorkspace that watches the
focusedContributions prop for changes and saves via the existing
saveSession mechanism. A ref guard prevents double-save alongside the
existing updateStatus-success effect.
- 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
Add three exclusivity guards that suppress legacy surfaces during the
initial post-Analyse reflection state (postAnalyseStatus === 'success'):
- CurrentInvestigationCard: suppressed because its selectedQuestion
from startCase was leaking into the initial reflection view
- OpenQuestionsPanel: suppressed because it rendered whenever hasGraph
was true, regardless of initial reflection state
- Terminal state cards (EvidenceLimitCard / CompletionCard): suppressed
because they fired on status='success' && !hasSelectedQuestion
Transition out of initial reflection happens when user clicks a proposed
finding, which sets formulationStep='active' and triggers the existing
deactivation useEffect.
No reasoning changes. No startCase changes. No mock changes.