An experiment · Sokrates · 2026-10-09

Below the agent’s read budget, file and unit length is not a cost driver

Splitting long files and units did not save an AI coding agent tokens. The same twelve changes, made by the same agent in two versions of one codebase that differ only in the length of their files and units, cost the same tokens, turns and time. Measured with two models, ten repeats per task and variant, control tasks and acceptance tests. What the agent pays for is the number of places a change touches, and files longer than one read.

What was tested

Sokrates' AI ease-of-change score and its AI Cost Estimator assumed that long files and long units make every change more expensive for an AI agent, because the agent has to read more to make the same change. The same claim was made with numbers in July 2026 in The Economic Benefit of Refactoring on martinfowler.com: after splitting a 17,155-line file, a change cost 83% fewer input tokens. This experiment measured the claim with repeats, controls and acceptance tests on a mature human-written codebase: Sokrates itself, as it was a year before the experiment.

Two variants of one codebase

Variant A is Sokrates at commit 5e6aa97a of 2025-09-20. Variant B is A with every main file brought under 500 lines of code and every unit under 50 lines and McCabe 25, by extract method and extract class only: 52 package-private helper classes in the original packages, every original class keeping its name and public API. The split was done in five parallel batches by coding agents under a strict brief, with the module tests and a golden-output check after every file: the reports both variants generate for a fixture are byte-identical across 850 normalized files.

The result: no difference

For every measure, the ratio of what variant B cost to what variant A cost, pooled over the ten target tasks (whose change lands in a split file) and separately over the two control tasks (whose files are byte-identical in A and B, so they should sit at 1.0). The pooled ratio is the geometric mean over tasks of the ratio of means, with a 95% bootstrap interval over runs. A value of 1.0 means the split changed nothing.

target tasks (split files)control tasks (identical files)

Per task

Input tokens per run, variant A and variant B, every run shown; the bar is the median. Tasks are ordered as in the task list; the two control tasks are last.

variant A runsvariant B runs

How the two agents read

The tool log of every run records each file read, with its line count, and each shell command with its output. The two models behave differently, and that is what decides whether length can matter.

The tasks

Real changes made to this code in the year after the snapshot, mined from the git history and re-derived against the snapshot. Each task is a behaviour description (what should happen, not where) and a JUnit acceptance test verified to fail on each untouched variant and to pass with a reference patch, on A and on B.

Compared with the martinfowler.com experiment

The two experiments agree on the mechanism and disagree on the result. His explanation for the 83% drop is that the agent read less code, not that there was less code; our logs say the same from the other side: what the agent reads is decided by how it searches, not by how long the file is. The difference in starting points is a factor of ten: his largest file was 17,155 lines, beyond what one read returns, so the agent had to page through it or read blind; ours all fit in one read, and a grep landed on one or two hits. If the cost of length is a step around the agent's read budget rather than a slope from zero, both results are consistent. That is the next experiment.

Conclusions

Limits

Next

Method

harness/run.py --tasks <tasks> --variants a --repeats 10 --m2 work/m2-a            # one worker per variant
harness/run.py --tasks <tasks> --variants b --repeats 10 --m2 work/m2-b
harness/compare.py --csv results/runs.csv                                           # the pooled tables
scripts/check_tasks.py                                                              # every task fails before, passes after, on both variants
scripts/golden.sh b                                                                 # B generates the same reports as A
scripts/build_site.py                                                               # this page

Longer write-up: docs/posts/analysis.md. Turn-by-turn traces of example runs (what each turn re-sent, read and edited): trace.html.