fix(notifications): stop sleep-control and session-close spam (macOS 2.7.3) - #15
Merged
Conversation
…2.7.3)
Three notifications fired without cause and had no way to switch off.
Sleep control ("Keeping Mac Awake" / "Sleep Control Returned")
Both were edge-triggered on the isActive flip in Auto mode, where the
hold condition is an OR of three volatile signals with no hysteresis and
no debounce. Every walk-away-and-come-back cycle cost two banners, and
toggling Auto off and back on re-fired the first. They were also the only
notifications in the app that bypassed AgentNotificationPrefs entirely,
so there was no toggle to silence them.
Sleep state is already live in the menu bar icon, the panel, and the iOS
Dashboard via MacStatus.sleepActive, so the banners only repeated what
the UI already showed. Both call sites are gone and SleepStateNotifier is
deleted (it had no other callers).
Session close ("Task completed" on quitting an agent)
A close event (SessionEnd / sessionEnd) normalizes to the same
.sessionEnd phase as a turn-end event (Stop / agentStop), so quitting an
agent produced a duplicate "done" alert seconds after the real one.
Split at the gate rather than in the normalizer: the phase stays
.sessionEnd, so hasEnded, scheduleTerminalRevert, and session history are
untouched, and IDE badges do not go stale waiting on the 10-minute sweep.
shouldNotify routes close events to the default-off housekeeping switch
via the new AgentNotificationCatalog.isSessionClose. Events are still
recorded and visible in Activity. Turn-end alerts are unchanged.
Housekeeping is added to the VS Code Copilot and Copilot CLI category
lists so the toggle that re-enables close alerts is reachable there.
This mirrors what opencode already does with session.deleted.
macOS only. The iOS companion is unchanged.
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.
macOS only. The iOS companion is unchanged and stays on its current App Store version.
Kills three notifications that fired without cause. Two for sleep control, one for closing an agent.
1 + 2. Sleep control banners
SleepStateNotifierfired on everyisActiveflip in Auto mode, and the hold condition is an OR of three volatile signals with no hysteresis and no debounce:shouldHoldAuto = isSnoozed || isAgentHookFresh || isUserActivityFreshTwo banners per walk-away cycle. Toggling Auto off and back on re-fired the first one. App launch in Auto with the user at the keyboard fired it immediately.
They were also the only notifications in the app that bypassed the preference gate entirely:
So there was no way to turn them off. Sleep state is already live in the menu bar icon, the panel, and the iOS Dashboard via
MacStatus.sleepActive, so the banners repeated what the UI already showed.Both call sites removed.
SleepStateNotifier.swiftdeleted, it had no other callers.3. "Task completed" when you close an agent
A close event and a turn-end event collapse into the same phase:
StopSessionEnd.sessionEndstopsessionEnd.sessionEndStopSessionEnd.sessionEndagentStopsessionEnd.sessionEndSo quitting an agent fired a duplicate "done" alert a second or two after the real one.
Fixed at the gate, not in the normalizer. Remapping the phase would have broken the session state machine, since
.sessionEnddriveshasEnded,scheduleTerminalRevert, andinsertSessionHistory. For Cursor and VS Code, closing a chat session does not kill the process, so their badge would have sat stale until the 10-minuteideIdleWindowsweep.Events are still recorded and visible in Activity. Turn-end alerts are untouched. Flip Housekeeping on in Configure > Agents to get close alerts back.
.housekeepingadded to the VS Code Copilot and Copilot CLI category lists so that toggle is reachable for them. This mirrors what opencode already does withsession.deleted -> .housekeeping.Verification
release.ymluses)plutil -linton project.pbxproj: OKdc-hookpresent and--pingexits 0Not verified locally: the iOS companion build, since iOS 26 is not installed in my Xcode. No iOS or
DoomCoderCorefile is touched, sobuild-iosis expected to be unaffected. That is the main thing this PR is here to confirm.Unrelated pre-existing flake noticed while verifying:
ringBufferCapsAt200inSyncTelemetryTestsfails about 25% of the time because sibling tests race on theSyncTelemetry.sharedsingleton.ci.ymlruns no tests, so it does not gate anything. Left alone as out of scope.Not in scope
Copilot CLI has a third close path,
errorOccurredwith a clean-exit signal (Ctrl+C, SIGTERM, exit 0/130/143), which is remapped to.sessionEndand still notifies. Deliberately left for a separate change.