61 lines
2.7 KiB
Markdown
61 lines
2.7 KiB
Markdown
---
|
||
name: Agent Team pane 未关闭修复
|
||
description: tmux agent pane 收到关闭要求后未被关闭的根因分析和修复方案
|
||
type: feedback
|
||
originSessionId: 786eafcb-68a7-48e9-838a-174584e5d9e8
|
||
---
|
||
# Agent Team tmux Pane 未关闭 — 根因分析与修复
|
||
|
||
## 问题现象
|
||
|
||
Agent Team 的 teammate(如 arch-writer-3)收到 `shutdown_request` 后,其 tmux pane 未被关闭,成为孤立 pane。
|
||
|
||
## 根因分析(3 个)
|
||
|
||
### 根因 1: 快照文件被覆盖(最关键)
|
||
|
||
`agent-pane-track.sh` 的 `PreToolUse` 分支每次都会覆盖快照文件。当多个 Agent 同时 spawn 时:
|
||
|
||
```
|
||
Pre(Agent-A) → 写快照 S1 (3 panes)
|
||
Pre(Agent-B) → 覆盖为 S2 (3 panes,但时间点不同)
|
||
Post(Agent-A) → 用 S2 比较 → 可能遗漏 Agent-A 创建的 pane
|
||
```
|
||
|
||
**修复**: 仅在快照文件不存在时才创建(`if [ ! -f "${SNAPSHOT_FILE}" ]`),防止后续 Agent 调用覆盖初始快照。同时快照文件名加入 `team_name` 确保同一 team 共享。
|
||
|
||
### 根因 2: 清理终止策略不够强
|
||
|
||
Claude Code 是交互式 Node.js 进程,单次 Ctrl+C 触发确认提示而非退出:
|
||
- `sleep 1` 太短(Claude 需要更长时间处理中断)
|
||
- `exit` + Enter 在 Claude 仍在运行时被 Claude 拦截
|
||
- `kill-pane` 有条件检查,可能跳过
|
||
|
||
**修复**: 双次 Ctrl+C → 等 3 秒 → exit → 无条件 kill-pane → 验证关闭 → 失败重试。
|
||
|
||
### 根因 3: 无持久化日志
|
||
|
||
hook 脚本只写 stderr,Claude Code 不持久化 stderr。出问题后无任何痕迹可查。
|
||
|
||
**修复**: 添加 `.claude/team-panes.log` 持久化日志,记录每次追踪和清理操作。
|
||
|
||
## Why: 为什么这些根因会导致问题
|
||
|
||
Agent Team 通常同时 spawn 多个 teammate(parallel Agent 调用),这触发了快照覆盖的竞态条件。被遗漏的 pane 不会被记录到 `team-panes.json`,因此 `TeamDelete` 清理时根本不知道这些 pane 的存在。
|
||
|
||
## How to apply: 后续开发注意事项
|
||
|
||
1. **tmux hook 脚本必须考虑并发**: 多个 Agent 可能同时触发 hook,共享资源(文件、状态)需要原子操作
|
||
2. **kill-pane 应作为最终手段无条件执行**: 不要假设 graceful shutdown 一定成功
|
||
3. **持久化日志是必须的**: hook 的 stderr 不会持久化,必须写日志文件
|
||
4. **排查孤立 pane 时检查 `team-panes.log`**: 路径 `.claude/team-panes.log`
|
||
|
||
## 关键文件
|
||
|
||
| 文件 | 说明 |
|
||
|------|------|
|
||
| `.claude/hooks/agent-pane-track.sh` | pane 追踪 hook(已修复快照覆盖) |
|
||
| `.claude/hooks/team-pane-cleanup.sh` | pane 清理 hook(已增强终止策略) |
|
||
| `.claude/team-panes.json` | 运行时状态文件 |
|
||
| `.claude/team-panes.log` | 持久化日志(新增) |
|