用途
Parcel Roster 提供对活跃 parcel worktree 的整体视图,回答三个问题:有哪些 parcel 正在进行、它们处于什么状态、哪些已准备好审计或合并。它随 rookery 一起提供,是 rookery worktree list(底层 CLI 视图)和 rookery status / rookery land history(历史侧视图)的代理友好 Markdown 版本。
该技能与 lane-roster 对应,但针对 parcel 树(配置的 worktrees 根目录),而非 lane 树(.claude/worktrees/*)。两者相互独立,不可混为一谈。
何时使用
- 开始 wave-triage 流程,需要整个 fleet 的快照
- 在一波并行构建后询问“哪些可以合并?”
- 判断某个 parcel 是仍在进行、已完成但未审计,还是已审计等待中
- 在编写新 parcel 之前,查看哪些 id 已被占用
何时不使用
- 需要 lane 会话(.claude/worktrees/)——改用 lane-roster
- 需要每个 parcel 的详细裁决——改用 parcel-audit
- 需要合并顺序决策——改用 wave-triage
路径解析(每个会话读一次)
该技能作用于位于可配置根目录下的 parcel worktree。按以下顺序解析一次 <worktrees_root>:
- CWD 中的 rookery.yaml:读取顶层 worktrees_root 键。若存在且非空则使用。
- ROOKERY_WORKTREES 环境变量:若第 1 步无结果则回退到此。
- 默认值:./worktrees(相对于 CWD)。
审计同级目录位于 <worktrees_root>/audits/。
工作流程
第 1 步 — 枚举 parcel worktree
按上述路径解析块解析 <worktrees_root>。遍历 <worktrees_root>/ 下的目录条目(对 */ 使用 Bash for 循环,或 Glob+过滤)。对每个条目,仅当以下两个条件同时成立时才纳入:
- 它是目录(跳过松散文件——真实 fleet 顶层常有 .pid、.iter 和偶尔的日志文件,它们不是 worktree)
- 它包含 .git 文件或目录(真实 worktree 总是如此;仅靠 Glob 无法确认)
按名称跳过的特殊目录:audits/、logs/、smoke-runs/。这些是同级产物根目录,不是 worktree。扩展此黑名单成本很低——优先使用 .git 存在性检查作为权威过滤器。
若 Glob 无返回,输出:
STATUS: no parcel worktrees found ROOT: <worktrees_root>
并停止。空树是有效答案。
第 2 步 — 每个 worktree 的 git 状态
对每个候选 <wt>:
git -C <wt> branch --show-current git -C <wt> log --oneline -1 git -C <wt> rev-list --count main..HEAD # commits ahead git -C <wt> rev-list --count HEAD..main # commits behind git -C <wt> status --porcelain | wc -l # dirty count git -C <wt> stash list | wc -l # stash count
使用 git -C <path>——绝不 cd。若任何命令出错(例如目录不是 git worktree,或 main 已不存在),将该错误原样记录在该行的 error 列并继续。不要因一个坏 worktree 中止整个 roster。
第 3 步 — 检查完成与审计标记
对每个 <wt>,通过 Glob(而非 Bash ls)检查文件存在性:
- <wt>/PARCEL_DONE.md — parcel 自身的完成报告
- <worktrees_root>/audits/<id>.v*.md — 审计文件(零个或多个;记录存在的最高版本)
其中 <id> 是 worktree 目录名。
第 4 步 — 输出表格
生成按 parcel id 排序的 Markdown 表格(字母数字排序,因此 I1 < I2 < P1 < P10 < P2,除非明确要求自然排序)。每个 worktree 一行:
| id | branch | ahead | behind | dirty | stash | DONE? | audit | last-commit |
|---|---|---|---|---|---|---|---|---|
| I1 | parcel/I1-merge | 4 | 0 | 0 | 0 | ✓ | v2 | ab7502d fix(...) |
| I2 | parcel/I2-wire | 1 | 0 | 3 | 0 | ✗ | — | 72a2e29 feat(...) |
- DONE?:若 PARCEL_DONE.md 存在则为 ✓,否则为 ✗
- audit:存在的最高版本(如 v1、v2),若无则为 —
- last-commit:短哈希 + 主题,截断以适应
表格下方输出一行 fleet 摘要:
FLEET: <total> parcels, <done-count> DONE, <audited-count> audited, <at-risk> at-risk (dirty or no-DONE-after-N-commits)
第 5 步 — 标记 at-risk 与 absorbed parcel
满足以下任一条件的 parcel 为 at-risk:
- dirty > 0(未提交的工作可能丢失)
- ahead > 0 且无 PARCEL_DONE.md 且最近 2 小时无提交(构建中途停滞)
满足以下条件的 parcel 为 absorbed:
- ahead == 0 且 behind >> 0(例如 behind ≥ 50)且 PARCEL_DONE 存在
Absorbed parcel 已通过 rebase 或 squash 将工作交付到 main;该分支现在是过时的历史指针。实践中这是已合并 wave 最常见的最终状态——操作者应知道该 parcel 是“已完成,未丢失”,以便干净地垃圾回收 worktree。
若 ahead > 0(仍有未合并提交)或 behind 较小(接近 main),则 parcel 为 fresh。
在主表格下方单独列出 at-risk 行。用独特标记(例如尾部 (absorbed))标记 absorbed 行,以免与进行中的 parcel 混淆。不要尝试修复或修剪——分支/worktree 删除是另一回事(rookery worktree)。
硬性规则
| 规则 | 原因 |
|---|---|
| 只读;绝不 git -C <wt> <mutating> | Roster 不得扰动 parcel 状态 |
| 使用 git -C <path>,绝不 cd | 复合 cd && ... 会破坏权限授予并违反项目 bash 约定 |
| 用 Glob 检查文件存在性,而非 Bash ls/find | Grep/Glob 是专用工具;Bash ls 浪费上下文 |
| 审计目录是 <worktrees_root>/audits/,不在 worktree 内 | 这是项目约定——不要在 worktree 内查找审计 |
| 绝不触碰 .claude/worktrees/ | 那些是 lane worktree;由 lane-roster 负责 |
| 从配置解析 <worktrees_root>,绝不硬编码 | 不同部署使用不同根目录 |
反模式
| 反模式 | 为何有害 |
|---|---|
| 用 ls <worktrees_root>/ 代替 Glob | Bash ls 增加噪音,且对此树比 Glob 慢 |
| 当一个 worktree 的 git log 失败时中止整个 roster | 单个坏 worktree 应优雅降级为 error: <msg> 行,而非杀死报告 |
| 未经用户要求就使用自然数字排序 | 字母排序可预测;自然排序会让调用者意外 |
| 在表格中嵌入审计裁决猜测 | 裁决是 parcel-audit 的职责;该技能仅报告存在性 |
| 在计数前重新运行 git fetch 更新 main | Roster 是本地状态的快照;网络调用超出范围 |
参见
- lane-roster — .claude/worktrees/ 下 lane worktree 的对应技能
- parcel-reader — 将单个 PARCEL_DONE.md 解析为结构化章节
- parcel-audit — 为单个 parcel 生成裁决
- wave-triage — 消费此 roster + 审计以计算合并顺序
- rookery worktree list / rookery status — 同一 fleet 的 CLI 视图