Skip to content

第 8 章 · Crewmate 委派:ship 任务与 scout 任务

本章目标:理解 FirstMate 的两种任务形态——交付变更的 ship 任务与产出知识的 scout 任务,掌握 intake 阶段的任务分派契约与委派机制。

8.1 两种任务形态的设计动机

你向 firstmate 说"修复这个 flaky 测试"和"调查一下登录接口为什么慢",是两种完全不同的请求:前者期望代码被改变并出货,后者期望得到一份可信的调查结论。把它们混在一种任务里会导致两种失败——该改代码的没改,不该改的乱改。

FirstMate 因此在任务层面内置了两种形态(官方称 "Two task shapes"):

text
ship 任务   改变项目,按项目模式出货(no-mistakes / direct-PR / local-only)
scout 任务  产出独立调查报告,绝不 push

这个区分写在架构文档里,而"什么时候派 scout"的判断规则由 AGENTS.md 的 intake 与授权契约(intake and authority contract)拥有。本章我们逐一拆解。

8.2 ship 任务:交付被授权的变更

ship 任务的目标是被授权的项目变更,最终以 PR、经批准的本地合并或其他项目模式定义的方式交付。它的完整生命周期是:

text
captain 请求 → firstmate intake(确定任务形态与交付模式)
           → fm-brief.sh 写任务简报
           → fm-spawn.sh 在干净 worktree 启动 crewmate
           → crewmate 实施 + 按模式验证
           → PR / approved local merge
           → teardown 清理 worktree

注意 hard rule 1 的分工:firstmate 自己不写项目代码——它只读 projects/,写受守卫的 backlog、简报和状态;真正动项目文件的是它 spawn 出来并监督的 crewmate。

8.3 scout 任务:产出知识而非变更

scout 任务适用于调查、诊断、规划、复现或审计类工作。它的交付物是一份独立报告:

text
data/<id>/report.md     ← scout 的唯一正式交付物,teardown 后依然保留

报告完成后的收尾流程(对应架构图中的 scout 分支):

text
report.md 完成 → decision inventory(未决决策清单)→ relay findings(向 captain 转达发现)→ teardown

两个关键安全设计:

  1. scout worktree 被声明为 scratch(草稿区)。根据 hard rule 3,它只有在报告存在且共享的未决决策完成门通过之后才允许丢弃;
  2. 诊断结论不是改代码的授权AGENTS.md 明确写道:"A diagnostic request, report, recommendation, or implementation-ready finding is evidence, not authorization to change code."——scout 发现了 bug 不等于可以顺手修掉,修复必须走新的 ship 授权。

8.4 intake 契约:何时该拆出 scout

不是所有问题都值得开一个 scout。AGENTS.md 给出的判断规则很克制:

text
满足以下任一条件时才适合 scout:
① captain 明确要求单独的知识或设计交付物;
② 未决的不确定性会实质性地改变"要不要做"或"做什么"。

同时有两条反浪费约束:

  • 如果既有证据已经能回答一个信息性问题,firstmate 应直接转达答案,而不是发起一个"纯设计 scout"(design-only scout);
  • 绝不允许一边给出一个"大概率够用的方案",一边又并行启动一个并不预期改变该方案的设计调研——这是纯粹的 token 浪费。

当实现意图不清楚时,正确姿势是先回答、必要时向 captain 提一个简洁的实现澄清问题,而不是派 speculative design 工作。

8.5 委派机制:worktree 门禁与并发规则

spawn 不是随便启动一个进程。fm-spawn.sh 有两道硬门禁:

text
门禁一:任务路径必须是真实的 git worktree root,
        且必须区别于项目主 checkout。
        否则拒绝启动。

门禁二:base-freshness——每个新 ship/scout 启动前,
        干净的任务 worktree 必须先对齐 origin 默认分支的已拉取 tip。
        基线不安全或无法验证 → spawn 停止。

第二道门禁保证了每个 crewmate 都从最新基线出发,避免并行工作建立在过期代码上。

关于并发AGENTS.md 的规则同样明确:

text
默认:只要每项变更可独立实施、可独立验证,
      且所选交付路径能调和普通的 rebase/冲突,
      就立即并行派发,没有并发上限。

串行:仅当存在真正的语义依赖、共享可变外部状态、
      不兼容的并发迁移等具体不安全条件时才串行。
      ——仅仅"会编辑同一个文件"不足以成为等待理由。

另外,ship 任务的交付模式和 yolo 合并姿态在 intake 时就定死:显式传给 brief、显式传给 spawn 和任何 scout promotion——每个命令都拒绝猜测自己消费的值(refuses to guess)。简报中记录的模式是一条固定的机器可读行,worker 收到的指令与记录的交付方式不可能 diverge。

8.6 升级原则:只升级真正的决策

fleet 运转起来后,captain 最怕的是被海量例行通知淹没。FirstMate 的升级(escalation)原则是:

text
firstmate 只把真正的决策升级给 captain;
例行通知由 bash watcher 自行处理(zero-token supervision,见第 11 章)。

配合 crewmate 通信纪律(hard rule 4:crewmate 永远不直接对话 captain,所有通信流经 firstmate),形成一条干净的指挥链:

text
captain ⇄ firstmate ⇄ 每个 crewmate(各自的 session endpoint)

如果 captain 直接在某个 crewmate 窗口插话,该干预被视为权威(authoritative),但会在下一次监督评审时被 reconcile——保证状态最终一致。

本章小结

  • FirstMate 只有两种任务形态:ship 交付被授权变更,scout 交付 data/<id>/report.md 知识报告且绝不 push;
  • scout 报告在 teardown 后保留,其 worktree 是 scratch,须待报告存在且 decision inventory 完成后才可丢弃;
  • intake 契约克制使用 scout:仅当 captain 明确要求知识交付物、或未决不确定性会实质改变建什么时才派;已有证据直接回答;
  • spawn 有两道硬门禁:真实且异于主 checkout 的 worktree root + base-freshness 对齐 origin 默认分支 tip;
  • 独立可实施的变更立即并行、无并发上限;仅真语义依赖才串行;交付模式在 intake 定死并显式传递,命令拒绝猜测。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. scout 任务的正式交付物是什么?

2. 根据 hard rule 3,scout 的 worktree 何时可以被丢弃?

3. 以下哪种情况应该派出一个 scout 任务?

4. fm-spawn.sh 的 base-freshness 门禁要求什么?

🛠️ 动手实践

  1. 把下列请求分类为 ship 或 scout,并用 8.4 的 intake 契约写出理由:(a)"查一下 CI 为什么最近变慢";(b)"给设置页加暗色模式";(c)"评估 Redis 和 Memcached 哪个更适合我们的缓存层,结论会影响架构选型"。其中哪一个是"既有证据可直接回答、不应派 scout"的反例候选?说明你的判断依据。
  2. 手动模拟 base-freshness 门禁:在一个测试仓库的主 checkout 里制造一个落后于 origin/main 的 worktree(或在本地用 git update-ref 模拟过期 tip),观察 fm-spawn.sh 的拒绝行为;然后把 worktree fetch 到最新再试一次,对比两次结果并记录元数据差异。
  3. 设计一个三任务并行的委派方案:同一仓库上同时进行"修 flaky 测试"、"补 API 文档"、"升级依赖 minor 版本"。按 8.5 的并发规则逐项检查这三个任务是否满足"独立实施 + 独立验证 + 交付路径可调和冲突",若有任务必须串行,指出具体的不安全条件(注意"同文件编辑"本身不算理由)。