feat(shell): yellow active session, growing composer, phase title, refined activity log, arrow panel toggle

Fix six GUI defects, verified live against the real stack:

- NavSessions: mark the in-progress (active) session in yellow (warning
  token) — both its status dot and its row background.
- SteerInput: the composer is now an auto-growing textarea that wraps and
  grows vertically (caps at 160px, then scrolls); Enter sends, Shift+Enter
  inserts a newline.
- WorkflowBar: show a synthetic title of the current phase under the 8 dots
  from static EN/IT strings (no LLM); English is displayed to match the chrome.
- CentralStatus: reformat the 5-line system-message tail as a structured,
  monospace list with per-line markers and an emphasized last line.
- AppShell + CentralStatus: move the left Model-activity panel toggle off the
  working spinner (now a pure status indicator) onto a dedicated arrow button
  (→ opens, ← closes).
- gate: rename the phase-confirm button "Conferma e prosegui" → "Salva e
  procedi" (builders.js + its L1 test).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 14:32:01 +02:00
co-authored by Claude Opus 4.8
parent 1f9818c50f
commit d6b4729ddf
8 changed files with 132 additions and 59 deletions
+29 -1
View File
@@ -13,6 +13,21 @@ const PHASES = [
{ id: "F8", name: "Results" },
];
// Synthetic, human-readable title for the current phase, shown under the dots.
// Static bilingual strings (no LLM): PHASE_LANG picks which set is displayed.
// The rest of the app chrome is English, so the label follows suit.
const PHASE_LANG: "en" | "it" = "en";
const PHASE_TITLES: Record<string, { en: string; it: string }> = {
F1: { en: "Clarifying the question", it: "Chiarimento della domanda" },
F2: { en: "Linking the schema", it: "Collegamento dello schema" },
F3: { en: "Exploring the data", it: "Esplorazione dei dati" },
F4: { en: "Planning the SQL", it: "Pianificazione della query" },
F5: { en: "Generating the SQL", it: "Generazione della query" },
F6: { en: "Validating the results", it: "Validazione dei risultati" },
F7: { en: "Reviewing with you", it: "Revisione con te" },
F8: { en: "Presenting results", it: "Presentazione dei risultati" },
};
type DotState = "done" | "running" | "error" | "pending";
// Each state is a tinted chip; red is reserved strictly for error (the GSD theme's
@@ -39,9 +54,13 @@ export function WorkflowBar({
const currentPhase = useSessionStore((s) => s.currentPhase);
const phaseError = useSessionStore((s) => s.phaseError);
const activeIdx = PHASES.findIndex((p) => p.id === currentPhase);
// On a finalized session all phases are done — surface the closing phase's title.
const titleId = finalized ? "F8" : currentPhase;
const phaseTitle = titleId ? PHASE_TITLES[titleId]?.[PHASE_LANG] : null;
return (
<div className="flex items-center justify-center gap-3">
<div className="flex flex-col items-center gap-1">
<div className="flex items-center justify-center gap-3">
<nav
aria-label="Workflow progress"
className="flex items-center gap-0 overflow-x-auto py-0.5"
@@ -99,6 +118,15 @@ export function WorkflowBar({
})}
</nav>
<ElapsedTimer key={resetKey ?? "none"} running={running} />
</div>
{phaseTitle && (
<span
data-testid="phase-title"
className="text-[0.72rem] font-medium uppercase tracking-[0.12em] text-muted-foreground"
>
{phaseTitle}
</span>
)}
</div>
);
}