Repository navigation
[ATT-06] Extend upstream notifications with canonical attention policy #8
Description
ID: ATT-06 (F-005). Priority: P1. Blocked by: #7. Backlog: #1.
Scope
Extend upstream v0.0.42's existing opt-in browser/Electron notification
coordinator, settings, sounds, in-app toasts, scoped click routes and badge
delivery. Hosting an environment never enables them. Do not add a competing
notification coordinator or duplicate the settings surface.
Upstream adoption evidence
At 719a76ca1dbf5490f1aa33ffb9966301e02be9a9:
apps/web/src/components/ThreadNotificationCoordinator.tsxobserves each
live environment shell, suppresses the initial observation, detects
approval/input/failure/completion transitions and routes clicks by scoped IDs.apps/web/src/components/settings/NotificationSettings.tsxrequests browser
permission from the settings gesture with visible permission errors.apps/web/src/threadNotifications.tsowns sound and browser/Electron badge
integration.ClientSettingsSchemadefaults notifications and in-app toasts
to off.
Remaining work is canonical attention/revision integration, category/mute/quiet
policy, explicit delivery-failure behavior and privacy defaults. The upstream
OS payload currently includes thread.title, and its badge counts pending
notifications cleared on focus, not canonical actionable threads. Preserve
that distinction and avoid double delivery when changing the source model.
Acceptance criteria
- Default off until explicit per-client consent. Expose category choices,
per-environment mute and quiet-hour policy in client preferences; disabling
immediately stops future notifications without resolving attention. - Browser permission is requested only from a user gesture. Denial/unsupported
delivery is visible; the in-app inbox remains usable. - Deduplicate by scoped item plus material revision/category. Initial snapshots,
history import, rebuild and reconnect replay do not notify; only post-live
transitions are candidates. Completion is optional awareness, not open
attention. Do not send one completion notification per replayed turn. - Reuse the interactive web/Electron presentation and shell badge boundary.
Do not add a second native notification emitter to the existing renderer
notification path.
A server-only host has no notification sink. Two independent opted-in clients
may each notify; a user-wide notification lease is not required. - Clicks restore/focus and route to the correct environment/thread, with an
explicit unavailable state when disconnected. - Use static category text by default; sensitive thread/prompt/tool/error detail
is not copied to OS notifications. Foreground suppression policy is explicit. - Exercise permission denial, disable/mute, quiet-hour boundaries, replay,
duplicates, multiple clients and click routing through existing tests.
Coverage and non-goals
Local/hosted web and Electron on supported desktop platforms, all provider
events and remote modes. Mobile/APNs/FCM is MOB-01. No server-host notification,
mandatory relay, account-level preference sync or background web service worker.
Activity
[-][ATT-06] Add opt-in frontend browser and desktop notifications[/-][+][ATT-06] Extend upstream notifications with canonical attention policy[/+]jdbencardinop commentedon Sep 30, 2026
ATT-06 completed locally
Implemented on
phase2/attention-notifications:96ac3942d(genuine isolated sourcefd5dd46b6cc2321c210b2423a21bf85c935461f2).2cecee4a3a3f078494ac9ddd98dd9b75ebcafbe5.0e412959124074776c7ed926f9081636eb582c6e.b78b175269949d99773e28f7d7f848acfd5a0dbd.d24e4a527c895426889df2a2beb74acd02a25d58.Delivered behavior and approved policy
The existing ThreadNotificationCoordinator remains the sole renderer emitter.
Canonical-capable environments use accepted post-live attention revisions and
newly completed turns. Explicitly unsupported environments retain the upstream
shell detector exclusively. No second native emitter, server-only sink, relay
dependency or user-wide lease was added.
System/sound and in-app consent remain off by default. Existing opt-in choices
retain approval/input/failure/completion categories; new provider-disconnection
alerts start disabled. Categories, environment mutes and quiet hours use the
existing client-local preferences and Settings surface.
Quiet hours use local wall clock, include the start, exclude the end, support
midnight crossing, and treat equal endpoints as all-day quiet. Disabled/muted/
quiet observations advance deduplication without queuing future alerts. Policy
changes cannot replay already-present candidates; delayed sound rechecks policy.
The focused active scoped thread is silent on every channel. Other focused
threads may toast/sound; background clients may use system alerts/sound.
Static payload text replaces sensitive titles; prompt/tool/error detail never
enters OS notifications. Permission is requested only from the Settings gesture.
Denial, unsupported delivery and runtime failures are visible without disabling
the inbox.
Clicks focus the client and retain environment/thread identity. Disconnected
destinations keep a persistent Retry open thread action until reconnection,
rather than trying to fetch a lazy route offline. Removed or unauthorized
destinations lead to the inbox. Notification badge semantics remain pending
notification threads cleared on focus, distinct from actionable inbox counts.
Shared boundary and validation
Foundation now retains current eligible candidates across consumer batching,
bounded by compact current entities rather than a journal. Snapshots, replay,
rebuild and nonlive states do not notify; resolved/deleted candidates leave
the map. Same-turn completed-summary updates do not create duplicate completion
alerts. No event/RPC protocol or server authority change was needed.
covering eligibility, policy boundaries, canonical and legacy presentation,
scoped routing, independent consumers, delivery failures, settings defaults/
patches/scoping, desktop persistence and the existing native badge contract.
new-code lint and the production web build passed.
post-live transport fixtures and a Notification stub. Gesture-only permission,
denial, static payload, revisions/duplicates, category/mute/quiet controls,
disabling, suppressed-event replay and offline retry routing passed.
Three expected stub notifications were delivered; no page errors.
accessibility and lazy-route loading on disconnected notification clicks.
OS alerts were sent. The earlier packaged gates retain their frozen source SHA.
Approved tpatch consolidation
Updating Foundation invalidated the old inbox root's historical-parent anchor.
A metadata reanchor did not move that source anchor. A genuine same-slug inbox
replay passed in isolation but became ambiguous when joined with its prior
history. Those attempts remain evidence; no old failure was relabeled.
The maintainer explicitly approved consolidating inbox and notifications into
one client-attention maintenance root.
attention-notificationsnow containsthe complete 30-path ATT-05 + ATT-06 intent, hard-depends on Foundation and
supersedes the retained historical
attention-inboxroot.All 30 preimage-bearing recipe operations were genuinely executed on the
updated Foundation baseline, with exact product-tree equality checked before
recording/landing and again after integration. Foundation was recorded on its
own lineage so it did not absorb the inbox's documentation. Its full 73-path
intent remains intact. All six maintained roots verify; DAG: zero violations.
This uses the recovery pattern documented in tesseracode/tesserapatch#25.
No live-state writes, original-branch changes, branch push or PR. Owned browser,
dev server, disposable data and temporary replay worktrees were cleaned up;
selected screenshots and sanitized browser results remain session-local.
#9 is the next recommended slice; #11 and #15 remain unblocked but queued.
Implemented with GPT-6 Astra through GitHub Copilot CLI; no delegated inference.