---
date: 2026-05-10
tags: [agent-pool, debugging, lock-files]
---

# agent-pool lock 字段：`pid` 是装饰，活性看 `heartbeat_pid`

## 现象

`agent-status.sh` 显示 4 个 slot 都 `claimed`，但所有 PID 列对应进程 `ps -p` 都是 dead。第一反应：4 个僵尸 slot，要 sweep。

## 真相

`scripts/dev/lib/agent-pool-lib.sh:113` 注释明文：

> 活性看 heartbeat_pid（长驻心跳守护），不是 pid（claim 调用进程，调用完就退）

字段语义：

| 字段 | 写入时机 | 期望生命 |
|---|---|---|
| `pid` | claim 时写入调用方 PID（`$$`） | **预期会死**（claim 脚本一行就退）|
| `heartbeat_pid` | `agent-heartbeat.sh` 在 while 循环开头写自己的 `$$` | 跟随 slot 占用全程 |

`agent-status.sh` 的 PID 列展示的是 **`pid` 字段**（claim 调用方），不是活性指示。`ap_lock_is_stale()` 才用 `heartbeat_pid` 判断。

## 后果（如果误信）

按"PID 死就 sweep"操作 → 调 `agent-sweep.sh` → sweep 内部用 `ap_lock_is_stale` 判断 → heartbeat_pid 还活着 → sweep 不干掉 → 误判与现象矛盾，进入死循环排查。

或者更糟：手工 `rm` 掉 lock 文件 → 真在干活的 agent 失去 lock → 别的任务接手 → 工作丢失。

## 给未来 AI 的判断口诀

排查 slot 状态时永远 `awk '/^heartbeat_pid=/{print $2}' lock` 拿真活性 PID，不要看 `agent-status.sh` 表格里的 PID 列。后者只标"当时谁 claim 的"。

## 改进建议（未实施）

- 选项 A：`agent-status.sh` 把 PID 列改成 `claim/heartbeat` 双 PID 显示
- 选项 B：表头加注释提示这是 claim PID 不代表活性
