HarnessForge v2:轨迹优先的 Coding Agent 训练数据工厂
从'先设计任务再收集轨迹'到'先收集轨迹再提炼任务'的范式转变。三阶段解耦架构:Repo 筛选 → Harness 持续开发(完整轨迹记录)→ 轨迹理解与任务提炼。让数据说话,而不是凭空设计。
HarnessForge v2:轨迹优先的 Coding Agent 训练数据工厂
核心转变:v1 试图在没有数据的情况下”精心设计高质量任务”——五个 Agent 角色协作,先合成任务再收集轨迹。这是过早优化。v2 做了一个根本性的反转:先大规模收集原始开发轨迹,再从轨迹中提炼任务。 就像预训练数据一样——先大规模采集,再做质量筛选。不在采集阶段追求精品。
最本质的设计洞察:repo 的 issue/PR 历史本身就是”答案的提示”——如果直接按 PR 粒度给任务,Dev 拿到的信息太多,任务太简单,轨迹没有训练价值。所以要故意把里程碑粒度做粗,让 Dev 面对一个大的、模糊的开发目标,产出有价值的长程探索轨迹。而 PR/issue 的真正价值在于:当 Dev 卡住时,它们是现成的、ground truth 级别的提示储备——不需要 LLM 去编,repo 里已经有了。粒度越粗 → 任务越难 → 轨迹越有价值;PR/issue 作为后备提示,保证 Dev 卡住了也不会死在那里。
〇、方案全景:一图看懂
v1 方案总览:五角色串行流水线
v1:先设计任务,再收集轨迹
┌──────────────────────────────────────────┐
│ 紧耦合 · 串行依赖 │
│ │
Release Notes │ ┌────────────┐ Feature → 复合任务 │
+ Changelog ──→ │ PM │ ──────────→ tasks │
│ │ (LLM ⭐⭐) │ + 四级渐进提示 │
│ └────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────┐ 合成验收测试 │
│ │ Test │ ──────────→ tests │
│ │ Crafter │ │
│ │ (LLM ⭐) │ │
│ └────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────┐ 按任务逐个执行 │
│ │ Dev │ ──────────→ trajectory │
│ │ (LLM ⭐⭐) │ 每个任务独立 │
│ └────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────┐ 筛选有训练价值的 │
│ │ Reviewer │ ──────────→ verified │
│ │ (LLM ⭐⭐) │ tasks │
│ └────────────┘ │
│ │
│ LLM 角色:4 个 │
│ 任务设计 → 轨迹收集 → 筛选:串行依赖 │
└──────────────────────────────────────────┘
v1 的核心问题:任务设计和轨迹收集强耦合。每个 release feature 被单独设计成一个独立任务,Dev 按任务逐个执行——虽然比 PR 聚类更自然,但本质上仍是”先精心设计任务、再收集轨迹”。在没有一条轨迹数据之前,就在投入大量精力”优化”任务描述、提示设计和测试合成。
v2 方案总览:三阶段解耦 · 轨迹优先
v2:先收集轨迹,再提炼任务
╔═══════════════╗ ╔═════════════════════╗ ╔═══════════════════╗
║ Stage 1 ║ ║ Stage 2 ║ ║ Stage 3 ║
║ Repo 筛选 ║ ──→ ║ Harness 持续开发 ║ ──→ ║ 轨迹理解 ║
║ + 里程碑规划 ║ ║ (完整轨迹记录) ║ ║ + 任务提炼 ║
╚═══════════════╝ ╚═════════════════════╝ ╚═══════════════════╝
│ │ │
│ │ │
┌────▼────┐ ┌─────▼──────┐ ┌──────▼──────┐
│ 脚本 + │ │ │ │ │
│ LLM辅助 │ │ ┌──────┐ │ │ 卡点切片 │
│ │ │ │ Dev │ │ │ DPO 对提取 │
│ Release │ │ │HY3.0 │ │ │ 长程 SFT │
│ Notes │ │ └──┬───┘ │ │ 片段切割 │
│ ↓ │ │ │卡住 │ │ Mentor交互 │
│ 里程碑 │ │ ▼ │ │ │
│ 序列 │ │ ┌──────┐ │ │ ↓ │
│ │ │ │Mentor│ │ │ verified │
│ │ │ │(LLM) │ │ │ tasks │
└─────────┘ │ └──────┘ │ └─────────────┘
│ │
独立执行 │ Navigator │ 独立执行
输出: │ (规则引擎) │ 输出:
repo list │ Verifier │ verified tasks
+ milestones │ (脚本) │ (规模可伸缩)
│ Recorder │
│ (日志) │
│ │
│ LLM:仅 2个 │
└────────────┘
v2 的核心优势:三阶段完全独立。Stage 2 的唯一目标就是”不停开发,留下轨迹”。任务提炼(Stage 3)在拥有数据之后才做,让数据说话。
v2 最本质的设计点:里程碑粒度故意做粗——跨多个 PR/issue,让 Dev 面对一个大的、模糊的开发目标。 这样才能产出有价值的长程探索轨迹。如果按 PR 粒度给任务,等于直接告诉 Dev 改什么,任务太简单,轨迹没有训练价值。而 PR/issue 的真正作用是”后备提示”:Dev 卡住时,Mentor 不需要生成提示——repo 中已有 issue 描述、PR 描述、PR 文件列表、PR diff 这些现成的、ground truth 级别的信息,按需释放即可。粗粒度保证了轨迹质量,后备提示保证了 Dev 不会死在那里。
v1 → v2 关键变化对比
| 维度 | v1 | v2 | 为什么更好 |
|---|---|---|---|
| 设计哲学 | 先设计任务,再收集轨迹 | 先收集轨迹,再提炼任务 | 数据驱动 vs 假设驱动 |
| 核心流程 | 任务设计与轨迹收集串行耦合 | 三阶段完全解耦 | 任何阶段可独立迭代、独立优化 |
| LLM 角色 | 4 个(PM / Test Crafter / Dev / Reviewer) | 2 个(Dev + Mentor)+ 规则/脚本 | 复杂度大幅降低 |
| 提示机制 | PM Agent 动态合成提示(需要 LLM) | 粗粒度保证难度,PR/issue 作为后备提示按需释放 | 不需要 LLM 合成提示 |
| 任务来源 | Release Feature → 逐个独立任务 | Release → 里程碑序列 → 持续开发 | 从离散任务变成连续开发流 |
| Dev 行为 | 每个任务独立执行,任务间无关联 | 沿里程碑持续开发,前序代码是后序的上下文 | 产出真正的长程轨迹 |
| Dev 模型 | Sonnet-4.5(外部模型) | HY3.0(默认)或 Opus-4.6(备选) | 目标模型成本低 + 能力边界;强模型轨迹质量高 |
| 失败处理 | 任务失败 → 该任务数据丢弃 | 里程碑 STUCK → 给提示 → 继续开发 | 失败本身是训练信号 |
| Task 质量保证 | 前置设计(靠假设,未验证) | 后置分析(靠数据,可验证) | 有轨迹后才决定什么是好 task |
| 最小验证 | 需要 PM/Test Crafter/Dev/Reviewer 全部就绪 | Stage 2 单独跑 3 天即可 | 快速 Go/No-Go 决策 |
最关键的变化:v1 的 Dev 是”接收任务 → 执行 → 交付”的模式,每个任务之间没有连续性。v2 的 Dev 是”从 base 开始持续开发,经过一个个里程碑,直到最终版本”——这更接近真实开发者的工作方式,也天然产出长程连续轨迹。
里程碑粒度:v2 成败的关键设计决策
三阶段解耦看起来简单,但 Stage 1 里”里程碑怎么切”直接决定 Stage 2 轨迹的质量。这是整个 v2 方案中最需要仔细设计的一环。
粒度太粗的问题:
如果一个里程碑是”实现 Django 5.1 的全部新特性”(即把一整个大版本作为一步),Dev 大概率在中途就彻底卡死——要理解的上下文太多、要做的修改太分散。结果是不断触发 Mentor 提示,轨迹退化为”反复收提示 → 照搬 → 再收提示”的机械循环,没有真正的探索和规划行为。
粒度太细的问题:
如果每个 commit 就是一个里程碑,Dev 基本上一两轮就完成了——退化成了 SWE-bench 的单 PR 模式。长程规划、探索回退、方向调整这些高价值信号完全不会出现。
推荐的粒度:一个完整 feature 的实现作为一个里程碑。
以 Django 5.1 为例:
- 🔴 太粗:“实现 Django 5.1 全部新特性” → 一步到位,Dev 卡死
- 🟢 合适:“实现
LoginRequiredMiddleware”(537 行, 12 文件)→ 需要理解中间件+装饰器+admin 适配,有足够的探索空间 - 🟢 合适:“实现
GeneratedField”(730 行, 19 文件)→ 新建子系统,需要长程规划 - 🔴 太细:“修复
DomainNameValidator的 underscore 处理”(126 行, 2 文件)→ 一两轮搞定
经验法则:一个好的里程碑应该让 Dev 需要 15-50 轮交互才能完成。少于 10 轮说明太简单(切细了),超过 80 轮通常意味着 Dev 已经在无效打转(切粗了或者超出模型能力)。
里程碑排序也很重要:应该按 repo 真实的开发顺序排列。后一个里程碑的代码可能依赖前一个里程碑的修改——这种依赖关系正是长程连续轨迹的价值来源。如果打乱顺序,Dev 的开发就变成了互不相关的独立任务,失去了”持续开发”的意义。
与业界现有方案全景对比
任务复杂度
▲
│
Feature 实现 │ ┌──────────────┐
+ 重构 │ │ HarnessForge │
│ │ v2 │ ← 长程 + 交互 + 多类型
│ └──────┬───────┘
│ │
跨模块 │ ┌───────────────┘
Bug Fix │ │
│ │ ┌──────────────┐
│ │ │ HarnessForge │
│ │ │ v1 │ ← 复合任务 + 五角色
│ │ └──────────────┘
│ │
单文件 │ │
Bug Fix │ ┌──┴───────┐ ┌──────────┐ ┌────────┐
│ │CoderForge│ │ SWE-smith│ │SWE-bench│
│ │ 258K条 │ │ 50K条 │ │ 2.3K条 │
│ └──────────┘ └──────────┘ └────────┘
│
└──────────────────────────────────────→
无轨迹 单任务轨迹 长程连续轨迹
(patch) (~20 turns) (里程碑链 ~200 turns)
↑
轨迹完整性
逐方案详细对比
| 维度 | SWE-bench | SWE-smith | CoderForge | Nebius SWE-agent | DeepSWE | Hybrid-Gym | HarnessForge v2 |
|---|---|---|---|---|---|---|---|
| 任务来源 | GitHub Issue/PR | Bug 注入 | 多源汇集 | SWE-agent 跑 SWE-bench | RL rollout | 基础技能分解 | Release 里程碑 |
| 任务类型 | Bug fix | Bug fix | Bug fix | Bug fix | Bug fix | 子技能 | Feature+重构+fix |
| 任务粒度 | 单 PR | 单 PR | 单 PR | 单 PR | 单 PR | 子步骤 | 跨多 PR 的里程碑 |
| 轨迹 | ❌ 无 | ✅ 单任务 | ✅ 单任务 | ✅ 单任务 | RL rollout | ✅ 子步骤 | ✅ 长程连续 |
| 轨迹长度 | — | ~15 turns | ~20 turns | ~20 turns | 变长 | ~5 turns | ~50 turns/里程碑 |
| Dev-Mentor 交互 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ 渐进提示 |
| 提示来源 | — | — | — | — | — | — | Repo 的 issue/PR(ground truth 级别) |
| DPO 数据 | 需外部构造 | 无 | 无 | 无 | 无 | 无 | 自然产出(不同提示级别的轨迹对) |
| 多语言 | Python | Python | Python | Python | Python | Python | Python/TS/Go/Rust |
| 规模 | 2.3K | 50K | 258K(155K verified) | 80K(40.6K verified) | — | — | 规模可伸缩 |
| 信息密度 | 低(仅 patch) | 中 | 中 | 中 | 中 | 低 | 高(完整过程+交互) |
| 训练方式 | SFT | SFT | SFT | SFT | RL (GRPO) | SFT→RL | SFT + RL + DPO |
| 代码污染 | 已确认严重 | 继承 SWE-bench | 继承 SWE-bench | 继承 SWE-bench | 继承 SWE-bench | — | 可控(低 star repo + contamination 检测) |
| 脚手架依赖 | 无 | 无 | ✅ 锁定 SWE-agent | ✅ 锁定 SWE-agent | 无 | 无 | 无锁定 |
| 开源 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | 规划中 |
| SWE-bench 提升 | 基线 | — | 23%→59.4% | 40.6% | 40%→46% | — | 待验证 |
各方案解决了什么问题
| 方案 | 解决的核心问题 | 未解决的问题 |
|---|---|---|
| SWE-bench | 定义了 repo 级代码任务的评测标准 | 无轨迹、数据污染严重、只有 Python bug fix |
| SWE-smith | 通过 Bug 注入扩大数据规模至 50K | 仍是单点 bug fix、无交互、只有 Python |
| CoderForge | 多源汇集达到 258K 规模,SWE-bench 大幅提升 | 脚手架锁定、任务偏 bug fix、无用户交互(作者自述三大局限) |
| Nebius SWE-agent | 80K 规模的 SWE-agent 轨迹 | 锁定 SWE-agent 框架、只有 Python bug fix |
| DeepSWE | 证明纯 RL(无 SFT)可训练 Coding Agent | 依赖 SWE-bench 任务、无多语言 |
| Hybrid-Gym | 基础技能分解(搜索、编辑、调试) | 子技能粒度太细、缺乏端到端任务 |
| HarnessForge v2 | 长程连续轨迹 + Mentor 交互 + 多语言多类型 | 需验证长程轨迹的训练价值、污染风险需量化 |
HarnessForge v2 直接回应了 CoderForge 承认的三个局限
CoderForge-Preview 数据集 README 中明确列出了三个局限1:
-
“Scaffold Specificity”(脚手架适配性差):CoderForge 的轨迹绑定了特定的 SWE-agent 脚手架,换框架就不适用。
- v2 回应:Dev 不锁定脚手架,可用 OpenHarness 43+ 内置工具,也可用 Claude Code 原生工具集。
-
“Task Scope Narrowness”(任务范围偏窄):主要是 bug fix,缺少 feature 实现和重构任务。
- v2 回应:里程碑直接来自 release notes,天然覆盖 feature 实现(60%)、重构(25%)、bug fix(15%)。
-
“Lack of User Interaction”(缺乏用户交互):所有轨迹都是 Agent 独自完成,没有人在过程中给反馈或提示。
- v2 回应:Mentor 的渐进提示机制模拟了真实的用户-Agent 交互。且提示来自 repo 的 issue/PR 信息,是 ground truth 级别的,不是 LLM 合成的。
与 FinMCP-Bench 的交叉启示
FinMCP-Bench 的核心发现——模型在多轮工具调用中 EMR 接近零——从另一个角度验证了 HarnessForge v2 的价值定位:
- FinMCP-Bench 暴露了”长程工具编排”是当前模型的系统性盲区
- HarnessForge v2 产出的里程碑级轨迹(每个里程碑 ~50 轮工具调用)恰好覆盖这个盲区
- 特别是 Mentor 提示触发的”方向调整”模式——在工具调用链中途收到反馈后重新规划——在 FinMCP-Bench 评测的所有模型中都几乎不具备
定位差异化总结:现有方案在”大量 × 单点 × 无交互”的象限竞争。HarnessForge v2 占据的是”长程 × 多类型 × 有交互”的象限——同时具备规模弹性。
一、为什么 v1 的方向需要修正
1.1 v1 的设计缺陷
HarnessForge v1 设计了多角色 Agent 协作系统(PM → Test Crafter → Dev → Reviewer),基于 repo 的 release feature 来设计独立任务,然后让 Dev 逐个执行。方向正确,但执行路径有三个结构性问题:
问题 1:在没有数据的情况下做优化。
v1 在收集第一条轨迹之前,就在精心设计”PM 如何写任务描述”、“四级渐进提示怎么设计”、“Reviewer 如何筛选有价值轨迹”。这些设计全靠假设——我们假设 release feature 能自然转化为好的任务描述,假设 Dev 会在这些任务上展现长程规划行为,假设渐进提示能触发真实的方向调整。
但这些假设在没有实际轨迹数据的情况下,无法验证。
问题 2:任务设计和轨迹收集强耦合。
v1 的角色是串行依赖的——PM 不合成任务,Dev 就没法执行;Test Crafter 不生成测试,就没法验证。而且每个环节的设计决策(任务描述风格、提示释放协议、测试合成策略)都需要大量实验来调优,调优又依赖后续环节的反馈——鸡生蛋困境。
问题 3:逐个独立任务的模式丢失了”持续开发”的信号。
v1 把每个 release feature 设计为一个独立任务,Dev 在隔离环境中逐个完成。这意味着 Dev 不需要考虑前一个 feature 对后一个的影响、不需要管理不断增长的代码库复杂度、不需要做真正的长程规划。本质上还是单点任务的变体,只是任务更大了。
1.2 思路转变:轨迹优先
转变的关键洞察是:“任务设计”和”轨迹收集”应该彻底解耦。
v1 的逻辑:设计任务 → 收集轨迹 → 验证(紧耦合,前置假设多)
v2 的逻辑:收集轨迹 → 从轨迹中发现任务 → 按需提炼(解耦,数据驱动)
具体来说:
- Repo 筛选(独立执行)——选好 repo,确定 base 状态和里程碑序列
- 持续开发(Harness Engineering)——Dev 在 repo 上不停开发,完成一个个里程碑,全程记录轨迹。这就是一个 harness engineering 过程,目标单一:开发 + 留下完整轨迹
- 轨迹理解与任务提炼(独立执行)——从海量原始轨迹中,分析 Dev 的行为模式,提炼出高价值的训练 task
三个阶段独立可控。每个阶段都可以单独优化,不会互相阻塞。
1.3 与现有工作的对比
| 方案 | 核心方法 | 任务类型 | 轨迹完整性 | 规模 | 局限 |
|---|---|---|---|---|---|
| SWE-bench | 从 issue/PR 提取 | 单点 Bug 修复 | 无轨迹(只有 patch) | 2.3K | 无过程数据 |
| SWE-smith | Bug 注入 + Agent 修复 | 单点 Bug 修复 | 有,但探索行为简单 | 50K | 只有 bug fix |
| CoderForge | 多源汇集 + SFT | 单点 Bug 修复 | 有(258K 条) | 155K verified | 脚手架锁定、偏 bug fix、缺乏用户交互1 |
| Nebius SWE-agent | SWE-agent 框架跑 | 单点 Bug 修复 | 有(80K 条) | 40.6% SWE-bench | 单一框架 |
| DeepSWE | RL on SWE-bench | 单点 Bug 修复 | RL rollout 轨迹 | — | 依赖 SWE-bench 任务 |
| HarnessForge v2 | 里程碑持续开发 | Feature 实现 + Bug 修复 + 重构 | 长程连续轨迹(含提示交互) | 规模可伸缩 | 需要验证长程轨迹的训练价值 |
v2 解决了 CoderForge 承认的三个局限1:
- “脚手架适配性差” → v2 不锁定脚手架,Dev 可以用任何工具组合
- “任务范围偏窄(偏 bug fix)” → v2 的里程碑覆盖 feature 实现、重构、bug fix 全谱系
- “缺乏用户交互” → v2 的渐进提示机制模拟了真实的用户-Agent 交互
二、三阶段架构
┌────────────────────────────────────────────────────────────────────┐
│ HarnessForge v2 三阶段架构 │
│ │
│ ╔══════════════╗ ╔════════════════════╗ ╔══════════════════╗ │
│ ║ Stage 1 ║ ║ Stage 2 ║ ║ Stage 3 ║ │
│ ║ Repo 筛选 ║ → ║ Harness 持续开发 ║ → ║ 轨迹理解 ║ │
│ ║ + 里程碑规划 ║ ║ (完整轨迹记录) ║ ║ + 任务提炼 ║ │
│ ╚══════════════╝ ╚════════════════════╝ ╚══════════════════╝ │
│ │
│ 独立执行 独立执行 独立执行 │
│ 输出:repo list 输出:raw trajectories 输出:verified tasks│
│ + milestone plan (数 TB 原始日志) + training data │
└────────────────────────────────────────────────────────────────────┘
三、Stage 1:Repo 筛选与里程碑规划
3.1 Repo 筛选标准
与 v1 一致,但增加了对 release 质量的要求:
| 维度 | 要求 | 原因 |
|---|---|---|
| 测试覆盖 | CI 完善,测试通过率 >90% | 测试是里程碑验收的基础 |
| Release 规范 | 语义化版本,有 changelog/release notes | 里程碑划分的输入 |
| Commit 活跃度 | 近 12 月 >200 commits | 确保足够的里程碑素材 |
| 代码规模 | 10K-500K 行 | 太小没挑战,太大环境不可控 |
| 依赖管理 | 有 lock 文件 | 环境可复现 |
| 语言 | Python / TypeScript / Go / Rust | 覆盖主流 |
3.2 里程碑规划
核心思路:以 repo 的真实演进为骨架,而不是人为设计任务。
对每个 repo,从 release notes / changelog / 重要 PR 中提取里程碑序列:
repo: django/django
base_version: "5.0" # 开发起点
target_version: "5.2" # 最终目标
milestones:
# === Django 5.1 features ===
- id: "M1"
source: "Django 5.1 Release Notes"
feature: "新增 LoginRequiredMiddleware"
description: |
添加一个全局中间件,默认要求所有视图登录才能访问。
需要提供 @login_not_required 装饰器用于豁免公开页面。
admin 视图需要自动适配。
verify_commit: "abc123" # 包含此 feature 的 commit
verify_tests: "python -m pytest tests/auth_tests/ tests/middleware/"
estimated_difficulty: 3 # 1-5
- id: "M2"
source: "Django 5.1 Release Notes"
feature: "GeneratedField 支持"
description: |
在 ORM 中支持数据库级别的 generated column。
需要支持 PostgreSQL、MySQL、SQLite、Oracle 四个后端。
verify_commit: "def456"
verify_tests: "python -m pytest tests/model_fields/test_generatedfield.py"
estimated_difficulty: 4
# === Django 5.2 features ===
- id: "M3"
source: "Django 5.2 Release Notes"
feature: "Composite Primary Key 支持"
description: |
允许模型定义复合主键(多列联合主键),替代 Django 历史上
必须有单列自增主键的限制。
verify_commit: "ghi789"
verify_tests: "python -m pytest tests/composite_pk/"
estimated_difficulty: 5
# ... 更多里程碑
里程碑的粒度原则:
- 每个里程碑对应一个完整 feature 的实现
- 粒度够大——需要跨多个文件的修改,不是单行 bug fix
- 有明确的验收测试
- 里程碑之间有顺序依赖(M2 的代码建立在 M1 完成的基础上)
里程碑的来源,按优先级排序:
- Release Notes 中的新 feature(最佳——天然就是 PM 视角的需求描述)
- 重要 PR(标有 “enhancement” / “feature” label)
- 重大 Bug Fix(涉及架构修改的复杂 fix)
- 重构 PR(标有 “refactor” / “performance” label)
3.3 执行方式
这一步完全可以脚本化 + LLM 辅助:
# 1. 获取 release notes
gh release list --repo django/django --limit 10
# 2. 获取每个 release 的详细 changelog
gh release view 5.1 --repo django/django
# 3. 用 LLM 从 changelog 中提取里程碑
# 输入:release notes 全文
# 输出:结构化的 milestones YAML
# 4. 为每个里程碑找到对应的 verify_commit
# 通过 git log 匹配 feature 关键词
3.4 首批 Repo 列表
精选 15 个 repo(比 v1 的 30 个减少一半,聚焦质量):
| 语言 | Repo | Release 节奏 | 里程碑/年估计 |
|---|---|---|---|
| Python | django/django | 每 8 月 major | ~15 |
| Python | fastapi/fastapi | 频繁 minor | ~20 |
| Python | pydantic/pydantic | 每 6 月 major | ~12 |
| Python | sqlalchemy/sqlalchemy | 每 6 月 major | ~15 |
| Python | celery/celery | 每年 major | ~10 |
| TypeScript | microsoft/TypeScript | 每 3 月 minor | ~20 |
| TypeScript | vercel/next.js | 每月 minor | ~25 |
| TypeScript | trpc/trpc | 每 6 月 major | ~10 |
| TypeScript | drizzle-team/drizzle-orm | 频繁 minor | ~15 |
| TypeScript | vitest-dev/vitest | 每 3 月 minor | ~12 |
| Go | gin-gonic/gin | 每年 major | ~8 |
| Go | hashicorp/terraform | 每月 minor | ~20 |
| Go | stretchr/testify | 每年 major | ~6 |
| Rust | tokio-rs/tokio | 频繁 minor | ~15 |
| Rust | serde-rs/serde | 不频繁 | ~5 |
估计总里程碑数:~210 个(15 repo × ~14 个/repo 平均)
四、Stage 2:Harness 持续开发
4.1 核心理念
这一阶段的目标极其单一:让 Dev 不停地开发,留下完整轨迹。
没有任务设计,没有难度评估,没有质量筛选——那些都是 Stage 3 的事。Stage 2 就是一个 Harness Engineering 过程:搭好环境,放 Agent 进去干活,把过程全部录下来。
4.2 多角色协作
虽然核心目标是”Dev 持续开发”,但引入辅助角色可以提升轨迹的信息密度:
┌──────────────────────────────────────────────────────────┐
│ Harness 执行环境 │
│ │
│ ┌───────────┐ │
│ │ Navigator │ ──→ 里程碑描述 + 验收标准 │
│ │ (引路人) │ │
│ └─────┬─────┘ │
│ │ 每个里程碑开始时下发任务 │
│ ▼ │
│ ┌───────────┐ ┌───────────┐ │
│ │ Dev │ ←─────→ │ Mentor │ │
│ │ (开发者) │ 卡住时 │ (导师) │ │
│ │ │ 请求帮助 │ │ │
│ └─────┬─────┘ └───────────┘ │
│ │ │
│ │ 里程碑完成 → 验收测试 │
│ ▼ │
│ ┌───────────┐ │
│ │ Verifier │ ──→ PASS: 进入下一个里程碑 │
│ │ (验证者) │ ──→ FAIL: 告知 Dev 哪些测试未通过 │
│ └───────────┘ │
│ │
│ ┌───────────┐ │
│ │ Recorder │ ──→ 全程记录(被动,无决策权) │
│ │ (记录器) │ │
│ └───────────┘ │
└──────────────────────────────────────────────────────────┘
| 角色 | 是否必须 | 职责 | 模型 |
|---|---|---|---|
| Dev | ✅ 必须 | 核心执行者,阅读代码、编写代码、运行测试 | HY3.0(待优化的目标模型) |
| Navigator | ✅ 必须 | 按顺序下发里程碑任务,不参与执行 | 规则引擎(不需要 LLM) |
| Mentor | ✅ 必须 | Dev 卡住时提供渐进提示(L1→L2→L3) | Opus-4.6 / Sonnet-4.5(需要深度理解) |
| Verifier | ✅ 必须 | 里程碑完成时运行验收测试,返回 pass/fail | 脚本(不需要 LLM) |
| Recorder | ✅ 必须 | 全程记录 Dev 的每一步操作 | 日志系统(不需要 LLM) |
关键设计:五个”角色”中,只有 Dev 和 Mentor 需要 LLM。Navigator 和 Verifier 是规则/脚本,Recorder 是日志系统。这不是 v1 的五个 LLM Agent 协作——实际的 LLM 开销只有 Dev + Mentor 两个。
4.3 Dev 的执行模式
dev_agent:
model: "HY3.0" # 默认选择:待优化的目标模型
Dev 模型选择是一个执行层面的 trade-off:
| 策略 | 模型 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|---|
| A. 用目标模型 | HY3.0 | 轨迹直接反映能力边界;零 API 成本;可大规模执行 | 可能太弱导致大量失败轨迹 | 默认方案,优先使用 |
| B. 用强模型 | Opus-4.6 | 任务分解更合理,轨迹质量更高;完成率高 | API 成本高;轨迹反映的是强模型而非目标模型的行为 | 建立 reference 轨迹、构造对比数据 |
| C. 混合 | 两者都用 | 同一任务两套轨迹可对比分析 | 成本和复杂度翻倍 | Phase 2+ 消融实验 |
Phase 1 先用 A(HY3.0),看完成率和轨迹质量。如果完成率过低(<20%),可以部分切换到 B 产出高质量 reference 轨迹,再用 HY3.0 的失败轨迹做对比。两种数据都有训练价值。
4. 内部模型无 API 成本,规模化零边际成本
sandbox: runtime: “Docker” image: “{repo}-{base_version}:latest” network: “none” # 纯离线 resources: { cpu: 4, memory: “8g” }
tools: - read_file / write_file / edit_file # 代码读写 - bash # Shell 执行 - grep / ripgrep / find # 搜索 - git diff / git log / git status # 版本控制 # 禁止:web_search, web_fetch(纯离线)
execution_loop: for each milestone in milestone_plan: 1. Navigator 下发里程碑描述 2. Dev 开始开发(不限轮次,直到主动声明完成或触发上限) - 阅读代码、搜索、规划 - 编写代码、运行测试、迭代修改 - 如果卡住 → 向 Mentor 请求帮助(或自动触发) 3. Dev 声明完成 → Verifier 运行验收测试 - PASS → 进入下一个里程碑 - FAIL → 告知哪些测试失败,Dev 继续修复 4. 超过 max_turns(100) 仍未通过 → 标记为 STUCK,强制进入下一个里程碑 (用 verify_commit 的代码作为基础,保证后续里程碑可以继续)
context_management: # 长程开发的上下文管理策略 - 每个里程碑开始时:重置对话上下文,但保留: - 当前代码状态(文件系统) - 前几个里程碑的一句话总结 - 之前遇到的关键错误和解法摘要 - 里程碑内部:保持完整上下文 - 这样既保证长程连续性,又避免上下文溢出
### 4.4 核心洞察:为什么不直接用 PR/issue 驱动任务
**这是 v2 方案最本质的设计点。**
一个直觉的做法是:把每个 PR 或 issue 直接作为一个任务交给 Dev。但这恰恰是错的——**PR/issue 本身就是"答案的提示"**。
如果你把 issue "QuerySet union() 与 annotate() 不兼容" 加上 PR 描述 "Fix union/intersection with annotate in QuerySet" 直接给 Dev,它拿到的信息已经非常充分了:知道问题是什么、大致改哪里、用什么思路。这种情况下 Dev 可能 5 轮就搞定——轨迹短、探索浅、训练价值低。
**所以核心设计是:故意把里程碑粒度做粗,不按 PR 粒度给任务。**
一个里程碑跨 5-15 个 PR/issue,Dev 面对的是 release note 里一句话级别的模糊目标:"支持 QuerySet 的嵌套聚合操作"。它不知道具体要改哪些文件、怎么拆分子任务、先改什么后改什么——必须自己探索。这样产出的轨迹才是长程的、有试错和方向调整的、有训练价值的。
**那 PR/issue 的价值在哪?它们是现成的、ground truth 级别的后备提示。**
| 角色 | 不是 | 而是 |
|------|------|------|
| PR/issue | 驱动任务的输入 | Dev 卡住时的后备提示 |
| 里程碑 | 单 PR 粒度 | 跨多 PR 的粗粒度目标 |
| Mentor | 主动给提示 | 只在 Dev 卡住时按需释放 |
这创造了一个优雅的平衡:
- **粗粒度 → 任务难 → 轨迹有价值**:Dev 必须长程探索,产出 25-50 轮的丰富轨迹
- **后备提示 → 不会卡死 → 轨迹可完成**:Dev 实在搞不定时,释放 issue 描述、PR 描述、文件列表,逐步降低难度
- **"从难到易"的过程本身就是高价值训练信号**:Dev 在没有提示时的探索轨迹 vs 收到提示后的调整轨迹,天然形成能力对比
repo 本身自然拥有这些后备提示,不需要任何 LLM 去合成。这是 HarnessForge v2 相对于所有现有方案最核心的结构性优势。
| 信息粒度 | 来源 | 何时释放 | 示例 |
|---------|------|---------|------|
| 最模糊 | issue 标题 | Dev 初始就可见(作为需求背景) | "QuerySet union() 与 annotate() 不兼容" |
| 方向级 | issue 描述 + 复现步骤 | 连续 3 次失败 | "在 union 后调用 annotate,SQL 生成缺少列投影" |
| 模块级 | PR 标题 + 描述 | 连续 5 次失败 | "Fix union/intersection with annotate in QuerySet" |
| 文件级 | PR 的 file list | 连续 8 次失败 | `query.py`, `compiler.py` |
| 代码级 | PR diff | 连续 12 次失败(最后手段) | `Query.combine()` 第 542 行 |
### 4.5 Mentor 的渐进提示机制
基于上述洞察,Mentor 的设计极度简化——它的核心逻辑是**按规则释放 repo 中已有的信息**,而不是动态生成提示。
```yaml
mentor_agent:
# 大多数情况下不需要 LLM——只是按规则释放预置信息
# 只有在 Dev 的困境需要"翻译"时才调用 LLM(可选)
mode: "rule_based" # 默认规则驱动
fallback_model: "claude-opus-4.6" # 仅在需要定制化提示时使用
# Mentor 持有的信息(全部来自 repo 本身,无需合成):
privileged_info:
- issue_title # → L0 提示素材
- issue_body # → L1 提示素材(问题描述、复现步骤)
- pr_title_and_desc # → L2 提示素材(解决方向)
- pr_file_list # → L3 提示素材(涉及哪些文件)
- pr_review_comments # → L2.5 提示素材(设计讨论)
- pr_diff # → L4 提示素材(具体代码变更)
trigger_rules:
# 自动触发(基于 Recorder 的监控数据):
- condition: "Dev 连续 3 次 edit → test → 同类失败,方向无变化"
action: "释放 L1(issue 描述)"
- condition: "Dev 连续 5 次失败,或在同一个文件上反复修改"
action: "释放 L2(PR 描述 + review 讨论摘要)"
- condition: "Dev 连续 8 次失败"
action: "释放 L3(PR 涉及的文件列表)"
- condition: "Dev 连续 12 次失败"
action: "释放 L4(PR diff 的关键片段)"
# Dev 主动请求:
- condition: "Dev 输出 '[STUCK] 我不确定该怎么继续'"
action: "释放当前级别的下一级"
hint_levels:
L0_awareness: |
[Navigator 初始下发]
本里程碑需要解决以下问题:
- {issue_title_1}
- {issue_title_2}
(Dev 一开始就拿到 issue 标题作为需求输入)
L1_direction: |
[Mentor] 社区对这个问题有过讨论,这里是一些线索:
---
{issue_body} ← 直接释放 issue 的原始描述
---
L2_approach: |
[Mentor] 有开发者曾经提交过相关修复,思路如下:
---
{pr_title}: {pr_description} ← 直接释放 PR 描述
---
Review 讨论中的关键意见:
{pr_review_comments_summary} ← 直接释放 review 摘要
L3_files: |
[Mentor] 需要修改的文件范围:
{pr_file_list} ← 直接释放 PR 的文件列表
L4_code: |
[Mentor] 这是关键的修改点:
{pr_diff_key_hunks} ← 释放 diff 中最核心的几个 hunk
对比 v1 的提示机制:
| 维度 | v1 | v2 |
|---|---|---|
| 提示来源 | PM Agent 生成(LLM 合成) | repo 的 issue/PR 释放(已有数据) |
| LLM 依赖 | 每次提示都需要 LLM 调用 | 绝大多数情况不需要 LLM |
| 提示质量 | 取决于 PM 模型能力 | ground truth 级别(人类写的、review 过的) |
| 对齐风险 | 可能与实际任务不匹配 | 天然对齐(就是描述同一个变更) |
| 扩展性 | 每个新 repo 都需要 PM 重新合成 | 自动化——脚本抓取 issue/PR 信息即可 |
4.5 Recorder 的轨迹格式
全量记录,不做任何过滤。过滤是 Stage 3 的事。
// 每一行是一个 turn
{
"repo": "django/django",
"milestone_id": "M1",
"milestone_desc": "新增 LoginRequiredMiddleware",
"turn_id": 1,
"timestamp": 1712956800,
"role": "dev",
"action": {
"type": "think",
"content": "需要理解 Django 的中间件机制..."
},
"observation": null,
"mentor_hint": null,
"files_touched": [],
"test_status": null,
"cumulative_edits": 0,
"cumulative_test_runs": 0
}
{
"turn_id": 2,
"role": "dev",
"action": {
"type": "bash",
"content": "find . -path '*/middleware*' -name '*.py' | head -20"
},
"observation": "./django/contrib/sessions/middleware.py\n./django/middleware/common.py\n...",
"mentor_hint": null,
"files_touched": [],
"test_status": null
}
// ... 几十到几百轮 ...
{
"turn_id": 45,
"role": "dev",
"action": {
"type": "test",
"content": "python -m pytest tests/auth_tests/test_middleware.py -x -q"
},
"observation": "3 failed, 12 passed",
"mentor_hint": null,
"test_status": { "passed": 12, "failed": 3, "total": 15 }
}
{
"turn_id": 46,
"role": "mentor",
"action": {
"type": "hint",
"level": "L1",
"content": "你的中间件逻辑对了,但忽略了 admin 视图的特殊情况。admin 已经有自己的认证检查,你的中间件不应该再套一层。"
},
"trigger_reason": "3 consecutive test failures with same error pattern"
}
{
"turn_id": 47,
"role": "dev",
"action": {
"type": "think",
"content": "原来如此,admin 视图需要豁免..."
},
"direction_change": true // 关键标记:Dev 收到提示后改变了方向
}
4.6 规模估算
| 参数 | 值 | 说明 |
|---|---|---|
| Repo 数量 | 15 | 首批 |
| 每 repo 里程碑数 | ~14 | 平均 |
| 总里程碑数 | ~210 | |
| 每里程碑 Dev turns | ~50 | 含探索、编码、测试、修复 |
| 每里程碑 Mentor turns | ~3 | 平均触发 3 次提示 |
| 总 Dev turns | ~10,500 | |
| 每 turn 平均 token | ~3K | 输入+输出 |
| 总 token(Dev) | ~31.5M |
Dev 使用内部模型 HY3.0,无 API 成本。Mentor 只在 Dev 卡住时才触发,调用量远小于 Dev。
4.7 产出
每个 repo 的持续开发过程产出一个原始轨迹包:
trajectories/
django/
metadata.yaml # repo 信息 + 里程碑计划
M1-login-middleware/
trajectory.jsonl # 完整轨迹(每行一个 turn)
final_diff.patch # Dev 最终提交的 diff
ground_truth.patch # 真实 commit 的 diff
test_results.json # 验收测试结果
mentor_log.json # Mentor 提示记录
summary.yaml # 里程碑执行摘要
M2-generated-field/
...
M3-composite-pk/
...
预计总原始轨迹:~210 个里程碑 × ~50 turns/里程碑 = ~10,500 turns,约 500MB-1GB 的 JSONL 数据。
4.8 渐进式 Harness 增强(备选路径)
一开始让 Dev 自由发挥,拿到数据后再考虑加 Harness 组件。
Stage 2 的初始版本故意做得简单——Dev 自由开发,Mentor 按需提示,Recorder 全程录制。这是最小可行版本。
但拿到第一批轨迹后,可能会发现一些模式:Dev 上来就写代码,不做规划;或者 Dev 的修改思路和最优路径差距很大。这时候可以渐进式地引入更多 Harness 组件:
| 阶段 | Harness 复杂度 | 新增组件 | 触发条件 |
|---|---|---|---|
| V0(当前) | ★ | Dev + Mentor + Recorder | 初始版本 |
| V1 | ★★ | + Plan 要求:Dev 每个里程碑开始时必须先输出开发计划 | Phase 1 数据显示 Dev 无规划就动手、频繁返工 |
| V2 | ★★★ | + Plan 审查:Dev 的计划和 ground truth 的实际路径对比,偏差大时要求纠正 | V1 数据显示 Dev 计划质量差 |
| V3 | ★★★★ | + 阶段检查点:每改完一个模块,Verifier 检查中间状态是否合理 | V2 数据显示 Dev 中途偏离但要到最后才发现 |
关键原则:每一级增强都基于前一级的数据反馈,不预设。
这种渐进式增强本身也会产出高价值的训练信号:
- “plan → 被纠正 → 修正 plan → 执行” 的轨迹训练的是规划和自我修正能力
- “中途检查 → 发现偏差 → 调整” 的轨迹训练的是过程监控能力
- 不同版本的 Harness 产出不同特征的轨迹,丰富了训练数据的多样性
但这些都是未来选项,不是当前方案的一部分。先跑通 V0,看数据再决定。
五、Stage 3:轨迹理解与任务提炼
5.1 核心判断
有了详细的完整轨迹,筛选出好的 task 不是难事。
每条轨迹里天然包含了所有关键信号:Dev 在哪里卡住了、花了多少轮、需不需要提示、提示后有没有调整方向、最终是否通过。这些信号是结构化的、可量化的——不需要复杂的分析框架,基本的规则过滤就能完成大部分筛选工作。
所以 Stage 3 不需要现在过度设计。先拿到轨迹数据,看看数据长什么样,再决定具体的提炼策略。在没有数据的时候设计数据处理流程——这正是 v1 犯过的错误,不能重蹈覆辙。
5.2 已知的分析维度
虽然不做详细设计,但轨迹中有几类明确可识别的信号:
| 信号 | 如何识别 | 价值 |
|---|---|---|
| 卡点 | 连续 N 次 edit→test→fail,错误类型不变 | 每个卡点天然就是一个 hard task |
| 方向调整 | 提示前后搜索/编辑的文件发生变化 | ”收到反馈后调整策略”的训练数据 |
| 渐进成功 | 测试通过数从 0 → N 逐步增加 | 问题分解和逐步推进能力 |
| 无效探索 | Dev 花了多轮走一个方向,最终回退 | 负样本——什么不该做 |
| 高效路径 | < 15 轮完成,无需提示 | 正样本——什么该做 |
这些信号在 Recorder 记录的结构化 JSONL 中都可以用简单规则提取。
5.3 可能的输出形式
| 输出 | 描述 | 确定程度 |
|---|---|---|
| 完整里程碑轨迹 | 一个里程碑全部 turns,训练长程能力 | 基本确定 |
| 卡点片段 | 从卡住到解决的 10-20 轮 | 基本确定 |
| 按阶段切割 | 探索→规划→编码→debug 各自独立 | 待验证 |
| 更复杂的提炼 | 取决于数据实际长什么样 | 完全待定 |
5.4 什么时候做
Phase 1 拿到第一批轨迹后,先人工看 5-10 条,理解数据的实际特征,再设计具体的提炼规则。
不排除”整条里程碑轨迹直接拿去训练效果就很好,不需要精细切割”的可能性。也不排除需要更复杂的分析。让数据说话。
六、为什么这个架构更好
6.1 vs v1:解耦带来的优势
| 维度 | v1(紧耦合) | v2(三阶段解耦) |
|---|---|---|
| 最小验证 | 需要多角色全部就绪才能跑 | Stage 2 单独跑就能产出轨迹 |
| 失败模式 | 某环节失败 → 全线停 | 某个里程碑 STUCK → 跳过,不影响其他 |
| 优化方向 | 不确定(没有数据作为反馈) | 明确(轨迹数据告诉你哪里该改进) |
| 任务质量 | 依赖 PM 的合成能力(不确定) | 依赖真实轨迹的分析(可验证) |
| 可复现性 | PM 每次合成可能不同 | 里程碑固定,轨迹可重跑 |
6.2 vs CoderForge/SWE-smith:差异化价值
| 维度 | CoderForge | SWE-smith | HarnessForge v2 |
|---|---|---|---|
| 任务类型 | Bug fix | Bug 注入 fix | Feature + Refactor + Bug fix |
| 轨迹长度 | 单任务(~20 turns) | 单任务(~15 turns) | 多里程碑连续(~50 turns/里程碑) |
| 交互模式 | 无 | 无 | 有 Mentor 提示交互 |
| 覆盖语言 | 主要 Python | 仅 Python | Python/TS/Go/Rust |
| 规模弹性 | 固定数据集 | 固定数据集 | Repo × Release × 策略,可持续扩展 |
6.3 核心优势总结
- 轨迹优先 = 数据驱动:不预设什么是”好任务”,让实际的 Dev 行为告诉你
- 三阶段独立可控:任何一个阶段都可以单独迭代,不互相阻塞
- Dev 用内部模型:轨迹直接反映目标模型的能力边界,而非外部模型的能力
- Mentor 交互是独特资产:唯一包含”从人类反馈中调整”模式的开源数据集
- Task 质量后置保证:先看到数据,再决定怎么用,而不是先猜测、再验证
七、实施路线
Phase 1:最小验证(3 天)
选 1 个 repo(Django),3 个里程碑
1. 准备 Django 5.0 → 5.1 的 3 个 feature 里程碑
2. Docker 环境 checkout v5.0
3. 用 HY3.0 作为 Dev,手动充当 Mentor
4. 记录完整轨迹(Claude Code 自带 turn log)
5. 人工分析轨迹,验证:
- 轨迹中是否有可识别的卡点、方向调整、渐进成功?
- 能否从轨迹中提炼出有意义的 task?
- Mentor 提示是否触发了真实的行为变化?
成功标准:3 个里程碑的轨迹中,至少提炼出 5 个有训练价值的 task。
Phase 2:自动化管线(2 周)
1. 编写自动化脚本:
- milestone_runner.py: 按里程碑顺序驱动 Dev
- mentor_service.py: 监控 Dev 状态,自动触发提示
- recorder.py: 全量轨迹记录
2. 在 5 个 repo 上跑,产出 ~70 个里程碑轨迹
3. 编写 Stage 3 的分析脚本:
- stuck_detector.py: 卡点识别
- dpo_extractor.py: DPO 对提取
- task_slicer.py: 片段切割
4. 产出第一批 verified_tasks
Phase 3:规模化 + RL 验证(3 周)
1. 15 个 repo 全量执行
2. 多模型 Dev(HY3.0 为主 + 对照模型用于消融)
3. Stage 3 全量分析 → 产出 verified tasks(规模随 repo 池和质量标准伸缩)
4. 消融实验:
- 长程轨迹 vs 单任务轨迹(证明长程的价值)
- 带 Mentor 交互 vs 无交互(证明交互的价值)
- HarnessForge v2 vs CoderForge(头对头)
5. RL 训练 Qwen3-32B,SWE-bench 评测
八、诚实的风险评估
| 风险 | 严重程度 | 缓解 |
|---|---|---|
| Dev 在复杂里程碑上完全卡死,轨迹全是无效探索 | 高 | Phase 1 就能发现;用更强模型(Opus)做 Dev 备选 |
| 长程轨迹在 RL 训练中不如短任务有效 | 中 | 消融实验验证;如果确实不行,至少 Stage 3 的片段切割还能产出短任务 |
| 上下文窗口溢出,Dev 在后期里程碑丧失前期记忆 | 中 | 每个里程碑重置上下文 + 保留摘要;已在 4.3 设计中解决 |
| 里程碑之间的依赖太紧,某个失败导致后续全崩 | 低 | STUCK 时用 verify_commit 强制推进,保证后续里程碑有干净基础 |
| Mentor 提示质量差,Dev 收到提示后仍然没有方向变化 | 中 | Mentor 用 Opus + 拥有 ground truth;Phase 1 验证提示有效性 |
| 预训练数据污染——Dev “记住了答案”而不是在探索 | 高 | 见下方专节讨论 |
八点五、核心风险:预训练数据污染
这是整个方案最根本的风险,值得单独拿出来讨论。
问题的本质
我们选的高 star 知名 repo(Django、Flask、Next.js……),恰好是预训练数据中覆盖最充分的那批。HY3.0 的训练集里大概率包含了这些 repo 的每一个 commit、每一条 PR、每一段 discussion。
当我们给 HY3.0 一个里程碑任务——“为 Django 5.1 实现 GeneratedField”——它可能不是在”探索”,而是在”回忆”。产出的轨迹看起来像长程探索,实际上模型在前几轮就知道答案了,后面的”思考”和”搜索”只是在走过场。
这种轨迹拿去做 RL,强化的是记忆而不是推理能力。模型在 contaminated 任务上分数虚高,但换一个真正 unseen 的问题就暴露真实水平。
但也不用过度悲观
预训练学到的是”知识”——代码语法、API 用法、常见模式。RL 要训练的是”行为”——面对不确定性时怎么探索、卡住了怎么调整、什么时候该放弃当前方向。 这两者不完全重叠。
几个缓解因素:
1. 粗粒度里程碑的组合性能部分对冲。 单个 PR 的 patch 可能被”记住”了,但把 5 个 feature 组合成一个里程碑,模型需要在同一个 codebase 上同时处理多个互相影响的修改——这种组合大概率不在预训练数据中。
2. Dev 的实现和 ground truth 一定会有偏差。 即使模型”知道”最终答案,实际执行路径也会不同——用了不同的中间变量名、不同的 debug 策略、不同的文件修改顺序。这些执行层面的差异是预训练不覆盖的。
3. 卡点和提示响应是天然 unseen 的。 “HY3.0 在 Django QuerySet 重构中第 15 轮卡住了,收到’看看 compiler.py’的提示后调整方向”——这个特定模型在特定上下文中的行为序列不可能出现在预训练数据中。
4. 最有价值的信号可能恰好在”记住了一部分但没记住全部”的区间。 完全 unseen → 太难(纯失败轨迹)。完全 seen → 太简单(纯回忆)。中间地带——模型知道大方向但不记得具体怎么改——产出的探索行为最真实、最有训练价值。
具体缓解措施
1. Repo 筛选阶段:混入低污染 repo。
不只选高 star 知名项目,刻意混入:
| 类型 | 例子 | 污染风险 |
|---|---|---|
| 2025 年底之后创建的新 repo | 处于 pretraining cutoff 之后 | 低 |
| 小众但高质量的 repo(star 500-2000) | 代码好但不在”热门”之列 | 中低 |
| 内部项目或企业 fork | 如果有合规的话 | 极低 |
| 知名 repo 的最新 release | 接近 cutoff 边界 | 中 |
Phase 1 建议选一个高污染 repo(Django)和一个低污染 repo 做对照。
2. Phase 1 直接测量 contamination。
方法很简单:给 HY3.0 一个里程碑任务,不给任何提示(甚至不给 issue 信息),只告诉它 release note 里的 feature 描述。观察:
- 如果它在前 3 轮内就准确定位到要改哪些文件 → 高度疑似记忆
- 如果它需要 10+ 轮的搜索和试探才找到方向 → 探索行为较真实
- 如果它完全找不到方向 → 任务难度超出能力
统计”高度疑似记忆”的比例。如果超过 50%,需要调整 repo 选择或任务设计。
3. Stage 3 增加 contamination 过滤。
在轨迹提炼阶段,对每条轨迹做简单检测:
- Dev 从未走错方向、从未需要提示、从未回退修改 → 标记为”疑似记忆”,降低权重或排除
- Dev 有真实的探索-试错-调整过程 → 标记为”高价值”,优先使用
4. RL 训练阶段:held-out 验证。
留出一组 unseen repo(不在任何训练数据中的新项目),作为 RL 训练效果的真实测量。如果模型在 seen repo 的 task 上提升 10%,但在 unseen repo 的 task 上只提升 2%,说明 RL 训练确实强化了记忆而不是能力。
坦率的判断
这个风险是真实的,但不是致命的。理由:
- RL 训练的核心目标是行为策略(怎么探索、怎么调整),不是知识(Django 的 API 怎么用)。即使 repo 见过,行为层面的训练信号仍然存在
- 粗粒度里程碑的组合性、Dev 的执行偏差、卡点和提示响应——这些都是天然的 unseen 信号
- 通过 repo 选择策略、Phase 1 的 contamination 测量、Stage 3 的过滤,可以量化并控制风险
最坏情况:即使 contamination 严重,Stage 3 的轨迹分析仍然能识别出真实的探索片段。只要不是 100% 的轨迹都是”纯回忆”,就能从中提炼出有效的训练数据——只是量会少一些。
九、从 v1 到 v2 的核心教训
不要在没有数据的时候做优化。
v1 设计了精巧的五角色系统来”合成高质量任务”,但这些精巧的设计全都建立在未经验证的假设上。当我们退后一步,问”最简单的方式是什么?“,答案是:让 Agent 直接去开发,把过程录下来,之后再分析。
这和大模型训练的一个核心经验一致:数据采集和数据筛选应该解耦。 在预训练中,我们先大规模爬取 web 数据,再用质量分类器筛选。在后训练中,我们先大量标注,再用 reward model 筛选。没有人试图在爬取阶段就”只爬高质量数据”——那是在采集阶段做了筛选阶段的事。
v1 犯了同样的错误:在”轨迹采集”阶段就试图做”任务设计”的事。
v2 的修正很简单:先采集,再筛选。让数据说话。
参考
- HarnessForge v1 — 原始五角色方案(本文为其 v2 迭代)
- CoderForge-Preview, Together AI, 2026.02 — HuggingFace — 258K 轨迹数据集,SWE-bench 23%→59.4%
- Nebius SWE-agent-trajectories — HuggingFace — 80K 轨迹,40.6% SWE-bench
- Philipp Schmid, The importance of Agent Harness in 2026 — “The Harness is the Dataset”
- OpenHarness — GitHub — Agent Harness 开源框架
- SWE-bench — arXiv:2310.06770
- SWE-smith — NeurIPS 2025 — Bug 注入合成
- DeepSWE — together.ai/blog/deepswe — 纯 RL 训练 Coding Agent
- Harness Engineering 深度解析 — Tuntang 站内
- The Harness is the Dataset — Tuntang 站内