第 10 章 · 项目模式与合并权限:no-mistakes / direct-PR / local-only
本章目标:掌握三种显式项目交付模式(no-mistakes / direct-PR / local-only)的语义与适用场景,理解
+yolo合并自治标志与 hard rule 2 的关系,学会为不同风险等级的项目选择合适的交付路径。
10.1 为什么交付方式必须「显式」
第 8 章我们知道了任务的两种形态:ship 改项目、scout 出报告。但 ship 任务改完代码之后,成果以什么方式落地,同样是一个必须事先说清的问题——是走完整验证管线再开 PR?是直接开 PR?还是只在本地合并?
如果这个决策留给临场发挥,就会出现两类事故:低风险改动被迫走重流程拖慢节奏;高风险改动却悄悄绕过了验证直接上线。所以 FirstMate 规定:每个任务在 intake(受理)时就确定交付模式与合并姿态,且模式一旦写进 brief 就不可漂移。
架构文档的原话是:
Delivery modes are explicit per task:
no-mistakes tasks run the full validation pipeline,
direct-PR tasks open PRs without that pipeline,
local-only tasks stay local until firstmate performs
an approved fast-forward merge.
Each task's mode and yolo merge posture are
firstmate's decision at intake.10.2 三种项目模式逐一拆解
模式一:no-mistakes(完整验证管线)
这是最重的交付路径。ship 任务跑完完整的验证管线后才允许进入合并流程。它适合核心业务仓库、生产相关代码、CI 纪律要求高的团队仓库。两个值得注意的工程细节:
- 管线在仓库里留存的验证证据会发布到一个 orphan evidence branch——一个与代码分支完全不共享历史的孤儿分支,因此证据永远不会混进 crew 分支或默认分支;
.no-mistakes/目录属于本地状态、保持 gitignore,若被误提交会被 CI 拒绝;.no-mistakes.yaml中设置的disable_project_settings: true只从受信任的默认分支副本生效,防止某条被推送的分支在验证期间偷偷启用自己的项目指令。
模式二:direct-PR(直接开 PR)
跳过 no-mistakes 管线,任务完成后直接开出 PR。适合有自己 CI 的开源风格仓库——GitHub/GitLab 的检查机制本身就是一道闸门。日常功能开发、文档改进多走这条路。
模式三:local-only(仅本地落地)
任务留在本地,直到 firstmate 执行一次经过批准的 fast-forward merge 才算落地。它不走远程 PR 路径,因此这类项目始终留在主第一副手身边管理;fleet sync 同步舰队时也会把 local-only 项目视为良性跳过(benign skip)。适合个人实验项目、还没有远程仓库的克隆。
三种模式的落地路径对比:
ship 任务完成
│
├─ no-mistakes ──→ 完整验证管线 → 孤儿证据分支留存证据 → PR 路径合并
│
├─ direct-PR ────→ 直接开 PR(依赖仓库自身 CI 把关)
│
└─ local-only ───→ 留在本地 → captain 批准后 fast-forward 合并进主本地检出10.3 模式如何流转:brief 固定,spawn 校验
模式不是一句口头约定。它的流转链路是刻意设计成「防漂移」的:
- 每个项目的常设姿态(standing posture)和可选的
+yolo标志记录在data/projects.md注册表里,作为船长的默认决定及其上下文,还包括条件性的no-mistakes-prod-only策略; - 受理任务时,firstmate 决定本任务的模式与 yolo 姿态;
- 模式被显式传给
bin/fm-brief.sh,模式与姿态两者都被显式传给bin/fm-spawn.sh和bin/fm-promote.sh——这几个命令都拒绝猜测自己消费的值; - ship brief 把模式写成一行固定的机器可读记录,spawn 若发现要启动的模式与记录不一致会拒绝启动,保证「给工人的指令」和「记录在案的交付方式」永不分叉。
data/projects.md 注册表示意(结构示意,非逐字格式):
project: github.com/captain/payments-core
posture: no-mistakes ← 常设姿态
merge: captain-approval ← 未加 yolo,默认须船长发话
project: github.com/captain/blog
posture: direct-PR
merge: +yolo ← 常设合并自治标志另外有一道「降级告警」保护:如果某次 ship spawn 的实际严谨度低于注册表中登记的水准(例如注册的是 no-mistakes 却试图按更轻的模式交付),系统会打印一条 deviation notice(偏差通知)然后继续——让你知情,但不擅自中断。
而 bin/fm-project-mode.sh 是注册表的唯一解析器,服务于那些「手头没有具体任务」的机械消费者:fleet sync 对 local-only 的跳过判定、home seeding 的拒绝与 no-mistakes 初始化等。
10.4 Hard Rule 2:没有船长的明确指示绝不合并 PR
第 4 章学过五条硬规则中的第二条:
Hard rule 2 — Never merge a PR without the captain's explicit word.
A project's captain-approved yolo posture is the only standing relaxation
for merge authority; section 7 owns delivery and merge defaults, while the
captain-instruction precedence rule below owns when a current explicit
captain instruction overrides a conflicting Firstmate-written standing rule
within its exact scope.三个层次要分清:
- 默认态:合并 PR 必须等船长明确发话("merge it");
- 常设放宽:只有船长为某个项目批准的
+yolo姿态可以常设地放宽合并权限——这是唯一的例外通道; - 指令优先级:AGENTS.md 第 7 节拥有交付与合并的默认值;而当船长当下的明确指示与 firstmate 写下的常设规则冲突时,「当下指示在其确切范围内优先」由专门的 precedence 规则裁定。
也就是说,即使你给项目开了 +yolo,你随时仍可以当场下达相反的明确指示收回这一次的决定权;反过来,没有 +yolo 时,任何「顺手合了」都是违规。
10.5 合并动作的技术保障:fm-pr-merge.sh
真正执行 PR 合并的是 bin/fm-pr-merge.sh,它在调用 forge CLI 之前通过 bin/fm-pr-check.sh 记录 pr= 与可用的 pr_head=。几条硬性约束:
fm-pr-merge.sh 的输入与校验:
输入要求:
- 必须是完整规范 URL,拒绝畸形 URL 与 repo override 标志
URL 分派:
- https://github.com/<owner>/<repo>/pull/<n>
→ gh-axi pr merge <n> --repo <owner>/<repo>(默认 --squash,
保留显式的 merge-method 标志)
- https://<host>/<path>/-/merge_requests/<n>(GitLab MR)
→ glab mr merge <n> -R https://<host>/<path>
(不加 merge-method 标志,沿用项目自身的合并方式)更重要的是合并前的实时校验。合并只在这五项条件经一次实时读取确认后才执行:
合并前置条件(live read,实时读取,不信缓存元数据):
1. MR 处于 open 状态
2. 可合并(mergeable)
3. 无冲突(conflict-free)
4. blocking discussions 已全部解决
5. 当前 head 上 pipeline 成功
满足后把这次合并绑定到该已验证 head。
记录在案的元数据永远不作为这些条件的依据——
因为一次 rebase 就会让它们过期失效。这套设计把「船长说了 merge it」翻译成了一组机器可验证的安全前提,避免人肉确认造成的遗漏。
10.6 如何为项目选择模式
给出一张决策参考表:
| 项目特征 | 推荐模式 | 理由 |
|---|---|---|
| 生产相关、核心业务库 | no-mistakes | 完整管线 + 证据留存,出错代价最高 |
| 有自身 CI 的常规开发仓库 | direct-PR | 平台检查即闸门,流程轻快 |
| 个人实验 / 无远程的项目 | local-only | 无 PR 路径可用,fast-forward 即可 |
| 高频琐碎改动 + 你完全信任 | 任一模式 + +yolo | 免去每次口头批准 |
选择时的三条经验法则:
- 看出错代价而不是改动频率:改动频繁但出错了很难回滚的(如支付、鉴权),宁可重流程;
- CI 成熟度决定 direct-PR 是否安全:仓库本身没有可靠 CI 时,direct-PR 等于裸奔;
+yolo是渐进授权:先观察一段时间某项目 firstmate 的交付质量,再考虑授予,且随时可以用当面的明确指令覆盖单次行为。
一次典型的人机合并对话是这样的:
captain> alright, merge it # CI 绿了之后,船长发话
firstmate> Aye, captain.
Verifying PR #42 is still open, mergeable, conflict-free,
with resolved discussions and a green pipeline at HEAD...
Merged (squash). Teardown queued for the task worktree.本章小结
- 三种交付模式语义分明:no-mistakes 跑完整验证管线、direct-PR 直接开 PR、local-only 留在本地等待批准后的 fast-forward 合并;模式与 yolo 姿态都在 intake 时确定。
- 模式经 brief 固化为机器可读行,
fm-brief.sh/fm-spawn.sh/fm-promote.sh全部拒绝猜测值;spawn 发现模式不符即拒绝启动,杜绝「指令与记录分叉」。 data/projects.md登记各项目常设姿态与可选+yolo;严谨度降级时打印 deviation notice 继续;fm-project-mode.sh是机械消费者的唯一注册表解析器。- Hard rule 2 默认要求船长明确发话才可合并;
+yolo是唯一的常设放宽通道,且当下明确指示可在其范围内覆盖常设规则。 fm-pr-merge.sh要求完整规范 URL,按 GitHub/GitLab 分派 CLI,并在实时读取确认 open / mergeable / conflict-free / discussions resolved / pipeline 绿五项后绑定到已验证 head 再合并。
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. 三种项目模式中,哪一种会运行完整验证管线(full validation pipeline)?
2. 关于 hard rule 2(未经船长明确指示绝不合并 PR),正确的说法是?
3. fm-pr-merge.sh 在执行合并前如何对待记录在案的元数据(如 pr=、pr_head=)?
4. local-only 项目的落地方式是什么?
🛠️ 动手实践
- 为你手头的三个真实项目分别选定交付模式(no-mistakes / direct-PR / local-only),参照本章 10.3 的示意结构写出各自的注册表条目,并用一句话说明每个选择的理由(对照 10.6 的三条经验法则)。
- 阅读 FirstMate 仓库中
bin/fm-brief.sh与bin/fm-spawn.sh的头部注释,找出「模式固定行」与「拒绝猜测」的具体实现位置,整理成一份笔记说明这条防漂移链路。 - 在一个测试仓库上演练合并决策流:开一个 PR 并等 CI 变绿后对 firstmate 说 "merge it",观察 fm-pr-merge.sh 报告的五项实时校验结果;随后再对比一个带
+yolo姿态的小项目,体会两种合并权限的差异。