campaign(战役式项目管理) 是做什么的?
主会话(主要会话)将所有者的目标转化为任务。贡献者代理在每个任务自己的分支上完成它;机器工作进入任务队列,该队列在确切提交上运行,而代理无需等待。评审者代理在需要时,从全新的上下文中审查任务。campaign land 仅在任务于确切代码上通过了检查、每项标准都有它指定的证据、并且对于审查所见的代码,所有必需的评审都已接受时,才将任务放入 main 分支。所有重要内容都存储在仓库中,因此任何代理(包括主会话)都可以被替换。
goals ─► PLAN ─► quests ─► campaign start ─► contributor ─► jobs (quiet) ─► evidence
│ │
└─► reviewer (by risk) ─► accept ─► campaign land
不变规则
- 证据,而非叙述。 只有当一项检查在将要合并的代码上作为作业运行时,才算有效;日志行或评审者的口头保证永远不能算作通过的测试。
- 每个文件集只有一个写入者。
campaign start拒绝重叠的文件集;land拒绝任务文件集之外的更改以及主会话文件的编辑。 - 先有标准,后有代码。 主会话编写每个任务的验收标准和每个标准所需的证据;贡献者从不编辑它们,更改任务文件会使先前的接受失效。
- 评审遵循风险。 每个需要审查的风险都有一名全新的评审者;一次接受仅覆盖该评审所见的代码以及评审的准确内容。
- 没有任何弱化是静默的。 降低风险、移除检查透镜或检查项、免除评审、在不运行CI的情况下合并或记录手动完成的合并,都需要一个理由,并且工具会记录该理由。
- 状态存在于文件中。
.campaign/<campaign>/目录和git保存着如何运行战役;对产品做什么的描述则放在它所描述的仓库的docs/中。 - 代理从不等待机器,度量从未在无隔离的环境下运行。
- 所有者决定目标、范围以及任何对用户可见行为的移除或缩减。 主会话决定其余部分并将其记录在
PLAN.md中。Campaign 从不租用机器或创建任何其他可计费资源。
角色
| 角色 | 做什么 | 写入内容 |
|---|---|---|
| 所有者(一个人) | 目标、非目标、保留决策 | PLAN.md 目标 |
| 主会话(主要会话) | 规划任务、启动代理、接受评审、合并、向所有者报告 | state.json(仅通过 campaign 命令)、任务文件、PLAN.md、main 分支 |
贡献者(campaign-contributor 代理) | 一个任务或子任务,按其分配 | 其分支和日志 |
评审者(campaign-reviewer 代理) | 一个任务通过一个透镜,从全新的上下文中审查 | 一个评审文件 |
贡献者的分配指明了工作类型;除了实现之外,每种类型在 references/assignments/<name>.md 中都有一个方法。主会话在每次启动时命名分配、模型层级和工作量,根据工作本身选择,而不是习惯:
| 分配 | 用于 | 层级,工作量 |
|---|---|---|
| 实现 | 具有具体标准的功能和修复 | 经济型,中等(低风险/正常风险);强力型,高(高风险/关键风险),或在经济型尝试停滞之后 |
| 设计 | 对重要计划的任务列表;格式、协议、持久性、并发性 | 强力型,高;即将冻结的设计使用最高级 |
| 研究 | 很少:机制本身是限制 | 强力型,最高级 |
| 性能 | 性能分析和优化 | 强力型,高级 |
| 探索 | 探索批次中的一个目标,或一个快速问题 | 经济型,中等 |
| 文档 | 文档、指南、README | 经济型,中等 |
| 维护 | 跨仓库的一个机械性更改 | 经济型,中等 |
评审者使用强力层级和高级工作量(关键任务使用最高级);对于关键任务和计划挑战,如果工具链支持,则使用来自另一模型家族的评审者。各工具链的层级模型定义在 references/harness.md 中。根据结果更改默认设置(campaign usage,满足标准,返工),而不是仅根据价格。主会话自行处理小型编辑(五行修复,琐碎的冲突):启动一个代理的成本更高。
启动一个战役
- 在主场仓库的主检出中:
campaign init --name NAME [--ci github]。所有者将目标、非目标、约束和保留决策写入.campaign/<campaign>/PLAN.md。 - 将目标分解为任务:
campaign new ID --title T --risk R --files GLOBS [--needs IDS] [--after IDS] [--provides C] [--consumes C] [--milestone M] --check NAME[:LEVEL[:MIN]]=CMD。填写每个任务文件(.campaign/<campaign>/quests/ID.md):成果、标准A1...每个标准附有所需证据(证据部分)、契约、决策、可以提前合并的内容。 - 当架构影响重大时,在构建任何东西之前,一名评审者(透镜为
design)挑战计划和任务列表。这是唯一值得等待的评审。
任务
- 规模: 能够交付一个完整、有意义行为的最小变更,评审者能将其整体理解,通常为几百到约1500行。拆分更大的任务;将不值得单独合并的变更折叠到它所属的任务中。
needs必须在任务开始前合并;after必须在任务合并前合并。一个任务可以基于after依赖项开始,但前提是该依赖项的任务文件确定了契约。- 契约(
--provides,--consumes)命名API、格式和协议,因此campaign check能看到两个任务触及同一个内容。 - 子任务: 一个任务内的并行写入者(
campaign start ID --task T --files GLOBS),由主会话合并到任务分支。该任务仍然只进行一次评审。 - 增量合并:
campaign land ID --upto COMMIT --reason R合并任务文件“可以提前合并”部分允许的前缀(行为保持的重构、测试、未使用的内部API、禁用开关后的代码)。绝不能提前合并:磁盘上或网络上的字节、公共API、用户可见的行为,或评审所针对的部分。 - 跨仓库工作 是由
after排序的多个任务(--repo PATH),并带有一个集成作业,该作业固定每个仓库的提交(--ref NAME=PATH@REF)。合并是有序的,绝不是原子性的:每个中间状态都必须能工作。 - 消息: 代理如果对不在其当前工作的任务有发现(无论哪个战役,只要在同一台机器上),发送
campaign message NAME:ID "text" --from WHO。该任务在其日志之一通过ID(msg-N)回复该发现之前,或主会话关闭它之前(campaign message ID --close msg-N --reason R),不能合并;NAME:写入该战役的主会话,并且从不阻止合并。详细信息和其他机器:references/host.md,消息部分。 - 范围变更: 新的要求首先放入任务文件(一个标准,或者如果它可以单独合并,则作为其自己的任务),然后交给贡献者;被取代的工作通过
campaign set ID status=dropped reason=...处理。
直接路径优先
只有决定下一步的事情才会阻塞它。一个任务的关卡检查(--check:构建、测试以及其风险所需的证据)会阻塞其合并。其延迟检查(--later:其他平台、长时间浸泡、完整矩阵、扩展模糊测试)在合并后的代码上以低优先级排队,并且必须在里程碑关闭前变绿。红色的结果在 campaign check 中是一个错误:要么向前修复或回退,然后 campaign verify ID --deferred 在 main 分支上重新运行它们。高风险或关键风险所需的证据(并发使用TSan,解码器使用模糊测试,持久性使用崩溃模型)始终是关卡检查。慢速的CI工作流可以通过相同的方式设为非关卡(campaign config ci_later=NAME,...)。
运行一个任务
campaign start ID在其自己的工作树中创建quest/<campaign>/ID以及一个日志。在后台启动一个贡献者,以便可以通过消息恢复,使用“贡献者”提示(references/prompts.md);仅在任务准备好、文件集不重叠且不等待同一台机器时并行运行任务。- 贡献者在其工作树中工作,保持其日志最新,并将证据作为作业生成:
campaign job submit --quest ID --level L --minutes M -- CMD和campaign verify ID。当只剩下作业时,它记录它们的ID并结束其轮次。 - 主会话等待,使用一个后台的
campaign wait --commits(直到作业结束、分支移动或消息到达才消耗token),然后在其上下文较小时(大约150k token)通过消息恢复贡献者。更大的上下文,或无法恢复它的工具链,将获得一个带有“恢复”提示的新贡献者,该提示根据日志和作业记录重建。 - 当日志显示“准备好评审”时,主会话设置
status=review并根据风险启动所需的评审者;每个评审者编写.campaign/<campaign>/reviews/ID-LENS.md。主会话将阻塞性发现按ID转发给贡献者。 - 一旦评审批准,或者在被修改后并附有确认作业(风险和评审),使用
campaign accept ID LENS;它提交带有接受的评审文件。然后使用campaign land ID,它还会移除任务的工作树、已合并的分支和构建槽,并记录它保留了什么。
探索批次
对于一个值得探索的列表(新基准测试中表现不佳的行、性能分析的热点、证据不足的代码、积压的小bug),同时发送几个经济型贡献者,每个对应一个目标,目标来自当前 main 分支上新的度量:references/assignments/exploration.md。根据其目标和主会话能够评审及合并的内容来确定批次大小,绝不根据空闲配额。
风险与评审
| 风险(第一个匹配的获胜) | 在构建之前 | 在最终合并之前 |
|---|---|---|
| 关键:不可逆(为发布冻结格式或协议、迁移用户数据、移除用户可见行为) | 所有者批准;一次 design 评审 | 高风险评审,加上评审者自己运行的接受证据 |
| 高:持久化格式、线缆协议、持久性、并发性、安全表面、共享公共API | 当决策难以逆转时进行一次 design 评审 | 针对主要风险透镜(durability、security 或 correctness)进行一次评审 |
| 正常:普通功能与修复 | — | 一次 correctness 评审,或者对于有强证据的小型更改使用 --waive REASON |
| 低:文档、测试、工具、机械性编辑、行为保持的重构 | — | 检查通过;主会话阅读差异 |
- 默认情况下一名评审者, 承担任务提出的所有风险问题(提示中命名了三到五个)。仅当需要单独的专业知识或独立性时才需要第二名评审者。
- 一次评审绑定到它所见的代码。 它命名其审查的提交(
Commit:)、一个结论以及一个发现表,每行包含ID、是否阻塞(是或否)和种类(缺陷、差距、微瑕)。APPROVE 覆盖该提交的代码;仅触及.campaign/的提交保持批准。在接受后编辑评审会使接受失效。 - 修复由作业确认,而非重新评审。 对于每个阻塞性发现,在修复的提交上将其探测程序或新测试作为作业重新运行,然后运行
campaign accept ID LENS --confirm C1=JOB --confirm C2=JOB。一个作业仅在它通过了任务仓库中已接受代码上的检查时才确认;一个阻塞性缺陷需要更改的代码;工具记录在审查的提交上,同一个探测程序是否失败。如果修复更改了评审从未见过的文件,则返回给评审者(评审命名修复后的提交并批准),除非--fix-scope REASON说明为什么它没有引入新的机制(例如针对发现的回归测试)。 - 两轮修复,然后停止。 第三轮意味着任务或设计是错误的:重新规划或询问所有者。非阻塞性发现成为一个后续任务,或带理由被丢弃。
- 设计只评审一次。 通过可执行模型或测试来解决争议行为,而不是另一轮文本讨论。
- 任务必须通过的检查只能在记录上更改:
campaign set ID ... --weaken REASON降低其风险、移除一个透镜、或移除、更改或推迟一个检查;这个更改保存在其历史中,由campaign status ID显示,并使其接受失效。风险所需的评审(低风险以上的代码评审,关键风险的设计评审)不能被移除,一旦存在评审,则拒绝免除。 - 系统评审基于事件,而非日历: 当
campaign check报告两个任务更改了一个文件或一个契约时,要求一名评审者(透镜为system)回答那个具体问题。 - 产出率:
campaign status --reviews统计结论和阻塞性缺陷。一种可选评审(正常风险)在大约五个同类任务中未发现实质性问题时,则对该类任务丢弃此评审;高风险和关键风险评审永远不会因为产出率而被丢弃。
证据
任务文件中的每个标准都命名它需要的证据;日志的“证据”表为每个标准提供一行,而合并时在即将合并的代码上检查每一行:
| 标准 | 其行必须命名 |
|---|---|
- A1 ...(无标签) | 一个在该代码上通过的作业(它本身,或重新运行的同一个作业) |
- A2 [artifact] ... | 一个提交在任务仓库中的 路径 |
- A3 [decision] ... | PLAN.md 的“决策”表中的一个ID |
- A4 [manual] ... | 谁手动检查了什么;显示为手动,绝不能作为自动化证明 |
证据应与声明成比例(references/review.md):测试检查值,而非计数;修复带有一个没有它就会失败的测试;声明带有一个测试能杀死的变异体;在独立的构建中使用消毒器。性能声明遵循 references/measurement.md:在命名提交上比较前后,对于决定任何事情的数字使用 exclusive,诚实的大小。
机器工作
| 级别 | 用于 | 隔离(quiet) |
|---|---|---|
none | 微小的单线程探测 | 无保持 |
light | 构建、测试套件、模糊测试 | 几个同时运行,nice 19 |
strict | 快速计时、行为运行 | Linux上专属核心;macOS上独占 |
exclusive | 决定性数字 |
…
[已截断用于翻译]