Poteto Mode Orchestrate 剧本解析:用单一协调者聊天驱动多日、多 PR、上百子代理的程序级编排
2026/9/17 5:14:21 网站建设 项目流程

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-kitcontrol-uicontrol-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.tsvledger.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 initwriteIfMissing,重复初始化不会破坏已有数据——测试 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 addorch unit setorch 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 approvalsMerge conflictsReady 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.recordpr + sha查找现有行,找到则原地替换(覆盖),否则追加;ts自动写入 ISO 时间戳(store.ts)。parseVerdict在 CLI 层把非法判定直接拒绝(orch.ts)。测试验证了:先record unit-test-verifiedrecord live-ui-verified后 summary 只剩后者,即同一键被覆盖;非法判定looks-good直接抛错(orch.test.ts)。

存活性与失败处理

  • 绝不 resume 一个代理去"看看它"。Resume 会重启空闲代理。用只读方式探测:台账、units.tsvgh、已 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.tsvledger.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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询