Skip to content

第 17 章 · 实战二:多项目并行交付流水线

本章目标:同时推进三个不同项目的任务,掌握 firstmate 的并行路由、dispatch profiles 选型与分项目的合并权限管理,把「一支舰队」用成一条交付流水线。

17.1 场景设定:三个项目、三种任务形态

单任务串行只是起步。FirstMate 的真正价值在于:你描述清楚要做什么,firstmate 把每个请求路由到独立的会话端点 + 独立的 git worktree,互不阻塞。本章设定三条并行工作线:

text
项目 A(web-api)    :ship 任务——修复一个偶发 500 的 bug
项目 B(data-pipeline):scout 任务——只读架构审计,产出报告
项目 C(cli-tool)   :ship 任务——新增一个小的 --version 子命令

三条线覆盖了第 8 章学过的两种任务形态和第 10 章的三种项目模式,是日常使用的典型缩影。

17.2 一次下达多个任务

不需要排队逐个交代。用一条自然语言消息把三件事一起说清:

text
> 三件事并行:
> 1) web-api 仓库修掉 /search 偶发 500 的 bug,走完整校验出 PR;
> 2) data-pipeline 只做架构审计:数据流、模块边界、技术债清单,
>    出报告不要动代码;
> 3) cli-tool 加一个 --version 子命令,本地验证后走 local merge。

你应该看到什么:firstmate 逐条复述并确认理解(包括每条的任务形态),随后派生最多三个船员,tmux 里出现多个 fm-task* 窗口;各窗口各自推进,完成顺序不必一致。

这里隐含两条机制值得回顾:

  • worktree 隔离(第 9 章):三个船员即使涉及同名文件也不会互相踩踏,因为每人一份干净 worktree;
  • 零 token 监督(第 11 章):watcher 睡在后台,谁完成、谁卡住才唤醒 firstmate 向你汇报,等待期间不烧 token。

17.3 用 dispatch profiles 给不同任务选不同的 harness

默认情况下所有船员都用同一个 crewmate harness(config/crew-harness)。当不同任务的性质差异很大时,可以启用 dispatch profiles:一个可选的本地 gitignored 文件 config/crew-dispatch.json,里面写自然语言规则,由 firstmate 在派发前阅读并用判断力匹配。

json
{
  "rules": [
    {
      "when": "bug 修复或需要跑完整测试流水线的 ship 任务",
      "use": [{ "harness": "claude", "effort": "high" }],
      "why": "修复类任务需要强工具调用与长上下文"
    },
    {
      "when": "架构审计、代码调研类 scout 任务",
      "use": [
        { "harness": "pi", "model": "deepseek-chat" },
        { "harness": "grok" }
      ],
      "why": "调研以低成本大吞吐优先,数组形式做配额感知的备选"
    }
  ],
  "default": [{ "harness": "claude" }]
}

官方 schema 要点:

  • 每条规则必须有 whenuseuse 和顶层 default 都接受单个 profile 对象或非空数组(数组经 quota-array-dispatch 做配额感知选择);
  • modeleffortlow|medium|high|xhigh|max)与规则级 why 都是可选,省略即用该 harness 自身默认值;
  • shell 脚本不解析语义——匹配规则靠 firstmate 的判断,脚本只负责把选中的 --harness/--model/--effort 具体参数传给 fm-spawn.sh 并校验 JSON 形状(bootstrap 用 jq 验证,非法配置报 CREW_DISPATCH: invalid ... 诊断而不是被悄悄绕过)。

两个必须知道的行为变化:该文件一旦存在,fm-spawn.sh 会拒绝任何没有显式 harness 的船员/scout 启动config/crew-harness 不再自动兜底);secondmate 的启动豁免于此约束,仍走 config/secondmate-harness。另外这份文件会被继承进 secondmate home,让整个舰队共享同一套派发策略。

bash
# 写好后无需重启,下次 bootstrap 自动校验生效
cat config/crew-dispatch.json | jq empty && echo "JSON OK"

17.4 分项目设定合并权限:三种模式各就各位

第 10 章讲过,每个项目的常设姿态记录在 data/projects.md,本章给三个项目分别指派最合适的模式:

项目模式理由
web-apidirect-PRbug 修复希望尽快出 PR 走 CI 复核,不需要 no-mistakes 全量校验管线
data-pipeline(无 ship)scout 任务永不 push,不存在合并问题
cli-toollocal-only小特性本地快改,由 firstmate 在你批准后做 fast-forward 本地合并即可

三种模式的官方语义一句话版:no-mistakes 跑完整校验管线、direct-PR 跳过该管线直接开 PR、local-only 停在本地直到 firstmate 执行一次经批准的 fast-forward 合并。可选的 +yolo 标志授予合并自治权——本章刻意不用它,让每一次合并都过你的手。

还有一个安全细节:若某个 ship 任务的执行严格度低于该项目登记的姿态,spawn 时会打印 deviation notice 并继续——登记不是摆设,偏差会被显式暴露。

17.5 决策积压处理:/ahoy 与 /bearings file include PRs

并行任务越多,升级到你面前的决策就越多。两个内置技能构成你的「值班仪表盘」:

text
> /bearings file include PRs

这条命令生成四段式摘要的同时,把带日期的版本报告写入 data/status-report-<YYYY-MM-DD>.md,并通过实时 PR 信息增强内容——适合作为每日开工的第一条指令。

text
> /ahoy

/ahoy 会回顾自你上一条真实消息以来的会话事件,加上未被回应的 captain 决策,然后按影响顺序一次一个引导你把悬而未决的事项处理完。并行场景下建议养成节奏:开工 /bearings,收工前 /ahoy 清空决策队列再离开。

17.6 故意制造冲突:亲眼看 unlanded-work 保护

现在做一个受控实验来理解硬规则 3。趁某个船员还在 worktree 里干活时,你在同一仓库的主 checkout 手动改动文件并保持未提交状态,然后催促任务收尾。

预期行为链:

  1. 船员的产出照常落地为它的分支/PR——不受你本地脏状态影响(隔离的价值);
  2. 但任何涉及你未提交改动的 teardown/landing 动作都会被拒绝:uncommitted changes are never landed;
  3. 只有当你明确授权丢弃那部分工作时,才可能绕过拒绝(且 --force 类操作仍需点名的授权)。

这个实验的结论是:FirstMate 对「未落地的劳动」采取保守保护——宁可停下来问你,也不静默销毁或代你提交。

17.7 收尾与复盘

三条线全部到达终点后,逐项复盘:

text
> /bearings

对照检查:A 的 PR 是否带着 risk 标注与 CI 结论?B 的报告是否落在 data/<id>/report.md 并附 decision inventory?C 是否在你批准后完成了 fast-forward 合并而没有产生远程分支?最后让 firstmate 对空闲船员做 teardown——记住空闲的 pane 是健康状态,只有存在 in-flight 工作时 teardown 才会拒绝。

本章沉淀出的流水线节拍可以固化为习惯:开工 /bearings file include PRs → 一句话下达批量任务 → 中途 /ahoy 清决策 → 合并逐个过手 → 收工复盘 + teardown

17.8 本章小结

  • 多任务并行只需一条结构清晰的自然语言消息,路由、隔离、监督全部由 firstmate 负责;
  • config/crew-dispatch.json 用自然语言规则按任务性质选 harness/model/effort,文件存在后 spawn 必须携带显式 harness,配置由 jq 校验且可被 secondmate home 继承;
  • 项目模式是合并权限的最小授权单位:no-mistakes 全量校验、direct-PR 快速出 PR、local-only 本地 fast-forward,严格度偏差会有 deviation notice;
  • /ahoy 按影响顺序逐一清理决策积压,/bearings file include PRs 是并行期的标准日报;
  • unlanded-work 保护在人为制造冲突时依然成立:未提交的工作绝不静默落地或销毁。

🧪 随堂测验

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

1. 关于 config/crew-dispatch.json 的规则匹配,正确的说法是?

2. 一旦 config/crew-dispatch.json 存在,下列哪个说法正确?

3. cli-tool 项目采用 local-only 模式,其官方语义是?

4. 船员仍在工作时,你手动在同一仓库留下未提交改动并催促收尾,firstmate 会如何处理这部分改动?

🛠️ 动手实践

  1. 为你的舰队编写一份包含至少两条规则和一个 default 的 config/crew-dispatch.json(规则覆盖 ship 修复类与 scout 调研类),用 jq empty 验证语法,然后重新启动 primary 观察是否有 CREW_DISPATCH 诊断输出。
  2. 同时向两个自己的项目下达一 ship 一 scout 两个任务,期间运行 /bearings file include PRs,核对生成的 data/status-report-*.md 内容是否正确区分了两类任务的进度。
  3. 复现 17.6 的冲突实验:在船员工作期间向同一仓库主 checkout 写入未提交改动,观察 teardown 的拒绝行为,最后明确授权丢弃后再确认清理成功,并把全过程记录成一篇笔记。