<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adrian Cockcroft</title>
    <description>The latest articles on DEV Community by Adrian Cockcroft (@adrianco_54).</description>
    <link>https://dev.to/adrianco_54</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F454486%2Ff5cb11a3-434b-4151-8aa8-4f1b2804bcae.png</url>
      <title>DEV Community: Adrian Cockcroft</title>
      <link>https://dev.to/adrianco_54</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adrianco_54"/>
    <language>en</language>
    <item>
      <title>Retort Thinking Level Results: What Opus Actually Does With the Extra Time</title>
      <dc:creator>Adrian Cockcroft</dc:creator>
      <pubDate>Fri, 31 Jul 2026 15:59:03 +0000</pubDate>
      <link>https://dev.to/adrianco_54/retort-thinking-level-results-what-opus-actually-does-with-the-extra-time-55f7</link>
      <guid>https://dev.to/adrianco_54/retort-thinking-level-results-what-opus-actually-does-with-the-extra-time-55f7</guid>
      <description>&lt;p&gt;This is a snapshot of the analysis that is updated whenever new experiments warrant it at:&lt;br&gt;
&lt;a href="https://github.com/adrianco/retort/blob/main/levels-blog.md" rel="noopener noreferrer"&gt;https://github.com/adrianco/retort/blob/main/levels-blog.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Published 2026-07-31 · updated 2026-07-31 — Adrian Cockcroft&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--effort low|medium|high|xhigh|max&lt;/code&gt; is the newest and largest cost lever in retort, and the least understood. &lt;a href="//versions-blog.md"&gt;versions-blog.md&lt;/a&gt; established &lt;em&gt;that&lt;/em&gt; it costs; this page is about &lt;em&gt;what the model does&lt;/em&gt; with the time, read out of the archived agent logs rather than inferred from the totals.&lt;/p&gt;

&lt;p&gt;The short version: below the top of the dial Opus 5 &lt;strong&gt;writes more&lt;/strong&gt;. At the top it stops writing and starts &lt;strong&gt;revising&lt;/strong&gt; — re-reading its own code, re-running its own tests, editing what it already wrote. That switch is where the cost curve leaves the time curve, and on the routine task it buys nothing the gate can see.&lt;/p&gt;

&lt;p&gt;Data: &lt;code&gt;adrianco/experiment-55&lt;/code&gt;, Claude Opus 5 and GPT-5.6 Terra, python and go, five effort levels, 2 replicates on the routine task (bookshop) and 1 on the hard task (brazil). Every figure below is recomputed from the per-run databases and the archived &lt;code&gt;_agent_stdout.log&lt;/code&gt; files.&lt;/p&gt;




&lt;h2&gt;
  
  
  The dial, end to end
&lt;/h2&gt;

&lt;p&gt;Claude Opus 5 on the routine task, python, mean of 2 replicates per level:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;effort&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;wall&lt;/th&gt;
&lt;th&gt;cost&lt;/th&gt;
&lt;th&gt;turns&lt;/th&gt;
&lt;th&gt;tool calls&lt;/th&gt;
&lt;th&gt;tokens&lt;/th&gt;
&lt;th&gt;src lines&lt;/th&gt;
&lt;th&gt;tests&lt;/th&gt;
&lt;th&gt;&lt;code&gt;test_coverage&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;requirement_coverage&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;2.0 min&lt;/td&gt;
&lt;td&gt;$0.76&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;452,552&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.00&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;3.1 min&lt;/td&gt;
&lt;td&gt;$1.04&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;648,077&lt;/td&gt;
&lt;td&gt;219&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.00&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;5.9 min&lt;/td&gt;
&lt;td&gt;$1.68&lt;/td&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;1,083,234&lt;/td&gt;
&lt;td&gt;458&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.00&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xhigh&lt;/td&gt;
&lt;td&gt;11.9 min&lt;/td&gt;
&lt;td&gt;$2.55&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;1,714,098&lt;/td&gt;
&lt;td&gt;574&lt;/td&gt;
&lt;td&gt;51&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.00&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;max&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;35.1 min&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$19.21&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;175&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;220&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;15,814,628&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;944&lt;/td&gt;
&lt;td&gt;78&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.00&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Everything scales monotonically — time, cost, turns, tokens, lines, tests. The one column that never moves is the one the project scores on: &lt;strong&gt;&lt;code&gt;requirement_coverage&lt;/code&gt; is 1.00 at every level&lt;/strong&gt;. The task is fully implemented in two minutes for 76 cents, and it is still exactly fully implemented 33 minutes and $19 later.&lt;/p&gt;

&lt;p&gt;Note the curve shapes differ. Wall clock grows &lt;strong&gt;17×&lt;/strong&gt; from low to max; cost grows &lt;strong&gt;25×&lt;/strong&gt;; tokens grow &lt;strong&gt;35×&lt;/strong&gt;. Cost outruns time because the work per turn intensifies, not just the number of turns.&lt;/p&gt;




&lt;h2&gt;
  
  
  The behavioural switch: from writing to revising
&lt;/h2&gt;

&lt;p&gt;The totals don't say what changed. The tool mix does. Same runs, mean tool calls per run:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;effort&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Write&lt;/th&gt;
&lt;th&gt;Edit&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Edit:Write&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;Read&lt;/th&gt;
&lt;th&gt;Bash&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0.30&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;0.80&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0.24&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xhigh&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;0.33&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;max&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;64&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.43&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;36&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;86&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Through &lt;code&gt;xhigh&lt;/code&gt; the pattern is stable and unremarkable: Opus writes files, runs the tests a handful of times, and stops. Writes outnumber edits roughly 3:1. More effort simply means more of the same — &lt;code&gt;high&lt;/code&gt; writes 12 files where &lt;code&gt;low&lt;/code&gt; wrote 5.&lt;/p&gt;

&lt;p&gt;At &lt;code&gt;max&lt;/code&gt; the shape of the work changes. Edits outnumber writes &lt;strong&gt;2.4:1&lt;/strong&gt;, Reads jump &lt;strong&gt;18×&lt;/strong&gt; (2 → 36), and Bash calls jump &lt;strong&gt;6×&lt;/strong&gt; (14 → 86). It is no longer producing a solution; it is auditing one it already has — re-reading its own modules, re-running the suite, adjusting. Tool calls per turn also rise from ~0.95 (one action per turn, all the way up the dial) to &lt;strong&gt;2.02&lt;/strong&gt;, meaning it starts batching parallel actions.&lt;/p&gt;

&lt;p&gt;This is where the self-imposed extras appear, and &lt;em&gt;only&lt;/em&gt; here. Across the ten python runs, mutation testing, subagent delegation and a hand-written OpenAPI document occur exclusively in the two &lt;code&gt;max&lt;/code&gt; runs — never at &lt;code&gt;low&lt;/code&gt; through &lt;code&gt;xhigh&lt;/code&gt;. That matches what the &lt;a href="//tasks-blog.md"&gt;slowest passing run&lt;/a&gt; turned out to contain: a seven-module package, unprompted &lt;code&gt;ruff&lt;/code&gt; linting, and mutation testing, for a books CRUD API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The switch point tracks task difficulty, not the dial position.&lt;/strong&gt; On the hard task the same flip happens two levels earlier:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;brazil, python (n=1)&lt;/th&gt;
&lt;th&gt;wall&lt;/th&gt;
&lt;th&gt;cost&lt;/th&gt;
&lt;th&gt;turns&lt;/th&gt;
&lt;th&gt;Edit:Write&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;18.7 min&lt;/td&gt;
&lt;td&gt;$8.14&lt;/td&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;td&gt;0.93&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;25.9 min&lt;/td&gt;
&lt;td&gt;$13.94&lt;/td&gt;
&lt;td&gt;126&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.91&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;59.9 min&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$45.34&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;231&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.11&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On bookshop, Opus revises only at &lt;code&gt;max&lt;/code&gt;. On brazil it is already revising at &lt;code&gt;medium&lt;/code&gt;. The dial doesn't set the behaviour directly — it sets a budget, and the model switches into revision mode once it has spent enough to have something worth revising.&lt;/p&gt;




&lt;h2&gt;
  
  
  Does any of it show up in a measured response?
&lt;/h2&gt;

&lt;p&gt;Only where there was headroom. Compare the same dial in go, where the test-coverage scorer is not already pinned at the ceiling:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;effort&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;python &lt;code&gt;test_coverage&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;go &lt;code&gt;test_coverage&lt;/code&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;td&gt;0.73&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;td&gt;0.74&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;td&gt;0.76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xhigh&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.87&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;max&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.88&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Python starts at 0.98 and has nowhere to go — the extra 33 minutes move it 0.01. Go starts at 0.73 and gains &lt;strong&gt;15 points&lt;/strong&gt;, a real and monotonic improvement. So the honest answer is not "effort buys nothing", it is: &lt;strong&gt;effort buys coverage exactly where coverage is missing, and nothing where it isn't.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Everything else is flat or worse. &lt;code&gt;requirement_coverage&lt;/code&gt; is 1.00 at all ten cells. Maintainability does not improve with effort — on python it reads 0.96 at &lt;code&gt;low&lt;/code&gt; and 0.89 at &lt;code&gt;max&lt;/code&gt;, because 944 lines are simply more to maintain than 192.&lt;/p&gt;




&lt;h2&gt;
  
  
  The same five names mean different things per vendor
&lt;/h2&gt;

&lt;p&gt;Run the identical sweep on GPT-5.6 Terra and the dial barely registers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;effort&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Terra cost&lt;/th&gt;
&lt;th&gt;Terra tokens&lt;/th&gt;
&lt;th&gt;Opus 5 cost&lt;/th&gt;
&lt;th&gt;Opus 5 tokens&lt;/th&gt;
&lt;th&gt;cost ratio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;$0.16&lt;/td&gt;
&lt;td&gt;182,387&lt;/td&gt;
&lt;td&gt;$0.76&lt;/td&gt;
&lt;td&gt;452,552&lt;/td&gt;
&lt;td&gt;5×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;$0.12&lt;/td&gt;
&lt;td&gt;118,504&lt;/td&gt;
&lt;td&gt;$1.04&lt;/td&gt;
&lt;td&gt;648,077&lt;/td&gt;
&lt;td&gt;9×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;$0.16&lt;/td&gt;
&lt;td&gt;165,724&lt;/td&gt;
&lt;td&gt;$1.68&lt;/td&gt;
&lt;td&gt;1,083,234&lt;/td&gt;
&lt;td&gt;11×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xhigh&lt;/td&gt;
&lt;td&gt;$0.17&lt;/td&gt;
&lt;td&gt;157,287&lt;/td&gt;
&lt;td&gt;$2.55&lt;/td&gt;
&lt;td&gt;1,714,098&lt;/td&gt;
&lt;td&gt;15×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;max&lt;/td&gt;
&lt;td&gt;$0.29&lt;/td&gt;
&lt;td&gt;278,882&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$19.21&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;15,814,628&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;67×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Terra's whole range is $0.12–$0.29 — its &lt;code&gt;max&lt;/code&gt; costs 2.4× its &lt;code&gt;medium&lt;/code&gt;. Opus 5's &lt;code&gt;max&lt;/code&gt; costs 25× its &lt;code&gt;low&lt;/code&gt;. Both score 1.00 in all ten cells.&lt;/p&gt;

&lt;p&gt;The two CLIs accept the same five words, which makes the factor look comparable. It isn't: &lt;code&gt;max&lt;/code&gt; is a mild nudge on one vendor and a regime change on the other. Any cross-vendor comparison has to pin the &lt;em&gt;level&lt;/em&gt; explicitly and still report cost, because matching the name does not match the behaviour.&lt;/p&gt;




&lt;h2&gt;
  
  
  What to actually do with the dial
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;On routine work, leave it at &lt;code&gt;low&lt;/code&gt;.&lt;/strong&gt; Ten of ten cells scored 1.00; &lt;code&gt;low&lt;/code&gt; did it in 2 minutes for 76 cents. Everything above it is paying for revision of an already-correct answer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Raise it when a measured response has headroom&lt;/strong&gt; — the go coverage gain is real. That is a reason to go to &lt;code&gt;xhigh&lt;/code&gt;, and the gain is already there at &lt;code&gt;xhigh&lt;/code&gt; rather than &lt;code&gt;max&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat &lt;code&gt;max&lt;/code&gt; as a different mode, not one more notch.&lt;/strong&gt; It is where the model starts auditing itself, where cost goes super-linear, and where it does work nobody asked for.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;n is small.&lt;/strong&gt; Two replicates per bookshop cell, one per brazil cell. The go &lt;code&gt;max&lt;/code&gt; row is n=1 (13.3 min, $4.21) and lands &lt;em&gt;below&lt;/em&gt; its own &lt;code&gt;xhigh&lt;/code&gt; (18.4 min, $6.70) — almost certainly the missing replicate rather than a real inversion, so the go &lt;code&gt;max&lt;/code&gt; figures are not used for any claim above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The brazil sweep is incomplete.&lt;/strong&gt; Opus 5 ran &lt;code&gt;low&lt;/code&gt;/&lt;code&gt;medium&lt;/code&gt;/&lt;code&gt;high&lt;/code&gt; before the account hit its usage limit; &lt;code&gt;xhigh&lt;/code&gt; and &lt;code&gt;max&lt;/code&gt; never ran. The brazil table is the shape of the first three levels only, and the two most expensive cells are missing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One measurement trap, recorded because it bit this analysis.&lt;/strong&gt; A Claude Code JSONL log can contain &lt;strong&gt;more than one &lt;code&gt;result&lt;/code&gt; record&lt;/strong&gt; — 2 of the 24 Opus runs here do. Reading &lt;code&gt;num_turns&lt;/code&gt; from the last record alone undercounts: the 45.6-minute &lt;code&gt;max&lt;/code&gt; run reports 94 that way when the true total is 116 + 94 = &lt;strong&gt;210&lt;/strong&gt;. An earlier version of &lt;a href="//tasks-blog.md"&gt;tasks-blog.md&lt;/a&gt; and &lt;a href="//experiments-blog.md"&gt;experiments-blog.md&lt;/a&gt; published the 94; both are corrected. Directly counted &lt;code&gt;tool_use&lt;/code&gt; blocks (256 for that run) are the more reliable measure and are what the tool-mix table above uses.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
    </item>
    <item>
      <title>Retort - The Optimal AI Coding Stack</title>
      <dc:creator>Adrian Cockcroft</dc:creator>
      <pubDate>Thu, 30 Jul 2026 23:41:14 +0000</pubDate>
      <link>https://dev.to/adrianco_54/retort-the-optimal-ai-coding-stack-5005</link>
      <guid>https://dev.to/adrianco_54/retort-the-optimal-ai-coding-stack-5005</guid>
      <description>&lt;p&gt;This snapshot of the current optimal stack changes all the time as new experiments complete. If you disagree or have different configurations or models available, run your own experiments with Retort and send a pull request...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/adrianco/retort/blob/main/optimal-blog.md" rel="noopener noreferrer"&gt;https://github.com/adrianco/retort/blob/main/optimal-blog.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to consume the current recommendation directly by tooling there is also a json formatted file at &lt;a href="https://github.com/adrianco/retort/blob/main/optimal.json" rel="noopener noreferrer"&gt;https://github.com/adrianco/retort/blob/main/optimal.json&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Living document — last updated 2026-07-30 (first published 2026-07-14). This records **what to run today&lt;/em&gt;&lt;em&gt;: the leading stacks, and the exact configuration each one needs. It is not a history. Superseded stacks and rejected configurations are not discussed here; they are retired, and retirement is the point.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What this document is
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;stack&lt;/strong&gt; is the whole thing you actually deploy, not just a model:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;language × model × quantization × serving layer × agent × context engine × sampling × prompt&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Retort scores stacks on &lt;strong&gt;pass-proportion&lt;/strong&gt; — run a stack N times on a real task and count the fraction whose output &lt;em&gt;fully implements the spec&lt;/em&gt;: every requirement on a fixed checklist, tests that actually execute, verified by an independent evaluator. A run that misses one requirement is a failure, not a 0.9. Read it as &lt;em&gt;the probability that a single unattended run comes out completely correct.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That harsh bar is deliberate, because it is the number that decides whether you can let a stack work unattended.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lifecycle: how a stack gets here, and how it leaves
&lt;/h2&gt;

&lt;p&gt;This document is the human-readable view of a lifecycle the tool already runs. Each stage is a retort command, so entries here are &lt;em&gt;derived&lt;/em&gt;, not curated by taste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CANDIDATE ──► SCREENING ──► TRIAL ──► PRODUCTION ──► RETIRED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;th&gt;How it's decided&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Candidate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;a new model, agent or configuration appears&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;retort intake --factor model --level &amp;lt;new&amp;gt;&lt;/code&gt; augments the existing design rather than restarting it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Screening&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Resolution III — do its main effects matter at all?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;retort run --phase screening&lt;/code&gt; → &lt;code&gt;retort analyze&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Trial&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Resolution IV/V — interactions estimated&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;retort promote --from screening --to trial&lt;/code&gt; (gate: p-value)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Production&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;listed in this document&lt;/strong&gt; — the recommended stack for its niche&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;retort promote --to production&lt;/code&gt; (gate: posterior confidence); &lt;code&gt;retort maturity&lt;/code&gt; scores readiness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Retired&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;dominated on &lt;em&gt;every&lt;/em&gt; metric by a newer stack — removed, not demoted&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;retort report pareto&lt;/code&gt; identifies who is still non-dominated&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The gates are configuration, not opinion — they live in each &lt;code&gt;workspace.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;promotion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;screening_to_trial&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;p_value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;0.10&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;trial_to_production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;posterior_confidence&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;0.80&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;A stack earns a place here only by leading on an axis a developer actually chooses along&lt;/strong&gt; — a language, a task size, a cost or latency budget. Being new is not a qualification. When it leads on none, &lt;code&gt;retort report pareto&lt;/code&gt; shows it dominated and it comes out. The list stays short on purpose.&lt;/p&gt;

&lt;p&gt;Configurations that reliably degrade a stack are eliminated outright and recorded as &lt;strong&gt;forbidden settings&lt;/strong&gt; (below). New model releases — frontier and local — trigger a re-qualification pass, so this document is expected to churn.&lt;/p&gt;




&lt;h2&gt;
  
  
  Start here: the cheapest (model × thinking level) that clears each cell
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A stack is a model &lt;em&gt;and&lt;/em&gt; a thinking level.&lt;/strong&gt; Measured on one cell across four Claude versions × five effort levels, every one of the 21 combinations passed — and the bill spanned &lt;strong&gt;16×&lt;/strong&gt;, from \$0.42 to \$6.75, for identical output. The dial moves cost more than the version does, and it moves the result not at all. So the recommendation is a pair, never a model alone.&lt;/p&gt;

&lt;p&gt;The machine-readable form of the table below is committed at &lt;strong&gt;&lt;a href="//optimal.json"&gt;&lt;code&gt;optimal.json&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; (regenerate with &lt;code&gt;retort report optimal --routing-json optimal.json&lt;/code&gt;) so other tools — the metaharness router, CI, your own scripts — can consume the routing decision directly rather than scraping prose.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Routine → cloud&lt;/th&gt;
&lt;th&gt;pass&lt;/th&gt;
&lt;th&gt;$&lt;/th&gt;
&lt;th&gt;Routine → local&lt;/th&gt;
&lt;th&gt;Hard → cloud&lt;/th&gt;
&lt;th&gt;pass&lt;/th&gt;
&lt;th&gt;$&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;c&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Opus 4.8 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$1.28&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Fable 5 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$10.59&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;clojure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Opus 4.7 @ &lt;code&gt;default&lt;/code&gt; n=6
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$1.06&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Opus 5 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$2.55&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;cpp&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Opus 4.8 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$1.08&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Opus 5 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$17.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;csharp&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Opus 4.8 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$0.65&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Sonnet 5 @ &lt;code&gt;default&lt;/code&gt; n=3
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$9.96&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;elixir&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Opus 4.8 @ &lt;code&gt;default&lt;/code&gt; n=3
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$0.85&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Fable 5 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$13.21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;erlang&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Opus 4.8 @ &lt;code&gt;default&lt;/code&gt; n=3
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$1.35&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Fable 5 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$12.06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;go&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GPT-5.6 Luna @ &lt;code&gt;default&lt;/code&gt; n=3
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$0.08&lt;/td&gt;
&lt;td&gt;Qwen3-Coder-Next 80B @ &lt;code&gt;default&lt;/code&gt; n=3
&lt;/td&gt;
&lt;td&gt;Opus 4.8 @ &lt;code&gt;default&lt;/code&gt; n=6
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$5.30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;java&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Opus 4.7 @ &lt;code&gt;default&lt;/code&gt; n=6
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$0.92&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Fable 5 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$12.01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;objc&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Opus 4.8 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$1.52&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Fable 5 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$13.30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GPT-5.6 Luna @ &lt;code&gt;default&lt;/code&gt; n=3
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$0.06&lt;/td&gt;
&lt;td&gt;Qwen3-Coder-Next 80B @ &lt;code&gt;default&lt;/code&gt; n=3
&lt;/td&gt;
&lt;td&gt;Opus 4.7 @ &lt;code&gt;default&lt;/code&gt; n=3
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$4.64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;rust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Opus 4.8 @ &lt;code&gt;default&lt;/code&gt; n=6
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$0.71&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Fable 5 @ &lt;code&gt;default&lt;/code&gt; n=3
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$9.63&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;swift&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Opus 4.8 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$1.25&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Fable 5 @ &lt;code&gt;default&lt;/code&gt; n=1
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$9.24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;typescript&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Opus 4.8 @ &lt;code&gt;default&lt;/code&gt; n=7
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$0.65&lt;/td&gt;
&lt;td&gt;Qwen3-Coder-Next 80B @ &lt;code&gt;default&lt;/code&gt; n=3
&lt;/td&gt;
&lt;td&gt;Opus 4.7 @ &lt;code&gt;default&lt;/code&gt; n=3
&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;$4.14&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Reading the &lt;code&gt;effort&lt;/code&gt; column.&lt;/strong&gt; Almost every cell says &lt;code&gt;default&lt;/code&gt;, and that is an honest statement rather than a recommendation: &lt;strong&gt;thinking level has only ever been &lt;em&gt;varied&lt;/em&gt; on one cell&lt;/strong&gt; (python × bookshop, exp-49). Everywhere else the corpus has exactly one measured level, so the router reports the level those runs actually used and does not imply a comparison nobody made. Where the dial &lt;em&gt;was&lt;/em&gt; swept, the finding was consistent — &lt;code&gt;low&lt;/code&gt; cost ~1.6× less than the CLI default at identical reliability, and the default is not the cheap end. Expect these to shift toward &lt;code&gt;low&lt;/code&gt; as the sweep widens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A &lt;code&gt;null&lt;/code&gt; means nothing measured clears the bar for that cell&lt;/strong&gt; — not "untested". And read the &lt;code&gt;n&lt;/code&gt;: several cells are n=1, where a 1.00 is much weaker evidence than a 1.00 at n=9.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;One bar for every stack: 1.00.&lt;/strong&gt; Local stacks used to qualify at &lt;strong&gt;0.50&lt;/strong&gt;, on the view that a \$0 stack is worth a lower bar if you are watching it. That contradicted the metric's own definition — &lt;em&gt;the probability a single **unattended&lt;/em&gt;* run comes out completely correct*, where a single sub-1.0 run is a fail — and it let a coin flip outrank a perfect stack purely on price (python-on-hard-task recommended the local 35B at &lt;strong&gt;0.50&lt;/strong&gt;). Being free is already expressed in the cost column; it should not also lower the standard.&lt;/p&gt;

&lt;p&gt;Raising local to 1.00 did &lt;strong&gt;not&lt;/strong&gt; push local out of the recommendations — it picked a &lt;em&gt;better&lt;/em&gt; local stack: routine python and go moved from the 35B (0.87 / 0.85) to the &lt;strong&gt;80B at 1.00, still \$0&lt;/strong&gt;. The double standard had been hiding the more reliable free option. Hard-task python moved from the 35B at 0.50 to &lt;strong&gt;Opus 4.7 at 1.00&lt;/strong&gt;, which is the honest answer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The leading stacks
&lt;/h2&gt;

&lt;p&gt;Reliability, cost and time are all reported &lt;strong&gt;per task size&lt;/strong&gt; — routine and hard are different jobs, and a stack that is cheap-and-certain on routine work can be neither on a hard one. The &lt;strong&gt;routine reliability here is a cross-language blend and is the least useful number in this document&lt;/strong&gt; — it hides a stack's weak languages inside its strong ones (local Qwen passes Python/Go but not Rust; Opus 4.8 dips on Java). Use it only as a rough sort; the per-language success-rate matrix below is the number to actually decide on. (Hard reliability is single-task, measured on Python/Go.)&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stack&lt;/th&gt;
&lt;th&gt;Reliability (routine · hard)&lt;/th&gt;
&lt;th&gt;Cost (routine · hard)&lt;/th&gt;
&lt;th&gt;Time (routine · hard)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Claude Opus 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 · 1.00&lt;/td&gt;
&lt;td&gt;$3.23 · $21.67&lt;/td&gt;
&lt;td&gt;546 s · 2630 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Claude Fable 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 · 1.00&lt;/td&gt;
&lt;td&gt;$1.58 · $10.47&lt;/td&gt;
&lt;td&gt;166 s · 1090 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GPT-5.6 Terra (codex)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 · —&lt;/td&gt;
&lt;td&gt;$0.22 · —&lt;/td&gt;
&lt;td&gt;155 s · —&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GPT-5.6 Luna (codex)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.67 · —&lt;/td&gt;
&lt;td&gt;$0.09 · —&lt;/td&gt;
&lt;td&gt;153 s · —&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Claude Sonnet 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 · 0.93&lt;/td&gt;
&lt;td&gt;$1.10 · $7.64&lt;/td&gt;
&lt;td&gt;237 s · 1252 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Claude Opus 4.8&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.98 · 0.59&lt;/td&gt;
&lt;td&gt;$0.93 · $3.27&lt;/td&gt;
&lt;td&gt;258 s · 608 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Claude Opus 4.7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 · 0.40&lt;/td&gt;
&lt;td&gt;$0.92 · $2.95&lt;/td&gt;
&lt;td&gt;165 s · 500 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Qwen3.6-35B-A3B (local, $0)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.86 · 0.25&lt;/td&gt;
&lt;td&gt;$0.00 · $0.00&lt;/td&gt;
&lt;td&gt;355 s · 1542 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Qwen3-Coder-Next 80B (local, $0, ctx 0.9)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 · 0.00&lt;/td&gt;
&lt;td&gt;$0.00 · $0.00&lt;/td&gt;
&lt;td&gt;604 s · 2014 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;(Table generated from &lt;code&gt;master.db&lt;/code&gt; by &lt;code&gt;retort report optimal&lt;/code&gt; — do not hand-edit between the markers.)&lt;/em&gt; Each local stack's routine number is scoped to the languages it is &lt;strong&gt;recommended&lt;/strong&gt; for (35B: Python/Go; 80B: Python/Go/TypeScript) — the full per-language truth, including the languages they fail, is in the matrix below. &lt;strong&gt;On the hard task local models are now measured and both do poorly&lt;/strong&gt; — 35B &lt;strong&gt;0.25&lt;/strong&gt;, 80B &lt;strong&gt;0.00&lt;/strong&gt; (see the per-stack bullets). Rust local is unqualified (80B 0.33, near-misses).&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  ⚠️ Local + hard task: the wall holds unattended, but a repair loop gets through
&lt;/h3&gt;

&lt;p&gt;The 0.00 below is the &lt;strong&gt;unattended, first-attempt&lt;/strong&gt; number and it stands — &lt;a href="//docs/past-experiments.md"&gt;exp-50&lt;/a&gt; re-ran it and got &lt;strong&gt;0/6 on first attempts&lt;/strong&gt;, matching exp-39 exactly.&lt;/p&gt;

&lt;p&gt;What exp-50 adds: with retort's &lt;strong&gt;self-repair second chance&lt;/strong&gt; — the cell re-seeded with its own code plus the evaluation's critique — the 80B reached full req-coverage on &lt;strong&gt;3 of 6&lt;/strong&gt; runs. Every pass was a second attempt; none was unattended. At half credit for a second-try pass that is a pass-proportion of &lt;strong&gt;0.25&lt;/strong&gt; against a published 0.00.&lt;/p&gt;

&lt;p&gt;Read it as: &lt;strong&gt;the 80B reliably gets ~11 of 12 capabilities and cannot close the last one alone, but closes it about half the time when told what is missing.&lt;/strong&gt; "Hard tasks → cloud" remains right for unattended use; a local stack &lt;em&gt;with a repair loop&lt;/em&gt; is a different and more promising proposition.&lt;/p&gt;

&lt;p&gt;(The re-test was launched on a theory — a 30-turn agent cap — that turned out to be wrong: the old runs took 32–90 turns and nothing truncated them. Kept visible in the write-up.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Pick by task size — the two columns tell different stories:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fable 5&lt;/strong&gt; clears the hard task &lt;strong&gt;every time (1.00), in all thirteen languages&lt;/strong&gt;. When a hard, multi-capability job has to be right unattended, this is the one — ~$10.47 and ~18 min a run, and the certainty is what you're buying.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opus 5&lt;/strong&gt; also clears the hard task 1.00 in all thirteen, at &lt;strong&gt;~$21.67 and ~44 min&lt;/strong&gt; — twice the money and 2.4× the time for the same outcome. It held this slot briefly on the strength of being the only stack measured across all 13 languages; once Fable 5 was actually run on the nine it had been missing, that distinction vanished. &lt;strong&gt;There is no language here where Opus 5 is the necessary choice.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sonnet 5&lt;/strong&gt; lands &lt;strong&gt;0.93 on hard&lt;/strong&gt; at ~15% less than Fable and comparable time — the cost-aware hard-task pick when roughly 1-in-14 misses is acceptable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opus 4.8&lt;/strong&gt; is the cheapest &lt;em&gt;hard-capable&lt;/em&gt; cloud stack, but hard reliability is only &lt;strong&gt;~0.59 — a coin flip&lt;/strong&gt;, so budget for review-and-retry. On &lt;strong&gt;routine&lt;/strong&gt; work it is ~1.00 and cheap; that's its real niche.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opus 4.7&lt;/strong&gt; is a fine, cheap &lt;strong&gt;routine&lt;/strong&gt; stack (1.00, ~$0.97) but &lt;strong&gt;weak on hard (0.40)&lt;/strong&gt; — don't send hard work to it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Qwen 35B local&lt;/strong&gt; does &lt;strong&gt;routine&lt;/strong&gt; Python / Go for &lt;strong&gt;$0&lt;/strong&gt; at &lt;strong&gt;0.85 each&lt;/strong&gt; — its real niche. Its leading number (0.78) is &lt;em&gt;lower&lt;/em&gt; than either language because the blend now includes its Rust and TypeScript runs, which score &lt;strong&gt;0.00&lt;/strong&gt; — the clearest example in this doc of why you must read the per-language matrix, not the average. On the &lt;strong&gt;hard task it scores 0.25&lt;/strong&gt; (3/12) — occasionally nails all 12 capabilities, but not reliably. Rust and TypeScript unqualified.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Qwen 80B local (&lt;code&gt;Qwen3-Coder-Next&lt;/code&gt;) — the best local stack for &lt;em&gt;Python, Go and TypeScript&lt;/em&gt; (&lt;code&gt;context_threshold: 0.9&lt;/code&gt;, "full context").&lt;/strong&gt; The featured numbers above are now at 0.9, the clean full-9-language baseline (exp-38, n=3/language): &lt;strong&gt;Python 1.00, Go 1.00, TypeScript 1.00&lt;/strong&gt; — all three reliable, all $0. &lt;strong&gt;TypeScript is the unlock&lt;/strong&gt;: it was 0.33 at ctx 0.35/0.7, and raising compaction to full context makes it pass 3/3. It's slower than the 35B (~600 s routine). &lt;strong&gt;Rust is 0.33 (1/3) → cloud&lt;/strong&gt; — but note its 2 failures are &lt;em&gt;near-misses&lt;/em&gt; (req-coverage 0.92/0.92; the code compiles and its tests pass 100%, it just misses 1–2 spec requirements), &lt;strong&gt;not&lt;/strong&gt; the thrash-to-the-wall stalls of the old story (confirmed via &lt;code&gt;retort diagnose&lt;/code&gt;+&lt;code&gt;rescore&lt;/code&gt;+&lt;code&gt;reevaluate&lt;/code&gt;, which caught them as scorer tooling false-failures and recovered their true near-miss scores). The other five languages → cloud: java/erlang are near-misses (0/3), and &lt;strong&gt;clojure/csharp/elixir score a genuine 0.00&lt;/strong&gt; — they can't produce working code at all (diagnosed GENUINE, not harness). On the &lt;strong&gt;hard task it scores 0.00, and that is now &lt;em&gt;verified&lt;/em&gt; config-invariant&lt;/strong&gt; — re-run at full context (exp-39, brazil at 0.9) it is still &lt;strong&gt;0/6&lt;/strong&gt;, same as 0.7 (exp-31): Python gets as close as &lt;strong&gt;11/12&lt;/strong&gt; but never all 12, and Go actually &lt;em&gt;regresses&lt;/em&gt; (a stall — the same late-compaction downside that bites any run that can't finish). So full context is strictly for the easy languages; it does not raise the hard-task ceiling. Rule: &lt;strong&gt;80B for local Python, Go and TypeScript (at &lt;code&gt;context_threshold: 0.9&lt;/code&gt;); Rust, the niche languages, and hard tasks → cloud.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The 80B's stall was a fixable config artifact, not a capability wall — and raising the compaction threshold is a graded lever, not a switch.&lt;/strong&gt; The intermittent hang was lcm compaction firing too early: at the default &lt;code&gt;context_threshold: 0.35&lt;/code&gt; it compacts live context at ~92K, truncating the agent's working history mid-build so it loses the thread and thrashes to the wall. Raising it walks the results up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;0.35 → 0.7&lt;/strong&gt; kills the Go stalls: over &lt;strong&gt;9 Go runs&lt;/strong&gt; (exp-34/36) &lt;strong&gt;0 stalls, Go = 8/9 = 0.89&lt;/strong&gt; (up from 0.67-with-2-stalls), and Python holds at &lt;strong&gt;1.00&lt;/strong&gt; (exp-37). But TypeScript was still only 0.33 here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;0.7 → 0.9 ("full context", compact at ~236K) unlocks TypeScript.&lt;/strong&gt; The full-9-language re-baseline at 0.9 (exp-38, n=3) gives &lt;strong&gt;Python 1.00, Go 1.00, TypeScript 1.00&lt;/strong&gt; — TS goes from 0.33 to 3/3 because at full context the agent keeps its whole working history through the longer TS build instead of being compacted mid-stream. &lt;strong&gt;So &lt;code&gt;lcm.context_threshold: 0.9&lt;/code&gt; is now the recommended config for the 80B&lt;/strong&gt;, and the featured table reflects it (the 0.7 runs remain the larger-n Go evidence and the proof that the fix is graded).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cost of going to 0.9: a run that &lt;em&gt;can't&lt;/em&gt; finish thrashes longer before failing (6 M tokens on a failed Rust/niche cell) — but those languages go to cloud anyway, so it doesn't touch the recommended Python/Go/TS path. (The same lever only &lt;em&gt;partly&lt;/em&gt; rescues the 35B on Rust — exp-35: first-ever Rust pass at 0.7, but 2/3 still stall. And it doesn't help the hard task: exp-39 re-ran brazil at 0.9 and got the same 0/6 as 0.7, with Go now hitting the late-compaction stall — full context helps the easy languages, not the hard ceiling.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The same lever partly explains the "Rust wall" — but only partly.&lt;/strong&gt; At 0.35 the 35B thrashes to the wall on &lt;em&gt;every&lt;/em&gt; Rust run (clean 0.00). At 0.7 it scored its &lt;strong&gt;first-ever Rust pass&lt;/strong&gt; (exp-35 rep1 = 1.00, at 113K context — exactly the regime 0.35 truncates), so Rust is &lt;em&gt;not&lt;/em&gt; a pure capability wall. But &lt;strong&gt;2 of 3 still stalled&lt;/strong&gt; at 0.7 — unlike the 80B (0/6), the 35B on Rust is only partially rescued. Net: raising &lt;code&gt;context_threshold&lt;/code&gt; is a real lever for local non-termination, but its strength is model- and language-dependent — a clean fix for the 80B on Go/TS, a partial one for the 35B on Rust. Rust stays → cloud.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On the Opus 4.8 hard number.&lt;/strong&gt; 0.59 is an honest blend: a small clean run scored 1.00 (n=6) while a larger one scored 0.50 (n=36). The optimistic single-run figure is not representative — treat hard-task Opus 4.8 as a coin flip, not a sure thing.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What to run, by language and task size
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Task size&lt;/strong&gt; is the axis that matters most, more than language:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Routine&lt;/strong&gt; — CRUD, glue, well-trodden patterns, a few interacting requirements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hard&lt;/strong&gt; — a novel domain, many interacting capabilities, real data, a protocol to implement correctly (our reference: an MCP server over six datasets, twelve required capabilities).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Start from the per-language success rate, not a single headline number.&lt;/strong&gt; This is the matrix that matters — routine pass-proportion for each language × stack, &lt;code&gt;pass (n)&lt;/code&gt;, generated from &lt;code&gt;master.db&lt;/code&gt;. A blank cell means we have no qualified runs there. Read &lt;em&gt;down&lt;/em&gt; a column to see where a model is weak (Opus 4.8 on Java; the 35B local passes Python/Go but scores 0.00 on Rust/TypeScript; the 80B local is strong on Python but drops on Go/TS), and &lt;em&gt;across&lt;/em&gt; a row to pick the cheapest stack that actually passes &lt;em&gt;that&lt;/em&gt; language:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Opus 5&lt;/th&gt;
&lt;th&gt;Fable 5&lt;/th&gt;
&lt;th&gt;Terra&lt;/th&gt;
&lt;th&gt;Luna&lt;/th&gt;
&lt;th&gt;Sonnet 5&lt;/th&gt;
&lt;th&gt;Opus 4.8&lt;/th&gt;
&lt;th&gt;Opus 4.7&lt;/th&gt;
&lt;th&gt;Qwen 35B local&lt;/th&gt;
&lt;th&gt;Qwen 80B local&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;c&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;clojure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;1.00 (6)&lt;/td&gt;
&lt;td&gt;1.00 (6)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;0.00 (3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;cpp&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;csharp&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;0.00 (3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;elixir&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;0.00 (3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;erlang&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;0.00 (3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;go&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (10)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;1.00 (10)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;1.00 (7)&lt;/td&gt;
&lt;td&gt;1.00 (6)&lt;/td&gt;
&lt;td&gt;0.85 (27)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;java&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;0.83 (6)&lt;/td&gt;
&lt;td&gt;1.00 (6)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;0.00 (3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;objc&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (26)&lt;/td&gt;
&lt;td&gt;1.00 (18)&lt;/td&gt;
&lt;td&gt;1.00 (10)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;1.00 (22)&lt;/td&gt;
&lt;td&gt;1.00 (21)&lt;/td&gt;
&lt;td&gt;0.87 (30)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;rust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;1.00 (6)&lt;/td&gt;
&lt;td&gt;1.00 (6)&lt;/td&gt;
&lt;td&gt;0.00 (2)&lt;/td&gt;
&lt;td&gt;0.33 (3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;swift&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;typescript&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;1.00 (1)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;0.00 (3)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;td&gt;1.00 (7)&lt;/td&gt;
&lt;td&gt;1.00 (6)&lt;/td&gt;
&lt;td&gt;0.00 (3)&lt;/td&gt;
&lt;td&gt;1.00 (3)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The language split: Python, Go and TypeScript run locally for free (on the 80B at full context); every other language means Claude.&lt;/strong&gt; The 80B (&lt;code&gt;Qwen3-Coder-Next&lt;/code&gt;, at &lt;code&gt;context_threshold: 0.9&lt;/code&gt;) is reliable on all three — &lt;strong&gt;Python 1.00, Go 1.00, TypeScript 1.00&lt;/strong&gt; (exp-38, n=3 each) — the last only after raising compaction to full context (it was 0.33 below that). The 35B is the faster alternative but only on &lt;strong&gt;Python and Go (0.85 each)&lt;/strong&gt;; it scores &lt;strong&gt;0.00&lt;/strong&gt; on TypeScript and Rust even at its tuned config, so its cross-language average (0.85 when scoped to Python/Go; lower if you blend in the languages it can't do) is exactly why this document leads with the matrix, not an average. &lt;strong&gt;Rust and the five niche languages (clojure/csharp/elixir/java/erlang) still go to cloud&lt;/strong&gt; — the 80B either near-misses (Rust 0.33, java/erlang) or can't produce working code at all (clojure/csharp/elixir score a genuine 0.00). So local has two stacks for Python/Go and one (the 80B at 0.9) that adds TypeScript.&lt;/p&gt;

&lt;p&gt;The recommendation table distills the matrix into, per language, the &lt;strong&gt;cheapest model that clears routine work&lt;/strong&gt;, the &lt;strong&gt;hard-task&lt;/strong&gt; pick, and the &lt;strong&gt;prompt / testing method&lt;/strong&gt; (the last is qualitative, from the prompt experiments):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Routine → cheapest qualifying&lt;/th&gt;
&lt;th&gt;Hard task&lt;/th&gt;
&lt;th&gt;Prompt / testing method&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Qwen 80B local ($0)&lt;/strong&gt; 1.00 for reliability, or &lt;strong&gt;35B&lt;/strong&gt; 0.85 for more speed&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Fable 5&lt;/strong&gt; (1.00); Opus 4.8 cheaper but ~0.59&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;80B:&lt;/strong&gt; &lt;em&gt;neutral&lt;/em&gt; (prompt is a no-op — all pass). &lt;strong&gt;35B:&lt;/strong&gt; &lt;em&gt;neutral&lt;/em&gt;/BDD, never ATDD. Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Qwen 35B ($0)&lt;/strong&gt; 0.85, or &lt;strong&gt;80B @ ctx 0.9 ($0)&lt;/strong&gt; 1.00 — both local-viable&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Fable 5&lt;/strong&gt;; Opus 4.8 cheaper / riskier&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;35B:&lt;/strong&gt; &lt;em&gt;neutral&lt;/em&gt; or BDD, never ATDD. &lt;strong&gt;80B:&lt;/strong&gt; &lt;em&gt;neutral&lt;/em&gt;. Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Qwen 80B @ ctx 0.9 ($0)&lt;/strong&gt; 1.00 (n=3) — newly local-viable, or &lt;strong&gt;Opus 4.8 (~$0.65)&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fable 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;80B:&lt;/strong&gt; &lt;em&gt;neutral&lt;/em&gt; (needs &lt;code&gt;context_threshold: 0.9&lt;/code&gt;). Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Opus 4.8 (~$0.71)&lt;/strong&gt; — local 0.33 (near-misses, → cloud)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fable 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Clojure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Opus 4.7 (~$1.06)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fable 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Opus 4.7 (~$0.92)&lt;/strong&gt;†&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fable 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;C#&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Opus 4.8 (~$0.65)&lt;/strong&gt;‡&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fable 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Elixir&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Opus 4.8 (~$0.85)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fable 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Erlang&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Opus 4.8 (~$1.35)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fable 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;C&lt;/strong&gt; ᴱ&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Opus 4.8 (~$1.28, n=1)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fable 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;C++&lt;/strong&gt; ᴱ&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Opus 4.8 (~$1.08, n=1)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fable 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Objective-C&lt;/strong&gt; ᴱ&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Opus 4.8 (~$1.52, n=1)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fable 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Swift&lt;/strong&gt; ᴱ&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Opus 4.8 (n=1)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Fable 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud: &lt;em&gt;neutral&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;† On our routine Java runs Opus 4.8 dipped to 0.83 while 4.7 held 1.00 — small n; review Java output whichever you use. ‡ C# Opus 4.8 is n=1; Sonnet 5 (~$1.57, n=3) is the better-sampled fallback. ᴱ C / C++ / Objective-C / Swift are the newer exploratory languages (exp-43); their routine picks are n=1, so treat them as "known to work once," not as reliability estimates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Fable 5 in every hard-task cell, and not Opus 5?&lt;/strong&gt; Both clear all thirteen languages at 1.00. Fable 5 does it for &lt;strong&gt;$10.47 / 18.2 min&lt;/strong&gt; per cell against Opus 5's &lt;strong&gt;$21.67 / 43.8 min&lt;/strong&gt; — 2.1× cheaper and 2.7× faster on the identical nine-language subset, using 2.3× fewer agentic turns. &lt;strong&gt;There is no language in this dataset where Opus 5 is the necessary choice.&lt;/strong&gt; (Opus 5 briefly held this column on the strength of being the only model measured across all 13; that was a gap in &lt;em&gt;coverage of the comparison&lt;/em&gt;, not a capability difference — see &lt;a href="//docs/past-experiments.md"&gt;exp-48&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt / testing method — it matters only in proportion to how weak the model is.&lt;/strong&gt; The table above (Python routine) makes the rule concrete: &lt;strong&gt;the prompt is a lever on a weak model and a no-op on a strong one.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strong models (all cloud, and the local 80B): flat line.&lt;/strong&gt; Every methodology passes — the 80B goes &lt;strong&gt;1.00 on all four&lt;/strong&gt;, ATDD included. Pick &lt;strong&gt;neutral&lt;/strong&gt; and spend nothing on methodology ceremony; it's the cheapest and loses nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weak models (the local 35B): the prompt bites.&lt;/strong&gt; neutral/BDD 0.67, TDD 0.33, and &lt;strong&gt;ATDD 0.00&lt;/strong&gt; — a weak model can't carry ATDD's front-loaded discipline and burns the run. So on the 35B: neutral (cheapest) or BDD, and &lt;strong&gt;never ATDD&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The takeaway: reach for a disciplined methodology only when you're near a model's capability edge; on a model that clears the task comfortably, the prompt is ritual.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The decision procedure:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hard task, must be right the first time, unattended?&lt;/strong&gt; → &lt;strong&gt;Fable 5&lt;/strong&gt; (1.00). Costliest and slowest; certainty is what the premium buys.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hard task, but cost matters and ~1-in-14 misses is tolerable?&lt;/strong&gt; → &lt;strong&gt;Sonnet 5&lt;/strong&gt; (0.93), ~15% under Fable. Opus 4.8 is cheaper again but only ~0.59 — budget a review-and-retry loop if you use it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routine, local &amp;amp; free?&lt;/strong&gt; (run the 80B at &lt;code&gt;context_threshold: 0.9&lt;/code&gt;) → &lt;strong&gt;Python: 80B (1.00)&lt;/strong&gt; for reliability or the &lt;strong&gt;35B (0.85)&lt;/strong&gt; for more speed. &lt;strong&gt;Go: 80B (1.00) or 35B (0.85)&lt;/strong&gt; — both viable. &lt;strong&gt;TypeScript: 80B (1.00)&lt;/strong&gt; — newly local-viable at full context (below 0.9 it's a coin-flip). Review the output; you'll still see a miss every few runs. (Rust, the niche languages, everything else → cloud.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routine, any other language?&lt;/strong&gt; → cheapest current cloud (Opus 4.7 / 4.8, ~$1); they all reach ~1.00, so paying more buys nothing. Use the &lt;strong&gt;neutral&lt;/strong&gt; prompt.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Reliability is a property of the &lt;em&gt;stack&lt;/em&gt;, not the model. A leading model on a bad configuration is not a leading stack. These are the settings each one requires.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local: Qwen3.6-35B-A3B
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;unsloth/Qwen3.6-35B-A3B-UD-MLX-4bit&lt;/code&gt; (4-bit MLX, ~20 GB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Serving&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;oMLX 0.5.0 · served from &lt;code&gt;~/models/&amp;lt;name&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hermes v0.18 with the &lt;code&gt;hermes-lcm&lt;/code&gt; plugin (&lt;code&gt;context.engine: lcm&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Context&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;context_length: 262144&lt;/code&gt; — set it explicitly; the default fallback is far lower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compaction&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;lcm.context_threshold: 0.9&lt;/code&gt; &lt;strong&gt;for the 80B&lt;/strong&gt; ("full context" — default 0.35 compacts at ~92K and causes intermittent stalls; 0.7 kills the stalls and 0.9 additionally unlocks TypeScript — see exp-34/38; env override: &lt;code&gt;LCM_CONTEXT_THRESHOLD=0.9&lt;/code&gt;). The 35B is fine at 0.35.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardware&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Apple Silicon, 64 GB. Raise the GPU wired limit: &lt;code&gt;sudo sysctl iogpu.wired_limit_mb=57344&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Sampling — this is not optional:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        &lt;span class="m"&gt;0.6&lt;/span&gt;     &lt;span class="c1"&gt;# anything in 0.2–0.7; the requirement is: NOT 1.0&lt;/span&gt;
&lt;span class="na"&gt;top_p&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;              &lt;span class="m"&gt;0.95&lt;/span&gt;
&lt;span class="na"&gt;top_k&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;              &lt;span class="m"&gt;20&lt;/span&gt;
&lt;span class="na"&gt;repetition_penalty&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.0&lt;/span&gt;     &lt;span class="c1"&gt;# OFF. See forbidden settings.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Harness settings that decide whether the model can work at all:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;playpen_root&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;~/.retort/work&lt;/span&gt;   &lt;span class="c1"&gt;# NOT the system temp dir — see forbidden settings&lt;/span&gt;
&lt;span class="na"&gt;timeout_minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;             &lt;span class="c1"&gt;# a high wall: local models are slow, let good work finish&lt;/span&gt;
&lt;span class="na"&gt;stall_minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="m"&gt;25&lt;/span&gt;             &lt;span class="c1"&gt;# kill unproductive loops, not slow-but-productive runs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Operational — the local serving layer needs babysitting over long sessions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Restart oMLX between long runs.&lt;/strong&gt; After many hours of continuous serving, oMLX quality degrades — a normally-flawless language (Python is 21/21) starts throwing &lt;strong&gt;fast all-zeros fails&lt;/strong&gt; (the model emits garbage in ~2 min). These look like a real result but are a serving artifact; the fix is to kill oMLX (the next run reloads a fresh server) — do it before any run whose result you intend to trust, and treat a sudden cluster of all-zeros on a reliable language as "restart the server," not "the model got worse."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch the disk — the paged-SSD cache is a trap.&lt;/strong&gt; oMLX's &lt;code&gt;--paged-ssd-cache&lt;/code&gt; grows to its configured cap (a 120 GB default filled a 926 GB disk to 98% in one session) and, per exp-24, &lt;strong&gt;it doesn't help these generation-bound runs at all&lt;/strong&gt; — set the cap small (~5–20 GB) or disable it. A full disk makes the agent's file writes fail → false zeros. &lt;code&gt;retort run&lt;/code&gt; now does a &lt;strong&gt;disk preflight&lt;/strong&gt; (aborts under 15 GB free, warns under 40 GB).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure Time Machine for a benchmarking box — or it will eat the disk.&lt;/strong&gt; On macOS/APFS, deleting a big cache doesn't free space if a Time-Machine &lt;strong&gt;local snapshot&lt;/strong&gt; still pins the freed blocks (an hourly cadence pinned ~93 GB of already-deleted oMLX cache in one session). Two settings fix it, and everything large here is regenerable (models re-download from HF, the repo state lives in git), so exclude it all from backups:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="c"&gt;# exclude the big, regenerable, high-churn paths (‑p = sticky, survives recreation)&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;tmutil addexclusion &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.cache/omlx-ssd     &lt;span class="c"&gt;# oMLX paged-SSD prefix cache&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;tmutil addexclusion &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.omlx/cache         &lt;span class="c"&gt;# oMLX prefix-block cache&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;tmutil addexclusion &lt;span class="nt"&gt;-p&lt;/span&gt; ~/models              &lt;span class="c"&gt;# MLX weights (re-download from HF)&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;tmutil addexclusion &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.cache/huggingface  &lt;span class="c"&gt;# HF download cache&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;tmutil addexclusion &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.retort/work        &lt;span class="c"&gt;# per-run playpens (transient)&lt;/span&gt;
  &lt;span class="c"&gt;# reclaim space a snapshot is already pinning, now (df won't budge until you do):&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;tmutil thinlocalsnapshots / 100000000000 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also drop the snapshot cadence from &lt;strong&gt;hourly to daily&lt;/strong&gt; (e.g. TimeMachineEditor) so cache churn between runs can't pile up dozens of space-pinning snapshots. Exclusions shrink the backup and per-snapshot delta; the daily cadence caps how many pin space at once; thinning clears what's already stuck.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud: Claude Fable 5, Sonnet 5, Opus 4.8 / 4.7
&lt;/h3&gt;

&lt;p&gt;There is no single cloud winner — the pick is set by task size (see the tables above): &lt;strong&gt;Fable 5&lt;/strong&gt; for hard work that must be right, &lt;strong&gt;Sonnet 5&lt;/strong&gt; for hard work on a budget, &lt;strong&gt;Opus 4.8 / 4.7&lt;/strong&gt; for cheap routine work.&lt;/p&gt;

&lt;p&gt;Run the model as shipped. The stack that matters is the agent around it; &lt;strong&gt;no sampling tuning is required or recommended, and on cloud the prompt is a flat line&lt;/strong&gt; — use the plain &lt;em&gt;neutral&lt;/em&gt; prompt and don't pay for methodology ceremony.&lt;/p&gt;




&lt;h2&gt;
  
  
  Forbidden settings
&lt;/h2&gt;

&lt;p&gt;Configurations that measurably degrade a stack. These are eliminated, not tuned.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Why it is forbidden&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;repetition_penalty&lt;/code&gt; &amp;gt; 1.0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Any repetition penalty derails an agentic tool-calling loop — the model stops converging, stalls, and produces nothing. This holds even at 1.05, and even when the model's own card recommends it: model-card sampling is tuned for single-turn generation, not multi-turn agent loops. &lt;strong&gt;Set it to 1.0.&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;&lt;code&gt;temperature: 1.0&lt;/code&gt;&lt;/strong&gt; (server default)&lt;/td&gt;
&lt;td&gt;Costs roughly half the reliability of a local coding stack. Any value in 0.2–0.7 is fine; the precise value does not matter.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Playpen under the system temp dir&lt;/strong&gt; (&lt;code&gt;/var/folders/...&lt;/code&gt; on macOS)&lt;/td&gt;
&lt;td&gt;Agents refuse to write to paths they consider system-owned, so the agent cannot create files &lt;em&gt;in its own workspace&lt;/em&gt; — and a run that writes nothing scores a false zero indistinguishable from an incapable model. Keep playpens under &lt;code&gt;$HOME&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;An unrecorded stack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A pass-proportion without the stack it was measured on is not a result. Capture versions, model revision hashes, sampling, agent config, and harness settings — every run writes a &lt;code&gt;provenance.json&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Measured data (auto-generated)
&lt;/h2&gt;

&lt;p&gt;These tables are regenerated from &lt;code&gt;master.db&lt;/code&gt; by &lt;code&gt;retort report optimal&lt;/code&gt; — run &lt;code&gt;retort report optimal --write optimal-blog.md&lt;/code&gt; to refresh everything between the &lt;code&gt;GEN&lt;/code&gt; markers. The leading stacks table above is generated the same way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per language — cheapest stack that clears its reliability bar (routine task):&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Routine → cheapest qualifying stack&lt;/th&gt;
&lt;th&gt;Reliability&lt;/th&gt;
&lt;th&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;c&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.8 ($1.28)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;clojure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.7 ($1.06)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;cpp&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.8 ($1.08)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;csharp&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.8 ($0.65)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;elixir&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.8 ($0.85)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;erlang&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.8 ($1.35)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;go&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Qwen3-Coder-Next 80B (local, $0, ctx 0.9) ($0)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;java&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.7 ($0.92)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;objc&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.8 ($1.52)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Qwen3-Coder-Next 80B (local, $0, ctx 0.9) ($0)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;rust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.8 ($0.71)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;swift&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.8 ($1.25)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;typescript&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Qwen3-Coder-Next 80B (local, $0, ctx 0.9) ($0)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Prompt / testing method — the local sweep (on cloud the prompt is a flat line):&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prompt&lt;/th&gt;
&lt;th&gt;35B pass&lt;/th&gt;
&lt;th&gt;80B pass&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;neutral&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.67 (n=3)&lt;/td&gt;
&lt;td&gt;1.00 (n=3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;BDD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.67 (n=3)&lt;/td&gt;
&lt;td&gt;1.00 (n=3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TDD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.33 (n=3)&lt;/td&gt;
&lt;td&gt;1.00 (n=3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ATDD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.00 (n=3)&lt;/td&gt;
&lt;td&gt;1.00 (n=3)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Keeping this current
&lt;/h2&gt;

&lt;p&gt;Each new frontier or local model release triggers a qualification pass on the standard tasks. A stack is added only when it leads on an axis someone chooses along, and is removed when it no longer leads on any. The tables are regenerated from &lt;code&gt;master.db&lt;/code&gt; by &lt;code&gt;retort report optimal&lt;/code&gt;; run &lt;code&gt;retort report optimal --health&lt;/code&gt; to check the data before trusting a refresh.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Known data-pipeline gaps&lt;/strong&gt; the generator has to work around (it curates the qualified config in &lt;code&gt;FEATURED_STACKS&lt;/code&gt; because master.db can't express it):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Historical local runs carry a blank &lt;code&gt;model&lt;/code&gt;&lt;/strong&gt; — older runs recorded &lt;code&gt;agent: hermes-local&lt;/code&gt; but no model, so ~250 rows are attributed to a stack only via their experiment slug. &lt;em&gt;Fixed going forward&lt;/em&gt;: the harness now always records the resolved model (&lt;code&gt;stack_metadata()&lt;/code&gt;), so exp-29 and later land with a real model id.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No sampling / context columns&lt;/strong&gt; — temperature, top_p, top_k, repetition_penalty are absent and &lt;code&gt;max_context_tokens&lt;/code&gt; is populated only on the newest runs, so "the qualified config" can't be filtered from the data; the tuned experiments are named in the script instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;experiment-11 isn't ingested&lt;/strong&gt; — it has no &lt;code&gt;retort.db&lt;/code&gt; (an empty/aborted experiment).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Backfilling the historical blank-model rows and re-ingesting would let the generator drop its slug curation and become a plain group-by.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Next review: on the next frontier release, or the next local model that fits 64 GB and tool-calls cleanly.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
    </item>
    <item>
      <title>Retort Tasks: What Gets Built, and How Differently a Run Can Pass</title>
      <dc:creator>Adrian Cockcroft</dc:creator>
      <pubDate>Thu, 30 Jul 2026 23:21:27 +0000</pubDate>
      <link>https://dev.to/adrianco_54/retort-tasks-what-gets-built-and-how-differently-a-run-can-pass-4cb6</link>
      <guid>https://dev.to/adrianco_54/retort-tasks-what-gets-built-and-how-differently-a-run-can-pass-4cb6</guid>
      <description>&lt;p&gt;This is a snapshot of an auto-generated analysis report from &lt;a href="https://github.com/adrianco/retort/blob/main/tasks-blog.md" rel="noopener noreferrer"&gt;https://github.com/adrianco/retort/blob/main/tasks-blog.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Published 2026-07-30 · updated 2026-07-30 — Adrian Cockcroft&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What retort actually asks an agent to build, and — for each task — the fastest and the slowest run that fully passed. Both mean shortest/longest &lt;code&gt;duration_seconds&lt;/code&gt; among runs scoring &lt;code&gt;requirement_coverage == 1.0&lt;/code&gt;, restricted to runs whose &lt;strong&gt;agent log was archived&lt;/strong&gt;, since a record with no log can't be shown.&lt;/p&gt;

&lt;p&gt;The slow end is worth as much attention as the fast end. Nothing fails there: every run below scores a perfect 1.00. They just take between 4× and 61× longer to get there, and the reasons differ per task — over-engineering on one, the language itself on another, and a tool that costs time on the third.&lt;/p&gt;

&lt;p&gt;Task definitions live in &lt;a href="https://dev.totasks/"&gt;&lt;code&gt;tasks/&lt;/code&gt;&lt;/a&gt; and are indexed by &lt;a href="//tasks/registry.yaml"&gt;&lt;code&gt;tasks/registry.yaml&lt;/code&gt;&lt;/a&gt;. Three of the seven registered tasks have been run at scale; the other four (&lt;code&gt;react-dashboard&lt;/code&gt;, &lt;code&gt;cli-data-pipeline&lt;/code&gt;, &lt;code&gt;brazil-bench-neutral&lt;/code&gt;, &lt;code&gt;funkygibbon-port&lt;/code&gt;) are defined but have few or no scored runs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A caveat on records.&lt;/strong&gt; Two faster runs exist in &lt;code&gt;master.db&lt;/code&gt; but are not shown here: a 2.49-min brazil (exp-2) and a 0.71-min rest-api (exp-1). Both predate agent-log archiving &lt;em&gt;and&lt;/em&gt; the mechanical gate — a sibling exp-2 "pass" carries &lt;code&gt;test_coverage=0.0&lt;/code&gt;, which today fails automatically. They are not comparable to the runs below.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. &lt;code&gt;rest-api-crud&lt;/code&gt; — the routine task
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://dev.totasks/rest-api-crud/"&gt;&lt;code&gt;tasks/rest-api-crud/&lt;/code&gt;&lt;/a&gt; · 712 runs · the "easy" task&lt;/p&gt;

&lt;p&gt;Build a CRUD REST API for a books collection: &lt;code&gt;POST /books&lt;/code&gt;, &lt;code&gt;GET /books&lt;/code&gt; (with &lt;code&gt;?author=&lt;/code&gt; filter), &lt;code&gt;GET/PUT/DELETE /books/{id}&lt;/code&gt;, plus &lt;code&gt;GET /health&lt;/code&gt;. Data in SQLite or the language's embedded equivalent, JSON responses with correct status codes, input validation, a README, and at least 3 tests. Scored in all 13 languages.&lt;/p&gt;

&lt;p&gt;This is the workhorse. It's deliberately unremarkable — the point is that a competent stack should score 1.00 on it every time, so it measures &lt;em&gt;reliability&lt;/em&gt;, not capability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fastest logged pass — 44.5s
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Fable 5, &lt;code&gt;effort=low&lt;/code&gt;, python, prompt=neutral&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Experiment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;adrianco/experiment-49-versions-cloud&lt;/code&gt; rep2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Duration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;44.5 s&lt;/strong&gt; · 7 turns · $0.86 · 105,745 tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12/12 requirements · 6 tests pass · coverage 0.98&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The entire run, condensed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Read]  TASK.md
[TEXT]  "I'll build a Flask + SQLite book API with tests."
[Write] app.py
[Write] test_app.py
[Write] README.md
[Write] requirements.txt
[Bash]  python3 -m venv venv &amp;amp;&amp;amp; ./venv/bin/pip install -q flask pytest &amp;amp;&amp;amp; ./venv/bin/python -m pytest -q
     -&amp;gt; ...... [100%] 6 passed in 0.19s
[TEXT]  "Done — all 6 tests pass."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One read, four writes, one verification command, done. No exploration, no iteration, no failed attempt. This is what the routine task looks like when a model simply knows the answer — and it's why the routine task no longer discriminates between frontier models on &lt;em&gt;reliability&lt;/em&gt;, only on cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Slowest logged pass — 45.6 min, for the same 1.00
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 5, &lt;code&gt;effort=max&lt;/code&gt;, python, prompt=neutral&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Experiment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;adrianco/experiment-55-terra-vs-opus5-effort-bookshop&lt;/code&gt; rep2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Duration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;45.6 min&lt;/strong&gt; (61×) · 94 turns · &lt;strong&gt;$24.96&lt;/strong&gt; (29×) · 18,448,183 tokens (174×)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12/12 requirements · &lt;strong&gt;104&lt;/strong&gt; tests · coverage 1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;2,351 lines against Fable 5's 194. It built a seven-module package, linted itself with &lt;code&gt;ruff&lt;/code&gt; unprompted, spawned a subagent, and ran &lt;strong&gt;mutation testing&lt;/strong&gt; — on a books CRUD API. Every one of the judge's five findings is an &lt;code&gt;info&lt;/code&gt; noting scope &lt;em&gt;beyond&lt;/em&gt; the spec: a &lt;code&gt;PATCH&lt;/code&gt; endpoint, filtering and pagination, a hand-written 304-line OpenAPI document, WAL journaling, NUL-byte validation. The task asked for five endpoints, a health check and at least three tests.&lt;/p&gt;

&lt;p&gt;It is not slop — it scores &lt;em&gt;better&lt;/em&gt; on maintainability (0.85 vs 0.27) and idiomaticity. But the gate cannot tell the two runs apart: both are 1.00. The full breakdown, including how much variance the thinking dial adds, is in &lt;a href="//experiments-blog.md"&gt;experiments-blog.md&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. &lt;code&gt;brazil-bench&lt;/code&gt; — the hard task
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://github.com/brazil-bench/benchmark-template" rel="noopener noreferrer"&gt;&lt;code&gt;github://brazil-bench/benchmark-template&lt;/code&gt;&lt;/a&gt; · 284 runs&lt;/p&gt;

&lt;p&gt;Build an MCP server over six real Kaggle CSVs of Brazilian football (23,954 matches across five files with three &lt;em&gt;different&lt;/em&gt; schemas, plus 18,207 FIFA players). Twelve pinned requirements in &lt;a href="//tasks/brazil-bench/REQUIREMENTS.json"&gt;&lt;code&gt;REQUIREMENTS.json&lt;/code&gt;&lt;/a&gt;: match queries by team / date-range / competition / season, team W-D-L records, player search and filtering, season standings computed from results, aggregate statistics, head-to-head, and automated tests.&lt;/p&gt;

&lt;p&gt;It is hard for reasons that have nothing to do with algorithms: team names carry state suffixes and accents (&lt;code&gt;São Paulo-SP&lt;/code&gt; vs &lt;code&gt;Sao Paulo&lt;/code&gt;), one file uses Portuguese column names and &lt;code&gt;DD/MM/YYYY&lt;/code&gt; dates, and &lt;strong&gt;the datasets overlap&lt;/strong&gt; — the same real-world match appears in two or three files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fastest logged pass — 3 min 19 s
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GPT-5.6 Terra (codex), &lt;code&gt;effort=medium&lt;/code&gt;, python, prompt=neutral&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Experiment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;adrianco/experiment-55-terra-vs-opus5-effort-brazil&lt;/code&gt; rep1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Duration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;199.5 s&lt;/strong&gt; · 16 agent steps · $0.3165 · 339,649 tokens (291,840 cached)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12/12 requirements · 7 tests pass · coverage 0.85&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Previous best in the modern harness was 5.67 min (Opus 5, clojure); the fastest previous &lt;em&gt;python&lt;/em&gt; brazil pass was 5.02 min. This is a real step change, not a rounding difference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The run, condensed:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[CMD]  ls &amp;amp;&amp;amp; sed -n '1,240p' TASK.md &amp;amp;&amp;amp; rg --files          # read spec + repo
[CMD]  sed -n '241,520p' TASK.md ... head data/kaggle/*.csv  # read rest of spec + data shapes
[CMD]  sed -n '1,240p' prompts.txt; wc -l data/kaggle/*.csv  # count rows
[MSG]  "building a dependency-free MCP stdio server with an indexed CSV data
        layer and BDD-style tests"
[EDIT] README.md, brazilian_soccer_mcp.py, server.py, test_*.py   # ALL files, one patch

[CMD]  python -m pytest -q                    -&amp;gt; exit 127: command not found: python
[MSG]  "The environment provides python3 rather than python"
[CMD]  python3 -m pytest -q                   -&amp;gt; 7 FAILED
                                                 "Extra data: line 2 column 1"
[EDIT] brazilian_soccer_mcp.py                # fix the extended-file parser
[CMD]  python3 -m pytest -q &amp;amp;&amp;amp; python3 server.py &amp;lt;&amp;lt;&amp;lt; '{jsonrpc initialize}...'
     -&amp;gt; 7 passed in 3.19s
     -&amp;gt; loaded 23954 matches and 18207 players
     -&amp;gt; top 2019: [Flamengo 38pl 90pts, Palmeiras 74, Santos 74]
     -&amp;gt; {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05", ...}}
[CMD]  python3 -c "Counter by source file"    # investigate dataset overlap
[EDIT] brazilian_soccer_mcp.py                # add standings source-dedup guard
[CMD]  python3 -m pytest -q &amp;amp;&amp;amp; py_compile &amp;amp;&amp;amp; git diff --stat
[MSG]  "all seven BDD-style tests pass, including the known 2019 Brasileirão
        standings result, and the MCP stdio handshake/tool call succeeds"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sixteen steps, two real failures, both diagnosed and fixed. Not a lucky one-shot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the solution looks like.&lt;/strong&gt; 342 lines across 3 files, &lt;strong&gt;zero dependencies&lt;/strong&gt; — Python standard library only:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;brazilian_soccer_mcp.py&lt;/code&gt; (291 lines) — a &lt;code&gt;SoccerData&lt;/code&gt; service plus the MCP layer.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;server.py&lt;/code&gt; (5 lines) — entrypoint, calls &lt;code&gt;serve()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;test_brazilian_soccer_mcp.py&lt;/code&gt; (46 lines) — 7 BDD-named tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Was the Kaggle data really blended and loaded? Yes.&lt;/strong&gt; All six files, verified in-run: &lt;code&gt;loaded 23954 matches and 18207 players&lt;/code&gt;, which is exactly &lt;code&gt;10296 + 4180 + 1337 + 1255 + 6886&lt;/code&gt;. Five match files with three different row shapes are normalized into one frozen &lt;code&gt;Match&lt;/code&gt; dataclass by a dispatching row-mapper:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kind&lt;/th&gt;
&lt;th&gt;Files&lt;/th&gt;
&lt;th&gt;Columns it reads&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;standard&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Brasileirao, Copa do Brasil, Libertadores&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;datetime&lt;/code&gt;, &lt;code&gt;home_team&lt;/code&gt;, &lt;code&gt;away_team&lt;/code&gt;, &lt;code&gt;home_goal&lt;/code&gt;, &lt;code&gt;season&lt;/code&gt;, &lt;code&gt;round&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;extended&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;BR-Football-Dataset&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;date&lt;/code&gt;, &lt;code&gt;home&lt;/code&gt;, &lt;code&gt;away&lt;/code&gt;, &lt;code&gt;tournament&lt;/code&gt;, plus corners/shots kept in an &lt;code&gt;extras&lt;/code&gt; dict&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;historic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;novo_campeonato_brasileiro&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Data&lt;/code&gt; (DD/MM/YYYY), &lt;code&gt;Equipe_mandante&lt;/code&gt;, &lt;code&gt;Gols_mandante&lt;/code&gt;, &lt;code&gt;Arena&lt;/code&gt;, &lt;code&gt;Vencedor&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Team names are matched through a &lt;code&gt;normalized()&lt;/code&gt; function that strips accents, lowercases, and removes state suffixes via a regex listing all 27 Brazilian UFs plus South American country codes — so &lt;code&gt;São Paulo-SP&lt;/code&gt; and &lt;code&gt;Sao Paulo&lt;/code&gt; compare equal. Dates go through a multi-format &lt;code&gt;parse_date&lt;/code&gt;. Both are direct answers to the spec's data-quality notes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What database backend? None.&lt;/strong&gt; There is no database and no graph store — no SQLite, no Neo4j, no networkx, no index of any kind. &lt;code&gt;SoccerData&lt;/code&gt; holds &lt;code&gt;self.matches: list[Match]&lt;/code&gt; and &lt;code&gt;self.players: list[dict]&lt;/code&gt;, and every query is a &lt;strong&gt;linear scan&lt;/strong&gt; over all 23,954 matches, re-filtered per call. The agent's own summary called it an "indexed CSV data layer"; that is not accurate — &lt;code&gt;defaultdict&lt;/code&gt; is imported and never used. At this data size a scan is fast enough that nothing catches it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On "knowledge graph":&lt;/strong&gt; the spec's overview asks for "a knowledge graph interface for Brazilian soccer data", but its &lt;em&gt;Required Capabilities&lt;/em&gt; section — which is what the pinned &lt;code&gt;REQUIREMENTS.json&lt;/code&gt; was authored from — specifies query categories, not storage. The word "graph" appears &lt;strong&gt;zero times&lt;/strong&gt; in &lt;code&gt;REQUIREMENTS.json&lt;/code&gt;. So this solution scores 12/12 while containing no graph whatsoever: no nodes, no edges, no traversal. It is a flat table with filters. Every brazil run in this project has been graded the same way, so the comparison between runs is fair — but the checklist does not test the spec's headline framing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A defect the gate did not catch.&lt;/strong&gt; Because the source files overlap in coverage (BR-Football 2014–2023, Brasileirao_Matches 2012–2022, novo_campeonato 2003–2019) and &lt;code&gt;load()&lt;/code&gt; concatenates without deduplication, the same real-world match is counted two or three times. The agent noticed this &lt;em&gt;partially&lt;/em&gt; — it added a guard so &lt;code&gt;standings()&lt;/code&gt; uses only the dedicated file, but only for Brasileirão and only for seasons 2003–2019, which is why the 2019 table it printed is historically correct (Flamengo, 38 played, 90 points).&lt;/p&gt;

&lt;p&gt;Everything else still double-counts. The run's own MCP handshake demonstrates it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"team"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Corinthians"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"season"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2022&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"venue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"home"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"matches"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"wins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"draws"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"losses"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"goals_for"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Brasileirão club plays &lt;strong&gt;19 home league matches&lt;/strong&gt; a season; even adding home cup and Libertadores ties, ~25 is the ceiling. 44 is the league fixtures counted twice plus the cups. The spec's own worked example says Corinthians' 2022 home record is 19 matches, 11 W, 5 D, 3 L.&lt;/p&gt;

&lt;p&gt;The tests do not catch this because they assert &lt;em&gt;accounting identities&lt;/em&gt; — &lt;code&gt;matches == wins + draws + losses&lt;/code&gt;, &lt;code&gt;points == wins*3 + draws&lt;/code&gt; — which stay true when every match is double-counted. The judge flagged the overlap as &lt;strong&gt;low/enhancement&lt;/strong&gt; and scoped it to &lt;code&gt;standings()&lt;/code&gt; alone; it is broader than that, and it is a correctness defect in &lt;code&gt;team_statistics&lt;/code&gt;, &lt;code&gt;head_to_head&lt;/code&gt;, &lt;code&gt;search_matches&lt;/code&gt; and &lt;code&gt;aggregate_statistics&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is a finding about the task's checklist, not a retraction of the run.&lt;/em&gt; The 3m19s and the 12/12 stand as measured. But "passes the pinned requirements" and "returns correct answers" are not the same thing, and here they diverge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Slowest logged pass — 64 minutes of Objective-C
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 5, objc, prompt=neutral&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Experiment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;adrianco/experiment-46-opus5-brazil&lt;/code&gt; rep1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Duration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;64.0 min&lt;/strong&gt; · 175 turns · 174 tool calls · &lt;strong&gt;$31.31&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12/12 requirements · coverage 1.00 · &lt;code&gt;code_quality&lt;/code&gt; 1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A different failure mode entirely: this one isn't gold-plating, it's the &lt;strong&gt;language&lt;/strong&gt;. Nine thousand lines of &lt;code&gt;.m&lt;/code&gt; and &lt;code&gt;.h&lt;/code&gt; — a hand-rolled CSV parser, match/player models, a query engine and an MCP server — because Objective-C offers no ecosystem to lean on here. The tool mix says it plainly: 59 Edits, 42 Writes, 54 Bash, and only &lt;strong&gt;2 Reads&lt;/strong&gt;. It was not exploring. It was typing.&lt;/p&gt;

&lt;p&gt;The cleanest way to see the cost is to hold the model and task fixed and vary only the language. Opus 5 ran all 13 on this task, and every one scored 1.00:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;clojure&lt;/th&gt;
&lt;th&gt;python&lt;/th&gt;
&lt;th&gt;rust&lt;/th&gt;
&lt;th&gt;swift&lt;/th&gt;
&lt;th&gt;java&lt;/th&gt;
&lt;th&gt;go&lt;/th&gt;
&lt;th&gt;cpp&lt;/th&gt;
&lt;th&gt;erlang&lt;/th&gt;
&lt;th&gt;c&lt;/th&gt;
&lt;th&gt;csharp&lt;/th&gt;
&lt;th&gt;elixir&lt;/th&gt;
&lt;th&gt;objc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;min&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5.7&lt;/td&gt;
&lt;td&gt;16.1&lt;/td&gt;
&lt;td&gt;38.2&lt;/td&gt;
&lt;td&gt;39.4&lt;/td&gt;
&lt;td&gt;41.4&lt;/td&gt;
&lt;td&gt;42.2&lt;/td&gt;
&lt;td&gt;42.3&lt;/td&gt;
&lt;td&gt;52.8&lt;/td&gt;
&lt;td&gt;53.2&lt;/td&gt;
&lt;td&gt;56.4&lt;/td&gt;
&lt;td&gt;58.3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;64.0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;$&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2.55&lt;/td&gt;
&lt;td&gt;9.38&lt;/td&gt;
&lt;td&gt;20.08&lt;/td&gt;
&lt;td&gt;16.87&lt;/td&gt;
&lt;td&gt;20.18&lt;/td&gt;
&lt;td&gt;22.35&lt;/td&gt;
&lt;td&gt;17.50&lt;/td&gt;
&lt;td&gt;23.01&lt;/td&gt;
&lt;td&gt;24.11&lt;/td&gt;
&lt;td&gt;39.05&lt;/td&gt;
&lt;td&gt;33.61&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;31.31&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Same model, same spec, same 1.00 — an &lt;strong&gt;11× spread in wall clock and 15× in cost&lt;/strong&gt;, decided entirely by the language. (TypeScript is omitted: it passed in 59.9 min but recorded &lt;code&gt;$0.00&lt;/code&gt;, a telemetry gap, not a free run.) This is the single strongest illustration of retort's premise that the &lt;em&gt;stack&lt;/em&gt; is the unit of measurement, not the model.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. &lt;code&gt;py-catalog-reservations&lt;/code&gt; — the modify-existing task
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://dev.totasks/py-catalog-reservations/"&gt;&lt;code&gt;tasks/py-catalog-reservations/&lt;/code&gt;&lt;/a&gt; · 18 runs&lt;/p&gt;

&lt;p&gt;The other two tasks build from an empty directory. This one ships a working 111-line &lt;code&gt;catalog/&lt;/code&gt; package (models, store, loans, service facade) &lt;strong&gt;and its existing test suite&lt;/strong&gt;, then asks for a &lt;em&gt;reservations&lt;/em&gt; feature: reserve only when zero copies are available, FIFO ordering, automatic fulfilment when a copy is returned, cancellation, all exposed through the facade — without breaking the six tests that already pass (a &lt;code&gt;no_regression&lt;/code&gt; gate).&lt;/p&gt;

&lt;p&gt;Built for the &lt;strong&gt;graphify tooling factor&lt;/strong&gt;: it needs comprehension of code the agent did not write.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fastest logged pass — 72.8s
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.8, &lt;code&gt;tooling=none&lt;/code&gt;, python&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Experiment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;adrianco/experiment-44-graphify-catalog&lt;/code&gt; rep1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Duration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;72.8 s&lt;/strong&gt; · 15 turns · $0.43 · 302,025 tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;11/11 requirements · 14 tests pass (6 existing + 8 new) · coverage 0.99&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Read] TASK.md
[Read] catalog/models.py, catalog/store.py, catalog/loans.py,
       catalog/service.py, tests/test_catalog.py, conftest.py   # read EVERYTHING first
[TEXT] "Now I'll implement the reservations capability."
[Edit]  catalog/models.py          # add the Reservation type
[Write] catalog/reservations.py    # new service
[Edit]  catalog/service.py  (×2)   # wire into the facade
[TEXT] "Now the tests for the new behavior:"
[Write] tests/test_reservations.py
[Bash] python -m pytest -q     -&amp;gt; command not found: python
[Bash] python3 -m pytest -q    -&amp;gt; .............. [100%] 14 passed in 0.01s
[TEXT] "All 14 tests pass — the 6 existing tests plus 8 new reservation tests."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the shape versus the greenfield task: &lt;strong&gt;six reads before the first edit.&lt;/strong&gt; On a modify-existing task the agent front-loads comprehension, then edits surgically — &lt;code&gt;models.py&lt;/code&gt; and &lt;code&gt;service.py&lt;/code&gt; are edited, not rewritten. That difference is the whole reason this task exists.&lt;/p&gt;

&lt;h3&gt;
  
  
  Slowest logged pass — 4.5 min, and free
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Qwen3-Coder-Next 80B &lt;strong&gt;local&lt;/strong&gt; (Hermes + oMLX), &lt;code&gt;tooling=beads&lt;/code&gt;, python&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Experiment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;adrianco/experiment-45-graphify-local-catalog&lt;/code&gt; rep1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Duration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;4.5 min&lt;/strong&gt; (3.7×) · 1,000,059 tokens · &lt;strong&gt;$0.00&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;11/11 requirements · coverage 1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The third failure mode is not a failure at all. This run is 3.7× slower than the cloud record and costs &lt;strong&gt;nothing&lt;/strong&gt; — it ran on a laptop. For a task you run once, $0.43 and 73 seconds wins; for one you run in a loop, the free option changes the arithmetic. It is the clearest case for reading the cost column next to the clock.&lt;/p&gt;

&lt;p&gt;One pattern worth flagging inside this experiment: the three slowest passing runs are all &lt;code&gt;tooling=beads&lt;/code&gt; (4.5, 4.3, 4.2 min), while every &lt;code&gt;none&lt;/code&gt; and &lt;code&gt;graphify&lt;/code&gt; run came in faster (2.6–3.3 min). That matches the README's factor analysis, where &lt;code&gt;beads&lt;/code&gt; measurably &lt;em&gt;adds&lt;/em&gt; cost. At n=3 per arm it is a consistent ordering rather than a proven effect — but it is the direction the tooling factor exists to detect.&lt;/p&gt;




&lt;h2&gt;
  
  
  The &lt;code&gt;python&lt;/code&gt; vs &lt;code&gt;python3&lt;/code&gt; stumble — found here, since fixed
&lt;/h2&gt;

&lt;p&gt;All three record holders — two different vendors, three different models — ran &lt;code&gt;python&lt;/code&gt;, got &lt;code&gt;command not found&lt;/code&gt;, and retried with &lt;code&gt;python3&lt;/code&gt;. Each paid a step for it.&lt;/p&gt;

&lt;p&gt;That is a property of &lt;em&gt;this machine&lt;/em&gt; (macOS ships &lt;code&gt;python3&lt;/code&gt; only) being charged to the model as agent work. Writing this page is what made it visible, because it is the one place three runs sit side by side.&lt;/p&gt;

&lt;p&gt;Pulling the thread found two bigger problems behind it. &lt;strong&gt;&lt;code&gt;pip install&lt;/code&gt; was a coin flip:&lt;/strong&gt; against a Homebrew interpreter it fails with &lt;code&gt;externally-managed-environment&lt;/code&gt;, so whether an agent could install a dependency at all came down to whether it happened to build a venv first — some did (Fable 5 above), some wrote stdlib-only code instead (Terra above). That is a difference in the &lt;em&gt;stack&lt;/em&gt;, silently attributed to the model. And &lt;strong&gt;the scorer built a different interpreter than the agent's&lt;/strong&gt;: it reuses a venv if the agent shipped one, otherwise it creates a throwaway — so a suite could be written against one interpreter and graded on another.&lt;/p&gt;

&lt;p&gt;Retort now provisions a venv into every python workspace before the agent starts, with &lt;code&gt;python&lt;/code&gt;, &lt;code&gt;pip&lt;/code&gt; and pytest already on PATH, and the scorer reuses that same venv. Provisioning happens outside the timed window, so this removes a turn without adding time. Python runs from before and after this change are &lt;strong&gt;not turn-count comparable&lt;/strong&gt; — it is logged in &lt;a href="//experiments-blog.md"&gt;experiments-blog.md&lt;/a&gt; with the other harness changes that moved numbers.&lt;/p&gt;

&lt;p&gt;The general lesson is the one this project keeps relearning: a benchmark number always includes some of the bench.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
    </item>
    <item>
      <title>The Retort Experiment Index: What Was Measured, and What the Harness Was Doing at the Time</title>
      <dc:creator>Adrian Cockcroft</dc:creator>
      <pubDate>Thu, 30 Jul 2026 23:15:42 +0000</pubDate>
      <link>https://dev.to/adrianco_54/the-retort-experiment-index-what-was-measured-and-what-the-harness-was-doing-at-the-time-2819</link>
      <guid>https://dev.to/adrianco_54/the-retort-experiment-index-what-was-measured-and-what-the-harness-was-doing-at-the-time-2819</guid>
      <description>&lt;p&gt;This is a snapshot of an auto-generated analysis report from &lt;a href="https://github.com/adrianco/retort/blob/main/experiments-blog.md" rel="noopener noreferrer"&gt;https://github.com/adrianco/retort/blob/main/experiments-blog.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Published 2026-07-30 · updated 2026-07-30 — Adrian Cockcroft&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An index, not an argument. Retort has run &lt;strong&gt;1,014 scored runs across 56 experiment groups and 13 languages&lt;/strong&gt;; this page says what each group was for, where to read the detail, and — the part that matters most for reading an old number — &lt;strong&gt;what the harness itself was doing at the time&lt;/strong&gt;. Several published figures moved because the tooling was fixed, not because a model changed.&lt;/p&gt;

&lt;p&gt;Detail lives in &lt;a href="//docs/past-experiments.md"&gt;&lt;code&gt;docs/past-experiments.md&lt;/code&gt;&lt;/a&gt;. Current recommendations: &lt;a href="//optimal-blog.md"&gt;&lt;code&gt;optimal-blog.md&lt;/code&gt;&lt;/a&gt; and the machine-readable &lt;a href="//optimal.json"&gt;&lt;code&gt;optimal.json&lt;/code&gt;&lt;/a&gt;. What the agents are asked to build, and the fastest and slowest passing run for each: &lt;a href="//tasks-blog.md"&gt;&lt;code&gt;tasks-blog.md&lt;/code&gt;&lt;/a&gt;. What's next: &lt;a href="//docs/future-experiments.md"&gt;&lt;code&gt;docs/future-experiments.md&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The categories
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;The question&lt;/th&gt;
&lt;th&gt;Experiments&lt;/th&gt;
&lt;th&gt;Written up in&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloud models&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Which frontier model, at what cost and reliability?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;exp-1&lt;/code&gt; (first grid: opus vs sonnet, 6 languages) · &lt;code&gt;exp-3/4/5/6/8&lt;/code&gt; (Opus 4.6 → 4.7 → 4.8) · &lt;code&gt;exp-7&lt;/code&gt; (&lt;strong&gt;fast mode&lt;/strong&gt; as a factor) · &lt;code&gt;exp-10&lt;/code&gt; (Fable 5) · &lt;code&gt;exp-15&lt;/code&gt; (Sonnet 5) · &lt;code&gt;exp-46&lt;/code&gt; (Opus 5, all 13 languages × both tasks) · &lt;code&gt;exp-48&lt;/code&gt; (Fable 5 gap-fill) · &lt;code&gt;exp-53&lt;/code&gt; (&lt;strong&gt;Codex / GPT-5.6&lt;/strong&gt; — first non-Claude lineage) · &lt;code&gt;exp-55&lt;/code&gt; (Terra vs Opus 5 at matched thinking levels)&lt;/td&gt;
&lt;td&gt;
&lt;a href="//model-blog.md"&gt;model&lt;/a&gt;, &lt;a href="//versions-blog.md"&gt;versions&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Local models&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Can a laptop do this, and what does it take?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;exp-12&lt;/code&gt; (Qwen2.5-Coder 7B via Ollama — first local run, n=1) · &lt;code&gt;exp-16/17/18&lt;/code&gt; (Qwen3-Coder → Hermes → the lcm context engine) · &lt;code&gt;exp-20&lt;/code&gt; (first all-9-language local sweep) · &lt;code&gt;exp-22/23&lt;/code&gt; (Qwen-Next 80B, Devstral) · &lt;code&gt;exp-27/28&lt;/code&gt; (sampling factorial, then the re-baseline) · &lt;code&gt;exp-29/30/33/36/37/38&lt;/code&gt; (the 80B, language by language) · &lt;code&gt;exp-47&lt;/code&gt; (gpt-oss-20b — first non-Qwen local lineage)&lt;/td&gt;
&lt;td&gt;
&lt;a href="//harness-blog.md"&gt;harness&lt;/a&gt;, &lt;a href="//model-blog.md"&gt;model&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Config levers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Same model, different stack — what actually moves?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;exp-34/35&lt;/code&gt; (lcm &lt;code&gt;context_threshold&lt;/code&gt; — the biggest local lever) · &lt;code&gt;exp-27&lt;/code&gt; (temperature / top_p / top_k / repetition_penalty, Res IV) · &lt;code&gt;exp-24&lt;/code&gt; (KV prefix cache — null: these runs are generation-bound, not prefill-bound) · &lt;code&gt;exp-16&lt;/code&gt; (context 64K → 128K → 256K) · &lt;code&gt;exp-49&lt;/code&gt; (&lt;strong&gt;thinking level&lt;/strong&gt;)&lt;/td&gt;
&lt;td&gt;
&lt;a href="//optimal-blog.md"&gt;optimal&lt;/a&gt;, &lt;a href="//harness-blog.md"&gt;harness&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Task difficulty&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Routine REST API vs a 12-capability MCP server&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;exp-2&lt;/code&gt; (introduces the hard task) · &lt;code&gt;exp-25/26&lt;/code&gt; (hard task, local 35B) · &lt;code&gt;exp-31/39&lt;/code&gt; (hard task, 80B — config-invariant) · &lt;code&gt;exp-50&lt;/code&gt; (re-test with the turn cap removed)&lt;/td&gt;
&lt;td&gt;&lt;a href="//model-blog.md"&gt;model&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Prompt / method&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Does prescribing BDD/TDD/ATDD change the outcome?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;exp-13/14&lt;/code&gt; (cloud, hard task) · &lt;code&gt;exp-19&lt;/code&gt; (local 35B) · &lt;code&gt;exp-32&lt;/code&gt; (local 80B — does a weaker model need the scaffolding more?)&lt;/td&gt;
&lt;td&gt;&lt;a href="//prompt-blog.md"&gt;prompt&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent &amp;amp; tooling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;What drives the run, and what does it get to use?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;exp-11&lt;/code&gt; (Gemini — first cross-&lt;em&gt;agent&lt;/em&gt; design; scaffolded, never run) · &lt;code&gt;exp-53&lt;/code&gt; (codex, where the agent factor actually landed) · &lt;code&gt;exp-44/45&lt;/code&gt; (&lt;strong&gt;graphify&lt;/strong&gt; knowledge-graph, frontier and local arms) · &lt;code&gt;beads&lt;/code&gt; throughout&lt;/td&gt;
&lt;td&gt;&lt;a href="//optimal-blog.md"&gt;optimal&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Self-repair&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Does a second attempt with the evaluator's feedback help?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;exp-21&lt;/code&gt; (35B) · &lt;code&gt;exp-41&lt;/code&gt; (80B, iteration 2) — an inline second chance now runs by default, at half credit&lt;/td&gt;
&lt;td&gt;&lt;a href="//model-blog.md"&gt;model&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two candidates were &lt;strong&gt;rejected before running&lt;/strong&gt;: Ornith-1.0-35B (vision-optimized, agent-hostile sampling) and Poolside Laguna XS 2.1 (architecture not in mainline serving). Both are documented with their gate-probe evidence at the end of &lt;a href="//docs/past-experiments.md"&gt;&lt;code&gt;docs/past-experiments.md&lt;/code&gt;&lt;/a&gt;, because a candidate ruled out cheaply is still a result.&lt;/p&gt;




&lt;h2&gt;
  
  
  Harness changes that moved published numbers
&lt;/h2&gt;

&lt;p&gt;Check this before comparing a number from one experiment against another. None of these involved a model changing.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Era&lt;/th&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;th&gt;What it moved&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;exp-17 → exp-27&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Three unrecorded stack variables at once&lt;/strong&gt; — playpen under &lt;code&gt;/var&lt;/code&gt; (writes silently refused: 41/48 runs in exp-27, 6/6 in exp-26), oMLX &lt;code&gt;temperature: 1.0&lt;/code&gt;, and context silently 128K while both the config and provenance read 256K&lt;/td&gt;
&lt;td&gt;Every Hermes-era local result in this range is an understated &lt;strong&gt;floor&lt;/strong&gt;, not a measurement. The exp-28 re-baseline supersedes them. It also overturned the "niche-language wall" — though exp-38 later confirmed clojure/csharp/elixir &lt;em&gt;are&lt;/em&gt; genuinely 0.00 on a fixed stack.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;exp-34 → exp-38&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;lcm &lt;code&gt;context_threshold&lt;/code&gt; 0.35 → 0.9&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TypeScript on the 80B went 0.33 → 1.00. A config lever, not a capability.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;exp-43&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Test-command exit code as the universal pass signal&lt;/strong&gt;; 900s scorer timeout; process-group reaping&lt;/td&gt;
&lt;td&gt;C/C++/Swift were being scored 0 for unparsed output, and leaked servers squatted ports and false-failed later cells.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;exp-46&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Run timeout 60 → 120 min&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Opus 5 is 3–5× slower and brazil cells average 47 min — the old wall was cutting off work in progress.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;exp-46&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;pytest exit-code fallback&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A project whose 239 tests all passed scored &lt;code&gt;test_coverage=0&lt;/code&gt; because its own pytest flags suppressed the summary line.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;exp-49&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;&lt;code&gt;effort&lt;/code&gt; became a factor&lt;/strong&gt; — and &lt;code&gt;aggregate&lt;/code&gt; was silently dropping factor columns it didn't know&lt;/td&gt;
&lt;td&gt;Everything before exp-49 ran at each CLI's default thinking level, uncontrolled; and all 63 exp-49 runs first landed in &lt;code&gt;master.db&lt;/code&gt; &lt;em&gt;without&lt;/em&gt; the very factor they were built to test.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;exp-50&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Hermes turn cap (30) never reconciled with the declared 200&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Local runs could be truncated mid-work and scored as model failures.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;exp-53&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Codex telemetry + per-token pricing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Codex runs recorded 0 tokens, 0 turns and \$0 until the parser matched the real CLI event shape. Costs are now priced from published rates for every vendor, since Claude Max reports a price it doesn't bill and Codex reports nothing at all.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;exp-55&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;&lt;code&gt;xhigh&lt;/code&gt; was missing&lt;/strong&gt; from retort's effort levels&lt;/td&gt;
&lt;td&gt;exp-49's "full sweep" had skipped a level that exists in both CLIs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ongoing&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Attribution&lt;/strong&gt; — local runs wrote a blank &lt;code&gt;model&lt;/code&gt;; experiment labels are now &lt;code&gt;&amp;lt;githubid&amp;gt;/exp#&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;~250 rows are identified by experiment slug rather than model id, and a stack predicate that enumerated local models &lt;em&gt;by exclusion&lt;/em&gt; once counted exp-47's gpt-oss runs as the 35B's.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;post-exp-55&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Python workspaces get a provisioned venv&lt;/strong&gt; (&lt;code&gt;python&lt;/code&gt;, &lt;code&gt;pip&lt;/code&gt; and pytest on PATH)&lt;/td&gt;
&lt;td&gt;Every earlier python run inherited a host with &lt;strong&gt;no &lt;code&gt;python&lt;/code&gt;&lt;/strong&gt; — only Homebrew's &lt;code&gt;python3&lt;/code&gt;. The fastest recorded run of all three tasks, across two vendors and three models, spent a turn on &lt;code&gt;command not found&lt;/code&gt; and a retry. Dependency installs were also luck: &lt;code&gt;pip&lt;/code&gt; against a Homebrew interpreter fails &lt;code&gt;externally-managed-environment&lt;/code&gt;, so whether an agent could install anything depended on whether it happened to build its own venv. And the scorer built a &lt;em&gt;different&lt;/em&gt; interpreter than the agent's. Python runs before and after this are not turn-count comparable.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The shape that keeps recurring: &lt;strong&gt;a failing model and a broken harness are identical in the scores.&lt;/strong&gt; &lt;code&gt;retort diagnose&lt;/code&gt; exists to separate them, and the standing rule is that a surprising zero gets reproduced by hand before it gets published. The full post-mortems are in &lt;a href="//docs/past-experiments.md"&gt;Historical: harness bugs &amp;amp; the local re-baseline saga&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusions that were retracted
&lt;/h2&gt;

&lt;p&gt;Kept visible, because the corrections are more useful than the originals.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Opus 5 is the only model that clears the hard task everywhere"&lt;/strong&gt; (exp-46) — withdrawn by exp-48. Fable 5 had never been &lt;em&gt;run&lt;/em&gt; on 9 of the 13 languages; when it was, it cleared them at roughly half the price. An unrun cell and an unpassable cell look identical in a table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Newer Claude versions take steadily more turns"&lt;/strong&gt; — corrected by exp-49. Three generations sit at ~9–13 turns; the apparent trend came from one old experiment's figures, which don't replicate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Thinking level explains the cross-version cost gap"&lt;/strong&gt; — retracted by the experiment run to test it. The single run that motivated it (33 turns at &lt;code&gt;max&lt;/code&gt;) did not replicate: 14, then 18.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"gpt-oss matches the 80B on Go at 3.6× the speed"&lt;/strong&gt; (exp-47, n=3) — removed at n=5, where Go fell to 0.80.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"The local hard-task wall is a turn cap"&lt;/strong&gt; (exp-50's whole premise) — wrong. &lt;code&gt;api_calls&lt;/code&gt; is 1:1 with turns, not 3:1, so nothing had been truncated. The wall is real.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Four of those five came from reading a single run as a result.&lt;/p&gt;




&lt;h2&gt;
  
  
  The slowest successful run
&lt;/h2&gt;

&lt;p&gt;&lt;a href="//tasks-blog.md"&gt;tasks-blog.md&lt;/a&gt; shows the fastest and slowest passing run for each task. The slow end is the more instructive one, because nothing fails there either.&lt;/p&gt;

&lt;p&gt;Both of these are the &lt;strong&gt;same task&lt;/strong&gt; — &lt;code&gt;rest-api-crud&lt;/code&gt;, python, a books CRUD API — and both score &lt;code&gt;requirement_coverage = 1.00&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Fastest (Fable 5, &lt;code&gt;effort=low&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;Slowest (Opus 5, &lt;code&gt;effort=max&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Wall clock&lt;/td&gt;
&lt;td&gt;44.5 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;45.6 min&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;61×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;$0.86&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$24.96&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;29×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tokens&lt;/td&gt;
&lt;td&gt;105,745&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;18,448,183&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;174×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Turns&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;94&lt;/strong&gt; (256 tool calls)&lt;/td&gt;
&lt;td&gt;13×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source + test lines&lt;/td&gt;
&lt;td&gt;194&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2,351&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tests&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;104&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;17×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;requirement_coverage&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test_coverage&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maintainability&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.27&lt;/td&gt;
&lt;td&gt;0.85&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;token_efficiency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;0.0019&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The slow run is &lt;strong&gt;not a failure, and not slop&lt;/strong&gt;. It scores &lt;em&gt;better&lt;/em&gt; on maintainability, idiomaticity and coverage. It built a seven-module package, ran &lt;code&gt;ruff&lt;/code&gt; on itself unprompted, spawned a subagent, and performed &lt;strong&gt;mutation testing&lt;/strong&gt; — on a books CRUD API. Every one of the judge's five findings is an &lt;code&gt;info&lt;/code&gt; describing scope &lt;em&gt;beyond&lt;/em&gt; the spec: a &lt;code&gt;PATCH&lt;/code&gt; endpoint, filtering/sorting/pagination, a hand-written 304-line OpenAPI 3.0 document served at &lt;code&gt;GET /openapi.json&lt;/code&gt;, WAL journaling and busy-timeouts on SQLite, and validation for NUL bytes and SQLite integer bounds.&lt;/p&gt;

&lt;p&gt;Nobody asked for any of it. The task asked for five endpoints, a health check, and at least three tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What actually goes wrong is that the gate cannot see the difference.&lt;/strong&gt; &lt;code&gt;requirement_coverage&lt;/code&gt; is 1.00 for both, so pass-proportion — the headline metric of this whole project — rates a 44-second $0.86 run and a 46-minute $25 run as identical. That is correct by its own definition and still the most misleading number on the page unless you read cost beside it. &lt;code&gt;token_efficiency&lt;/code&gt; is the response that &lt;em&gt;does&lt;/em&gt; separate them, by a factor of 534.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The dial also buys variance, not just cost.&lt;/strong&gt; Within exp-55, the same Opus 5 python cell run twice:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;effort&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;rep1&lt;/th&gt;
&lt;th&gt;rep2&lt;/th&gt;
&lt;th&gt;mean cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;1.9 min&lt;/td&gt;
&lt;td&gt;2.2 min&lt;/td&gt;
&lt;td&gt;$0.76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;3.0 min&lt;/td&gt;
&lt;td&gt;3.2 min&lt;/td&gt;
&lt;td&gt;$1.04&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;6.2 min&lt;/td&gt;
&lt;td&gt;5.6 min&lt;/td&gt;
&lt;td&gt;$1.68&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xhigh&lt;/td&gt;
&lt;td&gt;15.3 min&lt;/td&gt;
&lt;td&gt;8.6 min&lt;/td&gt;
&lt;td&gt;$2.55&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;max&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;24.5 min&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;45.6 min&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$19.21&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;At &lt;code&gt;low&lt;/code&gt; the two replicates agree within 15%; at &lt;code&gt;max&lt;/code&gt; they differ by 1.9×, and cost by 1.9×. Ten of ten cells score 1.00. On this task the thinking dial is a 25× cost multiplier that buys nothing measurable and becomes unpredictable at the top. &lt;em&gt;At n=2 the variance claim is suggestive, not established&lt;/em&gt; — but the cost is not in doubt. Meanwhile GPT-5.6 Terra ran the same ten cells between 1.4 and 4.0 minutes for $0.10–$0.33, also 1.00 throughout.&lt;/p&gt;

&lt;p&gt;One more thing the log shows: the slow run spent its opening turns probing the host interpreter and discovered that the preinstalled FastAPI was &lt;strong&gt;broken&lt;/strong&gt; (pydantic v1 cannot build models on Python 3.14), then chose Flask instead. That is the environment leaking into the measurement again — and it is the same class of problem as the missing &lt;code&gt;python&lt;/code&gt;, now addressed by &lt;a href="//tasks-blog.md"&gt;provisioning a clean venv per workspace&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reading the numbers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pass-proportion&lt;/strong&gt; is the fraction of runs that &lt;em&gt;fully&lt;/em&gt; implement the spec — every requirement on a pinned checklist, with tests that actually execute, verified by an independent LLM judge. A run that misses one requirement scores 0, not 0.9. Read a cell as &lt;em&gt;the probability that one unattended run comes out completely correct&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Three things to check before trusting one: &lt;strong&gt;&lt;code&gt;n&lt;/code&gt;&lt;/strong&gt; (many cells are 1–3 runs, and results at n=1 have reversed repeatedly in this project), &lt;strong&gt;the judge&lt;/strong&gt; (recorded per experiment in &lt;code&gt;master.db&lt;/code&gt; since exp-53; &lt;code&gt;requirement_coverage&lt;/code&gt; is one model's opinion, and only pools across experiments graded the same way), and &lt;strong&gt;the language mix&lt;/strong&gt; (an all-language average silently compares models that were run on different sets of languages — the per-language matrix is the like-for-like view).&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>performance</category>
      <category>testing</category>
    </item>
    <item>
      <title>Testing Claude from 4.7 to Opus 5 and Fable 5 - Why Are Newer Models Slower?</title>
      <dc:creator>Adrian Cockcroft</dc:creator>
      <pubDate>Mon, 27 Jul 2026 21:56:21 +0000</pubDate>
      <link>https://dev.to/adrianco_54/testing-claude-from-47-to-opus-5-and-fable-5-why-are-newer-models-slower-4jhj</link>
      <guid>https://dev.to/adrianco_54/testing-claude-from-47-to-opus-5-and-fable-5-why-are-newer-models-slower-4jhj</guid>
      <description>&lt;p&gt;What follows is re-generated automatically whenever relevant experiments finish. This is the current snapshot of &lt;a href="https://github.com/adrianco/retort/blob/main/versions-blog.md" rel="noopener noreferrer"&gt;https://github.com/adrianco/retort/blob/main/versions-blog.md&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Unit of Choice Is Model × Thinking Level, Not Model
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Published 2026-07-25 · updated 2026-07-30 — Adrian Cockcroft&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For a year the question has been "which model should I use?" That question is underspecified. Every frontier model now has a &lt;strong&gt;thinking-level&lt;/strong&gt; dial, and on the evidence below the dial moves cost more than the model choice does — while moving the result not at all.&lt;/p&gt;

&lt;p&gt;One task (a "bookshop" REST API), one prompt, one judge throughout. First four Claude versions × five thinking levels, three replicates each — &lt;strong&gt;21 cells, 63 runs, zero failures&lt;/strong&gt;. Then the same sweep against &lt;strong&gt;OpenAI's GPT-5.6 Terra&lt;/strong&gt;, to see whether any of it is a Claude peculiarity. It isn't, but the two vendors turn out to have built the dial to do different things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every cell passed. The bill spans 16×.
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;model&lt;/th&gt;
&lt;th&gt;effort&lt;/th&gt;
&lt;th&gt;turns&lt;/th&gt;
&lt;th&gt;tokens&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;cost&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;seconds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Opus 4.8&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;default&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;9.3&lt;/td&gt;
&lt;td&gt;245 K&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.42&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;79&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.8&lt;/td&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;10.3&lt;/td&gt;
&lt;td&gt;272 K&lt;/td&gt;
&lt;td&gt;$0.57&lt;/td&gt;
&lt;td&gt;83&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.8&lt;/td&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;14.0&lt;/td&gt;
&lt;td&gt;393 K&lt;/td&gt;
&lt;td&gt;$0.60&lt;/td&gt;
&lt;td&gt;117&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.7&lt;/td&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;7.3&lt;/td&gt;
&lt;td&gt;273 K&lt;/td&gt;
&lt;td&gt;$0.61&lt;/td&gt;
&lt;td&gt;56&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.8&lt;/td&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;12.7&lt;/td&gt;
&lt;td&gt;348 K&lt;/td&gt;
&lt;td&gt;$0.66&lt;/td&gt;
&lt;td&gt;97&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.7&lt;/td&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;8.7&lt;/td&gt;
&lt;td&gt;329 K&lt;/td&gt;
&lt;td&gt;$0.67&lt;/td&gt;
&lt;td&gt;65&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.7&lt;/td&gt;
&lt;td&gt;default&lt;/td&gt;
&lt;td&gt;10.3&lt;/td&gt;
&lt;td&gt;397 K&lt;/td&gt;
&lt;td&gt;$0.75&lt;/td&gt;
&lt;td&gt;91&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Opus 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;low&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;15.7&lt;/td&gt;
&lt;td&gt;432 K&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.75&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;114&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.7&lt;/td&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;11.7&lt;/td&gt;
&lt;td&gt;451 K&lt;/td&gt;
&lt;td&gt;$0.79&lt;/td&gt;
&lt;td&gt;97&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 5&lt;/td&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;18.0&lt;/td&gt;
&lt;td&gt;436 K&lt;/td&gt;
&lt;td&gt;$0.86&lt;/td&gt;
&lt;td&gt;142&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fable 5&lt;/td&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;8.0&lt;/td&gt;
&lt;td&gt;131 K&lt;/td&gt;
&lt;td&gt;$0.91&lt;/td&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.8-fast&lt;/td&gt;
&lt;td&gt;default&lt;/td&gt;
&lt;td&gt;11.5&lt;/td&gt;
&lt;td&gt;204 K&lt;/td&gt;
&lt;td&gt;$0.95&lt;/td&gt;
&lt;td&gt;125&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.7&lt;/td&gt;
&lt;td&gt;max&lt;/td&gt;
&lt;td&gt;14.0&lt;/td&gt;
&lt;td&gt;588 K&lt;/td&gt;
&lt;td&gt;$1.13&lt;/td&gt;
&lt;td&gt;171&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fable 5&lt;/td&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;13.3&lt;/td&gt;
&lt;td&gt;369 K&lt;/td&gt;
&lt;td&gt;$1.13&lt;/td&gt;
&lt;td&gt;109&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fable 5&lt;/td&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;10.3&lt;/td&gt;
&lt;td&gt;245 K&lt;/td&gt;
&lt;td&gt;$1.16&lt;/td&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fable 5&lt;/td&gt;
&lt;td&gt;default&lt;/td&gt;
&lt;td&gt;13.0&lt;/td&gt;
&lt;td&gt;352 K&lt;/td&gt;
&lt;td&gt;$1.21&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 5&lt;/td&gt;
&lt;td&gt;default&lt;/td&gt;
&lt;td&gt;31.0&lt;/td&gt;
&lt;td&gt;950 K&lt;/td&gt;
&lt;td&gt;$1.38&lt;/td&gt;
&lt;td&gt;270&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.8&lt;/td&gt;
&lt;td&gt;max&lt;/td&gt;
&lt;td&gt;15.3&lt;/td&gt;
&lt;td&gt;628 K&lt;/td&gt;
&lt;td&gt;$1.45&lt;/td&gt;
&lt;td&gt;326&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 5&lt;/td&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;30.7&lt;/td&gt;
&lt;td&gt;1,072 K&lt;/td&gt;
&lt;td&gt;$1.77&lt;/td&gt;
&lt;td&gt;399&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fable 5&lt;/td&gt;
&lt;td&gt;max&lt;/td&gt;
&lt;td&gt;13.7&lt;/td&gt;
&lt;td&gt;428 K&lt;/td&gt;
&lt;td&gt;$2.28&lt;/td&gt;
&lt;td&gt;241&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Opus 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;max&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;43.7&lt;/td&gt;
&lt;td&gt;2,337 K&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$6.75&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1,110&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Every row is pass-proportion 1.00.&lt;/strong&gt; Not "mostly" — all 63 runs fully implemented the spec, tests executing, verified by an independent judge. The cheapest configuration costs &lt;strong&gt;$0.42&lt;/strong&gt; and the dearest &lt;strong&gt;$6.75&lt;/strong&gt;: a &lt;strong&gt;16× spread buying literally nothing&lt;/strong&gt; on this task.&lt;/p&gt;

&lt;h2&gt;
  
  
  The dial is a bigger lever than the version
&lt;/h2&gt;

&lt;p&gt;Compare the two axes directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Within one model, changing only the thinking level:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;model&lt;/th&gt;
&lt;th&gt;low → max&lt;/th&gt;
&lt;th&gt;cost multiple&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.7&lt;/td&gt;
&lt;td&gt;$0.61 → $1.13&lt;/td&gt;
&lt;td&gt;1.9×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.8&lt;/td&gt;
&lt;td&gt;$0.57 → $1.45&lt;/td&gt;
&lt;td&gt;2.5×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fable 5&lt;/td&gt;
&lt;td&gt;$0.91 → $2.28&lt;/td&gt;
&lt;td&gt;2.5×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Opus 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.75 → $6.75&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;9.0×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Between models, holding the thinking level fixed:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;effort&lt;/th&gt;
&lt;th&gt;cheapest → dearest&lt;/th&gt;
&lt;th&gt;cost multiple&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;$0.57 (4.8) → $0.91 (Fable 5)&lt;/td&gt;
&lt;td&gt;1.6×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;default&lt;/td&gt;
&lt;td&gt;$0.42 (4.8) → $1.38 (Opus 5)&lt;/td&gt;
&lt;td&gt;3.3×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;max&lt;/td&gt;
&lt;td&gt;$1.13 (4.7) → $6.75 (Opus 5)&lt;/td&gt;
&lt;td&gt;6.0×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two things fall out. &lt;strong&gt;At &lt;code&gt;low&lt;/code&gt;, the four model generations nearly converge&lt;/strong&gt; — 1.6× apart, and all perfect. Most of what looks like "the new model is expensive" is the new model &lt;em&gt;thinking harder by default&lt;/em&gt;, not the weights being pricier. And &lt;strong&gt;the two axes interact&lt;/strong&gt;: Opus 5 responds to the dial 9×, where the older models respond 2×. The newest model is both the most expensive at its default and by far the most sensitive to the setting.&lt;/p&gt;

&lt;p&gt;The practical consequence is concrete: &lt;strong&gt;Opus 5 at &lt;code&gt;low&lt;/code&gt; ($0.75) is cheaper than Fable 5 at its default ($1.21) and half the price of Opus 5 at its own default.&lt;/strong&gt; If you want the newest model, the dial — not the version — is what decides your bill.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why cost tracks turns, and turns tracks the dial
&lt;/h2&gt;

&lt;p&gt;The mechanism is unchanged from earlier versions of this post, and it is the part that has held up under every re-measurement.&lt;/p&gt;

&lt;p&gt;Cost follows the &lt;strong&gt;number of agentic turns&lt;/strong&gt;, not per-turn speed. Seconds-per-turn is roughly flat; what varies is how many steps the loop takes. And token cost grows &lt;em&gt;faster&lt;/em&gt; than turns because &lt;strong&gt;every turn re-reads the whole accumulated conversation from cache&lt;/strong&gt;. Opus 5 at &lt;code&gt;max&lt;/code&gt;: 43.7 turns, and 2.34 M tokens against roughly 33 K actually generated. Cache reads are individually cheap, which is why the bill is $6.75 and not absurd — but they dominate the totals, and they scale with roughly the &lt;em&gt;square&lt;/em&gt; of the step count.&lt;/p&gt;

&lt;p&gt;So the dial's mechanism is simple: more thinking → more steps → quadratically more re-read context. That is why &lt;code&gt;max&lt;/code&gt; costs 9× on the model that takes the most steps to begin with.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the dial does not buy
&lt;/h2&gt;

&lt;p&gt;Nothing measurable here. Every level, every model: 1.00.&lt;/p&gt;

&lt;p&gt;That is a real finding &lt;em&gt;and&lt;/em&gt; a bounded one. This is &lt;strong&gt;one language on a routine task&lt;/strong&gt;, where the ceiling was already saturated — with everything at 1.00 there is no headroom in which a difference could show. Thinking level may well earn its cost on genuinely hard work, and nothing in these 63 runs tests that. It is the obvious next experiment.&lt;/p&gt;

&lt;p&gt;The honest summary: &lt;strong&gt;on work your stack already handles, the dial is pure expense. On work it doesn't, we don't know yet.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The version story, corrected
&lt;/h2&gt;

&lt;p&gt;An earlier version of this post described a smooth generational climb — Fable 5 10.7 turns → Opus 4.8 17.3 → Opus 5 36.0 — and built a narrative on it. Measured &lt;strong&gt;in one batch&lt;/strong&gt;, with the thinking level held at the historical default, three of those generations are indistinguishable:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;model&lt;/th&gt;
&lt;th&gt;in-batch turns (n=3)&lt;/th&gt;
&lt;th&gt;previously published&lt;/th&gt;
&lt;th&gt;ratio&lt;/th&gt;
&lt;th&gt;source of the old figure&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.8-fast&lt;/td&gt;
&lt;td&gt;11.5&lt;/td&gt;
&lt;td&gt;11.3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.02×&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;exp-7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fable 5&lt;/td&gt;
&lt;td&gt;13.0&lt;/td&gt;
&lt;td&gt;10.7&lt;/td&gt;
&lt;td&gt;1.21×&lt;/td&gt;
&lt;td&gt;exp-10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 5&lt;/td&gt;
&lt;td&gt;31.0&lt;/td&gt;
&lt;td&gt;36.0&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.86×&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;exp-46&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Opus 4.7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;10.3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;17.2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.60×&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;exp-6&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Opus 4.8&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;9.3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;17.3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.54×&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;exp-6&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three of five replicate closely. The two that don't both come from &lt;strong&gt;exp-6&lt;/strong&gt;, the oldest source — so the "gradual climb" was substantially one old experiment's inflated middle. Corrected: &lt;strong&gt;4.7, 4.8 and Fable 5 all sit around 9–13 turns; Opus 5 alone takes ~2.7× that.&lt;/strong&gt; Not a trend across versions — one model behaving differently.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(A note on how that was found: the cross-version comparison had been assembled from experiments run months apart on different harness versions. The fix was to re-run every arm in a single batch. If you take one methodological point from this post, take that one.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A second vendor: the dial does something completely different at OpenAI
&lt;/h2&gt;

&lt;p&gt;Everything above is Claude. If "the dial costs more than the model" were really about thinking level rather than about one vendor's tuning, it should show up elsewhere — so the same experiment was run against &lt;strong&gt;OpenAI's GPT-5.6 Terra&lt;/strong&gt;, driven by &lt;code&gt;codex exec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Terra is the right comparison because GPT-5.6's three tiers price onto the Claude ladder rather than against it: &lt;strong&gt;Luna (\$1/\$6) ↔ Sonnet · Terra (\$2.50/\$15) ↔ Opus · Sol (\$5/\$30) ↔ Fable.&lt;/strong&gt; Opus is the strongest Claude pick in most cells today, so Terra is its price-peer. Both CLIs expose exactly the same five levels — &lt;code&gt;low, medium, high, xhigh, max&lt;/code&gt; — so the dial can be set identically on both sides. &lt;strong&gt;Python and Go, n=2, 20 cells. Every one scored 1.00.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;effort&lt;/th&gt;
&lt;th&gt;Terra&lt;/th&gt;
&lt;th&gt;Opus 5&lt;/th&gt;
&lt;th&gt;ratio&lt;/th&gt;
&lt;th&gt;Terra time&lt;/th&gt;
&lt;th&gt;Opus 5 time&lt;/th&gt;
&lt;th&gt;Opus 5 turns&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;$0.19&lt;/td&gt;
&lt;td&gt;$0.81&lt;/td&gt;
&lt;td&gt;4.3×&lt;/td&gt;
&lt;td&gt;112 s&lt;/td&gt;
&lt;td&gt;136 s&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.15&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$1.14&lt;/td&gt;
&lt;td&gt;7.6×&lt;/td&gt;
&lt;td&gt;105 s&lt;/td&gt;
&lt;td&gt;222 s&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;$0.18&lt;/td&gt;
&lt;td&gt;$1.84&lt;/td&gt;
&lt;td&gt;10.2×&lt;/td&gt;
&lt;td&gt;132 s&lt;/td&gt;
&lt;td&gt;401 s&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xhigh&lt;/td&gt;
&lt;td&gt;$0.22&lt;/td&gt;
&lt;td&gt;$4.63&lt;/td&gt;
&lt;td&gt;21.0×&lt;/td&gt;
&lt;td&gt;169 s&lt;/td&gt;
&lt;td&gt;909 s&lt;/td&gt;
&lt;td&gt;62&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;max&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0.35&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$14.21&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;40.6×&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;254 s&lt;/td&gt;
&lt;td&gt;1669 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;92&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Terra's most expensive setting is half the price of Opus 5's cheapest.&lt;/strong&gt; At matched &lt;code&gt;max&lt;/code&gt; the gap is forty-fold — for an identical, independently-judged 1.00 on the same task.&lt;/p&gt;

&lt;p&gt;But the interesting column is the last one, because it shows the two dials are not the same instrument. &lt;strong&gt;Terra's agent steps stay flat across the entire range — 10 to 19 — no matter where the dial is set. Opus 5's climb from 16 to 92.&lt;/strong&gt; Turning the dial up on Opus 5 buys &lt;em&gt;more agentic iteration&lt;/em&gt;; turning it up on Terra appears to buy &lt;em&gt;deeper reasoning inside a roughly constant number of steps&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That distinction is exactly the mechanism this post has been building toward. Cost tracks turns, and turns re-read the accumulated conversation, so a dial that adds steps compounds and a dial that doesn't, doesn't. The per-token price difference between the two models is only about 2.4×; the rest of the 40× is turns. &lt;strong&gt;The thesis survives contact with a second vendor — but the vendors have made opposite choices about what the dial should do.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is a second, smaller surprise. &lt;strong&gt;OpenAI's flagship tier defaults to the &lt;em&gt;lowest&lt;/em&gt; reasoning setting&lt;/strong&gt; (Sol defaults to &lt;code&gt;low&lt;/code&gt;, while the cheaper Terra and Luna default to &lt;code&gt;medium&lt;/code&gt;), where Claude's default sits near &lt;code&gt;high&lt;/code&gt;. So "newer models think harder by default" — the tempting explanation earlier in this post — is not a law about frontier models. It is a product decision, and two vendors made it in opposite directions.&lt;/p&gt;

&lt;p&gt;This is also why the comparison had to set effort explicitly on both sides. &lt;code&gt;default&lt;/code&gt; is not a shared operating point: comparing out-of-the-box settings would have compared two companies' packaging choices and called it a model difference, and would have shown a muddled ~9× instead of the clean 4×→40× interaction.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Getting a trustworthy number out of Codex took four fixes first, none of which were visible without running it: the telemetry parser was written to an event shape the CLI does not emit and recorded **0 tokens, 0 turns&lt;/em&gt;&lt;em&gt;; input and output tokens were double-counted against their own cached and reasoning subsets, inflating cost ~490%; a ChatGPT subscription reports **no cost at all&lt;/em&gt;&lt;em&gt;, so Codex would have logged \$0 and won every cheapest-stack ranking on an unmeasured number; and Codex's &lt;code&gt;turn.completed&lt;/code&gt; fires once per invocation rather than per step, so recording it as "turns" would have placed it at the bottom of this post's own axis looking impossibly efficient. Cost here is list-price-per-token — the same basis Claude's CLI reports and does not bill on a Max plan.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  It isn't a Claude phenomenon
&lt;/h2&gt;

&lt;p&gt;The same cell run on local models, driven by the Hermes agent over oMLX on a 64 GB laptop:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;stack&lt;/th&gt;
&lt;th&gt;n&lt;/th&gt;
&lt;th&gt;turns&lt;/th&gt;
&lt;th&gt;replicates&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3.6-35B (local)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;12.0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10, 8, 18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen3-Coder-Next 80B (local)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;24.7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;44, 17, 13&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Placed on the same axis: &lt;strong&gt;Opus 4.8 9.3 · Opus 4.7 10.3 · 35B 12.0 · Fable 5 13.0 · 80B 24.7 · Opus 5 31.0.&lt;/strong&gt; A 35B open-weights model on a laptop sits in the same cluster as three Claude generations, and the 80B sits with Opus 5 well above it. Two vendors, a 20× parameter range, and the same two-group split — which points at &lt;strong&gt;how a model was tuned to behave in an agent loop&lt;/strong&gt; rather than at scale or architecture. With Terra above, that is now three independent lineages saying the same thing: step count is a tuning decision, not a capability tier.&lt;/p&gt;

&lt;p&gt;Caveat worth keeping: the 80B's replicates span 44/17/13, a 3.4× spread. A single 80B run tells you very little.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to actually do
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pick a (model, effort) pair, not a model.&lt;/strong&gt; The pair spans 16× in cost here; the model alone explains a minority of that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On routine work, turn the dial down.&lt;/strong&gt; &lt;code&gt;low&lt;/code&gt; cost 1.6× less than &lt;code&gt;default&lt;/code&gt; on average and changed no outcome. The CLI default is not the cheap end.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you want the newest model, run it at &lt;code&gt;low&lt;/code&gt;.&lt;/strong&gt; Opus 5 at &lt;code&gt;low&lt;/code&gt; undercuts Fable 5 at its default. Opus 5 at &lt;code&gt;max&lt;/code&gt; costs 16× the cheapest cell for the same passing app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check what your vendor's dial actually does.&lt;/strong&gt; On Opus 5 it adds agentic steps and compounds; on Terra it doesn't move step count at all. Same five names, different instrument — so a rule of thumb learned on one model does not transfer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't generalise any of this to hard tasks.&lt;/strong&gt; Everything above saturated at 1.00. The dial's value, if it has one, lives where the ceiling isn't already hit — and nothing here tests that.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Method: &lt;code&gt;python × bookshop × prompt=neutral&lt;/code&gt;, n=3 per cell, judged by an independent Opus 4.8 against a pinned requirement checklist; a run passes only if it implements the whole spec. Cost is list-price-per-token — the basis every metered stack here is recorded on, and one that does not vary with whose subscription happened to pay. Data: &lt;a href="//master.csv"&gt;&lt;code&gt;master.db&lt;/code&gt;&lt;/a&gt;, experiments &lt;code&gt;adrianco/experiment-49-versions-cloud&lt;/code&gt; (Claude × effort) and &lt;code&gt;adrianco/experiment-55-terra-vs-opus5-effort&lt;/code&gt; (cross-vendor, matched effort).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>Connecting to my old dev.to account</title>
      <dc:creator>Adrian Cockcroft</dc:creator>
      <pubDate>Fri, 24 Jul 2026 16:48:58 +0000</pubDate>
      <link>https://dev.to/adrianco_54/connecting-to-my-old-devto-account-16pk</link>
      <guid>https://dev.to/adrianco_54/connecting-to-my-old-devto-account-16pk</guid>
      <description>&lt;p&gt;I wrote some dev.to posts when I was working at AWS, and I've lost access to the email that I used to setup the account &lt;a href="https://dev.to/adrianco"&gt;https://dev.to/adrianco&lt;/a&gt; - so I'm continuing with this account &lt;a href="https://dev.to/adrianco_54"&gt;https://dev.to/adrianco_54&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/aws/scaling-aws-costs-to-match-the-business-f9k"&gt;https://dev.to/aws/scaling-aws-costs-to-match-the-business-f9k&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/aws/why-are-services-slow-sometimes-mn3"&gt;https://dev.to/aws/why-are-services-slow-sometimes-mn3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/aws/if-at-first-you-don-t-get-an-answer-3e85"&gt;https://dev.to/aws/if-at-first-you-don-t-get-an-answer-3e85&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/aws/what-is-sustainability-transformation-32hi"&gt;https://dev.to/aws/what-is-sustainability-transformation-32hi&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/adrianco/measuring-energy-usage-5ip"&gt;https://dev.to/adrianco/measuring-energy-usage-5ip&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>developer</category>
      <category>writing</category>
    </item>
    <item>
      <title>The Stack Under the Model: oMLX, llama.cpp, Hermes, and Why There Are So Many</title>
      <dc:creator>Adrian Cockcroft</dc:creator>
      <pubDate>Wed, 22 Jul 2026 22:49:51 +0000</pubDate>
      <link>https://dev.to/adrianco_54/the-stack-under-the-model-omlx-llamacpp-hermes-and-why-there-are-so-many-k75</link>
      <guid>https://dev.to/adrianco_54/the-stack-under-the-model-omlx-llamacpp-hermes-and-why-there-are-so-many-k75</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/adrianco/retort" rel="noopener noreferrer"&gt;Retort&lt;/a&gt; is a framework for comparing coding stacks, with results for versions of Claude and local tests on a 64GB M5Pro for many languages. It was developed with Claude, and I was getting confused by all the components of the harness and stack, so I asked Claude to explain what is out there and how they are being tested. That's what follows:&lt;/p&gt;

&lt;p&gt;Most benchmarks answer "which &lt;em&gt;model&lt;/em&gt; is best?" Retort insists that's the wrong&lt;br&gt;
unit. A coding result is produced by a whole &lt;strong&gt;stack&lt;/strong&gt; — and the model is only&lt;br&gt;
one layer of it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;language × model × weights-format × serving engine × agent/harness × context engine × sampling × prompt&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Change any layer and the numbers move. TypeScript went from failing to 1.00 on&lt;br&gt;
the local 80B by raising &lt;em&gt;one context-engine knob&lt;/em&gt; — same model, same weights.&lt;br&gt;
So before the results make sense, you need a map of the layers. This post is that&lt;br&gt;
map: what each piece is, where it came from, what competes with what, how they&lt;br&gt;
stack, and why the zoo is so crowded. Then it explains the &lt;strong&gt;metaharness&lt;/strong&gt; — the&lt;br&gt;
part of Retort that turns the harness &lt;em&gt;itself&lt;/em&gt; into a variable you can measure.&lt;/p&gt;

&lt;p&gt;If you've seen &lt;code&gt;oMLX&lt;/code&gt;, &lt;code&gt;llama.cpp&lt;/code&gt;, &lt;code&gt;Hermes&lt;/code&gt;, &lt;code&gt;GGUF&lt;/code&gt;, &lt;code&gt;omp&lt;/code&gt;, &lt;code&gt;lcm&lt;/code&gt;, or&lt;br&gt;
&lt;code&gt;OpenRouter&lt;/code&gt; fly past in the other blogs and nodded along without quite knowing&lt;br&gt;
what they are, start here.&lt;/p&gt;


&lt;h2&gt;
  
  
  The stack, top to bottom
&lt;/h2&gt;

&lt;p&gt;Read this from the bottom up — each layer sits on the one below it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────────────────────────────────────────┐
│  PROMPT / METHODOLOGY   "write tests first" · BDD · terse    │  ← how you ask
├──────────────────────────────────────────────────────────────┤
│  AGENT / HARNESS        claude-code · Hermes · gemini · omp  │  ← the ReAct loop:
│                         opencode                             │    read → edit → run → repeat
├──────────────────────────────────────────────────────────────┤
│  CONTEXT ENGINE         lcm (compaction) · sampling knobs    │  ← what the model "sees"
├──────────────────────────────────────────────────────────────┤
│  SERVING ENGINE         oMLX · llama.cpp · Ollama · cloud API│  ← turns weights into tokens
├──────────────────────────────────────────────────────────────┤
│  WEIGHTS + FORMAT       safetensors · GGUF · MLX  (a model   │  ← the numbers on disk
│                         at some quantization, e.g. 4-bit)    │
├──────────────────────────────────────────────────────────────┤
│  HARDWARE               Apple Silicon · NVIDIA · a cloud GPU │  ← what runs the math
└──────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"Which model is best" only asks about one band in the middle. Retort measures the&lt;br&gt;
column. The rest of this post walks the layers where the confusing names live —&lt;br&gt;
&lt;strong&gt;weights, serving, agent, context&lt;/strong&gt; — and then the metaharness, which makes the&lt;br&gt;
&lt;em&gt;agent&lt;/em&gt; layer a factor you can sweep.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 1: weights and their formats — safetensors, GGUF, MLX
&lt;/h2&gt;

&lt;p&gt;A model is a big pile of numbers (weights). How those numbers are &lt;em&gt;stored on&lt;br&gt;
disk&lt;/em&gt; is a surprising source of fragmentation, because the file format is tied to&lt;br&gt;
the engine that reads it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;safetensors&lt;/strong&gt; — the neutral, framework-agnostic format models are usually
published in (it replaced the old, unsafe pickle format). Both of the local
formats below are usually &lt;em&gt;converted from&lt;/em&gt; safetensors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GGUF&lt;/strong&gt; — the format used by &lt;strong&gt;llama.cpp&lt;/strong&gt;. A single self-contained file that
bundles the weights, the tokenizer, and metadata, at a chosen &lt;strong&gt;quantization&lt;/strong&gt;
(e.g. &lt;code&gt;Q4_K_M&lt;/code&gt; ≈ 4-bit). Designed to run well on CPUs and non-CUDA GPUs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MLX&lt;/strong&gt; — Apple's format, produced for &lt;strong&gt;Apple's MLX framework&lt;/strong&gt;. MLX is
Apple's array/ML library for Apple Silicon; it exploits the Mac's &lt;em&gt;unified
memory&lt;/em&gt; (CPU and GPU share the same RAM), which is why a 64 GB Mac can hold a
42 GB model that would otherwise need a datacenter GPU.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quantization&lt;/strong&gt; is the other axis here: the same model shipped at 4-bit is a&lt;br&gt;
quarter the size of 16-bit and runs far faster, at some accuracy cost. When you&lt;br&gt;
see &lt;code&gt;Qwen3-Coder-Next-4bit&lt;/code&gt; (≈42 GB) that's "the 80B model, MLX format, 4-bit."&lt;/p&gt;

&lt;p&gt;Why two local formats (GGUF and MLX) for the same models? Because each is glued&lt;br&gt;
to a different engine, which is the next layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 2: the serving engine — oMLX vs llama.cpp vs Ollama vs the cloud
&lt;/h2&gt;

&lt;p&gt;The serving engine is the program that loads the weights and turns your prompt&lt;br&gt;
into tokens, usually exposing an &lt;strong&gt;OpenAI-compatible HTTP endpoint&lt;/strong&gt; (&lt;code&gt;POST&lt;br&gt;
/v1/chat/completions&lt;/code&gt;) so anything that speaks that protocol can drive it. This&lt;br&gt;
is the layer with the most competitors, because it's where hardware, format, and&lt;br&gt;
performance all collide.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;llama.cpp&lt;/strong&gt; — the foundational open-source local engine, written in C/C++ by
Georgi Gerganov. It reads &lt;strong&gt;GGUF&lt;/strong&gt;, runs on almost anything (CPU, CUDA, and
Apple's &lt;strong&gt;Metal&lt;/strong&gt; GPU API), and defined the format the rest of the ecosystem
converged on. Most local tooling is either llama.cpp or a wrapper around it.
Its server binary is &lt;code&gt;llama-server&lt;/code&gt;; Retort's &lt;code&gt;llamacpp&lt;/code&gt; backend drives it with
&lt;code&gt;--jinja&lt;/code&gt; so the model's own chat/tool template is applied.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama&lt;/strong&gt; — a friendly daemon + model registry &lt;em&gt;built on top of&lt;/em&gt; llama.cpp
(&lt;code&gt;ollama run qwen&lt;/code&gt;). It made local models one-command easy and is how most
people first run one. Retort's earliest local attempt used it (see below) and
moved on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;oMLX&lt;/strong&gt; — a local server for &lt;strong&gt;MLX&lt;/strong&gt;-format models on Apple Silicon,
OpenAI-compatible on &lt;code&gt;127.0.0.1:8080&lt;/code&gt;. It's the MLX-world counterpart to
llama.cpp: same job (weights → tokens over HTTP), different format and a
Metal/MLX-native path tuned for Macs. Retort restarts it at each experiment
boundary and records the &lt;em&gt;effective&lt;/em&gt; settings in &lt;code&gt;provenance.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cloud APIs&lt;/strong&gt; — for Opus, Gemini, GPT, etc. you don't run a serving engine at
all; a provider runs it and you rent tokens. Same OpenAI-shaped protocol, so
the layers above don't care whether the tokens came from your laptop or a
datacenter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What competes with what:&lt;/strong&gt; llama.cpp (GGUF) and oMLX (MLX) are the two serious&lt;br&gt;
&lt;em&gt;local&lt;/em&gt; engines, split mostly by format and hardware heritage — GGUF/llama.cpp is&lt;br&gt;
the cross-platform default, MLX/oMLX is the Apple-Silicon-native path. Ollama&lt;br&gt;
competes on &lt;em&gt;ease&lt;/em&gt;, not capability (it &lt;em&gt;is&lt;/em&gt; llama.cpp underneath). Retort now&lt;br&gt;
supports &lt;strong&gt;both&lt;/strong&gt; local engines via a &lt;code&gt;serving.backend: omlx | llamacpp&lt;/code&gt; switch,&lt;br&gt;
precisely because neither dominates: some models ship only as MLX, some only as&lt;br&gt;
GGUF, and some new architectures land in one engine months before the other.&lt;br&gt;
That "which engine has this architecture yet?" gap is a recurring reason a&lt;br&gt;
promising model can't be tested — it's a serving-layer problem, not a model one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 3: the agent / harness — claude-code, Hermes, gemini, opencode, omp
&lt;/h2&gt;

&lt;p&gt;A served model just answers messages. To &lt;em&gt;build software&lt;/em&gt; it needs a loop that&lt;br&gt;
reads files, writes edits, runs the tests, reads the failures, and tries again —&lt;br&gt;
the &lt;strong&gt;agentic loop&lt;/strong&gt; (often "ReAct": reason → act → observe, repeat). That loop is&lt;br&gt;
the &lt;strong&gt;agent / harness&lt;/strong&gt;, and it's a real, swappable layer: the same model behaves&lt;br&gt;
differently under different harnesses because they differ in how they present&lt;br&gt;
tools, when they retry, and how they manage the conversation.&lt;/p&gt;

&lt;p&gt;The harnesses Retort supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;claude-code&lt;/code&gt;&lt;/strong&gt; — Anthropic's Claude CLI. Retort's default, and it doubles as
the impartial &lt;strong&gt;spec-gate judge&lt;/strong&gt; that grades every run (so an independent model
scores all agents fairly, even non-Claude ones).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gemini&lt;/code&gt;&lt;/strong&gt; — Google's &lt;a href="https://github.com/google-gemini/gemini-cli" rel="noopener noreferrer"&gt;Gemini CLI&lt;/a&gt;,
used for &lt;code&gt;gemini-*&lt;/code&gt; models. The agent usually &lt;em&gt;follows from the model id&lt;/em&gt;: list
a Claude id and you get claude-code, a Gemini id and you get the Gemini CLI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Hermes&lt;/code&gt;&lt;/strong&gt; — the harness Retort uses to drive &lt;strong&gt;local&lt;/strong&gt; models (via oMLX). It's
the featured local path: Hermes runs the ReAct loop and manages context (its
context engine is &lt;code&gt;lcm&lt;/code&gt;, below) while oMLX serves the tokens. &lt;em&gt;Note:&lt;/em&gt; here
"Hermes" is the &lt;strong&gt;agent&lt;/strong&gt;, not a model — the model underneath is Qwen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;opencode&lt;/code&gt;&lt;/strong&gt; — another open agent harness Retort can drive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;omp&lt;/code&gt;&lt;/strong&gt; — &lt;a href="https://github.com/can1357/oh-my-pi" rel="noopener noreferrer"&gt;oh-my-pi&lt;/a&gt;, an early
community-contributed local harness (it talked to &lt;strong&gt;llama.cpp&lt;/strong&gt;, not Ollama).
It's documented as a &lt;strong&gt;legacy&lt;/strong&gt; path — the first, honest dead-end on a 24 GB Mac
before the Hermes + oMLX stack became the featured one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why the agent is its own layer (and its own zoo):&lt;/strong&gt; each vendor ships the&lt;br&gt;
harness tuned for its own model, and open harnesses exist to run &lt;em&gt;any&lt;/em&gt; model. They&lt;br&gt;
genuinely differ — a weak model can pass under a forgiving harness and fail under&lt;br&gt;
a strict one — which is exactly why "which harness?" deserves measurement rather&lt;br&gt;
than assumption. That's what the metaharness (last section) is for.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 4: the context engine and sampling — the knobs that quietly decide everything
&lt;/h2&gt;

&lt;p&gt;Two smaller layers sit between the agent and the model, and they've caused more&lt;br&gt;
wrong conclusions in this project than any model choice.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The context engine (&lt;code&gt;lcm&lt;/code&gt;)&lt;/strong&gt; decides &lt;em&gt;what the model actually sees&lt;/em&gt;. An agentic
coding session quickly grows past the model's context window, so the engine
&lt;strong&gt;compacts&lt;/strong&gt; older turns to make room. Hermes's engine is &lt;code&gt;lcm&lt;/code&gt;, and its key
knob is &lt;code&gt;context_threshold&lt;/code&gt; — the fraction of the window at which it compacts.
At the default &lt;code&gt;0.35&lt;/code&gt; it compacts at ~92K tokens and the 80B intermittently
&lt;em&gt;stalls&lt;/em&gt;; raised to &lt;code&gt;0.9&lt;/code&gt; ("full context") the same model runs Python, Go, &lt;strong&gt;and
TypeScript at 1.00&lt;/strong&gt;. Same weights, same engine — a different threshold. This is
the single clearest example of a non-model layer deciding the result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sampling&lt;/strong&gt; — &lt;code&gt;temperature&lt;/code&gt;, &lt;code&gt;top_p&lt;/code&gt;, &lt;code&gt;top_k&lt;/code&gt;, &lt;code&gt;repetition_penalty&lt;/code&gt;: how
randomly the next token is picked. Retort learned the hard way that the oMLX
&lt;em&gt;default&lt;/em&gt; &lt;code&gt;temperature = 1.0&lt;/code&gt; roughly halved local reliability, and that a
&lt;code&gt;repetition_penalty ≠ 1.0&lt;/code&gt; (even a value a model's own card recommends) can
derail the multi-turn tool loop into stalls. These are recorded per run and held
fixed on purpose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The lesson threaded through the whole project: &lt;strong&gt;a set-but-unverified knob in one&lt;br&gt;
of these quiet layers produces confident, wrong results.&lt;/strong&gt; Retort's provenance&lt;br&gt;
records the &lt;em&gt;effective&lt;/em&gt; value of each, because the config file's value and the&lt;br&gt;
value the model actually ran at have diverged more than once.&lt;/p&gt;




&lt;h2&gt;
  
  
  So why &lt;em&gt;are&lt;/em&gt; there so many?
&lt;/h2&gt;

&lt;p&gt;The zoo isn't accidental. Several independent forces each spawn alternatives:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Force&lt;/th&gt;
&lt;th&gt;What it splits&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardware lineage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;serving engine + format&lt;/td&gt;
&lt;td&gt;Apple-Silicon/unified-memory → MLX/oMLX; cross-platform/CUDA → GGUF/llama.cpp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Format lock-in&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;which engine can even load a model&lt;/td&gt;
&lt;td&gt;a model published only as MLX can't run on llama.cpp, and vice-versa&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;New architectures&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;which engine supports them &lt;em&gt;first&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;a brand-new model's arch may land in one engine months before the other — the usual reason a candidate is "blocked"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ease vs control&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;wrapper vs raw engine&lt;/td&gt;
&lt;td&gt;Ollama (easy) wraps llama.cpp (control); one command vs every flag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vendor vs open&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;the agent/harness&lt;/td&gt;
&lt;td&gt;claude-code/gemini ship per-vendor; Hermes/opencode/omp run &lt;em&gt;any&lt;/em&gt; model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost &amp;amp; privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;local vs cloud&lt;/td&gt;
&lt;td&gt;a 64 GB Mac runs the 80B for \$0 and offline; the cloud rents frontier capability per token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Quantization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;size vs accuracy&lt;/td&gt;
&lt;td&gt;the same model at 4-bit / 6-bit / 8-bit trades RAM and speed against quality&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;None of these layers &lt;em&gt;dominates&lt;/em&gt;, so none of the others disappear. That's the&lt;br&gt;
whole reason Retort measures the stack instead of the model: the interesting&lt;br&gt;
question is usually "which &lt;em&gt;combination&lt;/em&gt; is best for &lt;strong&gt;my&lt;/strong&gt; language, task, and&lt;br&gt;
budget?" — and the answer moves as new engines, formats, and harnesses land.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where Retort's featured stacks sit today:&lt;/strong&gt; the free local path is&lt;br&gt;
&lt;strong&gt;Qwen3-Coder-Next 80B, MLX 4-bit, served by oMLX, driven by Hermes with &lt;code&gt;lcm&lt;/code&gt; at&lt;br&gt;
&lt;code&gt;context_threshold 0.9&lt;/code&gt;&lt;/strong&gt; on a 64 GB Mac — Python/Go/TypeScript at 1.00 for \$0.&lt;br&gt;
The cloud path is &lt;strong&gt;Claude Opus 4.8 via claude-code&lt;/strong&gt; for the languages and hard&lt;br&gt;
tasks the local stack can't yet clear. Same protocol, different columns.&lt;/p&gt;




&lt;h2&gt;
  
  
  The metaharness: making the harness &lt;em&gt;itself&lt;/em&gt; a variable
&lt;/h2&gt;

&lt;p&gt;Everything above treats the harness as a fixed choice per run. But the harness is&lt;br&gt;
a bundle of &lt;em&gt;strategies&lt;/em&gt; — and those strategies plausibly move results as much as&lt;br&gt;
the model does. The &lt;strong&gt;&lt;a href="https://dev.toretort_metaharness/"&gt;&lt;code&gt;retort_metaharness&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; layer&lt;br&gt;
(a documented, experimental side-branch) makes the &lt;strong&gt;agentic-orchestration harness&lt;br&gt;
a first-class factor&lt;/strong&gt; you can sweep, so a statistical analysis can say &lt;em&gt;how much&lt;br&gt;
of any lift is the harness versus the raw model.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It doesn't reinvent Retort — it composes the same design generator, ANOVA, and&lt;br&gt;
Pareto engine — but it adds three new factors on top of the usual language/model:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;harness_config&lt;/code&gt; — the orchestration strategy (the headline factor)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;level&lt;/th&gt;
&lt;th&gt;what it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;base-ReAct&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;plain single-agent reason→act→observe loop. The control: no tricks.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;self-consistency-N&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;sample &lt;strong&gt;N&lt;/strong&gt; independent solutions and majority/judge-select the best. An &lt;em&gt;accuracy&lt;/em&gt; lever that costs N× the tokens (default N=5).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;routed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;a &lt;strong&gt;cheap&lt;/strong&gt; model drafts; a &lt;strong&gt;frontier&lt;/strong&gt; model takes over only on low-confidence steps. A &lt;em&gt;cost&lt;/em&gt; lever — aims for comparable reliability at lower \$.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;+agenticow-memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ReAct plus a copy-on-write memory that persists agent state across steps/replicates — tests whether memory changes the outcome.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;+darwin-evolved-genome&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ReAct driven by a harness "genome" (prompt + tool policy) tuned by an evolutionary loop — tests whether evolution moves the needle.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;scaffold&lt;/code&gt; — the reasoning structure wrapped around each attempt
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;none&lt;/code&gt; · &lt;code&gt;plan-and-solve&lt;/code&gt; (plan first, then execute) · &lt;code&gt;reflexion&lt;/code&gt; (attempt,&lt;br&gt;
self-critique, retry).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;model&lt;/code&gt; — the raw model, spanning cheap→frontier
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;deepseek-v4-pro&lt;/code&gt; · &lt;code&gt;glm-5.2&lt;/code&gt; · &lt;code&gt;opus-4.8&lt;/code&gt; · &lt;code&gt;gpt-5.2&lt;/code&gt;, reached through&lt;br&gt;
&lt;strong&gt;OpenRouter&lt;/strong&gt; (a unified API that routes one request format to many providers),&lt;br&gt;
chosen to spread from cheap to frontier so the analysis can &lt;em&gt;separate&lt;/em&gt; a model&lt;br&gt;
effect from a harness effect.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it would actually test
&lt;/h3&gt;

&lt;p&gt;Because a fractional-factorial design crosses &lt;strong&gt;all&lt;/strong&gt; of these at once (rather than&lt;br&gt;
changing one thing at a time), the ANOVA can attribute the variance in a metric to&lt;br&gt;
&lt;strong&gt;model vs harness vs scaffold vs language + their interactions&lt;/strong&gt;, and report which&lt;br&gt;
effects are cleanly estimated versus confounded. Concretely, it answers questions&lt;br&gt;
the model-only grid structurally can't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Of the lift from &lt;code&gt;+agenticow-memory&lt;/code&gt;, how much is the memory branching versus
just the underlying model being good?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Does &lt;code&gt;routed&lt;/code&gt; actually hold reliability while cutting cost — i.e., does it sit
on the accuracy-vs-\$ Pareto front?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Is &lt;code&gt;self-consistency-5&lt;/code&gt; worth 5× the tokens, or a rounding error on a task the
model already nails?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Is a reasoning &lt;code&gt;scaffold&lt;/code&gt; a real lever or a ritual — and does that depend on
model strength?&lt;/em&gt; (Retort already found the sibling result that &lt;strong&gt;the prompt is a
lever only in proportion to how weak the model is&lt;/strong&gt;; the metaharness generalizes
that from &lt;em&gt;prompt&lt;/em&gt; to &lt;em&gt;full orchestration&lt;/em&gt;.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest caveats: it's &lt;strong&gt;cloud-only&lt;/strong&gt; (OpenRouter, metered — the&lt;br&gt;
&lt;code&gt;self-consistency × frontier × replicates&lt;/code&gt; corner gets expensive) and the real&lt;br&gt;
orchestration logic lives in an &lt;strong&gt;external solver&lt;/strong&gt; the adapter shells out to, so&lt;br&gt;
without that solver only a \$0 stub runs. That's why it's a documented&lt;br&gt;
side-branch rather than a headline result — it stays one until a first screening&lt;br&gt;
run shows the harness variance is real enough to promote. The staged plan lives in&lt;br&gt;
&lt;a href="//docs/future-experiments.md"&gt;&lt;code&gt;docs/future-experiments.md&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;There are "so many" harnesses and engines because at least six independent forces&lt;br&gt;
— hardware, format, new architectures, ease-vs-control, vendor-vs-open, and&lt;br&gt;
cost-vs-privacy — each keep their own alternatives alive, and no layer has a&lt;br&gt;
winner that retires the others. The practical consequence is the thesis of this&lt;br&gt;
whole repo: &lt;strong&gt;don't benchmark the model, benchmark the stack.&lt;/strong&gt; The model is one&lt;br&gt;
band in a tall column, and the quiet layers under and around it — the serving&lt;br&gt;
engine, the context threshold, the sampling defaults, and the orchestration&lt;br&gt;
strategy — routinely decide the result. The metaharness is Retort turning the last&lt;br&gt;
of those, the orchestration layer, from an assumption into a measurement.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>testing</category>
      <category>agents</category>
    </item>
  </channel>
</rss>
