HarnessForge v2 研发实施方案
基于「轨迹优先」proposal 的工程落地方案。三阶段:Repo 筛选与里程碑规划 → CVM 持续开发与轨迹记录 → 轨迹切片与 Task 提炼。面向研发团队的完整技术文档。
HarnessForge v2 研发实施方案
文档定位:这是 HarnessForge v2 Proposal 的工程实施版。Proposal 回答「做什么、为什么」,本文档回答「怎么做、谁来做、用什么跑」。面向有研发背景的客户,可直接据此排期和执行。
〇、方案总览
核心思路
Stage 1 Stage 2 Stage 3
Repo 筛选 CVM 持续开发 轨迹提炼
+ 里程碑规划 + 全量轨迹记录 + Task 输出
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
输入: GitHub 输入: repo + milestones 输入: raw trajectories
输出: milestones 输出: ~500MB JSONL 输出: verified tasks
+ DPO 对 + SFT 数据
人力: 1 人·2d 人力: 0(自动运行) 人力: 1 人·3d
机器: 本地 机器: 1 台 CVM 机器: 本地/CVM
与 Proposal 的差异
| 维度 | Proposal 设计 | 本方案调整 | 原因 |
|---|---|---|---|
| Dev 模型 | HY3.0(内部模型) | 可插拔:支持 HY3.0 / Qwen3-Coder / Claude Sonnet | Phase 1 先用可控的模型验证管线,确认跑通后再切内部模型 |
| 运行环境 | Docker 集群 | 单台 CVM | 降低基础设施复杂度,Phase 1 验证不需要多机 |
| Agent 框架 | OpenHarness / Claude Code CLI | SWE-agent 魔改 + 自研 Recorder | SWE-agent 轨迹格式成熟、社区验证充分,改造成本低于 OpenHarness(API 不稳定,12 天 6 版) |
| Mentor 模型 | Opus-4.6 | 规则引擎为主 + LLM 兜底 | Mentor 80% 的工作是释放 repo 已有信息,不需要 LLM;只在需要”翻译”提示时调用 |
一、Stage 1:Repo 筛选与里程碑规划
1.1 目标
为 Stage 2 准备「repo + 里程碑序列 + 环境配置」三元组。每个三元组是一个可独立执行的开发任务包。
1.2 Repo 筛选标准
| 维度 | 硬性标准 | 检查方式 |
|---|---|---|
| CI | 有 GitHub Actions 或 CircleCI | ls .github/workflows/ |
| 测试 | ≥50 个测试用例 | pytest --co -q | wc -l |
| 活跃度 | 近 6 月 ≥100 commits | git log --since="6 months ago" --oneline | wc -l |
| 代码量 | 10K–500K 行 | cloc --json |
| Release | ≥3 个语义化版本 tag | git tag -l "v*" | wc -l |
| 依赖锁定 | 有 lock 文件 | ls requirements.txt / package-lock.json / go.sum |
| 环境可复现 | Docker build + 测试通过 | 实际构建验证 |
1.3 首批 Repo(Phase 1:5 个)
Phase 1 只选 5 个 repo,覆盖两种语言、两种污染风险等级:
| Repo | 语言 | Stars | 污染风险 | 里程碑/年估计 | 选择理由 |
|---|---|---|---|---|---|
| django/django | Python | 82K | 高 | ~15 | Release notes 极规范,里程碑素材最丰富 |
| pydantic/pydantic | Python | 22K | 中 | ~12 | v1→v2 重构提供了大量 feature 实现任务 |
| fastapi/fastapi | Python | 80K | 高 | ~20 | 频繁 minor release,适合细粒度里程碑 |
| drizzle-team/drizzle-orm | TypeScript | 26K | 低 | ~15 | 2023 年创建,预训练污染风险较低 |
| vitest-dev/vitest | TypeScript | 14K | 低 | ~12 | 测试框架,代码结构清晰,CI 完善 |
污染对照设计:高污染 repo(Django/FastAPI)的轨迹质量会和低污染 repo(Drizzle/Vitest)做对比分析。如果高污染 repo 的 Dev 在前 3 轮就精准定位文件(疑似记忆),而低污染 repo 需要 10+ 轮探索,说明污染信号存在且可量化。
1.4 里程碑规划
里程碑粒度原则
里程碑粒度光谱
┌──────────────────────────────────────────────┐
│ 太细 合适 太粗 │
│ │
│ 单 commit 完整 feature 整个大版本 │
│ 2-3 轮搞定 15-50 轮交互 卡死/打转 │
│ 无训练价值 高价值轨迹 无效探索 │
└──────────────────────────────────────────────┘
经验法则:一个好的里程碑 = 一个完整 feature 的实现,让 Dev 需要 15–50 轮交互才能完成。
- < 10 轮:切细了,退化成 SWE-bench 单 PR 模式
- > 80 轮:切粗了,Dev 大概率在无效打转
里程碑提取流程
# 对每个 repo 执行:
# 1. 列出 release 历史
gh release list --repo $REPO --limit 20
# 2. 获取每个 release 的详细 changelog
gh release view $TAG --repo $REPO
# 3. 用 LLM 从 changelog 中提取里程碑
# 输入:release notes 全文 + 相邻版本 diff stat
# 输出:结构化 milestones.yaml
# 4. 为每个里程碑定位 verify_commit
# 通过 git log 匹配 feature 关键词
git log $BASE_TAG..$TARGET_TAG --oneline --grep="feature关键词"
# 5. 环境验证
# 在 Docker 中 checkout base_tag → 安装依赖 → 运行测试
里程碑输出格式
# milestones/django.yaml
repo: django/django
language: python
base_version: "5.0"
target_version: "5.2"
environment:
dockerfile: |
FROM python:3.12-slim
WORKDIR /workspace
RUN apt-get update && apt-get install -y git ripgrep && rm -rf /var/lib/apt/lists/*
RUN git clone --depth=300 https://github.com/django/django.git .
RUN git checkout v5.0
RUN pip install -e ".[dev]"
test_cmd: "python -m pytest tests/ -x -q --tb=short"
milestones:
- id: "M1"
source: "Django 5.1 Release Notes"
feature: "LoginRequiredMiddleware"
description: |
添加一个全局中间件,默认要求所有视图登录才能访问。
需要提供 @login_not_required 装饰器豁免公开页面。
admin 视图需要自动适配。
verify_commit: "abc123"
verify_tests: "python -m pytest tests/auth_tests/ tests/middleware/ -x -q"
estimated_difficulty: 3
estimated_turns: "20-35"
# 后备提示素材(来自 repo,不需要 LLM 合成)
hint_sources:
issue_titles:
- "Add LoginRequiredMiddleware (#34523)"
issue_body: "path/to/issue_34523.md" # 预抓取
pr_title: "Fixed #34523 -- Added LoginRequiredMiddleware"
pr_files: ["django/contrib/auth/middleware.py", "django/views/decorators/login.py", ...]
pr_diff_key_hunks: "path/to/pr_diff_34523.patch" # 预抓取
- id: "M2"
source: "Django 5.1 Release Notes"
feature: "GeneratedField"
# ...
- id: "M3"
source: "Django 5.2 Release Notes"
feature: "Composite Primary Key"
# ...
1.5 交付物
| 文件 | 说明 |
|---|---|
repos/selected-repos.yaml | 筛选通过的 repo 列表 + 环境信息 |
milestones/{repo}.yaml | 每个 repo 的里程碑序列(含后备提示素材) |
dockerfiles/{repo}/Dockerfile | 已验证可构建的 Docker 镜像 |
hint_sources/{repo}/{milestone}/ | 预抓取的 issue/PR 信息(JSON/Markdown) |
1.6 工期与人力
| 任务 | 耗时 | 人力 | 说明 |
|---|---|---|---|
| Repo 筛选 + 环境验证 | 0.5 天 | 1 人 | 脚本 + 手动确认 |
| 里程碑提取 | 1 天 | 1 人 | LLM 辅助 + 人工校验 |
| 后备提示素材抓取 | 0.5 天 | 脚本 | gh api 批量抓取 |
| 合计 | 2 天 | 1 人 |
二、Stage 2:CVM 持续开发与轨迹记录
2.1 目标
在 CVM 上让 Dev Agent 按里程碑序列持续开发,全程记录完整轨迹。
2.2 CVM 环境架构
┌─────────────────────────────────────────────────────────┐
│ CVM (单台服务器) │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 编排层 (Python) │ │
│ │ │ │
│ │ milestone_runner.py ←→ mentor_service.py │ │
│ │ │ │ │ │
│ │ ▼ │ │ │
│ │ recorder.py │ │ │
│ │ (JSONL 写入) │ │ │
│ └────────┬───────────────────────┘ │
│ │ │
│ ┌────────▼──────────────────────────────────────┐ │
│ │ Docker 沙箱 (每个 repo 一个容器) │ │
│ │ │ │
│ │ /workspace/ ← repo 代码 │ │
│ │ Dev Agent (SWE-agent / 自研) │ │
│ │ 网络: none (纯离线) │ │
│ │ 资源: 4 CPU, 8GB RAM │ │
│ └────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────┐ │
│ │ 轨迹存储 │ │
│ │ /data/trajectories/ │ │
│ │ {repo}/{milestone}/ │ │
│ │ trajectory.jsonl │ │
│ │ mentor_log.json │ │
│ │ final_diff.patch │ │
│ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
2.3 Dev Agent 框架选型
经过技术评估,推荐以下方案(优先级从高到低):
方案 A:SWE-agent 魔改(推荐)
| 优势 | 说明 |
|---|---|
| 轨迹格式成熟 | trajectory.jsonl 格式已被 CoderForge / SWE-smith / Nebius 等项目采用,生态兼容好 |
| SWE-bench 生态 | 直接复用 SWE-bench 的 Docker 构建管线和测试验证框架 |
| 社区验证 | 40.6% SWE-bench Verified(mini SWE-agent),可作为 baseline |
| 工具集完善 | 文件读写、搜索、bash 执行、git 操作一应俱全 |
需要魔改的部分:
# 1. 里程碑驱动(替换原有的单 issue 模式)
class MilestoneRunner:
"""按里程碑序列驱动 Dev,而非逐个 issue"""
def run_milestone_chain(self, milestones: list[Milestone]):
for ms in milestones:
# 不重置文件系统——前序代码是后序的上下文
result = self.run_single_milestone(ms)
if result.status == "STUCK":
# 用 verify_commit 强制推进,保证后续里程碑有干净基础
self.force_advance(ms.verify_commit)
# 2. Mentor 提示注入接口
class MentorHook:
"""在 SWE-agent 的 action loop 中插入 Mentor 检查点"""
def after_action(self, action, observation, state):
hint = self.mentor.should_release_hint(state)
if hint:
# 将提示注入 Dev 的下一轮上下文
return self.format_hint_message(hint)
return None
# 3. 上下文管理
class ContextManager:
"""里程碑间的上下文衔接"""
def on_milestone_start(self, milestone, prev_summaries):
# 重置对话上下文,但保留:
# - 当前代码状态(文件系统不变)
# - 前几个里程碑的一句话总结
# - 之前遇到的关键错误和解法摘要
pass
方案 B:OpenHarness(备选)
优势是事件级轨迹粒度和多模型原生支持。但 API 不稳定(12 天 6 版),如果 SWE-agent 方案遇到阻碍,切换到 OpenHarness。
方案 C:Claude Code CLI(轻量 Fallback)
最简实现:claude -p + Python 编排。轨迹粒度是轮级(每轮一个 JSON),不如方案 A/B 精细,但实现最快。作为 Phase 1 PoC 的保底方案。
2.4 五角色设计
Stage 2 有 5 个”角色”,但只有 Dev 和 Mentor 需要 LLM,其余是脚本或规则引擎。
┌───────────────────────────────────────────────────┐
│ Stage 2 执行环境 │
│ │
│ ┌─────────┐ 里程碑描述 ┌──────────┐ │
│ │Navigator│ ───────────→ │ Dev │ │
│ │(规则引擎)│ │ (LLM) │ │
│ └─────────┘ └─────┬────┘ │
│ │ │
│ 卡住时│请求帮助 │
│ ▼ │
│ ┌──────────┐ │
│ │ Mentor │ │
│ │ (规则 │ │
│ │ +LLM) │ │
│ └──────────┘ │
│ │
│ ┌─────────┐ 测试结果 ┌──────────┐ │
│ │Verifier │ ←────────── │Recorder │ │
│ │(脚本) │ │(日志系统) │ │
│ └─────────┘ └──────────┘ │
└───────────────────────────────────────────────────┘
| 角色 | 实现 | LLM | 职责 |
|---|---|---|---|
| Navigator | Python 脚本 | ❌ | 按序下发里程碑描述和验收标准 |
| Dev | SWE-agent + 目标模型 | ✅ | 核心执行者——阅读代码、编写代码、运行测试 |
| Mentor | 规则引擎 + LLM 兜底 | ⚠️ 可选 | Dev 卡住时按规则释放 repo 已有信息 |
| Verifier | Shell 脚本 | ❌ | 里程碑完成时运行验收测试,返回 pass/fail |
| Recorder | Python 日志 | ❌ | 全程记录 Dev 的每一步操作 |
2.5 Mentor 渐进提示机制
Mentor 的核心逻辑是按规则释放 repo 中已有的信息,不需要 LLM 动态生成提示。
提示层级
| 层级 | 内容来源 | 触发条件 | 信息量 |
|---|---|---|---|
| L0 | issue 标题 | Dev 初始就可见 | 最模糊 |
| L1 | issue 描述 + 复现步骤 | 连续 3 次相同错误 | 方向级 |
| L2 | PR 标题 + 描述 + review 讨论 | L1 后 5 轮无进展 | 模块级 |
| L3 | PR 涉及的 file list | L2 后 5 轮无进展 | 文件级 |
| L4 | PR diff 关键片段 | L3 后 5 轮无进展(最后手段) | 代码级 |
触发规则(伪代码)
class MentorService:
def __init__(self, milestone: Milestone):
self.hint_level = 0
self.hint_sources = milestone.hint_sources # Stage 1 预抓取
self.last_hint_turn = 0
self.COOLDOWN = 8 # 前 8 轮不介入
def should_release_hint(self, state: DevState) -> Optional[Hint]:
if state.turn < self.COOLDOWN:
return None
turns_since = state.turn - self.last_hint_turn if self.last_hint_turn else 999
# L0 → L1: 连续 3 次相同失败
if self.hint_level == 0 and state.consecutive_same_failures >= 3:
return self._release(1)
# L1 → L2: 释放后 5 轮无进展
if self.hint_level == 1 and turns_since >= 5 and not state.has_progress:
return self._release(2)
# L2 → L3: 释放后 5 轮无进展
if self.hint_level == 2 and turns_since >= 5 and not state.has_progress:
return self._release(3)
# L3 → L4: 释放后 5 轮无进展(最后手段)
if self.hint_level == 3 and turns_since >= 5 and not state.has_progress:
return self._release(4)
# Dev 主动求助
if state.dev_stuck_signal:
return self._release(self.hint_level + 1)
return None
def _release(self, level: int) -> Hint:
self.hint_level = level
self.last_hint_turn = state.turn
content = self.hint_sources.get_level(level)
return Hint(level=level, content=content, source="repo")
关键设计:Mentor 80% 的场景是纯规则释放——把 Stage 1 预抓取的 issue/PR 信息按层级发给 Dev。只有在 L4 释放后 Dev 仍然卡住(极少数情况),才调用 LLM 生成定制化指导。
2.6 轨迹记录格式
全量记录,不做任何过滤(过滤是 Stage 3 的事)。
{
"repo": "django/django",
"milestone_id": "M1",
"milestone_desc": "新增 LoginRequiredMiddleware",
"turn_id": 1,
"timestamp": 1712956800,
"role": "dev",
"action": {
"type": "search",
"tool": "ripgrep",
"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,
"cumulative_edits": 0,
"cumulative_test_runs": 0,
"direction_change": false,
"token_usage": { "input": 2450, "output": 380 }
}
关键字段:
| 字段 | 说明 | Stage 3 价值 |
|---|---|---|
mentor_hint | 本轮是否收到提示及内容 | DPO 对构造的分割点 |
direction_change | Dev 是否改变了整体方向 | ”从反馈中调整”的训练信号 |
test_status | 测试 pass/fail/error 详情 | 卡点识别 |
token_usage | 输入输出 token 数 | 成本核算 + 效率分析 |
2.7 里程碑执行流程
async def run_repo(repo_config: RepoConfig):
"""对一个 repo 执行完整的里程碑链"""
sandbox = DockerSandbox(repo_config)
await sandbox.setup() # Docker build + checkout base_version
prev_summaries = []
for milestone in repo_config.milestones:
print(f"[Navigator] 开始里程碑 {milestone.id}: {milestone.feature}")
# 初始化角色
mentor = MentorService(milestone)
recorder = TrajectoryRecorder(repo_config.repo, milestone.id)
verifier = TestVerifier(sandbox, milestone.verify_tests)
# Dev 上下文:里程碑描述 + 前序摘要
dev_context = build_dev_context(milestone, prev_summaries)
# 执行循环
status = "timeout"
for turn in range(100): # 最多 100 轮
# Dev 执行一步
action, observation = await dev_agent.step(dev_context)
recorder.record(turn, action, observation)
# Mentor 检查是否需要提示
state = build_dev_state(recorder)
hint = mentor.should_release_hint(state)
if hint:
recorder.record_hint(turn, hint)
dev_context.inject_hint(hint)
# 检查是否运行了测试
if is_test_execution(action):
test_result = verifier.parse_result(observation)
recorder.record_test(turn, test_result)
# Dev 声明完成
if "TASK_COMPLETE" in observation:
final_test = await verifier.run_full()
if final_test.all_pass:
status = "success"
break
else:
dev_context.inject_test_failure(final_test)
# 里程碑结束处理
if status == "timeout":
# STUCK:用 verify_commit 强制推进
await sandbox.force_advance(milestone.verify_commit)
status = "stuck"
# 保存轨迹和 diff
recorder.save()
await sandbox.export_diff(f"trajectories/{repo}/{milestone.id}/final_diff.patch")
# 生成摘要供下一个里程碑使用
summary = generate_milestone_summary(recorder)
prev_summaries.append(summary)
print(f"[Navigator] 里程碑 {milestone.id}: {status}, "
f"{recorder.total_turns} turns, max_hint L{mentor.hint_level}")
2.8 STUCK 处理策略
里程碑 STUCK 是正常情况(预期 20-30% 的里程碑会 STUCK),处理方式:
┌───────────────────────────────────────────┐
│ 里程碑 STUCK 处理流程 │
│ │
│ Dev 超过 100 轮仍未通过 │
│ │ │
│ ▼ │
│ [记录 STUCK 状态和最后轨迹] │
│ │ │
│ ▼ │
│ [用 verify_commit 的代码替换工作目录] │
│ ← 保证后续里程碑有干净基础 │
│ │ │
│ ▼ │
│ [继续下一个里程碑] │
│ │
│ 注意:STUCK 的轨迹不是废品! │
│ 它包含 Dev 的全部探索过程, │
│ Stage 3 可以从中提取"做错了什么"的信号 │
└───────────────────────────────────────────┘
2.9 产出估算
| 参数 | Phase 1 (5 repos) | Phase 2 (15 repos) |
|---|---|---|
| Repo 数 | 5 | 15 |
| 里程碑/repo | ~12 | ~14 |
| 总里程碑 | ~60 | ~210 |
| Dev turns/里程碑 | ~50 | ~50 |
| 总 turns | ~3,000 | ~10,500 |
| 原始轨迹体积 | ~150MB | ~500MB–1GB |
| 运行时间 | ~3 天 | ~2 周 |
2.10 CVM 配置要求
| 资源 | 最低要求 | 推荐配置 | 说明 |
|---|---|---|---|
| CPU | 8 核 | 16 核 | Docker 沙箱和编排器并行 |
| 内存 | 16 GB | 32 GB | Docker 容器 8GB + 编排器 + 模型推理缓冲 |
| 磁盘 | 100 GB SSD | 200 GB SSD | Docker images + 轨迹存储 |
| GPU | 不需要(如用 API) | 1× A10(如用本地模型) | 本地部署 Qwen3-32B 需要 GPU |
| 网络 | 需要(API 调用) | — | Docker 沙箱内部禁网 |
如果 Dev 用内部模型(HY3.0):需要内网可达的推理服务端点,CVM 通过 API 调用,Docker 沙箱仍然禁网(Dev 不能直接上网搜索)。
三、Stage 3:轨迹切片与 Task 提炼
3.1 目标
从 Stage 2 的原始轨迹中提炼出可直接用于训练的数据。
3.2 设计原则
在没有数据的时候不做过度设计。 Stage 3 的具体策略应该在拿到第一批轨迹后根据数据特征来确定。以下是已知可行的分析维度和初步方案,会在 Phase 1 数据到手后调整。
3.3 轨迹质量信号
| 信号 | 识别方式 | 训练价值 |
|---|---|---|
| 卡点 | 连续 N 次 edit→test→fail,错误类型不变 | 每个卡点天然就是一个 hard task |
| 方向调整 | 提示前后搜索/编辑的文件发生变化 | ”收到反馈后调整策略”的训练数据 |
| 渐进成功 | 测试通过数从 0 → N 逐步增加 | 问题分解和逐步推进能力 |
| 无效探索 | Dev 花了多轮走一个方向,最终回退 | 负样本——什么不该做 |
| 高效路径 | < 15 轮完成,无需提示 | 正样本——什么该做 |
| 疑似记忆 | 前 3 轮直接定位正确文件,无探索 | 污染标记,降权或排除 |
3.4 数据提炼管线
原始轨迹 (JSONL)
│
├──→ [卡点检测器] → 卡点片段(从卡住到解决的 10-20 轮)
│ ↓
│ 有 Mentor 提示的片段 → DPO 对素材
│ 无 Mentor 提示的片段 → SFT hard 数据
│
├──→ [完整轨迹] → 里程碑级 SFT 数据(完整 turns)
│
├──→ [污染检测器] → 疑似记忆的轨迹标记
│
└──→ [统计报告] → 每个 repo/milestone 的执行画像
3.4.1 卡点切片
def extract_stuck_segments(trajectory: list[Turn]) -> list[Segment]:
"""从轨迹中提取"卡住→解决"的片段"""
segments = []
i = 0
while i < len(trajectory):
if is_stuck_start(trajectory, i):
# 找到卡点开始(连续 3+ 次相同错误)
start = max(0, i - 2) # 包含卡住前的 2 轮上下文
# 找到卡点结束(错误模式变化或测试通过)
end = find_stuck_end(trajectory, i)
segment = Segment(
turns=trajectory[start:end],
stuck_at=i,
resolved_at=end,
hint_received=any(t.mentor_hint for t in trajectory[start:end]),
hint_level=max_hint_level(trajectory[start:end]),
)
segments.append(segment)
i = end
else:
i += 1
return segments
3.4.2 DPO 对构造
同一个里程碑,不同提示级别的轨迹自然形成 DPO 对:
Chosen (更高效):
Dev 在 L1 提示后 5 轮内找到方向 → 完成
Rejected (更低效):
Dev 没有提示,在错误方向上探索了 15 轮 → 最终需要 L2 提示
━━━ 或者 ━━━
Chosen: 同一里程碑,HY3.0 的最优轨迹(最少 turns、最少提示)
Rejected: 同一里程碑,HY3.0 的最差轨迹(最多 turns、最多提示)
如果同一个里程碑用不同模型跑(Phase 2+),还可以构造跨模型的 DPO 对。
3.4.3 污染检测
def contamination_score(trajectory: list[Turn], milestone: Milestone) -> float:
"""计算轨迹的污染嫌疑分数"""
# 信号 1: Dev 前 3 轮是否直接定位到正确文件
correct_files = set(milestone.hint_sources.pr_files)
early_files = set()
for turn in trajectory[:3]:
if turn.action.type in ("read_file", "edit_file"):
early_files.add(turn.action.path)
early_hit_rate = len(early_files & correct_files) / len(correct_files)
# 信号 2: Dev 是否从未走错方向
direction_changes = sum(1 for t in trajectory if t.direction_change)
# 信号 3: Dev 是否不需要任何提示
hints_needed = max(t.mentor_hint.level for t in trajectory if t.mentor_hint) \
if any(t.mentor_hint for t in trajectory) else 0
# 综合评分 (0-1, 越高越可疑)
score = (early_hit_rate * 0.5 +
(1 if direction_changes == 0 else 0) * 0.3 +
(1 if hints_needed == 0 else 0) * 0.2)
return score
3.5 输出格式
Verified Task 卡片
task_id: "django-M1-login-middleware"
repo: "django/django"
language: "python"
base_commit: "abc123"
# 任务描述(里程碑原始描述)
description: |
添加一个全局中间件,默认要求所有视图登录才能访问...
# 验收测试
test_cmd: "python -m pytest tests/auth_tests/ tests/middleware/ -x -q"
# 完整轨迹
trajectory_file: "trajectories/django/M1/trajectory.jsonl"
total_turns: 32
hints_received: ["L1"]
# 关键时刻
key_moments:
- { turn: 5, event: "first_test_run", result: "0/8 pass" }
- { turn: 15, event: "stuck", detail: "连续 3 次 admin 相关测试失败" }
- { turn: 15, event: "hint_received", level: "L1" }
- { turn: 17, event: "direction_change", detail: "从全局中间件转向 admin 适配" }
- { turn: 28, event: "near_completion", result: "7/8 pass" }
- { turn: 32, event: "all_pass" }
# 卡点切片
stuck_segments:
- { start: 12, end: 22, hint_level: "L1", resolution: "admin 视图豁免" }
# 污染评估
contamination_score: 0.35 # 中等(高 star repo,但有探索行为)
# RL 元数据
difficulty: 4
rl_value: "high"
training_formats:
sft: "trajectories/django/M1/sft_full.jsonl"
dpo_chosen: "trajectories/django/M1/dpo_chosen.jsonl"
dpo_rejected: "trajectories/django/M1/dpo_rejected.jsonl"
stuck_segment: "trajectories/django/M1/stuck_segment_0.jsonl"
3.6 Stage 3 工期
| 任务 | 耗时 | 人力 |
|---|---|---|
| 编写分析脚本 | 1 天 | 1 人 |
| 人工看 5-10 条轨迹,调整策略 | 0.5 天 | 1 人 |
| 全量分析 + 输出 | 1 天 | 脚本 |
| 质量抽检 | 0.5 天 | 1 人 |
| 合计 | 3 天 | 1 人 |
四、与业界方案全景对比
4.1 定位矩阵
任务复杂度
▲
│
Feature 实现 │ ┌──────────────┐
+ 重构 │ │ HarnessForge │
│ │ v2 │ ← 长程 + 交互 + 多类型
│ └──────┬───────┘
│ │
跨模块 │ ┌───────────────┘
Bug Fix │ │
│ │ ┌──────────────┐
│ │ │ CoderForge │
│ │ │ 258K 条 │
│ │ └──────────────┘
│ │
单文件 │ ┌──┴───────┐ ┌──────────┐ ┌────────┐
Bug Fix │ │SWE-smith │ │Nebius │ │SWE-bench│
│ │ 50K 条 │ │ 80K 条 │ │ 2.3K 条│
│ └──────────┘ └──────────┘ └────────┘
│
└──────────────────────────────────────→
无轨迹 单任务轨迹 长程连续轨迹
(patch) (~20 turns) (里程碑链 ~50 turns)
4.2 逐方案对比
| 维度 | SWE-bench | SWE-smith | CoderForge | Nebius | HarnessForge v2 |
|---|---|---|---|---|---|
| 任务来源 | GitHub Issue/PR | Bug 注入 | 多源汇集 | SWE-agent 跑 SWE-bench | Release 里程碑 |
| 任务类型 | Bug fix | Bug fix | Bug fix | Bug fix | Feature+重构+fix |
| 任务粒度 | 单 PR | 单 PR | 单 PR | 单 PR | 跨多 PR 的里程碑 |
| 轨迹 | ❌ | ✅ ~15t | ✅ ~20t | ✅ ~20t | ✅ ~50t/里程碑 |
| Dev-Mentor 交互 | ❌ | ❌ | ❌ | ❌ | ✅ 渐进提示 |
| 提示来源 | — | — | — | — | Repo issue/PR |
| DPO 数据 | 需外部构造 | ❌ | ❌ | ❌ | 自然产出 |
| 多语言 | Python | Python | Python | Python | Python/TS |
| 脚手架依赖 | — | ❌ | ✅ 锁定 | ✅ 锁定 | 无锁定 |
| SWE-bench 提升 | 基线 | — | +36pp | 40.6% | 待验证 |
4.3 HarnessForge v2 回应了 CoderForge 的三个局限
CoderForge-Preview 的 README 明确列出了三个局限:
| CoderForge 局限 | HarnessForge v2 应对 |
|---|---|
| Scaffold Specificity(脚手架锁定) | Dev 不锁定脚手架,使用标准 CLI 工具 |
| Task Scope Narrowness(偏 bug fix) | 里程碑覆盖 feature(60%)、重构(25%)、fix(15%) |
| Lack of User Interaction(无交互) | Mentor 渐进提示模拟用户-Agent 交互 |
4.4 与 OpenHarness 框架的关系
OpenHarness 研究 的核心发现:Agent Harness 的核心复杂度仅 ~2.3%(11.7K 行 Python 复刻了 Claude Code 98% 的工具能力)。这意味着 HarnessForge 不需要依赖重量级框架,SWE-agent 魔改或自研轻量编排器即可覆盖需求。
OpenHarness 的事件级轨迹粒度优于 Claude Code CLI 的轮级粒度,如果 API 趋于稳定(当前 v0.1.6),可以在 Phase 2 切换。
五、实施路线
Phase 1:最小验证(1 周)
目标:验证管线可行性 + 轨迹质量
Day 1-2: Stage 1
- 选 1 个 repo(Django),3 个里程碑
- 准备环境、里程碑描述、后备提示素材
Day 3-4: Stage 2
- CVM 环境搭建
- Dev Agent 跑 3 个里程碑(用 Claude Sonnet 或可用模型)
- 手动充当 Mentor(验证提示机制的有效性)
- 记录完整轨迹
Day 5: Stage 3
- 人工分析轨迹(5 条)
- 验证:轨迹中是否有可识别的卡点、方向调整?
- 验证:能否从轨迹中提炼出有意义的 task?
- 验证:Mentor 提示是否触发了真实的行为变化?
Day 6-7: 编写分析脚本 + 输出评估报告
Phase 1 成功标准:
- 3 个里程碑的轨迹中,至少提炼出 5 个有训练价值的 task
- 至少 1 个里程碑的 Dev 需要 L1+ 提示才突破
- 轨迹格式可被训练框架(verl-agent / ms-swift)读取
- 轨迹中有 可量化的污染信号(高/低污染 repo 的对比数据)
Phase 2:自动化管线(2 周)
1. 自动化脚本编写:
- milestone_runner.py: 按里程碑顺序驱动 Dev
- mentor_service.py: 监控 Dev 状态,自动触发提示
- recorder.py: 全量轨迹记录
- stuck_detector.py: 卡点识别
- dpo_extractor.py: DPO 对提取
2. 5 个 repo 全量执行 → ~60 个里程碑轨迹
3. Stage 3 全量分析 → 产出 verified tasks + DPO 对
4. 评估报告:
- 每个 repo 的里程碑完成率
- 平均轨迹长度和提示释放分布
- 污染检测结果
- 数据质量分级统计
Phase 3:规模化 + 训练验证(3 周)
1. 扩展到 15 个 repo
2. 多模型 Dev 执行:
- HY3.0 为主(目标模型,零 API 成本)
- Opus-4.6 为参考(构造跨模型 DPO 对)
3. Stage 3 全量分析 → verified tasks
4. 消融实验:
a. 长程轨迹 vs 单任务轨迹 → 证明长程的价值
b. 带 Mentor 交互 vs 无交互 → 证明交互的价值
c. HarnessForge v2 vs CoderForge → 头对头对比
d. 混合训练(HarnessForge + CoderForge)vs 单一数据
5. RL 训练 + SWE-bench 评测
六、风险与缓解
| 风险 | 严重度 | 概率 | 缓解 |
|---|---|---|---|
| Dev 在复杂里程碑上完全卡死 | 高 | 中 | Phase 1 就能发现;STUCK 处理保证后续里程碑可继续 |
| 预训练数据污染导致轨迹价值低 | 高 | 中 | 高/低污染 repo 对照;污染检测器过滤;低 star repo 补充 |
| SWE-agent 魔改工作量超预期 | 中 | 低 | 备选方案 B(OpenHarness)和方案 C(Claude Code CLI) |
| CVM 资源不足以支撑并行 | 低 | 低 | 里程碑串行执行即可,不需要并行 |
| 长程轨迹在 RL 训练中效果不如预期 | 中 | 中 | Stage 3 的片段切割仍能产出短任务数据,不会白跑 |
| 里程碑粒度不合适 | 中 | 中 | Phase 1 试 3 个不同粒度,数据反馈后调整 |
七、成本估算
Phase 1(1 周,1 个 repo)
| 项目 | 单价 | 数量 | 小计 |
|---|---|---|---|
| CVM 使用 | ~$5/天 | 5 天 | $25 |
| Dev API(Claude Sonnet) | ~$0.50/里程碑 | 3 | $1.5 |
| Mentor API(仅 LLM 兜底) | ~$0.10/里程碑 | 1 | $0.1 |
| 合计 | ~$27 |
如果 Dev 用内部模型(HY3.0),API 成本为零,仅 CVM 费用。
Phase 2(2 周,5 个 repo)
| 项目 | 单价 | 数量 | 小计 |
|---|---|---|---|
| CVM 使用 | ~$5/天 | 14 天 | $70 |
| Dev API(如用外部模型) | ~$0.50/里程碑 | 60 | $30 |
| Mentor API | ~$0.10/里程碑 | 15 | $1.5 |
| 合计 | ~$102 |
Phase 3(3 周,15 个 repo)
| 项目 | 单价 | 数量 | 小计 |
|---|---|---|---|
| CVM 使用 | ~$5/天 | 21 天 | $105 |
| Dev API(混合模型) | — | 210 里程碑 | ~$105 |
| 消融实验 RL 训练 | — | — | 内部 GPU |
| 合计(不含 GPU) | ~$210 |
八、关键决策点
以下决策需要在执行过程中确认:
| 决策 | 时间点 | 需要的信息 | 选项 |
|---|---|---|---|
| Dev 模型选择 | Phase 1 开始前 | 内部推理服务可达性 | A. HY3.0(零成本) B. Claude Sonnet($0.50/里程碑) C. Qwen3-Coder 本地部署 |
| Agent 框架 | Phase 1 Day 1 | 框架安装和基本测试 | A. SWE-agent 魔改 B. OpenHarness C. Claude Code CLI |
| CVM 配置 | Phase 1 Day 1 | 机器申请 | 16C32G + 200GB SSD |
| 代码仓库 | Phase 1 开始前 | — | A. tuntang 知识库内 tools/harnessforge/ B. 独立仓库 |
| 里程碑粒度调整 | Phase 1 Day 5 | 前 3 个里程碑的轨迹数据 | 根据实际 turns 分布调整粒度标准 |
| Phase 2 repo 选择 | Phase 1 完成后 | Phase 1 评估报告 | 基于污染对照和轨迹质量选定最终 5 个 repo |
参考
- HarnessForge v2 Proposal — 核心方案设计
- HarnessForge v1 — 原始五角色方案
- CoderForge-Preview 精读 — 258K 轨迹基线分析
- OpenHarness 深度研究 — 框架技术评估
- HarnessForge 开发文档 — 基于 OpenHarness 的实现方案
- HarnessForge v2 CLI 版 — Claude Code CLI 实现
- Harness Engineering — Harness 工程化范式
- The Harness is the Dataset — 轨迹数据飞轮理论
- SWE-agent, GitHub — Agent 框架参考
- CoderForge-Preview, HuggingFace — 258K 轨迹数据集