docs: README 补上验收清单、盯梢、关窗即结束
这三块是这个工具最不一样的地方,而 README 的功能列表里一条都没有 —— 一个开源项目最该讲清楚的恰恰是"它和别的有什么不同"。 - 验收清单:要点来源分级、Stop 拦截逼报证据、拿真实 diff 旁路复核、 为什么只有两档没有"部分完成"、以及"它压根不提的事没人查"那条独立路径。 自跑验收命令的三道闸(白名单/拒元字符/默认关+逐条授权)也写明。 - 会话观察者:讲清楚它治的是"做浅"不是"停了",三种追问怎么交替, 以及三条实机撞出来的硬约束(只有 busy 算干活、打字时不发、画面在变不打扰)。 - 关窗即结束:四条边界都写上,尤其"只记接得回来的"和"绑不到 pane 的不碰"。 - 项目管理:补上右键菜单、「添加目录」和扫描的分工、失效项目为什么静默有害。 所有数字和行为都对着代码核过(白名单取自 AcceptanceVerifier.whitelist, 节奏取自 SessionWatchdog 的 needStreak/cooldown/interval)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
c6dccca3d4
commit
a8707ba6be
1 file changed
+101
@@ -7,6 +7,8 @@ Claude Code 本地开发调度中心。用一个 Claude 窗口管理所有项目
|
||||
- **灵动岛** — MacBook 刘海变成 agent 控制中心,Liquid Glass + 状态驱动的像素小人
|
||||
- **实时会话监控** — 每个 Claude 会话的 `busy / waiting / shell / idle` 状态一眼可见
|
||||
- **精准跳转** — 点通知或点会话,直接跳到那个会话所在的终端 tab(不是"跳到 iTerm 然后自己找")
|
||||
- **验收清单** — 从你的原话和批准过的计划里拆出要点,跨会话累积;它说做完了,拿真实 git diff 复核
|
||||
- **会话观察者(盯梢)** — 它停下来就追问,问的是它不想被问的那些:落到哪个文件了、发布后还在不在
|
||||
- **高风险审批** — 不可逆操作(`rm -rf /`、force push 到 main 等)在岛上拦截确认
|
||||
- **tmux 多项目管理** — 每个项目一个 tmux 窗口,iTerm2 标签页体验
|
||||
- **用量统计** — 按项目查看 token 消耗、会话数、模型分布
|
||||
@@ -212,6 +214,80 @@ bash scripts/release.sh # 跑测试 → universal 编译 → 签名
|
||||
|
||||
`kind: bg` 的会话跑在 daemon 下、不在任何终端里,改为定位到显示它的 `claude agents` 查看器 tab。
|
||||
|
||||
## 验收清单
|
||||
|
||||
解决的不是「它有没有回答」,是**「它有没有做」**。
|
||||
|
||||
同时开五六个会话时,真正的成本不是等待,是**核对**。每个会话结束时都会给一份看起来很完整的报告,而你没有精力逐个去仓库里翻。清单把这件事变成可数的。
|
||||
|
||||
### 要点从哪来
|
||||
|
||||
不是 Claude 自己列的 todo —— 那份天然会漏掉它不想做的事。要点按来源分级:
|
||||
|
||||
| 来源 | 说明 | 权威性 |
|
||||
|------|------|--------|
|
||||
| `plan` | 你批准过的计划里拆出来的 | 最高 |
|
||||
| `userPrompt` | 你的原话里拆出来的 | 高 |
|
||||
| `inferred` | 推导出的隐含项(改了 A 就得同步 B),你没明说,所以单独标出来 | 中 |
|
||||
| `claudeTodo` | Claude 自己列的 todo | 参考 |
|
||||
| `manual` | 你手敲的 | — |
|
||||
|
||||
按项目累积、跨会话保留。上下文被压缩、会话被 resume,清单都还在 —— **这套系统存在的理由就是「压缩会让人忘事」**。
|
||||
|
||||
### 它说做完了之后
|
||||
|
||||
Stop hook 拦下收工那一刻,要它逐条报证据(哪个文件、哪几行)。然后走**旁路复核**:拿真实的 `git diff` 去对,说辞只用来定位该看哪几个文件,**以 diff 为准**。
|
||||
|
||||
结论只有两档,`confirmed` 和 `disputed`,没有"部分完成":
|
||||
|
||||
| 状态 | 含义 |
|
||||
|------|------|
|
||||
| 待验收 | 还没报过 |
|
||||
| 已验收 | 自报做完,且 diff 里找得到对应改动 |
|
||||
| **疑似未做** | **自报做完了,但真实 diff 里找不到** |
|
||||
|
||||
刻意不留中间档。有"部分完成"的话,模型会一律往那一档躲,产出一个什么都没说的结论;逼它二选一、拿不准算 `disputed`,代价只是让人多看一眼。
|
||||
|
||||
还有一档更隐蔽的漏:**它压根不提的事情,没有任何东西会去查**。所以另有一条独立的路 —— 直接去仓库里搜(commit 信息、改动文件名、现有文件名三处),一点痕迹都没有的会被单拎出来问。
|
||||
|
||||
### 让 Hub 自己跑验收命令(默认关)
|
||||
|
||||
开了之后 Hub 可以自己跑 `swift test` 之类来验证,而不是听它说"测过了"。这是全案唯一会执行命令的功能,三道闸缺一不可:
|
||||
|
||||
1. **白名单**:argv 开头必须完全匹配(`swift test`、`npm run`、`go test`、`bash scripts/`、`git diff/status/log` 等)。刻意排除 `npx` / `pnpm dlx`(会下载执行任意包,白名单等于形同虚设)、`npm install`(有副作用)、git 的一切写操作。
|
||||
2. **拒绝 shell 元字符**:不做转义,直接拒。配合 `execve` 执行,不经过 shell。
|
||||
3. **默认关 + 逐条授权**:总开关默认 off;开了之后每条新命令首次执行前还要你在验收页点「允许」。
|
||||
|
||||
## 会话观察者(盯梢)
|
||||
|
||||
给某个项目打开盯梢后,它停下来就会被追问,直到活真的干透。
|
||||
|
||||
### 它解决的不是「停了」,是「做浅了」
|
||||
|
||||
只会说「继续」的盯梢能防它停,防不了它**每次都继续、每次都做表面功夫**,最后交一份看起来很完整的报告。所以追问是一份轮换的清单,每条都是一个它不想被问的角度:
|
||||
|
||||
> 这轮的产出具体落到了哪些文件?给完整路径。答不上路径就说明只写了结论没落地。
|
||||
>
|
||||
> 你落的那些改动,下一次构建/发布之后还在不在?不确定就去看构建脚本,别猜。
|
||||
>
|
||||
> 你自己列的 todo 逐条对一遍:哪些真做完了、哪些只是勾了框?
|
||||
|
||||
三种追问交替发:**通用清单**(上面这些,可以在设置里换成你自己的)、**从验收清单当场生成的具体条目**("你说做完了「X」,但真实 diff 里找不到,具体是哪个文件的哪几行?")、以及**针对它刚说的那段话临时想的问题**。
|
||||
|
||||
只问通用的,几轮之后它就摸清套路、答案越来越像模板;只问清单又变成对答案。
|
||||
|
||||
### 三条硬约束(都是实机撞出来的)
|
||||
|
||||
1. **只有 `busy` 算在干活。** `shell` 表示挂着后台 shell,和它在不在思考无关 —— 早期把它当成在干活,会话停了 20 分钟一次没催到。
|
||||
2. **你在输入框里打字时绝不发。** 注入是往当前光标位置敲字,会直接拼到你没发完的那句后面,改变你本来要说的意思。
|
||||
3. **画面在变就不打扰。** 慢命令往外吐输出时状态可能是 `shell`、转圈符号可能被滚屏顶掉,但画面一直在变 —— 这比"有没有转圈符号"可靠得多。
|
||||
|
||||
### 节奏
|
||||
|
||||
Stop hook 一报收工就判断(等 12 秒,给你留出插话的时间),45 秒轮询作兜底。两次追问之间至少隔 3 分钟 —— 它读完一条要想一会儿,催太密就是打断。发送分两步:先文字、停一下、再回车,合在一起时终端偶尔会把回车吃进上一段输入里,看起来催过了其实一个字没送。
|
||||
|
||||
**默认全关。** 它会往你的终端里敲字,装上 Hub 的人不该在不知情时被自动插话。
|
||||
|
||||
## 高风险操作审批
|
||||
|
||||
`PreToolUse` hook 会拦截**不可逆**操作,在岛上弹出审批:
|
||||
@@ -247,6 +323,31 @@ bash scripts/welcome.sh
|
||||
|
||||
主窗口的「项目」页也能直接扫描、搜索、按 8 种模式启动(Claude Code / 跳过权限 / 纯终端 / 继续上次会话 / 选择历史会话 / Finder / VS Code)。
|
||||
|
||||
**右键任意项目行**就能弹出这个菜单,岛和主窗口用的是同一份内容。
|
||||
|
||||
### 「添加目录」和扫描的分工
|
||||
|
||||
扫描只认有 `.git` 的目录,而且**撞到 `.git` 就停止下钻**。所以 monorepo 里的子目录、还没 git init 的目录永远扫不进来 —— 那类项目用「添加目录」手工选,不限于 git 仓库。
|
||||
|
||||
### 失效项目
|
||||
|
||||
目录被删掉之后,清单里那条不会自己消失,而且它是**静默有害**的:`tmux` 对不存在的 `-c` 目录**返回 0 并悄悄用家目录**,`open` 则什么都不做。表现出来就是「Finder 没反应」+「Claude 开到了 `~`」,看起来像界面坏了。
|
||||
|
||||
所以目录没了的项目会被标出来(岛上尤其必要 —— 那里不显示路径),右键菜单只留「从列表移除」,工具栏出现「清理失效 N」。**只动清单,不碰磁盘上的任何文件。**
|
||||
|
||||
## 关掉终端窗口就结束会话
|
||||
|
||||
tmux 的默认语义是「关窗口 = detach,进程照跑」。这对跑长活是对的,但和人的直觉相反:你关掉窗口就是干完了,之后在界面上看到「1 个会话」亮着,只会认为界面在撒谎。
|
||||
|
||||
打开这个开关(默认开,设置里可关)后,检测到没有终端连着就结束它。四条边界:
|
||||
|
||||
- **结束前先把 sessionId 记进名册**,项目行和右键菜单出现「接着上次」,一键 `claude --resume` 回到原来的上下文。
|
||||
- **只记接得回来的**。`--resume` 认的是磁盘上那份 transcript,不是 id 本身;一次都没说过话的会话没有 transcript,记了只会长出一个点下去报错的按钮。
|
||||
- **绑不到 tmux pane 的一个都不碰**。不在 tmux 里的会话(VS Code 扩展、直接开的终端、后台任务)判断不了"有没有终端连着",杀它们等于拿"不知道"当处决理由。
|
||||
- **新起的会话 90 秒宽限 + 连续两轮确认**。建会话是先建 detached 再让终端 attach 的,iTerm 冷启动那几秒客户端数就是 0 —— 没宽限期会把你刚点开的项目当场杀掉。
|
||||
|
||||
关掉开关则什么都不杀,只在项目行上标成「终端已关」。
|
||||
|
||||
## 开发
|
||||
|
||||
```bash
|
||||
|
||||
Reference in new issue
Block a user