Skip to content

feat(desktop): 任务级「消息免打扰」,单条任务不再发通知 - #6244

Merged
MagicLizi merged 27 commits into
makecindy:mainfrom
WZBbiao:feat/session-notify-mute
Oct 28, 2026
Merged

MagicLizi merged 27 commits into
makecindy:mainfrom
WZBbiao:feat/session-notify-mute

Conversation

@WZBbiao

@WZBbiao WZBbiao commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

这次改了什么

摘要

任务右键菜单新增「消息免打扰」:开了之后这条任务不再发系统通知(toast / 提示音)、
不上 Agent 灵动岛、不推手机、不发飞书;任务里的未读与角标照常,任务照常跑。
菜单项自己就是开关,设过之后同一位置文案变成「允许消息通知」。

四道门都加在发出侧,而不是让每个调用方自己判断:

通道 位置
系统 toast / 手机 / 飞书(renderer IPC 路径) notificationService.ts 的 notification:show-session-event 一个早退
Agent 灵动岛(含提示音) agent-island/state.ts 的 shouldDisplaySession:静音任务只从展示面排除(displaySuppressedSessionIds),岛面/菜单栏/提示音不出现;事件仍进状态机
手机推送 device-link/index.ts 的 sendMobileSessionNotify,覆盖代输入这类不走会话终态路径的调用方
自动化 run scheduler-host/notifier.ts,只掐个人通道;wecomGroup 是共享群通知,不跟个人静音走

判定不能逐事件查库(灵动岛与通知都在同步事件路径上),所以复用插件后台隐藏任务那套
进程内索引:hiddenSessionRegistry 泛化成 sessionFlagRegistry,一次加载同时索引
hidden_at 与 notifications_muted。加载完成前按「未静音」处理,宁可多提醒一次。

变更类型

  • feat 新功能

范围

  • 关联 Issue / 需求:按会话设置「消息免打扰」:静音通知横幅、声音、灵动岛与手机推送 #6230
  • 本 PR 包含:sessions.notifications_muted 列与 migration 0130(最初排到 0129,与 main 的 0129_chemical_thor 撞号后按 migration 规则以主干链重新生成);四道发送侧门;任务右键菜单项与其乐观更新/回滚;五语文案;术语表 proposed 条目。
  • 明确不包含:跨设备(device-link)任务的静音。这类任务的提醒由任务所在的那台设备发出,本机设了也不算数,所以对它们直接不显示这个菜单项(与「移动任务」对 remoteHostId 的处理同口径)。
  • 用户可见变化:任务右键菜单多一项「消息免打扰 / 允许消息通知」;开了的任务不再发提醒。
  • 是否存在 breaking change:无。

UI 变化

  • 引用的设计规范:docs/design-rules/DESIGN.md §4 Select & Dropdown(菜单面板与菜单行)。新项直接复用共享的 DropdownMenuItem 与侧栏 menuStyles.ts 的 MENU_ITEM_CLASS,没有引入任何新的颜色、字号、间距或圆角 token,因此 Light / Dark 由既有语义 token 一并覆盖(本次未做双模式实机目检,也没有新增颜色)。文案按 docs/design-rules/DESIGN.md 的双模式要求只走 t(),五语齐备。

怎么验证的

自动验证

pnpm --filter desktop db:generate
结果:生成 drizzle/0130_heavy_iron_patriot.sql(原 0129_dizzy_yellowjacket,撞号后重生成)(ALTER TABLE sessions ADD notifications_muted integer DEFAULT false NOT NULL)

pnpm --filter desktop db:validate
结果:✅ 130 sql files + journal aligned + no schema drift + scripts CJS-only + frozen baselines

npx vitest run src/main/localDb/__tests__/migrationReplay.test.ts
结果:Test Files 1 passed / Tests 16 passed(新增「存量任务全部回填为未静音」用例)

npx vitest run src/main/localDb/ipc/__tests__/sessionsPerTaskFlags.test.ts \
  src/main/__tests__/notificationService.test.ts \
  src/main/scheduler-host/__tests__/notifier.test.ts \
  src/renderer/features/cc-agent/sidebar/__tests__/SessionTaskMenu.test.tsx \
  src/renderer/features/cc-agent/sidebar/__tests__/sessionNotificationMute.test.ts
结果:Test Files 6 passed / Tests 133 passed

npx vitest run --project standard(全量桌面端单测)
结果:Test Files 5 failed | 3776 passed | 12 skipped;Tests 8 failed | 58723 passed | 103 skipped
      这 5 个文件在改动前的同一 checkout 上同样失败(stash 对照过):
      makerSendToSessionOrdering(源正则断言已漂移)、drizzle-proxy-perf(fixture 缺更早的列)、
      piGatewaySessionAffinity.integration、botGroupWorkDir、executor(依赖本机 ripgrep/凭证)。
      本改动新增 0 个失败。

pnpm --filter desktop typecheck
结果:通过

npx eslint <本次改动的 11 个文件>
结果:17 个 error,全部是既有 unused-vars(stash 对照同为 17 个),本次新增行 0 个

node scripts/check-i18n.mjs
结果:五语 12687 个 key 全部一致

node scripts/check-i18n-glossary.mjs
结果:无新增违规;文档已用 pnpm i18n:glossary-doc 重新生成

node scripts/check-dco.mjs
结果:DCO check passed: 1 commit signed off

手工验证

隔离 dev 沙箱实机(pnpm restart:desktop:remote --region=cn --isolated=@worktree,
沙箱 Cindy-dev2-notify-mute-40b5a3,与正式 profile 完全隔离),全程走 CDP 驱动真实 UI:

  1. migration 生效:沙箱库 schema_version = 129(换号前实测;现为 130),sessions.notifications_muted 存在
    (INTEGER NOT NULL DEFAULT false),应用正常起窗、正常登录。
  2. 在沙箱里新建了一条本机任务并跑完一轮。
  3. 在该任务上触发真实右键菜单,菜单项为
    置顶 | 重命名 | 消息免打扰 | 复制任务链接 | 共享任务 | 移动任务 | 导出任务… | 在新窗口打开 | 归档 | 删除。
  4. 点「消息免打扰」后:同一位置文案变成「允许消息通知」,库中 notifications_muted 由 0 变 1。
  5. 重载窗口后再开菜单,文案仍是「允许消息通知」;再点一次恢复,库里回到 0。
  6. 对 device-link(别的设备的)任务开菜单,确认不出现该项。

review 后续(自动审查两轮)

自动审查在首轮之后又提了若干条,已按「成立就改、不成立就回帖说明」处理:

commit 处理
6bcfd237c 已上岛任务被静音时要收走岛面;sessionFlagRegistry 加载期按字段分别登记;done 通知在异步富化后、真正发送前再判一次静音;渲染侧回滚不再盖掉期间别处写入的新值
da5685baf 静音任务不再收到代输入 / 桌面专属确认卡的 IM 旁路提示(im/desktopConfirmNotice 注入 isSuppressed,notifyInputHandoffOwner 早退)
6c9b34a21 同步 main(db24db2aa),解决 localDb/ipc/sessions.ts 里静音写入块与 clearSessionAttention 的相邻冲突
91adaaf3e 静音改为「只退出展示面」:侧栏卡片的实时活动、等待交互态与远端活动镜像不再被一起清掉;local-db:sessions:update 严格校验 notificationsMuted 只接受真 boolean;两处异步等待后补发送前复查;渲染侧回滚加操作序号

91adaaf3e 之后的验证:

npx vitest run --project standard src/main/agent-island/__tests__ \
  src/main/localDb/__tests__/agentIslandSessionPatch.test.ts \
  src/main/localDb/ipc/__tests__/sessionsPerTaskFlags.test.ts \
  src/main/__tests__/notificationService.test.ts \
  src/main/im/__tests__/desktopConfirmNotice.test.ts \
  src/main/scheduler-host/__tests__/notifier.test.ts \
  src/renderer/features/cc-agent/sidebar/__tests__/sessionNotificationMute.test.ts
结果:16 files / 479 tests passed

pnpm --filter desktop typecheck
结果:通过

pnpm check:dco
结果:4 commits signed off, 1 exempt (merge commits)

未执行的验证

  • 实机确认「真的不弹系统通知/不上灵动岛」这一步没做成。 这台机器上 dev 窗口的
    document.hasFocus() 恒为 true(窗口在另一个 Space、document.hidden === true,
    activate 其它 App / Page.bringToFront / window.blur() 都没能把它翻成 false),
    而这个状态本身就在通知发送的前置门里,抹不掉它就无法做出「有通知 vs 无通知」的对照。
    换真机(把 dev 窗口放到当前 Space 并失焦)就能补; 目前这部分的证据是直接打在四道门上的单测。
  • 手机推送与飞书没做实机:沙箱账号没注册推送 token、没绑 bot owner。
  • 双模式实机目检未做(本次没有任何颜色/样式新增,菜单项复用共享组件)。

风险

风险分类

  • SQLite / migration
  • 无已知风险

影响与回滚

  • 影响范围:给 sessions 加一列(notifications_muted,NOT NULL DEFAULT false)。
    存量任务全部回填为「未静音」,升级后行为与升级前完全一致;不改任何既有列的语义,
    不重写历史 migration,不改任务列表/搜索/用量等任何口径。
  • 回滚 / 降级方式:功能代码可整体 revert;降级回旧版本时多出的这一列会被旧代码忽略
    (旧版 SELECT 走显式列/整表投影,多余列不影响),不需要回滚 migration,
    也不需要恢复历史库。
  • 兼容性:这一列不进 device-link 的 patch-meta allowlist,不会经隧道下发——旧版对端
    不会收到它不认识的 patch 字段,因此没有协议兼容风险。

提交前检查

  • 已 review 完整 diff
  • 每个 commit 都带 DCO 签名(git commit -s,见 DCO)
  • UI 改动已在「UI 变化」注明引用的设计规范章节(不涉及 UI 则跳过)
  • 未提交凭证、令牌或授权文件
  • 已核对受影响的文档,行为变化涉及的旧结论已同步修订(docs/dev-rules/plugin-task-api-implementation.md 里的注册表名跟着改了)
  • 已确认测试结果或说明未执行原因

会话右键菜单新增「消息免打扰」:开着的任务不再发系统 toast(含提示音)、
不上 Agent 灵动岛、不推手机、不发飞书;任务内的未读与角标照常,任务照常跑。
菜单项是开关,设过之后文案变成「允许消息通知」。

实现走一个进程内同步索引(原 hiddenSessionRegistry 泛化为 sessionFlagRegistry)
而不是逐事件查库,四道门都在发出侧:

- notificationService 的 notification:show-session-event:桌面 / 手机 / 飞书一次挡住;
- maker-ipc/register 的 shouldNotifyAgentIslandForSession:挡在进岛之前,岛态不进入即无声;
- device-link 的 sendMobileSessionNotify:覆盖代输入等不走会话终态路径的调用方;
- scheduler-host 的 DesktopNotifier:自动化 run 的桌面 / 飞书通道(共享群通知不跟个人静音走)。

数据库加 sessions.notifications_muted(migration 0129,默认 false,存量任务全部按未静音)。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
@WZBbiao
WZBbiao requested a review from a team as a code owner October 16, 2026 12:46
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-28T02:15:43.164694Z
We couldn’t complete this review. Comment @codex review to try again.
3318650 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@greptile-apps

greptile-apps Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 3/5

[High impact] Adds a database column and notification muting logic across the app.

合并前需要修复灵动岛残留运行状态,以及索引加载后静音设置持续不生效的问题。

Findings

  1. P1 已结束任务仍显示运行中 ▶
  2. P1 加载时丢失静音设置 ▶
  3. P2 开启免打扰后仍发提醒 ▶
  4. P2 旧请求回滚覆盖新设置 ▶
Fix with agent prompt
### Issue 1
apps/desktop/src/main/maker-ipc/register.ts:4821-4823
用户在任务已经上岛后开启「消息免打扰」,这里只阻断后续事件,没有移除已有条目。任务完成或被停止时,清理事件也会被同一个判断丢弃。写入 `notificationsMuted` 时又没有清理岛态,导致已结束任务一直显示为运行中。请在开启免打扰时主动移除已有条目,而不只是阻止新事件进入。

### Issue 2
apps/desktop/src/main/localDb/sessionFlagRegistry.ts:73-75
`touchedDuringLoad` 现在被两个字段共用,但加载时仍按整个任务跳过。例如,已有静音设置的任务在索引首次加载前或加载期间被 `setSessionHidden` 恢复显示,只会登记隐藏状态。这里随后跳过整行,原有静音设置就不会进入 `mutedIds`。即使加载完成,该任务仍会继续发通知。请分别记录两个字段的改动,加载时只跳过已改动的字段。

### Issue 3
apps/desktop/src/main/notificationService.ts:244
静音只在收到通知请求时检查一次,但 `done` 通知还要等待预览读取、写入队列和协作任务判断。如果用户在等待期间成功开启免打扰,后面的桌面通知和飞书消息仍会发出。请在这些等待结束、真正发送前再次检查静音;手机出口已经做了这层检查。

### Issue 4
apps/desktop/src/renderer/features/cc-agent/sidebar/sessionNotificationMute.ts:24
失败回滚无条件写回调用开始时的 `previous`,会覆盖另一个窗口刚保存的设置。例如窗口 A 的静音请求仍在等待,窗口 B 成功开启静音并广播给 A,随后 A 的旧请求失败,这里就把 A 改回未静音,而数据库仍是静音。请给乐观更新记录版本,只有没有收到更新的设置时才回滚,或失败后重读当前值。

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

本 PR 为本机任务增加「消息免打扰」,保存到 notifications_muted,并在多个通知出口读取进程内索引。

  • A task menu lets users mute notifications for one local task.
  • Muted tasks stop sending personal alerts across desktop and mobile.

已明确的范围与取舍:WZBbiao 说明跨设备任务不支持本机静音;索引加载完成前按未静音处理;共享群通知不跟随个人静音。这些不作为问题报告。

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[任务右键开关] --> B[本地更新并保存]
  B --> C[数据库 notifications_muted]
  B --> D[更新进程内索引]
  B --> E[广播给其他窗口]
  D --> F[桌面与飞书通知判断]
  D --> G[灵动岛事件判断]
  D --> H[手机推送判断]
  D --> I[自动化个人通知判断]
  J[自动化共享群通知] --> K[不受个人静音影响]
Loading

Reviews (1) · Last reviewed commit: "feat(desktop): 任务级「消息免打扰」,单条任务不再发通知" · Reviewed by Greptile

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3602339c8d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

makecindy#6244 的 review 后续:

- 已经上岛的任务现在才被静音时,主动把它从岛上收走。只挡后续事件会让卡片永远停在
  「运行中」——终态事件也被同一道门挡住,岛态再也不会被清掉。
- sessionFlagRegistry 的加载期改动登记按字段分开。原来两列共用一个 id 集合,加载窗口
  内改过 hidden 会连带丢掉那一行原有的静音标记,加载完成后这条任务会继续发通知。
- notification:show-session-event 的 done 分支在取正文、等交接判定之后、真正发之前
  再确认一次静音:等待期间用户开了免打扰,桌面与飞书仍然会发出去。
- 渲染侧的失败回滚只在「值还是我们写进去的那个」时才回滚,避免盖掉期间别的窗口刚
  保存的新值。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
@WZBbiao

WZBbiao commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

已按 review 补了一版(commit 6bcfd23),逐条对应:

  • 已上岛的任务被静音后会停在「运行中」 — 成立。原来只挡后续事件,终态也被同一道门挡住,岛态永远不会被清。现在开静音时主动把该任务从岛上收走(agentIslandSessionPatch 多了 notificationsMuted === true → handleSessionClosed,与转入后台同一条路径)。补了 localDb/__tests__/agentIslandSessionPatch.test.ts。
  • 加载期两列共用一个 touched 集合会丢静音标记 — 成立。改成按字段各记一份,加载结果只跳过加载期间真被改过的那个字段。补了回归用例(加载窗口内写 hidden,原有静音不许丢)。
  • done 分支等待期间开静音仍会发 — 成立但窗口很窄。已在取正文 / 等交接判定之后、真正发之前再确认一次;手机通道本来就自带这道门。补了用例。
  • 旧请求回滚盖掉新设置 — 成立。回滚改成只在「当前值还是我们写进去的那个」时才执行;找不到行时也不回滚。

本地已重跑:定向 7 个文件 139 通过、全量 --project standard 14708 通过(仅剩改动前就失败的 3 个文件)、typecheck 通过、eslint 无新增。

@MagicLizi

Copy link
Copy Markdown
Contributor

维护者确认门在拦:本 PR(任务级「消息免打扰」)触发 product(feat + 生产 UI 路径)、rules(规则文档 docs/dev-rules/plugin-task-api-implementation.md)与 arch(核心路径 563 行 / 总 diff 7989 行)三类确认,属于用户可见的新功能,不适用既有语义 fallback(不是 bugfix / 已有功能补充 / 纯技术改动 / 机械编辑)。

讨论 issue 已建(见下方链接)。请维护者直接在本 PR 上 Approve 确认;需要作者修改则 Request Changes 写明要求。在维护者确认前,自动流程不进入代码审查、不合并。

讨论 issue:#6248

@MagicLizi MagicLizi added awaiting-discussion 等待维护者讨论(review-pr) touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) touches:large-diff 改动量较大(review-pr 自动维护,仅展示) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) touches:redline 改动碰到红线路径(updater / DB schema 等,review-pr 自动维护,仅展示) touches:rules 改动碰到规则 / 规范文档(review-pr 自动维护,仅展示) labels Oct 16, 2026
makecindy#6244 的 review 后续(chatgpt-codex-connector 在 device-link/index.ts:2035 的 P2):
「消息免打扰」只掐掉了手机 push,代输入与桌面专属确认卡的 IM 提示照发。

- im/desktopConfirmNotice 新增 isSuppressed 注入:静音任务的确认卡/代输入指引
  飞书提示直接零动作(连 openId 都不查)。桌面卡片本身只在桌面出现,不受影响。
  接线处(desktopConfirmNoticeWiring)传 sessionFlagRegistry 的同一判定,
  于是 issue / 批量重命名 / 插件文件授权三张确认卡与代输入飞书兜底一起收口。
- maker-ipc/register 的 notifyInputHandoffOwner 最早处早退:静音任务连渠道内的
  「去 Cindy 打开」一行指引也不发(手机 push 另有 sendMobileSessionNotify 的同一道门)。

判定成立的理由:PR 声明的行为是静音任务「不发飞书」,而这两条路径对静音任务照发;
且同一次代输入里手机 push 已被掐掉、IM 指引还在发,本身就是自相矛盾。判定仍走
进程内同步索引(未加载按未静音),不在事件路径上查库。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: da5685baf7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/desktop/src/main/localDb/mapper.ts Resolved
…相邻冲突

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>

# Conflicts:
#	apps/desktop/src/main/localDb/ipc/sessions.ts
makecindy#6244 在 da5685b 之后新来的 5 条 review:

1. 静音不该清掉任务的实时活动(register.ts:4826)。岛面抑制改成展示面过滤:
   AgentIslandState 新增 displaySuppressedSessionIds,shouldDisplaySession 排除
   静音任务;事件照常进状态机,侧栏卡片的逐步活动、等待交互态与远端活动镜像
   不再跟着消失。shouldNotifyAgentIslandForSession 不再按静音挡摄取,岛面收敛
   由 publish() 从同步索引对齐后重发(账号切换/索引重载自愈)。
2. main 严格校验静音字段(mapper.ts:500):local-db:sessions:update 出现
   notificationsMuted 就必须是真 boolean;字符串 "false" 不再被 `!!` 存成已静音。
3. 桌面确认提示在解析 openId 之后、真正发送之前再判一次静音
   (desktopConfirmNotice.ts:73)。
4. 代输入指引在读标题/预览之后、发送之前再判一次静音(register.ts:3014)。
5. 渲染侧回滚加操作序号(sessionNotificationMute.ts:27):同向并发(两个窗口
   都在关静音)时,先失败的那次不再把后一次的成功翻回去。

测试:agent-island 与四个发送侧门相关的 16 个测试文件 479 用例全绿,desktop
typecheck 通过。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 91adaaf3e8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

codex 在 state.ts:2700 的 P2:只在 shouldDisplaySession 里过滤不够。
buildAgentIslandDisplayState 之后还会用 getActiveTransientSession 取回
state.activeTransientSessionId 指向的任务,再由 orderSessionsForAutomaticTransientStack
prepend 回列表——静音任务一旦完成/报错(或它的完成卡还在驻留时被静音),仍会生成
completion/error 卡片并触发提示音。

补三处同口径的抑制:
- enqueueTransientReveal:静音任务不揭示、不进揭示队列(清掉它自己的 reveal 标记);
- getActiveTransientSession:静音任务即使被排成 active transient 也不返回;
- promoteNextTransientReveal:跳过揭示队列里的静音任务;
- restoreSessionScopedReveal(user prompt 回滚)同样不把静音任务重新激活。

活动快照与未读账本走另一条路,静音不影响(侧栏仍能看到它已完成)。
测试:state.test.ts 新增「静音任务的完成卡不回到岛面,也不占 active transient / 揭示队列」
与「完成卡已经在岛上时再静音,下一次展示面就不再包含它」;把这几处抑制临时去掉时
这两条会失败(已验证),加上后 12 个文件 390 用例全绿,desktop typecheck 通过。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
…t 与术语表冲突

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
- 撞号:main 的 0129_chemical_thor 已在主干,本分支的 sessions.notifications_muted
  按规则以主干链重新生成,落到 0130_heavy_iron_patriot(SQL 与原来一致),
  删除旧的 0129_dizzy_yellowjacket。
- migrationReplay:回放区间改为 125..130,同时断言 scheduled_model_baseline
  与 notifications_muted 两列;免打扰回填用例的起点改为 129。
- 三个会话 IPC 用例补 electron 的 app mock:main 给 localDb 静态引入了
  WorktreeManager → workdir-probe-host,该模块顶层读 app.once,缺 app 会在
  收集阶段整文件失败。

验证:db:validate、migrationReplay、PR 相关 16 个用例文件、pnpm --filter
desktop typecheck 均通过。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
@MagicLizi MagicLizi removed touches:redline 改动碰到红线路径(updater / DB schema 等,review-pr 自动维护,仅展示) touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) labels Oct 21, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5f81100946

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@WZBbiao

WZBbiao commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

已再次同步 main 至 640c61b036(merge commit 5f81100946),当前 MERGEABLE。

migration 再次撞号:main 已占用 0132_abnormal_dazzler 与 0133_chat_history_cache。按 database-and-migrations.md 的「撞号以最新主干迁移链重新生成,不手改文件名 / journal / snapshot」,本分支的 sessions.notifications_muted 用 db:generate 重落为 0134_acoustic_scourge,SQL 与原 0132_daily_domino 完全一致(ALTER TABLE sessions ADD notifications_muted integer DEFAULT false NOT NULL)。

测试:migrationReplay 的两条用例补上 main 新增迁移所需的最小 fixture 表(sessions / plugin_usage_events),断言口径不变。

  • pnpm --filter desktop db:validate ✅(0000..0134 连续、journal/snapshot 对齐、无 schema drift、CJS only、历史指纹冻结)
  • npx vitest run --project standard src/main/localDb/__tests__/migrationReplay.test.ts ✅ 17 passed
  • 本 PR 相关面(notificationService / agent-island / desktopConfirmNotice / sessions IPC / sidebar 免打扰)✅ 989 passed
  • pnpm --filter desktop typecheck ✅;pnpm check:i18n / check:i18n-glossary ✅;pnpm check:dco ✅

CI 现状:DCO / Desktop Git integration / Windows runner and database checks / verify-checks 通过;Linux unit tests (3/4) 与 Windows unit tests (3/4) 红在 main 继承来的 src/renderer/voice-input/__tests__/useVoiceInput.startup.test.ts > keeps an authorized microphone closed through a short composer click(断言 prewarm 被调用一次,实际 0 次)。该用例与 useVoiceInput.ts 均由 main 的 ca535f2031(#7283)最后改动,本分支对这些文件零改动(git diff origin/main HEAD -- src/renderer/voice-input 为空),本地连跑 3 次 3 次必现,属 main 侧既有红灯,不在本 PR 内修改。

0132_abnormal_dazzler / 0133_chat_history_cache 进入主干后,两条从更早版本回放的用例
需要 fixture 里先有 sessions 与 plugin_usage_events 表;断言口径不变(回放序列到 0134)。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
按自动审查的两条 P2 收口:

- `notification:show-session-event` 与预览后的复查都改成 `markAttention` 门控:
  其它设备(device-link)任务传 `markAttention: false`,本机库里可能恰有同 id 的
  无关任务行(还原/复制过的库),那一行的静音标记不该压掉远端提醒。手机通道的
  唯一出口 `sendMobileSessionNotify` 收到 `muteExempt` 时同样跳过该判定。
- `getActiveBlockingReveal()` 也排除 `displaySuppressedSessionIds`:静音任务不上
  岛面,但仍是 needs-interaction,排在前面时会被选成「当前阻塞卡」,导致
  `dismissPublishedBlockingReveal()` 因 id 与真实展示卡不一致而拒绝,点岛外只收起
  hover、确认卡一直展开。与 `hasBlockingSession()` 用同一集合。

测试:新增 notificationService(远端事件不被本地静音压掉)与 agent-island state
(静音把前一张阻塞卡挤出仲裁位后,点岛外仍能收起可见卡)各一条;两条在修复前
分别以「spy 未被调用」和「dismiss 返回 false」失败。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
@WZBbiao

WZBbiao commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

第二轮:自动审查的 3 条 P2 已逐条处理(bd98675e60),另一条 f906ba8817 补上上一轮漏提交的 migrationReplay fixture。

已修两条

  • 本地静音误伤远端提醒:notification:show-session-event 的入口与「预览后复查」都改成 markAttention && isSessionNotificationsMutedSync(...),与公共出口 showDesktopSessionEvent 既有的 isLocalSession 豁免同口径;sendMobileSessionNotify 新增可选 muteExempt,由 handler 对 markAttention === false 透传,其它调用方(scheduler / 代输入 / 伙伴自主)行为不变。
  • 静音任务占着阻塞卡仲裁位:getActiveBlockingReveal() 现在与 hasBlockingSession() 一样排除 displaySuppressedSessionIds。此前它会选中排在前面但不上岛面的静音任务,导致 dismissPublishedBlockingReveal() 因 id 不一致拒绝 dismiss——点岛外只收起 hover,可见的确认卡一直展开。

判定超范围一条:把执行机的静音位投影进 SESSION_ACTIVITY、让控制端也不提醒,属于跨设备协议与产品语义变更(PR 描述已写明不含跨设备静音,远端任务也不显示该菜单项)。已在 thread 里说明并在 #6230 里另立需求。

验证

  • npx vitest run --project standard(notificationService / agent-island / device-link / maker-ipc / scheduler notifier / sidebar / agentIslandSessionPatch / migrationReplay)→ 10253 passed
  • 新增两条用例在修复前分别以 expected "spy" to be called once, but got 0 times 与 expected false to be true 失败,确认非空跑
  • pnpm --filter desktop typecheck ✅;pnpm --filter desktop db:validate ✅;pnpm check:dco ✅

CI:15 项全绿(含之前红过的 Linux/Windows unit tests (3/4)——那条 useVoiceInput.startup 是本分支零改动的 main 侧用例,本轮未再现),当前 MERGEABLE / BLOCKED,只差维护者 Approve。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

产品、规则与架构范围确认:认可当前 PR 先交付本机任务级消息免打扰,接受本轮不做跨设备静音同步及共享群通知豁免,同意解除 #6248 的维护者确认门。后续代码审查、迁移和通知链路验证按仓库流程继续。

@MagicLizi

Copy link
Copy Markdown
Contributor

确认任务级「消息免打扰」的产品行为与当前实现范围,同意推进。

  • 本机任务静音后,个人通知横幅、提示音、灵动岛、手机与飞书提醒停止;任务继续执行,实时活动、任务内未读、角标及确认卡片保留。
  • 本轮接受仅本机生效,不同步另一台控制电脑的静音状态;另一台电脑仍可能独立提醒。跨设备统一免打扰留待后续需求,不要求本 PR 扩展协议。
  • 自动化的共享群通知不跟随个人静音;接受启动或切号时索引尚未加载的短窗口内仍可能收到提醒,不将其承诺为任何时刻都绝不提醒。

本次 Approve 确认 #6248 涉及的产品、规则与架构范围。后续独立代码审查、数据库迁移和各通知出口验证继续按仓库流程推进。

@WZBbiao

WZBbiao commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bd98675e60

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

按自动审查的两条 P1 收口:

- `sessionService.patchMeta()` 在查 sticky origin 之前先放行 `notificationsMuted`:
  免打扰是本机属性(提醒由任务所在设备发,入口也对 device-link 任务隐藏),
  被控端 `patch-meta` 的 allowlist 只有 status/title/pinnedAt,隧道过去必然抛
  INVALID_PARAMS,让开关白回滚一次。
- `syncDisplaySuppression()` 只对 `sourceDeviceId === null` 的条目查本机静音索引:
  远端投影进来的任务可能与本机被静音的旧行同 id(还原/复制的库),不能拿本机
  标记压掉远端卡片与提示音。

测试:sessionService(sticky origin 下静音走本机 update、status 仍走隧道)与
agent-island device sessions(同 id 本地行静音不影响远端卡片)各一条;两条在
修复前分别以 update 未被调用、岛面为空失败。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
@MagicLizi MagicLizi added status:conflict 与目标分支有冲突(review-pr 自动维护,仅展示) and removed awaiting-discussion 等待维护者讨论(review-pr) labels Oct 27, 2026
check:test-hygiene 禁止在 beforeEach/helper 里重载模块,基线只允许该文件 2 次。
用例内 loadSessionService() 已自带一次重载,describe 级 beforeEach 多余。

顺带给 describe 补 afterEach 的 unstubAllGlobals,避免 stub 的 window 泄漏到后续用例。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
main 已占用 0134_schedule_model_location,本分支的 sessions.notifications_muted 按
database-and-migrations.md 用 db:generate 重落为 0135_tranquil_triton,SQL 不变;
migrationReplay 的回放序列断言跟到 135。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
@WZBbiao

WZBbiao commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Failed to sample tokens
ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@WZBbiao

WZBbiao commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

CI 唯一红项与本 PR 无关,记录一下供重跑参考:

Windows unit tests (3/4) 失败在 src/main/maker-host/__tests__/model-context-limit-store.test.ts > clears only the exact provider compaction policies and restores after deletion failure(expected 65 to be null)。该测试与其被测文件由 main 的 03a93eafbb 引入,本 PR 零改动;本地 macOS 上该文件 22 tests 全过。其余 14 项全绿。

自动审查(Codex)在 99499fb704 上连续返回 "We couldn't complete this review"(服务侧失败);上一轮成功审查在 bd98675e60 提出的两条 P1 已修(bf5e7feb93)并回复。当前 0 个未解决 thread。

另:本轮又把 main 同步进分支(main 占了 0134_schedule_model_location),sessions.notifications_muted 按迁移规则重落为 0135_tranquil_triton,SQL 不变。

@WZBbiao

WZBbiao commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Failed to sample tokens
ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
@WZBbiao

WZBbiao commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

已再次同步 main 到 7be4c57d7b(HEAD 65559bcf9a),15 项里 14 项绿,唯一红项与本 PR 无关,需要 rerun:

失败项:Windows unit tests (3/4) → src/main/maker-host/__tests__/model-context-limit-store.test.ts > clears only the exact provider compaction policies and restores after deletion failure,断言 expected 65 to be null(stageProviderModelCompactionClear() 没清掉 custom:quote"connection 的 65)。

证据:

  • 该测试与其被测文件由 main 的 03a93eafbb 引入,本 PR 对 maker-host/ 零改动(git diff --name-only origin/main...HEAD | grep model-context-limit-store 为空)。
  • 本地 macOS 上该文件 22 tests 全过。
  • main 在 7be4c57d7 上的 client-ci 结论是 success,即该测试在 main 的分片里能过;本 PR 多了几个测试文件改变了 shard 组成,它才在 Windows 上稳定失败(两次重跑、同一断言)。

我这边 token 只有 pull 权限,无法 rerun 检查。请维护者或自动化对 Windows unit tests 重跑;若重跑仍红,说明该测试对分片组成敏感,需要单独排查(不在本 PR 范围)。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>

# Conflicts:
#	apps/desktop/src/main/localDb/ipc/__tests__/sessionsPerTaskFlags.test.ts
#	apps/desktop/src/main/localDb/ipc/__tests__/sessionsRestoreIfArchived.test.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5a0741376f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>

# Conflicts:
#	i18n/GLOSSARY.md
codex review P2:`notification:show-session-event` 的 `channels` 与
`markAttention` 都由 renderer 自报,而 `markAttention === false` 正好跳过
「消息免打扰」门禁(并把手机通道标成 `muteExempt`)。这条 handler 之前没有任何
来源断言,插件 webview 等其它 webContents 也能调到同一个 channel。

改法:handler 入口先 `assertTrustedAppRendererEvent(event)`,不通过直接
PERMISSION_DENIED,早于 payload 校验、角标记账和任何通道发送。这是仓库里 184
个高权限 IPC 的既有口径,只放行 Cindy 自有顶层 renderer(主窗口 / 副窗口 /
右栏窗口都已登记为 app-content)。

没做的事(如实说明):「从 Main 持有的远端会话/设备关系判定豁免」做不到 ——
device-link 的远端会话镜像是 renderer 的 remoteProjectsStore,main 侧没有
session→device 的权威映射(岛上的 sourceDeviceId 也是 renderer 喂进来的)。
要让 main 自己判定,需要 main 维护一份由 peer push 派生的 session→device 登记,
属于跨设备协议语义变更,得单独裁决。所以这一位仍由 renderer 报,边界靠上面那道
来源断言;XSS 前提下的纵深防御也一并写进了代码注释。

测试:`npx vitest run --project standard src/main/__tests__/notificationService.test.ts`
(63 通过,新增「rejects a caller that is not the Cindy renderer before any channel
or badge work」:来源断言失败时不记角标、不弹 toast、不发手机/飞书);同批跑了
im / agent-island / localDb 的相关文件(434 通过);typecheck、check:test-hygiene、
check:i18n、check:i18n-glossary 均通过。

Signed-off-by: WZBbiao <16611004+WZBbiao@users.noreply.github.com>
@MagicLizi

Copy link
Copy Markdown
Contributor

PR #6244 自动代码审查报告(heavy 档)

  • PR:feat(desktop): 任务级「消息免打扰」,单条任务不再发通知 #6244 「feat(desktop): 任务级「消息免打扰」,单条任务不再发通知」
  • head 3318650f37155f90cfed3dadacfdc8acb7db0aef / base cdfec9aa5b8cd1bcd6018477b14b20cb0d7168d5(main)/ diffHash fefc3b6e…08e9
  • 分档:heavy(命中红线路径 apps/desktop/drizzle/0135_tranquil_triton.sql 等 migration 文件)
  • 审查范围:48 个文件、8729 行(其中 drizzle/meta/0135_snapshot.json 7338 行为机器生成快照,已核对与 journal/schema 对齐,不逐行评审)

Findings

没有 P0/P1。以下仅为不阻断的 P2 级观察,按口径不列为 finding、不发 thread:

  • agent-island/service.ts 的 syncDisplaySuppression() 在每次 publish() 全量遍历 state.sessions 并逐个调 setAgentIslandSessionDisplaySuppressed;岛面条目数受 TTL 约束,当前量级无碍,属可选优化。
  • localDb/__tests__/orcaTeamStore.test.ts 新增 fixture 行缩进与相邻行不一致(纯格式,不影响测试语义)。

UI 证据(非阻断提醒):本 PR 命中 UI 路径但描述未附截图 / 录屏 / HTML 界面证据(uiEvidenceMissing)。作者已给出隔离沙箱的实机操作描述(菜单文案两态、库值翻转、device-link 任务不显示入口)。建议补充改动后效果截图,便于核对与 DESIGN.md 的一致性。本次改动复用共享 DropdownMenuItem 与 menuStyles.MENU_ITEM_CLASS,未新增颜色 / 字号 / 间距 / 圆角 token,Light / Dark 由既有语义 token 覆盖(本次未做双模式实机目检)。

Rule coverage

按 rule-map 命中并读取以下规则原文及其 Review 清单,逐项结论(只审新增 / 正在修改的代码):

  1. AGENTS.md + docs/dev-rules/development-workflow.md:PR 模板三大段齐全、验证命令与结果如实列出(含预先声明的既有失败用例);改动单目的(任务级免打扰);无破坏性操作、无凭证入库。✅
  2. docs/dev-rules/database-and-migrations.md:migration 0135_tranquil_triton.sql 基于最新主干迁移链重新生成(历史撞号 0129→0132→0134→0135 的换号过程在 PR 评论有记录,未手改文件名 / journal / snapshot);SQL 单行零注释;ALTER TABLE sessions ADD notifications_muted integer DEFAULT false NOT NULL 与 schema.ts(boolean mode、notNull、default false)、snapshot、journal 表达同一结构;存量行默认未静音(migrationReplay 有回归用例);仅在隔离库 / replay fixture 上跑过未合入 migration。db:validate 六步全过(见 Verification)。companion 无改动。✅
  3. docs/dev-rules/electron-security-and-process-boundaries.md:notification:show-session-event 新增 assertTrustedAppRendererEvent(event) 来源断言(在任何副作用之前),只认 Cindy 自有 app-content 顶层 renderer;main / 副窗口均已 markAppContentWindow 登记,无合法调用方被误伤(preload 单一入口 notificationShowSessionEvent);renderer 自报的 notificationsMuted 之外,本次新增字段在 local-db:sessions:update 做真 boolean 严格校验(拒 "false" 字符串被 !! 反转);远程可编辑 allowlist REMOTE_EDITABLE_META 仍只含 status/title/pinnedAt,静音不经隧道下发。未放宽任何权限边界。✅
  4. docs/dev-rules/architecture-invariants.md + docs/dev-rules/desktop-development.md:hiddenSessionRegistry → sessionFlagRegistry 为同模块泛化(一次加载同时索引 hidden_at 与 notifications_muted),依赖方向不变;全仓已无 hiddenSessionRegistry 残留引用;main 侧通知出口收口在 notificationService / device-link / scheduler-host / im 各唯一出口,无渲染层直发。✅
  5. docs/dev-rules/credentials-and-local-storage.md:notifications_muted 落在既有 sessions 表(本地账号库),无新落盘位置、无凭证、无临时文件;测试全部用内存 / 临时库。✅
  6. docs/dev-rules/remote-and-mobile-adaptation.md:device-link 仅 sendMobileSessionNotify 加 muteExempt 可选参数(内部函数签名,不进 wire protocol),远端任务(markAttention === false / sourceDeviceId 非空)显式豁免本机静音标记,防还原 / 复制库同 id 误伤;跨设备同步明确不在本 PR 范围(维护者已确认)。无协议、无 allowlist 变更。✅
  7. UI(DESIGN.md §4 Select & Dropdown + docs/design-rules/cindy-design-system.md):菜单项复用 DropdownMenuItem / MENU_ITEM_CLASS,无自造组件、无硬编码颜色绕过 token;文案走 t(),五语 key 齐备(check-i18n 通过);两态文案「消息免打扰 / 允许消息通知」符合术语表 proposed 条目(check-i18n-glossary 无新增违规)。UI 效果证据缺失按非阻断处理(见 Findings 末段)。✅
  8. docs/product-rules/core-product-principles.md / 讨论 issue PR #6244 维护者确认请求:任务级「消息免打扰」(product / rules / arch 触发) #6248 要求逐条核对(见 Intent alignment)。✅
  9. heavy 档恶意代码与数据外发专项:
    • 本次未新增 / 升级任何第三方依赖(diff 无 package.json / lockfile 变更),无 install 钩子、无新网络端点、无新数据出口。
    • signoff.triggers 中无 security 触发,security.hardHits/softHits 均为空(阶段一内容门 pass)。
    • 新增的数据流只有:静音布尔值 renderer → 本地库 → 进程内同步索引 → 各提醒出口的早退判定;muteExempt 只维持既有远端通知行为,不新增外发。无后门 / 越权 / 渲染层或插件能力扩张。
    • security-scan.mjs --base cdfec9aa… 已执行:依赖审计按「无新增依赖」跳过;semgrep(p/javascript + p/nodejs,仅新增代码)0 条 finding,但有 5 个文件因 TypeScript 语法解析失败未覆盖(vite-env.d.ts、agent-island/__tests__/service.test.ts、botCanonicalSession.test.ts、sessionsUpdate.test.ts、mapper.ts),这部分不等于「已扫描无问题」——已由人工逐文件通读补位(mapper.ts 改动仅 3 行字段映射,测试文件为用例新增)。

Verification

在审查 worktree(detached = PR head)实际执行,保留真实退出码:

命令 结果
pnpm --filter desktop db:validate ✅ exit 0:0000..0135 sql files + journal aligned + no schema drift + scripts CJS-only + historical runtime identities frozen(136 sql / snapshot 链 id/prevId 连续)
npx vitest run src/main/localDb/__tests__/migrationReplay.test.ts src/main/localDb/ipc/__tests__/sessionsPerTaskFlags.test.ts src/main/__tests__/notificationService.test.ts src/main/scheduler-host/__tests__/notifier.test.ts src/main/localDb/__tests__/agentIslandSessionPatch.test.ts src/main/im/__tests__/desktopConfirmNotice.test.ts ✅ exit 0:6 files / 128 tests 全过
npx vitest run src/renderer/features/cc-agent/sidebar/__tests__/SessionTaskMenu.test.tsx src/renderer/features/cc-agent/sidebar/__tests__/sessionNotificationMute.test.ts src/renderer/lib/__tests__/sessionService.test.ts ✅ exit 0:3 files / 38 tests 全过
npx vitest run src/main/agent-island/__tests__/state.test.ts ✅ exit 0:168 tests 全过
npx vitest run src/main/agent-island/__tests__/service.test.ts ✅ exit 0:178 tests 全过
pnpm --filter desktop run --if-present typecheck ✅ exit 0(tsc --noEmit)
node scripts/check-i18n.mjs ✅ exit 0:五语 13997 key 一致
node scripts/check-i18n-glossary.mjs ✅ exit 0:无新增违规(18 处既有 proposed 术语告警,与本 PR 无关)
node scripts/security-scan.mjs --base cdfec9aa… ✅ exit 0:依赖漏洞扫描:本 PR 未新增依赖,无需扫描;静态扫描(semgrep,仅新增):0 条(semgrep 对 5 个文件解析失败,覆盖不完整,已人工补位,见 Rule coverage 第 9 条)

未执行项(如实说明):

  • 未跑全量 vitest --project standard(PR 作者已报告 5 个改动前即失败的既有文件并做了 stash 对照;本轮为定向验证,未复跑全量)。
  • 未做 Light / Dark 双模式实机目检与 UI 截图比对(无新增视觉 token,复用 themed 组件;PR 描述亦声明未目检)。
  • 未实机复验 toast / 提示音 / 手机 / 飞书的端到端有无对照(依赖真机与推送环境);以 4 个出口的早退判定 + 单测覆盖为证据。
  • 未运行 scripts/check-dco.mjs(DCO 由 CI 的 DCO App check 把关,client-ci 已绿)。

Intent alignment

  • 用户要什么(来源:PR 标题 / 描述、需求 按会话设置「消息免打扰」:静音通知横幅、声音、灵动岛与手机推送 #6230、讨论 issue PR #6244 维护者确认请求:任务级「消息免打扰」(product / rules / arch 触发) #6248,读取于 2026-10-28):任务右键菜单新增「消息免打扰」开关;开启后该任务不再发系统 toast / 提示音、不上 Agent 灵动岛(含运行中条目)、不推手机、不发飞书;任务继续执行,任务内未读、角标与确认卡片保留。明确边界:跨设备(device-link)任务不提供本机静音入口、不扩展协议;自动化共享群(wecomGroup)通知不跟随个人静音;启动 / 切号索引加载窗口内可能仍提醒,不承诺时刻零提醒。
  • 最初怎么做:初始实现为单提交 3602339c8de0a45f565b7b57eb75e338cf93e62b(2026-10-16,PR 创建时的完整批次,含 migration、sessionFlagRegistry 泛化、四道发送侧门、菜单项、五语文案与术语表;基线 007af518eaeb)。已实际 git show 读取该 revision 的关键文件。
  • 现在要合什么:head 3318650f3715… 的完整 diff 与关键调用链(notificationService / agent-island / device-link / scheduler-host / im / localDb / renderer 菜单与乐观更新)。
原目标 / 初始行为 最终行为与影响 代码 / 提交证据 变化依据
静音任务不发任何外向提醒(四道门) 保持,并补齐 IM 旁路(代输入 / 桌面确认提示)与公共桌面出口;发送前异步等待后二次判定 notificationService.ts、maker-ipc/register.ts(notifyInputHandoffOwner)、im/desktopConfirmNotice*.ts 审查 thread r4294910718 / r4355308323 等,作者逐条修复并 Resolve;仍服务同一目标
灵动岛:初始在 shouldNotifyAgentIslandForSession 挡在进岛前(岛态不进入) 改为「只退出展示面」(displaySuppressedSessionIds):岛面 / 菜单栏 / 提示音不出现,事件仍进状态机,侧栏实时活动 / 等待交互态 / 远端镜像保留 agent-island/state.ts、service.ts(syncDisplaySuppression / handleNotificationMuteChanged),提交 91adaaf3 维护者 MagicLizi 2026-10-27 明确确认「任务继续执行,实时活动、任务内未读、角标及确认卡片保留」;是向已确认口径收敛,非偏离
免打扰为任务属性 最终收紧为本机属性:menu 对 deviceLinkDeviceId 任务隐藏、patchMeta 不随 sticky origin 隧道、岛面抑制跳过 sourceDeviceId 非空条目、远端通知 muteExempt 豁免 sessionService.ts、SessionTaskMenu.tsx、agent-island/service.ts、device-link/index.ts,提交 bd98675e / bf5e7feb 维护者确认「仅本机生效,不要求本 PR 扩展协议」;thread r4384322512 / r4388248401 / r4388248412 已 Resolve
migration 0129 多次撞号后按 database-and-migrations.md 以主干链重落为 0135_tranquil_triton(SQL 逐字一致) drizzle/0135_tranquil_triton.sql、_journal.json、db:validate 六步 仓库规则明确要求,PR 评论有换号记录
  • 讨论结果落实(issue PR #6244 维护者确认请求:任务级「消息免打扰」(product / rules / arch 触发) #6248 + 维护者确认评论逐条核对):① 完成 / 错误 / 待确认的个人提醒全停(桌面横幅 + 声音 / 手机 / 飞书)→ 四道门 + IM 旁路均有早退且有单测;② 灵动岛完全不展示该任务(含运行中条目)→ shouldDisplaySession 过滤 + 已上岛任务收起 + 完成卡 / 阻塞卡仲裁排除,均有 state / service 用例;③ 任务继续执行、未读 / 角标 / 确认卡片保留 → markSessionNeedsAttention 在静音门之前记账、状态机不断、桌面确认卡不收;④ 三个范围取舍(跨设备不提供入口、共享群不跟、加载窗口可能提醒)全部按确认口径实现并写进代码注释 / PR 描述;⑤ issue 特别点名的「代输入与桌面专属确认的旁路 IM 发送」已补(isSuppressed 注入 + notifyInputHandoffOwner 早退,thread r4294910718 已 Resolve 并有回归用例)。全部落实,无表面应付。
  • 对照结论:一致(含已获维护者明确同意的两次口径收敛),无原意偏离、无无关扩范围。多轮 Codex / Greptile 意见(22 条 thread)全部 Resolve,逐条修复均可对应到最终 diff;Codex 本轮多次「Failed to sample tokens」为服务侧失败,其上一轮成功审查的 2 条 P1 已修并回归。核心目标可核实,无存疑项。

Overall

pass —— 没有 P0/P1。原意一致性复核完成且一致;讨论 issue 的明确要求逐条落实;维护门已由维护者 MagicLizi 的 Approve 放行(product / rules / arch 三触发 released,确认 issue #6248 已关闭),0 未解决 thread,CI 双源全绿(client-ci、pr-design-basis 均 success)。

补充提醒(不阻断):

  • 机器人静默期已超时放行:copilot-pull-request-reviewer 与 chatgpt-codex-connector 对当前 head 尚未表态,其意见可能在合并后才到;届时如有问题按后续流程跟进。
  • UI 效果证据(截图 / 录屏 / HTML)建议作者后续补充(见 Findings)。

@MagicLizi
MagicLizi merged commit 4073dd9 into makecindy:main Oct 28, 2026
15 checks passed
@MagicLizi MagicLizi removed the status:conflict 与目标分支有冲突(review-pr 自动维护,仅展示) label Oct 28, 2026
@MagicLizi

Copy link
Copy Markdown
Contributor

合了。四道门都收在发送侧、连同 id 远端任务的误伤和并发回滚这些边角都处理得很干净,审查里能看出是真推敲过的——以后一屏挂着好几个任务,终于只让要紧的那条叫人了。

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

Labels

touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) touches:large-diff 改动量较大(review-pr 自动维护,仅展示) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) touches:redline 改动碰到红线路径(updater / DB schema 等,review-pr 自动维护,仅展示) touches:rules 改动碰到规则 / 规范文档(review-pr 自动维护,仅展示)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants