Conversation
- WATCHING keys on the last command of a list, past transparent wrappers, with script runners keyed as `<runner> <script>`; a bare runner rule still covers every script. - bash reports the whole submitted line when history proves it, and a `bind -x` key (fzf) is no longer a command on bash 4+. - fish 4 / kitty command lines on OSC 133;C are read. - ConEmu OSC 9;<n> subcommands no longer ring. - Panes no longer inherit another terminal's identity variables. - Overflowed Doors surface their rings and TODOs on the "N more" arrows. - A helper promoted mid-command keeps its running command. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Command lines from OSC 633;E and 133;C share one bound/decode/sanitize path that keeps line breaks, so a multi-line command keys on its last command outside unit tests too. - The tokenizer emits grouping parentheses and keeps command substitutions and array assignments whole, replacing a quote-blind regex pass. - Rule lookup lives in one getter used by the terminal context and the tutorial detector; the overflow arrow reserves one measured width. - Smaller cleanups: one OSC 9 subcommand switch, shared decoders and flag specs, one env-strip regex, test helpers, trimmed prose. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- WATCHING, terminal reports and command exits are sources on one ring: every ring sets TODO when it opens, and an await, resumed work or rule removal takes back only the TODO and detail that ring set. - Notification detail follows one richness order, so a bell never replaces an OSC 9 message or an exit code. - A report about a state the user already acknowledged, with no output since, updates the TODO instead of summoning again. - Progress is its own sub-state: updates never take a ring away, command boundaries end abandoned cycles silently, titles name the command. - Deferral behind animation is capped at 30 s; the command-exit minimum runtime is its own constant; hosts apply one chunk's events in order. - WATCHING detail is never persisted, so older builds keep restoring. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Persisted sessions tolerate an unknown notification source (dropping only that detail); the writer strips to the sources strict older builds know, as a frozen allowlist. - The ring keeps one richness helper (also used by deferral, which now keeps the richer report), a watching record, and the receipt it replaced; derived and duplicated flags are gone. - The acknowledged-report rule lives in the completion dispatcher; the withdrawal reason decides whether the detector resets. - One ordered, timestamping event dispatcher serves the VS Code host, the fake adapter, and live replay. - Tests share arm/finish/heartbeat helpers; stale "track" wording fixed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- The renderer reports presence (window focused and visible, with typing, mouse, or wheel input within the inactivity timeout) and focus (the passthrough pane, or a context's source); a Session is engaged when both point at it. VS Code webviews and standalone windows are separate viewers. - A completion while engaged is held, not dropped: acknowledging or leaving drops it, going idle rings it. The walk-away permission prompt now reaches the user. - Only acknowledgement clears a ring. Any keystroke, paste, or drop into a pane clears its TODO (Windows, kitty, and one-key answers included); a click, Door, or tap keeps it. `dor` reveals move focus without acknowledging; browser panes never acknowledge. - The user's own keystroke echo no longer counts as work. - Mobile taps and input acknowledge through the mobile composition. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF
- Entering passthrough no longer acknowledges on its own: pane clicks,
zoom, the dev-server chip, Doors, and keyboard Enter acknowledge at their
handlers, so spawns, splits, promotions, `dor` reveals and a raw frame
taking focus can never clear a ring.
- User input is one `writePty(…, { userInput })`: the host clears the
ring and TODO and opens the echo window before writing (one message per
keystroke in VS Code). Mobile input uses the same helper.
- Rings and held completions share one source-set shape and one
hold-or-deliver path; viewers store only present focus.
- Shared window-focus source, ref-counted engagement reporter, one VS Code
realm teardown, `inactivityTimeout` naming, shared test utilities.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF
- One AlertManager per app, beside the PTYs and the parse site, fed in stream order; windows are viewers (stamped by label) that send commands and render `alert:state`, exactly like VS Code's extension host. - A window reload keeps its rings and TODOs; alert timers no longer run in a throttled webview; awaits survive a Workspace transfer and the per-window transfer snapshot machinery is deleted. - User input rides the PTY write so the sidecar acknowledges before the echo; remote Client writes acknowledge and remote resizes get the resize grace in both hosts; a killed VS Code panel removes its entries. - Exited PTYs stay owned until killed, so clearing their TODO still reaches the window. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF
- One host module (commands, per-realm awaits with synchronous answers on realm end, validation, store binding) and one client serve both hosts over one `alert:command` wire; the fake adapter runs the real host. - One owner PTY stream and one Client-input wrapper feed the manager in both hosts; the resize grace rides the PTY resize and the persisted alert rides the spawn, so no separate resize, seed or remove calls. - Alert entries go when ownership drops (kill, orphan reap), fixing the leak on window close; a `sync` command re-syncs a reconnected viewer. - Rust: the tool-event hold is gone, one "showing" route covers every id-keyed event (fixing an exit before a transfer's mark), await results go to their window, and stamping/serialization are shared. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF
- One delivery scheduler inside the shared alert host (VS Code extension host, standalone sidecar, fake adapter): once per sink per episode, the deadline fixed at the episode's start, rechecked at the deadline. - Speech needs the user not engaged with that pane; push needs every viewer away. A failed gate consumes the delivery. - Realms publish their Sessions' Workspace overrides; the host resolves them against the settings it holds and sends `alert:deliver` to the owning viewer, which speaks or pushes with the pane's label. - Deletes the renderer ring watcher, its receipts, and the Workspace transfer's delivery pause/resume/snapshot machinery. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF
…per command - The shared alert host sends push itself (standalone: the sidecar's Burrow service; VS Code: this window's service or the broker over the peer link), titled by labels each window publishes with its Workspace overrides on a throttle; windows only speak (`alert:speak`), so a suspended window no longer delays the walked-away channel. - A VS Code window in active use counts as presence for push. - A command start ends the "already acknowledged" state, so a command that stays silent until its notification rings again. - One scheduler map and per-sink table; the push-device fence lives with the device list; shared speech test stub; routing and gates stated once. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF
- 3.6.6 is the newest iTerm2 whose escape-code additions Dormouse fully supports (OSC 9;4 progress, color-scheme reporting); Claude Code now reports each turn as a progress cycle, so a turn ending on a pane the user isn't engaged with rings "claude finished". - Color-scheme queries are answered explicitly and classified as terminal reports, never input. - A regression suite replays a recorded Claude Code turn through the real host parse site for all four engagement outcomes. - The delivery scheduler keeps a Session's published policy and label through a respawn and drops it only on removal. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF
- The identity rule advertises the lowest iTerm2 version that unlocks the version-gated behavior Dormouse supports, never one whose additions it would mishandle; the recorded Claude turn is described once, in its test. - One step runner and episode collector serve the engagement and manager tests; the VT extension options live in their own module. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF
- WATCHING keys skip here-document bodies and treat shell reserved words as grammar, so heredocs and loops key on the command they run. - Presence does not lapse while an iframe browser pane holds focus (its input is invisible to the window), so push waits for a real absence. - A partial publication no longer drops a Session's delivery overrides and silently cancels its pending speech or push. - Mobile acknowledges a tap, not a scroll swipe or radial drag; zoom and unzoom always acknowledge. - A viewer's `sync` re-sends only its own Sessions and stores to it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF
Deploying mouseterm with
|
| Latest commit: |
b0d6dd7
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://2cf97dc1.mouseterm.pages.dev |
| Branch Preview URL: | https://alert-improve.mouseterm.pages.dev |
dormouse-bot
left a comment
Collaborator
There was a problem hiding this comment.
This is feedback on work in progress, not a merge verdict. Mark the PR ready when you want the full review. The inline comments cover four behavior bugs and one stale spec sentence: two in the WATCHING key, one in remote input acknowledgement, and one in held-report deferral.
nedtwigg
marked this pull request as ready for review
September 24, 2026 07:25
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
dormouse-bot
left a comment
Collaborator
There was a problem hiding this comment.
Three findings in addition to the draft review's open threads.
… bound, hand-back ownership - The command tokenizer keeps a redirection's `&` or `|` in its word (`2>&1`, `<&3`, `>|`, `&>`, `&>>`), reads `|&` and fish's `&|` as pipes, and drops a comment (`#` starting a word) through the end of its line; the watch key skips redirections, so `make 2>&1 | tee log`, `pnpm build &> log` and `claude # x; then deploy` key on the program they run. - fish's grammar words are grammar: `end` closes, `and` / `or` / `not` / `begin` open, and a fish `case` line is patterns alone; POSIX's `case WORD` newline `in` still works. - `isWatchKey` checks the drive prefix on the program only, so `npm run b:dev` keys `npm b:dev` instead of falling back to `npm`. - A remote Client's write acknowledges only when it holds more than mouse reports, in both hosts, through `alertedPty.writeClientInput`. - A held report whose deferral already came due rings on idle escalation instead of starting a fresh deferral ceiling. - `hand_back` returns a transferring id to its source even after the target window's close dropped its owner; a killed id stays unowned. - Drop the stale renderer-local episode claims; `AlertState.episode` is required. Restore the original inactivity-timeout helper copy. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF
- Opening a ring no longer sets `todo`; the ring shows its own detail, and public `notification` is the ring's detail while ringing, else the TODO's. - Acknowledging without input (click, Door, zoom, tap), dismissing (`a`), or `t` on a ringing Session turns the ring into a TODO carrying its detail; typing, a paste or drop, and the pill clear both. `t` on a standing TODO still turns it off. - A withdrawal (await, resumed work, rule removal) takes only the ring and its detail; the prior-TODO restore machinery is gone. A dropped hold or deferral leaves no TODO. - An unacknowledged ring persists as the TODO a look would leave, with its detail, within the strict-reader source allowlist. - Specs, the VS Code README, the tutorial hint and detector comment, and the stories and fixtures that primed a fresh ring with TODO follow. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF
Member
Author
|
Two product changes from the owner ride along with the round-1 fixes:
🤖 Generated with Claude Code |
dormouse-bot
approved these changes
Sep 24, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Alerts had false negatives and false positives. Most of both came from one abstraction:
attend()meant "the user typed or clicked in this pane in the last 15 s". It was checked once, when a completion happened, and a "yes" threw the completion away.Replaying a recorded Claude Code session showed the worst case. A user presses Enter and walks away without leaving the window. Claude's "needs your permission" arrives inside that 15 s window and is dropped for good: no ring, no TODO, no push. Conversely, watching a pane for 15 s without typing made it ring.
This PR rebuilds the alert system in six phases. Each phase is its own commit followed by a
/simplifycommit, then a whole-branch code review and a merge oforigin/main.What changes for users
dorreveals, and scroll swipes never do.CSI 13 u, and one-key answers to prompts.sudo,npx,caffeinate, …pnpm dev≠pnpm test, while a barepnpmrule still covers both).133;Ccommand lines are read.bind -xkeys no longer count as commands.OSC 9;<n>no longer rings.VTE_VERSION,WT_SESSION,TMUX).OSC 9;4progress. 3.7.0 adds sequences we'd mishandle. A turn ending on a pane you're not engaged with rings "claude finished".Architecture
alert:commandwire.pty:exitbefore a transfer's mark;Testing
pnpm teston the merged tree, standalonetsc --noEmit, and Rustcargo test --lib(115). lib vitest has 4009 tests.dor await --until quietresolves;window.statewiring (needs an Extension Development Host);Deferred (spec
## Future)🤖 Generated with Claude Code
https://claude.ai/code/session_01HwN55bUVmCNmPiX7vHGCVF