Skip to content

Pulse 25.0.0

Choose a tag to compare

@github-actions github-actions released this 30 Sep 02:35
5957a24

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 个问题:
    1. 失败的工具(Claude PostToolUseFailure)也算回答了它的权限请求;
    2. 重启后已回答的等待不再变红(回答它的那次工具运行也在日志里、按顺序重放);
    3. 答案前后的并行工具不再把答案盖掉(旧的活动文件每会话只留最后一次);
    4. 进程号被别的程序复用即算会话结束;
    5. 一个 Cursor / OpenCode 进程一整天跑着很多会话:活着的进程只留住工作中与需要你的会话,空闲、
      过期的照常离开列表;
    6. 中途被打断、永远不报 Stop 的回合不再无限橙:两小时无消息转为「最近」;
    7. Claude 的 AskUserQuestion 显示问题本身、ExitPlanMode 显示计划第一行,不再是工具名;
    8. Pi 的提示没有标题时不再显示字面的 ui_prompt;
    9. pid ≤ 1 永不写进事件;
    10. Pulse 的安装标记只认整段 pulse-hook 命令(impulse-hook.sh 不是);
    11. 带注释(JSONC)的设置文件拒绝改写并说明原因;
    12. CRLF 换行原样保留;
    13. BOM 原样保留;
    14. 空的用户 hook 数组([])逐字保留;
    15. Codex 的 notify 按整条 TOML 语句识别与移除(跨行也一样);
    16. Pi 的排除词只看程序本身,pi ./pipeline.ts 仍是 Pi。
  • 另外:只提交了 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