---
date: 2026-05-09
type: error
tags: [bash, git-worktree, slot-pool, path-detection]
---

# slot-pool 池根目录探测自指：slot 也是 worktree，第二次 init 路径变 `.pool/.pool`

## 现象

`scripts/dev/slot-pool/pool-init.sh` 第一次跑，slot-1 创建到 `.pool/slot-1` 后失败（其它原因 fix 中）。

修好那个再跑第二次时：

```
pool-init: 池根目录: /home/chentao/Code/ffworkspace-wt/.pool/.pool
fatal: 'pool/slot-1' is already used by worktree at '/home/chentao/Code/ffworkspace-wt/.pool/slot-1'
```

池根路径多了个 `.pool` 嵌套，且 git 报分支已被另一 worktree 占用——但其实 pool-init 的 "目录已存在则跳过" 逻辑应该已经 short-circuit。

## 根因

`sl_pool_parent`（lib/slot-lock.sh）用启发式探测池父目录：

```bash
non_main="$(git worktree list --porcelain \
  | awk '/^worktree / {print $2}' \
  | grep -v "^${main_dir}$" \
  | head -1)"
dirname "${non_main}"
```

逻辑：找一个非主仓库的 worktree，用它的父目录当池父目录。第一次跑时池里没东西，第一个 non-main worktree 是用户日常的 `ffworkspace-wt/workflow-optimization` 之类，`dirname` = `/home/chentao/Code/ffworkspace-wt`，正确。

第二次跑时，slot-1 已经存在，它 _本身_ 也是一个 git worktree，`git worktree list` 把它列出来。如果它在排序中靠前（取决于 git 内部存储顺序），`head -1` 会拿到它，`dirname /home/chentao/Code/ffworkspace-wt/.pool/slot-1` = `/home/chentao/Code/ffworkspace-wt/.pool`，再拼 `/.pool` 就变 `.pool/.pool`。**池目录自指了**。

## 解法

scan worktree list 时排除 `.pool/` 内的项，加多层回退：

```bash
non_main="$(git worktree list --porcelain \
  | awk '/^worktree / {print $2}' \
  | grep -v "^${main_dir}$" \
  | grep -v '/\.pool/' \                 # ← 关键：排除池内 worktree
  | head -1)"
if [[ -n "${non_main}" ]]; then
  dirname "${non_main}"; return
fi
# 回退 1：主仓库旁的 ffworkspace-wt/ 兄弟目录
sibling="$(dirname "${main_dir}")/ffworkspace-wt"
[[ -d "${sibling}" ]] && { echo "${sibling}"; return; }
# 回退 2：主仓库父目录
dirname "${main_dir}"
```

也可以让用户显式 `export FFOA_POOL_ROOT=/abs/path` 短路所有探测。

## 适用范围

- 任何"自管理"工具（自身产物会被工具自己扫到）都要小心自指——package manager 扫包时遇到自己的产物缓存、build 脚本扫源码遇到自己生成的 dist 目录、slot-pool 扫 worktree 遇到自己创建的 slot 等等。
- 经验法则：**用启发式 + 排除规则不如显式配置文件 / 环境变量**——后者无歧义、无自指、可调试。本案保留启发式但加 `FFOA_POOL_ROOT` 环境变量 override 入口。
- 测试启发式探测的 bug 必须**至少跑两次**——第一次产物没出来时探测器看不到，等产物存在了语义就变了。本类 bug 单测 1 次永远绿。

## 其它

`git worktree list` 的输出顺序：实测是 `.git/worktrees/` 目录下文件的 `readdir` 顺序（通常按 inode），不可依赖。不要假设特定顺序。
