Skip to content

Harness 竞速

第一次让两个 harness 跑同一个 brief 互拼,你做这件事是因为决不出 Codex 还是 Claude Code 在你的代码库上更好。第二次做,是因为 Aider 快了 40%、diff 也更干净——你想知道哪个 harness 在哪类任务上赢。到第十次,你跑竞速是因为它比靠猜便宜。

SprintLoop 里的harness 是执行 brief 的 agent 运行时:Claude Code、Codex CLI、Cursor Compose、Aider、Devin,或任意通过 harness adapter API 接入的 harness。竞速 指把同一个 brief 并行 dispatch 给两个或更多 harness,落进同级的若干 lane 中,让它们都跑完(或被首位 sign-off 一口气杀掉),再用 diff comparator 而不是直觉挑赢家。

为什么要跑竞速

经得起认真成本分析的三个理由:

  • 质量。 不同 harness 犯的错不同。Claude 倾向于 commit message 解释过头、边界用例测得不够;Codex 倾向于注释不够、refactor 过度;Aider 又快又外科手术式,但碰到含糊的 brief 会卡住。winner picker 不在乎这些风格差异——它按 diff 大小、测试覆盖率变化、lint 通过、Review Committee 判定打分。在真正重要的那些 run 上,你拿到的是整组里最好的。
  • 速度。 竞速 dispatch 在第一个产出过关 diff 的 harness 那里结束(CI 绿、没有阻塞判定)。在并行工作上,这通常比让 harness 串行跑、失败再 fallback 快 30–50%。
  • 成本控制。 这是反直觉的一条。你会以为竞速代价是 N 倍。实际上第二名 harness 在它的预算被花掉大半之前就被杀掉了——我们遥测里被 cancel 的 lane 中位数只消耗赢家 18% 的 token。所以一场三路竞速通常是单次 dispatch 的 1.4–1.6 倍,而不是 3 倍。

反对竞速的情形是:brief 很 trivial(“重命名这个变量”)、或你对特定类工作就信某个 harness(“这个仓库里所有小 refactor 都是 Aider 赢”)。这没问题——竞速是 per-dispatch opt-in,工作区会记住哪些 brief 你跑了竞速、哪些没跑。

comparator 怎么选赢家

竞速里每条跑完的 lane 退出时带着一个分数。分数是这些信号的线性组合:

信号权重来源
CI green0.30GitHub / GitLab status checks
Reviewer verdict0.25Review Committee (Architect, Security, QA)
Diff size delta0.15相对 brief 估算的 LOC 增减
Test coverage delta0.15覆盖率工具输出 (jest, pytest, go test)
Lint clean0.08仓库声明的任何 linter
Wall time0.07首个完成的奖励(90 秒后衰减)

权重可在 Settings → Racing 按工作区配置。上述默认值是基于约 14,000 场竞速、六个月的内部遥测调出来的;要把产品交付到受监管行业的团队,通常会把 reviewer verdict 权重调高、diff size 权重调低。

竞速里第一条 lane 一发出”ready for review”信号,comparator 就开始跑。打平(5% 之内)会浮出一个 picker —— 人类 dispatcher 拿到并排 diff 视图自己挑。平局区间之外,则自动晋升赢家、cancel 其他同级。

什么被 cancel,什么留下

comparator 选出赢家后,同级 lane 转入 canceled,其作用域 claim 立即释放。它们的 tool log 和签名条目永远留在审计台账上——没有纸面记录的竞速是最差形态的浪费——你可以打开任意一条被 cancel 的 lane 的 diff,看看输家试过什么。

关于被 cancel 的同级,两件事要知道:

  • 它们的 commit 不会被 push。 一条被 cancel 的 lane 不会开 PR。它的分支留在 SprintLoop worker 本地,归档,30 天内若未打 tag 即被清理。
  • 它们的 tool call 和模型支出仍计入账单。 cancel 阻止的是新的 token 消耗,不会追回已经花掉的。这就是 comparator 的”首个完成奖励”为什么有用——快的输家比慢的输家便宜。

常见竞速及其用法

我们最常见到的竞速组合:

  1. Claude Code vs. Codex 跑功能实现。 非 trivial 工作的默认。两个 harness 的强项有实质差异——Claude 强在架构,Codex 强在紧凑、地道的实现——comparator 多半能干净利落地破局。
  2. Aider vs. Codex 跑小 refactor。 知道工作是机械性的时候,Aider 更小的表面积常常在速度上赢,Codex 提供一道理智检查:refactor 没有跑偏。
  3. 三路跑难缠的 bug。 Claude Code、Codex、Cursor Compose。要省着用——通常是单 harness dispatch 已经失败之后才用。
  4. 同一个 harness、两个不同 prompt。 同 harness 不同 brief。主要用于 prompt 工程实验——有用,但一旦选定赢家 prompt 就关掉。

你会真正看到的成本

200 行规模功能的一场三路竞速,按现行模型价格通常落在 $0.40–$1.20 区间——具体看你拼哪几个 harness 以及 maxTokens 配得多激进。输方 lane 会在赢方 CI 信号产生后几秒内被 comparator 杀掉,所以 token 支出的长尾是有界的。

工作区设置里有每日竞速预算。超额后,后续竞速会降级为单 harness dispatch 并显示一条横幅。这是软性控制——可以内联覆盖——但它已经把好几个团队从一种失控循环里救出来:默认开着竞速,所有 brief 都被竞速。

启动你的第一场竞速

Cmd+N 打开 dispatch 对话框。在 harness picker 下面,把 Race 切开。挑两到三个 harness(每个都要有 key——见 Get started)。如果你的工作区设了预算上限,把它设进去。Dispatch。

dispatch 返回 N 个同级 lane ID。每条都在 Lanes 面板里渲染成自己的卡片;这些卡片在视觉上分组在一个 “Race” 头下,附带实时赢家指示。点任意一张卡,就能落到那条 lane 的 tool log 和 diff。

赢家选出后,竞速头会折叠进赢方的 lane 卡片,其余卡片归档到一个 “Canceled siblings” 折叠区。事后可以点进任意一条 inspect。