B — WorkflowBar renders F1..F8 as colored ring-dots (no phase-name text):
green=done, amber=running (subtle pulse), red=error, gray=pending; green
connectors lead the active dot, each dot carries data-state. Lightweight
error signal: sessionStore gains `phaseError`, set when an info event has
level=error during the active phase, cleared on the next ui_request.
C — denser single-line session rows (inline status dot + name, py-1), a
3-level type hierarchy (L1 SESSIONS / L2 section+group headers / L3 names),
and the "No group" label removed (ungrouped render after the last group,
guarded so the empty-state still teaches when there are zero groups).
Live-verified with Playwright (all four dot states, sidebar hierarchy, and
E's deferred activity-panel check). Frontend 93/93, tsc -b clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- CentralStatus: replace the red pulsing dot at the start of the "working" line
with the rotating WorkingSpinner, now a button that opens the model-activity
panel (onOpenActivity). WorkingSpinner is extracted to its own module (was
local to AppShell).
- ModelActivityPanel: show the last 5 lines of the model-stream tail (refreshing
as the stream grows) with an expand toggle to the full stream, replacing the
unbounded full transcript.
- AppShell: drop the separate spinner button (the inline icon is now the single
trigger) and the local WorkingSpinner def.
- Remove the now-orphaned Transcript.tsx (its only consumer was the panel).
TDD: CentralStatus + ModelActivityPanel tests RED->GREEN; frontend suite 87/87;
tsc clean. Live visual verification pending (to do with the B/C frontend pass).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
While the model works (active session, no pending widget), CentralStatus shows
a Claude-Code-style live status: a pulsing dot, elapsed seconds (ticking), and a
short tail of the model's current output — so the centre no longer looks stuck
during the long F1 loop. Verbose stream stays in the left panel. No tokens yet
(would need the SessionBridge to forward Pi usage).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- SessionMenu: anglicize all Italian labels (Vista divisa → Split view, etc.)
- RenameDialog: add empty-name guard + change title to "Rename session"
- DeleteConfirmDialog: translate title and description to English
- SessionActions.test: add 2 new tests (empty name guard, cancel on DeleteConfirmDialog)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Remove the microphone icon from the composer footer
- Left: workspace selector in its place
- Right: model + thinking-level selectors (persist via PUT /settings) next to
the context-usage gauge
- Delete the Settings dialog (form + button); only "New session" remains
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Center ThothII logo + tagline; break "Human In The Loop" onto a second line
- Rename "New question" → "New session"; the button now clears the screen and
focuses the sticky bottom composer instead of opening a dialog
- Composer is always rendered and pinned at the bottom; typing the first
message there creates the session (no modal)
- Add inline stop control (square + inner circle) that interrupts and saves
the session via /close
- Always-present send affordance (CornerDownLeft ↵) on the right of the box
- Status footer under the box: mic (inert), model name, thinking level, and a
context-usage gauge (placeholder)
- Brand-tinted spinner beside the logo while the harness/backend holds the
ball; hidden once a widget needs human input
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The interface is now fully English regardless of the chat language (session
titles stay in whatever language the user typed). Changed the right-rail
subtitle to 'Datamart Builder with Human In The Loop'. Translated all chrome:
new-question/settings dialogs, workflow phase strip (F1-F8), session rail,
steer input, widgets (select/multiselect/freetext/fallback/reserved controls)
and viewers (SQL, results, schema linking). Test matchers updated in lockstep.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adopt the portal's design language so the app embeds seamlessly into its
header/sidebar chrome later:
- Token layer rewritten as raw OKLCH triplets (the previous oklch()-wrapped
vars produced invalid colors; the UI was effectively unstyled). Values mirror
GSD: Manrope + Fraunces fonts, #cb333b red brand, warm off-white surfaces,
pill buttons, brand focus rings. Dark tokens follow .dark or the portal's
[data-bs-theme=dark].
- Layout: no left sidebar, no header (the portal supplies them). Conversation
column flush-left with a slim F1-F8 phase strip; session rail moved to the
RIGHT, mirroring the portal's left sidebar (red section label, red-tint active
item). Editorial empty state.
- Transcript component now actually renders the streamed assistant turns (the
store accumulated them but nothing displayed them). Toaster mounted for errors
(matchMedia polyfill added to the jsdom test setup).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Removes workspace/model/provider/thinking fields. Dialog now posts only { question } to createSession and calls onCreated on success.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- sessionStore.applyEvent: on ui_request set currentPhase normalized from the
descriptor's phase to its short id (e.g. "F4_schema_linking" -> "F4"), so
WorkflowBar actually highlights the active phase; falls back to the existing
phase when the descriptor has none. setPhase kept for resume/getSession.
- Add pushToast store action; WidgetHost wraps postResponse in try/catch,
pushes an error toast and keeps the widget pending on failure (clearPending
only on success) so the user can retry.
- Tests: store currentPhase normalization + no-phase passthrough + pushToast;
new WorkflowBar.test.tsx asserting the matching phase is highlighted.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>