- commit
- 68a85cf
- parent
- d8e883d
- author
- codex@macbookpro
- date
- 2026-04-03 11:47:47 +0800 CST
chore: remove legacy watchdog a11y flow
11 files changed,
+90,
-284
Raw patch view.
1diff --git a/plans/A11Y_GUI_CONTROL.md b/plans/A11Y_GUI_CONTROL.md
2index 737ec75c9eb2942b25da314e9783362d6026a3b4..dfcffbf072e5fc8ef8beeb15a2c1ad4dfb11fc27 100644
3--- a/plans/A11Y_GUI_CONTROL.md
4+++ b/plans/A11Y_GUI_CONTROL.md
5@@ -1,9 +1,11 @@
6-# A11Y GUI Control — 基于无障碍树的浏览器与操作系统控制
7+# A11Y GUI Control — 基于无障碍树的浏览器与操作系统控制(历史归档)
8
9 > 日期: 2026-03-30
10-> 状态: 验证完成,待开发
11+> 状态: 历史归档(探索记录,非当前需求)
12 > 参与: Claude (验证执行) + George (架构指导)
13
14+> 说明:本文保留当时对通用 a11y / GUI 控制的探索记录。基于 Safari 的 `a11y_msg.sh` / watchdog 续命脚本已于 2026-04-03 随 `T-S074` 从仓库移除;当前正式续命主线只有 conductor renewal。若未来重启通用 a11y host-ops 能力,应另开新任务,不直接把本文视为 active requirement。
15+
16 ---
17
18 ## 核心思路
19@@ -136,7 +138,7 @@ george@Mac Desktop % proxy_on"
20
21 ---
22
23-## 开发计划
24+## 当时设想的开发计划
25
26 ### Phase 1:conductor a11y 端点
27
28@@ -199,7 +201,7 @@ Claude → conductor → a11y/tree(Safari, ChatGPT页面) → 读对话
29
30 ---
31
32-## 与现有架构的关系
33+## 当时设想与现有架构的关系
34
35 - **baa-conductor**:a11y 端点作为新的 host-ops 类端点,与 exec/files 同级
36 - **BAA 指令系统**:a11y 工具注册为 conductor 的 tool,AI 通过 baa 代码块调用
37@@ -219,7 +221,7 @@ Claude → conductor → a11y/tree(Safari, ChatGPT页面) → 读对话
38
39 ---
40
41-## 补充:续命机制与看门狗模式(2026-03-30 验证)
42+## 补充:历史续命探索与看门狗模式(2026-03-30 记录,已废弃)
43
44 ### 左右手互博验证
45
46@@ -245,7 +247,7 @@ tk_conductor Claude (Safari)
47 - 改为轻量版:直接 `keystroke "v" using command down` + `keystroke return`,不扫描元素
48 - 发送方式统一用剪贴板粘贴 + 回车,不依赖找 Send 按钮
49
50-### 轻量版 a11y_msg.sh
51+### 当时使用的轻量版 a11y_msg.sh(脚本已删除)
52
53 ```bash
54 #!/bin/bash
55@@ -267,7 +269,7 @@ osascript -e 'tell application "System Events" to tell process "Safari"
56 end tell'
57 ```
58
59-### 看门狗模式(设计,待实现)
60+### 看门狗模式(历史设计,未实现,已废弃)
61
62 三个 Claude 标签页:A(主工作)、B(思考工具)、C(看门狗)
63
64diff --git a/plans/STATUS_SUMMARY.md b/plans/STATUS_SUMMARY.md
65index 655c6e8b4fe57224e73f0685c48a6dcbdf6c9917..ac2cfd4917e6716d6e6f8fc5946922b0a8b081ba 100644
66--- a/plans/STATUS_SUMMARY.md
67+++ b/plans/STATUS_SUMMARY.md
68@@ -2,11 +2,11 @@
69
70 ## 当前时间
71
72-- `2026-04-01`
73+- `2026-04-03`
74
75 ## 当前代码基线
76
77-- 当前主分支:`main@ffda03b`
78+- 当前主分支:`main@d8e883d`
79 - canonical local API:`http://100.71.210.78:4317`
80 - canonical public host:`https://conductor.makefile.so`
81 - 活跃任务文档和近期刚完成的任务文档保留在 `tasks/` 根目录;较早已完成任务归档到 [`../tasks/archive/README.md`](../tasks/archive/README.md)
82@@ -57,6 +57,12 @@
83 - BAA instruction policy 现在已支持默认配置与自定义 allowlist,后续 automation control 指令扩面不再依赖硬编码集合
84 - Claude final-message 现在已补更稳的 SSE fallback,主路径字段漂移时仍能回退到稳定提取
85 - renewal 模块公共 helper 已收口到统一 `utils`,projector / dispatcher / automation 不再重复维护同类逻辑
86+- 当前正式续命链路只保留 conductor renewal:
87+ - `browser.final_message` ingress
88+ - renewal projector
89+ - renewal dispatcher
90+ - `browser.proxy_delivery`
91+ - 旧 watchdog / Safari a11y 续命方案已随 `T-S074` 从仓库移除
92
93 ## 当前已纠正的文档/代码不一致
94
95@@ -73,17 +79,17 @@
96 - `T-BUG-029` / `T-BUG-031` 的任务卡已完成,但旧汇总文档仍把它们写成 pending manual verification;现统一改为“建议补做浏览器复核”
97 - Artifact 静态服务已经完成,不再把它写成“下一阶段主线”
98 - `T-S050` 曾引入 stagit repo 静态页,但该能力已迁到 `baa-pgit`,当前仓库内残留实现已随 `T-S073` 删除
99+- 旧 watchdog / Safari a11y 续命方案此前仍以“可继续保留/重写”的口径留在根目录计划文档中;现已随 `T-S074` 删除旧代码,并统一降级为历史方案
100
101 ## 当前最高优先级
102
103 **当前下一波任务:**
104
105-- [`../tasks/T-S074.md`](../tasks/T-S074.md):删除旧版 watchdog 与 Safari a11y 续命方案
106-- Web UI 主线 `T-S070 -> T-S071 -> T-S072` 保持下一顺位
107+- Web UI 主线 `T-S070 -> T-S071 -> T-S072`
108
109 其余没有 open bug / open opt。
110
111-如继续推进,建议先完成 `T-S074`,之后回到 Web UI 主线,再根据新需求或代码审查结果继续拆任务。
112+如继续推进,建议直接回到 Web UI 主线;旧 watchdog / Safari a11y 续命方案已随 `T-S074` 删除,当前正式续命链路只保留 conductor renewal。
113
114 **并行优化项:**
115
116@@ -98,6 +104,7 @@
117 - 当前 open bug 见 [`../bugs/README.md`](../bugs/README.md)
118 - 当前没有 open `MISSING-*` blocker
119 - 其余 backlog 仍以 `OPT-*` 为主
120+- 历史文档中仍会保留 watchdog / a11y 关键词,但不代表当前 active 方案
121
122 ## 当前活跃需求文档
123
124@@ -113,6 +120,9 @@
125 - [`./NEXT_WAVE_REQUIREMENTS.md`](./NEXT_WAVE_REQUIREMENTS.md)(历史需求视图)
126 - [`./TONIGHT_SPRINT.md`](./TONIGHT_SPRINT.md)(历史冲刺计划)
127 - [`../HANDOFF.md`](../HANDOFF.md)(历史交接记录)
128+- [`./WATCHDOG_LOGGING_ENHANCEMENT.md`](./WATCHDOG_LOGGING_ENHANCEMENT.md)(历史 watchdog V1 需求记录,代码已删除)
129+- [`./WATCHDOG_V2_CONDUCTOR_INTEGRATED.md`](./WATCHDOG_V2_CONDUCTOR_INTEGRATED.md)(历史 watchdog V2 设计草案,未落地)
130+- [`./A11Y_GUI_CONTROL.md`](./A11Y_GUI_CONTROL.md)(历史 Safari a11y / GUI 控制探索)
131 - [`./BAA_ARTIFACT_DOWNLOAD_REQUIREMENTS.md`](./BAA_ARTIFACT_DOWNLOAD_REQUIREMENTS.md)
132 - [`./ARTIFACT_STATIC_SERVICE.md`](./ARTIFACT_STATIC_SERVICE.md)(主线已完成,保留实现参考)
133
134@@ -125,6 +135,7 @@ Phase 1(浏览器主链)、Artifact 静态服务,以及 timed-jobs + 续
135 - 当前主线已无 open bug blocker
136 - `browser.chatgpt` / `browser.gemini` helper target 与 Gemini DOM delivery adapter 已在主线
137 - 当前这轮 backlog 已全部收口;自动化仲裁、统一浮层控制、系统级暂停、重启后风控恢复、delivery 可靠性增强和 policy 配置化均已完成
138+- 当前正式续命链路只保留 conductor renewal;旧 watchdog / Safari a11y 续命方案已删除
139
140 之前的浏览器主链继续保持:
141
142@@ -143,4 +154,4 @@ Phase 1(浏览器主链)、Artifact 静态服务,以及 timed-jobs + 续
143 - recent relay cache 是有限窗口;极老 replay 超出窗口后,仍会落回 conductor dedupe
144 - `status-api` 继续保留为显式 opt-in 兼容层,不是当前删除重点
145 - 远端 `baa-conductor-artifact` 已在 `2026-04-01` 应用 [`../packages/d1-client/src/d1-setup.sql`](../packages/d1-client/src/d1-setup.sql);后续如新建或重置 D1 环境,仍需执行同一 schema 初始化脚本
146-- 当前仓库内的旧 watchdog / a11y 续命方案计划由 `T-S074` 直接删除
147+- 历史文档中仍保留旧 watchdog / a11y 讨论;这是保留演进记录的有意行为,不代表仓库仍保留该方案
148diff --git a/plans/TONIGHT_SPRINT.md b/plans/TONIGHT_SPRINT.md
149index 3c36311d9df6dfabd1a3cd414bd60c5fd326dc75..8b13bf06c82296b4d5c95de1634611db34807013 100644
150--- a/plans/TONIGHT_SPRINT.md
151+++ b/plans/TONIGHT_SPRINT.md
152@@ -5,7 +5,7 @@
153 > 执行: Codex (写代码) / Claude Code (小改动/文档)
154 > 看门狗: watchdog.sh (后台,60秒间隔)
155
156-> 状态: 历史冲刺计划。当前代码进度以 `tasks/TASK_OVERVIEW.md` 和 `plans/STATUS_SUMMARY.md` 为准。
157+> 状态: 历史冲刺计划。当前代码进度以 `tasks/TASK_OVERVIEW.md` 和 `plans/STATUS_SUMMARY.md` 为准;其中 watchdog 相关步骤已于 `T-S074` 删除,仅保留历史记录。
158
159 ---
160
161diff --git a/plans/WATCHDOG_LOGGING_ENHANCEMENT.md b/plans/WATCHDOG_LOGGING_ENHANCEMENT.md
162index 21c3d9fac562aef251f38dd1745c38dc1197c12b..c79d37fbfe3e7d9ec51327b2301d7db8668dd689 100644
163--- a/plans/WATCHDOG_LOGGING_ENHANCEMENT.md
164+++ b/plans/WATCHDOG_LOGGING_ENHANCEMENT.md
165@@ -1,20 +1,21 @@
166-# 看门狗日志增强需求
167+# 看门狗日志增强需求(历史归档)
168
169 > 日期:2026-03-31
170-> 优先级:`低`(当前续命主力已切到 API 代理方式,watchdog 仅作兜底脚手架)
171-> 状态:`需求记录`
172-> 来源:原 `T-S060`,降级为需求文档
173+> 状态:`历史归档(T-S074 已移除旧实现)`
174+> 来源:原 `T-S060`,后续降级为需求文档
175
176-## 背景
177+> 说明:本文仅保留旧版 watchdog V1 的需求记录。自 2026-04-03 起,`tools/watchdog/` 已从仓库删除;当前正式续命链路只保留 conductor renewal(`browser.final_message` ingress → renewal projector → renewal dispatcher → `browser.proxy_delivery`)。
178+
179+## 历史背景
180
181 仓库 `tools/watchdog/` 下有两个脚本:
182
183 - `watchdog.sh`:轮询心跳文件,判断是否需要续命
184 - `a11y_msg.sh`:通过 macOS 辅助功能 API(osascript)操控 Safari 发消息
185
186-这是早期的 GUI 续命方案(V1),依赖 Claude 手动设心跳状态。当前续命主力已切到 conductor renewal(API 代理方式:projector + dispatcher + Firefox proxyDelivery),watchdog 降为兜底脚手架。
187+这是早期的 GUI 续命方案(V1),依赖 Claude 手动设心跳状态。该方案最终没有继续保留;当前正式续命主力已切到 conductor renewal(API 代理方式:projector + dispatcher + Firefox proxyDelivery),watchdog 也不再作为兜底脚手架存在。
188
189-## 当前问题
190+## 当时记录的问题
191
192 ### `a11y_msg.sh`
193
194@@ -28,7 +29,7 @@
195 1. Python 解析心跳文件失败时(`ST="error"`),主循环没有显式 FAIL 日志
196 2. CHECK 日志已比较完整,续命后也记录了 `a11y_rc`,这部分基本到位
197
198-## 需求
199+## 原始需求记录
200
201 ### 1. `a11y_msg.sh` 日志增强
202
203@@ -49,20 +50,19 @@
204 - 不清空 `wake_at` / `max_wake_at`
205 - 不引入旧版 `origin/feat/watchdog-logging` 分支的状态机回退
206
207-## 允许修改的目录
208+## 原计划修改目录
209
210-- `tools/watchdog/`
211+- `tools/watchdog/`(现已删除)
212
213-## 为什么优先级低
214+## 归档说明
215
216-- 续命主力已切到 conductor renewal(API 代理),不依赖 watchdog
217-- watchdog 仅在 conductor 链路完全断裂时作为最后保险
218-- 当前 watchdog 功能正常,只是出错时排障困难
219-- 不阻塞任何主线功能
220+- 正式续命主线已切到 conductor renewal(API 代理),不依赖 watchdog
221+- 旧 watchdog / a11y 代码已随 `T-S074` 删除
222+- 如未来需要新的 host-level 兜底续命能力,应重新立项,不延续本文方案
223
224 ## 关联
225
226 - 原任务卡:`T-S060`(已撤回)
227-- watchdog V1 代码:`tools/watchdog/watchdog.sh`、`tools/watchdog/a11y_msg.sh`
228-- watchdog V2 设计:[`WATCHDOG_V2_CONDUCTOR_INTEGRATED.md`](./WATCHDOG_V2_CONDUCTOR_INTEGRATED.md)(事件驱动方案,同样搁置)
229+- 原 watchdog V1 代码:`tools/watchdog/watchdog.sh`、`tools/watchdog/a11y_msg.sh`(均已删除)
230+- watchdog V2 设计:[`WATCHDOG_V2_CONDUCTOR_INTEGRATED.md`](./WATCHDOG_V2_CONDUCTOR_INTEGRATED.md)(历史事件驱动草案,未落地)
231 - 续命主力:`apps/conductor-daemon/src/renewal/`(projector + dispatcher)
232diff --git a/plans/WATCHDOG_V2_CONDUCTOR_INTEGRATED.md b/plans/WATCHDOG_V2_CONDUCTOR_INTEGRATED.md
233index 94bf2c1ed11ea2a95ebc6162946ae3ce82042a69..50decf602cc90fa2cde7f347b01056281f4eef45 100644
234--- a/plans/WATCHDOG_V2_CONDUCTOR_INTEGRATED.md
235+++ b/plans/WATCHDOG_V2_CONDUCTOR_INTEGRATED.md
236@@ -1,19 +1,21 @@
237-# Watchdog V2 — Conductor 集成方案
238+# Watchdog V2 — Conductor 集成方案(历史归档)
239
240 > 日期: 2026-03-30
241-> 状态: 方案设计
242+> 状态: 历史归档(未落地,T-S074 已移除旧 watchdog)
243
244-## 问题
245+> 说明:本文保留当时对事件驱动 watchdog V2 的设计草案。该方案最终没有进入当前主线;自 2026-04-03 起,仓库已删除旧版 watchdog / Safari a11y 续命实现,正式续命链路只保留 conductor renewal。
246+
247+## 当时要解决的问题
248
249 当前看门狗依赖 Claude 手动设心跳文件状态(working → waiting),Claude 经常忘记,导致续命失效。
250
251-## 核心洞察
252+## 当时的核心洞察
253
254 Conductor 已拦截每个 AI 的 SSE final-message。收到 final-message = AI 回复结束 = 需要续命。
255
256 **不需要 Claude 手动设状态,conductor 天然知道。**
257
258-## 链路
259+## 历史链路设想
260
261 ```
262 Claude 回复结束
263@@ -26,11 +28,11 @@ Claude 回复结束
264 → 通过 a11y 给 Safari 对话页发续命消息
265 ```
266
267-## 实现位置
268+## 当时设想的实现位置
269
270 `firefox-ws.ts` 的 `handleBrowserFinalMessage` 末尾,或 `ingest.ts` 的 `ingestAssistantFinalMessage` 末尾。
271
272-## 配置
273+## 当时设想的配置
274
275 ```typescript
276 interface WatchdogConfig {
277@@ -44,7 +46,7 @@ interface WatchdogConfig {
278 }
279 ```
280
281-## 逻辑
282+## 当时设想的逻辑
283
284 ```typescript
285 let lastRenewalTime = 0;
286@@ -63,14 +65,14 @@ function onFinalMessage(platform: string, conversationId: string) {
287 }
288 ```
289
290-## 触发条件
291+## 当时设想的触发条件
292
293 1. watchdog enabled
294 2. final-message 来自指定平台
295 3. 距上次续命超过冷却期
296 4. 可选:匹配 conversationId
297
298-## 对比
299+## 方案对比(历史记录)
300
301 | | V1(当前) | V2(本方案) |
302 |---|---|---|
303@@ -81,11 +83,11 @@ function onFinalMessage(platform: string, conversationId: string) {
304 | 失败模式 | 忘设状态→永不续命 | SSE 链路通就续命 |
305 | 复杂度 | 心跳+状态机+进度文件 | 一个 hook + setTimeout |
306
307-## V1 保留为兜底
308+## 历史说明:当时曾设想 V1 作为兜底
309
310-V2 依赖 SSE 链路(插件→WS→conductor),链路断了 V2 不工作。V1 独立于 conductor,作为最后保险。
311+该设想最终未采用。2026-04-03 起,V1 与 V2 均不再保留;当前仓库只保留 conductor renewal 主链。
312
313-## 实现步骤
314+## 当时设想的实现步骤
315
316 1. conductor-daemon 加 watchdog 配置读取
317 2. ingest/firefox-ws 加 final-message hook
318@@ -93,7 +95,7 @@ V2 依赖 SSE 链路(插件→WS→conductor),链路断了 V2 不工作。
319 4. 加开关端点:POST /v1/watchdog/enable, /disable
320 5. 测试验证
321
322-## 风险
323+## 当时识别的风险
324
325 - conductor 和 Safari 不在同一台机器时不工作(a11y 是本机操作)
326 - osascript 在 node 子进程可能有 TCC 权限问题
327diff --git a/tasks/T-S074.md b/tasks/T-S074.md
328index 1af586cbb75c5696d68400f207275940f030064e..d4010dccfdc6fb5485e4b9b965ddb97bc54cb61b 100644
329--- a/tasks/T-S074.md
330+++ b/tasks/T-S074.md
331@@ -2,7 +2,7 @@
332
333 ## 状态
334
335-- 当前状态:`待开始`
336+- 当前状态:`已完成`
337 - 规模预估:`S`
338 - 依赖任务:无
339 - 建议执行者:`Codex`
340@@ -152,22 +152,22 @@
341
342 ### 开始执行
343
344-- 执行者:
345-- 开始时间:
346-- 状态变更:
347+- 执行者:`Codex`
348+- 开始时间:`2026-04-03 11:43:07 CST`
349+- 状态变更:`待开始 -> 进行中`
350
351 ### 完成摘要
352
353-- 完成时间:
354-- 状态变更:
355-- 修改了哪些文件:
356-- 核心实现思路:
357-- 跑了哪些测试:
358+- 完成时间:`2026-04-03 11:46:41 CST`
359+- 状态变更:`进行中 -> 已完成`
360+- 修改了哪些文件:`tasks/TASK_OVERVIEW.md`、`plans/STATUS_SUMMARY.md`、`plans/WATCHDOG_LOGGING_ENHANCEMENT.md`、`plans/WATCHDOG_V2_CONDUCTOR_INTEGRATED.md`、`plans/A11Y_GUI_CONTROL.md`、`plans/TONIGHT_SPRINT.md`、`tasks/T-S074.md`,并删除 `tools/watchdog/` 下全部文件。
361+- 核心实现思路:删除 `tools/watchdog/` 旧脚本与说明,并把当前总览 / 状态 / 方案文档统一改成“仅保留历史记录,当前续命主线只有 conductor renewal”。
362+- 跑了哪些测试:`test ! -e /Users/george/code/baa-conductor-remove-watchdog-a11y/tools/watchdog && echo removed`、`git -C /Users/george/code/baa-conductor-remove-watchdog-a11y diff --check`、`rg -n "watchdog|a11y_msg|WATCHDOG_V2|A11Y_GUI_CONTROL" /Users/george/code/baa-conductor-remove-watchdog-a11y --glob '!HANDOFF.md'`、`git -C /Users/george/code/baa-conductor-remove-watchdog-a11y status --short`
363
364 ### 执行过程中遇到的问题
365
366--
367+- 无阻塞问题;主要工作是清理旧实现并统一文档口径。
368
369 ### 剩余风险
370
371--
372+- 历史文档中仍会保留 watchdog / a11y 关键词;这是为了保留演进记录,不代表仓库仍保留该方案。
373diff --git a/tasks/TASK_OVERVIEW.md b/tasks/TASK_OVERVIEW.md
374index f2756edcf887b3b0c862114003bcd8652b87d620..704310f5ec407bd56468c90df3690b3dac77e02d 100644
375--- a/tasks/TASK_OVERVIEW.md
376+++ b/tasks/TASK_OVERVIEW.md
377@@ -2,8 +2,8 @@
378
379 ## 当前基线
380
381-- 日期:`2026-04-01`
382-- 主分支基线:`main@ffda03b`
383+- 日期:`2026-04-03`
384+- 主分支基线:`main@d8e883d`
385 - canonical local API:`http://100.71.210.78:4317`
386 - canonical public host:`https://conductor.makefile.so`
387 - 当前活跃任务卡和近期刚完成的任务卡保留在本目录;较早已完成任务归档到 [`./archive/README.md`](./archive/README.md)
388@@ -55,6 +55,12 @@
389 - BAA instruction policy 现在已支持默认配置与自定义 allowlist,后续 automation control 指令扩面不再依赖硬编码集合
390 - Claude final-message 现在已补更稳的 SSE fallback,主路径字段漂移时仍能回退到稳定提取
391 - renewal 模块的公共 helper 已收口到统一 `utils`,projector / dispatcher / automation 不再重复维护同类逻辑
392+- 当前正式续命链路只保留 conductor renewal:
393+ - `browser.final_message` ingress
394+ - renewal projector
395+ - renewal dispatcher
396+ - `browser.proxy_delivery`
397+ - 旧 watchdog / Safari a11y 续命方案已随 `T-S074` 从仓库移除
398
399 ## 当前已确认的不一致
400
401@@ -73,6 +79,7 @@
402 - `T-BUG-029`、`T-BUG-031` 的任务卡已是 `已完成`,但旧文档仍把它们写成 pending manual verification;现统一改为“建议补做浏览器复核”
403 - Artifact 静态服务已经完成,不再把 `T-S039`~`T-S045` 写成“当前活跃主线”
404 - `T-S050` 曾引入 stagit repo 静态页,但该能力已迁到 `baa-pgit`,当前仓库内残留实现已随 `T-S073` 删除
405+- 旧 watchdog / Safari a11y 续命方案此前仍停留在根目录计划文档与任务队列中;现已随 `T-S074` 删除旧代码,并统一降级为历史方案
406
407 ## 当前活跃任务与优先级
408
409@@ -96,6 +103,7 @@
410 | [`T-S069`](./T-S069.md) | proxy_delivery 成功语义增强 | L | T-S060 | Codex | 已完成 |
411 | [`T-S065`](./T-S065.md) | policy 配置化 | M | 无 | Codex | 已完成 |
412 | [`T-S073`](./T-S073.md) | 移除 conductor 内的 stagit 仓库静态页能力 | M | 无 | Codex | 已完成 |
413+| [`T-S074`](./T-S074.md) | 删除旧版 watchdog 与 Safari a11y 续命方案 | S | 无 | Codex | 已完成 |
414
415 ### 当前下一波任务
416
417@@ -103,18 +111,17 @@
418
419 | 任务 | 标题 | 规模 | 依赖 | 建议 AI | 状态 |
420 |---|---|---|---|---|---|
421-| [`T-S074`](./T-S074.md) | 删除旧版 watchdog 与 Safari a11y 续命方案 | S | 无 | Codex | 待开始 |
422 | [`T-S070`](./T-S070.md) | Conductor UI 基础设施:Vue 3 脚手架与 `/app` 静态托管 | M | 无 | Codex | 待开始 |
423 | [`T-S071`](./T-S071.md) | Conductor UI 会话鉴权:登录页与浏览器 session | M | T-S070 | Codex | 待开始 |
424 | [`T-S072`](./T-S072.md) | Conductor UI `Control` 工作区首版 | L | T-S070, T-S071 | Codex | 待开始 |
425
426 当前没有 open bug / open opt。
427
428-如继续推进,建议先完成 `T-S074`,再回到 `T-S070 -> T-S071 -> T-S072` 的 Web UI 主线。
429+如继续推进,建议直接回到 `T-S070 -> T-S071 -> T-S072` 的 Web UI 主线。
430
431 说明:
432
433-- `T-S073` 已完成;`T-S074` 是剩余的仓库边界收缩任务
434+- `T-S073` / `T-S074` 已完成,仓库边界收缩已结束
435 - `T-S070` / `T-S071` / `T-S072` 仍是后续正式 Web UI 主线
436 - `Channels` 工作区和正式 `channel` 域模型继续留在 `T-S072` 之后再拆下一轮
437
438@@ -140,7 +147,8 @@
439 | T-S048 | Gemini 投递适配器 | ✅ |
440 | T-S049 | 开放 chatgpt/gemini target | ✅ |
441 | T-S050 | stagit git 静态页面 | ✅ |
442-| T-S070 | 移除 conductor 内的 stagit 仓库静态页能力 | ✅ |
443+| T-S073 | 移除 conductor 内的 stagit 仓库静态页能力 | ✅ |
444+| T-S074 | 删除旧版 watchdog 与 Safari a11y 续命方案 | ✅ |
445 | T-S052 | D1 数据库初始化 | ✅ |
446 | T-S053 | 插件诊断日志 | ✅ |
447 | T-S054 | 插件日志 WS 转发 | ✅ |
448@@ -196,18 +204,20 @@
449 - [`../plans/NEXT_WAVE_REQUIREMENTS.md`](../plans/NEXT_WAVE_REQUIREMENTS.md):历史需求视图
450 - [`../HANDOFF.md`](../HANDOFF.md):历史交接记录
451 - [`../plans/TONIGHT_SPRINT.md`](../plans/TONIGHT_SPRINT.md):历史冲刺计划
452+- [`../plans/WATCHDOG_LOGGING_ENHANCEMENT.md`](../plans/WATCHDOG_LOGGING_ENHANCEMENT.md):历史 watchdog V1 需求记录,代码已删除
453+- [`../plans/WATCHDOG_V2_CONDUCTOR_INTEGRATED.md`](../plans/WATCHDOG_V2_CONDUCTOR_INTEGRATED.md):历史 watchdog V2 设计草案,未落地
454+- [`../plans/A11Y_GUI_CONTROL.md`](../plans/A11Y_GUI_CONTROL.md):历史 Safari a11y / GUI 控制探索,不再作为当前续命方案
455 - [`../plans/BAA_ARTIFACT_DOWNLOAD_REQUIREMENTS.md`](../plans/BAA_ARTIFACT_DOWNLOAD_REQUIREMENTS.md):已废弃,保留历史决策说明
456 - [`../plans/ARTIFACT_STATIC_SERVICE.md`](../plans/ARTIFACT_STATIC_SERVICE.md):主线已完成,保留实现与验收参考
457
458 ## 当前主线判断
459
460-Phase 1(浏览器主链)、Artifact 静态服务,以及 timed-jobs + 续命主线都已完成收口。`T-S060`、`T-S061`、`T-S062`、`T-S063`、`T-S064`、`T-S065`、`T-S066`、`T-S067`、`T-S068`、`T-S069` 已全部落地;当前主线没有 open bug blocker,也没有 open opt,`T-S073` 已完成,剩余待开始任务是 `T-S074` 与后续 Web UI 主线。
461+Phase 1(浏览器主链)、Artifact 静态服务,以及 timed-jobs + 续命主线都已完成收口。`T-S060`、`T-S061`、`T-S062`、`T-S063`、`T-S064`、`T-S065`、`T-S066`、`T-S067`、`T-S068`、`T-S069` 已全部落地;当前主线没有 open bug blocker,也没有 open opt,`T-S073` / `T-S074` 已完成,剩余待开始任务只剩后续 Web UI 主线。
462
463 如果继续推进,建议:
464
465 - 远端 `baa-conductor-artifact` 已在 `2026-04-01` 应用 [`packages/d1-client/src/d1-setup.sql`](../packages/d1-client/src/d1-setup.sql) 的最新 schema;后续如新建或重置 D1 环境,仍需先执行同一脚本
466-- 再完成 `T-S074`
467-- 之后回到 `T-S070 -> T-S071 -> T-S072` 的正式 Web UI 工作台主线
468+- 直接回到 `T-S070 -> T-S071 -> T-S072` 的正式 Web UI 工作台主线
469
470 ## 现在该读什么
471
472diff --git a/tools/watchdog/.gitignore b/tools/watchdog/.gitignore
473deleted file mode 100644
474index 9eb2fd9a5bae8480a63fb95986ea22889282ff88..0000000000000000000000000000000000000000
475--- a/tools/watchdog/.gitignore
476+++ /dev/null
477@@ -1 +0,0 @@
478-watchdog.log
479diff --git a/tools/watchdog/README.md b/tools/watchdog/README.md
480deleted file mode 100644
481index 8e9cea8fbd39f385f24333ff6d215000bd433f93..0000000000000000000000000000000000000000
482--- a/tools/watchdog/README.md
483+++ /dev/null
484@@ -1,97 +0,0 @@
485-# Watchdog — Claude 对话续命看门狗
486-
487-## 原理
488-
489-1. Claude 写心跳文件 `/tmp/claude_heartbeat.json`
490-2. Claude 写进度文件 `/tmp/claude_progress.json`(当前任务、做到哪了)
491-3. 看门狗每 60 秒检查心跳,按条件续命
492-4. Claude 被唤醒后先读进度文件,接上之前的工作
493-
494-## 状态机
495-
496-| status | 含义 | 看门狗行为 |
497-|--------|------|------------|
498-| working | 干活中 | 不动(除非兜底超时) |
499-| waiting | 等待续命 | 按条件续命 |
500-| renewed | 已续命 | 不动 |
501-| paused | 暂停 | 跳过 |
502-| done | 完成 | 看门狗退出 |
503-
504-## 唤醒条件(三层,任一满足)
505-
506-1. **定时唤醒**:`wake_at > 0 && now >= wake_at`(我判断任务要10分钟就设10分钟后)
507-2. **空闲超时**:`wake_at == 0 && idle > timeout`(不确定多久,靠超时兜底)
508-3. **兜底上限**:`max_wake_at > 0 && now >= max_wake_at`(无论什么状态都叫醒,防止彻底卡死)
509-
510-## 心跳文件 `/tmp/claude_heartbeat.json`
511-
512-```json
513-{
514- "ts": 1774808270,
515- "timeout": 300,
516- "status": "working",
517- "wake_at": 0,
518- "max_wake_at": 1774809870,
519- "tab": "OpenClaw的GUI控制机制 - Claude",
520- "renewal_msg": "watchdog续命:请继续"
521-}
522-```
523-
524-## 进度文件 `/tmp/claude_progress.json`
525-
526-被唤醒后先读这个文件,知道之前在做什么、做到哪了:
527-
528-```json
529-{
530- "updated_at": 1774808270,
531- "task": "conductor开发:files/read kind修复 + 日志落盘 + T-S049",
532- "subtasks": [
533- {"id": "fix-kind", "status": "done", "note": "一行改动已提交"},
534- {"id": "log-ingest", "status": "in_progress", "note": "codex在写,预计5分钟"},
535- {"id": "T-S049", "status": "pending"}
536- ],
537- "codex_windows": ["baa-conductor — codex"],
538- "claude_windows": ["claude --dangerously-skip-permissions"],
539- "next_action": "检查codex是否完成log-ingest,完成则合并并开始T-S049"
540-}
541-```
542-
543-## 工作流
544-
545-```
546-Claude 开始工作:
547- 1. 写心跳 status=working
548- 2. 写进度 task/subtasks/next_action
549- 3. 分配任务给 codex/claude
550- 4. 设心跳 status=waiting, wake_at=N分钟后, max_wake_at=30分钟后
551- 5. 停止工具调用,等看门狗唤醒
552-
553-看门狗唤醒 Claude:
554- → Safari 发续命消息
555-
556-Claude 被唤醒:
557- 1. 读进度文件,知道之前在做什么
558- 2. 检查各 codex/claude 窗口状态
559- 3. 继续工作
560-```
561-
562-## 用法
563-
564-```bash
565-# 启动
566-nohup bash tools/watchdog/watchdog.sh 60 &
567-
568-# 发消息
569-bash tools/watchdog/a11y_msg.sh "标签页全名" "消息"
570-
571-# 停止看门狗
572-python3 -c "import json; d=json.load(open(/tmp/claude_heartbeat.json)); d[status]=done; json.dump(d,open(/tmp/claude_heartbeat.json,w))"
573-```
574-
575-## 文件
576-
577-- watchdog.sh — 看门狗主循环
578-- a11y_msg.sh — Safari 无障碍消息发送
579-- watchdog.log — 运行日志
580-- /tmp/claude_heartbeat.json — 心跳(看门狗读)
581-- /tmp/claude_progress.json — 进度(Claude 读写)
582diff --git a/tools/watchdog/a11y_msg.sh b/tools/watchdog/a11y_msg.sh
583deleted file mode 100755
584index 43ca8e610dfa2f56ab9ec1fc5e0d327aa360af4c..0000000000000000000000000000000000000000
585--- a/tools/watchdog/a11y_msg.sh
586+++ /dev/null
587@@ -1,41 +0,0 @@
588-#!/bin/bash
589-# a11y 消息发送:通过 Safari 无障碍 API 给指定标签页发消息
590-# 用法: a11y_msg.sh <标签页全名> <消息>
591-# 示例: a11y_msg.sh "OpenClaw的GUI控制机制 - Claude" "续命消息"
592-
593-TAB_NAME="$1"
594-shift
595-MSG="$*"
596-
597-if [ -z "$TAB_NAME" ] || [ -z "$MSG" ]; then
598- echo "用法: $0 <标签页全名> <消息>"
599- exit 1
600-fi
601-
602-# 1. 切标签页(全名匹配)
603-osascript -e "tell application \"Safari\"
604- repeat with w in windows
605- repeat with t in tabs of w
606- if name of t is \"$TAB_NAME\" then
607- set current tab of w to t
608- set index of w to 1
609- return \"matched\"
610- end if
611- end repeat
612- end repeat
613- return \"not found\"
614-end tell" 2>/dev/null
615-
616-sleep 1
617-
618-# 2. 设剪贴板 + 粘贴 + 回车
619-osascript -e "set the clipboard to \"$MSG\""
620-osascript -e 'tell application "System Events" to tell process "Safari"
621- set frontmost to true
622- delay 0.5
623- keystroke "v" using command down
624- delay 0.5
625- keystroke return
626-end tell' 2>/dev/null
627-
628-echo "SENT to [$TAB_NAME]"
629diff --git a/tools/watchdog/watchdog.sh b/tools/watchdog/watchdog.sh
630deleted file mode 100755
631index 4f045ccd94a25e9bcd45056396101e296a0377a8..0000000000000000000000000000000000000000
632--- a/tools/watchdog/watchdog.sh
633+++ /dev/null
634@@ -1,80 +0,0 @@
635-#!/bin/bash
636-# 看门狗 v4:renewed 超时重试
637-
638-SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
639-CHECK_INTERVAL=${1:-60}
640-HEARTBEAT=/tmp/claude_heartbeat.json
641-LOG="${SCRIPT_DIR}/watchdog.log"
642-
643-echo "[$(date)] watchdog v4 started, interval=${CHECK_INTERVAL}s" >> "$LOG"
644-
645-while true; do
646- sleep $CHECK_INTERVAL
647- [ ! -f "$HEARTBEAT" ] && continue
648-
649- RESULT=$(python3 << PYEOF
650-import json, time
651-try:
652- d = json.load(open("$HEARTBEAT"))
653- now = int(time.time())
654- ts = d.get("ts", 0)
655- timeout = d.get("timeout", 300)
656- status = d.get("status", "unknown")
657- tab = d.get("tab", "")
658- msg = d.get("renewal_msg", "watchdog续命")
659- wake_at = d.get("wake_at", 0)
660- max_wake = d.get("max_wake_at", 0)
661- idle = now - ts
662- need = "no"
663- reason = ""
664-
665- if status in ("done", "paused"):
666- pass
667- elif max_wake > 0 and now >= max_wake:
668- need = "yes"
669- reason = f"max_wake_at reached ({now}>={max_wake})"
670- elif status == "waiting":
671- if wake_at > 0 and now >= wake_at:
672- need = "yes"
673- reason = f"wake_at reached ({now}>={wake_at})"
674- elif wake_at == 0 and idle > timeout:
675- need = "yes"
676- reason = f"idle timeout ({idle}s>{timeout}s)"
677- elif status == "renewed" and idle > timeout:
678- need = "yes"
679- reason = f"renewed but no response, retry ({idle}s>{timeout}s)"
680-
681- print(f"{status}|{idle}|{timeout}|{tab}|{need}|{msg}|{reason}|{wake_at}|{max_wake}")
682-except:
683- print("error|0|0|||no|||0|0")
684-PYEOF
685-)
686-
687- IFS="|" read -r ST IDLE TOUT TAB NEED MSG REASON WAKE MAXW <<< "$RESULT"
688-
689- if [ "$ST" = "done" ]; then
690- echo "[$(date)] EXIT: done" >> "$LOG"
691- exit 0
692- fi
693-
694- if [ "$ST" = "paused" ]; then
695- echo "[$(date)] PAUSED" >> "$LOG"
696- continue
697- fi
698-
699- echo "[$(date)] CHECK: status=$ST idle=${IDLE}s timeout=${TOUT}s need=$NEED wake=$WAKE max=$MAXW reason=$REASON" >> "$LOG"
700-
701- if [ "$NEED" = "yes" ]; then
702- echo "[$(date)] RENEWAL: $REASON" >> "$LOG"
703- bash "${SCRIPT_DIR}/a11y_msg.sh" "$TAB" "$MSG"
704- A11Y_RC=$?
705- python3 << PYEOF2
706-import json, time
707-d = json.load(open("$HEARTBEAT"))
708-d["ts"] = int(time.time())
709-d["status"] = "renewed"
710-json.dump(d, open("$HEARTBEAT", "w"))
711-PYEOF2
712- echo "[$(date)] RENEWED (a11y_rc=$A11Y_RC)" >> "$LOG"
713- fi
714-done