baa-conductor

git clone 

commit
4ac55fa
parent
96c8601
author
codex@macbookpro
date
2026-03-27 15:16:10 +0800 CST
docs: add next browser follow-up task docs
7 files changed,  +533, -9
M PROGRESS/2026-03-27-current-code-progress.md
+7, -0
 1@@ -7,6 +7,7 @@
 2 - 代码和自动化测试都表明:`/describe/business`、`/describe/control`、`GET /v1/browser`、`POST /v1/browser/actions`、`POST /v1/browser/request`、`POST /v1/browser/request/cancel` 已经形成正式主链路。
 3 - 目前不应再把系统描述成“只有 Claude 专用页面路径”;当前是“通用 browser surface 已落地,但正式 relay 仍只有 Claude 接通,其它平台主要停留在空壳页和元数据链路”。
 4 - 当前仍不能写成“全部收尾完成”。剩余未闭项主要是:真实 Firefox 手工 smoke 未完成、风控状态仍是进程内内存态、`BUG-012` 还没有 stale `inFlight` 自动清扫机制,以及正式 browser relay 仍只有 Claude 接通。
 5+- 针对这些残余项,当前已经拆出三张后续任务卡:`T-S026`、`T-S027`、`T-S028`。
 6 
 7 ## 本次核对依据
 8 
 9@@ -227,6 +228,12 @@
10 - 真实 Firefox 扩展运行环境里的 reconnect 生命周期本身,仍依赖后续 `hello` / 状态同步来体现“真正重连完成”。
11 - 这一层现有设计未扩改,因此仍建议在真实 Firefox 环境里补手工 smoke。
12 
13+## 已拆出的后续任务
14+
15+- `T-S026`:真实 Firefox 手工 smoke 与验收记录
16+- `T-S027`:补 `browser-request-policy` stale `inFlight` 自愈清扫
17+- `T-S028`:收口 ChatGPT browser relay 到正式合同
18+
19 ## 建议给 Claude 重点复核的点
20 
21 1. 复核 `../apps/conductor-daemon/src/index.ts` 与 `../apps/conductor-daemon/src/index.test.js`
M plans/STATUS_SUMMARY.md
+14, -4
 1@@ -16,7 +16,10 @@
 2 ## 当前状态分类
 3 
 4 - `已完成`:`T-S001` 到 `T-S025`,以及 `T-BUG-011`、`T-BUG-012`、`T-BUG-014`
 5-- `当前 TODO`:无高优先级主线任务
 6+- `当前 TODO`:
 7+  - `T-S026` 真实 Firefox 手工 smoke 与验收记录
 8+  - `T-S027` browser-request-policy stale `inFlight` 自愈清扫
 9+  - `T-S028` ChatGPT browser relay 正式化
10 - `待处理缺陷`:当前无 open bug backlog(见 `bugs/README.md`)
11 - `低优先级 TODO`:`4318/status-api` 兼容层删旧与解耦
12 
13@@ -75,7 +78,10 @@
14 
15 当前策略:
16 
17-- 当前没有高优先级主线 blocker
18+- 当前最高优先级剩余任务按顺序是:
19+  - `T-S026`:真实 Firefox 手工 smoke 与验收记录
20+  - `T-S027`:补 `browser-request-policy` stale `inFlight` 自愈清扫
21+  - `T-S028`:收口 ChatGPT browser relay 到正式合同
22 - 当前 bug backlog 单独留在 `bugs/` 目录,不把它和主线需求任务混写
23 - 当前不把大文件拆分当作主线 blocker
24 - 以下重构工作顺延到下一轮专门重构任务:
25@@ -88,7 +94,7 @@
26 ## 当前缺陷 backlog
27 
28 - 当前 open bug backlog:无
29-- 当前没有 bug fix 正在主线开发中;如需继续推进,优先从残余风险或后续增强项开新卡
30+- 当前没有 bug fix 正在主线开发中;当前下一波主线任务顺序是 `T-S026 -> T-S027 -> T-S028`
31 
32 ## 低优先级 TODO
33 
34@@ -156,8 +162,12 @@
35 - `pnpm verify:mini` 只收口 on-node 静态检查和运行态探针,不替代会话级 smoke
36 - `status-api` 的终局已经先收口到“保留为 opt-in 兼容层”;真正删除它之前,还要先清 `4318` 调用方并拆掉当前构建时复用
37 - 风控状态当前仍是进程内内存态;`conductor` 重启后,限流、退避和熔断计数会重置
38-- 正式 browser HTTP relay 当前仍只支持 Claude;其它平台目前只有空壳页和元数据链路,没有接入通用 request / SSE 合同
39+- 正式 browser HTTP relay 当前正式验收仍只有 Claude;ChatGPT 已有 bridge / plugin 代码路径,但还没完成正式 `/v1/browser/request` 验收与文档转正;Gemini 继续留在下一波
40 - 当前 open bug backlog 已清空
41+- 当前主线下一波任务已拆成:
42+  - `T-S026`:真实 Firefox 手工 smoke 与验收记录
43+  - `T-S027`:补 `browser-request-policy` stale `inFlight` 自愈清扫
44+  - `T-S028`:收口 ChatGPT browser relay 到正式合同
45 - `BUG-012` 这轮修复解决的是“永久挂起”,不是“自动回收泄漏 slot”;如果未来出现长期不恢复的 lease 泄漏,同一 `target` 的请求会超时失败,而不是自动自愈
46 - `BUG-014` 的自动化验证目前覆盖的是 conductor 侧语义透传,不是 Firefox 扩展真实运行环境里的 reconnect 生命周期;真实“重连完成”仍依赖后续 `hello` / 状态同步
47 - 当前机器未发现 `Firefox.app`,因此尚未执行“手动关 tab -> tab_restore -> WS 重连后状态回报恢复”的真实 Firefox 手工 smoke;这是当前唯一环境型残余风险
M tasks/T-S025.md
+4, -0
 1@@ -177,6 +177,10 @@
 2 - `2026-03-27`:同一轮跟进里,`verify-mini.sh` 的 wrapper 调用也改成数组参数拼装,降低空参数场景下的脚本调用风险。
 3 - `2026-03-27`:当前没有新增手工 smoke 结果;环境阻塞仍然是本机缺少可启动的 `Firefox.app`。
 4 - `2026-03-27`:后续缺陷任务已修复 `BUG-014`,并补上 `ws_reconnect.completed === false` 的 smoke 断言;剩余风险不再是 completed 语义,而是真实 Firefox reconnect 生命周期仍依赖手工验收。
 5+- `2026-03-27`:真实 Firefox 手工 smoke 的执行流程和记录模板已拆到 `/Users/george/code/baa-conductor/tasks/T-S026.md`,后续真机验收直接按该任务卡执行并回写结果。
 6+- `2026-03-27`:其余两项工程化后续任务也已拆卡:
 7+  - `/Users/george/code/baa-conductor/tasks/T-S027.md`:补 `browser-request-policy` stale `inFlight` 自愈清扫
 8+  - `/Users/george/code/baa-conductor/tasks/T-S028.md`:把 ChatGPT browser relay 收口到正式合同
 9 
10 ## 自动化验证
11 
A tasks/T-S026.md
+215, -0
  1@@ -0,0 +1,215 @@
  2+# Task T-S026:真实 Firefox 手工 Smoke 与验收记录
  3+
  4+## 直接给对话的提示词
  5+
  6+读 `/Users/george/code/baa-conductor/tasks/T-S026.md` 任务文档,完成开发任务。
  7+
  8+如需补背景,再读:
  9+
 10+- `/Users/george/code/baa-conductor/tasks/T-S025.md`
 11+- `/Users/george/code/baa-conductor/docs/api/firefox-local-ws.md`
 12+- `/Users/george/code/baa-conductor/docs/api/control-interfaces.md`
 13+- `/Users/george/code/baa-conductor/plugins/baa-firefox/README.md`
 14+- `/Users/george/code/baa-conductor/plans/STATUS_SUMMARY.md`
 15+
 16+## 当前基线
 17+
 18+- 仓库:`/Users/george/code/baa-conductor`
 19+- 分支:`main`
 20+- 提交:`a2b1055`
 21+- 开工要求:不要从其他任务分支切出;如需新分支,从当前 `main` 新切
 22+
 23+## 建议分支名
 24+
 25+- `docs/firefox-manual-smoke`
 26+
 27+## 目标
 28+
 29+在真实 `Firefox.app` 环境里完成一轮手工 smoke,验证插件管理闭环、`tab_restore`、`ws_reconnect` 和状态回报恢复,并把结果回写到项目文档。
 30+
 31+## 背景
 32+
 33+当前代码和自动化测试已经覆盖了:
 34+
 35+- `GET /v1/browser`
 36+- `POST /v1/browser/actions`
 37+- `POST /v1/browser/request`
 38+- `POST /v1/browser/request/cancel`
 39+- 正式 SSE
 40+- 结构化 `action_result`
 41+- `shell_runtime`
 42+
 43+但当前仍缺一轮真实 Firefox 桌面环境下的手工验收。现有自动化 smoke 验证的是 conductor 侧协议和语义透传,不等于真实扩展运行时、真实 tab 生命周期和真实 WS 重连闭环。
 44+
 45+## 涉及仓库
 46+
 47+- `/Users/george/code/baa-conductor`
 48+
 49+## 范围
 50+
 51+- 真实 Firefox 扩展加载与握手确认
 52+- `plugin_status`、`tab_open`、`tab_restore`、`ws_reconnect` 手工 smoke
 53+- 浏览器端 tab 关闭 / 恢复 / 重连后的状态回报验证
 54+- 验收结果记录和文档回写
 55+
 56+## 路径约束
 57+
 58+- 这张任务卡默认是“手工验证 + 文档回写”,不是代码修复任务
 59+- 如果验证过程中发现真实 bug,先记录证据并新开 `bugs/BUG-XXX`,不要在同一任务里顺手修代码
 60+- 只有当文档与真实行为不一致时,才回写文档;不要顺手改业务代码
 61+
 62+## 推荐实现边界
 63+
 64+建议优先做:
 65+
 66+- 先确认本地 `conductor` / Firefox 插件都处于可验证状态
 67+- 再按固定场景顺序执行手工 smoke
 68+- 最后把结果统一写回 `tasks/`、`plans/`、`PROGRESS/`;如有异常,再补 `bugs/`
 69+
 70+## 允许修改的目录
 71+
 72+- `/Users/george/code/baa-conductor/tasks/`
 73+- `/Users/george/code/baa-conductor/plans/`
 74+- `/Users/george/code/baa-conductor/PROGRESS/`
 75+- `/Users/george/code/baa-conductor/bugs/`
 76+- `/Users/george/code/baa-conductor/docs/api/`
 77+- `/Users/george/code/baa-conductor/docs/firefox/`
 78+
 79+## 尽量不要修改
 80+
 81+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/`
 82+- `/Users/george/code/baa-conductor/plugins/baa-firefox/`
 83+- `/Users/george/code/baa-conductor/tests/`
 84+- `/Users/george/code/baa-conductor/packages/`
 85+
 86+## 必须完成
 87+
 88+### 1. 环境就绪确认
 89+
 90+- 确认真实 `Firefox.app` 可启动
 91+- 确认插件已按临时扩展方式加载:`about:debugging#/runtime/this-firefox`
 92+- 确认管理页显示:
 93+  - `本地 WS = 已连接`
 94+  - `本地 HTTP = 已连接` 或处于明确重试
 95+- 确认本地接口可用:
 96+  - `GET /health`
 97+  - `GET /v1/browser`
 98+
 99+### 2. 执行手工 smoke 场景
100+
101+- 场景 A:基线握手与 `plugin_status`
102+  - 触发 `plugin_status`
103+  - 确认返回 `accepted=true`、`completed=true`
104+  - 确认 `GET /v1/browser` 可看到当前 `client_id`、`last_action_result`、`shell_runtime`
105+- 场景 B:`tab_open` + 登录态元数据
106+  - 触发 Claude `tab_open`
107+  - 如未登录,则在真实壳页完成登录
108+  - 确认管理页和 `GET /v1/browser` 已出现账号、指纹、endpoint / shell runtime 信息
109+- 场景 C:手动关闭 tab 后执行 `tab_restore`
110+  - 手动关闭 Claude shell tab
111+  - 触发 `plugin_status` 或等待状态刷新,确认 `actual` 缺失或 `drift` 不对齐
112+  - 触发 `tab_restore`
113+  - 确认新 tab 被恢复,且 `desired=true`、`actual.exists=true`、`drift.aligned=true`
114+- 场景 D:执行 `ws_reconnect`
115+  - 触发 `ws_reconnect`
116+  - 确认 HTTP 返回里的 `completed=false`
117+  - 在管理页观察 `本地 WS` 发生断开后重连
118+  - 重连后确认 `GET /v1/browser` 仍能看到当前 client 和恢复后的状态回报
119+- 场景 E:浏览器重开或扩展重载后的自动恢复
120+  - 保持 Claude 在 `desired=true` 状态
121+  - 关闭并重开 Firefox,或在 `about:debugging` 里重载扩展
122+  - 确认插件管理页启动后会自动恢复缺失的 shell tab
123+
124+### 3. 记录结果并回写
125+
126+- 把每个场景写成 `通过 / 失败 / 阻塞`
127+- 记录真实机器环境:
128+  - macOS 版本
129+  - Firefox 版本
130+  - 验证时间
131+  - 本地 API 地址
132+- 把最终结论回写到:
133+  - `/Users/george/code/baa-conductor/tasks/T-S025.md`
134+  - `/Users/george/code/baa-conductor/plans/STATUS_SUMMARY.md`
135+  - `/Users/george/code/baa-conductor/PROGRESS/2026-03-27-current-code-progress.md`
136+
137+### 4. 异常处理
138+
139+- 如果某一步和当前文档结论不一致,记录最小复现步骤
140+- 如属于新问题,新开 `bugs/BUG-XXX` 和对应 `FIX-BUG-XXX.md`
141+- 不要在同一轮手工 smoke 任务里顺手改代码把问题“消掉”
142+
143+## 需要特别注意
144+
145+- `ws_reconnect` 的当前预期是“动作立即返回 `completed=false`,真实完成靠后续 `hello` / 状态同步体现”
146+- `tab_restore` 要看的是“手工关 tab 后能否恢复 + 恢复后的状态是否回到 aligned”,不是只看 HTTP 200
147+- 如果 Firefox 重开后自动恢复生效,要同时看:
148+  - 浏览器里 tab 是否真的恢复
149+  - `GET /v1/browser` 的 `shell_runtime` 是否同步恢复
150+- 这轮不是 ChatGPT / Gemini relay 验收,除非顺手验证平台根页 adopt;否则默认以 Claude 为主验收面
151+
152+## 验收标准
153+
154+- 有一份真实 Firefox 手工 smoke 记录,覆盖 `plugin_status`、`tab_open`、`tab_restore`、`ws_reconnect`、浏览器重开 / 扩展重载自动恢复
155+- 结果已明确写成 `通过 / 失败 / 阻塞`
156+- 如发现异常,已补最小复现和 bug 卡
157+- 相关状态文档已回写,不再只写“当前环境阻塞”
158+
159+## 推荐验证命令
160+
161+- `export LOCAL_API_BASE=http://100.71.210.78:4317`
162+- `curl -s "${LOCAL_API_BASE}/health" | jq`
163+- `curl -s "${LOCAL_API_BASE}/v1/browser" | jq '.data.current_client'`
164+- `curl -s -X POST "${LOCAL_API_BASE}/v1/browser/actions" -H "content-type: application/json" -d '{"action":"plugin_status"}' | jq`
165+- `curl -s -X POST "${LOCAL_API_BASE}/v1/browser/actions" -H "content-type: application/json" -d '{"action":"tab_open","platform":"claude"}' | jq`
166+- `curl -s -X POST "${LOCAL_API_BASE}/v1/browser/actions" -H "content-type: application/json" -d '{"action":"tab_restore","platform":"claude"}' | jq`
167+- `curl -s -X POST "${LOCAL_API_BASE}/v1/browser/actions" -H "content-type: application/json" -d '{"action":"ws_reconnect"}' | jq`
168+
169+## 手工验收记录模板
170+
171+建议按下面格式回写:
172+
173+```md
174+## 真实 Firefox 手工 Smoke 记录(YYYY-MM-DD)
175+
176+- 机器:
177+- macOS:
178+- Firefox:
179+- 扩展加载方式:
180+- LOCAL_API_BASE:
181+
182+### 场景 A:plugin_status
183+- 结果:
184+- 观察:
185+
186+### 场景 B:tab_open + 元数据
187+- 结果:
188+- 观察:
189+
190+### 场景 C:手动关 tab -> tab_restore
191+- 结果:
192+- 观察:
193+
194+### 场景 D:ws_reconnect
195+- 结果:
196+- 观察:
197+
198+### 场景 E:浏览器重开 / 扩展重载自动恢复
199+- 结果:
200+- 观察:
201+
202+### 总结
203+- 是否通过:
204+- 新发现问题:
205+- 剩余风险:
206+```
207+
208+## 交付要求
209+
210+完成后请说明:
211+
212+- 实际验证了哪些场景
213+- 每个场景的结果是什么
214+- 回写了哪些文档
215+- 是否发现新 bug
216+- 还有哪些剩余风险
A tasks/T-S027.md
+136, -0
  1@@ -0,0 +1,136 @@
  2+# Task T-S027:补 browser-request-policy stale `inFlight` 自愈清扫
  3+
  4+## 直接给对话的提示词
  5+
  6+读 `/Users/george/code/baa-conductor/tasks/T-S027.md` 任务文档,完成开发任务。
  7+
  8+如需补背景,再读:
  9+
 10+- `/Users/george/code/baa-conductor/bugs/BUG-012-browser-request-policy-waiter-deadlock.md`
 11+- `/Users/george/code/baa-conductor/bugs/FIX-BUG-012.md`
 12+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/browser-request-policy.ts`
 13+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/local-api.ts`
 14+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
 15+- `/Users/george/code/baa-conductor/PROGRESS/2026-03-27-current-code-progress.md`
 16+
 17+## 当前基线
 18+
 19+- 仓库:`/Users/george/code/baa-conductor`
 20+- 分支:`main`
 21+- 提交:`a2b1055`
 22+- 开工要求:不要从其他任务分支切出;如需新分支,从当前 `main` 新切
 23+
 24+## 建议分支名
 25+
 26+- `feat/policy-stale-sweeper`
 27+
 28+## 目标
 29+
 30+给 `browser-request-policy` 增加 stale `inFlight` 自愈清扫,避免长期泄漏 lease 时同一 `target` 后续请求只能稳定超时失败。
 31+
 32+## 背景
 33+
 34+`BUG-012` 这轮已经修掉了“waiter 永久挂起”,当前行为变成“明确超时失败”。这比永久挂起好,但还不等于自愈:
 35+
 36+- 如果某个 lease 真的泄漏且一直不恢复
 37+- 同一 `client/platform` 的 `inFlight` 会一直占住
 38+- 后续请求会反复打到 `waiter_timeout`
 39+
 40+当前代码里也还没有配套的 stale lease 可观测性,`/v1/browser` 读面只能看到 `in_flight` / `waiting`,还看不到“是不是已经卡死太久、有没有被后台回收过”。
 41+
 42+## 涉及仓库
 43+
 44+- `/Users/george/code/baa-conductor`
 45+
 46+## 范围
 47+
 48+- `browser-request-policy` 的 stale lease 检测与后台清扫
 49+- lease / target 活跃时间或等价诊断字段
 50+- `/v1/browser` policy 读面的最小可观测性补充
 51+- 专项回归测试
 52+- 相关状态文档回写
 53+
 54+## 路径约束
 55+
 56+- 这张卡优先限制在 `conductor-daemon` 侧完成
 57+- 不要把风控运行态持久化并进来
 58+- 不要顺手把策略系统大改成新架构
 59+- 如果需要给 lease 增加 `touch` / `heartbeat` 一类接口,优先做最小增量,不要扩成通用 tracing 系统
 60+
 61+## 推荐实现边界
 62+
 63+建议优先做:
 64+
 65+- 给 lease 或 target 增加“最后活跃时间”追踪
 66+- 后台定期扫描明显 stale 的 `inFlight`
 67+- 只回收“足够明确已经异常卡死”的 slot,不要误杀正常长请求
 68+- 在 `getSnapshot()` / `/v1/browser` 里补最小但可验证的诊断字段
 69+- 补手工时钟驱动的专项测试,覆盖“泄漏后自动恢复”和“正常请求不被提前回收”
 70+
 71+## 允许修改的目录
 72+
 73+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/`
 74+- `/Users/george/code/baa-conductor/tasks/`
 75+- `/Users/george/code/baa-conductor/plans/`
 76+- `/Users/george/code/baa-conductor/PROGRESS/`
 77+- `/Users/george/code/baa-conductor/docs/api/`
 78+
 79+## 尽量不要修改
 80+
 81+- `/Users/george/code/baa-conductor/plugins/baa-firefox/`
 82+- `/Users/george/code/baa-conductor/tests/browser/`
 83+- `/Users/george/code/baa-conductor/packages/db/`
 84+- `/Users/george/code/baa-conductor/apps/status-api/`
 85+
 86+## 必须完成
 87+
 88+### 1. 实现 stale lease 自愈清扫
 89+
 90+- 长时间无恢复的 `inFlight` 不能再只表现为后续请求稳定超时
 91+- 至少要能自动释放明显异常卡死的 slot,并让后续 waiter 有机会继续推进
 92+- 不能依赖人工重启进程来恢复同一 `target` 的可用性
 93+
 94+### 2. 补最小可观测性
 95+
 96+- `BrowserRequestPolicyController.getSnapshot()` 或 `/v1/browser` policy 读面要能看出:
 97+  - 目标最近活跃时间或等价字段
 98+  - 是否发生过 stale sweep
 99+  - 必要时最后一次 sweep 原因或计数
100+- 不要只做内部恢复而不留下诊断痕迹
101+
102+### 3. 补专项测试和文档
103+
104+- 补手工时钟测试,至少覆盖:
105+  - 泄漏 lease 被 sweep 后,同一 target 的等待请求能继续推进
106+  - 正常完成的请求不会被误回收
107+  - 现有 waiter timeout / platform admission 语义不回退
108+- 更新相关文档,说明这轮解决了什么、还剩什么风险
109+
110+## 需要特别注意
111+
112+- 最大风险是误回收仍然健康的长请求,尤其是 SSE 或慢上游请求;实现时必须有明确的 stale 判定依据
113+- 这张卡的目标是“自愈 slot 泄漏”,不是把所有超时都吞掉,也不是隐藏真实上游失败
114+- 不要顺手把 `BUG-012` 已经关闭的结论改回 open;如果这轮发现新边界问题,单独补风险说明或新 bug 卡
115+
116+## 验收标准
117+
118+- 泄漏 lease 场景下,同一 `target` 不再只能稳定命中 `waiter_timeout`
119+- 至少有一条自动化测试能证明 stale sweep 后 waiter 被恢复推进
120+- `/v1/browser` policy 读面或等价 snapshot 能看出 stale sweep 诊断信息
121+- 现有 `BUG-012` 回归测试仍通过
122+- `git diff --check` 通过
123+
124+## 推荐验证命令
125+
126+- `pnpm -C /Users/george/code/baa-conductor -F @baa-conductor/conductor-daemon build`
127+- `node --test /Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
128+- `git -C /Users/george/code/baa-conductor diff --check`
129+
130+## 交付要求
131+
132+完成后请说明:
133+
134+- stale `inFlight` 最终如何判定和回收
135+- 新增了哪些诊断字段
136+- 跑了哪些测试
137+- 还有哪些剩余风险
A tasks/T-S028.md
+137, -0
  1@@ -0,0 +1,137 @@
  2+# Task T-S028:收口 ChatGPT browser relay 到正式合同
  3+
  4+## 直接给对话的提示词
  5+
  6+读 `/Users/george/code/baa-conductor/tasks/T-S028.md` 任务文档,完成开发任务。
  7+
  8+如需补背景,再读:
  9+
 10+- `/Users/george/code/baa-conductor/tasks/T-S023.md`
 11+- `/Users/george/code/baa-conductor/tasks/T-S025.md`
 12+- `/Users/george/code/baa-conductor/docs/api/README.md`
 13+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/local-api.ts`
 14+- `/Users/george/code/baa-conductor/plugins/baa-firefox/controller.js`
 15+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
 16+- `/Users/george/code/baa-conductor/tests/browser/browser-control-e2e-smoke.test.mjs`
 17+- `/Users/george/code/baa-conductor/PROGRESS/2026-03-27-current-code-progress.md`
 18+
 19+## 当前基线
 20+
 21+- 仓库:`/Users/george/code/baa-conductor`
 22+- 分支:`main`
 23+- 提交:`a2b1055`
 24+- 开工要求:不要从其他任务分支切出;如需新分支,从当前 `main` 新切
 25+
 26+## 建议分支名
 27+
 28+- `feat/chatgpt-browser-relay`
 29+
 30+## 目标
 31+
 32+把 `platform=chatgpt` 的 `/v1/browser/request` 路径收口成正式支持面,并补齐自动化验证和文档口径。
 33+
 34+## 背景
 35+
 36+当前代码现实和文档口径之间有明显落差:
 37+
 38+- Firefox 插件和 bridge 层已经有 `chatgpt` 平台定义、header 组装、`api_request` 派发能力
 39+- `index.test.js` 里也已有 `chatgpt` 的 bridge 命令与请求级测试
 40+- 但正式文档、smoke 和进度口径仍然写成“正式 relay 只有 Claude 接通”
 41+
 42+这会让后续协作者无法判断 `chatgpt` 到底是“未实现”,还是“已具备骨架但未正式验收”。这张卡的目标就是把这个灰区清掉。
 43+
 44+## 涉及仓库
 45+
 46+- `/Users/george/code/baa-conductor`
 47+
 48+## 范围
 49+
 50+- `/v1/browser/request` 上 `platform=chatgpt` 的正式支持面
 51+- 必要时补 `buffered` / `sse` / `cancel` 路径缺口
 52+- ChatGPT 对应自动化 smoke
 53+- 正式文档和进度文档回写
 54+
 55+## 路径约束
 56+
 57+- 这张卡优先收口 `chatgpt`,不要把 `gemini` 一起做成大任务
 58+- 不要破坏 Claude 现有 prompt shortcut、legacy `/v1/browser/claude/*` 包装和现有 smoke
 59+- 如需改 Firefox 插件,优先做 ChatGPT 相关最小增量,不要顺手重写整个平台抽象
 60+
 61+## 推荐实现边界
 62+
 63+建议优先做:
 64+
 65+- 先确认 `local-api -> bridge -> plugin/page proxy` 这条 ChatGPT 请求链现状
 66+- 先把 `buffered` 路径收口成正式支持面
 67+- 如果当前代码已能稳定支撑 `sse` / `cancel`,一并纳入 smoke 和文档
 68+- 如果 `sse` 仍有真实缺口,不要模糊描述,明确写成限制并单开后续任务或 bug
 69+
 70+## 允许修改的目录
 71+
 72+- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/`
 73+- `/Users/george/code/baa-conductor/plugins/baa-firefox/`
 74+- `/Users/george/code/baa-conductor/tests/browser/`
 75+- `/Users/george/code/baa-conductor/docs/api/`
 76+- `/Users/george/code/baa-conductor/docs/firefox/`
 77+- `/Users/george/code/baa-conductor/tasks/`
 78+- `/Users/george/code/baa-conductor/plans/`
 79+- `/Users/george/code/baa-conductor/PROGRESS/`
 80+
 81+## 尽量不要修改
 82+
 83+- `/Users/george/code/baa-conductor/packages/db/`
 84+- `/Users/george/code/baa-conductor/apps/status-api/`
 85+- `/Users/george/code/baa-conductor/packages/host-ops/`
 86+- `/Users/george/code/baa-conductor/plugins/baa-firefox/` 里的 Gemini 专用模板逻辑
 87+
 88+## 必须完成
 89+
 90+### 1. 确认并收口 ChatGPT 正式请求面
 91+
 92+- 确认 `POST /v1/browser/request` 在 `platform=chatgpt` 下的真实行为
 93+- 至少把 `buffered` 模式收口成自动化可验证的正式支持面
 94+- 如当前代码已具备条件,补 `sse` 和 `cancel` 的正式验证;如果没有,就明确写出当前限制
 95+
 96+### 2. 补自动化验证
 97+
 98+- 至少补一条从 `local-api` 到 Firefox bridge stub 的 ChatGPT 请求测试
 99+- 优先补到已有测试文件里,不新起一套平行测试体系
100+- 不能只测 bridge 原语,必须覆盖正式 `/v1/browser/request` 合同
101+
102+### 3. 同步正式文档和进度口径
103+
104+- `docs/api/README.md`、必要时 `docs/api/business-interfaces.md` 要与代码现实一致
105+- `tasks/`、`plans/`、`PROGRESS/` 的状态描述要同步
106+- 如果最终只做到 `buffered`,文档必须明确写“ChatGPT 哪些模式已正式支持,哪些还没有”
107+
108+## 需要特别注意
109+
110+- ChatGPT 仍依赖真实浏览器里捕获到的有效 header / 登录态;不要把“有代码路径”写成“无前提可用”
111+- Claude prompt shortcut 仍然只属于 Claude,不要扩成 ChatGPT 共用语义
112+- Gemini 继续留到下一波;除非是共享通用路径上的低风险修正,否则不要把范围扩成 `chatgpt + gemini`
113+- 任何文档结论都要以当前代码和自动化验证为准,不要沿用旧口径
114+
115+## 验收标准
116+
117+- 至少一条自动化测试证明 `platform=chatgpt` 的 `/v1/browser/request` 正式可用
118+- 如果 `sse` / `cancel` 也已纳入支持面,测试中要有对应覆盖
119+- 文档不再错误写成“正式 relay 只有 Claude”。
120+- Claude 现有请求、cancel、smoke 不回退
121+- `git diff --check` 通过
122+
123+## 推荐验证命令
124+
125+- `pnpm -C /Users/george/code/baa-conductor -F @baa-conductor/conductor-daemon build`
126+- `node --test /Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
127+- `node --test /Users/george/code/baa-conductor/tests/browser/browser-control-e2e-smoke.test.mjs`
128+- `git -C /Users/george/code/baa-conductor diff --check`
129+
130+## 交付要求
131+
132+完成后请说明:
133+
134+- ChatGPT 最终正式支持了哪些请求模式
135+- 改了哪些测试和文档
136+- 是否改到 Firefox 插件侧
137+- Gemini 为什么仍然留在下一波
138+- 还有哪些剩余风险
M tasks/TASK_OVERVIEW.md
+20, -5
 1@@ -16,7 +16,10 @@
 2 ## 状态分类
 3 
 4 - `已完成`:`T-S001` 到 `T-S025`,以及 `T-BUG-011`、`T-BUG-012`、`T-BUG-014`
 5-- `当前 TODO`:无高优先级主线任务
 6+- `当前 TODO`:
 7+  - `T-S026` 真实 Firefox 手工 smoke 与验收记录
 8+  - `T-S027` browser-request-policy stale `inFlight` 自愈清扫
 9+  - `T-S028` ChatGPT browser relay 正式化
10 - `待处理缺陷`:当前无 open bug backlog(见 `../bugs/README.md`)
11 - `低优先级 TODO`:`4318/status-api` 兼容层删旧与解耦
12 
13@@ -54,13 +57,18 @@
14 23. [`T-S023.md`](./T-S023.md):打通通用 browser request / cancel / SSE 链路与 `conductor` 风控策略
15 24. [`T-S024.md`](./T-S024.md):回写正式文档、补 browser smoke 并同步主线状态
16 25. [`T-S025.md`](./T-S025.md):收口插件管理闭环与真实 Firefox 验收
17-
18 最近完成的缺陷任务:
19 
20 26. [`T-BUG-011.md`](./T-BUG-011.md):修复 `writeHttpResponse()` 在背压断连下的永久挂起,并补专项测试
21 27. [`T-BUG-012.md`](./T-BUG-012.md):修复 `browser-request-policy` waiter 永久挂起,并补专项测试
22 28. [`T-BUG-014.md`](./T-BUG-014.md):修正 `ws_reconnect` 的 `completed` 语义,并补 smoke 断言
23 
24+## 已准备的后续任务
25+
26+- [`T-S026.md`](./T-S026.md):真实 Firefox 手工 smoke 与验收记录
27+- [`T-S027.md`](./T-S027.md):补 `browser-request-policy` stale `inFlight` 自愈清扫
28+- [`T-S028.md`](./T-S028.md):收口 ChatGPT browser relay 到正式合同
29+
30 当前主线已经额外收口:
31 
32 - 根级 `pnpm smoke`,覆盖 repo 内可自举的 runtime compatibility / legacy absence / codexd e2e / browser-control e2e smoke
33@@ -73,8 +81,11 @@
34 
35 ## 当前活动任务
36 
37-- 当前没有高优先级活动任务卡;如需继续推进,直接新开后续任务
38-- 当前没有正在执行中的缺陷修复卡;如需继续推进,优先从残余风险或后续增强项开新卡
39+- 当前高优先级剩余任务按顺序是:
40+  - [`T-S026.md`](./T-S026.md):真实 Firefox 手工 smoke 与验收记录
41+  - [`T-S027.md`](./T-S027.md):补 `browser-request-policy` stale `inFlight` 自愈清扫
42+  - [`T-S028.md`](./T-S028.md):收口 ChatGPT browser relay 到正式合同
43+- 当前没有正在执行中的缺陷修复卡;如需继续推进工程改动,优先从残余风险或后续增强项开新卡
44 
45 ## 当前主线收口情况
46 
47@@ -113,8 +124,12 @@
48 当前已知主线遗留:
49 
50 - 风控状态当前仍是进程内内存态;`conductor` 重启后,限流、退避和熔断计数会重置
51-- 正式 browser HTTP relay 当前仍只支持 Claude;其它平台目前只有空壳页和元数据链路,没有接入通用 request / SSE 合同
52+- 正式 browser HTTP relay 当前正式验收仍只有 Claude;ChatGPT 已有 bridge / plugin 代码路径,但还没有完成正式 `/v1/browser/request` 验收与文档转正;Gemini 继续留在下一波
53 - 当前 open bug backlog 已清空
54+- 当前主线剩余任务已拆成:
55+  - [`T-S026.md`](./T-S026.md):补真实 Firefox 手工 smoke 与验收记录
56+  - [`T-S027.md`](./T-S027.md):补 `browser-request-policy` stale `inFlight` 自愈清扫
57+  - [`T-S028.md`](./T-S028.md):收口 ChatGPT browser relay 到正式合同
58 - `BUG-012` 这轮修复解决的是“永久挂起”,不是“自动回收泄漏 slot”;如果未来出现长期不恢复的 lease 泄漏,同一 `target` 的请求会超时失败,而不是自动自愈
59 - `BUG-014` 的自动化验证目前覆盖的是 conductor 侧语义透传,不是 Firefox 扩展真实运行环境里的 reconnect 生命周期;真实“重连完成”仍依赖后续 `hello` / 状态同步
60 - runtime smoke 仍依赖仓库根已有 `state/`、`runs/`、`worktrees/`、`logs/launchd/`、`logs/codexd/`、`tmp/` 等本地运行目录;这是现有脚本前提,不是本轮功能回归