agent ui: show elapsed seconds on status ticks during compaction

During a compaction pass, bare `status` ticks from claude are the only
live signal (no dedicated progress event exists in the headless stream-json).
Previously these rendered as a coalescing `⚙ status` row — uninformative
while waiting for a long compact to finish.

The harness emits `TurnStateChanged { state: Compacting, since_unix }`
immediately before invoking `session.compact()` for both the turn-end and
idle-session manual-compact paths. The frontend already tracks this in
`stateName` / `stateSince` for the state badge (`📦 compacting · Xs`);
now the terminal's `status` tick renderer reads the same two variables so
consecutive ticks show `⚙ compact · Xs…` (elapsed, in-place updating via
the existing coalescer) instead of the unhelpful `⚙ status`.

Result: what used to look like

    ⚙ status
    ⚙ compact · manual · 37k→2k tokens · 40.1s

now looks like

    ⚙ compact · 3s…   (updating in place)
    ⚙ compact · manual · 37k→2k tokens · 40.1s

Auto-compact (triggered by hive-claude's InfiniteSession policy internally,
no TurnState::Compacting set by the harness) continues to show `⚙ status`
as before.

Addresses #2276 (follow-up to status-tick coalescing in #2335).
This commit is contained in:
iris 2026-07-19 15:59:12 +02:00 committed by mara
commit 617eecf94e

View file

@ -2011,12 +2011,17 @@ window.marked = marked;
// Bare `status` ticks (claude's own generic "still working" signal,
// no detail beyond the label) — collapse consecutive ticks into one
// updating row instead of a fresh note each (see `makeCoalescer`
// above). These are the only signal we get during a compaction pass
// (no dedicated "compacting…" event from claude), so without
// collapsing a compaction looked like a wall of identical `⚙ status`
// rows followed by silence.
// above). When the harness state is `compacting` (set by the
// `turn_state_changed` SSE event), show elapsed time via `stateSince`
// — the same source the state badge uses — so the terminal reflects
// compaction progress; otherwise fall back to the generic label.
if (v.subtype === 'status') {
updateStatus(api, '⚙ status');
let label = '⚙ status';
if (stateName === 'compacting') {
const elapsed = Math.round((Date.now() - stateSince) / 1000);
label = '⚙ compact · ' + elapsed + 's…';
}
updateStatus(api, label);
return;
}
// Other system subtypes (context_window_exceeded, etc.) — render a