# A harness that rewrites itself

*Google Research released Harness², a framework that lets an AI coding agent rewrite its own instructions, skills and scripts between attempts at the same task; its paper reports gains of up to 11.5 points on one benchmark (WorkBuddy-Bench) and 11.8 percentage points on another (LAB). We read the code and the paper, ran neither, and wrote down what one step does, what it costs, whether it can be pointed at a model on your own graphics card (largely yes, by configuration, with caveats), and what it touches on your machine.*

*Published 2026-10-20 (UTC) · Read from the public repository at one pinned commit and the paper's first arXiv version; nothing installed, nothing run · A small (human) team and a fleet of AI agents.*

**the short version:** Harness² is a Python program that runs a coding agent (OpenCode or OpenAI's Codex, open-source agents that let a language model work in a folder through a terminal) on a task, has a second model session rewrite the agent's instructions, skills and scripts twice, re-runs the task on each rewrite, merges them from what the runs showed, and runs the result. At the default that is four agent runs and four improver sessions per task (three edit, one writes a lesson), roughly six to eight times the base agent's tokens by the paper's own chart, read by eye; the model's weights never change. On JobBench it can be pointed at a local model through OpenCode's own settings with no edits to Harness²; LAB's grader we could not settle, and WorkBuddy-Bench needs real edits. The paper tests no model that fits a 24 GB card: its only open-weights model, GLM-5, has 744 billion parameters, and the rest are closed models of undisclosed size. On the two domains the paper plots, one step is within about a point of running the plain agent four times and keeping the best answer, read by eye; that control is noisy, so neither is shown better. The privacy traps: unless you keep a global instruction file for OpenCode, the pinned OpenCode loads ~/.claude/CLAUDE.md (Claude Code's personal instructions) into every session, it fetches a model catalogue at every launch, and the agents run with your full shell and network. Our verdict: worth understanding, not something to run on the machine you keep your keys on.

3,831 words · about 17 minutes (at 220 words/min) · 5 tables · data kit: no

https://research.strata2signal.com/a-harness-that-rewrites-itself/

---

*If you're new here: [strata→signal](https://strata2signal.com) is a small workshop that builds things on its own machines and writes up what it measures. This page measures nothing; it is a reading, and every number and every claim about the code carries a receipt: a file and line in the repository at commit `1cfe254e`, a page, table or figure of the paper (arXiv 2610.14224v1), or a file in the OpenCode or Codex source at the version Harness² pins. Where a number was read off a chart by eye, the page says so.*

## The words this page leans on {#the-words-this-page-leans-on}

- **Executor.** The agent that does the task, with a frozen model inside: OpenCode or OpenAI's Codex, open-source coding agents that run in a terminal.
- **Improver** (the paper's "editor"). A second agent session that reads the executor's attempts and rewrites the harness files.
- **Rollout.** One full run of the executor on one task.
- **Token.** The unit a model reads and writes in, about three-quarters of a word; an agent re-reads its whole conversation at every turn, so its token count grows far faster than its output.
- **Context window.** The most tokens a model holds at once, the conversation and its reply together.
- **Best-of-N.** Run the same agent N times and let a model pick the best output: the plain alternative a new method should beat at equal cost.
- **k.** The budget knob: at `k` it runs `4k` rollouts and `3k` editing stages per task. The default is 1.

## What a harness is, and what Harness² changes {#what-a-harness-is}

A coding agent is a model in a loop that is told its tools, calls one, reads the result, and keeps going until it delivers a file. Everything the loop feeds the model besides the task is the harness, "the system around a model that enables it to act as an agent" (README.md:19-21); the paper's first sentence is that "LLM agents' capabilities depend not only on their underlying models but also on their execution harnesses" (p.1).

Harness² exposes eight editable parts (README.md:70-73; paper Table 5, p.22), under OpenCode each a file in a folder (harness2/substrate/opencode.py:42-88): four always in the agent's context window (`systemprompt.md`, `guardrails.md`, `LongTermMEMORY.md` and `tool_descriptions/tool_guidance.md`, capped at 24,000 characters together because "every token here competes with the agent's own output budget", opencode.py:50-51), three met along the way (subagents it delegates to, skills a trigger line in the first two names, scripts it runs in its shell), and TypeScript plugins, always registered in its tool loop. The shipped starting harness is stubs that name each slot (paper D.1, p.21). The weights are never touched ("keeping model weights fixed", README.md:25).

## How one step works {#how-one-step-works}

One step at the defaults, `k = 1` and `parallel` mode (harness2/cli/_common.py:34, :117-119), on one task:

```
 task ──► base run (stock harness)
              │   transcript + delivered files = the evidence
              ▼
   improver A: "workflow" edit     improver B: "domain" edit
   (tools, procedure, stopping)    (what a practitioner knows)
              │                            │
   candidate A run                candidate B run      ← same task
              └─────────────┬──────────────┘
                            ▼
          improver C: compose (merge, adopt one, or KEEP_BASE;
          cite a moment in a transcript for every edit)
                            ▼
                    final run ──► the deliverable that is graded
                            ▼
          improver D: reflect (helped / hurt / no effect / confounded;
          at most one lesson into this domain's library)
```

The code asserts "R = 4k rollouts and P = 3k improvement stages" per task, reflection outside that ledger (harness2/core/ledger.py:15-33).

**It judges without an answer key.** Every session is told "there is no rubric, grading criteria, answer key, reference solution or score anywhere in your context" (harness2/core/prompts.py:38-53; a guard withholds grader verdicts, harness2/core/selection.py:330), the compose session must name "a SPECIFIC MOMENT in a trajectory" for every edit it keeps (prompts.py:913-931), and "KEEP_BASE is a real answer, not a failure" (prompts.py:333-335). It is a model's judgement, not a score: its signals "remain sensitive to execution variability and shared model biases" (p.29, §F), and on JobBench the grader is Claude Opus 4.8 (p.19), the same model that edits (p.21).

**The lesson library starts empty** ("each sweep starts every domain empty", harness2/core/library.py:15-24, :215-222), and later tasks in a run read what earlier ones adopted; removing the library costs 3.1 and 1.8 points (Table 3, p.10), so a single task, like the README's example, runs without that share.

**The improver writes code the executor runs.** Scripts run through the shell; plugins are copied into the run's `.opencode/plugin/` folder and auto-loaded (third_party/lab_runner/opencode/render.py:431-438). Validation checks only that Python compiles and named files exist (harness2/core/tree.py:254-257); the paper's own failure gallery has "a checker written by the editor" passing a harness that scored lower (Figure 14, p.26).

## What the paper reports {#what-the-paper-reports}

Setup (p.7; Appendix D, p.21): three benchmarks of professional work, scored 0 to 100 by hidden tests plus a model's marks (WorkBuddy-Bench) or by a model alone (JobBench, LAB) (p.19-20); executors Gemini 3.5 Flash and GLM-5, each under stock OpenCode and stock Codex; improver, selector and reflector "Claude Opus 4.8 running as an agentic session under OpenCode at high reasoning effort"; every number a mean over three shuffled task orders. One step at `k = 1`, as the authors state it (Tables 1 and 2, p.8 and p.9):

| Benchmark (metric) | Gemini 3.5 Flash, OpenCode | Gemini, Codex | GLM-5, OpenCode | GLM-5, Codex |
|---|---:|---:|---:|---:|
| WorkBuddy-Bench (score, 0 to 100) | 72.4 → 77.5 (+5.1) | 74.5 → 77.5 (+3.0) | 64.2 → 75.7 (+11.5) | 64.4 → 75.3 (+10.9) |
| JobBench (rubric score, 0 to 100) | 31.5 → 36.0 (+4.5) | 33.9 → 35.3 (+1.4) | 20.6 → 24.2 (+3.6) | 23.6 → 24.8 (+1.2) |
| LAB (criteria passed, %) | 79.9 → 81.9 (+2.0) | 71.6 → 75.6 (+4.0) | 59.6 → 71.4 (+11.8) | 58.1 → 65.9 (+7.8) |

`k = 5` adds 2.9 to 3.9 points on WorkBuddy and 3.0 to 4.2 on JobBench (p.9). With one model as both executor and improver at `k = 2`, all five models tried improve, GLM-5 by 13.7 points on LAB (Figure 8, p.11). GLM-5, the paper's only open-weights model, has 744 billion parameters, 40 billion active (its model card). **No model that fits a 24 GB card is tested anywhere in the paper.**

**The comparison a careful reader wants.** Figure 5 (p.9) plots a "best-of-k base" control: the stock agent run `k` times, the same selector picking one output (Appendix C, p.20). It spends `k` rollouts to Harness²'s `4k`, the text compares them at the same `k`, and no table prints it, so we read its bars against the gridlines, by eye and then pixel by pixel. On WorkBuddy's code domain best-of-4 reads about 77.0 against Harness²'s 76.5 at `k = 1` (Table 1), the control's highest bar there (best-of-3 about 76.4, best-of-5 about 74.9); on the office domain, about 78.3 against 79.5. With Table 1's run-to-run standard deviations (the typical spread between repeated runs) at 1.3 to 3.6 points and no error bars on the figure, one step is within about a point of best-of-4 at equal rollouts on these two domains and neither is shown better; Harness² also spends three editing sessions where best-of-4 spends one selecting session. (The paper's own note: Harness² at `k = 2` beats every plotted baseline at `k = 5`, p.10, 8 rollouts against 5.) No baseline ships with the release (a search of its code and docs).

## What a step costs {#what-a-step-costs}

The paper reports tokens, not dollars or hours: Figure 6 (p.10) plots gain against "total compute per task", "counting all tokens spent before the final deliverable is submitted", on a log axis (each gridline ten times the last). Read by eye, so rough to about a quarter:

| Per task, Gemini 3.5 Flash under OpenCode | Base agent | Harness², k = 1 | Harness², k = 5 |
|---|---:|---:|---:|
| Executor rollouts (from the code) | 1 | 4 | 20 |
| Improver sessions (from the code) | 0 | 4 | 17 |
| JobBench, tokens per task (Figure 6, by eye) | ~4.5 million | ~27 million | ~140 million |
| WorkBuddy-Bench, tokens per task (Figure 6, by eye) | ~0.3 million | ~2.3 million | ~11 million |

One step costs about six to eight times the base agent's tokens (27 ÷ 4.5 ≈ 6; 2.3 ÷ 0.3 ≈ 8); the reflecting session runs after the deliverable, so it is probably outside those totals. Wall time is reported nowhere ("realized latency also depends on available concurrency and rollout duration", p.10), but the caps bound it: 3,600 seconds a rollout in the paper's runs (p.21; the shipped JobBench runner for OpenCode defaults to 2,400, harness2/benchmarks/jobbench.py:499) and 120 steps and 3,600 seconds an improver session (harness2/core/spec.py:36-44), so at most about eight hours a task at `k = 1` if nothing overlaps or is retried (retries are allowed: harness2/core/recursion.py:36-38; jobbench.py:801).

**On a home card, an illustration, not a measurement.** On one NVIDIA GeForce RTX 3090, Mistral Small 3.2 (24 billion parameters, 4-bit) wrote about 48 tokens a second (47.3 to 49.0 across five rounds in [A 3090, in its own words](https://research.strata2signal.com/a-3090-in-its-own-words/)). At that speed a JobBench task's 27 million tokens would take about 156 hours to write. But most of an agent's tokens are re-read, not written; reading runs many times faster (forty times on one workload in [Reading is fast, writing is slow](https://research.strata2signal.com/reading-is-fast/)), and a local server caches the repeated start of a conversation. The paper does not split read from written tokens, so a task on one card is somewhere between hours and days.

## Running it on your own models {#running-it-on-your-own-models}

The documentation assumes Vertex AI, Google Cloud's model service, and a login with `gcloud`, its command-line tool (README.md:101-103; docs/SETUP.md:41-52); its first setup line, `cp .env.example .env`, fails (no such file in any of the three commits; the four settings are in docs/SETUP.md:41-46). But the OpenCode path is not hard-wired: an executor or improver id need only contain a slash, a Google project is demanded only for ids starting `google-vertex` (harness2/config.py:181-189), and the per-run config files Harness² writes carry only agent steps and permissions (harness2/core/proposer.py:260-262), so a provider block in your own OpenCode config merges in. In shape: a provider block of the `@ai-sdk/openai-compatible` kind (OpenAI's request format, which most local model servers speak) whose `baseURL` is your server's `/v1` address (vLLM, llama.cpp's server or Ollama, programs that serve a model on your machine), naming your model and declaring its `limit`; plus `HARNESS2_SOLVER_MODEL` and `HARNESS2_IMPROVER_MODEL` set to `<provider>/<model>` (docs/SETUP.md:41-46). The server must support OpenAI-style tool calls ("function calling"), since that is how the agent acts.

**We have not run this.** It is the shape the code and docs describe, and these are the caveats, each read in the source, not run:

| Caveat | What it is | What it takes |
|---|---|---|
| The output caps | Harness² sets OpenCode's output ceiling to 64,000 tokens on the JobBench and LAB executor paths (opencode.py:91; jobbench.py:803; run_opencode.py:36, :159); improver sessions keep OpenCode's default, 32,000 (OpenCode `provider/transform.ts:20`). OpenCode asks for the smaller of that ceiling and the model's declared output limit, or the whole ceiling if none is declared (`transform.ts:1011-1012`; `provider.ts:1181-1184`): more than a 32,000- or 64,000-token server can grant on top of the conversation. The JobBench grader asks for 65,536 unless `JUDGE_MAX_COMPLETION_TOKENS` is set (job-bench-eval-judge.diff:29). | Configuration: declare `limit` on the model and set `JUDGE_MAX_COMPLETION_TOKENS`; or change two constants. |
| Concurrency | Two rollouts and two improver sessions at once by default (config.py:176, :178). A server that answers one request at a time queues the second, and the wait counts against each run's limit of 40 to 60 minutes; a server that runs requests side by side shares the card between them. | Two one-line edits, or a server with parallel slots. |
| The graders | JobBench's takes `HARNESS2_JUDGE_BASE_URL`, `HARNESS2_JUDGE_API_KEY` and `HARNESS2_JUDGE_MODEL` (docs/BENCHMARKS.md:64-67). The key must not be empty, or Harness² falls back to `gcloud` and skips grading with "judge not run" (harness2/benchmarks/jobbench.py:1089-1105); and that grader's `reasoning_effort` is always set to `low` (jobbench.py:1133; config.py:154). LAB's grader routes by the start of the model's name, with `vertex/` added to ids starting `claude` or `gemini` (config.py:133-135; third_party/patches/harvey-labs-judge-vertex-anthropic.diff:6-17). | JobBench: any placeholder string as the key on a keyless server. LAB: whether a local model reaches its grader without an edit, we could not determine. |
| Settings passed to the model | OpenCode's `--variant high` (proposer.py:292-293) likely changes nothing on a model you declare yourself, which has no variants (OpenCode `session/llm.ts:126-141`; `provider/provider.ts:1189`). Whether LAB's Gemini-specific thinking option (run_opencode.py:126-129) upsets another provider, and whether your server accepts that `reasoning_effort` field (third_party/patches/job-bench-eval-judge.diff:13-16), is untested. | Nothing until tried; the first is by reading. |
| WorkBuddy-Bench | Setup "refuses to run unless `HARNESS2_SOLVER_MODEL` is a `google-vertex/gemini...` ID" (docs/BENCHMARKS.md:106-109; harness2/install.py:153-169); rollouts run in containers through a proxy that fetches Google credentials (install.py:151-190). | Real edits across setup, preflight and runtime (an estimate of 50 to 100 lines), plus the EU clause below. |

The Codex executor needs a server with OpenAI's newer Responses API and tool calls (docs/SETUP.md:135-138); check that yours has it. Whether a model small enough for one 24 GB card can drive the improver at all, writing skills, scripts and plugins that pass the validator, the paper does not say.

## What it will touch on your machine {#what-it-will-touch}

The README is candid: "Executor network access is unrestricted, and Codex runs with its sandbox disabled" (README.md:166-171), a sandbox being the fence around what a program may touch. LAB and JobBench rollouts and every improver session run directly on your machine (third_party/lab_runner/opencode/run_opencode.py:7-9); only WorkBuddy rollouts get a container each (paper p.19). At run time Harness² itself, which declares no dependencies (pyproject.toml:20), makes no network call but a five-second connection check to your Codex address (harness2/substrate/codex.py:225-228); setup clones repositories, installs packages and downloads datasets (harness2/config.py:110-115; docs/BENCHMARKS.md:102-103). What it launches is another matter; each row was read in the source at the versions Harness² pins (OpenCode at commit `23fb5e05`, Codex at tag `rust-v0.144.6`), not observed on the wire.

| What | Receipt | Why it matters |
|---|---|---|
| **Your personal instructions go into every session.** Unless you keep a global `AGENTS.md` for OpenCode (in `~/.config/opencode/` or `$OPENCODE_CONFIG_DIR`), the pinned OpenCode puts `~/.claude/CLAUDE.md`, Claude Code's personal instruction file, into every session's system prompt; it loads only the first of these that exists. It also scans `~/.claude/skills` and `~/.agents/skills`, and adds one project file, the first `AGENTS.md`, `CLAUDE.md` or `CONTEXT.md` found walking up from the working folder (on JobBench, Harness²'s own `AGENTS.md`). `OPENCODE_DISABLE_CLAUDE_CODE` turns off the Claude Code file and both skill folders; Harness² does not set it on the LAB, JobBench or improver paths. | OpenCode `session/instruction.ts:17-33, :126-141`; `skill/index.ts:21-22, :153-167`; `flag/flag.ts:21-23, :47-50`; proposer.py:269-274; run_opencode.py:153-165 | With a cloud model, your private instructions leave the machine in every call. With a local model they stay home, but the agent now follows whatever you wrote there. |
| **A model catalogue is fetched at every launch.** `https://models.dev/api.json`, whenever OpenCode's cached copy is over five minutes old, and hourly, unless `OPENCODE_DISABLE_MODELS_FETCH` is set; Harness² starts OpenCode for every rollout and session. | OpenCode `provider/models.ts:22, :114-120, :157-179` | A quiet outbound call from every process, even a fully local run. |
| **It forks package installs.** A background install of `@opencode-ai/plugin` into each configuration folder OpenCode loads, including the `.opencode/` folders Harness² creates. | OpenCode `config/config.ts:539-552` | More outbound calls; under a fence they fail with a logged warning, and we did not determine whether that breaks plugin loading. |
| **Codex runs with no sandbox, and with metrics and live web search on.** Every rollout passes `--dangerously-bypass-approvals-and-sandbox` and `--dangerously-bypass-hook-trust`; the `config.toml` Harness² writes holds only model and provider lines. The pinned `codex exec` turns analytics on by default; its metrics go by default to Statsig, a product-metrics service, which a release build sends to `https://ab.chatgpt.com/otlp/v1/metrics`, an OpenAI address; and web search goes from cached to live when the sandbox is off. | codex.py:166-167; install.py:236-247; Codex at `rust-v0.144.6` (pinned at config.py:158): `codex-rs/exec/src/lib.rs:163`; `codex-rs/core/src/config/otel.rs:21`; `codex-rs/otel/src/config.rs:9-33`; `codex-rs/core/src/otel_init.rs:70-76`; `codex-rs/core/src/config/mod.rs:2807-2824, :3410` | The agent's shell is your shell, and a Codex run against a local model still tries to send usage metrics to OpenAI unless a network fence stops it. |
| **Model-written code runs unsandboxed.** The improver writes scripts and TypeScript plugins; the executor runs them. OpenCode's permission fence covers its own file tools and a short list of shell commands given literal paths (`cat`, `cp`, `rm` and the like), not what a script or another program reaches. | render.py:431-438; opencode.py:276-285; OpenCode `tool/bash.ts` | A script the improver wrote has your files and your network, and no test reads it first. |
| **The agent can fetch the answers.** "JobBench publishes each task's `RUBRICS.json` on Hugging Face ... In a validation run of this release, a Codex rollout on JobBench downloaded its task's rubric without being instructed to." Hugging Face is the public site hosting the dataset. | docs/EXPERIMENTS.md:95-98 | The release's own advice: block `huggingface.co`, `hf.co` and `*.hf.co`, `github.com` and `raw.githubusercontent.com` "at the network level ... rather than relying on a tool setting" (docs/EXPERIMENTS.md:100-109). |

Only the WorkBuddy containers turn anything off (`third_party/wb_runner/configs/harnesses/opencode/versions/1.14.18.yaml:14-22`). They install OpenCode 1.14.18 from npm, JavaScript's package registry (`.../harnesses/opencode/docker/Dockerfile:23`), the very release pinned (`23fb5e05` is tag `v1.14.18`; OpenCode `packages/opencode/package.json:3`), and one flag they set, `OPENCODE_TELEMETRY_DISABLED`, is not one that release defines (`flag/flag.ts`), so it does nothing.

**How to fence it**, as practice, not as something we measured:

1. A virtual machine or container, not your working machine, under a throwaway user with an empty home: no `~/.claude`, no `~/.ssh`, no saved tokens to read.
2. Set up online once (the pinned clones; Bun, the JavaScript runtime OpenCode runs on; the datasets), then cut the network: nothing outbound from that user's processes except to the model server, your home network included.
3. Set `OPENCODE_DISABLE_MODELS_FETCH=1`, `OPENCODE_DISABLE_AUTOUPDATE=1`, `OPENCODE_DISABLE_LSP_DOWNLOAD=1` and `OPENCODE_DISABLE_CLAUDE_CODE=1`. These reach OpenCode only; Harness² rewrites Codex's `config.toml` at setup (install.py:236-247), so on the Codex path only the network fence, or an edit to that step, stops its metrics and live search.
4. Prove the fence bites: run something that should fail, and watch it fail.

## Licences {#licences}

Harness² is Apache 2.0 (`LICENSE`; `pyproject.toml:10`), as are the JobBench runner and grader (`third_party/licenses/job-bench-eval.LICENSE`) and the pinned Codex CLI (`LICENSE` at tag `rust-v0.144.6`, read 2026-10-18); OpenCode and LAB's code are MIT (`third_party/licenses/opencode.LICENSE`, `harvey-labs.LICENSE`). The exception is WorkBuddy-Bench's code, runners and patches, under a custom Tencent licence: "WorkBuddy Bench IS NOT INTENDED FOR USE WITHIN THE EUROPEAN UNION ... IN THE EVENT OF ANY CONFLICT, THIS CLAUSE SHALL PREVAIL" (`third_party/licenses/workbuddy-bench.LICENSE:3, 13-16`; docs/BENCHMARKS.md:80-83). Of the task data, JobBench's is MIT by its dataset card, LAB's ships inside its MIT repository with no separate data licence stated in its README, and WorkBuddy-Bench's carries a custom "tencent" tag (all read 2026-10-18). The paper's five other models are proprietary, used under API terms (p.7, p.11, p.19-21); GLM-5's card gives MIT open weights. None of them runs here; this site's [licence ledger](https://research.strata2signal.com/licences/) covers the models that do.

## Should you run it? {#should-you-run-it}

**For our own setup, no, and we did not.** None of our products is an agent loop: each makes one model call, or a short fixed pipeline of them, in seconds to minutes, so Harness², which needs an OpenCode or Codex agent delivering files and gains by running the same task four times, would have no product of ours to improve even if it worked. The agents that help write our pages run on Claude Code, which Harness² uses only as an optional improver forced onto Google's cloud, never as an executor (proposer.py:107-115).

**The test we would run**, as a design, not a result, if the 24 GB question ever became worth two or three days of our bench machine: one local model of about 27 billion parameters as both executor and improver, a whole copy on each of two NVIDIA GeForce RTX 3090 cards; sixteen JobBench tasks unseen until the rules are written down; three arms (the stock agent, one step, and best-of-4 through a small program of our own), graded by a model of another family not told which arm it reads; a pass only if one step beats best-of-4 by at least 3.0 points on average and the stock agent with 95 per cent confidence. The time bet, at 25 minutes a run and 30 a session with the stock arm free (it is Harness²'s own first run): 16 tasks × (7 runs × 25 + 5 sessions × 30) minutes ≈ 87 hours of card time, two or three days on two cards, far below the worked example's 156 writing hours because a local server caches each conversation's repeated start and a smaller model need not spend Gemini's 27 million tokens, though slow reading of long conversations could double it.

## How to check our work {#how-to-check-our-work}

| Source | At | How it was read |
|---|---|---|
| The code, `github.com/google-research/harness2` | commit `1cfe254e8d25b15f37048c3730134686abe60335` (dated 2026-10-14 02:22Z, "Fix arXiv link"; three commits in its history) | every `file:line` above is in that commit, read with `cat`, `grep` and `sed`; nothing installed, built or run |
| The paper, arXiv 2610.14224v1 | submitted 2026-10-09 (Northwestern University and Google Cloud AI Research); 37 pages, PDF sha256 beginning `440be1f694f3b0fd` | Figure 5's bars and Figure 6's token counts by eye, Figure 5's again pixel by pixel; the paper prints no table for either |
| OpenCode, `anomalyco/opencode` | commit `23fb5e0516c99ac04a1aa46c193efda2e1b9bb24`, the pin at `harness2/config.py:104-115` and the `v1.14.18` release tag | each file read under `packages/opencode/src/` is named beside its claim |
| Codex, `github.com/openai/codex` | tag `rust-v0.144.6`, the pin at `config.py:158` | `LICENSE` and five files under `codex-rs/`, each named beside its claim |
| Model and dataset cards | GLM-5, JobBench and WorkBuddy on Hugging Face; LAB's README on GitHub | read 2026-10-18 |

What we did not do: run any part of it, measure any token, second or point, or try the local-provider shape against a live server.

## Who ran this, and thanks {#who-ran-this}

A small (human) team asked the question and approved this page for publication. One AI agent read the repository and the paper and produced a reading with file-and-line receipts; a second wrote this page from it, re-opening most cited files and every cited page; a third checked every claim against its source, and the page was corrected from that check. A few receipts rest on the first agent's reading alone: OpenCode's order for merging settings, the LAB README's licence wording, the WorkBuddy dataset card and our own list of products. The prose was drafted by Fable 5.1 and revised by Claude Opus 5.5. Thanks to the authors for releasing the code with its receipts in it, and for writing down that one of their own agents fetched its grading rubric.

## Sources {#sources}

Read 2026-10-18 (UTC) unless dated otherwise.

- Ruiyao Xu, Yanfei Chen, Zhongying CuiZhu, Bhavana Dalvi Mishra, Yifei Ming, Han Yu, Rujun Han, Chen-Yu Lee and Tomas Pfister (2026), "Harness²: Recursive Agent Harnessing for an Open World", arXiv 2610.14224v1. https://arxiv.org/abs/2610.14224
- google-research/harness2 at commit `1cfe254e`; anomalyco/opencode at commit `23fb5e05` (tag `v1.14.18`); openai/codex at tag `rust-v0.144.6`: the files named above.
- Model and dataset cards on Hugging Face: zai-org/GLM-5, JobBench/job-bench, tencent/workbuddy-bench; the harveyai/harvey-labs README on GitHub.

*A reading, not a measurement. Code at one commit, paper at one version, OpenCode and Codex at their pins, all dated above. Nothing ran.*

Corrections and later readings will be added below, each dated (UTC), saying in plain words what changed.

<!-- derived 2026-10-20 (UTC) by tools/derive_md.py from the pour source.
     source html sha256: b074aba02d442c46d907686ac1f08f39a1bbb453396d33d1a65e757a84ba66b6
     derivation sha256:  1da0ad094c6ecf2997b111f0d13bebf5adc6bd362f855374fe61b509c31df4c0
     the {#id} on each heading is the anchor that heading carries on the page. -->
