FakeEventSource.addEventListener was a no-op, so emit() only drove onmessage.
Production relies on addEventListener for the backend's NAMED events
(event: ui_request), so the unit tests could pass while prod silently broke.
- fakeEventSource: store named handlers in a Map<string,Set>; add emitNamed()
that dispatches to them; keep emit() for the unnamed/default onmessage path
- useSessionStream.test: ui_request now driven via emitNamed (production path);
add a separate test for the unnamed text_delta path via plain emit
- f1-loop.test: widget emission switched to emitNamed("ui_request", ...)
- verified: tests FAIL if addEventListener wiring is removed from
useSessionStream (then restored)
- cleanup: fake-pi.mjs drops unused execFileSync import, uses static spawnSync
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add NewSessionDialog.test.tsx covering §9 graceful degradation:
empty models -> free-text input; non-empty models -> dropdown; plus a
createSession body-keys assertion
- Normalize model entries to {value,label} so object-shaped models
({provider,id}) render correctly in the dropdown (was assuming strings)
- NavSessions: invalidate the ["sessions"] query after a successful
resumeSession so the list/status refreshes immediately
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- NavSessions: left nav listing sessions via listSessions (TanStack Query),
clicking resumes via resumeSession and sets active; active item highlighted
- NewSessionDialog: ShadCn dialog with question textarea, workspace native
select (from listWorkspaces), graceful model field (dropdown when models
list is non-empty, free-text input when empty per §9 degradation),
optional thinking/provider fields; try/catch surfaces errors inline
- SteerInput: text input + button POSTs to postSteer, clears on send,
supports Enter key; only shown when a session is active
- WorkflowBar: renders 8 phases (F1..F8) with data-active highlighting
driven by useSessionStore.currentPhase (new store field + setPhase action)
- AppShell: wires all four components; right artifact sidebar now collapsible
via a toggle button (useState sidebarOpen); replaces old "Nuova domanda"
button with NewSessionDialog trigger
- f1-loop.test: updated to drive through the new dialog flow (open → fill
question → submit → wait for SSE → respond)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>