Measures how much code AI coding agents add, from patches benchmarks already publish
See the codeAmong agents that successfully solve the same SWE-bench issue, which leave the smallest code footprint?
Parsimony imports public SWE-bench Verified predictions and published evaluation results, statically measures their Python changes, and compares successful solutions. It makes no LLM API calls, runs no SWE-bench reruns, installs nothing from target repositories and never executes submitted code.
Status: beta / research prototype. No official cross-model ranking or validated full-benchmark score exists. Everything in
examples/is exploratory and must not be read as a model recommendation. Analyzer0.5.0-betareplaced lexical tokens with coding units (AST elements) as the primary metric (see the changelog). The current two-submission 500-task audit uses it. Older audits are kept for history and are not comparable.
Python 3.12+, no runtime dependencies for Python analysis. Optional tracks: JavaScript/TypeScript use Node.js and the official TypeScript parser (npm ci installs the pinned typescript), Go uses pip install '.[languages]' (the current checksum-pinned grammar builds from source, requiring a C compiler and Python development headers); see language tracks for pinned parsers, scope and reproducible commands. Analyzer 0.8 introduced a versioned Go grammar/EOF fix and 0.9 rejects malformed hunk headers and duplicate file sections instead of skipping or double-counting them; published historical cohorts keep their recorded analyzer identities. Run from this checkout (pip install -e . is optional). Measurements depend on the interpreter's tokenizer, so use one pinned Python version for anything you compare.
# Metadata, base commits and human patches for all 500 Verified tasks.
python -m parsimony dataset --output verified.jsonl
# Analyze five successful tasks per submission (alphabetical, NOT a representative sample).
python -m parsimony analyze \
20250522_sweagent_claude-4-sonnet-20250514 \
20250225_sweagent_claude-3-7-sonnet \
--dataset verified.jsonl --limit 5 --output results.jsonl
# Compare only tasks solved AND analyzed by every selected agent.
python -m parsimony leaderboard results.jsonl --shared > leaderboard.json
python -m unittest discover -s tests -v
Useful analyze options:
--limit N only limits analysis attempts. It never changes the resolve-rate denominator.--task TASK_ID (repeatable) analyzes a chosen cohort while keeping all 500 records.--include-failed also measures explicitly failed patches (see failed patches).--resume appends missing records to an interrupted full single-submission run and retries fetch_error records. It verifies agent, results hash, ref and analyzer/Python versions first.--patch-only gives hunk-only estimates without fetching sources. These are a separate, less reliable mode that is never pooled with full-file results.Output has one record per agent/task, including failures, unavailable analyses and skipped tasks. leaderboard rejects duplicate agent/task records. --agent NAME selects agents.
base_commit, and the patch is applied in memory with strict position/context validation. Unapplicable patches are recorded as errors, never scored as zero. Network failures are recorded as retryable fetch_error.ast (docstrings removed) and walked in source order. A unit is one syntactic element: a statement (if, return, assignment, def), an expression (call, attribute access, arithmetic or boolean operation), each comparison, a name or a literal. Each statement block also ends with one EndBlock unit, so nesting and moving code into or out of a block count. Punctuation, brackets, commas, load/store markers, comments, formatting and name length are not units: if x.count(y) > 0: foo(a, b) is 12 units. Units are unknown (null), never zero, when a file does not parse on both sides (lexical_files).approximate_files).net_units = added − deleted, churn = added + deleted. Negative net is genuine shrinking. A renamed name or changed literal is one changed unit; the structural_churn diagnostic ignores identifier/literal values. The pre-0.5 metric, normalized lexical tokens (net_tokens, token_churn), remains a diagnostic. files_changed counts implementation files whose normalized code differs..py implementation files count. Excluded: test/doc/example/benchmark directories, test filenames, setup.py/conftest.py, generated files (a header comment in the base commit), protobuf output, migration scripts, vendored and build output. Django's db/migrations/ and test/ framework packages count as implementation. Every record lists touched_files and excluded_files. See implementation() for the exact rules.patch (not test_patch) is measured identically. model_human_ratio = model churn / human churn, or null when the human churn is zero.leaderboard reports medians (net, churn, human ratio, files, AST and complexity deltas), sample counts and resolve rate, sorted by median net units. --shared uses the intersection of resolved and analyzable tasks, which avoids task-mix confounding but can favor easy tasks.
See the scoring specification. Per-task percentiles against a frozen reference panel are blended 80/20 and averaged with equal task weights. Successes score 1 to 100. Explicitly failed attempts get a bounded nonpositive growth/churn penalty down to −25. Missing measurements, unknown outcomes and out-of-scope successes (every touched file excluded) produce bounds, not invented scores.
python -m parsimony.scoring score examples/ten-model-score-panel.json \
examples/ten-model-results.jsonl --output /tmp/parsimony-scores.json
python -m parsimony.sensitivity examples/ten-model-score-panel.json \
examples/ten-model-results.jsonl --output /tmp/sensitivity.json
sensitivity runs a paired-task bootstrap and a grid over net weight, failure cap and a net_floor=0 anti-deletion variant. It covers neither panel composition nor task-selection bias.
Freeze the task population before looking at candidate scores:
# Commit analyzer changes first; freeze requires a clean checkout unless --analyzer-commit is given.
python -m parsimony.release freeze verified.jsonl --name verified-500-beta-v1 --output population.json
python -m parsimony analyze SUBMISSION --dataset verified.jsonl --ref EXPERIMENTS_COMMIT \
--include-failed --output all-results.jsonl
python -m parsimony.release audit population.json all-results.jsonl \
--dataset verified.jsonl --output coverage.json
The manifest pins dataset bytes, task IDs/base commits, Python version and analyzer commit. audit checks records against it: population, duplicates, base commits, resolve totals and the analyzer_commit every record carries since 0.4.0. It reports coverage, statuses, exclusions, zero-footprint, value-only, out-of-scope, lexical and approximate records. This is coverage reporting, not authenticity certification. An official score additionally needs a preregistered, deduplicated successful-reference panel covering every frozen task.
Legacy layout. Predictions come from the public swe-bench-submissions S3 bucket (verified/<submission>/all_preds.jsonl), and results/results.json from SWE-bench/experiments on GitHub. Current mini-SWE-agent layout (used on 404): per_instance_details.json supplies per-task booleans, and patches come from logs/<task>/patch.diff via metadata.yaml. Unsupported layouts fail explicitly. For custom or local artifacts, write a JSON manifest:
{"agent": "unique-agent-name", "submission_url": "https://example.org/submission",
"prediction_url": "all_preds.jsonl", "results_url": "results.json"}
python -m parsimony analyze --manifest submission.json --dataset verified.jsonl --output results.jsonl
Mere absence from resolved is never treated as failure. With --include-failed, failures must come from explicit evidence:
resolved: false per instance.results.json has no failure list) use per-task logs/<task>/report.json with resolved: false and an applied patch.Missing logs or reports remain unknown, and a warning is printed when a submission publishes no explicit failures.
--ref COMMIT pins GitHub results (S3 is not versioned by it). Records keep SHA256 hashes of predictions, results and each patch, artifact URLs, base commit, reference patch hash, analyzer version/commit/source hash and Python version. Downloads are cached atomically by URL under .parsimony-cache/ (--cache PATH goes before the subcommand). Cached URLs are never refreshed, so use a new cache for mutable upstream changes. Keep the metadata JSONL and cache alongside results for reproducibility. To share exactly the bytes a result set depends on, pack a verified snapshot:
python -m parsimony.snapshot create examples/beta-500-v4/*-results.jsonl --output cache-v4.tar.gz
python -m parsimony.snapshot restore cache-v4.tar.gz --cache .parsimony-cache # checks every SHA256 first
Current website ranking: lowest mean net coding units added first, by default across measured in-scope solved attempts (Count attempts: Solved only; All measured, successful and failed, is selectable), with equal 1/N weight for each counted attempt, without correctness weighting or passing-reference selection. Missing measurements are excluded, never zero-filled. Footprint values are raw mean coding units, not percentages; Solved % is upstream resolved / full frozen population. Columns are Rank, Model, Net units added (mean), Net units added over solved attempts only (mean), upstream Solved %, and Measured eligible/population; any numeric column can be sorted, and rank stays on the all-attempt mean. Equal means tie and models with no measurements stay unranked. Partial coverage can bias the order; this is smallest measured footprint, not best coding ability. Failed no-ops and large deletions can rank first, and a few very large failed deletions can dominate a mean (on Verified, the #1 model's mean is −244 against +10 over solved attempts). A 10% trimmed mean was used briefly on 2026-10-01 and removed at the owner's request. The historical 80/20 scores, CI and score ranks remain available only as explicitly labelled optional archived diagnostics; they do not determine website rank.
python -m parsimony.site PANEL RECORDS... --output site/index.html renders one self-contained page offline from a frozen panel and measured JSONL. Each page has:
--external, see parsimony/external.py). That index is a model-level score, not a result on the board's tasks; it is matched only for the same model and effort (weaker matches disclosed on hover), unmatched configurations have no point, and it never affects rank. Solved %, the AA Coding Index and the solved-only mean are also selectable. A Chart picker also offers a bar view of mean net units added only (same company colours and fading; ?chart=bar links straight to it) and a Show self-run checkbox that removes self-run configurations from the chart, bars and table (?selfrun=0); axis ticks sit at round values inside the data-fitted range, with any self-run configurations in a separate group below because they cover only a task subset. The DeepSWE Python page also shows self-run configurations (--self-run, see examples/self-run): newer models run by the owner through pi or Claude Code on the first 3–10 tasks, measured with the board's analyzer, not graded. They are faded on the chart, labelled self-run on hover, listed in grey rows and never ranked, and appear only in the all-tasks view. Numeric axes fit the visible points with 5% padding. In All tasks only, Gemini 3.1 Pro (including Preview and effort variants) is excluded from numeric-axis fitting when at least two other points have finite values on that axis and exclusion changes the fit; Gemini 3.1 Professional and Gemini 3.1 Pro Plus are not excluded. Solved normally stays at 0–100%; when this exclusion changes its fit, it uses the other points' 5%-padded range bounded to 0–100%. Coverage stays fixed at 0–100%, and task-view scaling is unchanged. Points outside fitted axes are extrapolated at their true coordinates using the same linear scales, never clamped or replaced with edge markers; labels and hover disclose this, and hover details and the table retain actual values. Data and ranks are unchanged; there is no Pareto overlay.Each board has a Count attempts: All measured / Solved only selector. Solved only is the default. It ranks by mean net units over measured, in-scope upstream successes and updates footprint charts consistently; failed and unknown-outcome attempts are excluded from task views. Measured then shows measured solved / upstream solved attempts, including repeated attempts. Models without measured successes remain unranked and absent from charts; ungraded self-runs are hidden. The second footprint column shows the alternative mean. Upstream Solved %, external indices and archived score diagnostics remain unchanged. Link to the alternative with ?attempts=all (combine with &chart=bar for bars). Solved-only means still compare different task mixes, not a shared-solved cohort, and benchmark success does not establish maintainability.
Visible copy stays compact, with detailed caveats and archived-score explanations collapsed under How to read this. Pages are always light mode and show an instant tooltip with the model name and both selected axis names and values, plus the task outcome in task view. The archived 80/20 Score, its bootstrap 95% CI and rank ranges (--sensitivity) are available only as labelled optional graph metrics. They never affect the net ranking, and the CI never affects Score.
| Page | Data | Build flag |
|---|---|---|
site/index.html (main) | DeepSWE Python, 26 models | --benchmark deepswe |
site/javascript.html, typescript.html, go.html | DeepSWE JavaScript, TypeScript, Go v2; separate pinned tracks with explicit coverage limits | --benchmark deepswe |
site/verified.html | SWE-bench Verified, 34 configurations | --benchmark verified |
site/live.html | Live Lite Python: DeepSeek V4.1 Flash, GPT-5.6 Sol, Claude Opus 4.8 and GPT-5.5 / agav0.2.0-beta.2 as source-declared model + agent configurations on all 300 tasks | --benchmark live |
--nav LABEL=URL links the boards. All pages are served at parsimony.lasu.dev (Cloudflare Pages, output directory site). Edit parsimony/template.html for layout and copy, then rebuild all six pages (HANDOFF.md has the exact commands).
Every website page includes a local JSON importer near the bottom. Explore any benchmark with known code amounts—lines, tokens, bytes or your own defined units—without running the analyzer. Download the example, edit it and open it in the browser. Imports stay local, are labeled unverified and never mix with published boards. See the format and public contribution guide.
See CONTRIBUTING.md. python -m parsimony.contribute export turns existing JSONL into a checksummed bundle under submissions/. PR checks validate it offline. contribute verify (also a manual CI job) re-downloads recorded patches, checks hashes and re-measures them.
| Example | Analyzer | What it shows |
|---|---|---|
| deepswe-python | 0.5.2-beta | 26 current models (2026) × 34 DeepSWE Python tasks × 4 attempts, one agent (mini-SWE-agent); imported with python -m parsimony.deepswe (the website's main board) |
| deepswe-javascript | 0.7.0-beta | 26 models × 5 JS-labelled tasks × 4 attempts; all 5 tasks calibratable; official TypeScript parser, script kind by file extension |
| deepswe-typescript | 0.7.0-beta | 26 models × 35 TS-labelled tasks × 4 attempts; official TypeScript parser; 33 tasks calibratable (5 analysis errors in 3,640 records), two upstream language-label mismatches documented |
| deepswe-go-v2 | 0.8.0-beta | 26 models × 34 Go tasks × 4 attempts; corrected grammar/EOF policy, 3,508 eligible footprints and one genuine syntax error; all 34 tasks calibratable; large scalar files in a checksummed release asset |
| deepswe-go | 0.6.0-beta | Historical Go v1 cohort, retained unchanged; superseded by v2 |
| mini-swe-agent-500 | 0.5.2-beta | 34 configurations × all 500 tasks with failures, mini-SWE-agent v0.0.0–v2.4.2; Gemini 3.5 Flash added with 441 measured attempts and 59 explicit no-generation outcomes; frozen population, archived score diagnostics and agent-version checks |
| livecodebench-pilot | 0.7.0-beta units, separate complete-file scope | NONPUBLISHED fresh-code pilot: 18 configurations × 1,055 retained Python tasks; 17,353 measured attempts, fixed sample index 0, explicit partial-export/unknown/missing/failed states; original six snapshots preserved; provenance release review pending |
| ten-model-500 | 0.5.0-beta | Ten models (plus Claude Opus 4.5) × all 500 tasks, mini-SWE-agent v2.0.0 only; superseded as the website's data |
| beta-500-v5 | 0.5.0-beta | Two complete 500-task cohorts in coding units; units vs tokens, coverage audit, fresh-artifact recheck |
| beta-500-v4 | 0.4.0-beta | Two complete 500-task cohorts in tokens (superseded by v5) |
| beta-500-v3 | 0.3.1-beta | Two complete 500-task cohorts; coverage audit (superseded by v4) |
| beta-500-v2 investigation | 0.3.0-beta | Metric blind spots fixed in 0.3.1 |
| beta-500 | 0.2.0-beta | First coverage audit (exclusion defect) |
ten-model report, ten-model-*.json | 0.5.0-beta | 10 models × 10 shared-success tasks; pipeline demo (superseded by ten-model-500) |
smoke-results.jsonl | 0.5.0-beta | Live-artifact smoke test, legacy layout (--limit 5, experiments 40f164d) |
The smoke and ten-model samples were regenerated with 0.5.0 (python -m examples.run_ten_models for the latter). Earlier versions are in git history.
See the repository audit and release-readiness review for engineering fixes, validation commands and outstanding release gates, and the browser/accessibility audit for tested behavior and remaining gaps. These audits are not independent benchmark certification or an accessibility-conformance claim.
Code footprint is not technical debt. Small code can be cryptic, incorrect beyond the benchmark tests, insecure or hard to maintain. Larger changes may add valuable validation. Human patches are a baseline, not an optimum. Net-weighted scores reward deletion, and SWE-bench tests do not protect untested code, so check the net_floor sensitivity variant.
The existing Python boards measure Python only. Optional JavaScript/TypeScript and Go tracks (introduced in analyzer 0.6.0; JavaScript/TypeScript moved to the official TypeScript parser in 0.7.0, Go to a versioned corrected grammar/EOF policy in 0.8.0) are kept separate from Python and each other; raw counts are not cross-language comparable. Scope is unified text diffs only: binary/rename-only diffs, quoted paths, malformed hunk headers and repeated sections for one implementation file are unsupported (recorded as errors, never scored). There is no call-graph, runtime, maintainability or behavioral-equivalence modeling. Path and generated-file filters are heuristic. Interpreter tokenizer/AST changes (notably f-strings) change results. Coding units measure size and nesting, not readability: a test-specific hardcoded branch can cost fewer units than a general fix.
python -m parsimony.stability): weights and cap never change a rank; most neighbouring models are statistically tied, and the agent version alone moves a model by up to 5.6 points.Measures how much code AI coding agents add, from patches benchmarks already publish
See the codeAmong agents that successfully solve the same SWE-bench issue, which leave the smallest code footprint?
Parsimony imports public SWE-bench Verified predictions and published evaluation results, statically measures their Python changes, and compares successful solutions. It makes no LLM API calls, runs no SWE-bench reruns, installs nothing from target repositories and never executes submitted code.
Status: beta / research prototype. No official cross-model ranking or validated full-benchmark score exists. Everything in
examples/is exploratory and must not be read as a model recommendation. Analyzer0.5.0-betareplaced lexical tokens with coding units (AST elements) as the primary metric (see the changelog). The current two-submission 500-task audit uses it. Older audits are kept for history and are not comparable.
Python 3.12+, no runtime dependencies for Python analysis. Optional tracks: JavaScript/TypeScript use Node.js and the official TypeScript parser (npm ci installs the pinned typescript), Go uses pip install '.[languages]' (the current checksum-pinned grammar builds from source, requiring a C compiler and Python development headers); see language tracks for pinned parsers, scope and reproducible commands. Analyzer 0.8 introduced a versioned Go grammar/EOF fix and 0.9 rejects malformed hunk headers and duplicate file sections instead of skipping or double-counting them; published historical cohorts keep their recorded analyzer identities. Run from this checkout (pip install -e . is optional). Measurements depend on the interpreter's tokenizer, so use one pinned Python version for anything you compare.
# Metadata, base commits and human patches for all 500 Verified tasks.
python -m parsimony dataset --output verified.jsonl
# Analyze five successful tasks per submission (alphabetical, NOT a representative sample).
python -m parsimony analyze \
20250522_sweagent_claude-4-sonnet-20250514 \
20250225_sweagent_claude-3-7-sonnet \
--dataset verified.jsonl --limit 5 --output results.jsonl
# Compare only tasks solved AND analyzed by every selected agent.
python -m parsimony leaderboard results.jsonl --shared > leaderboard.json
python -m unittest discover -s tests -v
Useful analyze options:
--limit N only limits analysis attempts. It never changes the resolve-rate denominator.--task TASK_ID (repeatable) analyzes a chosen cohort while keeping all 500 records.--include-failed also measures explicitly failed patches (see failed patches).--resume appends missing records to an interrupted full single-submission run and retries fetch_error records. It verifies agent, results hash, ref and analyzer/Python versions first.--patch-only gives hunk-only estimates without fetching sources. These are a separate, less reliable mode that is never pooled with full-file results.Output has one record per agent/task, including failures, unavailable analyses and skipped tasks. leaderboard rejects duplicate agent/task records. --agent NAME selects agents.
base_commit, and the patch is applied in memory with strict position/context validation. Unapplicable patches are recorded as errors, never scored as zero. Network failures are recorded as retryable fetch_error.ast (docstrings removed) and walked in source order. A unit is one syntactic element: a statement (if, return, assignment, def), an expression (call, attribute access, arithmetic or boolean operation), each comparison, a name or a literal. Each statement block also ends with one EndBlock unit, so nesting and moving code into or out of a block count. Punctuation, brackets, commas, load/store markers, comments, formatting and name length are not units: if x.count(y) > 0: foo(a, b) is 12 units. Units are unknown (null), never zero, when a file does not parse on both sides (lexical_files).approximate_files).net_units = added − deleted, churn = added + deleted. Negative net is genuine shrinking. A renamed name or changed literal is one changed unit; the structural_churn diagnostic ignores identifier/literal values. The pre-0.5 metric, normalized lexical tokens (net_tokens, token_churn), remains a diagnostic. files_changed counts implementation files whose normalized code differs..py implementation files count. Excluded: test/doc/example/benchmark directories, test filenames, setup.py/conftest.py, generated files (a header comment in the base commit), protobuf output, migration scripts, vendored and build output. Django's db/migrations/ and test/ framework packages count as implementation. Every record lists touched_files and excluded_files. See implementation() for the exact rules.patch (not test_patch) is measured identically. model_human_ratio = model churn / human churn, or null when the human churn is zero.leaderboard reports medians (net, churn, human ratio, files, AST and complexity deltas), sample counts and resolve rate, sorted by median net units. --shared uses the intersection of resolved and analyzable tasks, which avoids task-mix confounding but can favor easy tasks.
See the scoring specification. Per-task percentiles against a frozen reference panel are blended 80/20 and averaged with equal task weights. Successes score 1 to 100. Explicitly failed attempts get a bounded nonpositive growth/churn penalty down to −25. Missing measurements, unknown outcomes and out-of-scope successes (every touched file excluded) produce bounds, not invented scores.
python -m parsimony.scoring score examples/ten-model-score-panel.json \
examples/ten-model-results.jsonl --output /tmp/parsimony-scores.json
python -m parsimony.sensitivity examples/ten-model-score-panel.json \
examples/ten-model-results.jsonl --output /tmp/sensitivity.json
sensitivity runs a paired-task bootstrap and a grid over net weight, failure cap and a net_floor=0 anti-deletion variant. It covers neither panel composition nor task-selection bias.
Freeze the task population before looking at candidate scores:
# Commit analyzer changes first; freeze requires a clean checkout unless --analyzer-commit is given.
python -m parsimony.release freeze verified.jsonl --name verified-500-beta-v1 --output population.json
python -m parsimony analyze SUBMISSION --dataset verified.jsonl --ref EXPERIMENTS_COMMIT \
--include-failed --output all-results.jsonl
python -m parsimony.release audit population.json all-results.jsonl \
--dataset verified.jsonl --output coverage.json
The manifest pins dataset bytes, task IDs/base commits, Python version and analyzer commit. audit checks records against it: population, duplicates, base commits, resolve totals and the analyzer_commit every record carries since 0.4.0. It reports coverage, statuses, exclusions, zero-footprint, value-only, out-of-scope, lexical and approximate records. This is coverage reporting, not authenticity certification. An official score additionally needs a preregistered, deduplicated successful-reference panel covering every frozen task.
Legacy layout. Predictions come from the public swe-bench-submissions S3 bucket (verified/<submission>/all_preds.jsonl), and results/results.json from SWE-bench/experiments on GitHub. Current mini-SWE-agent layout (used on 404): per_instance_details.json supplies per-task booleans, and patches come from logs/<task>/patch.diff via metadata.yaml. Unsupported layouts fail explicitly. For custom or local artifacts, write a JSON manifest:
{"agent": "unique-agent-name", "submission_url": "https://example.org/submission",
"prediction_url": "all_preds.jsonl", "results_url": "results.json"}
python -m parsimony analyze --manifest submission.json --dataset verified.jsonl --output results.jsonl
Mere absence from resolved is never treated as failure. With --include-failed, failures must come from explicit evidence:
resolved: false per instance.results.json has no failure list) use per-task logs/<task>/report.json with resolved: false and an applied patch.Missing logs or reports remain unknown, and a warning is printed when a submission publishes no explicit failures.
--ref COMMIT pins GitHub results (S3 is not versioned by it). Records keep SHA256 hashes of predictions, results and each patch, artifact URLs, base commit, reference patch hash, analyzer version/commit/source hash and Python version. Downloads are cached atomically by URL under .parsimony-cache/ (--cache PATH goes before the subcommand). Cached URLs are never refreshed, so use a new cache for mutable upstream changes. Keep the metadata JSONL and cache alongside results for reproducibility. To share exactly the bytes a result set depends on, pack a verified snapshot:
python -m parsimony.snapshot create examples/beta-500-v4/*-results.jsonl --output cache-v4.tar.gz
python -m parsimony.snapshot restore cache-v4.tar.gz --cache .parsimony-cache # checks every SHA256 first
Current website ranking: lowest mean net coding units added first, by default across measured in-scope solved attempts (Count attempts: Solved only; All measured, successful and failed, is selectable), with equal 1/N weight for each counted attempt, without correctness weighting or passing-reference selection. Missing measurements are excluded, never zero-filled. Footprint values are raw mean coding units, not percentages; Solved % is upstream resolved / full frozen population. Columns are Rank, Model, Net units added (mean), Net units added over solved attempts only (mean), upstream Solved %, and Measured eligible/population; any numeric column can be sorted, and rank stays on the all-attempt mean. Equal means tie and models with no measurements stay unranked. Partial coverage can bias the order; this is smallest measured footprint, not best coding ability. Failed no-ops and large deletions can rank first, and a few very large failed deletions can dominate a mean (on Verified, the #1 model's mean is −244 against +10 over solved attempts). A 10% trimmed mean was used briefly on 2026-10-01 and removed at the owner's request. The historical 80/20 scores, CI and score ranks remain available only as explicitly labelled optional archived diagnostics; they do not determine website rank.
python -m parsimony.site PANEL RECORDS... --output site/index.html renders one self-contained page offline from a frozen panel and measured JSONL. Each page has:
--external, see parsimony/external.py). That index is a model-level score, not a result on the board's tasks; it is matched only for the same model and effort (weaker matches disclosed on hover), unmatched configurations have no point, and it never affects rank. Solved %, the AA Coding Index and the solved-only mean are also selectable. A Chart picker also offers a bar view of mean net units added only (same company colours and fading; ?chart=bar links straight to it) and a Show self-run checkbox that removes self-run configurations from the chart, bars and table (?selfrun=0); axis ticks sit at round values inside the data-fitted range, with any self-run configurations in a separate group below because they cover only a task subset. The DeepSWE Python page also shows self-run configurations (--self-run, see examples/self-run): newer models run by the owner through pi or Claude Code on the first 3–10 tasks, measured with the board's analyzer, not graded. They are faded on the chart, labelled self-run on hover, listed in grey rows and never ranked, and appear only in the all-tasks view. Numeric axes fit the visible points with 5% padding. In All tasks only, Gemini 3.1 Pro (including Preview and effort variants) is excluded from numeric-axis fitting when at least two other points have finite values on that axis and exclusion changes the fit; Gemini 3.1 Professional and Gemini 3.1 Pro Plus are not excluded. Solved normally stays at 0–100%; when this exclusion changes its fit, it uses the other points' 5%-padded range bounded to 0–100%. Coverage stays fixed at 0–100%, and task-view scaling is unchanged. Points outside fitted axes are extrapolated at their true coordinates using the same linear scales, never clamped or replaced with edge markers; labels and hover disclose this, and hover details and the table retain actual values. Data and ranks are unchanged; there is no Pareto overlay.Each board has a Count attempts: All measured / Solved only selector. Solved only is the default. It ranks by mean net units over measured, in-scope upstream successes and updates footprint charts consistently; failed and unknown-outcome attempts are excluded from task views. Measured then shows measured solved / upstream solved attempts, including repeated attempts. Models without measured successes remain unranked and absent from charts; ungraded self-runs are hidden. The second footprint column shows the alternative mean. Upstream Solved %, external indices and archived score diagnostics remain unchanged. Link to the alternative with ?attempts=all (combine with &chart=bar for bars). Solved-only means still compare different task mixes, not a shared-solved cohort, and benchmark success does not establish maintainability.
Visible copy stays compact, with detailed caveats and archived-score explanations collapsed under How to read this. Pages are always light mode and show an instant tooltip with the model name and both selected axis names and values, plus the task outcome in task view. The archived 80/20 Score, its bootstrap 95% CI and rank ranges (--sensitivity) are available only as labelled optional graph metrics. They never affect the net ranking, and the CI never affects Score.
| Page | Data | Build flag |
|---|---|---|
site/index.html (main) | DeepSWE Python, 26 models | --benchmark deepswe |
site/javascript.html, typescript.html, go.html | DeepSWE JavaScript, TypeScript, Go v2; separate pinned tracks with explicit coverage limits | --benchmark deepswe |
site/verified.html | SWE-bench Verified, 34 configurations | --benchmark verified |
site/live.html | Live Lite Python: DeepSeek V4.1 Flash, GPT-5.6 Sol, Claude Opus 4.8 and GPT-5.5 / agav0.2.0-beta.2 as source-declared model + agent configurations on all 300 tasks | --benchmark live |
--nav LABEL=URL links the boards. All pages are served at parsimony.lasu.dev (Cloudflare Pages, output directory site). Edit parsimony/template.html for layout and copy, then rebuild all six pages (HANDOFF.md has the exact commands).
Every website page includes a local JSON importer near the bottom. Explore any benchmark with known code amounts—lines, tokens, bytes or your own defined units—without running the analyzer. Download the example, edit it and open it in the browser. Imports stay local, are labeled unverified and never mix with published boards. See the format and public contribution guide.
See CONTRIBUTING.md. python -m parsimony.contribute export turns existing JSONL into a checksummed bundle under submissions/. PR checks validate it offline. contribute verify (also a manual CI job) re-downloads recorded patches, checks hashes and re-measures them.
| Example | Analyzer | What it shows |
|---|---|---|
| deepswe-python | 0.5.2-beta | 26 current models (2026) × 34 DeepSWE Python tasks × 4 attempts, one agent (mini-SWE-agent); imported with python -m parsimony.deepswe (the website's main board) |
| deepswe-javascript | 0.7.0-beta | 26 models × 5 JS-labelled tasks × 4 attempts; all 5 tasks calibratable; official TypeScript parser, script kind by file extension |
| deepswe-typescript | 0.7.0-beta | 26 models × 35 TS-labelled tasks × 4 attempts; official TypeScript parser; 33 tasks calibratable (5 analysis errors in 3,640 records), two upstream language-label mismatches documented |
| deepswe-go-v2 | 0.8.0-beta | 26 models × 34 Go tasks × 4 attempts; corrected grammar/EOF policy, 3,508 eligible footprints and one genuine syntax error; all 34 tasks calibratable; large scalar files in a checksummed release asset |
| deepswe-go | 0.6.0-beta | Historical Go v1 cohort, retained unchanged; superseded by v2 |
| mini-swe-agent-500 | 0.5.2-beta | 34 configurations × all 500 tasks with failures, mini-SWE-agent v0.0.0–v2.4.2; Gemini 3.5 Flash added with 441 measured attempts and 59 explicit no-generation outcomes; frozen population, archived score diagnostics and agent-version checks |
| livecodebench-pilot | 0.7.0-beta units, separate complete-file scope | NONPUBLISHED fresh-code pilot: 18 configurations × 1,055 retained Python tasks; 17,353 measured attempts, fixed sample index 0, explicit partial-export/unknown/missing/failed states; original six snapshots preserved; provenance release review pending |
| ten-model-500 | 0.5.0-beta | Ten models (plus Claude Opus 4.5) × all 500 tasks, mini-SWE-agent v2.0.0 only; superseded as the website's data |
| beta-500-v5 | 0.5.0-beta | Two complete 500-task cohorts in coding units; units vs tokens, coverage audit, fresh-artifact recheck |
| beta-500-v4 | 0.4.0-beta | Two complete 500-task cohorts in tokens (superseded by v5) |
| beta-500-v3 | 0.3.1-beta | Two complete 500-task cohorts; coverage audit (superseded by v4) |
| beta-500-v2 investigation | 0.3.0-beta | Metric blind spots fixed in 0.3.1 |
| beta-500 | 0.2.0-beta | First coverage audit (exclusion defect) |
ten-model report, ten-model-*.json | 0.5.0-beta | 10 models × 10 shared-success tasks; pipeline demo (superseded by ten-model-500) |
smoke-results.jsonl | 0.5.0-beta | Live-artifact smoke test, legacy layout (--limit 5, experiments 40f164d) |
The smoke and ten-model samples were regenerated with 0.5.0 (python -m examples.run_ten_models for the latter). Earlier versions are in git history.
See the repository audit and release-readiness review for engineering fixes, validation commands and outstanding release gates, and the browser/accessibility audit for tested behavior and remaining gaps. These audits are not independent benchmark certification or an accessibility-conformance claim.
Code footprint is not technical debt. Small code can be cryptic, incorrect beyond the benchmark tests, insecure or hard to maintain. Larger changes may add valuable validation. Human patches are a baseline, not an optimum. Net-weighted scores reward deletion, and SWE-bench tests do not protect untested code, so check the net_floor sensitivity variant.
The existing Python boards measure Python only. Optional JavaScript/TypeScript and Go tracks (introduced in analyzer 0.6.0; JavaScript/TypeScript moved to the official TypeScript parser in 0.7.0, Go to a versioned corrected grammar/EOF policy in 0.8.0) are kept separate from Python and each other; raw counts are not cross-language comparable. Scope is unified text diffs only: binary/rename-only diffs, quoted paths, malformed hunk headers and repeated sections for one implementation file are unsupported (recorded as errors, never scored). There is no call-graph, runtime, maintainability or behavioral-equivalence modeling. Path and generated-file filters are heuristic. Interpreter tokenizer/AST changes (notably f-strings) change results. Coding units measure size and nesting, not readability: a test-specific hardcoded branch can cost fewer units than a general fix.
python -m parsimony.stability): weights and cap never change a rank; most neighbouring models are statistically tied, and the agent version alone moves a model by up to 5.6 points.