A host reboot kills the tmux server, so `SessionManager::recover` iterated an
empty list and every session vanished from the API while its sidecar sat
untouched on disk. A second recovery pass now reads the sidecars tmux had
nothing to adopt and registers each as `SessionStatus::Dormant` — a record of
what was running, with no pane and no PTY bridge behind it.
`SessionStatus` deserializes leniently now, like `ActivityState`: an unknown
spelling reads as `Dead` rather than failing the whole `Session`.
Refs #162
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The TUI has always raised `KillConfirm` before `x` kills anything; the web
sent `DELETE /api/sessions/:id` on the first press and only prompted when the
daemon refused. The command bar puts both behind the same three keystrokes,
so the difference now reads as a bug (#160).
The web follows the TUI: a kill is destructive and unattended agents live in
these sessions. `killDialog.ts` grows a confirmation that shares the force
prompt's shell, names the blockers the card already knows about, and keeps the
focus on Cancel. The guarded refusal still opens its own dialog behind it.
The name field starts empty and the reroll is gone; the worktree branch keeps
a default by borrowing one handle from /api/names. A card whose name the
daemon generated renders dimmed until a first prompt settles it.
Refs #131
Replaces the inline activity dot with a coloured bar positioned inside
each row's own indent gutter, per the updated docs/SIDEBAR.md contract.
Active breathes, awaiting-input blinks, error flashes; idle stays
solid. prefers-reduced-motion leaves every state static.
The kill button now sends the unforced DELETE immediately instead of
asking first. Only the daemon's guard refusal raises a prompt, and it is
a real dialog rather than confirm(), so it can offer the override the
daemon already implements.
The API error envelope is decoded into ApiRequestError, keeping the code
and the unsaved-work breakdown so the dialog names what is in the way.
The command fragment named the full command line, so a session spawned
with `claude --dangerously-skip-permissions` spent the whole line on a
flag. Cards now name the program only — its icon in the web client, its
bare name in the TUI — and keep the full command line in the tooltip.
Adds `maestro_protocol::display::command_program`, the Rust counterpart
of the web's `splitCommand`.
Line 2 of a session card spelled out its blocked work ("1 uncommitted
file") and its command ("claude"). Both now render as marks: the
breakdown as diff notation, and the command's leading program as its
tool's icon in the web client.
The probe carries the line delta of the tracked changes — staged and
unstaged together, against HEAD — so `git add` never makes the counter
drop. Untracked files stay a file count; counting their lines means
reading every one off disk. A tracked change with no line delta falls
back to `~N` rather than claiming `+0 -0`.
The TUI keeps its command as text: a terminal cannot be assumed to have
a font carrying tool glyphs.