Skip to content

fix(tui): show "Compacting" status during compaction instead of Idle#191

Merged
yishuiliunian merged 2 commits into
mainfrom
fix/compact-status-indicator
Jun 3, 2026
Merged

fix(tui): show "Compacting" status during compaction instead of Idle#191
yishuiliunian merged 2 commits into
mainfrom
fix/compact-status-indicator

Conversation

@yishuiliunian
Copy link
Copy Markdown
Contributor

Summary

  • Compaction (/compact, auto-compaction, resume-rehydrate) showed ● Idle with a frozen spinner instead of an active indicator.
  • Completes fix(runtime): unfreeze TUI after /compact and resume; observability sweep #190's design (compact_banner is the sole compacting signal) by having the TUI status line actually consume it.
  • Presentation-layer only — no AgentStatus mutation, no protocol change.

Root cause

#190 made AgentStatus backend-only and removed view-state's status mutation. Manual /compact is handled as a control command in the idle phase, so status stays WaitingForInput; the status decision tree had no branch for compact_banner, falling through to Idle. The 750ms activity grace also let the spinner freeze mid-compaction.

Changes

  • views/unified_status_label.rs (new): extracted the status-tier decision into a pure pick_label(ActivityInputs); added a Compacting tier (after Thinking, before Streaming). 9 inline unit tests cover every tier + priority ordering + spinner animation.
  • views/unified_status.rs: status_icon_and_label now delegates to pick_label with compacting: conv.compact_banner.is_some(); is_agent_active gains || conv.compact_banner.is_some() so the spinner animates for the whole compaction.
  • views/mod.rs: register the new module.

Test plan

  • bazel test //crates/loopal-tui:loopal-tui-unit-test (new tier/priority/animation tests)
  • bazel test //crates/loopal-tui:loopal-tui_test (existing banner-render suite, no regression)
  • bazel build //crates/loopal-tui:loopal-tui --config=clippy (zero warnings)
  • CI passes

#190 made AgentStatus backend-only and declared compact_banner the sole
signal for compacting, but the unified status line never consumed it.
Manual /compact runs as a control command in the idle phase, so status
stays WaitingForInput and the decision tree fell through to Idle with a
frozen spinner — covering auto-compaction and resume-rehydrate too.

Extract the status-label decision into a pure pick_label() and add a
Compacting tier (after Thinking, before Streaming). Feed it
compact_banner.is_some(), and add the same flag to is_agent_active so the
spinner animates for the whole compaction rather than freezing after the
750ms activity grace.

Presentation-layer only: no AgentStatus mutation, no protocol change, so
it does not reintroduce the #189/#190 turn-lifecycle desync risk.
rustfmt expands single-line `ActivityInputs { field: x, ..base() }` to
multi-line; apply the canonical formatting.
@yishuiliunian yishuiliunian merged commit d15052a into main Jun 3, 2026
4 checks passed
@yishuiliunian yishuiliunian deleted the fix/compact-status-indicator branch June 3, 2026 02:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant