Repository navigation
fix(notifications): drop events for another Chau7 instance's tabs - #281
Merged
Merged
Conversation
Problem: every Chau7 instance on the Mac shares the AI event log and CLI
hooks, so Chau7 Next received events tagged with the production app's
tab ids. Delivery treated any explicit tab id as its own: styling failed
("Explicit tabID not found", 111 warnings in the field log) and the
fallback still showed a desktop notification, 57 duplicates while both
apps ran. Routing retries of unresolved events also logged "delivery
prepared" at INFO on every attempt.
Decision: notification preparation now drops an event whose explicit
tab this instance does not own. Ownership is a bounded record (4096) of
tab ids seen live in this run, refreshed from the open tabs before each
decision, so a tab closed just before its event still counts as owned.
Retried preparations log at DEBUG.
Rationale: an id never hosted here can only belong to another instance;
acting on it duplicates that instance's alert. Remembering closed tabs
keeps results for a tab the user just closed.
Validation: new tests events_for_another_instances_tab_are_dropped and
known_tabs_are_bounded_oldest_first; retry counter covered in
routing_missing_identity_retries_and_exhaustion.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Problem: closing a tab typed `exit`, then sent SIGTERM to the shell's group and SIGKILL 0.5 s later; quitting sent SIGTERM. Interactive zsh ignores SIGTERM, so whenever `exit` did not land (a full-screen program in the foreground) the shell was SIGKILLed, losing history and exit hooks; the field log shows exactly this sequence. A full-screen program in its own foreground group never received a signal at all. Decision: send SIGHUP, as Terminal.app and iTerm do, to the PTY's foreground process group (new Chau7Terminal::foreground_pgrp) and to the shell's group, keeping the same delays before SIGKILL. App quit hangs up every live shell. Rationale: shells and their jobs treat SIGHUP as the terminal going away: they save history, run exit traps and pass it to their jobs. Validation: new test closing_hangs_up_a_shell_that_ignores_sigterm (a PTY child that ignores SIGTERM and never reads `exit` runs its HUP handler; the previous sequence killed it). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Problem: every write started the input-to-output clock, including Enter. The next output after Enter is the command's (Codex booting took 925 ms), and keys typed while the shell still loaded its startup files waited for them (1,933 ms), so the field log reported input lag that the UI never had. Decision: shell_latency::measures_echo: a write starts the measure only when it has no line submit, the shell is not loading and echo is on. Rationale: input latency is meant to be keystroke-to-echo; command run time and shell startup are other measures. Validation: new test only_echoed_keystrokes_start_an_input_measure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Problem: GPUI's caller-located errors carry an empty target outside a `crates/` tree, so vendored GPUI lines were written as ": window not found" at ERROR. Those come from window event senders firing after a window closed, on every window close. Decision: a record without a target is labelled with its source location (for example gpui-pre/src/window.rs:1720); GPUI's "window not found" with an empty target is written at DEBUG. Other library errors keep their level. Rationale: error lines must say where they come from, and an expected close-time race should not count as an error. Validation: new tests library_records_without_a_target_are_labelled_by_location and only_gpuis_closed_window_race_is_demoted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Problem: the Full Disk Access guard re-probes every few seconds and logged the same WARN each time access was still denied. Decision: warn when access becomes denied or a child process is actually refused; an unchanged denial logs at DEBUG. Rationale: the warning reports a change worth acting on, not the polling cadence. Validation: new test unchanged_denial_is_not_rewarned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Fixes for the findings from reviewing the Chau7 Next test build's log (about 28,000 lines since 2026-10-11 plus the new build's session).
Changes
exit, then SIGTERM, then SIGKILL. Interactive zsh ignores SIGTERM, so the shell was killed and lost history and exit hooks wheneverexitdid not land. It now sends SIGHUP (like Terminal.app and iTerm) to the PTY's foreground job and the shell's group; app quit hangs up every shell..zshrc). Only echoed keystrokes are measured now.: window not foundERROR lines. Targetless GPUI records are labelled by source location, and GPUI's expected closed-window race is logged at DEBUG.Not changed: events from AI sessions that cannot be mapped to any tab (for example a Claude session running in the other app) still enter the feed as untargeted events and are dropped after the routing retries; they may belong to a Next tab whose identity is not known yet.
Validation
events_for_another_instances_tab_are_dropped,known_tabs_are_bounded_oldest_first,closing_hangs_up_a_shell_that_ignores_sigterm(real PTY child that ignores SIGTERM),only_echoed_keystrokes_start_an_input_measure,library_records_without_a_target_are_labelled_by_location,only_gpuis_closed_window_race_is_demoted,unchanged_denial_is_not_rewarned; retry counter added to the existing suppression test.cargo clippy --workspace --all-targets -D warningsclean; staged guardrail gate replayed locally. Fullapps/chau7-nextworkspace: 3,341 passed, 0 failed, 2 ignored.crates/: clippy clean, 560 passed, 0 failed, 3 ignored. CI: macOS, Linux, Windows and quality gates pass.🤖 Generated with Claude Code