Problem
frontend/src/components/demo/DemoPhasePanel.tsx:46 renders the phase accordion as a fully-controlled shadcn <Accordion value={value}> without a paired onValueChange handler. During a live run value follows runningPhase, which auto-advances the open panel as each phase starts — works as intended.
After completion, runningPhase becomes null and value falls back to phases[0]?.id (i.e., 'data'). User clicks on Modeling / Decision / Verify / Agent / Cleanup headers register focus, but Radix immediately snaps the open panel back to 'data' because there is no onValueChange to update the external state. The visitor cannot expand any other phase to inspect the per-step cards after the run finishes.
Repro
make demo-clean (or seed showcase_rich manually).
- Open
/showcase, pick showcase_rich, click Start.
- Wait for
pipeline_complete (banner turns green).
- Click the Modeling accordion header → focus moves but the panel does not expand. Same for every non-Data phase.
Workaround
Reload the page. Once value is recomputed from runningPhase = null on a fresh mount with no run state, the user-clicked phase opens. But on a green-banner state you've already lost the per-step detail.
Fix sketch (~15 LOC)
Add a local useState<string | null>(null) for the user's manual open value. Pass value = runningPhase ?? userOpen ?? phases[0]?.id and wire onValueChange={setUserOpen}. Reset userOpen to null when a new run starts (e.g., on the step_start of step_index === 1).
Notes
Problem
frontend/src/components/demo/DemoPhasePanel.tsx:46renders the phase accordion as a fully-controlled shadcn<Accordion value={value}>without a pairedonValueChangehandler. During a live runvaluefollowsrunningPhase, which auto-advances the open panel as each phase starts — works as intended.After completion,
runningPhasebecomesnullandvaluefalls back tophases[0]?.id(i.e.,'data'). User clicks on Modeling / Decision / Verify / Agent / Cleanup headers register focus, but Radix immediately snaps the open panel back to'data'because there is noonValueChangeto update the external state. The visitor cannot expand any other phase to inspect the per-step cards after the run finishes.Repro
make demo-clean(or seedshowcase_richmanually)./showcase, pickshowcase_rich, click Start.pipeline_complete(banner turns green).Workaround
Reload the page. Once
valueis recomputed fromrunningPhase = nullon a fresh mount with no run state, the user-clicked phase opens. But on a green-banner state you've already lost the per-step detail.Fix sketch (~15 LOC)
Add a local
useState<string | null>(null)for the user's manual open value. Passvalue = runningPhase ?? userOpen ?? phases[0]?.idand wireonValueChange={setUserOpen}. ResetuserOpentonullwhen a new run starts (e.g., on thestep_startofstep_index === 1).Notes
.handoffs/2026-05-26-...).agent + ops + final polish) is a natural carrier if this isn't picked up sooner.