Repository navigation
Pulse 25.0.0
25.0.0 — Reach(抵达)
这一版只做一件事:每一个真正的「需要你」都到达你一次,回答了就消失,一个键就回到提示前。
为此先做减法(Pulse 自己的记录、诊断窗口、过滤框都删了),再把 hook 事件收成一个追加式事件日志并修掉
审计出的 16 个问题,最后把「抵达」这条路从第一次打开到按下 ↩ 逐段补齐。源码从 17.5k 行降到 15.2k 行。
不兼容旧版本:旧的 attention.tsv、活动目录与 session-log.json 在启动时删除,不读、不迁移。
减法
- Pulse 不再存自己的记录。
SessionLog(session-log.json)、会话时间线、活动日志、通知审计都删了;
横幅记账改为只在内存里的WaitLedger,重启从零开始,启动时已经在等的等待是基线、不补发。 - 诊断窗口删了:设置 → Hooks 就是诊断(每个在这台 Mac 上的 Agent 一行,不在的合成一行,
「复制报告」)。托盘头部的「新鲜度」、过滤框、设置里的「终端」一节也删了。 - 一个投影:
SessionProjection与SnapshotBuilder合成一个纯值TrayState.project——
行、灯、标题、计数、新等待的边沿一次算出。 - QA 代码不进产品:夹具、截图与预览窗口搬进独立的
PulseQA可执行目标;发布的 app 只有PulseBar。 - AGENTS.md 与代码注释改为只说现在的事实;版本号只写在 CHANGELOG。
一个事件日志(Attention Protocol v5)
- 所有 hook 事件(包括每次工具运行)按顺序追加到一个文件
events.tsv:十一列 v5 行(多了tool),
只追加、0600、超过 1 MiB 按会话压缩(开着的阻塞与回答它的行永不丢)。 - 启动时先整份重放再画第一次托盘;之后按字节偏移读新行,日志被压缩重写(新一代)时整份再读、
只应用没应用过的行;读失败或读到空不重置任何状态。 - 审计修掉的 16 个问题:
- 失败的工具(Claude
PostToolUseFailure)也算回答了它的权限请求; - 重启后已回答的等待不再变红(回答它的那次工具运行也在日志里、按顺序重放);
- 答案前后的并行工具不再把答案盖掉(旧的活动文件每会话只留最后一次);
- 进程号被别的程序复用即算会话结束;
- 一个 Cursor / OpenCode 进程一整天跑着很多会话:活着的进程只留住工作中与需要你的会话,空闲、
过期的照常离开列表; - 中途被打断、永远不报 Stop 的回合不再无限橙:两小时无消息转为「最近」;
- Claude 的 AskUserQuestion 显示问题本身、ExitPlanMode 显示计划第一行,不再是工具名;
- Pi 的提示没有标题时不再显示字面的
ui_prompt; - pid ≤ 1 永不写进事件;
- Pulse 的安装标记只认整段
pulse-hook命令(impulse-hook.sh不是); - 带注释(JSONC)的设置文件拒绝改写并说明原因;
- CRLF 换行原样保留;
- BOM 原样保留;
- 空的用户 hook 数组(
[])逐字保留; - Codex 的
notify按整条 TOML 语句识别与移除(跨行也一样); - Pi 的排除词只看程序本身,
pi ./pipeline.ts仍是 Pi。
- 失败的工具(Claude
- 另外:只提交了 prompt、还没跑过工具的会话不算停滞(停滞要有工具事件为证)。
抵达
- 横幅随等待撤回。 等待被回答、被忽略或会话结束时,它的横幅从通知中心撤走(已送达与排队中的都撤);
汇总横幅在它点名的最后一个等待关上时撤走;送达途中就被回答的,一送达就撤。点一条等待已经不在的横幅
只打开托盘,不再跳到一个已经没有的提示。 - 在眼前的等待补发一次。 提示窗口当时就在最前的阻塞先只亮灯;30 秒后它还开着、而它的 App 已不在
最前,补发一次横幅(从那时起每一拍沿会话进程的父链看一次前台 App,App 还在最前就继续等)。启动时重放出的等待永不补发。 - 第一次打开有一张设置卡。 这台 Mac 上有没连接的 Agent 时,托盘唯一的提示是「在这台 Mac 上找到
Claude、Codex——连接」,排在通知授权之前,空托盘里也有。一次点击:装上 hook、请求通知授权,然后列出
剩下的事——「Codex:在 Codex 里运行 /hooks 并信任 Pulse」「已在运行的会话会在它们的下一步之后出现」,
直到「知道了」。空态改为照实的一句「已连接的 Agent 开始工作时,会话会出现在这里」。 - 一个手势。 点菜单栏与全局快捷键都打开托盘并选中最久的等待(没有就第一行),一个 ↩ 就到提示。
快捷键只提供编辑器不占用的 ⌃⌥Space、⌥⌘P,仍默认关闭;存下的 ⌘⇧P、⌘⇧U、⌃⌥P 读作关闭,需要重新选(⌘⌥P 原样保留,现在写作 ⌥⌘P)。 - 一次性的自动化提议。 第一次因终端自动化关着而只落到 App、而打开它本可以确切落到 iTerm 会话或
Terminal 标签时,行上问「下次直接跳到那个标签页——macOS 会询问你一次」[允许] [暂不]。回答过就不再问
(记在settings.json的automationOfferAnswered)。 - 文案一遍:一个概念一个词(设置、需要你、运行中、轮到你、最近、仅进程、停滞),「」引号与不带空格的
「——」;「为什么」说人话、不提 hook——「Claude 请求权限 · 4 分钟前」「在 Pulse 之前启动——下一步之后
显示详情」;汇总横幅「N 个 Agent 需要你」;preview 包写「ad-hoc 签名 · 未公证」,不再写「未签名」;
版本不一致的提示不再让用户去跑打包脚本。surface_check.py拒绝任何含 hook 的explain*文案。 - 「复制报告」多写两件事:全局快捷键与它是否注册成功、自动化提议是否已回答。
已知的不确定
- 没有在真机上验证。 这一版的横幅撤回、30 秒补发、设置卡与自动化提议都只有单元测试与截图夹具,
没有在一台真的 Mac 上跑过 Notification Center、TCC 自动化询问与各家终端。 - Cursor 的 hook 形状最不确定:它对照的是文档而不是源码,而那份文档在构建环境里打不开,事件名与字段
是按第三方的类型绑定核对的;漂移时它最可能先坏。 - 20 秒宽限:阻塞后 20 秒内结束的回合先暂存;拒绝后灯会多红到宽限期满,才落到「轮到你」。
- 30 秒补发靠时钟一拍:30 秒内的等待让时钟每 5 秒走一拍(省电模式 10 秒),补发最多晚几秒;
如果 App 一直在最前而你早已离开座位,它就一直不补发——Pulse 只知道前台是谁,不知道你在不在看。 - 启动前就在跑的会话在它的下一个事件之前只显示为「仅进程」,没有标题、问题与时间。
- 自己写的桥接脚本必须往
events.tsv一次追加整行 v5(十一列);v4 行与半行都不读。
Gatekeeper
This build is ad-hoc / unnotarized (no Apple Developer ID in CI).
About stays preview — it is not Gatekeeper-ready and must not be
described as notarized stable. First open: Control-click → Open, or
xattr -dr com.apple.quarantine /Applications/Pulse.app.
Download verification
808c960aa0f943f30d32090006e6b442a22fac72b022e02fa12719163be5a8c4 zig-out/package/pulse-25.0.0-macos-PulseBar.dmg