Skip to content

Make the alert action dismiss and open the context, never edit a rule - #707

Draft
nedtwigg wants to merge 2 commits into
alert-defer-default-onfrom
alert-dismiss-simplify
Draft

nedtwigg wants to merge 2 commits into
alert-defer-default-onfrom
alert-dismiss-simplify

Conversation

@nedtwigg

Copy link
Copy Markdown
Member

Stacked on #706.

The pane-header alert button, a in command mode, and the mobile header button used to run a five-way transition table: dismiss, or consume attentionDismissedRing, or toggle the running command's WATCHING rule, or open the context. Now they do one thing: dismiss a ringing Session (setting TODO, as before) and open the terminal context. WATCHING rules are created only in the terminal context ("Watch all <cmd> commands") and removed there or in Settings.

  • attentionDismissedRing, dismissOrToggleAlert, AlertButtonActionResult, toggleSessionAlert, disableSessionAlert deleted; ActivityState is plain AlertState.
  • a and > open the context through a Wall-provided openTerminalContext instead of clicking the bell or faking a contextmenu event.
  • Fixes a false claim in the spec and two comments that the watched-command list was rendered in two places; Settings is the one place a rule for a since-closed Pane can be removed.
  • Spec, shortcuts table, README, and tutorial hints updated; alert.md budget ratcheted 7250 → 7200.

Next PR in the series makes every ring flash the Pane; the one after retires the bell icon.

🤖 Generated with Claude Code

nedtwigg and others added 2 commits September 19, 2026 23:49
The pane-header alert button, `a` in command mode, and the mobile header
button ran a five-way transition table that could silently turn a WATCHING
rule on or off. They now do one thing: dismiss a ringing Session (setting
`todo`, as before) and open the terminal context. WATCHING rules are created
and removed in the terminal context, and removed for a since-closed Pane in
Settings — the only place that can reach one.

`attentionDismissedRing` existed only to stop the click after an
attention-based dismissal from editing a rule, so it is gone from `AlertState`,
the manager entry, `alertStatesEqual`, and the side map that kept it off the
public Activity snapshot; `ActivityState` is now plain `AlertState`. No wire or
persisted type carried it. `dismissOrToggleAlert`, `AlertButtonActionResult`,
`toggleSessionAlert`, and `disableSessionAlert` are deleted with it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ynthetic click

The a and > keys now call one openTerminalContext hook on the keyboard
context instead of clicking the header's bell or dispatching a fake
contextmenu event, so the keyboard layer no longer depends on the header
having a button. onAlertButton was a pass-through to dismissSessionAlert
and is gone; the header calls the store directly, the alert label is one
boolean, DEFAULT_ACTIVITY_STATE aliases DEFAULT_ALERT_STATE, and the
watched-command remove control names what it does.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 20, 2026

Copy link
Copy Markdown

Deploying mouseterm with  Cloudflare Pages  Cloudflare Pages

Latest commit: c9f396f
Status: ✅  Deploy successful!
Preview URL: https://2fadd863.mouseterm.pages.dev
Branch Preview URL: https://alert-dismiss-simplify.mouseterm.pages.dev

View logs

@dormouse-bot dormouse-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feedback on work in progress, not a merge verdict — mark the PR ready when you want the full review.

The collapse to one action reads well, and the PR's claim about the watched-command list checks out: WatchedCommandList is mounted only by SettingsDialog, so the spec line and both comments really were wrong.

One consequence worth weighing. The alert button and a now call dismissSessionAlert unconditionally, so AlertManager.dismissAlert is reached in states the old transition table never routed to it — and clearAllRingsIfActive cancels a pending deferred notification before it reports that nothing was ringing. With deferral now the default from the base PR (#706), a pane whose agent emitted its "done" notification while the TUI is still redrawing is holding that notification behind deferredNotificationTimer with nothing latched. Clicking the alert button there drops it outright: no ring, no TODO, no notification detail, and dismissAlert returns before notify, so nothing re-renders either. The button's own new copy — Alert settings, "Click or right-click for options" — invites exactly that click, while right-click and > open the same context without the loss, so the two routes the spec presents as interchangeable aren't.

It also makes the new rule "Dismissing a Session with nothing ringing changes nothing and notifies no one" false as written; the test of that name dismisses a notification that rang immediately, so the deferred case is uncovered. The inline suggestion gates on hasActiveRing first, which restores the rule literally and leaves attend's eager cancellation alone.

Comment on lines +1083 to +1087
// Dismissing a ring leaves the TODO behind, so the summons is not lost; on a
// Session with nothing ringing there is nothing to do.
if (!this.clearAllRingsIfActive(entry)) return;
entry.todo = true;
this.notify(id);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clearAllRingsIfActive clears the deferral before it answers whether a ring was active, so a dismiss on a quiet Session destroys a notification that was only waiting for the animation to stop. Checking hasActiveRing first makes the no-op path a real no-op.

Suggested change
// Dismissing a ring leaves the TODO behind, so the summons is not lost; on a
// Session with nothing ringing there is nothing to do.
if (!this.clearAllRingsIfActive(entry)) return;
entry.todo = true;
this.notify(id);
// Dismissing a ring leaves the TODO behind, so the summons is not lost. A
// Session with nothing ringing has nothing to dismiss, and must keep any
// notification still deferred behind animation.
if (!this.hasActiveRing(entry)) return;
this.clearAllRingsIfActive(entry);
entry.todo = true;
this.notify(id);

dismissSessionAlert(id);
const rect = button.getBoundingClientRect();
context.open(id, { origin: { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 } });
}, [actions, id, context]);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actions is no longer read in this callback.

Suggested change
}, [actions, id, context]);
}, [id, context]);

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.

2 participants