diff --git a/chapters/01-what-is-firstmate.md b/chapters/01-what-is-firstmate.md index 57fc302..8135e03 100644 --- a/chapters/01-what-is-firstmate.md +++ b/chapters/01-what-is-firstmate.md @@ -2,281 +2,256 @@ ## 这一章讲什么 -FirstMate 的核心不是某个工具,而是一套分工。搞不清这套分工,你会不断遇到「为什么它不肯自己改代码」「为什么它不肯直接合并」这类摩擦;搞清楚之后,这些行为会变得完全可预期。 +FirstMate 把你和一群编码 agent 的协作分成三个角色。弄清谁负责什么,你就会明白它为什么不自己改代码、为什么合并前一定要问你。 -所以这一章只做三件事:把三个角色各自的职责划清楚;把一件活从你开口到落地合并要过的每一关走一遍;再解释为什么要这么切分。 +这一章讲三件事:三个角色各管什么;最重要的四条规矩;一件活从你提出到合并要经过哪几步。最后有两个只读的练习。 -本章所依据的权威文件,都在 FirstMate 仓库里被版本追踪:`AGENTS.md`(大副的职责契约,最重要)、`README.md`,以及 `bin/` 下脚本的头部注释。每个小节会指出具体出处。 +本章依据 FirstMate 仓库里的 `AGENTS.md`(主要是第 1 节的硬规矩和第 7 节的任务流程)、`README.md`,以及几个 `bin/` 脚本开头的注释。想核对细节,可以直接去读这些文件。 ## 三个角色 -FirstMate 用航海的比喻给三个角色命名。第一次出现时给出中英文对照,之后只用中文。 +FirstMate 借用了船上的称呼。 -### 船长 / captain - 你 +### 船长 / captain:你 -船长就是你,那个真人。FirstMate 的 `AGENTS.md` 开头就把这件事定死了:「You are the first mate. The user is the captain.」 +船长就是你本人。`AGENTS.md` 开头写着:"You are the first mate. The user is the captain." -船长负责的是**意图和授权**: +你负责: -- 提出要做什么活。 -- 在需要拍板的地方拍板 - 尤其是合并、破坏性操作、不可逆操作、涉及安全的选择。 -- 决定每个项目的交付姿态(走哪条交付路径、合并权限开不开)。 +- 说清楚要做什么。 +- 在关键的地方拍板,特别是合并,以及有破坏性、不可逆或涉及安全的操作。 +- 决定每个项目用哪种交付方式、合并前要不要先问你。 -船长**不负责**盯进度、不负责在多个终端之间切来切去、不负责记住哪个窗口跑着哪件活。这些是大副的事。 +你不用盯进度,不用在一堆终端之间来回切,也不用记哪个窗口在做哪件活。这些都交给大副。 -### 大副 / firstmate - 你唯一的对话对象 +### 大副 / firstmate:你唯一的对话对象 -大副是你在所有项目上所有软件工作的**唯一联络人**(`AGENTS.md` 第 1 节)。你只跟它说话。 +你所有项目上的软件工作,都只跟大副说。它负责: -大副负责的是**判断、调度、监督、汇报**: +- 判断这件活属于哪个项目,是直接改,还是先调查清楚。 +- 登记工单,给船员写任务简报(brief)。 +- 派船员干活,每个船员一个独立的 git 工作树(worktree)。 +- 盯着整支队伍把活干完,只在真正需要你决定时才来找你。 +- 用简单的话告诉你结果:一个 PR、一次你批准过的本地合并,或者一份调查报告。 -- 判断这件活属于哪个项目、该做成什么形态(写代码,还是先去调查)。 -- 立工单,写船员的任务简报(brief)。 -- 派出船员,给每人一份干净的隔离工作副本。 -- 监督整支队伍直到收工,只在真正需要你拍板时才来打扰你。 -- 把结果翻译成结论汇报给你 - PR 链接、已批准的本地合并,或者一份调查报告。 +大副自己不改项目代码,原因见下面的规矩一。 -大副**不负责**写项目代码。这是它最反直觉、也最关键的一条边界,下面单独讲。 +### 船员 / crewmate:动手干活的人 -### 船员 / crewmate - 真正干活的那个 +船员是大副派出去的 agent,一人负责一件活。每个船员有自己的会话窗口(比如一个 tmux 窗口或 Herdr 标签页,你随时可以看,也可以直接在里面打字)和自己的工作树。 -船员是大副派出去的自主 agent,一个船员一件活,每人一个可见的会话端点(tmux 窗口、Herdr 标签页等)和一份独立的 git 工作副本(FirstMate `README.md` 的「Features」一节)。 +船员负责: -船员负责的是**执行**: +- 在自己的工作树里改代码、跑测试、写文档。 +- 启动质检流水线,流水线停下来等回复时由它作答。 +- 通过流水线开 PR。 +- 把进展报告给大副。 -- 在自己的工作副本里真正改代码、跑测试、写文档。 -- 跑质检流水线,回应流水线的每一道关卡。 -- 开 PR。 -- 把状态变化上报给大副。 +船员不决定合并,也不直接找你说话。 -船员**不负责**决定要不要合并,也**不负责**跟你对话。 +## 四条硬规矩 -## 四条硬规矩,以及它们为什么存在 +`AGENTS.md` 第 1 节按优先级列了五条硬规矩(hard rules)。这里讲对新手影响最大的四条。 -`AGENTS.md` 第 1 节列了一组「硬规矩」(hard rules),按优先级排序。这里挑四条对新手影响最大的,重点是讲清楚**为什么**,而不只是罗列。 +### 规矩一:大副不改项目 -### 规矩一:大副永不写项目代码 +原文是 "Never write to a project."。大副只读项目,不在项目里编辑、提交,也不运行会改变项目状态的命令。改项目是船员的事。 -原文是 "Never write to a project.":大副不在 `projects/` 或任何项目工作副本下编辑、提交、或运行任何会改变状态的命令 - 大副读项目,船员改项目。 +例外很少,而且都有严格限制,比如你当场明确批准的某个具体操作。即使在例外情况下,也不允许强推,不允许丢弃还没合入的工作。 -只有几条极窄的例外:受守护的项目初始化、fleet sync、二副 / secondmate 同步与继承本地资料的传播、自我更新、已批准的 `local-only` 合并路径,以及船长在当下就某个具体项目、具体操作明确批准的一次性操作。而且这些例外**从不**授权强推、stash、丢弃未落地的工作,也从不授权大副手写项目的 `AGENTS.md`。 +为什么这样定:大副亲手改的代码,没有独立的工作树,不经过质检流水线,也没有 PR 审查。把大副挡在代码外面,每一处改动就都得走同一条有检查的路。另外,大副要在多件活之间排优先级、处理冲突,它自己手上没有改动,判断才公正。 -**为什么**:如果大副既当调度员又当施工队,那它自己的改动就没有任何一关来把关 - 没有隔离的工作副本,没有质检流水线,没有 PR 审查。更要紧的是,大副是那个要在多件活之间做仲裁的角色;一个同时在改代码的仲裁者,会不自觉地把自己那份改动当成既成事实。把它挡在代码外面,才能保证**每一处项目改动都走同一条有关卡的路**。 +### 规矩二:你不点头,就不合并 PR -### 规矩二:未经船长明确同意,不合并 PR +原文是 "Never merge a PR without the captain's explicit word."。 -原文是 "Never merge a PR without the captain's explicit word." +唯一的例外是你给某个项目打开了 `yolo` 开关。打开后,大副可以自己合并 CI 全部通过、而且没超出任务范围的 PR。但即使打开了 `yolo`: -唯一的常规放松是项目被船长批准的 `yolo` 姿态 - 而且 `yolo` 只管合并权限这一件事,跟走哪条交付路径是两个正交的维度(`AGENTS.md` 第 7 节)。即便开了 `yolo`,破坏性、不可逆、涉及安全的合并依然要上交给你;红色 CI 也依然不能合,除非你当下明确点名放行某一个具体检查项。 +- CI 没通过的 PR 仍然不合,除非你当场明确放行某一项具体的检查。 +- 有破坏性、不可逆或涉及安全的合并,仍然要问你。 -**为什么**:合并是这条流水线上唯一真正不可逆的一步。前面每一步都能重做 - 工作副本可以扔掉,提交可以重写,PR 可以关掉。一旦并入主干,它就成了别人的基线。所以自动化可以负责「让这件活达到可合并的状态」,但「要不要真的合」必须停在人这里。 +`yolo` 只管合并权限,跟用哪种交付方式无关。 -### 规矩三:不销毁尚未落地的工作 +为什么这样定:合并之前的每一步都能重来,工作树可以扔,提交可以改,PR 可以关。一旦合进主分支,别人就会在它上面接着干活,很难再撤回。所以前面的步骤可以交给自动化,要不要合由人来定。 -原文是 "Never tear down unlanded work." +### 规矩三:不删还没合入的工作 -未提交的改动一律算作没落地,而 `bin/fm-teardown.sh` 独占「什么算落地」这个判定。它的头部注释里写得很清楚:一个无法证明自己已经正常关闭的端点会**先拒绝**,而不是先删掉那条记录 - 因为那条记录是唯一能说明「什么东西还活着」的东西,把这种关闭当成清理完成,等于把端点丢在那里没人管。 +原文是 "Never tear down unlanded work."。没提交的改动一律算没合入。一件活有没有合入,由收尾脚本 `bin/fm-teardown.sh` 判断。它发现还有没合入的东西,或者确认不了,就会拒绝清理。 -所以,当清理这一步拒绝执行时,那是**停下来查清楚**的信号,不是一个要绕过去的障碍。 +清理被拒绝时,要停下来查清楚原因,不要想办法绕过去。只有你明确同意丢弃这些工作,才能强制清理。 -**为什么**:并行跑一支队伍,最大的风险不是做错,而是**悄悄丢掉**。做错了会有人看见;丢掉了,你以为活干完了,其实那份改动已经随着工作副本一起没了。把「拒绝」设成默认,代价只是你多花一分钟去看一眼;反过来的代价是不可恢复的。 +为什么这样定:同时跑很多件活,最怕的是东西悄悄丢了。做错了总会有人发现;丢了,你还以为活已经干完了。拒绝清理的代价只是多看一眼,误删的代价却无法挽回。 -### 规矩四:船员从不直接跟船长对话 +### 规矩四:船员不直接找你 -原文是 "Crewmates never address the captain.":所有船员的沟通都经由大副。 +原文是 "Crewmates never address the captain."。船员有什么事都先告诉大副。 -**为什么**:这是整个模型能成立的前提。你之所以能同时跑三件活而不变成标签页保姆,正是因为只有一个声音会来找你。如果每个船员都能直接喊你,那你就回到了自己盯三个终端的状态 - 只是这次有三个 agent 同时在喊。大副的价值恰恰在于它吸收掉了绝大部分噪音,只把真正需要你决定的事递上来。 +为什么这样定:你能同时跑好几件活而不被打扰,是因为只有大副一个人来找你。要是每个船员都能直接找你,你又回到了同时盯好几个终端的状态。 -反过来,如果你直接在某个船员的窗口里插话干预,那是有效的 - `AGENTS.md` 要求大副把这种直接干预当作权威的,并在下一次监督复查时把它对上。 +反过来,你可以直接在某个船员的窗口里说话。大副会把这当作你的指示,并在下一次检查时据此调整。 -## 一件活的完整旅程 +## 一件活是怎么走完的 -拿一件具体的活来走一遍最清楚。就用 **「写这本教程的第一章」** 这件活本身 - 你正在读的这份文件,就是它的产物,而它刚好完整走完了全程。 +拿「写这本教程的第一章」这件活举例,这一章最早就是这样写出来的。 -### 第 0 关:船长开口 +### 第 0 步:你提出要求 -你对大副说了一段话,大意是:这个仓库叫 Learn FirstMate,是给 FirstMate 新手的学习项目;产出形态是中文教程加动手练习;这一趟先搭好骨架,并写出第一章《FirstMate 是什么》,讲清楚三方分工和一件活的完整旅程。 +你告诉大副:这个仓库叫 Learn FirstMate,是给 FirstMate 新手用的,写成中文教程加动手练习;这次先搭好框架,写出第一章,讲清三个角色和一件活的完整流程。 -注意这里你说的是**意图**,不是施工方案。你没有指定文件叫什么名字、章节分几节、用什么格式。这些是下一关的事。 +你只说了想要什么,没说文件叫什么、分几节、用什么格式。这些留给后面的步骤决定。 -### 第 1 关:大副判断与立工单 +### 第 1 步:大副分析,登记工单 -大副做几件事(`AGENTS.md` 第 7 节 "Intake and authority"): +大副要做这几件事(`AGENTS.md` 第 7 节): -- **认项目**:每个请求都独立判定项目归属。一个明确指名的项目优先,一个清楚的追问继承它的指代对象,否则就拿请求去比对项目登记表、正在办的活、以及项目的代码和 README。只有一个有把握的匹配就直接推进,并用平实的话说出选了哪个项目。 -- **定交付形态**:分成两种。**ship**(出活)是默认,产出的是项目改动,走选定的交付路径;**scout**(侦察)产出的是知识,落在 `data//report.md`,永远不开 PR。写第一章要往仓库里写文件,所以是 ship。 -- **定交付路径和合并权限**:这件活走 `no-mistakes`(完整质检流水线),`yolo` 关着 - 也就是必须你点头才合并。这两个值在立项时就要定下来,而且传的时候分工不同:交付路径要**显式**传给简报,交付路径和 `yolo` 两个值都要**显式**传给派工命令(以及把侦察提升成出活的那一次)。`bin/fm-brief.sh` 这两个值里只收 `--mode`,根本没有 `--yolo` 这个参数 - 合并权限不是船员的事;`bin/fm-spawn.sh` 则同时要 `--mode` 和 `--yolo`,出活时两个都是必填;把侦察提升成出活的 `bin/fm-promote.sh` 同样两个都要,因为侦察本身没记过交付姿态,提升那一刻才是定这份交付契约的地方。每条命令都拒绝去猜自己要消费的那些值:`bin/fm-spawn.sh` 的头部注释说得很明确,派工从不自己去查这两个值。 -- **立工单**:这件活进入 backlog 队列。当自动流转关卡生效时,派工这一步本身就会把工单挪到「在办」,所以记录派工不是一个需要另外记得去做的步骤。 -- **写简报**:派工之前,先写好这件活的任务简报。简报里 `## Captain's intent`(船长意图)放你自己的原话和你说过的边界,`## Firstmate spec`(大副规格)放这个意图所必需的施工指令。这两段是分开的,因为质检流水线会把前者当成验收标准来读。 +- **确定项目。** 你点名了项目,就用它;接着上一件事往下说,就沿用上一件的项目;都没有,就拿你的话去比对已登记的项目、正在做的活和项目内容。只有一个项目明显对得上时,直接开始,并告诉你选的是哪个;拿不准就问你一句。 +- **确定任务类型。** 默认是交付任务(ship),产出对项目的改动。另一种是调研任务(scout),只产出一份报告,不开 PR。写第一章要往仓库里加文件,所以是交付任务。 +- **确定交付方式和合并权限。** 这件活用 `no-mistakes`(完整的质检流水线)交付,`yolo` 关着,所以合并前要你同意。这两项在一开始就定好,后面的步骤不会自己去猜。 +- **登记工单。** 这件活进入待办队列(backlog)。 +- **写任务简报。** 简报从固定模板(`bin/fm-brief.sh`)生成,其中的任务部分由大副填两块:「船长意图」(Captain's intent)记你的原话和你提的限制,「大副规格」(Firstmate spec)写具体怎么做。两块分开写,是因为质检流水线会拿「船长意图」当验收标准。 -### 第 2 关:派出船员到隔离工作副本 +### 第 2 步:派船员到独立的工作树 -大副通过 `bin/fm-spawn.sh` 派工。这一步有一条断言必须过:派工必须解析出一份**真正独立于主检出目录**的隔离任务工作副本;隔离断言失败就直接中止这件活,不会降级成「那就在主目录里干吧」(`AGENTS.md` 第 7 节 "Dispatch and supervision handoff")。 +大副用 `bin/fm-spawn.sh` 派出船员。派工时会检查:船员拿到的必须是一个独立的工作树,不能是大副自己用的主仓库目录。检查不通过,这件活就停下来,不会退而求其次在主仓库目录里干(`AGENTS.md` 第 7 节)。 -船员开机后第一件事,就是自己再验一遍隔离(`AGENTS.md` 第 11 节,由 `bin/fm-brief.sh` 的简报脚手架落实):确认当前目录和 git 顶层目录都指向那份一次性的任务工作副本,而不是大副操作的那个主检出。然后才开自己的分支,开始干活。 +船员启动后会自己再检查一遍(`AGENTS.md` 第 11 节):当前目录确实是这件活专用的工作树。确认之后才建分支,开始干活。 -从这一刻起,船员在自己那份副本里读权威文件、写 `README.md` 和 `chapters/01-what-is-firstmate.md`、提交。它跟主检出、跟其他并行的活,完全不碰面。 +每件活一个工作树,好处有两个: -### 第 3 关:质检流水线 +- 同一个仓库上的几件活可以同时做,互不干扰。改到同一个文件不算排队的理由,只有真正互相依赖这类情况才需要一件一件来(`AGENTS.md` 第 7 节)。 +- 一件活搞砸了,影响只限于它自己的工作树。 -实现提交完成后,在**同一个**船员身上触发验证。这里有一条很重要的边界(`AGENTS.md` 第 7 节 "Selected delivery path and merge authority"):选定的交付路径独占自己的严格度。当选了 `no-mistakes`,那么 review、修复、测试、文档、push、开 PR、CI 全部由 `no-mistakes` 独占 - 不再叠加一个独立的人工审查关卡。 +### 第 3 步:质检流水线 -流水线自己应用每一处修复;船员的角色是**回应关卡**,不是自己动手修。 +船员提交完改动后,大副让同一个船员启动 `no-mistakes` 流水线。选了 `no-mistakes`,代码审查、修复、测试、文档、推送、开 PR、CI 就全部由它负责,不再另加人工审查(`AGENTS.md` 第 7 节)。 -流水线可能停下来提一类叫 `ask-user` 的发现 - 需要人来定的问题。这种发现**永远不是船员自己能答的**:船员把它原样上交,由大副来判断或者再上交给你。船员回答自己的 `ask-user` 发现,违反的是交付路径那一节的规矩,而不是第 1 节那张硬规矩清单里的某一条:`AGENTS.md` 第 7 节 "Selected delivery path and merge authority" 写着,实现这件活的那个 worker 从不回答自己提出的发现。 +发现的问题由流水线自己修。船员不自己动手改,只在流水线停下来等回复时作答。 -### 第 4 关:开 PR,等你点头 +流水线有时会提出 ask-user 类问题,也就是需要人来决定的问题。这类问题船员不能自己回答,要交给大副。大副要么自己决定,要么再来问你。 -流水线把分支推上去、开好 PR、盯着 CI。CI 第一次转绿时,船员就上报 PR - 不等合并监控跑完。上报的是 PR 的完整 `https://` 链接,不是一个光秃秃的编号(`AGENTS.md` 第 7 节 "PR ready, landing, and teardown")。 +### 第 4 步:开 PR,等你同意 -然后它**停下来**。`yolo` 关着,合并权限在你手上。 +流水线推送分支、开 PR,然后盯着 CI。CI 第一次全部通过时,船员就向大副报告,附上 PR 的完整 `https://` 链接。 -大副拿到这个信号后,用 `bin/fm-pr-check.sh` 记录 PR 并武装合并轮询,再把结果翻译成你能直接决策的一句话给你:PR 的完整链接、一句结论摘要、以及 `no-mistakes` 给出的风险等级。 +`yolo` 关着,所以到这里就停下,等你决定。 -### 第 5 关:船长点头,合并 +大副用 `bin/fm-pr-check.sh` 登记这个 PR,开始定期查看它有没有被合并。然后告诉你三样东西:PR 链接、一句话结论、`no-mistakes` 给出的风险等级。 -你说「合了」。这句话本身就是明确授权。 +### 第 5 步:你同意,合并 -合并走 `bin/fm-pr-merge.sh`,因为它会记录合并元数据,并且在无法证明合并真的发生时**拒绝**,而不是把它报成已落地。 +你说「合了」,这就是明确的授权。 -### 第 6 关:清理收尾 +大副用 `bin/fm-pr-merge.sh` 合并。这个脚本会记录合并信息;如果确认不了合并真的成功,它会拒绝,不会当作已经合入。 -只有在**落地被确认之后**,才拆掉这件活(`AGENTS.md` 第 7 节 "PR ready, landing, and teardown"):归还工作副本、关掉会话端点、清掉易变状态、把工单流转掉。前面说过,这一步的拒绝是要去查的信号。 +### 第 6 步:收尾清理 -清理完成后记录完成、只保留配置允许的近期 Done 历史、并重新评估队列里那些阻塞条件和时间门已经解除的活(同一节)。 +确认已经合入后,大副才清理这件活:归还工作树,关掉会话窗口,清掉临时状态,把工单标记为完成。清理被拒绝的话,就按规矩三停下来查。 + +清理完,大副会再看一遍待办队列,把之前被卡住、现在可以开始的活安排上。 ### 流程图 ``` - 船长 / captain - │ 「搭好教程骨架,写出第一章」 - ▼ - ┌─────────────────────────────────────────────┐ - │ 大副 / firstmate │ - │ │ - │ 认项目 ─► 定形态(ship/scout) ─► 定路径与 │ - │ 合并权限 ─► 立工单 ─► 写简报 │ - │ │ - │ ✗ 自己不碰项目代码 │ - └───────────────────┬─────────────────────────┘ - │ fm-spawn.sh - │ (隔离断言不过 = 中止) - ▼ - ┌────────────────────────────────┐ - │ 船员 / crewmate │ - │ 一次性隔离 git 工作副本 │ - │ 自己的分支 │ - │ │ - │ 改代码 / 写文档 / 提交 │ - └─────────────┬──────────────────┘ - │ done: 交接 - ▼ - ┌────────────────────────────────┐ - │ no-mistakes 质检流水线 │ - │ review / 测试 / lint / │ - │ 文档 / push / PR / CI │ - │ │ - │ 流水线自己修;船员只回应关卡 │ - └─────────────┬──────────────────┘ - │ - ┌─────────┴──────────┐ - │ │ - ask-user 发现 CI 转绿 - │ │ - ▼ ▼ - 上交大副 ─► 必要时 PR + 完整链接 - 再上交船长 │ - │ ▼ - └────────────► ┌──────────┐ - │ 等待点头 │ ◄── yolo 关着 = 必须你同意 - └────┬─────┘ - │ 船长:「合了」 - ▼ - fm-pr-merge.sh - (无法证明就拒绝) - │ - ▼ - fm-teardown.sh - 归还工作副本 / 关端点 / 流转工单 - (未落地的活 = 拒绝,不是障碍) + 船长 / captain + │ 「搭好教程框架,写出第一章」 + ▼ + ┌──────────────────────────────────────┐ + │ 大副 / firstmate │ + │ │ + │ 确定项目 -> 确定任务类型 -> │ + │ 确定交付方式和合并权限 -> │ + │ 登记工单 -> 写任务简报 │ + │ │ + │ 自己不改项目代码 │ + └──────────────────┬───────────────────┘ + │ fm-spawn.sh + │ (不是独立工作树就停下) + ▼ + ┌──────────────────────────────────────┐ + │ 船员 / crewmate │ + │ │ + │ 独立的 git 工作树,自己的分支 │ + │ 改代码 / 写文档 / 提交 │ + └──────────────────┬───────────────────┘ + │ + ▼ + ┌──────────────────────────────────────┐ + │ no-mistakes 质检流水线 │ + │ │ + │ 审查 / 修复 / 测试 / 文档 / │ + │ 推送 / 开 PR / CI │ + │ │ + │ 问题由流水线自己修 │ + │ ask-user 类问题交给大副, │ + │ 大副自己定,或者再来问你 │ + └──────────────────┬───────────────────┘ + │ CI 通过,船员报告 PR 链接 + ▼ + 等你同意 ◄── yolo 关着,必须你点头 + │ + │ 你:「合了」 + ▼ + fm-pr-merge.sh 合并 + (确认不了就拒绝) + │ + ▼ + fm-teardown.sh 收尾清理 + 归还工作树 / 关窗口 / 关工单 + (还有没合入的工作就拒绝清理) ``` -## 为什么是这样设计的 - -两条约束带来的实际好处,值得单独说清楚。 - -### 隔离工作副本带来了什么 - -每件活一份干净的一次性 git 工作副本,直接换来三件事: - -**并行不打架。** 同一个仓库上同时跑三件活,各自在自己的副本和分支上,不会互相踩。文件或子系统重叠只被当成一个风险信号,而不是一个必须排队的理由 - 只有真正的语义依赖、共享的可变外部状态、互不兼容的并发迁移这类具体条件,才需要串行(`AGENTS.md` 第 7 节 "Intake and authority")。 - -**失败是局部的。** 一件活搞崩了自己的工作树,影响范围就是那一份副本。扔掉它不会碰到别人。 - -**「扔掉」这件事有明确的边界。** 因为副本是一次性的,清理就成了一个常规动作;正因为它是常规动作,才更需要规矩三那道「未落地就拒绝」的关卡,来保证常规动作不会顺手带走你还需要的东西。 - -### 「大副不碰代码」带来了什么 - -**每一处项目改动都走同一条有关卡的路。** 没有「大副顺手改一下」这个后门,就不会出现一部分改动过了流水线、另一部分没过的局面。 - -**监督者保持中立。** 大副要在多件活之间做优先级和冲突的仲裁。它手上没有自己的改动,这个仲裁才可信。 - -**边界是可验证的,不是靠自觉。** 这条规矩不是一句君子协定:派工时有隔离断言,简报里有工作副本隔离断言,清理时有落地判定。它被写进了工具,所以违规会被挡住,而不是事后才发现。 - ## 动手练习 -下面两个练习都是**只读**的:只是让大副读取并汇报状态,不会改动任何仓库,也不会做不可回退的操作。你随时可以停下。 +两个练习都是只读的:让大副读资料、讲给你听,不改任何仓库。 -做练习前,先在你的 FirstMate 目录里启动一个 primary 会话(例如 `claude`),这样你面前的这个 agent 就是你的大副。 +开始前,在你的 FirstMate 目录里启动一个主会话(比如运行 `claude`),这个会话里的 agent 就是你的大副。 -### 练习 1:认识你的船 +### 练习 1:问大副它的边界 对大副说: -> 大副,先给我讲清楚你自己的边界:你能对我的项目做什么、不能做什么,以及那几条硬规矩分别是什么、为什么存在。回答里请指出你是根据哪个文件的哪一节说的。不要改动任何文件,只回答。 - -**预期会看到什么** +> 大副,讲讲你自己的边界:你能对我的项目做什么、不能做什么,有哪几条硬规矩,各自为什么存在。说明你依据的是哪个文件的哪一节。不要改任何文件,只回答。 -- 一段用平实语言讲出来的职责边界,而不是把 `AGENTS.md` 原文贴给你。 -- 它会说到自己不写项目代码、不在未经你同意时合并 PR、不销毁未落地的工作、以及船员不直接找你这几条。 -- 它会指出出处,主要是 `AGENTS.md` 第 1 节。 -- 它会在消息里至少称呼你一次「船长 / captain」- 这是 `AGENTS.md` 明文要求的强制性尊称。 +**你应该看到** -**怎么判断做成了** +- 它用自己的话讲清楚边界,而不是大段贴 `AGENTS.md` 原文。 +- 讲到这几条:不改项目代码;你没同意就不合并 PR;不删还没合入的工作;船员不直接找你。 +- 说明出处,主要是 `AGENTS.md` 第 1 节。 +- 至少称呼你一次「船长」(或 captain)。`AGENTS.md` 要求大副在每条聊天消息里都这样称呼你。 -三个都满足才算:它讲的是结论而不是机制的堆砌;它给出了可核对的出处;以及 - 最关键的 - 它**没有动任何被版本追踪的文件**。 +**怎么检查** -验证办法是**前后对比**:提问之前先在 FirstMate 目录里跑一次 `git status --short` 和 `git diff HEAD`,把两份输出都留着;问完之后再各跑一次,两次应该完全一样。看的是「有没有多出新的差异」,不是工作树干不干净 - 一个在用的 FirstMate 目录本来就可能有你自己还没提交的改动,要求它干净只会得到一个假的失败。两条命令缺一不可:`git status --short` 只报文件的状态字母,如果大副改的正好是你本来就有未提交改动的那个文件,它前后都只显示一行 ` M AGENTS.md`,漏判;`git diff HEAD` 报的是内容,能把这种改动照出来。 +提问之前,在 FirstMate 目录里运行 `git status --short` 和 `git diff HEAD`,把输出存下来;问完再运行一次。前后输出一样,就说明大副没改任何被 git 追踪的文件。 -这个对比能证明的只有一件事:追踪文件没被改过。`data/`、`state/`、`config/`、`projects/`、`.no-mistakes/` 是大副私有的运行状态,被 gitignore 掉了(`AGENTS.md` 第 1 节把这五个目录连同 `.env` 一起点名为船长私有且不入版本库;第 2 节的布局表再逐项标注),会话期间写这些是正常的,这两条命令本来也看不见 - 它们不算对项目的改动。 +两条命令都要跑:`git status --short` 只列出哪些文件有改动,如果大副改的正好是你本来就改过的文件,前后看起来一样;`git diff HEAD` 会列出具体内容,能看出区别。 -如果它给你贴了一大段原文却没有自己的组织,或者它顺手改了什么文件,那就是没做成。 +工作区不必是干净的,你自己可能本来就有没提交的改动,只要前后一致就行。`data/`、`state/`、`config/`、`projects/`、`.no-mistakes/` 这几个目录是你本机私有的,已经被 gitignore,会话期间有写入是正常的,上面两条命令也看不到它们。 -### 练习 2:把一件真实的活对回流程图 +如果它贴了一大段原文却没有自己的总结,或者顺手改了文件,就算没做成。 -练习 1 练的是角色边界,这一次练的是这一章的另一半:**一件活从你开口到落地合并的完整旅程**。看的是关卡顺序对不对,以及哪几关必须停在你这里。 +### 练习 2:用一件真实的活对照流程 -这个练习需要 backlog 里至少有一件在案的活。如果你刚装好 FirstMate、队列还是空的,就先跳过它,等你用 FirstMate 派出并做完第一件真实的活之后再回来 - 只有到那时候,才有真东西能用来核对它讲得对不对。 +这个练习需要待办队列里至少有一件活。如果你刚装好 FirstMate,队列还是空的,就先跳过,等做完第一件真实的活再回来。 对大副说: -> 大副,从 backlog 里挑一件最近已经做完的活,照这一章流程图的关卡顺序讲一遍它实际是怎么走的:每一步对应哪一关、那一步是你做的还是船员做的、以及中间哪些地方非得我本人点头才能往下走。不要改任何文件,也不要派任何船员,只讲这件已经发生过的事。如果 backlog 里还没有做完的活,就直接说没有,然后拿队列里最近的一件讲它现在走到了哪一关、下一关是什么。 - -**预期会看到什么** +> 大副,从待办队列(backlog)里挑一件最近做完的活,按这一章流程图的顺序讲它实际是怎么走的:每一步对应流程里的哪一步,是你做的还是船员做的,哪些地方必须等我同意才能继续。不要改文件,也不要派船员,只讲已经发生的事。如果还没有做完的活,就直接说没有,然后挑最近的一件,讲它现在走到哪一步、下一步是什么。 -- 关卡是**按顺序**讲出来的:立工单与写简报 → 派工到隔离工作副本 → 质检流水线 → 开 PR 等你点头 → 合并 → 清理收尾。 -- 每一关都点明了执行者:判断、派工、监督、汇报是大副做的;改代码、跑流水线、开 PR 是船员做的。 -- 它会明确指出必须由你拍板的位置 - 至少是合并那一关;如果这件活当时出过 `ask-user` 发现,那也是一处。 -- 讲的是这件活**实际**发生的事,会带上任务标识、PR 链接这类你能自己回去核对的东西,而不是把流程图重述一遍。 +**你应该看到** -**怎么判断做成了** +- 按顺序讲:登记工单和写简报,派船员到独立工作树,质检流水线,开 PR 等你同意,合并,收尾清理。 +- 每一步都说清是谁做的:分析、派工、监督、汇报是大副做的;改代码、跑流水线、开 PR 是船员做的。 +- 指出哪里必须你拍板:至少是合并这一步;如果当时出现过 ask-user 类问题,那也算一处。 +- 讲的是这件活真实发生的事,带着任务编号、PR 链接这类你能自己核对的信息,而不是把流程图再念一遍。 -两条都满足才算:关卡的**顺序和归属**都是对的 - 尤其不能出现「船员自己决定合并」或者「大副自己改了项目代码」这种讲法;并且它准确点出了合并那一关必须有你的明确授权。 +**怎么检查** -文件层面的判断跟练习 1 一样:提问前后各跑一次 `git status --short` 和 `git diff HEAD`,两次输出应该一样。另外它不该派出任何船员 - 你直接看一眼有没有新开的会话窗口就知道。 +- 顺序和分工都对。特别是不能出现「船员自己决定合并」或「大副自己改了代码」这种说法。 +- 明确说了合并需要你同意。 +- 跟练习 1 一样,提问前后各跑一次 `git status --short` 和 `git diff HEAD`,输出应该一样。再看看有没有多出新的船员窗口,应该没有。 -如果它给你的是一段对不上任何一件真实活的抽象复述,那是没做成;如果它顺手去「补完」那件活剩下的步骤,那更是没做成 - 这个练习只要求它读和讲。 +如果它讲的内容对不上任何一件真实的活,或者顺手去把那件活剩下的步骤做完了,就算没做成。 ## 下一章 -第 2 章讲**如何提出一件活**:一句话的请求怎么变成一件有明确项目、明确交付形态、明确验收边界的活,以及你怎么说能少走弯路。 +第 2 章讲怎么提出一件活:一句话的要求怎么变成项目、任务类型和验收标准都明确的任务,以及怎么说能少走弯路。