ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Multi-Loop Collision:当 CI Sweeper 与 PR Babysitter 同时修改同一个 PR——来自 loop-engineering 的真实事故复盘与分支锁解决方案

2026/9/24 16:26:09 拓冰建站 浏览量
Multi-Loop Collision:当 CI Sweeper 与 PR Babysitter 同时修改同一个 PR——来自 loop-engineering 的真实事故复盘与分支锁解决方案 人工智能AI AgentAgent 工作流CLI研发协作AI 技能MCP 服务【免费下载链接】loop-engineeringPractical patterns, starters CLI tools for loop engineering with AI coding agents. Design systems that prompt and orchestrate agents (inspired by Addy Osmani and Boris Cherny). Includes loop-audit, loop-init, loop-cost.项目地址https://gitcode.com/gh_mirrors/lo/loop-engineering点击查看免费下载本文基于 loop-engineering 仓库中的真实生产事故记录 stories/multi-loop-collision.md 展开。它记录了两个独立调度的 AI 行动循环CI Sweeper 与 PR Babysitter在同一分支上各自生成互相冲突的修复提交最终造成约 5 倍 token 消耗和 45 分钟人工解耦的完整经过。读完本文你将掌握行动循环为什么需要分支锁branch lock、acting_on状态约定如何在多个循环之间实现碰撞检测、以及 loop-worktree 的lock/unlock命令如何把这一约定从靠人自觉升级为机械化的咨询式锁。事故背景两个循环盯上了同一条分支事故场景非常简单却极具代表性。团队同时在同一个仓库里运行着两个具备自动修复能力的行动循环L2循环配置职责CI Sweeper/loop 15m最多重试 3 次监控失败 CI诊断并提交最小修复PR Babysitter/loop 10m同一仓库盯守活跃 PR 的 CI、review、rebase 与合并两者共享的目标是fix/auth-token-refresh分支对应 PR #318。按照 patterns/ci-sweeper.md 的定位CI Sweeper 负责对 main 或活跃分支上的失败 CI 快速响应而按照 patterns/pr-babysitter.md 的定位PR Babysitter 负责把 PR 从开题推到可合并状态。当一条 PR 的分支上同时出现失败的 CI 测试时两个循环的职责范围天然重叠——这正是事故的温床。什么在正常工作两个循环的判断都没错复盘首先要诚实记录做得对的部分。根据 stories/multi-loop-collision.md 的记录两个循环都独立且正确地定位到了失败的auth测试test_refresh_token_expiry一类的鉴权令牌刷新用例说明各自的 triage 分类逻辑工作正常周二早上审计时两个循环的状态文件都如实记录了这次重叠ci-sweeper-state.md与pr-babysitter-state.md说明状态文件作为可观测性载体是有效的。问题从来不是循环不会发现问题而是两个循环没有互相感知。什么坏了两套互相冲突的修复提交事故链条如下时间戳来自原文档14:02CI Sweeper 在fix/auth-token-refresh分支上拉起一个 worktree开始实施它认为的最小修复14:07PR Babysitter 在同一个 PR上拉起了另一个不同的最小修复方案结果是两个提交、两种互斥的修复思路同时出现在 PR 上reviewer 完全被搞糊涂了不知道哪个是真正的修复更糟的是成本失控该 PR 的合并 token 消耗约 40 万 token而正常水平约 8 万 token——一个 PR 花了平时 5 倍的预算。这两个循环各自遵循了自己的模式文档CI Sweeper 打开 worktree、起草修复、等待 verifier 与人工确认见 patterns/ci-sweeper.md 的Typical CyclePR Babysitter 对失败检查项拉起minimal-fix子代理见 patterns/pr-babysitter.md 的典型循环。单个循环看每一步都是规范动作整体看缺了一道互斥检查。量化指标原文档给出了完整的事故度量表指标数值重复修复尝试2 次人工解耦耗时45 分钟根因缺少acting_on碰撞检查结合 patterns/ci-sweeper.md 的成本画像可以进一步理解为什么这么贵一次典型的 L2 修复尝试worktree implementer verifier本身就接近 20 万 token两次独立修复叠加后token 消耗落到 40 万量级完全符合成本模型的推算而 45 分钟的人工解耦时间本质上是把两个 AI 循环各自产生的错误上下文重新对齐的代价。教训行动循环需要状态层面的分支锁原文档给出的教训只有一句话但它是整套 multi-loop 协调机制的核心Action loops need abranch lockin state.行动循环会实际改动分支、提交代码的循环L2 及以上必须在状态文件中声明自己正在处理哪条分支/哪个 PR即写入acting_on: branch-or-pr-id。随后这一约定被固化为 docs/multi-loop.md 的碰撞检测流程每个行动循环在状态文件中写入acting_on: 分支名或 PR id在拉起 worktree 修复之前先读取所有其他模式的状态文件如果发现另一个循环的acting_on与自己的目标匹配则跳过本次执行并把跳过原因记入 loop-run-log.md。落到这次事故的具体职责划分是CI Sweeper 拥有红色 CI的处理权PR Babysitter 在读到ci-sweeper-state.md显示某个 PR 已被acting_on标记时跳过对该 PR 的修复动作。多循环协调的五条原则docs/multi-loop.md 把上述事故上升为通用原则。在一个仓库里跑多个循环是常态但没有边界的多循环就是循环互殴。协调原则如下每条分支一个属主One owner per branch——最多只有一个循环在一小时内改动某条分支状态文件相互分离——STATE.md用于 triage优先级与人工收件箱行动循环使用各自专属的状态文件Triage 只报告行动循环才执行——Daily Triage 在 L1 阶段永不与 CI Sweeper 的修复竞争共享 denylist——把同一份路径 denylist 复制进每个LOOP.md聚合 token 预算——参见 templates/loop-budget.md.template。推荐的仓库根目录状态布局如下来自原文档STATE.md # Daily Triage优先级、人工收件箱 pr-babysitter-state.md # PR 观察者 ci-sweeper-state.md # 活跃 CI 失败 尝试次数 dependency-sweeper-state.md # 进行中的依赖更新 post-merge-state.md # 合入后清理积压 loop-run-log.md # 只追加的可观测性日志循环冲突时的优先级栈当多个循环目标重叠时docs/multi-loop.md 定义了明确的优先级栈冲突时由高优先级循环先执行优先级循环理由1CI Sweeper红色 main 阻塞一切2PR Babysitter活跃 PR 对时间敏感3Dependency SweeperCI 红色时暂停4Post-Merge Cleanup非高峰、紧急度最低5Daily TriageL1 只出报告负责调度其他循环调度协调应在根目录LOOP.md中显式文档化。原文档给出了可直接复制的示例## Multi-loop schedule - CI Sweeper: /loop 15m (active hours) - PR Babysitter: /loop 10m (active hours, skip if CI Sweeper acting on same PR) - Daily Triage: /loop 1d 08:00 - Dependency Sweeper: /loop 6h (skip if main CI red) - Post-Merge: /loop 1d 22:00注意 PR Babysitter 一行的括号注释skip if CI Sweeper acting on same PR——这就是本次事故后补上的调度契约对应本仓库实际运行的多循环调度表见 LOOP.md 的 Multi-loop coordination 一节。从状态约定到机械化锁loop-worktree lock/unlock纯靠状态文件 人工阅读的碰撞检测有一个致命弱点它依赖循环的控制脚本自觉去读别人的状态文件。仓库给出的更强方案是用工具把约定机械化——tools/loop-worktree 的lock/unlock命令把docs/multi-loop.md的acting_on约定实现为一个咨询式锁advisory lockloop-worktree lock --paths package.json,package-lock.json --owner dependency-sweeper --ttl 6h \ || exit 2 # 另一个属主持有重叠路径的锁 —— 跳过本次运行 loop-worktree create --run-id $RUN_ID --pattern dependency-sweeper # ... 执行修复工作 ... loop-worktree unlock --owner dependency-sweeper控制脚本在拉起 worktree之前执行loop-worktree lock工作完成后执行loop-worktree unlock。关键设计是loop-worktree create本身不检查锁两者靠控制脚本中的配对约定来保持同步——这正与loop-context --check和loop-worktree mark --status escalated的配对方式一致见 docs/multi-loop.md 与 tools/loop-worktree/README.md。同样的约定也通过--lock-paths选项存在于 tools/loop-sandbox一次性沙箱 agent 运行也属于可能撞车的控制脚本但它是可选开启的——不带--lock-paths的loop-sandbox run不受锁保护。锁的源码级原理路径重叠、TTL、等待与死锁检测在 tools/loop-worktree/src/lock.ts 中可以读到这个锁的完整实现几个关键设计值得注意锁文件即状态每个属主一个 JSON 文件存放在.loop-worktrees/locks/owner.json字段包括owner、paths、lockedAt与可选的expiresAt不传--ttl则永不过期必须显式unlock见 lock.ts。这个文件的物理存在形式就是acting_on约定的机械化版本——只不过它锁定的是路径 glob而非分支名因此还能捕捉跨模式的冲突比如 CI Sweeper 与 Dependency Sweeper 同时要改package.json。按路径段比较的重叠判断pathsOverlap把两个 glob 按/切分成段逐段比较通配段*/**与该位置任意内容兼容因此src/**与src/foo.ts重叠而docs/api与docs/apidocs.md不重叠不同字面段不是简单的前缀匹配。实现注释明确说明这是故意简单的咨询式锁而非完整 glob 引擎lock.ts。跨进程互斥lock的检查-再写入临界区通过一个独占创建的 mutex 文件.loop-worktrees/locks/.mutex串行化5 秒超时避免两个同时发起的lock调用都在对方写入前通过重叠检查——这正是本功能要防的竞态本身lock.ts。等待与死锁检测带--wait 15m时锁被占用会进入等待队列并写入.wait.json等待图一旦成环立即抛出Deadlock detected: A - B - Alock.ts不会无限挂起。过期清理loop-worktree locks --sweep只报告过期锁加--force才删除孤立锁属主崩溃未解锁会被显式暴露而非静默忽略与gc命令默认只报告的仓库惯例一致lock.ts。这些行为都有测试用例背书。tools/loop-worktree/test/lock.test.mjs 覆盖了路径段边界docs/apivsdocs/apidocs.md不重叠、相同属主重复加锁会替换而非叠加、过期锁不再阻塞新锁、非法--owner含路径分隔符、可逃逸锁目录被拒绝、并发lock竞争时恰好只有一个获胜以及--wait排队与死锁环检测如Deadlock detected: B - A - B。落地示例把碰撞检测写进两个循环的状态文件对于不引入锁工具的场景原文档与模式文档给出了纯状态文件的做法。CI Sweeperpatterns/ci-sweeper.md在ci-sweeper-state.md中跟踪commit SHA、失败 job、尝试次数、worktree/PR 链接、结果。将acting_on写入后形如## CI Sweeper — Active Failures Last run: 2026-06-09 14:30 UTC ### fix/auth-token-refresh (PR #318) — acting_on - Job: test-auth - Failure: AssertionError in test_refresh_token_expiry - Attempts: 1/3 - Last action: Minimal fix proposed in worktree fix/ci-auth-refresh - Status: Waiting for verifier humanPR Babysitterpatterns/pr-babysitter.md在pr-babysitter-state.md中记录每个被盯守 PR 的状态并在读到ci-sweeper-state.md中对应acting_on标记后跳过修复- #318 (fix/auth-token-refresh) Checks: test-auth FAILING (owned by CI Sweeper — skipping fix) Last action: no-op, logged skip to loop-run-log.md每次跳过都要写入 loop-run-log.md只追加、按 run 一条 JSON字段含pattern、outcome、tokens_estimate保证这次为什么没动手对人工完全透明。对于无法自动判定属主的歧义情况docs/multi-loop.md 建议在STATE.md中开一个共享的Human Inbox## Human Inbox (ambiguous / cross-loop) - [ ] PR #42: CI Sweeper and PR Babysitter both flagged — human pick owner同类事故佐证优先级锁与预检PR #318 并非孤例。仓库里的姊妹篇事故 stories/dependency-vs-ci-sweeper-collision.md 记录了一次跨模式碰撞CI Sweeper 正在 main 上修复回归时Dependency Sweeper 把一次安全的 minor 依赖升级直接合入红色 main引入传递性回归CI Sweeper 在环境已经变化的情况下继续修原 bug一小时内烧掉约 150 万 token且两个循环同时写loop-run-log.md导致 git push 冲突。它的教训与 PR #318 互补高优先级修复活跃时低优先级变更循环不得执行。据此 docs/multi-loop.md 补上了优先级栈Dependency Sweeper 现在运行预检——先读ci-sweeper-state.md确认 main CI 是否绿色非绿则跳过并在 2 小时后重试同时用错峰的 cron 调度避免状态文件写冲突。两起事故合起来给出完整的防碰撞策略状态层的acting_on声明 工具层的咨询式锁 优先级栈 预检pre-flight 错峰调度。实操清单给仓库新增一个行动循环前结合原文档与本次复盘部署任何新的 L2 行动循环前建议逐项核对声明分支属主状态文件写入acting_on: branch-or-pr-id行动前读取所有其他模式的状态文件用锁机械化约定控制脚本在create前loop-worktree lock --paths globs --owner pattern完成后unlock冲突时exit 2跳过并记入loop-run-log.md遵守优先级栈确认自己的循环在冲突时的优先级CI Sweeper PR Babysitter Dependency Sweeper Post-Merge Cleanup Daily Triage设置预算与熔断行动循环要配loop-guard熔断loop-context --check与尝试上限防止同一条失败反复重试烧 token成本画像与每日上限见 patterns/ci-sweeper.md 与 patterns/pr-babysitter.md安全细则见 docs/safety.md共享 denylist 与聚合预算把同一份路径 denylist 复制到每个LOOP.mdtoken 预算按 templates/loop-budget.md.template 聚合保持可观测跳过、等待、升级都要落 loop-run-log.md歧义冲突进STATE.md的 Human Inbox。参考事故原始记录stories/multi-loop-collision.md协调规范docs/multi-loop.md工具实现tools/loop-worktreelock.ts、cli.ts、lock.test.mjs循环模式patterns/ci-sweeper.md、patterns/pr-babysitter.md同类事故stories/dependency-vs-ci-sweeper-collision.md本仓库实际调度与优先级LOOP.md赞分享人工智能AI AgentAgent 工作流CLI研发协作AI 技能MCP 服务【免费下载链接】loop-engineeringPractical patterns, starters CLI tools for loop engineering with AI coding agents. Design systems that prompt and orchestrate agents (inspired by Addy Osmani and Boris Cherny). Includes loop-audit, loop-init, loop-cost.项目地址https://gitcode.com/gh_mirrors/lo/loop-engineering点击查看免费下载相关推荐PR Babysitter Loop 实战指南用 loop-engineering 模式自动化 PR 审查、CI 修复与合并就绪判定PR Babysitter Loop 实战指南用 loop engineering 模式自动化 PR 审查、CI 修复与合并就绪判定 导读 本文基于 pat人工智能AI AgentAgent 工作流CLI研发协作AI 技能MCP 服务Codex 上的 PR Babysitter基于 Loop Engineering 的 PR 看护与自动修复实践Codex 上的 PR Babysitter基于 Loop Engineering 的 PR 看护与自动修复实践 PR BabysitterPR 看护循环人工智能AI AgentAgent 工作流CLI研发协作AI 技能MCP 服务loop-engineering 多循环优先级冲突实战复盘Dependency Sweeper 与 CI Sweeper 在同一分支上互踩的根因、损失与修复方案loop engineering 多循环优先级冲突实战复盘Dependency Sweeper 与 CI Sweeper 在同一分支上互踩的根因、损失与修复方人工智能AI AgentAgent 工作流CLI研发协作AI 技能MCP 服务上一篇Buzz如何在本地实现完全离线的专业级语音转文字下一篇探索GleanFacebook Incubator中的高效数据收集框架创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考