codex@macbookpro
·
2026-03-27
BUG-014-ws-reconnect-premature-completed.md
1# BUG-014: ws_reconnect 报 completed=true 但实际还未重连
2
3## 状态
4
5- 已修复(2026-03-27,代码核对 + 自动化验证)
6
7## 当前代码结论
8
9- `plugins/baa-firefox/controller.js` 的 `ws_reconnect` 分支现在会返回 `deferred: true`、`scheduled: true`
10- `sendPluginActionResult(...)` 的公共发送路径会把 deferred 结果写成 `completed: false`
11- `tests/browser/browser-control-e2e-smoke.test.mjs` 已覆盖:
12 - `plugin_status.completed === true`
13 - `ws_reconnect.completed === false`
14- 验证结果:
15 - `pnpm -C /Users/george/code/baa-conductor -F @baa-conductor/conductor-daemon build` 通过
16 - `node --test /Users/george/code/baa-conductor/tests/browser/browser-control-e2e-smoke.test.mjs` 通过(`3/3`)
17
18## 剩余风险
19
20- 当前自动化验证覆盖的是 conductor 侧端到端语义透传,不是 Firefox 扩展真实运行环境里的 reconnect 生命周期本身
21- 真实浏览器里“真正重连完成”仍依赖后续 `hello` / 状态同步来体现;这一层现有设计未扩改
22
23## 修复前现象
24
25执行 `ws_reconnect` 动作后,conductor 立即收到 `action_result` 且 `completed: true, failed: false`,但此时 WS 实际尚未断开,更没有重连。真正的断开和重连在 80ms 后的 `setTimeout` 回调中才发生。
26
27- 哪个模块:`plugins/baa-firefox/controller.js`,`runPluginManagementAction` 中 `ws_reconnect` 分支
28- 返回了什么:`completed: true`
29- 预期:要么等重连完成再报 `completed: true`,要么报 `completed: false` 表示异步完成
30- 复现条件:任何 `ws_reconnect` 调用
31
32## 修复前触发路径
33
34```text
35POST /v1/browser/actions {"action":"ws_reconnect"}
36 → conductor dispatch → WS → Firefox controller.js
37 → runPluginManagementAction("ws_reconnect")
38 → setTimeout(() => { closeWsConnection(); connectWs(); }, 80)
39 → 函数立即返回(setTimeout 非阻塞)
40 → .then() → sendPluginActionResult({ completed: true })
41 → conductor 收到 action_result,认为重连完成
42 → 80ms 后 WS 才真正断开并重连
43```
44
45## 修复前根因
46
47`ws_reconnect` 用 `setTimeout` 延迟执行断开和重连,但 `runPluginManagementAction` 是同步返回的,不等 setTimeout 回调。上层 `.then()` 在函数返回后立刻发送 `completed: true` 的 action_result。
48
49## 修复前影响
50
51- 语义不准确:conductor 侧依赖 `completed` 判断动作是否执行完毕
52- 如果后续有自动化逻辑在收到 completed=true 后立即发送请求,可能在旧连接上发送
53- 80ms 窗口内 WS 消息行为不可预期
54
55## 严重度
56
57Low-Medium
58
59## 修复方案(已落地)
60
61方案 A(推荐):让 `runPluginManagementAction` 的 ws_reconnect 分支返回一个带标记的结果,上层据此发送 `completed: false`,让 conductor 知道这是异步完成的动作。重连成功后 conductor 通过 `hello` 消息自然感知。
62
63方案 B:把 `setTimeout` 改为 `await sleep(80)` + 同步执行,等重连握手完成后再返回。但这会让 action 响应变慢。