Poteto Mode Orchestrate 剧本解析:用单一协调者聊天驱动多日、多 PR、上百子代理的程序级编排
【免费下载链接】pluginsCursor plugin specification and official plugins项目地址: https://gitcode.com/GitHub_Trending/plugins125/plugins
导读
Orchestrate是 pstack 插件 Poteto Mode 中面向「程序(Program)」级别的编排剧本,回答一个核心问题:当一个项目需要多日持续作战、几十个堆叠 PR、数十乃至上百个子代理,而人类每天只检查两次时,如何用一个常驻的协调者聊天把整条流水线跑完并安全收尾。读完本文,你将掌握协调者/子协调者/工作代理的角色划分、基于纯文本文件的 Store 布局、bun scripts/orch/orch.ts(简称orch)的完整命令用法、Brief 模板与缩放规则、七个执行步骤、队列排空纪律、Stack 安全与验证台账,以及故障恢复与升级策略。
本文以 orchestrate.md 为骨架,结合 orch.ts、store.ts 与 orch.test.ts 的源码实现逐层展开。
何时路由到 Orchestrate:程序与单任务的边界
剧本开篇就划清了边界:"You own the program, never the code."当一个完整项目被交给一个常驻协调者聊天时——多日周期、大量堆叠 PR、数十到数百个子代理、人类每天只检查两次而非每五分钟一次——就应路由到这里。三种形态的区分是:
- Autonomous run:一个任务被驱动到某个判定谓词(predicate)即为完成,参见 autonomous-run.md。
- figure-it-out:一次野心勃勃的运行需要定制工作流时使用。
- Orchestrate:当工作超越任何单个代理的寿命时路由到这里。一个代理能在本次会话预算内完成的工作,不叫程序,不应走 Orchestrate。
在 SKILL.md 中这个边界被进一步强化:figure-it-out 设计一次定制运行,orchestrate 运行整个程序;"standing project-scale program"(多日、多个堆叠 PR、一个协调者下的代理群)一律路由 Orchestrate(见 SKILL.md)。
剧本同时强调仪式感必须随程序规模伸缩:在廉价且近乎同构的单元上,要按各节的指示把仪式折叠掉,而不是机械套用全套流程。
三条铁律
- 完成是队列事件,不是中断(Completions are queue events, not interrupts)。
- 每一次 spawn 和每一次 resume 都必须逐字携带常驻指令(standing orders verbatim)。
- Brief 就是产品。含糊的 brief 会安静地失败,因为工作代理无法向你提问。
这三条规则贯穿全文,是后面所有纪律的推导起点。
角色与布局:协调者、子协调者、工作代理/验证代理
协调者(Coordinator,即本聊天)
协调者是本地(Local)的,负责:框定程序(Frame)、撰写 brief、排空收件箱(drain the inbox)、拥有对人类的汇报、做判断决策。它从不编写或编辑代码。冲突合并、restack、代码变更永远是任务;只有机械落地一个已验证单元(对工作代理提交做 fast-forward 或干净的 cherry-pick,然后 push)属于簿记,协调者可以在本地 git 成本低的仓库里自己做。
关键纪律:整个循环端到端都是 agentic 的——代理只能通过 Task 工具被 spawn、resume 和排空;状态读写只在 drain 点通过scripts/orch/orch.ts进行,"一条命令进、一行输出出";CLI 从不 spawn、等待或唤醒任何东西。
子协调者(Sub-coordinator)
子协调者总是本地、持久(durable)、每个 track 一个,仅当程序超出单个协调者一次 drain 能管理的规模时才引入。协调者自己就能 drain 的 track 不需要中间层。原因有二:每嵌套一层都要重新支付一次完整的定位前导(orientation preamble);阻塞式子协调者会在父级空闲时隐藏它的子代理。
子协调者职责:拥有其 track 的单元与看板、撰写其工作代理的 brief、spawn 自己的工作代理与验证代理(嵌套深度到 3 层,嵌套 spawn 拥有完整 Task schema,包括environment)、在 wave 边界汇总聚合。它从不转发原始的子报告;在途子代理数量上限约为十个,作为滚动窗口,绝不使用阻塞式批次——因为阻塞式批次每个批次都要付出最慢子代理的代价。
工作代理 / 验证代理(Worker / Verifier)
- 默认
environment: "cloud",除非任务确实需要本机:cursor-team-kit的control-ui或control-cli运行时验证、读取agent-transcripts/下的本地转录、模拟器与本地 IDE 状态、仅存在于本机的认证。 - 云端代理读不到本地 store,所以它们的 brief 要么内联所需内容,要么指向仓库路径。
- 偏好更少但更宽的工作代理。每个 worktree 或分支只有一个写入者(对应 principle-separate-before-serializing-shared-state 原则)。
- 一个单元的验证代理必须与工作代理使用不同的模型族,以保证独立性。
深度与 track 划分
深度保持在三层:协调者、track、工作代理。track 分解按项目定制(build、landing、verification 是常见切法,但不是必须的形状)。剧本明确记录:硬编码的 swarm 树曾尝试过,因过于僵化而被搁置。
Store 布局:纯文本文件即事实
在系统提示中的当前代理 store 路径下创建orchestrate/<project-slug>/。每个文件恰好一个写入者;拥有者发布事实,读者在读取时聚合。簿记统一用bun scripts/orch/orch.ts(下文写作orch),但其规范化的纯 TSV/JSON 文件不依赖 CLI 也可直接阅读。
| 文件 | 作用 | 维护规则 |
|---|---|---|
preferences.md | 常驻指令登记册 | 编号行,每行一条约束(模型策略、栈形状与数量、验证门槛、禁止路径、升级策略)。每次 spawn 和每次 resume 逐字粘贴。指令会跨 resume 衰减,每丢一条都要耗掉人类一轮。当你发现自己重复某条指令时,先追加该行再行动(对应 principle-encode-lessons-in-structure) |
overview.md | 持久 PR 与 issue 数据库 | 只追加,绝不按事件整篇重写 |
units.tsv | 单元表 | 一行一个单元:id、track、state、branch、PR、head SHA、brief 路径。原地更新行 |
frontier.json | 计算出的合并前沿 | 按 Stack safety 节维护 |
ledger.tsv | 验证台账 | 按 Verification 节维护 |
inbox/ | 完成指针 | 存放完成通知;gates.md停放人类门禁(问题、选项、无答复时的默认值) |
decisions.tsv | 决策轨迹 | 通过 show-me-your-work 技能维护 |
status.md | 状态页 | 每次 drain 时从units.tsv和ledger.tsv派生,绝不手工维护;从表重新生成,而不是把事件叙述进去 |
源码印证:纯文本 store 的实现细节
store.ts 用约 1600 行 TypeScript 实现了这套纯文本 store,几个值得注意的实现事实:
- TSV 头严格校验:
units.tsv头为id\ttrack\tstate\tbranch\tpr\tsha\tbrief(7 列),ledger.tsv头为pr\tsha\tverdict\tevidence\tverifier\tts(6 列),读写都做宽度与头校验(store.ts),格式损坏会直接报错而非静默吞掉。 - 原子写入:所有写入都走"临时文件 + rename",避免半写状态(store.ts)。
- CSV 公式注入防护:
cleanCell会把以= + - @开头的单元格前缀',防止把表格公式当数据处理(store.ts)。 - PID 文件锁:
.orch.lock记录持有者 pid;写入前必须拿到锁,--force可夺锁,持有者 pid 已死(process.kill(pid, 0)返回 ESRCH)则自动替换,对应剧本"死会话的 store 锁会在下次写入时自动清除、orch 会替换持有者 pid 已消失的锁"(store.ts)。 - 幂等初始化:
orch init只writeIfMissing,重复初始化不会破坏已有数据——测试 orch.test.ts 验证了两次 init 后文件内容一致。
测试中还覆盖了锁的两种行为:写入者在锁被他人持有时被阻塞并报store lock held by pid N,只有--force才能夺锁;以及脏锁(pid 已死)自动替换(orch.test.ts)。
Brief:唯一的产品
你对代理的提示是你唯一的产品,一份草率的 brief 会在整棵树上放大成次品。每次 spawn 都携带完整 brief;一个你填不出来的字段,就是一个你还没界定清楚的单元。
完整模板:
GOAL 一句话,说明产出,能让没有聊天权限的陌生人直接执行 SCOPE 本单元可写的路径;不可写的路径;其独占的 worktree 或分支 CONTEXT 指向文件和 PR 的指针;当本单元依赖上游报告时,完整粘贴上游报告, 因为工作代理看不到兄弟代理 ACCEPTANCE 可检查的标准,一行一条 VERIFY 精确命令或 control 技能路径,外加已知陷阱 TIMEBOX 运行时长的大致上限;到期返回部分发现并停止,而不是继续跑 FORBIDDEN 不 gt、不 rebase、不 force-push、不修 scope 之外的东西,再加单元级禁令 REPORT 状态、分支、head SHA、PR、判定、实际跑了什么、偏差、建议的后续 STANDING <preferences.md 逐字粘贴>按单元缩放 brief
- 一行命令的单元:模板折叠成一段,但仍须点名 goal、scope、verify 命令和报告形状。一个"两行编辑外包 4KB 脚手架"的 brief,其书写与遵守成本比编辑本身还高。
- 本地 spawn可以直接按 store 路径引用常驻指令文件;逐字粘贴是给云端 spawn 和每次 resume 的。
子协调者 brief 与依赖中继
子协调者 brief 额外包含:其 track 边界与单元清单、spawn 预算(云端默认 + 本地例外清单)、drain 协议、rollup 格式(每个子代理:名字、状态、PR、head SHA、判定、一行说明,外加 track 状态与 frontier 增量)。
依赖是上下文中继,不只是排序。未声明的上游上下文会让工作代理靠猜。缺失字段是拒绝 spawn 的条件。每个 wave 每子协调者抽查一个工作代理 brief,且抽查与该 wave 并发进行,绝不作为其前置门禁。失败的 brief 会停掉该 track 并修正子协调者的指令,而不只是修正该工作代理——因为 brief 质量在运行后期会衰减。绝不 resume-chain 一个 brief;用整合后的 scope 重新 spawn。
七个执行步骤
1. Frame(框定)
把"完成谓词"写成可数的形式,例如"全部 126 个单元已合并,每个都在台账中记为unit-test-verified或更优"。量化范围:单元数、大致工作量、预期栈数量、墙上时钟预算。如果单个代理能在该预算内完成,在此停下,改走 Autonomous run。
Collapsing 的含义是:直接在本会话内干活,需要时用普通工作代理、验证内联、边做边落地,不启用下述 store、登记册或 pilot 机制。对照预算安排落地节奏:大约到 70% 预算时停止 spawn,落地所有已验证的东西。
按项目命名 track。有争议的分解或单向门,先在 arena 技能(pstack/skills/arena/SKILL.md)中过一遍再开始 pilot。framing 只呈现一次;可逆的准备不等待。
2. Install the runtime(安装运行时)
运行orch init。通过 show-me-your-work 技能(pstack/skills/show-me-your-work/SKILL.md)打开决策轨迹,在任何 spawn 之前写好常驻指令,并用orch frontier set --repo <repo-dir>从既有 PR 播种frontier.json。
3. Pilot(试点)
把一个单元推过完整路径:brief、工作代理、验证、栈条目、台账行、合并。Pilot 的存在目的是在代价是一个代理而非五十个代理时,证伪 brief 模板、验证配方和单元规模。从 pilot 证据修正契约后,再开始任何扇出。Pilot 规模随单元缩放:对近乎同构的廉价单元,第一个单元本身就是 pilot,作为普通单元运行、verify 命令内联,落地即开始扇出。专用 pilot 管线(独立验证代理、审计门禁)只用于昂贵或新颖的单元形态,克隆单元没必要——串行 pilot 没有可证伪的东西。
4. Scale(扩容)
按在途上限 spawn 一个滚动窗口的工作代理,子代理完成即补位。阻塞式批次要付出每个批次最慢子代理的代价。只有超过 Roles 节的一次-drain 阈值才 spawn track 子协调者。每次 drain 后重算就绪工作。把上游报告中继进下游 brief。兄弟间通信只向上。抽样 brief 审计与它所抽样的 wave 并行运行,失败时停的是下一次补位,而不是当前这一波。
5. Drain(排空)
在每个 drain 点执行下文"队列与 drain 纪律"。
6. Land(落地)
落地是连续的,绝不是收尾阶段。集成从第一个已验证单元开始,与剩余 wave 并行推进。重型仓库上 stacker 从 wave 一开始就是常驻角色,单元一验证就集成;本地 git 便宜的仓库,协调者按 Roles 节自己落地已验证单元。保持前沿绿色先于上层栈工作。Stack safety 主导。frontier.json只在合并或报告了新 head SHA 时才推进。
7. Close(收尾)
排空最终收件箱;把每个 spawn 过的代理调和成终止行(done、abandoned、zombie-reconciled);在真实工件上确认谓词;确认每个已落地 PR 的当前 head SHA 都有判定;按 show-me-your-work 审计轨迹(含跨模型评审);把反复出现的修正编码进preferences.md或 brief 模板。保留 store 原样——它就是事后复盘材料。
队列与 Drain 纪律
- 收到完成通知时,运行
orch inbox push <agent> <unit> <status> [--report PATH],然后回到你正在做的事。绝不内联深度评审;需要评审的完成会变成验证单元。绝不在 drain 中评审 diff。 - 四个时点批量 drain:关键小节结束、track rollup、前沿 watcher 唤醒(通过 loop 技能布防,配长心跳兜底)、人类报告之前。每批以
orch inbox drain开始。drain 期间到达的通知等下一批。 - 优先完成的关键小节:撰写 brief、栈操作、冲突决策、写门禁、更新台账或前沿。
- 每次 drain 把每个指针分类为:landed、needs-verify、failed、zombie、noise;通过
orch unit add、orch unit set、orch ledger record写入结果行,运行orch status,然后在一条消息里 spawn 下一波。 - 在 track rollup 时对每个 spawn 过的子代理对账:已到、已重 spawn、或其 scope 被显式吸收。默默重做缺失子代理的工作,会同时掩盖浪费的开支和该结果本要填补的覆盖缺口。
- 一次 drain 回合以
orch status的三行输出结束:按状态统计的计数、什么变了、有哪些门禁开着。细节在status.md中。
源码印证:orch CLI 的完整命令面
orch.ts 用 commander 实现了全部簿记命令。全局选项:--store <dir>(或环境变量ORCH_STORE)、--json(输出完整行)、--force(夺锁)。完整命令树:
| 命令 | 用途 | 关键参数 |
|---|---|---|
orch init | 初始化 store | — |
orch unit add <id> | 新增单元 | --track <track>(必填)、--brief <path>;新单元状态为pending |
orch unit set <id> | 更新单元 | --state <state>(必填)、--branch、--pr、--sha |
orch unit get/list/counts | 查询单元 | list 支持--state、--track过滤 |
orch ledger record <pr> <sha> <verdict> | 记录验证判定 | --evidence <path>(必填)、--verifier <name> |
orch ledger check <pr> <sha> | 查询判定 | 未记录输出NOT-VERIFIED,退出码 2 |
orch ledger summary | 判定统计 | — |
orch inbox push <agent> <unit> <status> | 推入完成指针 | --report <path> |
orch inbox drain/peek/count | 排空/窥视/计数 | drain 支持--peek(只读不排空) |
orch gate park/list/resolve | 管理门禁 | park 需--question、--options、--default;resolve 需--answer |
orch frontier set/show | 计算/展示前沿 | set 需--repo <dir>(或ORCH_REPO),可选--prs <n,...>钉定 PR 顺序 |
orch status | 渲染status.md并打印摘要 | — |
orch standing show/add <line> | 管理常驻指令 | 自动编号追加 |
退出码约定(测试 orch.test.ts 验证):成功为 0,用户/用法错误为 1,not-found 为 2(且--json下仍向 stdout 输出结构化 JSON,如{"pr":"184530","sha":"abc123","verdict":"NOT-VERIFIED"})。
orch status的三行摘要来自statusLines(orch.ts):counts:(单元数与状态分布、台账判定分布)、changed:(与上次渲染的差异,如units done 0->3; ledger unit-test-verified 1->4)、gates open:(门禁数量与 ID)。status.md内含<!-- orch-summary ... -->注释用于差异检测(store.ts)。
Stack 安全
- 前沿是计算对象,绝不是叙述。每次合并和栈突变后都要从
gt重新计算frontier.json——因为 GitHub base ref 会在 restack 中途漂移,而 gt 的追踪才是权威:有序 PR 列表、分支名、head SHA、代数(generation number)、最低未合并 PR。在 gt 认识该栈的地方解析它(通常是 stacker 的 clone)。gt 元数据从未见过提交的 checkout 会报告无 PR,命令直接报错而不是猜。 - 每个栈恰好一个 stacker 可运行
gt,在其栈内串行。持有者记录在常驻指令中。Restack 在云端运行——此规模下本地 restack 会把笔记本拖垮。 - 工作代理绝不 rebase、绝不运行
gt。Babysitter 按 babysit.md 行事,每个栈一个,scope 限定在一个不可变前沿代内;它们把冲突报告给 stacker,而不是自己 restack。 - PR 关闭与重定向只经 stacker。关闭一个基 PR 会让其上方整条链成为孤儿。合并与栈手术是和其它单元一样带 brief 的单元。
- 一个 retro watcher跟踪已合并 PR 的 revert、合并后 CI 破裂和孤儿后续。
源码印证:前沿计算
orch frontier set --repo的实现:先gt log short --stack --reverse拿到有序分支,再对每个分支gt info解析 PR 号与状态(MERGED/CLOSED/OPEN,其中OPEN匹配一长串 Graphite 状态词,如Needs approvals、Merge conflicts、Ready to merge等),再用git rev-parse取每个分支 SHA,代数 +1,lowestUnmerged取第一个OPEN的 PR(store.ts)。可选的--prs <n,...>钉定会校验实际顺序与预期完全一致,漂移时报frontier pin mismatch: missing from gt ...; extra in gt ...; order differs ...(store.ts)。测试用 fakegt脚本验证了 merged/closed/open 三种状态、钉定校验与不可解析输出的显式报错(orch.test.ts)。
验证体系:台账是唯一答案
验证规模随单元缩放:
- VERIFY 是单个廉价命令时,工作代理运行并报告输出,协调者抽查凭证即可。
- 专用验证代理(模型族与工作代理不同)只用于验证昂贵、依赖判断或高爆炸半径的单元。一个只会重跑一条命令的验证代理是仪式,不是验证。
台账命令:orch ledger record写行,orch ledger check查当前 PR 与 head SHA。ledger.tsv每行一个判定,键为PR 号 + head SHA,五档判定:
| 判定 | 含义 |
|---|---|
live-ui-verified | 真实 UI 验证通过 |
unit-test-verified | 单元测试验证通过 |
type-check-only | 仅类型检查 |
verifier-blocked | 验证器被阻塞(不是通过) |
verifier-failed | 验证失败 |
关键规则:
- CI 绿是判定的输入,不是判定本身。行为类工作必须好于
type-check-only。 verifier-blocked不是通过;环境恢复后重新 spawn。verifier-failed产生一个修复单元,而不是重新验证。- 工作代理可自报,但验证代理在同一键上覆盖之。
- 新 head SHA 使旧行失效,restack 后必须重新验证。
- 台账回答"这个是否被验证过",不靠记忆,也不靠转录。
一个单元在落地那一刻输出被外部化之前都不算完成,绝不批量拖到运行结束:工作代理 push 分支、验证代理写台账行、凭证落进 store。"只存在于某台 VM 上、而那台 VM 死了"的工作等于从未做过。
源码印证:台账的键与覆盖语义
ledger.record按pr + sha查找现有行,找到则原地替换(覆盖),否则追加;ts自动写入 ISO 时间戳(store.ts)。parseVerdict在 CLI 层把非法判定直接拒绝(orch.ts)。测试验证了:先record unit-test-verified再record live-ui-verified后 summary 只剩后者,即同一键被覆盖;非法判定looks-good直接抛错(orch.test.ts)。
存活性与失败处理
- 绝不 resume 一个代理去"看看它"。Resume 会重启空闲代理。用只读方式探测:台账、
units.tsv、gh、已 push 的分支、Cursor 仪表盘里云端代理的状态。转录的 mtime 不是存活证据。 - 静默死亡得到收件箱里一条合成的复盘行(单元、失败模式、最后证据、选项)。证据一到就重规划。绝不等待完全静止。
- 按模式重试:
| 失败模式 | 处理 |
|---|---|
| 命中上限或 OOM | 缩小 scope 重新 spawn |
| 网络断连 | 原样重试 |
| 工具错误 | 换不同模型重试 |
| 未知 | 重试一次 |
两次重试后放弃该单元并绕行重规划。
- 迟归数小时的僵尸:在接受任何东西之前,先对照当前前沿与台账调和。通过全新单元抢救独有发现,绝不盲合并。
- 当继续 spawn 会产生树级垃圾(上游输出差、验收坏了、基础设施死了)时:在常驻指令顶部写一行停止线,让在途工作完成,修好原因,再清除该行。
- 用约束子代理的同样方式约束你自己的基础设施重试。连续几次工具中止后停止重试,把终止交接写入持久状态(做了什么、存在哪里、恢复用的确切命令),结束运行。
- Cursor 重启之后:本地代理已死,云端工作没死。重读常驻指令与
units.tsv,重算前沿,按 PR 与分支而非代理 ID 重新挂接云端工作,从存储的 brief 加当前状态为每个 track 重 spawn 一个子协调者,drain,继续。死会话的 store 锁在下一次写入时自行清除;orch会替换持有者 pid 已消失的锁(源码见上文 PID 锁实现与测试 orch.test.ts)。
升级策略:什么该打扰人类
到达人类(批量汇入状态页,而不是逐条):不可逆动作(对共享分支 force-push、部署、删除、关闭别人的 PR)、没有实验能定案的产品或偏好判断、与观察到的现实相矛盾的常驻指令、重规划后仍然存活的程序级死胡同。先把它作为gates.md条目停放,再绕行其继续工作。
绝不打扰人类:前沿微调、restack 机制、重试、CI flake 分诊、评审线程分诊、格式修复、brief 已禁止的 scope(拒绝并继续)、以及"我该继续吗"。拿不准就行动并记录。
运行中发现的问题只修阻挡前沿的部分,其余一律停进 follow-ups——在这个扇出规模下,一次小的 scope 泄漏会倍增成没人要的 PR。
Reply 契约:从表里取数,不靠叙述
在检查点与收尾时回复:谓词及对照units.tsv与ledger.tsv的计数、各 track 及其落地内容、前沿(PR 列表加 SHA)、判定摘要、放弃了什么及原因、等待人类的门禁(唯一允许的请求)、store 路径、轨迹路径。数字来自表,不是叙述。包含 PR 链接。
这条契约与 drain 纪律呼应:一次 drain 回合的三行摘要、收尾时的完整报告,全部以表为事实源,保证协调者聊天在长周期运行中始终能向人类给出可核验、可续接的状态快照。
小结
Orchestrate 剧本把"程序级多代理并行"从口号变成了可执行的纪律:角色分层(协调者/子协调者/工作代理)、纯文本 store(每文件一写入者)、brief 模板与缩放、七步执行、队列 drain、Stack 安全、验证台账、失败恢复与升级边界。其背后的 orch.ts 与 store.ts 以约 1600 行实现和完整测试(orch.test.ts)把这些纪律落成了可运行、可审计、可恢复的工具——让"人类每天检查两次"的长周期程序,有一个不依赖任何单次会话寿命的持久骨架。
【免费下载链接】pluginsCursor plugin specification and official plugins项目地址: https://gitcode.com/GitHub_Trending/plugins125/plugins
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考