harness-evaluator 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- harness_evaluator-0.1.0/.gitignore +42 -0
- harness_evaluator-0.1.0/LICENSE +21 -0
- harness_evaluator-0.1.0/PKG-INFO +333 -0
- harness_evaluator-0.1.0/README.md +295 -0
- harness_evaluator-0.1.0/pyproject.toml +89 -0
- harness_evaluator-0.1.0/runs/sample-minimal.yaml +32 -0
- harness_evaluator-0.1.0/runs/sample-run.yaml +59 -0
- harness_evaluator-0.1.0/runs/task-mix.yaml +92 -0
- harness_evaluator-0.1.0/src/harness_evaluator/__init__.py +3 -0
- harness_evaluator-0.1.0/src/harness_evaluator/adapters/__init__.py +1 -0
- harness_evaluator-0.1.0/src/harness_evaluator/adapters/base.py +232 -0
- harness_evaluator-0.1.0/src/harness_evaluator/adapters/claude_code.py +126 -0
- harness_evaluator-0.1.0/src/harness_evaluator/adapters/codex.py +102 -0
- harness_evaluator-0.1.0/src/harness_evaluator/adapters/omp.py +83 -0
- harness_evaluator-0.1.0/src/harness_evaluator/adapters/opencode.py +83 -0
- harness_evaluator-0.1.0/src/harness_evaluator/adapters/pi.py +83 -0
- harness_evaluator-0.1.0/src/harness_evaluator/adapters/registry.py +68 -0
- harness_evaluator-0.1.0/src/harness_evaluator/adapters/utils.py +88 -0
- harness_evaluator-0.1.0/src/harness_evaluator/cli.py +533 -0
- harness_evaluator-0.1.0/src/harness_evaluator/dashboard/__init__.py +1 -0
- harness_evaluator-0.1.0/src/harness_evaluator/dashboard/app.py +352 -0
- harness_evaluator-0.1.0/src/harness_evaluator/dashboard/templates/index.html +46 -0
- harness_evaluator-0.1.0/src/harness_evaluator/dashboard/templates/run_detail.html +161 -0
- harness_evaluator-0.1.0/src/harness_evaluator/evaluator/__init__.py +1 -0
- harness_evaluator-0.1.0/src/harness_evaluator/evaluator/open_ended.py +804 -0
- harness_evaluator-0.1.0/src/harness_evaluator/evaluator/swe.py +356 -0
- harness_evaluator-0.1.0/src/harness_evaluator/evaluator/utils.py +90 -0
- harness_evaluator-0.1.0/src/harness_evaluator/gateway/__init__.py +1 -0
- harness_evaluator-0.1.0/src/harness_evaluator/gateway/canary.py +164 -0
- harness_evaluator-0.1.0/src/harness_evaluator/gateway/models.py +182 -0
- harness_evaluator-0.1.0/src/harness_evaluator/gateway/parsers/__init__.py +1 -0
- harness_evaluator-0.1.0/src/harness_evaluator/gateway/parsers/anthropic.py +95 -0
- harness_evaluator-0.1.0/src/harness_evaluator/gateway/parsers/openai.py +108 -0
- harness_evaluator-0.1.0/src/harness_evaluator/gateway/proxy.py +663 -0
- harness_evaluator-0.1.0/src/harness_evaluator/gateway/reconcile.py +130 -0
- harness_evaluator-0.1.0/src/harness_evaluator/gateway/store.py +157 -0
- harness_evaluator-0.1.0/src/harness_evaluator/orchestrator/__init__.py +1 -0
- harness_evaluator-0.1.0/src/harness_evaluator/orchestrator/config.py +401 -0
- harness_evaluator-0.1.0/src/harness_evaluator/orchestrator/engine.py +434 -0
- harness_evaluator-0.1.0/src/harness_evaluator/orchestrator/results_store.py +249 -0
- harness_evaluator-0.1.0/src/harness_evaluator/reporting/__init__.py +1 -0
- harness_evaluator-0.1.0/src/harness_evaluator/reporting/static_report.py +362 -0
- harness_evaluator-0.1.0/src/harness_evaluator/runner/__init__.py +1 -0
- harness_evaluator-0.1.0/src/harness_evaluator/runner/docker.py +776 -0
- harness_evaluator-0.1.0/src/harness_evaluator/stats/__init__.py +604 -0
- harness_evaluator-0.1.0/tasks/open-design-001.yaml +43 -0
- harness_evaluator-0.1.0/tasks/open-design-002.yaml +51 -0
- harness_evaluator-0.1.0/tasks/open-design-003.yaml +59 -0
- harness_evaluator-0.1.0/tasks/open-design-004.yaml +57 -0
- harness_evaluator-0.1.0/tasks/open-design-005.yaml +61 -0
- harness_evaluator-0.1.0/tasks/open-design-006.yaml +72 -0
- harness_evaluator-0.1.0/tasks/open-design-007.yaml +74 -0
- harness_evaluator-0.1.0/tasks/open-design-008.yaml +82 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-001/.gitignore +2 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-001/requirements.txt +1 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-001/src/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-001/src/solution.py +18 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-001/tests/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-001/tests/test_solution.py +24 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-002/.gitignore +2 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-002/requirements.txt +1 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-002/src/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-002/src/solution.py +15 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-002/tests/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-002/tests/test_solution.py +23 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-003/.gitignore +3 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-003/requirements.txt +1 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-003/src/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-003/src/solution.py +21 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-003/tests/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-003/tests/test_solution.py +19 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-004/.gitignore +3 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-004/requirements.txt +2 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-004/src/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-004/src/solution.py +42 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-004/tests/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-004/tests/test_solution.py +26 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-005/.gitignore +3 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-005/package.json +7 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-005/src/solution.ts +23 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-005/tests/test_solution.test.ts +12 -0
- harness_evaluator-0.1.0/tasks/repos/swe-bugfix-005/tsconfig.json +11 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-001/.gitignore +2 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-001/requirements.txt +1 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-001/src/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-001/src/solution.py +35 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-001/tests/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-001/tests/test_solution.py +40 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-002/.gitignore +3 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-002/requirements.txt +2 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-002/src/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-002/src/solution.py +26 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-002/tests/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-002/tests/test_solution.py +27 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-003/.gitignore +3 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-003/package.json +7 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-003/src/solution.ts +18 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-003/tests/test_solution.test.ts +24 -0
- harness_evaluator-0.1.0/tasks/repos/swe-feature-003/tsconfig.json +11 -0
- harness_evaluator-0.1.0/tasks/repos/swe-perf-001/.gitignore +3 -0
- harness_evaluator-0.1.0/tasks/repos/swe-perf-001/requirements.txt +1 -0
- harness_evaluator-0.1.0/tasks/repos/swe-perf-001/src/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-perf-001/src/solution.py +23 -0
- harness_evaluator-0.1.0/tasks/repos/swe-perf-001/tests/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-perf-001/tests/test_solution.py +13 -0
- harness_evaluator-0.1.0/tasks/repos/swe-perf-002/.gitignore +3 -0
- harness_evaluator-0.1.0/tasks/repos/swe-perf-002/package.json +7 -0
- harness_evaluator-0.1.0/tasks/repos/swe-perf-002/src/solution.ts +28 -0
- harness_evaluator-0.1.0/tasks/repos/swe-perf-002/tests/test_solution.test.ts +12 -0
- harness_evaluator-0.1.0/tasks/repos/swe-perf-002/tsconfig.json +11 -0
- harness_evaluator-0.1.0/tasks/repos/swe-refactor-001/.gitignore +2 -0
- harness_evaluator-0.1.0/tasks/repos/swe-refactor-001/requirements.txt +1 -0
- harness_evaluator-0.1.0/tasks/repos/swe-refactor-001/src/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-refactor-001/src/solution.py +36 -0
- harness_evaluator-0.1.0/tasks/repos/swe-refactor-001/tests/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-refactor-001/tests/test_solution.py +30 -0
- harness_evaluator-0.1.0/tasks/repos/swe-refactor-002/.gitignore +3 -0
- harness_evaluator-0.1.0/tasks/repos/swe-refactor-002/requirements.txt +1 -0
- harness_evaluator-0.1.0/tasks/repos/swe-refactor-002/src/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-refactor-002/src/solution.py +27 -0
- harness_evaluator-0.1.0/tasks/repos/swe-refactor-002/tests/__init__.py +0 -0
- harness_evaluator-0.1.0/tasks/repos/swe-refactor-002/tests/test_solution.py +21 -0
- harness_evaluator-0.1.0/tasks/swe-bugfix-001.yaml +67 -0
- harness_evaluator-0.1.0/tasks/swe-bugfix-002.yaml +71 -0
- harness_evaluator-0.1.0/tasks/swe-bugfix-003.yaml +67 -0
- harness_evaluator-0.1.0/tasks/swe-bugfix-004.yaml +76 -0
- harness_evaluator-0.1.0/tasks/swe-bugfix-005.yaml +64 -0
- harness_evaluator-0.1.0/tasks/swe-feature-001.yaml +93 -0
- harness_evaluator-0.1.0/tasks/swe-feature-002.yaml +91 -0
- harness_evaluator-0.1.0/tasks/swe-feature-003.yaml +92 -0
- harness_evaluator-0.1.0/tasks/swe-perf-001.yaml +62 -0
- harness_evaluator-0.1.0/tasks/swe-perf-002.yaml +83 -0
- harness_evaluator-0.1.0/tasks/swe-refactor-001.yaml +96 -0
- harness_evaluator-0.1.0/tasks/swe-refactor-002.yaml +98 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
*.egg
|
|
7
|
+
build/
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
|
|
13
|
+
# Distribution
|
|
14
|
+
dist/
|
|
15
|
+
|
|
16
|
+
# IDE
|
|
17
|
+
.idea/
|
|
18
|
+
.vscode/
|
|
19
|
+
*.swp
|
|
20
|
+
*.swo
|
|
21
|
+
|
|
22
|
+
# Test/coverage
|
|
23
|
+
.pytest_cache/
|
|
24
|
+
.coverage
|
|
25
|
+
htmlcov/
|
|
26
|
+
.mypy_cache/
|
|
27
|
+
.ruff_cache/
|
|
28
|
+
|
|
29
|
+
# Runtime data
|
|
30
|
+
heval_workdir/
|
|
31
|
+
heval_results.db
|
|
32
|
+
heval_gateway.db
|
|
33
|
+
*.db
|
|
34
|
+
|
|
35
|
+
# OS
|
|
36
|
+
.DS_Store
|
|
37
|
+
Thumbs.db
|
|
38
|
+
|
|
39
|
+
# Astro site
|
|
40
|
+
site/node_modules/
|
|
41
|
+
site/dist/
|
|
42
|
+
site/.astro/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 yorch
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: harness-evaluator
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Harness evaluator: compare agentic coding harnesses on token/time/cost effectiveness
|
|
5
|
+
Project-URL: Homepage, https://github.com/yorch/harness-evaluator
|
|
6
|
+
Project-URL: Documentation, https://yorch.github.io/harness-evaluator/
|
|
7
|
+
Project-URL: Source, https://github.com/yorch/harness-evaluator
|
|
8
|
+
Project-URL: Issues, https://github.com/yorch/harness-evaluator/issues
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Software Development :: Testing
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Requires-Dist: aiohttp>=3.9
|
|
20
|
+
Requires-Dist: fastapi>=0.110
|
|
21
|
+
Requires-Dist: httpx>=0.27
|
|
22
|
+
Requires-Dist: jinja2>=3.1
|
|
23
|
+
Requires-Dist: pandas>=2.0
|
|
24
|
+
Requires-Dist: pydantic>=2.0
|
|
25
|
+
Requires-Dist: pyyaml>=6.0
|
|
26
|
+
Requires-Dist: rich>=13.0
|
|
27
|
+
Requires-Dist: statsmodels>=0.14
|
|
28
|
+
Requires-Dist: typer>=0.12
|
|
29
|
+
Requires-Dist: uvicorn>=0.29
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
36
|
+
Requires-Dist: types-pyyaml>=6.0; extra == 'dev'
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# harness-evaluator
|
|
40
|
+
|
|
41
|
+
[](https://github.com/yorch/harness-evaluator/actions/workflows/ci.yml)
|
|
42
|
+
[](https://github.com/yorch/harness-evaluator/actions/workflows/docker.yml)
|
|
43
|
+
[](https://yorch.github.io/harness-evaluator/)
|
|
44
|
+
[](https://opensource.org/licenses/MIT)
|
|
45
|
+
|
|
46
|
+
Harness evaluator: compare agentic coding harnesses (Claude Code, Codex, Pi,
|
|
47
|
+
OpenCode, OMP) on token efficiency, task effectiveness, and time efficiency.
|
|
48
|
+
|
|
49
|
+
See [DESIGN.md](DESIGN.md) for the full design specification and
|
|
50
|
+
[the docs site](https://yorch.github.io/harness-evaluator/) for comprehensive documentation.
|
|
51
|
+
|
|
52
|
+
## Quick start
|
|
53
|
+
|
|
54
|
+
No clone required — harness-evaluator bundles its task library and publishes to PyPI as `harness-evaluator`:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uvx harness-evaluator init # scaffold harness-evaluator.yaml
|
|
58
|
+
docker pull ghcr.io/yorch/harness-evaluator-runner:latest # pull the runner image
|
|
59
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
60
|
+
uvx harness-evaluator gateway --port 8877 # separate terminal
|
|
61
|
+
uvx harness-evaluator run harness-evaluator.yaml
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### From source
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# 1. Install dependencies
|
|
68
|
+
uv sync --extra dev
|
|
69
|
+
|
|
70
|
+
# 2. Pull the pre-built Docker image (or build locally with: docker build -t harness-evaluator-runner:latest .)
|
|
71
|
+
docker pull ghcr.io/yorch/harness-evaluator-runner:latest
|
|
72
|
+
|
|
73
|
+
# 3. Set API keys
|
|
74
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
75
|
+
export OPENAI_API_KEY=sk-...
|
|
76
|
+
|
|
77
|
+
# 4. Start the gateway proxy (in a separate terminal)
|
|
78
|
+
harness-evaluator gateway --port 8877
|
|
79
|
+
|
|
80
|
+
# 5. Run a minimal evaluation (1 harness, 1 model, 1 task, 1 repeat)
|
|
81
|
+
harness-evaluator run runs/sample-minimal.yaml
|
|
82
|
+
|
|
83
|
+
# Or dry-run to see the matrix without executing
|
|
84
|
+
harness-evaluator run runs/sample-minimal.yaml --dry-run
|
|
85
|
+
|
|
86
|
+
# Curated 20-task mix (5 harnesses × 2 models × 20 tasks × 3 repeats = 600 cells)
|
|
87
|
+
harness-evaluator run runs/task-mix.yaml --dry-run
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Docker image
|
|
91
|
+
|
|
92
|
+
The runner executes harnesses inside an isolated Docker container. A pre-built
|
|
93
|
+
image is available on GHCR (recommended), or you can build locally:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Pull the pre-built image (recommended)
|
|
97
|
+
docker pull ghcr.io/yorch/harness-evaluator-runner:latest
|
|
98
|
+
|
|
99
|
+
# Or build locally
|
|
100
|
+
docker build -t harness-evaluator-runner:latest .
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## M1: Gateway Proxy (completed)
|
|
104
|
+
|
|
105
|
+
The gateway proxy is a custom HTTP/SSE server that sits between a harness and
|
|
106
|
+
the provider API, capturing every call's token usage, cost, and latency.
|
|
107
|
+
|
|
108
|
+
See [docs/gateway-proxy.md](docs/gateway-proxy.md) for a detailed explanation
|
|
109
|
+
with architecture diagram, token parsing, storage schema, and configuration
|
|
110
|
+
reference.
|
|
111
|
+
|
|
112
|
+
### Running the proxy
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
harness-evaluator gateway --port 8877
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Configure harnesses to route through the proxy:
|
|
119
|
+
```bash
|
|
120
|
+
export ANTHROPIC_BASE_URL=http://127.0.0.1:8877
|
|
121
|
+
export OPENAI_BASE_URL=http://127.0.0.1:8877
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Running the canary
|
|
125
|
+
|
|
126
|
+
After sending a request through the proxy, verify token capture accuracy:
|
|
127
|
+
```bash
|
|
128
|
+
harness-evaluator canary --tolerance 1.0
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### What the proxy captures
|
|
132
|
+
|
|
133
|
+
- **Token usage**: input, output, cache-read, cache-write, reasoning tokens
|
|
134
|
+
- **Cost**: calculated from a pricing table per model
|
|
135
|
+
- **Latency**: wall-clock time per API call
|
|
136
|
+
- **Full request/response**: headers and bodies stored in SQLite
|
|
137
|
+
- **Streaming support**: real-time SSE parsing for both Anthropic and OpenAI
|
|
138
|
+
|
|
139
|
+
### Observability tiers
|
|
140
|
+
|
|
141
|
+
- **full**: open harness, all metadata captured
|
|
142
|
+
- **partial**: closed harness, provider traffic captured via proxy
|
|
143
|
+
- **minimal**: closed harness, only total spend via billing API
|
|
144
|
+
|
|
145
|
+
### Reconciliation
|
|
146
|
+
|
|
147
|
+
Token usage from proxy, billing API, and harness self-report are reconciled
|
|
148
|
+
with per-harness tolerance bands. Discrepancies are flagged as a transparency
|
|
149
|
+
metric.
|
|
150
|
+
|
|
151
|
+
## M2: Core Pipeline (completed)
|
|
152
|
+
|
|
153
|
+
The core pipeline handles eval matrix building, execution, and reporting.
|
|
154
|
+
|
|
155
|
+
### Running an eval
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Dry run (print the matrix without executing)
|
|
159
|
+
harness-evaluator run runs/sample-run.yaml --dry-run
|
|
160
|
+
|
|
161
|
+
# Execute the eval
|
|
162
|
+
harness-evaluator run runs/sample-run.yaml
|
|
163
|
+
|
|
164
|
+
# Generate reports
|
|
165
|
+
harness-evaluator report broad-first-pass --output ./reports
|
|
166
|
+
|
|
167
|
+
# View results in console
|
|
168
|
+
harness-evaluator results broad-first-pass
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Run configuration
|
|
172
|
+
|
|
173
|
+
Eval runs are configured via YAML files (see `runs/sample-run.yaml`):
|
|
174
|
+
- `harnesses`: list of harness specs (name, adapter, observability tier)
|
|
175
|
+
- `models`: list of model specs (name, provider, API key env var)
|
|
176
|
+
- `tasks`: list of task IDs or `*` for all tasks in the library
|
|
177
|
+
- `repeats`: number of repeats per cell (default 5)
|
|
178
|
+
- `budget_usd`: maximum total spend (optional)
|
|
179
|
+
- `parallel_runs`: number of parallel container runs (default 1)
|
|
180
|
+
|
|
181
|
+
### Task definitions
|
|
182
|
+
|
|
183
|
+
Tasks are defined as YAML files in a task library directory (see `tasks/`):
|
|
184
|
+
- `track`: `swe` (hidden tests) or `open_ended` (LLM judge)
|
|
185
|
+
- `task_prompt`: the prompt given to the harness
|
|
186
|
+
- `test_command`: command to run tests
|
|
187
|
+
- `test_patch`: hidden test patch applied before evaluation
|
|
188
|
+
- `timeout_seconds`: per-task timeout
|
|
189
|
+
|
|
190
|
+
### Features
|
|
191
|
+
|
|
192
|
+
- **Matrix building**: harness × model × task × repeat
|
|
193
|
+
- **Budget caps**: stops when $ budget exhausted
|
|
194
|
+
- **Cell-level resumability**: skips completed cells on re-run
|
|
195
|
+
- **Retry logic**: transient failures retried with exponential backoff
|
|
196
|
+
- **Exit classes**: PASS, FAIL, RETRYABLE_KILL, NON_RETRYABLE_KILL
|
|
197
|
+
- **Partial credit**: fraction of tests passing
|
|
198
|
+
- **Error classification**: success, partial, overfit, timeout, refusal, wrong_approach, crash, no_change
|
|
199
|
+
- **Reports**: HTML, JSON, CSV with within-model leaderboards
|
|
200
|
+
|
|
201
|
+
## M3: Harness Adapters (completed)
|
|
202
|
+
|
|
203
|
+
Adapters wrap each coding harness with a uniform interface for the runner.
|
|
204
|
+
|
|
205
|
+
### Supported harnesses
|
|
206
|
+
|
|
207
|
+
| Harness | Adapter | Observability | Notes |
|
|
208
|
+
|---------|---------|--------------|-------|
|
|
209
|
+
| OpenCode | `opencode` | full | Open-source, system prompt visible |
|
|
210
|
+
| Claude Code | `claude-code` | partial | Closed, proxy captures traffic |
|
|
211
|
+
| Codex | `codex` | partial | Closed, proxy captures traffic |
|
|
212
|
+
| Pi | `pi` | minimal | May bypass proxy |
|
|
213
|
+
| OMP | `omp` | minimal | May bypass proxy |
|
|
214
|
+
|
|
215
|
+
### Listing adapters
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
harness-evaluator adapters
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Observability tiers
|
|
222
|
+
|
|
223
|
+
- **full**: Open/cooperating harness. System prompts, tool definitions, context
|
|
224
|
+
strategy, and turn-level metadata are available.
|
|
225
|
+
- **partial**: Closed harness but provider traffic is captured through the
|
|
226
|
+
gateway proxy. Token usage and cost are accurately attributed.
|
|
227
|
+
- **minimal**: Only total spend or billing data is available. Traffic may
|
|
228
|
+
bypass the proxy. Cost accounting relies on billing reconciliation.
|
|
229
|
+
|
|
230
|
+
### Adapter design
|
|
231
|
+
|
|
232
|
+
Each adapter implements:
|
|
233
|
+
- `prepare()`: Check/install the harness
|
|
234
|
+
- `run(task_prompt, timeout)`: Execute the harness non-interactively
|
|
235
|
+
- `cleanup()`: Clean up after the run
|
|
236
|
+
- `get_env()`: Set gateway proxy env vars and API keys
|
|
237
|
+
|
|
238
|
+
The adapter registry (`harness_evaluator.adapters.registry`) loads adapters by name and
|
|
239
|
+
the Docker runner uses it to dispatch to the correct adapter based on the
|
|
240
|
+
run config's `harness.adapter` field.
|
|
241
|
+
|
|
242
|
+
## M4: Open-Ended Track (completed)
|
|
243
|
+
|
|
244
|
+
The open-ended track evaluates tasks without a single correct answer using a
|
|
245
|
+
frozen LLM judge, structured rubric, and structural checks.
|
|
246
|
+
|
|
247
|
+
### Components
|
|
248
|
+
|
|
249
|
+
- **Frozen Judge** (`FrozenJudge`): Versioned LLM judge with an immutable prompt.
|
|
250
|
+
Version `v1.0` is the initial frozen prompt. Changing the prompt requires
|
|
251
|
+
bumping the version, which invalidates prior calibration data.
|
|
252
|
+
- **Rubric** (`Rubric`): Weighted criteria with 0-5 scoring scale. Default
|
|
253
|
+
rubric includes correctness (3x), completeness (2x), code_quality (1.5x),
|
|
254
|
+
test_quality (1.5x), documentation (1x).
|
|
255
|
+
- **Structural Checks** (`StructuralChecker`): Verifies file existence, Python
|
|
256
|
+
syntax, and test command execution. Structural failures cap the composite
|
|
257
|
+
success at 0.5.
|
|
258
|
+
- **Calibration** (`CalibrationSet`): Anchor submissions with known expected
|
|
259
|
+
scores for drift detection. Mean absolute error > 0.15 flags drift.
|
|
260
|
+
|
|
261
|
+
### Running calibration
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
265
|
+
harness-evaluator calibrate --model claude-sonnet-4-20250514
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Evaluation flow
|
|
269
|
+
|
|
270
|
+
1. Get git diff of changes
|
|
271
|
+
2. Run structural checks (file existence, syntax, tests)
|
|
272
|
+
3. Run LLM judge against rubric
|
|
273
|
+
4. Composite score: judge score, capped at 0.5 if structural checks fail
|
|
274
|
+
5. Pass threshold: 0.7
|
|
275
|
+
|
|
276
|
+
## M5: Dashboard (completed)
|
|
277
|
+
|
|
278
|
+
Interactive FastAPI web dashboard for exploring eval results.
|
|
279
|
+
|
|
280
|
+
### Starting the dashboard
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
harness-evaluator dashboard --port 8080
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Then open http://127.0.0.1:8080 in your browser.
|
|
287
|
+
|
|
288
|
+
### Features
|
|
289
|
+
|
|
290
|
+
- **Run overview**: List all runs with summary stats (cells, passed, failed, cost)
|
|
291
|
+
- **Run detail**: Per-run view with leaderboards and filtered results table
|
|
292
|
+
- **Filtering**: Filter by model, harness, task track, and minimum success rate
|
|
293
|
+
- **Leaderboards**: Within-model harness comparison sorted by success rate
|
|
294
|
+
- **REST API**: JSON endpoints for programmatic access:
|
|
295
|
+
- `GET /api/runs` — list all runs
|
|
296
|
+
- `GET /api/run/{name}` — get filtered results
|
|
297
|
+
- `GET /api/run/{name}/leaderboard` — get leaderboard data
|
|
298
|
+
|
|
299
|
+
## M6: Statistics (completed)
|
|
300
|
+
|
|
301
|
+
Statistical analysis of evaluation results, including mixed-effects modeling,
|
|
302
|
+
variance decomposition, bootstrap confidence intervals, and consistency analysis.
|
|
303
|
+
|
|
304
|
+
### Running stats
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
harness-evaluator stats my-run --db harness_evaluator_results.db
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Components
|
|
311
|
+
|
|
312
|
+
- **Mixed-Effects Model**: `success ~ C(harness) + C(model) + (1|task)`
|
|
313
|
+
Treats harness and model as fixed effects, task as a random effect.
|
|
314
|
+
Reports coefficients, standard errors, p-values, and confidence intervals.
|
|
315
|
+
- **Variance Decomposition**: Partitions variance into harness, model, task,
|
|
316
|
+
and residual components. Reports percentage of total variance explained.
|
|
317
|
+
- **Bootstrap CIs**: Non-parametric bootstrap confidence intervals (default
|
|
318
|
+
1000 resamples, 95% CI) for success rate by harness.
|
|
319
|
+
- **Consistency Analysis**: Per harness × model combination, reports mean,
|
|
320
|
+
std, coefficient of variation, min/max success, and bootstrap CI.
|
|
321
|
+
- **Warnings**: Automatically warns when sample size is too small (<30)
|
|
322
|
+
or when the mixed-effects model fails to converge.
|
|
323
|
+
|
|
324
|
+
## Architecture
|
|
325
|
+
|
|
326
|
+
- **Gateway**: custom HTTP/SSE proxy that intercepts provider calls and captures
|
|
327
|
+
token usage, cost, and latency with full request/response logging.
|
|
328
|
+
- **Orchestrator**: builds the eval matrix (harness × model × task × repeats),
|
|
329
|
+
manages budget caps, and handles cell-level resumability.
|
|
330
|
+
- **Runner**: Docker-based isolation, one container per eval cell.
|
|
331
|
+
- **Adapters**: per-harness integration (Python core + TS shims where needed).
|
|
332
|
+
- **Evaluator**: SWE-bench-style (hidden tests) and open-ended (LLM judge) tracks.
|
|
333
|
+
- **Reporting**: CLI reports + static HTML + interactive web dashboard.
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# harness-evaluator
|
|
2
|
+
|
|
3
|
+
[](https://github.com/yorch/harness-evaluator/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/yorch/harness-evaluator/actions/workflows/docker.yml)
|
|
5
|
+
[](https://yorch.github.io/harness-evaluator/)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
Harness evaluator: compare agentic coding harnesses (Claude Code, Codex, Pi,
|
|
9
|
+
OpenCode, OMP) on token efficiency, task effectiveness, and time efficiency.
|
|
10
|
+
|
|
11
|
+
See [DESIGN.md](DESIGN.md) for the full design specification and
|
|
12
|
+
[the docs site](https://yorch.github.io/harness-evaluator/) for comprehensive documentation.
|
|
13
|
+
|
|
14
|
+
## Quick start
|
|
15
|
+
|
|
16
|
+
No clone required — harness-evaluator bundles its task library and publishes to PyPI as `harness-evaluator`:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
uvx harness-evaluator init # scaffold harness-evaluator.yaml
|
|
20
|
+
docker pull ghcr.io/yorch/harness-evaluator-runner:latest # pull the runner image
|
|
21
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
22
|
+
uvx harness-evaluator gateway --port 8877 # separate terminal
|
|
23
|
+
uvx harness-evaluator run harness-evaluator.yaml
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### From source
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# 1. Install dependencies
|
|
30
|
+
uv sync --extra dev
|
|
31
|
+
|
|
32
|
+
# 2. Pull the pre-built Docker image (or build locally with: docker build -t harness-evaluator-runner:latest .)
|
|
33
|
+
docker pull ghcr.io/yorch/harness-evaluator-runner:latest
|
|
34
|
+
|
|
35
|
+
# 3. Set API keys
|
|
36
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
37
|
+
export OPENAI_API_KEY=sk-...
|
|
38
|
+
|
|
39
|
+
# 4. Start the gateway proxy (in a separate terminal)
|
|
40
|
+
harness-evaluator gateway --port 8877
|
|
41
|
+
|
|
42
|
+
# 5. Run a minimal evaluation (1 harness, 1 model, 1 task, 1 repeat)
|
|
43
|
+
harness-evaluator run runs/sample-minimal.yaml
|
|
44
|
+
|
|
45
|
+
# Or dry-run to see the matrix without executing
|
|
46
|
+
harness-evaluator run runs/sample-minimal.yaml --dry-run
|
|
47
|
+
|
|
48
|
+
# Curated 20-task mix (5 harnesses × 2 models × 20 tasks × 3 repeats = 600 cells)
|
|
49
|
+
harness-evaluator run runs/task-mix.yaml --dry-run
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Docker image
|
|
53
|
+
|
|
54
|
+
The runner executes harnesses inside an isolated Docker container. A pre-built
|
|
55
|
+
image is available on GHCR (recommended), or you can build locally:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Pull the pre-built image (recommended)
|
|
59
|
+
docker pull ghcr.io/yorch/harness-evaluator-runner:latest
|
|
60
|
+
|
|
61
|
+
# Or build locally
|
|
62
|
+
docker build -t harness-evaluator-runner:latest .
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## M1: Gateway Proxy (completed)
|
|
66
|
+
|
|
67
|
+
The gateway proxy is a custom HTTP/SSE server that sits between a harness and
|
|
68
|
+
the provider API, capturing every call's token usage, cost, and latency.
|
|
69
|
+
|
|
70
|
+
See [docs/gateway-proxy.md](docs/gateway-proxy.md) for a detailed explanation
|
|
71
|
+
with architecture diagram, token parsing, storage schema, and configuration
|
|
72
|
+
reference.
|
|
73
|
+
|
|
74
|
+
### Running the proxy
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
harness-evaluator gateway --port 8877
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Configure harnesses to route through the proxy:
|
|
81
|
+
```bash
|
|
82
|
+
export ANTHROPIC_BASE_URL=http://127.0.0.1:8877
|
|
83
|
+
export OPENAI_BASE_URL=http://127.0.0.1:8877
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Running the canary
|
|
87
|
+
|
|
88
|
+
After sending a request through the proxy, verify token capture accuracy:
|
|
89
|
+
```bash
|
|
90
|
+
harness-evaluator canary --tolerance 1.0
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### What the proxy captures
|
|
94
|
+
|
|
95
|
+
- **Token usage**: input, output, cache-read, cache-write, reasoning tokens
|
|
96
|
+
- **Cost**: calculated from a pricing table per model
|
|
97
|
+
- **Latency**: wall-clock time per API call
|
|
98
|
+
- **Full request/response**: headers and bodies stored in SQLite
|
|
99
|
+
- **Streaming support**: real-time SSE parsing for both Anthropic and OpenAI
|
|
100
|
+
|
|
101
|
+
### Observability tiers
|
|
102
|
+
|
|
103
|
+
- **full**: open harness, all metadata captured
|
|
104
|
+
- **partial**: closed harness, provider traffic captured via proxy
|
|
105
|
+
- **minimal**: closed harness, only total spend via billing API
|
|
106
|
+
|
|
107
|
+
### Reconciliation
|
|
108
|
+
|
|
109
|
+
Token usage from proxy, billing API, and harness self-report are reconciled
|
|
110
|
+
with per-harness tolerance bands. Discrepancies are flagged as a transparency
|
|
111
|
+
metric.
|
|
112
|
+
|
|
113
|
+
## M2: Core Pipeline (completed)
|
|
114
|
+
|
|
115
|
+
The core pipeline handles eval matrix building, execution, and reporting.
|
|
116
|
+
|
|
117
|
+
### Running an eval
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Dry run (print the matrix without executing)
|
|
121
|
+
harness-evaluator run runs/sample-run.yaml --dry-run
|
|
122
|
+
|
|
123
|
+
# Execute the eval
|
|
124
|
+
harness-evaluator run runs/sample-run.yaml
|
|
125
|
+
|
|
126
|
+
# Generate reports
|
|
127
|
+
harness-evaluator report broad-first-pass --output ./reports
|
|
128
|
+
|
|
129
|
+
# View results in console
|
|
130
|
+
harness-evaluator results broad-first-pass
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Run configuration
|
|
134
|
+
|
|
135
|
+
Eval runs are configured via YAML files (see `runs/sample-run.yaml`):
|
|
136
|
+
- `harnesses`: list of harness specs (name, adapter, observability tier)
|
|
137
|
+
- `models`: list of model specs (name, provider, API key env var)
|
|
138
|
+
- `tasks`: list of task IDs or `*` for all tasks in the library
|
|
139
|
+
- `repeats`: number of repeats per cell (default 5)
|
|
140
|
+
- `budget_usd`: maximum total spend (optional)
|
|
141
|
+
- `parallel_runs`: number of parallel container runs (default 1)
|
|
142
|
+
|
|
143
|
+
### Task definitions
|
|
144
|
+
|
|
145
|
+
Tasks are defined as YAML files in a task library directory (see `tasks/`):
|
|
146
|
+
- `track`: `swe` (hidden tests) or `open_ended` (LLM judge)
|
|
147
|
+
- `task_prompt`: the prompt given to the harness
|
|
148
|
+
- `test_command`: command to run tests
|
|
149
|
+
- `test_patch`: hidden test patch applied before evaluation
|
|
150
|
+
- `timeout_seconds`: per-task timeout
|
|
151
|
+
|
|
152
|
+
### Features
|
|
153
|
+
|
|
154
|
+
- **Matrix building**: harness × model × task × repeat
|
|
155
|
+
- **Budget caps**: stops when $ budget exhausted
|
|
156
|
+
- **Cell-level resumability**: skips completed cells on re-run
|
|
157
|
+
- **Retry logic**: transient failures retried with exponential backoff
|
|
158
|
+
- **Exit classes**: PASS, FAIL, RETRYABLE_KILL, NON_RETRYABLE_KILL
|
|
159
|
+
- **Partial credit**: fraction of tests passing
|
|
160
|
+
- **Error classification**: success, partial, overfit, timeout, refusal, wrong_approach, crash, no_change
|
|
161
|
+
- **Reports**: HTML, JSON, CSV with within-model leaderboards
|
|
162
|
+
|
|
163
|
+
## M3: Harness Adapters (completed)
|
|
164
|
+
|
|
165
|
+
Adapters wrap each coding harness with a uniform interface for the runner.
|
|
166
|
+
|
|
167
|
+
### Supported harnesses
|
|
168
|
+
|
|
169
|
+
| Harness | Adapter | Observability | Notes |
|
|
170
|
+
|---------|---------|--------------|-------|
|
|
171
|
+
| OpenCode | `opencode` | full | Open-source, system prompt visible |
|
|
172
|
+
| Claude Code | `claude-code` | partial | Closed, proxy captures traffic |
|
|
173
|
+
| Codex | `codex` | partial | Closed, proxy captures traffic |
|
|
174
|
+
| Pi | `pi` | minimal | May bypass proxy |
|
|
175
|
+
| OMP | `omp` | minimal | May bypass proxy |
|
|
176
|
+
|
|
177
|
+
### Listing adapters
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
harness-evaluator adapters
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Observability tiers
|
|
184
|
+
|
|
185
|
+
- **full**: Open/cooperating harness. System prompts, tool definitions, context
|
|
186
|
+
strategy, and turn-level metadata are available.
|
|
187
|
+
- **partial**: Closed harness but provider traffic is captured through the
|
|
188
|
+
gateway proxy. Token usage and cost are accurately attributed.
|
|
189
|
+
- **minimal**: Only total spend or billing data is available. Traffic may
|
|
190
|
+
bypass the proxy. Cost accounting relies on billing reconciliation.
|
|
191
|
+
|
|
192
|
+
### Adapter design
|
|
193
|
+
|
|
194
|
+
Each adapter implements:
|
|
195
|
+
- `prepare()`: Check/install the harness
|
|
196
|
+
- `run(task_prompt, timeout)`: Execute the harness non-interactively
|
|
197
|
+
- `cleanup()`: Clean up after the run
|
|
198
|
+
- `get_env()`: Set gateway proxy env vars and API keys
|
|
199
|
+
|
|
200
|
+
The adapter registry (`harness_evaluator.adapters.registry`) loads adapters by name and
|
|
201
|
+
the Docker runner uses it to dispatch to the correct adapter based on the
|
|
202
|
+
run config's `harness.adapter` field.
|
|
203
|
+
|
|
204
|
+
## M4: Open-Ended Track (completed)
|
|
205
|
+
|
|
206
|
+
The open-ended track evaluates tasks without a single correct answer using a
|
|
207
|
+
frozen LLM judge, structured rubric, and structural checks.
|
|
208
|
+
|
|
209
|
+
### Components
|
|
210
|
+
|
|
211
|
+
- **Frozen Judge** (`FrozenJudge`): Versioned LLM judge with an immutable prompt.
|
|
212
|
+
Version `v1.0` is the initial frozen prompt. Changing the prompt requires
|
|
213
|
+
bumping the version, which invalidates prior calibration data.
|
|
214
|
+
- **Rubric** (`Rubric`): Weighted criteria with 0-5 scoring scale. Default
|
|
215
|
+
rubric includes correctness (3x), completeness (2x), code_quality (1.5x),
|
|
216
|
+
test_quality (1.5x), documentation (1x).
|
|
217
|
+
- **Structural Checks** (`StructuralChecker`): Verifies file existence, Python
|
|
218
|
+
syntax, and test command execution. Structural failures cap the composite
|
|
219
|
+
success at 0.5.
|
|
220
|
+
- **Calibration** (`CalibrationSet`): Anchor submissions with known expected
|
|
221
|
+
scores for drift detection. Mean absolute error > 0.15 flags drift.
|
|
222
|
+
|
|
223
|
+
### Running calibration
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
227
|
+
harness-evaluator calibrate --model claude-sonnet-4-20250514
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Evaluation flow
|
|
231
|
+
|
|
232
|
+
1. Get git diff of changes
|
|
233
|
+
2. Run structural checks (file existence, syntax, tests)
|
|
234
|
+
3. Run LLM judge against rubric
|
|
235
|
+
4. Composite score: judge score, capped at 0.5 if structural checks fail
|
|
236
|
+
5. Pass threshold: 0.7
|
|
237
|
+
|
|
238
|
+
## M5: Dashboard (completed)
|
|
239
|
+
|
|
240
|
+
Interactive FastAPI web dashboard for exploring eval results.
|
|
241
|
+
|
|
242
|
+
### Starting the dashboard
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
harness-evaluator dashboard --port 8080
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Then open http://127.0.0.1:8080 in your browser.
|
|
249
|
+
|
|
250
|
+
### Features
|
|
251
|
+
|
|
252
|
+
- **Run overview**: List all runs with summary stats (cells, passed, failed, cost)
|
|
253
|
+
- **Run detail**: Per-run view with leaderboards and filtered results table
|
|
254
|
+
- **Filtering**: Filter by model, harness, task track, and minimum success rate
|
|
255
|
+
- **Leaderboards**: Within-model harness comparison sorted by success rate
|
|
256
|
+
- **REST API**: JSON endpoints for programmatic access:
|
|
257
|
+
- `GET /api/runs` — list all runs
|
|
258
|
+
- `GET /api/run/{name}` — get filtered results
|
|
259
|
+
- `GET /api/run/{name}/leaderboard` — get leaderboard data
|
|
260
|
+
|
|
261
|
+
## M6: Statistics (completed)
|
|
262
|
+
|
|
263
|
+
Statistical analysis of evaluation results, including mixed-effects modeling,
|
|
264
|
+
variance decomposition, bootstrap confidence intervals, and consistency analysis.
|
|
265
|
+
|
|
266
|
+
### Running stats
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
harness-evaluator stats my-run --db harness_evaluator_results.db
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Components
|
|
273
|
+
|
|
274
|
+
- **Mixed-Effects Model**: `success ~ C(harness) + C(model) + (1|task)`
|
|
275
|
+
Treats harness and model as fixed effects, task as a random effect.
|
|
276
|
+
Reports coefficients, standard errors, p-values, and confidence intervals.
|
|
277
|
+
- **Variance Decomposition**: Partitions variance into harness, model, task,
|
|
278
|
+
and residual components. Reports percentage of total variance explained.
|
|
279
|
+
- **Bootstrap CIs**: Non-parametric bootstrap confidence intervals (default
|
|
280
|
+
1000 resamples, 95% CI) for success rate by harness.
|
|
281
|
+
- **Consistency Analysis**: Per harness × model combination, reports mean,
|
|
282
|
+
std, coefficient of variation, min/max success, and bootstrap CI.
|
|
283
|
+
- **Warnings**: Automatically warns when sample size is too small (<30)
|
|
284
|
+
or when the mixed-effects model fails to converge.
|
|
285
|
+
|
|
286
|
+
## Architecture
|
|
287
|
+
|
|
288
|
+
- **Gateway**: custom HTTP/SSE proxy that intercepts provider calls and captures
|
|
289
|
+
token usage, cost, and latency with full request/response logging.
|
|
290
|
+
- **Orchestrator**: builds the eval matrix (harness × model × task × repeats),
|
|
291
|
+
manages budget caps, and handles cell-level resumability.
|
|
292
|
+
- **Runner**: Docker-based isolation, one container per eval cell.
|
|
293
|
+
- **Adapters**: per-harness integration (Python core + TS shims where needed).
|
|
294
|
+
- **Evaluator**: SWE-bench-style (hidden tests) and open-ended (LLM judge) tracks.
|
|
295
|
+
- **Reporting**: CLI reports + static HTML + interactive web dashboard.
|