im_wower
·
2026-03-28
T-S004.md
1---
2status: completed
3base_ref: main@7c9f009
4updated_at: 2026-03-25 00:21:37 +0800
5---
6
7# Task T-S004:修复 conductor-daemon 测试 listener 泄漏
8
9## 直接给对话的提示词
10
11读 `/Users/george/code/baa-conductor/tasks/archive/T-S004.md` 任务文档,完成开发任务。
12
13如需补背景,再读:
14
15- `/Users/george/code/baa-conductor/bugs/BUG-009-conductor-daemon-index-test-leaks-local-listener.md`
16- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
17- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.ts`
18
19## 当前基线
20
21- 仓库:`/Users/george/code/baa-conductor`
22- 分支:`main`
23- 提交:`7c9f009`
24- 开工要求:不要从其他任务分支切出;如需新分支,从当前 `main` 新切
25
26## 建议分支名
27
28- `fix/conductor-daemon-test-listener-leak`
29
30## 目标
31
32修复 `conductor-daemon` 测试在异常路径下遗留本地 HTTP listener、导致 `node --test` 挂住的问题,并把 cleanup 边界收紧到稳定可复现的最小修复。
33
34## 背景
35
36- `BUG-009` 指向的是测试层资源清理不完整,而不是运行时主功能错误。
37- 这类问题容易让 CI 或本地回归在失败后卡住,浪费排查时间。
38- 当前优先需要的是让测试 fixture / setup / teardown 在异常路径下也能可靠释放 listener。
39
40## 涉及仓库
41
42- `/Users/george/code/baa-conductor`
43
44## 范围
45
46- 修复 `apps/conductor-daemon/src/index.test.js` 的 cleanup 路径
47- 只在必要时微调 `apps/conductor-daemon/src/index.ts`
48- 更新 `BUG-009` 文档说明
49
50## 路径约束
51
52- 优先用 `try/finally`、fixture helper 或统一 teardown 收口。
53- 不做无关重构,不扩散到其它测试文件。
54
55## 推荐实现边界
56
57建议优先检查:
58
59- 测试里创建本地 listener 的 helper 是否总能进入 cleanup
60- 失败断言、提前 return、异常抛出路径是否绕过了关闭动作
61- 是否需要把 cleanup 责任从测试调用点移到更稳定的 helper 包装里
62
63## 允许修改的目录
64
65- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
66- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.ts`
67- `/Users/george/code/baa-conductor/bugs/BUG-009-conductor-daemon-index-test-leaks-local-listener.md`
68
69## 尽量不要修改
70
71- `/Users/george/code/baa-conductor/apps/codexd/`
72- `/Users/george/code/baa-conductor/apps/status-api/`
73- `/Users/george/code/baa-conductor/bugs/README.md`
74
75## 必须完成
76
77### 1. 修复测试 cleanup
78
79- 让异常路径下的 listener 也一定能关闭
80- 避免依赖人工排查或二次运行才能释放资源
81
82### 2. 覆盖复现路径
83
84- 至少用现有测试或新增最小测试证明挂住问题已被覆盖
85- 最好能重复运行同一组测试而不残留 listener
86
87### 3. 回写 bug 文档
88
89- 在 `BUG-009` 里写清根因、修复方式和剩余风险
90
91## 需要特别注意
92
93- 不要顺手改 codexd 或 status-api
94- 这是测试稳定性修复,不要把任务扩展成运行时架构调整
95- 与并行任务共享 `bugs/` 目录时,只改自己的 bug 文档
96
97## 验收标准
98
99- `conductor-daemon` 测试不再因本地 listener 残留而挂住
100- 重复运行指定测试时没有资源泄漏迹象
101- `BUG-009` 文档已回写根因与修复结果
102- `git diff --check` 通过
103
104## 推荐验证命令
105
106- `npx --yes pnpm -C /Users/george/code/baa-conductor -F @baa-conductor/conductor-daemon test`
107- `node --test /Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
108- `node --test /Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
109- `git -C /Users/george/code/baa-conductor diff --check`
110
111## 交付要求
112
113完成后请说明:
114
115- 修改了哪些文件
116- 泄漏根因是什么
117- 你如何保证 cleanup 一定执行
118- 跑了哪些验证
119- 还存在哪些残余风险
120
121## 更新要求
122
123开始时更新 frontmatter 的:
124
125- `status`
126- `base_ref`
127- `updated_at`
128
129完成后补充下面这些内容:
130
131## files_changed
132
133- `/Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
134- `/Users/george/code/baa-conductor/bugs/BUG-009-conductor-daemon-index-test-leaks-local-listener.md`
135- `/Users/george/code/baa-conductor/tasks/archive/T-S004.md`
136
137## commands_run
138
139- `node --check /Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
140- `node --test --test-name-pattern='ConductorRuntime fixture closes the local API listener when a started test aborts|ConductorRuntime exposes a local Firefox websocket bridge over the local API listener|ConductorRuntime exposes a minimal runtime snapshot for CLI and status surfaces' /Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
141- `node --test /Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
142- `node --test /Users/george/code/baa-conductor/apps/conductor-daemon/src/index.test.js`
143- `npx --yes pnpm -C /Users/george/code/baa-conductor -F @baa-conductor/conductor-daemon test`
144- `git -C /Users/george/code/baa-conductor diff --check`
145
146## result
147
148- 在 `index.test.js` 新增 `withRuntimeFixture(...)`,把 `ConductorRuntime` 的 `stop()` 和 `stateDir` 删除固定收进 `finally`
149- 将 runtime snapshot 用例和 Firefox WS 用例切到该 helper,避免断言失败或 `await` 抛错时跳过 cleanup
150- 新增异常路径回归测试:在 `runtime.start()` 之后主动抛错,再校验原端口返回 `ECONNREFUSED`
151- `BUG-009` 已回写最终根因、修复方式和剩余风险
152
153## risks
154
155- 未来如果有新的 runtime 测试绕过 `withRuntimeFixture(...)`、重新手写尾部 cleanup,可能再次引入同类 listener 泄漏
156- 这次修复没有改动 `ConductorRuntime.stop()` 本身;如果运行时关闭逻辑未来出现内部阻塞,需要单独补运行时层测试
157
158## next_handoff
159
160- 当前无需额外交接;后续新增会起本地 listener 的测试时,优先复用 `withRuntimeFixture(...)`