---
date: 2026-05-10
tags: [agent-pool, testing, isolation, side-effect]
---

# 测试隔离要覆盖所有相关全局状态，不只是池根

## 现象

`scripts/dev/agent-pool/tests/run-tests.sh` 跑一遍后，**真实**的
`<repo-parent>/<repo>.code-workspace` 文件被污染：folders 列表变成
`/tmp/agent-pool-test.XXX/slot-N` 的临时路径，VSCode 打开看到 slot 数
不对、点开路径报"文件不存在"。

## 根因

测试只设置了 `FFOA_AGENT_POOL_ROOT=/tmp/agent-pool-test.XXX` 隔离池根，
但 `ap_write_code_workspace()` 内部同时使用：

| 数据源 | 路径解析 | 测试期取到的值 |
|---|---|---|
| **写入文件位置** | `ap_codeworkspace_file()` 用 `<repo-parent>/<repo>.code-workspace` | **真实文件路径**（依赖 main_dir，跟 pool_root 无关）|
| **写入 folders 内容** | 遍历 `${pool_root}/slot-*` | **测试池路径** |

结果：真文件 + 测试 slot 路径的污染组合。

cleanup trap 删 `${TEST_POOL_ROOT}` 但不重写 `.code-workspace`，
cleanup 后 dead 路径留在真文件里。

## 修复

测试初始化补一行隔离 codeworkspace 文件：

```bash
TEST_POOL_ROOT="$(mktemp -d -t agent-pool-test.XXXXXX)"
export FFOA_AGENT_POOL_ROOT="${TEST_POOL_ROOT}"
export FFOA_CODEWORKSPACE_FILE="${TEST_POOL_ROOT}/test.code-workspace"  # 关键
export AP_STALE_TIMEOUT=5
export AP_HEARTBEAT_INTERVAL=2
```

这样测试期 `ap_codeworkspace_file()` 返回临时位置，文件随 `${TEST_POOL_ROOT}`
一起被 cleanup 删掉。

## 通用准则

引入新的"全局状态文件"时（不止 codeworkspace，还有 lock dir / config /
cache 等），同时为它配套：

1. `FFOA_<XXX>_FILE` 或 `FFOA_<XXX>_DIR` 环境变量覆盖（`ap_codeworkspace_file()`
   已经支持，但测试没用）
2. 测试 setup 阶段一并 export 到隔离位置
3. 文档记下这两个变量在测试期必须一起设

否则只隔离一半，测试会**部分污染真实状态**——这种污染特别隐蔽：
立即看不出（cleanup trap 假装"完成"了），过几小时才在用户那边表现成
"VSCode 显示对不上"。

## 实战代价

实测：用户 VSCode 打开 `workspace.code-workspace` 看到只有 2 个 slot
还是临时池路径，反复诊断"slot-3 (free) 但实际有"——花了一段时间
排查才意识到是测试污染（一开始误判为 PR #285 的 `.code-workspace
自动维护` 设计 bug）。

## 关联

- PR #288 d67ba690 commit
- PR #285（引入 `.code-workspace` 自动维护，路径解析方式跟 pool_root 解耦
  的设计本身没问题，是测试侧没跟上）
- 同 PR 另一条 learning `delayed-learning-stash-trap.md` 在测试隔离主题上
  类似（"侧面效应不被 cleanup 覆盖" 的同类问题）
