)
Poteto Mode 的 Shipping Playbook以独立验证驱动绿色 PR 堆栈的自底向上落地pstack 实战指南【免费下载链接】pluginsCursor plugin specification and official plugins项目地址: https://gitcode.com/GitHub_Trending/plugins125/plugins导读本文讲解 pstack 插件中 Poteto Mode 的Shipping playbookpstack/skills/poteto-mode/playbooks/shipping.md它是工程团队在 Cursor 中把一批已通过的堆栈式 PR 安全合并进主干的标准流程。它的核心信条只有一句话绿色不代表安全Green is not safe——CI 全绿只是必要不充分条件每个 PR 必须经过与写代码者相互独立的 Agent 验证并且只能从堆栈底部开始、沿着连续已验证的链条逐个落地。读完本文你将掌握如何解析当前 forgegh或 Origin、如何给每个 PR 分配独立验证 Agent、如何用git patch-id防止 verdict 失效、以及如何用仓库自带的watch-pr脚本观察合并前沿frontier而不擅动队列。一、Shipping 在整个流程中的位置Babysit 的下半场在 Poteto Mode 的二十三本 playbook 中Shipping 与 babysit.md 是一对相邻的阶段SKILL.md 中明确列出Babysit. Driving a PR or a stack to merge-ready、Shipping. The half after Babysit。Babysit负责把堆栈养绿声明模式drive/background/threads-only/check、解决冲突、处理 review threads、分类 CI直到 forge 判定 frontier 达到 merge-ready。Shipping接手这个看起来可以合并的堆栈独立验证每一个 PR、重新确认 verdict 仍然描述当前 patch、只准备并落地底部 PR、每次合并后重新计算、在缺口ceiling处停下。两者的分界线非常明确Babysit 的drive结束于 merge-ready落地landing是 Shipping 的职责。任何一个 PR 状态请求如果带有merge、land、ship、merge when ready的意图都会在 Babysit 中被路由到本 playbook见 babysit.md 第 6 步。从源码看二者的衔接在watch-pr脚本中也有体现Babysit 用--status-only或轮询得到READY/WAITING就停止而 Shipping 的观察循环则使用--queued-stack --stack-prs bottom作为事件唤醒并自己轮询gh pr view的终态字段刻意不复用 Babysit 的 queuedWAITING/merge-queue停止条件这正是 shipping.md 第 8 步明确禁止的。二、第 1 步解析 Forge并为每个 PR 分配独立验证Shipping 的第一步是解析 forge即确定用哪套 CLI 操作 PRGitHub CLIgh是默认。如果command -v origin成功且 Origin 能解析当前仓库则用origin pr ...完成 view / watch / edit / merge 操作。否则留在gh并记录这次回退fallback。绝不要求 Graphitegt——它不被视为必需依赖。随后是验证阶段规则非常严格一个 PR 一个 subagent禁止批量not batched每个验证者都是Cursor cloud agent验证者必须实际操作真实表面real surface按改动类型使用cursor-team-kit插件提供的control-ui浏览器/Electron/Web UI或control-cliCLI/TUI工具针对 parent 分支与 head 分支分别演练每个 subagent 返回PASS、PASSNOTES或FAIL并把自己的 verdict发布到它验证的那个 PR 上Safe安全的定义verdict 必须来自一个没有写过该代码的 Agent。CI 绿不是 verdict机器人给的 approved review 也不是 verdict。这一设计对应 Poteto Mode 的Prove It Works与Guard the Context Window原则验证必须对着真实产物而非它能编译同时把大批量验证工作路由给 subagent主线程只保留结论摘要。三、第 2 步只落地从底部开始的连续已验证 run堆栈是一串互相依赖的 PR。Shipping 的关键判断是可落地性landability是连通的从最低的未合并 PR 开始向上走停在第一个没有通过 verdict 的 PR 处。其中PASS与PASSNOTES都算通过。一个位于未验证 PR 之上的已验证 PR不可落地。也就是说即使第 3 个 PR 验证通过了只要它下面的第 2 个 PR 没有通过第 3 个也不允许合并。报告时要把这个天花板ceiling作为 PR 号明确说出并说明是哪一环断开了链条。这是对Sequence Work into Verifiable Units原则的忠实执行交付顺序必须让整个序列对 reviewer 自证其正确性。四、第 3 步Re-check——verdict 必须仍然描述当前 patchverdict 是历史事实而 patch 会漂移。为此 Shipping 要求为每个 PR 记录三样东西verdict 时的 head SHAverdict 时的 base SHA该 PR base-to-head diff 的稳定git patch-id。原因在于一次 rebase 或 base retarget 会重写 SHA可以静默地让 verdict 失效而不触碰任何检查项checks 依然绿。因此在落地之前必须把记录的 patch-id 与当前 base-to-head 的 patch-id 比较patch 变了 → 重新验证patch 没变 → 保留代码 verdict但要在当前 head 上重跑 mergeability 与 CI。两个常见的偷懒替代品被明确禁止匹配的 commit message和旧 SHA 上的绿色勾都不能当作 verdict 仍然有效的证据。这从源码上对应watch-pr中mergeAssessment的实现——它会检查历史 commit 上是否曾有SUCCESShadPreviousPassingCi并区分当前 head 的检查与以前通过过的检查policy.ts。五、第 4 步只准备底部 PR落地是严格串行的准备阶段只允许触碰最底部的那个 PRfetch当前 trunk必要时把最低的已验证分支rebase 到精确的 trunk tippush 该分支只把那一个 PR的 base retarget 到 trunkorigin pr edit pr --base trunk或gh pr edit pr --base trunkpush 之后重跑第 3 步因为 push 改变了 headpatch-id 可能已经变化不要retarget、arm 或合并任何后代 PRdescendants。这条一次只动一个的纪律对应 Poteto Mode 的Minimize Reader Load与Separate Before Serializing Shared State原则堆栈是共享的串行状态任何并行修改都会让队列失去可审计性。六、第 5 步一次落地一个 PR当底部 PR 满足条件时用 squash 合并现在可合并origin pr merge pr --squash或gh pr merge pr --squash检查还在跑、且用户要求 merge-when-ready只 arm 那一个 PRorigin pr merge pr --squash --auto或gh pr merge pr --squash --auto。需要注意两种--auto语义并不相同Origin 的--auto是 Origin merge-when-readyGitHub 的--auto是 GitHub auto-merge。合并必须等它真正完成后才能准备下一个 PRWait for that PR to merge before preparing the next one。这里与 Babysit 有一条联动风险当 merge-when-ready 被 arm 时一个父 PR 没有必需检查的堆叠 PR 可能立即合并进父 PR从而塌缩 review 粒度lost-ref 竞态也可能让 PR 显示合并但父 ref 未更新见 babysit.md 第 6 步。Shipping 因此要求以 forge 的真实状态为准而不是以某个字段为准。七、第 6 步不要用 GitHub 的autoMergeRequest推断堆栈就绪GitHub 的autoMergeRequest字段最多只能证明某个 GitHub PR 请求过 auto-merge它不能证明Origin merge-when-ready 已被 arm某个后代 PR 已被排入队列某个 patch verdict 仍然有效连续堆栈是安全的。因此对当前底部 PR必须确认活动 forgeactive forge自身的状态如果活动 forge 无法报告该状态就要明确说状态未知而不是用 GitHub 字段凑合。这与 policy.ts 中assessGitHubMerge的谨慎态度一脉相承BLOCKED状态只有在 head rollup 是ERROR/FAILURE时才被判定为refused不可合并否则仍按允许、依据 rollup处理——单一的字段永远不足以拍板。八、第 7 步每次合并后重新计算每合并一个 PR整个堆栈的坐标系就变了fetch trunk确认合并后的 SHA 确实存在于 trunk把已合并的 PR 从冻结的 bottom-to-top 列表中移除检查新的底部 PR的 base、head、checks 与 patch-id宿主host可能会自动 retarget 子 PR但不要假设它做了对那一个 PR 重复第 36 步独立的工作independent work不在这条链上自行单独发布。注意冻结列表frozen bottom-to-top list一词——它来自 Babysit 的 queued 模式在队列模式下PR 列表一旦捕获就冻结每次重新 arm watcher 时传入同一份列表只在拥有 PR 已合并、产生 sanctioned follow-up PR这一种例外下修订babysit.md 第 6 步。Shipping 复用了同一套心智模型队列快照不可随意变更。九、第 8 步观察 frontier直到合并或失败——但不擅动队列这是 Shipping 中自动化程度最高的一步也是与watch-pr脚本结合最紧密的一步。Origin 路径使用origin pr view pr --checks --comments与origin pr checks pr --watch然后重读 PR直到它报告 merged 或 blocked。GitHub 路径把 scripts/watch-pr/watch-pr 当作事件唤醒event wakescripts/watch-pr/watch-pr --queued-stack --stack-prs bottom每次被唤醒后轮询gh pr view pr --json state,mergedAt,mergeStateStatus,statusCheckRollup,autoMergeRequest在mergedAt非空或state为MERGED之前READY一律忽略。只有那时才执行第 7 步。硬失败hard-fail仅限以下三种情况state为CLOSED且mergedAt为空某个必需检查以FAILURE或CANCELLED结束且 auto-merge 已不再 pending、确实阻塞合并mergeStateStatus为UNSTABLE或DIRTY且没有 pending 的 auto-merge。反过来说checks 还在跑、或 auto-merge 已 arm 时的BLOCKED不是失败。也不要使用 Babysit 的 queuedWAITING/merge-queue停止条件那是 Babysit 报告 frontier merge-ready 用的不是 Shipping 观察合并用的。观察循环应该在/loop的动态模式下持有每有合并或新的 ceiling 就报告如果队列卡住要先诊断再动手而不是直接改动队列。从源码理解watch-pr的判定逻辑watch-pr是 pstack 自带的一个 GitHub 专用观察器默认输出 JSON--pretty输出人类可读文本轮询时输出 NDJSONcli.ts。它的核心判定在 policy.tsclassifyPr单 PR 模式按优先级依次检查四类 blockermerge-conflictsCONFLICTING/DIRTY→review-threads未解决评论→failing-checks→merge-gatedraft、CHANGES_REQUESTED、closed-without-merge没有 blocker 且 checks pending 则为waiting否则判定ready/merged。selectTierMajorStackDecisionstack 模式对整堆做同样的分层扫描第一层的任何一个 blocker 都会终结整个堆栈。runQueued--queued-stack模式实现了一个完整的状态机整堆扫描whole-stack-sweep→ frontier 轮询frontier-poll→ 产出QUEUE/STATUS/WAITING/ADVANCE/COMPLETE/TIMEOUT/BLOCKER等事件。其中ADVANCE表示另一个 actor 合并了 frontier前进到新 frontierCOMPLETE表示队列全部合并policy.ts。查询失败采用指数退避重试min(max(interval, 60) * 2^(failures-1), 300)秒连续错误超过--max-query-errors默认 5则输出status-queryblockerpolicy.ts。数据来源在 github.ts 中通过 GitHub GraphQL 拉取REVIEW_THREADS_QUERYreview 线程、PR_COMMIT_STATUS_QUERY最近 50 个 commit 的 status rollup、PR_CHECK_ROLLUP_QUERY最近 1 个 commit 上的 check run / status context 分页。可观测的字段类型定义在 types.ts其中MergeStateStatus枚举了BEHIND / BLOCKED / CLEAN / CONFLICTING / DIRTY / DRAFT / HAS_HOOKS / UNKNOWN / UNSTABLE九种状态——第 8 步的硬失败判定正是针对其中UNSTABLE、DIRTY与BLOCKED的组合语义设计的。watch-pr的常用 CLI 选项汇总cli.ts选项默认值说明--owner owner/--repo repo无显式指定 GitHub 仓库--pr number无要观察的 PR 号--stackfalse观察整条连接的开放堆栈--queued-stackfalse观察冻结队列直到全部合并与--stack互斥--stack-prs n,...无冻结的 bottom-to-top 队列仅 queued 模式且要求--queued-stack--interval seconds60轮询间隔--sweep-interval seconds300整堆扫描间隔--timeout seconds0截止时间0 表示禁用--max-query-errors count5连续查询错误预算--status-onlyfalse只输出一次状态表并退出 0--allow-draftfalse不把 draft 视为 merge gate--prettyfalse输出人类可读文本而非 JSON十、第 9 步在 ceiling 停下并汇报当已验证的 run 全部合并后Shipping 结束于一次清晰的汇报。这不是接着合并下一个的信号而是**新的验证回合new pass through step 1**的起点报告落地了什么每个 PR 及其验证者、verdict报告下一个未验证的 PR 是谁报告验证它需要做什么。按照 playbook 的统一要求最终回复必须覆盖verified run 及其 ceiling、每个 PR 的 verdict 与产出者、你 arm 了什么以及如何确认、落地了什么、以及下一个缺口gap需要什么。回复风格遵循 Poteto Mode 的Writing the reply规范——短陈述句、每句话承载证据或标签measured / inferred / guess、绝不虚构链接SKILL.md。十一、落地实战一个最小可运行的检查清单把上述九步压缩成 Agent 可以直接照做的清单forge 解析command -v origin成功且可解析仓库 → 用origin pr ...否则gh并记录回退不要求gt。独立验证每个 PR 一个 Cursor cloud subagent对 parent vs head 实操control-ui/control-cliverdict 发布到该 PRPASS/PASSNOTES通过FAIL阻断。记录 patch 指纹head SHA、base SHA、git patch-id落地前比对 patch-id变了就重验没变则重跑 mergeability 与 CI。只准备底部fetch trunk → rebase 到 trunk tip → push → retarget 唯一底部 PR 的 base → 重跑第 3 步。逐个落地forge pr merge pr --squash要 merge-when-ready 则加--auto并明确你用的是哪个 forge 的--auto语义。不读autoMergeRequest当就绪以活动 forge 对底部 PR 的真实报告为准报不了就说未知。合并后重算确认 merged SHA 在 trunk、冻结列表去掉该 PR、检查新底部 PR 的 base/head/checks/patch-id。观察 frontierGitHub 用scripts/watch-pr/watch-pr --queued-stack --stack-prs bottom唤醒再轮询gh pr view的终态字段只在三种硬失败条件下判定失败BLOCKEDpending checks 或 auto-merge armed 不是失败在/loop动态模式下持有。停在 ceiling汇报 landed / next unverified PR / 验证所需工作延长 run 是新的一轮第 1 步。十二、适用前提与边界本 playbook 面向 GitHub 与 Origin 两个 forgewatch-pr脚本是 GitHub 专属babysit.md 明确指出公共 watcher 保持 GitHub-specific不要假装它能覆盖 Origin也不要在本 playbook 里为 Origin 另写实现。Origin 路径完全走origin pr ...命令。Babysit 与 Shipping 分工不可混淆Babysit 的drive结束于 merge-ready落地与 merge-when-ready 的 arm 必须显式请求否则路由回本 playbookbabysit.md 第 6、9 步。本 playbook 属于 pstack 插件安装方式为在 Cursor 中执行/add-plugin pstack见 pstack/README.md并通过/poteto-mode触发其完整规则与原则索引位于 SKILL.md。验证子代理的模型角色配置由/setup-pstack决定默认 code 走grok-4.6-fast-xhigh、判断与文案走claude-fable-5-1-thinking-max可在 pstack 中按角色覆盖SKILL.md 的 Subagents 一节。总结Shipping playbook 把落地一批绿色 PR从一句合并吧变成了一套可审计、可重放、防回归的工程协议绿色不是安全独立 verdict 才是堆栈只能从底部连续落地verdict 会过期patch-id 是对账的锚点观察合并前沿时你的职责是报告而不是改动队列。配合watch-pr的终态判定与冻结队列机制一个 Agent 可以在/loop下整夜无人值守地把一摞 PR 安全地送进主干并在每个缺口处留下清晰、可继续的交接说明。【免费下载链接】pluginsCursor plugin specification and official plugins项目地址: https://gitcode.com/GitHub_Trending/plugins125/plugins创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考