Skip to content

feat: device-owned notification preferences (#2500 Track 4) - #2534

Merged
DoodleBears merged 18 commits into
mainfrom
t3/device-notification-preferences
Oct 21, 2026
Merged

DoodleBears merged 18 commits into
mainfrom
t3/device-notification-preferences

Conversation

@DoodleBears

@DoodleBears DoodleBears commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Why the change

让手机持久保存四类通知选择并复制到所有已配对 Host,同时让打开的浏览器按各远程 Host 的本地选择提醒新的 attention。

Requested by Vain. Refs #2500 · 任务 claim · Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183.

Special things to note

  • Merge risk: high. 影响手机持久化、Host 发送过滤、浏览器通知及 CLI。migration106 新增设备副本表;回退需备份或前向恢复,不能只回退代码。浏览器每个活动 Host/凭证保留 O(已见身份数) 内存,无固定容量;移除、换凭证、最终释放时清理。审阅重点是 device authority、完整基线、deadline/abort 与生命周期。手机 CLI 仅支持严格定向的 development client,release-client parity 未获豁免、未实现证明。Draft 保留,由父协调者按最新 CI 决定合并。
  • Verification: head 39780fbd2b2c625af87e7185daad67281487bc2b / base f3b3c3389f15d8ba58848f4703e7750cdd1f91d5。R10仅改Managed Git fallback测试,生产/依赖/Client未变。Linux Node24.21/Vitest5.0.1:原文件11项exit0;真实WriteStream callback延迟80ms受控red1→green0;去探针后11项exit0;邻接git-probe9项exit0。测试明确49ms未abort/未切换,+1ms首源abort并进入备用,冻结测试时钟后以独立真实2秒上限等待真实下载/校验/tar/probe,最终仅首源abort、timer0;未加大生产stall或全局timeout。原CI run39691576559/shard1唯一失败计数保留:1failed322passed3skipfiles、1failed3083passed4skiptests;CI缺phase日志,不把受控复现冒充原CI具体阶段。Windows邻接组合exit1:phoneCLI8项通过,git-probe另有macOS路径fixture失败(1fail/15pass/1skip);Linux9项通过不抹除Windows失败。最终root/mobile type、lint、format各exit0。R9 d47d组合build、239项交界回归及四bundle真实同blob证据保留,本次tests-only不重复build/docs。旧80d timer count1受控诊断、8fc两项CI失败,以及R5长串行exit1未归因/R6旧83ae单轮exit0分别留存,不写fix/baseline。本轮未启动Host/native/模型,集成E2E留全部merge后统一批次。
  • CI / external handoff: CI plan 为 full(core package manifest),mobile=yes;未运行962文件全套,未弱化门禁,旧 CI 不算新 head 通过。已继承公共 Expo fix(mobile): align Expo SDK 58 patch baseline #2548(58.0.17),native inputs 已随公共补丁变化,外部验收必须新 dev build;本轨未运行 native fingerprint。iOS/Android 三档系统文字 × light/dark、真实 phone dev CLI、系统权限/OS banner 均未验收,移交统一外部批次。详细 HTML 绑定精确 head,作为本地/T3 材料;暂无 GitHub reviewer 可访问的托管 URL。

Change outline

flowchart LR
  P[手机偏好 owner] -->|保存后复制、配对、前台重试| H[各 Host 的设备副本]
  D[精确目标的开发 CLI] -->|公开 owner 方法| P
  H --> S[Host 发送过滤]
  A[Host attention.list / dmReplies] --> S
  A --> Q[humanAttention notifications 查询]
  Q --> F[现有 Host Feed / 共享 Inbox 完整分页]
  F --> B[浏览器通知 owner]
  C[浏览器本地选择与权限] --> B
Loading
  • 手机四类即时设置和开发 CLI 使用同一已初始化 owner。旧 Host 开关仅种子化首次选择;非当前离线 Host 在前台按1–30秒退避补同步,后台/移除取消。Host-copy CLI 只读写发送副本,不冒充手机选择。
  • deepseekbot inbox --notifications 对应 Host 决定的 actions、群 mention/reply 和普通 DM 的完整分页;原 Activity 排序、30条 UI 窗口和 Host 来源隔离不变。
  • 浏览器启用在完整基线后检查期限与取消再落盘;同连接读取失败保留基线,断线恢复建立静默基线。按 Host/凭证内稳定身份去重,不用来源创建时间水位或2000条淘汰。普通关闭入口、统一 locale 私密正文、有界脱敏显示失败诊断均保留。T7 viewer 移除释放顺序与 T4 forget/取消共享同一 Host 生命周期。

Web 1440×900,浅/深色:Before 为 f878c43 的原入口,After 为83ae实际通知界面;图片由本 head 承载,不是本次集成 head 的新运行截图。本轮按协调要求不启动 Host;当前入口可由 Messages → Remote Host icon 右键 → Remote notifications 复验。原生截图未运行,不用 Web 替代。

Light — Before

Before light: icon-only Host strip

Light — After

After light: remote notification choices

Dark — Before

Before dark: icon-only Host strip

Dark — After

After dark: remote notification choices

外部原生 fixtures:两台批次 owner 的 QA Host、四类 attention、首次种子/已建立选择、重启和重配对、A持续在线而B恢复、UI/CLI同owner、权限拒绝/无token、系统过滤与点击目标。iOS与Android各验证 default/intermediate/maximum 系统字号 × light/dark,并记录真实设备/build及同条件 before/after;12格均未运行。开发 CLI 另测错误/重复target、release、未初始化/重复owner、断线/超时,超时结果未知时先读取,不盲目重试。

Human comment discussion_r4339304548 的 lead 已采用原文 “stop spamming me with notifications.”,保留必要验证步骤,不改通知语义。

证据范围:本轨旧运行只验证文字和附件名,未验收图片/卡片;最新 main 的 T5 renderer 已继承,不能把旧缺口写成当前实现仍缺失。Host icon/colour 按设备本地设计;DSH Desktop 未验收;未做物理两机真实 tailnet 测试。浏览器只在页面打开时提醒,Notification API 证据不等同 OS banner。

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: fe232e8f-e21e-4fcf-ae28-4f69594b77cd
📥 Commits

Reviewing files that changed from the base of the PR and between f3b3c33 and 39780fb.

⛔ Files ignored due to path filters: 5
  • .github/pr-screenshots/n4/a-d.png is excluded by !**/*.png
  • .github/pr-screenshots/n4/a-l.png is excluded by !**/*.png
  • .github/pr-screenshots/n4/b-d.png is excluded by !**/*.png
  • .github/pr-screenshots/n4/b-l.png is excluded by !**/*.png
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing: 59
  • .agents/skills/verify-deepseekbot/features/phone-notifications.md
  • .agents/skills/verify-deepseekbot/features/remote-hosts.md
  • apps/mobile/scripts/tob-mobile-driver.mjs
  • apps/mobile/src/host/device-notification-preferences.ts
  • apps/mobile/src/host/host-session.ts
  • apps/mobile/src/host/inbox.ts
  • apps/mobile/src/host/native-notification-preferences.ts
  • apps/mobile/src/host/push-session.ts
  • apps/mobile/src/host/wire.ts
  • apps/mobile/src/ui/notification-settings.tsx
  • apps/mobile/src/ui/shell/notification-screen.tsx
  • apps/mobile/src/ui/strings.ts
  • apps/mobile/test/device-notification-preferences.test.ts
  • apps/mobile/test/host-session-unpair.test.ts
  • apps/mobile/test/notification-discovery.test.ts
  • apps/mobile/test/notification-settings.test.tsx
  • changes/2500-device-notifications.md
  • docs/architecture/botharness-architecture.md
  • docs/bot-cli.md
  • docs/bot-cli.zh.md
  • packages/client/src/client/appearance-control.ts
  • packages/client/src/client/host-tabs.tsx
  • packages/client/src/client/index.ts
  • packages/client/src/client/locale.ts
  • packages/client/src/client/remote-hosts.ts
  • packages/client/src/client/remote-notification-settings.tsx
  • packages/client/src/client/remote-notifications.ts
  • packages/client/test/client-observer.test.ts
  • packages/client/test/notification-control.test.ts
  • packages/client/test/remote-hosts.test.ts
  • packages/client/test/remote-notifications.test.ts
  • packages/core/package.json
  • packages/core/src/appearance/control.ts
  • packages/core/src/bots/cli-browser-notifications.ts
  • packages/core/src/bots/cli-device-notifications.ts
  • packages/core/src/bots/cli-inbox.ts
  • packages/core/src/bots/cli-live.ts
  • packages/core/src/bots/cli-phone-notifications.ts
  • packages/core/src/bots/development-inspector.d.mts
  • packages/core/src/bots/development-inspector.mjs
  • packages/core/src/bridge/methods.ts
  • packages/core/src/bridge/rpc.ts
  • packages/core/src/database/schema-plan.ts
  • packages/core/src/diagnostics/client-diagnostics.ts
  • packages/core/src/diagnostics/client-observer.ts
  • packages/core/src/push/delivery.ts
  • packages/core/src/push/http.ts
  • packages/core/src/runtime/human-attention.ts
  • packages/core/src/runtime/notification-attention.ts
  • packages/core/test/appearance-control.test.ts
  • packages/core/test/bridge-rpc.test.ts
  • packages/core/test/cli-browser-notifications.test.ts
  • packages/core/test/cli-device-notifications.test.ts
  • packages/core/test/cli-inbox.test.ts
  • packages/core/test/cli-phone-notifications.test.ts
  • packages/core/test/human-attention-query.test.ts
  • packages/core/test/managed-git.test.ts
  • packages/core/test/push-delivery.test.ts
  • scripts/cli-ui-inventory.json
+--------------------------------------------------------------+
| 🥕 I brought carrots. You brought corner cases. Let's party. |
+--------------------------------------------------------------+
  \
   \     /)/)
        ( '')
        /  |
      o(___)
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@DoodleBears
DoodleBears force-pushed the t3/device-notification-preferences branch from eab3494 to 8fc9384 Compare October 21, 2026 22:24
@DoodleBears

Copy link
Copy Markdown
Contributor Author

精确版本交接:8fc93842981d515bbf1b39c61994413c92249aa4,base 8fb45a29fa7a33540d5bbc3c048de9562a63e9cb。Requested by Vain;Refs #2500。

完整 build 在相同生产代码 f9ead34 整体 exit0;后续仅两处测试 fixture 修复。最终 root/mobile typecheck、lint、format、changelog、CLI parity、24文件210项单worker回归及624页 docs build 均 exit0。四个 Browser/Computer js/maps 真实重建后与提交 blob 一致,无人为产物差异。R6 固定 head 独立 Standards0/Spec0;父协调者另核对 T7 viewer remove 与 T4 forget 交界及最终 test-only delta。

R5 长串行 exit1 的 relay timeout/unavailable 保留,根因未证实。R6 固定旧83ae产物单轮完整序列 exit0,不代表旧故障已修复或是 baseline;最终集成运行 E2E 留统一批次。本轮未启动 Host/Metro/设备/模型。

PR 四张浅/深色 before/after 已在公开 GitHub 页面解码为1440×900,并目视核对;图片来源版本已明确标注。精确 head 的 HTML 解释材料已生成并检查桌面/窄屏,无私密资料;当前仅本地/T3可用,没有 GitHub reviewer 可访问的托管链接,不声称公共 HTML 交付完成。公开 PR 正文保留对应数据流、风险和验收边界。

iOS/Android 原生12格、真实手机 dev CLI、OS banner 尚未运行,转统一外部交接;Expo58.0.17公共补丁后需新 dev build。development-only CLI 不代表 release-client parity 已完成或豁免。migration106 前向恢复及 O(已见身份数) 会话内内存风险保留。CI成功后由父协调者按用户授权合并;本任务保持 Draft,不自行合并或等待 CI。

Human comment discussion_r4339304548 已按原文修改并推送,回复见 #2534 (comment) 。

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183

@DoodleBears
DoodleBears force-pushed the t3/device-notification-preferences branch from 8fc9384 to 80d8ed1 Compare October 21, 2026 22:47
@DoodleBears

Copy link
Copy Markdown
Contributor Author

R8 已推送:head 80d8ed1,base c63947d。Draft 保留,新 CI 交父协调者。

旧8fc的 shard2失败 保留,处理两项:

  1. gateway参数契约补上 notifications;真实service转发的limit/cursor/notifications及Activity、notification owner不可用拒绝均有断言。原断言本地red,修复后green。
  2. 手机CLI测试拆为独立目标拒绝与超时场景。受控idle socket与延迟发现证明旧 clients.size===1 可以在本次请求尚未发送时成立;改等本次 Runtime.evaluate 抵达,断言19999ms未结束、再1ms返回 inspector-timeout,并等待WebSocket/HTTP/pending命令清理、验证timer清空。没有改生产20s deadline或全局15s测试timeout。原CI缺少阶段trace,不声称其具体阻塞阶段已证实,也不归baseline。

最初两文件31项与相邻四文件41项均exit0。随后rebase T8:仅Host菜单与feature map发生冲突,settings和notifications入口、state、dialog及两条journey均保留;T8共享model revision模块与main无diff,T4通知owner/control/sharedInbox未变。最终组合build、root/mobile typecheck、lint、format和9文件151项交界回归均整体exit0。四个Browser/Computer js/maps真实重建、blob等于HEAD,无人为diff。未启动Host/native/模型或全962文件suite;R7的210项/docs、R5失败与R6旧产物单轮成功继续单列。

精确head的HTML与PR说明已刷新;HTML仍仅本地/T3可访问,无公共托管URL。原生/真实phone dev CLI/OS banner及release parity边界、migration106恢复和O(seen)内存风险不变。重型检查窗口已释放,等待父检查新CI后按用户授权处理合并。

Requested by Vain. Refs #2500. Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183。

Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Issue: #2500

Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
Include notifications in the gateway parameter contract and assert forwarding
while preserving unavailable-owner refusals. Split inspector refusal scenarios,
wait for this evaluation rather than a global socket count, assert the exact
20-second deadline, and await bounded fixture cleanup.

The controlled idle-socket/delayed-discovery probe exposes a premature clock
advance. The original CI timeout has no phase trace, so its exact phase is not
claimed as proven. No production code or timeout configuration changes.

Issue: #2500
Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
The server close callback can finish before the client socket close event.
The client ws close handshake then still owns its 30-second timer even though
the 20-second request timeout and CLI result have completed. Observe real peer
close events, wait for them during fixture teardown, and restore the observer.
Keep the zero-timer assertion and the original business deadline unchanged.

Issue: #2500
Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
@DoodleBears
DoodleBears force-pushed the t3/device-notification-preferences branch from 80d8ed1 to d47d76f Compare October 21, 2026 23:09
@DoodleBears

Copy link
Copy Markdown
Contributor Author

R9 follow-up pushed at d47d76f07f0d37bd63dfb356ec23ecad80b74503 (base f3b3c3389f15d8ba58848f4703e7750cdd1f91d5). Requested by Vain; Refs #2500. Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183.

  • Preserved the previous run39689056938/job119530962820 failure: 1failed/316passed/8skipfiles and 1failed/2516passed/15skiptests. The failed assertion was fake timer count1. The original CI has no timer-stack trace.
  • Controlled reproduction held the client raw-socket close event: request20s completed, server cleanup completed, but the client ws30s close-handshake timer remained. Releasing raw close and awaiting the actual peer-close event cleared it. The fixture now awaits those real close events before the unchanged timer0 assertion. Red1→green0; no clearAllTimers, business-deadline change, global timeout increase or production change.
  • Rebased merged T5. Conflicts were only architecture and feature-map documentation; retained both T5 message/resource/request and T4 notification journeys. Source owners remain unchanged. GO2 full build, root/mobile typecheck, lint (including changelog/parity), format and12files239focused tests each exit0. Four tracked Browser/Computer bundles rebuilt identically to their committed blobs. Current CI is new; old passes are not borrowed.
  • R5 long-sequence exit1 remains unexplained. R6 one complete sequence on old83ae artifacts exited0; that does not prove a fix. No Host/native/model run in this round. Native12cells, real phone devCLI, release-client CLI parity and OSbanner remain external handoff gaps. Main now contains T5 rich message rendering; this track's old runtime evidence does not qualify that renderer.

Exact-head HTML was regenerated and previewed at900/360px as local/T3 material; no public reviewer-hosted URL is available. Public light/dark before/after images decode at1440×900; their old runtime provenance remains explicit in the PR. Human request discussion_r4339304548 retains “stop spamming me with notifications.” and its QA contract.

PR remains Draft. Parent owns new CI and merging; this thread does not watch or merge. Heavy window released; no owned Host/process and no listeners47411/47412.

Advance only the 49+1ms source timeout, then await real fallback installation
under a separate real-time bound. Assert source order, abort scope and timer cleanup.
Controlled delayed filesystem callbacks reproduce the old timing-sensitive failure;
the original CI phase is not observed.

Issue: #2500
Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183
@DoodleBears

Copy link
Copy Markdown
Contributor Author

R10 pushed at 39780fbd2b2c625af87e7185daad67281487bc2b, base f3b3c3389f15d8ba58848f4703e7750cdd1f91d5. Requested by Vain. Refs #2500. Agent-Task: codex/local/01a15ee9-f10e-7e21-90ba-727ffccb2183.

Only packages/core/test/managed-git.test.ts changed. Production, dependency pins and R9 phone CLI cleanup are unchanged.

Evidence: the original file executed all 11 tests on WSL Linux / Node24.21 / Vitest5.0.1 and passed. A controlled 80ms delay after real filesystem write completion reproduced the CI's available:false: the backup source also hit the test's 50ms stall deadline before the pipeline completed. The same probe passes with explicit test-clock control. Original CI has no installation-phase trace, so this does not claim direct observation of its exact delayed phase.

The final test verifies no abort/source switch at49ms, first-source abort and backup selection at50ms, then awaits real download, checksum, tar extraction and Git probe. It requires backup success, only the first source aborted, and zero fake timers. A separate real2s deadline bounds that I/O wait; finally clears it and restores real timers. No production timeout increase, skipped test, global timer clearing or blind CI retry.

  • Controlled Linux red1 → green0; probes removed before final whole-file Linux11tests exit0.
  • Linux neighboring Git probe9tests exit0. Windows neighboring selection remains exit1: phone CLI8tests passed; the unrelated macOS POSIX-path fixture failed under Windows path semantics (combined1failed/15passed/1skipped). It is not marked green or silently waived; its test and owner match main, with no independent main run claimed.
  • Final root/mobile typecheck, lint (including changelog/parity), and format each exit0. This is tests-only, so no new Client/docs build. R9's complete combinationbuild and239tests remain separate prior-head evidence.
  • Preserved run39691576559/job119539348891:1failed322passed3skipped files;1failed3083passed4skipped tests. The aggregate only reported test-full. New CI belongs to the parent coordinator.

PR remains Draft. No Host/native/Metro/model run; owned Windows and Linux processes are gone and ports47411/47412 are clear. Exact-head PR/HTML and native handoff are refreshed; native, real phone CLI, OS banner and release-client parity gaps remain. R5 unexplained failure and R6 old-runtime pass stay separate.

@DoodleBears
DoodleBears marked this pull request as ready for review October 21, 2026 23:37
@DoodleBears
DoodleBears merged commit 9361934 into main Oct 21, 2026
12 of 13 checks passed
@DoodleBears
DoodleBears deleted the t3/device-notification-preferences branch October 28, 2026 04:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants