Skip to content

[ATT-06] Extend upstream notifications with canonical attention policy #8

Closed

Description

@jdbencardinop

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.tsx observes 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.tsx requests browser
    permission from the settings gesture with visible permission errors.
  • apps/web/src/threadNotifications.ts owns sound and browser/Electron badge
    integration. ClientSettingsSchema defaults 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

  1. added
    fork-backlogMaintainer backlog for the multi-machine fork
    status:blockedRelease or dependency gate remains; no implementation yet
    priority:P1Next workspace capabilities after foundation
    on Sep 14, 2026
  2. changed the title [-][ATT-06] Add opt-in frontend browser and desktop notifications[/-] [+][ATT-06] Extend upstream notifications with canonical attention policy[/+] on Sep 23, 2026
  3. added
    status:readyScope ready and all implementation gates satisfied
    status:in-progressActively implementing the scoped issue
    and removed
    status:blockedRelease or dependency gate remains; no implementation yet
    status:readyScope ready and all implementation gates satisfied
    on Sep 29, 2026
  4. jdbencardinop commented on Sep 30, 2026

    @jdbencardinop
    Author

    ATT-06 completed locally

    Implemented on phase2/attention-notifications:

    • Shared eligibility source: 96ac3942d (genuine isolated source fd5dd46b6cc2321c210b2423a21bf85c935461f2).
    • Full 73-path Foundation attestation: 2cecee4a3a3f078494ac9ddd98dd9b75ebcafbe5.
    • Consolidated client-attention source replay: 0e412959124074776c7ed926f9081636eb582c6e.
    • Product integration: b78b175269949d99773e28f7d7f848acfd5a0dbd.
    • Clean verified tip: 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.

    • Final committed-source run: 241 tests passed across 10 focused files,
      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.
    • Web, client-runtime, server, mobile and desktop typechecks passed; scoped
      new-code lint and the production web build passed.
    • Approved integrated browser pass used a disposable backend, controlled
      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.
    • Browser verification exposed and fixed explicit switch checked-state
      accessibility and lazy-route loading on disconnected notification clicks.
    • This is not a new native OS/platform qualification. No provider turns or real
      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-notifications now contains
    the complete 30-path ATT-05 + ATT-06 intent, hard-depends on Foundation and
    supersedes the retained historical attention-inbox root.

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    fork-backlogMaintainer backlog for the multi-machine forkpriority:P1Next workspace capabilities after foundation

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions