Defer terminal-notification alerts until animation stops by default - #706
Conversation
Deploying mouseterm with
|
| Latest commit: |
8fe508f
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://fa99eaf9.mouseterm.pages.dev |
| Branch Preview URL: | https://alert-defer-default-on.mouseterm.pages.dev |
dormouse-bot
left a comment
There was a problem hiding this comment.
Feedback on work in progress, not a merge verdict — mark the PR ready when you want the full review.
The flag gates a second behavior, and nothing a user reads mentions it. deferAlertsUntilQuiet also gates withdrawResumedWatchingRing, which docs/specs/alert.md states as "With deferAlertsUntilQuiet, withdraw a WATCHING ring when watched work resumes confirmed BUSY." That is why the two tests here had to switch the flag off — ALERT_RINGING latches when user has no attention (view hidden) and leaves a stale WATCHING ring alone once output has resumed. So the default flip ships ring withdrawal out of the box as well, while the switch's helper text in lib/src/components/SettingsDialog.tsx ("When the animation watcher is fully armed, terminal notifications wait for the pane to become quiet") and the Alarm settings row both describe only the deferral half. A latched claude-finished ring that disappears when the agent starts a new turn is the case a user will actually hit, with nothing to read about it. Either widen that copy or put withdrawal on its own condition.
"Users who saved the setting keep their value" reaches further than the body says. updateAlertSettings normalizes and persists the whole blob, so a user who once changed only speakDelayMs has deferAlertsUntilQuiet: false sitting in dormouse:alert-settings and never picks up the new default — despite never having expressed a preference about deferral. For a change motivated by an experience every agent user has, the set that keeps the old behavior is "anyone who has opened Settings and touched anything", not "anyone who set this switch". Worth deciding whether that is intended, or whether the persisted key should be dropped when it still matches the old default.
The rationale's closing clause reads as attributing indefinite deferral to the switch being off, when the on state is what produces it — scheduleDeferredNotification re-arms at the detector's quiet deadline with no cap. Since that unbounded case is now the shipped default, it is the sentence most worth being unambiguous. Inline suggestion below.
One small thing outside the diff: standalone/src/browser-sidecar-adapter.test.ts builds its canonical fixture as { ...DEFAULT_ALERT_SETTINGS, deferAlertsUntilQuiet: true }, now identical to DEFAULT_ALERT_SETTINGS — so the assertion no longer distinguishes "forwarded the blob it was handed" from "emitted the default". Flipping that override to false restores it.
Coding agents emit their "done" notification while their TUI is still redrawing, so the undeferred ring summoned the user to a pane that was still animating. The switch stays as an escape hatch for the protocols' literal timing, and the AlertManager field now follows DEFAULT_ALERT_SETTINGS so a manager that never receives a settings blob behaves like one that does. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The switch also gates withdrawal of a WATCHING ring when watched work resumes, so the default flip ships that out of the box too, while the helper text under the switch and the Alarm settings row described only the deferral half. Both now name both behaviors, and the settings row points at the section that owns each rule instead of restating one. The rationale leads with deferral being the unbounded state rather than reading as though the off position were, and records why an install that already saved a settings blob keeps the old value: with no version field to key a migration on, dropping a persisted false on read would leave the off position unpersistable. The browser-sidecar adapter's canonical blob differs from DEFAULT_ALERT_SETTINGS again, so the assertion still tells a forwarded blob apart from an emitted default. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
dd35485 to
8fe508f
Compare
First of a stacked series simplifying the alert system.
Coding agents (
claude,codex) emit their "done" notification while their TUI is still redrawing, so an undeferred ring summons you to a pane that is still animating.deferAlertsUntilQuietnow defaults on; the switch stays as an escape hatch for the protocols' literal timing. TheAlertManagerfield followsDEFAULT_ALERT_SETTINGSso a manager that never receives a settings blob behaves like one that does.docs/specs/alert.mdAlarm settings row and the rationale paragraph updated.normalizeAlertSettings.DeferralEnabled→DeferralDisabled(the non-default state is the one worth a snapshot).Installs that have never saved an alert-settings blob pick the new default up. Any install that has changed any alert setting has the whole blob persisted, so it keeps
deferAlertsUntilQuiet: falseuntil the switch is flipped in Settings; the blob has no version field to key a one-shot migration on, and dropping a persistedfalseon read would make the preference unpersistable (decision recorded in the rationale).🤖 Generated with Claude Code