feat(dashboard): highlight proposals pane + bell on new proposal
test / unit (pull_request) Successful in 17s
test / integration (pull_request) Successful in 1m8s

When a fresh proposal lands in the supervise queue, the
dashboard:

  1. Rings the terminal bell via `curses.beep()` so tmux's
     `monitor-bell` (or the terminal's own bell-on-activity)
     surfaces a notice in the dashboard pane even when the
     operator is focused on claude in the right pane.
  2. Bolds + green-attrs the `proposals:` pane label and
     suffixes it with `(new!)` so a glance at the dashboard
     screen catches the alert at a glance.

The highlight tracks the existing per-row green-highlight
window (`_NEW_PROPOSAL_HIGHLIGHT_SEC`). The bell only fires for
NEWLY arrived proposals after the first tick — pre-existing
queue entries on dashboard startup don't ring.
This commit is contained in:
2026-05-26 15:55:47 -04:00
parent 33f1b40479
commit 9ac05c1a63
+28 -1
View File
@@ -1352,6 +1352,10 @@ def _main_loop(stdscr: "curses._CursesWindow") -> None:
if manifest_cache[0] is None:
manifest_cache[0] = Manifest.resolve(USER_CWD)
return manifest_cache[0]
# First-tick guard: a brand-new dashboard finds any
# pre-existing queue entries on its first poll; those
# shouldn't ring the bell as if they just arrived.
saw_first_tick = False
while True:
pending = discover_pending()
if selected >= len(pending):
@@ -1363,10 +1367,21 @@ def _main_loop(stdscr: "curses._CursesWindow") -> None:
now = time.monotonic()
live_ids = {qp.proposal.id for qp in pending}
# Detect proposals we've never seen before — used to ring
# the terminal bell (so tmux's monitor-bell or the
# terminal's own bell-on-activity surface a notice when
# the operator isn't looking at the dashboard pane).
newly_arrived = live_ids - first_seen.keys()
if saw_first_tick and newly_arrived:
try:
curses.beep()
except curses.error:
pass
for proposal_id in live_ids:
first_seen.setdefault(proposal_id, now)
for stale_id in list(first_seen.keys() - live_ids):
del first_seen[stale_id]
saw_first_tick = True
_render(
stdscr, pending, selected, status_line,
@@ -1541,10 +1556,22 @@ def _render(
# ----- proposals pane (top) -----
row = 2
# When any proposal is in the recent-arrival window (the
# individual rows are green-highlighted by the existing logic),
# also highlight the pane label so the alert is visible at a
# glance even when the operator is focused elsewhere.
proposals_have_recent = any(
_is_recent(qp.proposal.id, first_seen, now) for qp in pending
)
proposals_label = "proposals:"
if proposals_have_recent:
proposals_label += " (new!)"
if proposals_focused:
proposals_label += " (focused)"
stdscr.addnstr(row, 0, proposals_label, w - 1, curses.A_DIM)
label_attr = curses.A_DIM
if proposals_have_recent:
label_attr = curses.A_BOLD | green_attr
stdscr.addnstr(row, 0, proposals_label, w - 1, label_attr)
row += 1
if not pending:
stdscr.addnstr(