Skip to content

Repository files navigation

RepoFix Harness v0.1

一个窄而真实的 Agent Harness:给它一个 git 仓库 + 一个开发任务,它自动完成

定位代码 → 修改 → 跑 pytest → 根据失败修复 → 再验证 → 输出 diff + trace + report

为什么叫 Harness

模型只负责下一步决策;工具执行、权限控制、状态维护、上下文构建、执行预算、 Validation、重试和 Trace 全部由确定性的 Harness 代码管理。Agent 决策与执行控制 刻意分离——模型说"我修好了"不算数,pytest exit code 为 0 才算数。

                ┌── Context Manager(不整库投喂,只给快照)
                │
Task → Agent → Harness → Tool Runtime
                │             │
                │             ↓
                │         Repository
                │
                ├── State(step/retry/attempt/diff/observations)
                ├── Policy(命令 allowlist/denylist + 路径 jail)
                ├── Budget(max_steps / max_retries / max_files)
                ├── Trace(JSONL,每步一行)
                │
                ↓
             Validator(pytest 是唯一成功标准)
                │
         ┌──────┴──────┐
       PASS           FAIL
        ↓               ↓
      Done         FailureContext 注入上下文 → 定向重试

快速开始

uv sync
bash scripts/setup_fixture.sh   # 新克隆后执行一次:重建靶子仓库的 git 历史

# 端到端演示(自带靶子仓库,无需外部代码)
uv run python main.py --repo fixtures/demo-repo \
  --task "修复 PDF parser 在空页时报错的问题,保证测试套件全部通过"

# 不花 token 的离线演示(确定性脚本 agent)
uv run python main.py --repo fixtures/demo-repo --scripted \
  --task "修复 PDF parser 在空页时报错的问题,保证测试套件全部通过"

# 跑完后重置靶子仓库,可重复演示
bash scripts/reset_fixture.sh

产物在 runs/{run_id}/:

  • trace.jsonl — 每步一行:step / stage / tool / status / attempt / duration_ms / args
  • report.md — 任务、结果、改动文件、每次 attempt 的失败原因、工具统计、总耗时
  • diff.patch — 最终工作区 diff

也可以指向任何真实仓库:--repo /path/to/any/git/repo(要求工作区干净, 否则先提交或 --allow-dirty)。

LLM 配置

通过环境变量接入任意 Anthropic 兼容端点:

  • ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN(或 ANTHROPIC_API_KEY)
  • 模型:REPOFIX_MODEL > ANTHROPIC_DEFAULT_SONNET_MODEL > ANTHROPIC_MODEL, 或命令行 --model

动作协议是 JSON 文本(而非原生 tool_use),因此对网关后端不挑剔, 也让确定性测试(ScriptedAgent)能复用同一条管线。

网络韧性分三层:SDK 自带 429/5xx 自动重试(2 次)→ LLMAgent 再叠加一层 更长退避的重试预算(3 次,1s→2s→4s)→ 仍不可达则抛 AgentUnavailableError, 由 orchestrator 转成受控的 ERROR 终局(trace/report 照常落盘,不崩进程)。 4xx 裁决类错误(坏 key、坏请求)不重试。

演示剧本为什么"第一次必然失败"

fixtures/demo-repo 的测试套件里有一个任务文案没提的隐藏契约 (test_empty_page_keeps_position:空页必须保留位置)。最省的修法是跳过空页, 它能让崩溃消失、却违反位置契约——于是:

attempt 1: 最小修复 → pytest FAIL(读错误输出)
attempt 2: 定向修复 → pytest PASS

失败→恢复链路由此可稳定复现,且不是脚本伪造:测试编码了未写进任务的真实需求。

测试 Harness 自身(不需要 LLM)

uv run pytest tests/
  • test_policy.py — rm -rf / git push / ~/.ssh / .. 逃逸全部 DENIED; pytest / ruff / git 只读命令放行
  • test_tools.py — edit 唯一匹配语义、路径 jail(含符号链接逃逸)、输出截断
  • test_orchestrator_scripted.py — ScriptedAgent 驱动完整 fail→fix→pass 循环, 以及 POLICY_VIOLATION / finish 拒绝 / step 预算等停止条件

结构

harness/       # 真正的重点:orchestrator / state / policy / context / tracer
agent/         # coding_agent(LLM) 与 scripted_agent(确定性)
tools/         # read_file / search_code / edit_file / run_command / git_diff
validation/    # pytest 结果解析 + FailureContext
fixtures/      # 靶子仓库
tests/         # harness 自身的单测
scripts/       # 冒烟脚本 / fixture 重置

明确不做(v0.1)

多 Agent、LangGraph、MCP、RAG、Web UI、长期 Memory、数据库、Docker、自动提 PR、 联网搜索、OpenTelemetry。

About

RepoFix —— 以 pytest 为唯一成功标准的自主修 bug Agent Harness。

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages