mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-07 17:09:13 -10:00
perf(tui): refresh status chrome once a second while a decision prompt waits on you
Refs #6728 (CW-6993).
Measured on macOS against a local mock provider. A session sitting on an
approval prompt used 3.1-3.2% CPU with the installed 0.10.2 release build
(91dbd4f785), against 0.41% on the launch screen and 0.35% idle after a
finished turn. With NO_ANIMATIONS=1 the same approval wait used 0.53%, so
the extra cost was motion. A `sample` of the debug build put the main
thread's active time in draw_app_frame_inner: ApprovalView and
DecisionBand re-planning a full frame on every status tick.
Cause: while a turn waits on approval, `is_loading` and the pending tool
card keep should_tick_status_animation true, so the 5 Hz braille status
clock (UI_STATUS_ANIMATION_MS, 200 ms) redraws the whole frame. Ambient
ocean motion already stops whenever a view is on the stack
(decorative_shell_motion_enabled), so the status clock was the only driver.
Behind a prompt waiting on the person the only thing that needs to stay
current is the second-resolution elapsed label ("running (19s)").
Fix: status_animation_interval_ms returns 1,000 ms while an Approval,
Elevation or UserInput prompt is on top. Low-motion still wins with its own
2.4 s cadence. Input, engine events and sub-agent progress still set
needs_redraw directly, so they are not slowed.
Evidence (same tree, my change reverted vs applied, debug builds, 60 s
idle on an approval prompt, two runs each, CPU summed over codewhale and
its tmux host): before 14.68% / 14.73%, after 3.91% / 3.50%. tmux pane
captures 2 s apart still show the elapsed label advancing (19s -> 21s).
Artifacts: CW/artifacts/cw6993-idle-20261018 (measure.sh, results.txt,
samples, screens).
Tests: scripts/dev-test.sh tui motion 56 passed; cadence 13 passed;
status_animation 5 passed; approval 405 passed. clippy -p codewhale-tui
--all-targets --locked with CI flags: clean. cargo fmt --check clean.
sync-changelog --check up to date.
Not addressed: the card for a command waiting on approval still says
"running (Ns)" with a spinner although nothing has started. That label is
a UX decision, left for the founder. Not measured on FreeBSD (the reporter's
platform) or in a release build of this tree.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NBKbhx19BRbZtvWK8rVKjz
This commit is contained in:
1 parent
9a34d80a83
commit
cebea8cd49
4 files changed
+12
No files matched your search
@@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
failure mark.
|
||||
- The keybinding docs now say what Alt-V opens with nothing selected, and
|
||||
that clicking a card keeps Alt-V on it while newer cards arrive.
|
||||
- The TUI uses less CPU while it waits on you. With an approval, elevation
|
||||
or question prompt open, the status spinner and elapsed-time labels behind
|
||||
it refresh once a second instead of five times a second.
|
||||
- On Windows, Codewhale processes that start at the same moment no longer
|
||||
lose the built-in plugins. The rename that publishes the built-in plugin
|
||||
snapshot now retries a brief sharing or access refusal, as the other atomic
|
||||
|
||||
@@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
failure mark.
|
||||
- The keybinding docs now say what Alt-V opens with nothing selected, and
|
||||
that clicking a card keeps Alt-V on it while newer cards arrive.
|
||||
- The TUI uses less CPU while it waits on you. With an approval, elevation
|
||||
or question prompt open, the status spinner and elapsed-time labels behind
|
||||
it refresh once a second instead of five times a second.
|
||||
- On Windows, Codewhale processes that start at the same moment no longer
|
||||
lose the built-in plugins. The rename that publishes the built-in plugin
|
||||
snapshot now retries a brief sharing or access refusal, as the other atomic
|
||||
|
||||
@@ -213,6 +213,7 @@ const TOOL_HANG_WATCHDOG_TIMEOUT: Duration = Duration::from_secs(600);
|
||||
// the per-tool spinner pulse — keep this fast enough that the whale-spout
|
||||
// braille pattern reads as continuous motion instead of teleport-frames.
|
||||
const UI_STATUS_ANIMATION_MS: u64 = crate::tui::spinner::BRAILLE_SPINNER_FRAME_MS;
|
||||
const UI_DECISION_PROMPT_STATUS_ANIMATION_MS: u64 = 1_000;
|
||||
/// Ambient fish, the idle-mark caustic, and the completion wake use a modest
|
||||
/// ~12.5fps clock by default. On measured high-Hz displays the adaptive probe
|
||||
/// may raise this (still bounded); low_motion always freezes the cadence.
|
||||
|
||||
@@ -158,6 +158,11 @@ pub(crate) fn rail_min_chat_width(idle_empty: bool) -> u16 {
|
||||
pub(crate) fn status_animation_interval_ms(app: &App) -> u64 {
|
||||
if app.effective_low_motion_for_status() {
|
||||
crate::tui::display_refresh::adaptive_animation_interval_ms(true)
|
||||
} else if matches!(
|
||||
app.view_stack.top_kind(),
|
||||
Some(ModalKind::Approval | ModalKind::Elevation | ModalKind::UserInput)
|
||||
) {
|
||||
UI_DECISION_PROMPT_STATUS_ANIMATION_MS
|
||||
} else {
|
||||
// Keep the braille marker on its fixed 5 Hz table for width stability;
|
||||
// only atmosphere uses the measured display cadence.
|
||||
|
||||
Reference in new issue
Block a user