Box the Notification variant to satisfy clippy's large_enum_variant
lint, fix paren mismatches from the boxing pass, and update test
helpers to unwrap AcpUpdate before inspecting the notification.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The event pump now handles AcpUpdate::TurnDone markers that arrive
in the same FIFO as notifications. It fires the done oneshot only
after persisting every preceding notification, so finish_queued_acp_turn
can no longer race ahead of the transcript.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The prompt response callback now sends an AcpUpdate::TurnDone marker
through the same unbounded channel as notifications instead of
signaling the done oneshot directly. Since notifications and the
prompt response both run in the ACP dispatch loop in wire order,
TurnDone lands after every notification chunk for the turn.
The event pump (next commit) will fire the done oneshot only after
persisting all preceding notifications, closing the race where
finish_queued_acp_turn ran before the transcript was complete.
Closes#259
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous fix (e3556bd) added `flex: 1 1 0` to `.st-tool-arg` in
`structured.css`, but `styles.css` has a duplicate copy of the same
rules that was left stale. Because both load, the unfixed copy in
`styles.css` can override the fix and re-enable horizontal scroll.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Same root cause as the tool-group-title fix — .st-tool-arg
defaulted to flex: 0 1 auto, so long commands pushed the row
past the container. Adding flex: 1 1 0 lets the ellipsis
truncation work.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prompts sent while a turn is active are queued on the daemon instead of
in the browser's React state. The queue is persisted in the session
sidecar and drained as the next turn when the current one completes.
Fixes the bug where queued messages were delivered to the wrong session
when switching focus in the UI: the client-side queue captured the new
sessionId in its drain closure.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After a graceful daemon restart, recovered structured sessions now
receive a synthetic continue prompt so the agent resumes without
manual intervention. The User row carries `"maestro": {"type":
"restart_continue"}` metadata for future UI differentiation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Structured sessions spawned with auto_approve lost the flag on daemon
restart because it lived only in the in-memory SessionRecord. Add it to
the Session struct (sidecar JSON) so recovery reads it back instead of
hardcoding false.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tool rows interleaved with agent text now produce separate
collapsed groups instead of one per turn. The timeline reads
text → group → text → group, matching chronological order.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1b2e5f5 changed force kill to remove dirty worktrees but left the
test asserting the old keep-on-disk behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Agent text and thought rows stay outside the collapsed tool group as
standalone transcript items instead of being absorbed into it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The React port replaced CSS class names with Tailwind utilities, breaking
three visual contracts:
- SessionCard used inline bg-* classes instead of .is-active/.is-open/
.is-previewing that the styles.css cascade targets.
- PaneTitle used className "at-title" instead of "attach-title", so font,
overflow, and child layout rules never applied.
- MultiView's Pane never applied .is-focused or .is-preview, so every
pane matched :not(.is-focused) and was dimmed to 0.45 opacity.
Closes#256
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The visibility recovery only reconnected the catalog and daemon-link
sockets. Per-pane attach and structured WebSockets relied on backoff
timers that Android suspends alongside the sockets, leaving the
terminal disconnected after backgrounding.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously --force left the worktree on disk so the operator could
inspect it. Now it removes the worktree unconditionally — the
confirmation prompt already shows the breakdown, so the decision
happens before the delete, not after.
Natural exit still leaves dirty worktrees on disk (no operator
confirmation in that path).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The onConfirm handler in Sidebar resolves (not rejects) when the daemon
refuses an unforced kill — it mutates state to switch to force mode and
returns. That left `pending` stuck at true in the KillDialog, so the
"Force kill" button rendered disabled.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Post-React-migration regressions: spawn submit button moved to modal
footer, sidebar footer restored (help/theme/palette/status/spawn),
session card stripped of redundant Tailwind, action buttons use proper
leaf-act/leaf-actions CSS structure for hover-only visibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The collapsed tool group now reads "N tool calls · Label 'arg'" so the
operator sees the current command at a glance. While a turn is active,
the most recent agent text stays outside the group as visible narration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the 12.7k-line vanilla TypeScript SPA with React + Zustand +
Tailwind. 16 issues across milestone 48.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mark_session_dead_with_worktree_settlement cloned the session under the
lock, dropped it, did async work, then wrote the stale clone to the
sidecar. A haiku rename (or any other metadata update) that landed
between the clone and the write was silently overwritten, so the sidecar
reverted to name_source: Generated and the next daemon recovery
re-triggered autoname.
Re-read record.session under the lock at write time so the sidecar
always reflects the latest state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the deleted kit.ts + kit.css with DesignKit.tsx, gated behind
import.meta.env.DEV and loaded on ?kit. Shows the full tailwind.config.ts
token mapping (colours across all 6 palettes, typography, spacing,
radii, z-index) plus buttons, ActivityRail states, SessionCard states,
and terminal chrome, all switchable live through ThemeContext.
Closes#254
Deletes the vanilla shell and mounts App.tsx on #root. main.ts and the
23 views it drove are gone; App.tsx composes the ported components —
sidebar, multi-view, command bar, spawn modal, help and restart
overlays, daemon link, drawer — around the catalog and layout stores.
The pure parts of four deleted modules moved next to the components
that still use them: the spawn-form model and spawnSimilar into
components/spawn, the transcript's markdown/format helpers and the diff
into components/structured, the help overlay's grouping into
components/dialogs. Document-level event names now live in uiEvents.ts.
Deduplicated two pairs the migration left side by side: the sidebar
uses dialogs/KillDialog and common/ContextMenu. It also listens for the
command bar's kill/rename events, which nothing had picked up since
catalog.ts went away.
styles.css stays as the token and base layer, with `#app` renamed to
`#root` and the pane-body rules re-keyed off the classes the React
panes actually carry.
Closes#253