<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Coding-Agents | AkitaOnRails.com</title><link>https://akitaonrails.github.io/en/tags/coding-agents/</link><description>Fabio Akita's blog — tech, career, and assorted geek topics. English edition.</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Mon, 19 Oct 2026 23:20:51 +0000</lastBuildDate><atom:link href="https://akitaonrails.github.io/en/tags/coding-agents/index.xml" rel="self" type="application/rss+xml"/><item><title>I Self-Published My Own Book/e-book: Competent Enough</title><link>https://akitaonrails.github.io/en/2026/10/13/i-self-published-my-own-book-ebook-competent-enough/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/10/13/i-self-published-my-own-book-ebook-competent-enough/</guid><pubDate>Tue, 13 Oct 2026 19:00:00 -0300</pubDate><description>&lt;p&gt;I just published my own book about artificial intelligence. It&amp;rsquo;s called &lt;em&gt;Competent Enough&lt;/em&gt;, subtitled &amp;ldquo;A year putting artificial intelligence to the test, without fear and without propaganda&amp;rdquo;, and it&amp;rsquo;s free, in EPUB and PDF, to read on your phone, PC or Kindle. The official page is &lt;a href="https://ailair.akitaonrails.com/book/"target="_blank" rel="noopener"&gt;here&lt;/a&gt;, and the &lt;a href="https://github.com/akitaonrails/ai-book-2026"target="_blank" rel="noopener"&gt;repository&lt;/a&gt; is public.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://ailair.akitaonrails.com/book/"target="_blank" rel="noopener"&gt;&lt;img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20261013190000_book-competent-enough-3d.png" alt="Competent Enough, the book, in 3D" loading="lazy" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The book consolidates almost everything I wrote about AI on this blog from February to October 2026: all the experiments, the Frank projects, the benchmarks, billions of tokens spent and hundreds of hours of work over eight months, reorganized into a format that&amp;rsquo;s easier to read than a pile of dated posts. It came out in Portuguese and in English.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I just published my own book about artificial intelligence. It&rsquo;s called <em>Competent Enough</em>, subtitled &ldquo;A year putting artificial intelligence to the test, without fear and without propaganda&rdquo;, and it&rsquo;s free, in EPUB and PDF, to read on your phone, PC or Kindle. The official page is <a href="https://ailair.akitaonrails.com/book/"target="_blank" rel="noopener">here</a>, and the <a href="https://github.com/akitaonrails/ai-book-2026"target="_blank" rel="noopener">repository</a> is public.</p>
<p><a href="https://ailair.akitaonrails.com/book/"target="_blank" rel="noopener"><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20261013190000_book-competent-enough-3d.png" alt="Competent Enough, the book, in 3D"  loading="lazy" /></a></p>
<p>The book consolidates almost everything I wrote about AI on this blog from February to October 2026: all the experiments, the Frank projects, the benchmarks, billions of tokens spent and hundreds of hours of work over eight months, reorganized into a format that&rsquo;s easier to read than a pile of dated posts. It came out in Portuguese and in English.</p>
<blockquote>
  <p><strong>Important notice:</strong> this is a <em>preview</em>. The book is still in progress and new versions will come out until I consider it done. If you find anything wrong, from a typo to a fact, <a href="https://github.com/akitaonrails/ai-book-2026/issues"target="_blank" rel="noopener">open an issue on GitHub</a>. The trail I describe below exists precisely so that the fix reaches the right paragraph.</p>

</blockquote>
<p>This text is about the technical backstage. How you turn 131 blog posts, written over months, with opinions that changed along the way, into a book with a beginning, middle, end, appendices, glossary and bibliography. And how you do that with agents without losing control of what the book says.</p>
<h2>What&rsquo;s inside<span class="hx:absolute hx:-mt-20" id="whats-inside"></span>
    <a href="#whats-inside" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Five parts, each answering a question people keep asking me:</p>
<ol>
<li><strong>What is this thing, anyway.</strong> Is it intelligent? Is AGI coming?</li>
<li><strong>The marathon.</strong> Does it actually work, or is it all demo?</li>
<li><strong>Numbers and propaganda.</strong> Which AI is best? Can you believe the announcements?</li>
<li><strong>Who keeps the keys.</strong> Is it dangerous to let it touch my things?</li>
<li><strong>And my job?</strong> Will it replace me? What comes next?</li>
</ol>
<p>That&rsquo;s 20 chapters and two interludes, plus a preface, a &ldquo;how to read&rdquo;, a &ldquo;before you start&rdquo; saying what the book doesn&rsquo;t explain and where to learn it, an epilogue and an afterword. Then come ten appendices (the machine inside without math, further reading, how to study with AI at your side, three bubbles, a timeline, a minimal kit for using agents safely, ai-memory, how to read a benchmark or an announcement, the year&rsquo;s projects, and the backstage for programmers), the sources, the image credits, a glossary of almost 150 terms and more than 300 references in ABNT style. The print edition passes 500 pages at 6 by 9 inches; the screen edition, around 475. There are more than 50 figures, all with a provenance record.</p>
<p>The audience is different from the blog&rsquo;s. The book was written for people who are anxious or confused about AI: the professional afraid of being replaced, the parent who read that AGI is two years away, the manager being sold an &ldquo;AI transformation&rdquo;. Most of them don&rsquo;t program. That changes the voice, and I&rsquo;ll come back to it.</p>
<h2>The problem: half a million words that disagree with each other<span class="hx:absolute hx:-mt-20" id="the-problem-half-a-million-words-that-disagree-with-each-other"></span>
    <a href="#the-problem-half-a-million-words-that-disagree-with-each-other" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>On October 12 I published <a href="/en/2026/10/12/llms-agents-competent-enough/">the year&rsquo;s synthesis</a>, which became chapter 20. On the 13th I started the book. I had 131 posts from 2026 on the blog, almost half a million words, from model benchmarks to a bitcoin wallet.</p>
<p>Reorganizing that by hand would take months. And there&rsquo;s a worse problem than volume: I changed my mind during the year. I redid the benchmark several times, corrected costs, switched tools, and a February post contradicts a September one with complete naturalness. A book that simply pasted the posts in order would be a book that contradicts itself.</p>
<p>So I did what the whole book describes: I handed the grunt work to coding agents and kept the part of deciding, building the process and checking. The process is the subject of this text.</p>
<h2>Step 1: a sealed inventory<span class="hx:absolute hx:-mt-20" id="step-1-a-sealed-inventory"></span>
    <a href="#step-1-a-sealed-inventory" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The first thing was a script that reads the 131 posts and records, for each one, the SHA-256 hash of the Portuguese file and of the English file, plus the exact commit of the blog repository everything was read from. If a comma changes in a post, the hash changes with it. That file is machine-generated and never edited by hand.</p>
<p>Then an agent read each post and filled out a fixed form, with a schema defined in YAML: the thesis in one or two sentences, the claims a book would need to verify, which of them age fast, which lay reader&rsquo;s fear the text answers, what to cut. Each analysis carries the hash of the post it came from.</p>
<p>Of the 131 texts, 96 had AI as the central subject or with relevant weight. The others only came in when they taught something specific, and every AI post left out has its reason recorded in the structure file. A script fails the structure if any AI post is left without a destination.</p>
<h3>Lineage: who supersedes whom<span class="hx:absolute hx:-mt-20" id="lineage-who-supersedes-whom"></span>
    <a href="#lineage-who-supersedes-whom" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>To solve the contradiction problem, there&rsquo;s a lineage map. It says which post superseded which, what can still be salvaged from the older one, and which corrections coming from the reference projects (the benchmark repository, ai-memory&rsquo;s, ai-jail&rsquo;s, my home server notes) apply to each text.</p>
<p>The rule for chapters is to tell the most recent state and, when the change teaches something, tell the change. &ldquo;In June I thought X; in July the numbers said Y&rdquo; is a story. Printing the old number as if it were current is an error, and the checker treats it as an error.</p>
<h2>Step 2: the structure is data, and it generates the configuration<span class="hx:absolute hx:-mt-20" id="step-2-the-structure-is-data-and-it-generates-the-configuration"></span>
    <a href="#step-2-the-structure-is-data-and-it-generates-the-configuration" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>From the analyses came a proposed structure: five parts, each answering a reader&rsquo;s fear, twenty chapters, two interludes. I read it, changed it and approved it. Some pieces came in at my request, like the &ldquo;before you start&rdquo; and the appendix on the machine inside.</p>
<p>That structure lives in a single YAML file, and it&rsquo;s the source of truth. Each chapter has its id, title, opening scene, the question it answers, the arc, the list of source posts and the figure ideas. The Quarto configuration, which assembles the book, is generated from that file by script. Nobody edits the configuration by hand.</p>
<p>This matters because structural change is where a book breaks. Midway I moved the cut-off: the January posts went out, and the story settled between February and October. Ten posts vanished from the base.</p>
<p>Three chapters needed a new scene, a dozen units needed small repairs, and the damage that&rsquo;s hard to see was elsewhere: a sentence in an untouched chapter saying &ldquo;the five reviewers from chapter 5&rdquo;, the timeline, the projects appendix, chart labels, every translation. That&rsquo;s why there&rsquo;s an impact script that, before any edit, lists every paragraph, figure, reference and translation that depends on a post.</p>
<h2>Step 3: a pilot chapter becomes a contract<span class="hx:absolute hx:-mt-20" id="step-3-a-pilot-chapter-becomes-a-contract"></span>
    <a href="#step-3-a-pilot-chapter-becomes-a-contract" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Before scaling, a pilot chapter. I picked chapter 5, about the first ten percent of a project, and it served to calibrate the voice and discover the doubts an agent would have along the way. Each doubt resolved became a written rule.</p>
<p>Those rules went into a contract document every agent reads before writing, along with three things:</p>
<ul>
<li>the book&rsquo;s voice guide, which inherits the blog&rsquo;s rules (my WRITER.md, the humanizer and my finishing checklist) and only adds what changes when the text leaves a dated post and goes into a book a lay reader holds in their hands;</li>
<li>a continuity file, saying which chapter explains each concept and what each character is called, so nobody explains &ldquo;context window&rdquo; five times;</li>
<li>the entire structure, so each agent knows what the other chapters cover.</li>
</ul>
<p>Besides the voice rules that already existed (a chapter opens on a scene with a date, a place and something at stake, never on a definition; it closes on a hook toward the next one, never on &ldquo;in this chapter we saw&rdquo;), some of the rules that came out of the pilot, to give you a taste:</p>
<ul>
<li>when the chapter brief and the post disagree on a detail, the post wins;</li>
<li>the chapter that owns a concept explains it properly; if the term shows up earlier in reading order, it gets a half-sentence gloss and a pointer, never a second explanation;</li>
<li>a fact verified online gets a citation even if the original post had no link;</li>
<li>model and product names in the vendor&rsquo;s spelling, even when the blog abbreviated them.</li>
</ul>
<blockquote>
  <p>It&rsquo;s the project instructions file I describe in the chapter about how to talk to the machine, at the scale of a book. Anyone who has written an AGENTS.md for a codebase recognizes all of it.</p>

</blockquote>
<h2>Step 4: parallel drafts, contradictions expected<span class="hx:absolute hx:-mt-20" id="step-4-parallel-drafts-contradictions-expected"></span>
    <a href="#step-4-parallel-drafts-contradictions-expected" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>With the contract ready, the chapters were drafted in parallel, one agent per chapter, in two waves: parts I and II first, then III through V, so the later chapters could build on the earlier ones. Each agent received its chapter&rsquo;s brief, the analyses, the full posts, the lineage and the reference-project files it needed.</p>
<p>Agents working at the same time contradict each other, and that happened. One chapter said FrankMD had around 130 commits in three days; another, that it had 212 in 19 days. Both numbers came from the posts and were right, they were just different windows. An integration ledger collected those conflicts, and the rule became making the window explicit in each chapter.</p>
<p>After the drafts comes the integration pass, with another set of agents, each owning a group of chapters and forbidden from touching the others. Their job: apply the conflict ledger, cut concepts explained twice, check that every callback matches what the other chapter actually says, make sure the last paragraph of a chapter leads into the first of the next, and redo the fact-check assuming the draft is wrong.</p>
<p>To read the seams, the build generates a &ldquo;seams&rdquo; file: the final paragraph of each unit next to the opening paragraph of the next. It&rsquo;s the fastest read there is for finding where the book stops feeling like one book.</p>
<h2>Step 5: an invisible marker per paragraph<span class="hx:absolute hx:-mt-20" id="step-5-an-invisible-marker-per-paragraph"></span>
    <a href="#step-5-an-invisible-marker-per-paragraph" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>This is the part I find most useful in the whole project. Every paragraph of the book, in the source file, carries a comment saying where it came from:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">&lt;!-- src: 2026/09/28/llms-sao-boas-em-reproduzir-o-que-existe-e-coisas-novas --&gt;
</span></span><span class="line"><span class="cl">Every LLM was trained only on what is public...
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">&lt;!-- src: original --&gt;
</span></span><span class="line"><span class="cl">New text, written for the book.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">&lt;!-- src: ref:ai-jail/README.md --&gt;
</span></span><span class="line"><span class="cl">Fact checked in the reference project.</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>The marker disappears when the book is built, through a Pandoc Lua filter, so the reader never sees it. It exists for maintenance. I edit posts after publishing all the time, and the book has to follow.</p>
<p>The <code>rake drift</code> command redoes the inventory, compares the hashes, and lists the chapters that depend on a post that changed, with the post&rsquo;s diff since the commit at which the book last read it. The marker leads straight to the paragraphs that came from that post, and only those need review. Once resolved, a script records the new hash and the commit.</p>
<p>A real example, from today. I removed from the <a href="/en/2026/10/13/ai-reverse-engineering-is-adobe-dead/">reverse engineering post</a> a paragraph about a Linus Tech Tips video. <code>drift</code> flagged chapter 19 and one appendix; the diff showed that passage had never been used in the book; two commands later, both were stamped with the new hash. Without the marker, I&rsquo;d have had to reread two chapters to discover I didn&rsquo;t need to change anything.</p>
<p>The bibliography plays the same role for external sources: each reference records which post cited it. And each image has its own provenance record.</p>
<h2>Step 6: what the fact-check caught<span class="hx:absolute hx:-mt-20" id="step-6-what-the-fact-check-caught"></span>
    <a href="#step-6-what-the-fact-check-caught" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Every number, date and name was checked against three oracles: the posts, the reference projects and primary sources online, with the same adversarial checker prompt I use on the blog&rsquo;s articles. The full list is in the book&rsquo;s afterword, and a good part of the corrections are to my own blog:</p>
<ul>
<li>in the March review of the Strix Halo mini-PC, I had set aside 96 GB of memory for the GPU; in April I lowered it to 64, and later posts still said 96. The book uses 64 for everything after April;</li>
<li>a counting bug in one of the benchmark&rsquo;s tools undercounted by 40 to 90 times the cost of runs made on it before August. The book cites none of those costs;</li>
<li>in the June text about Claude Fable 5, I wrote it cost ten times more than Opus 4.8 per run. Redoing the math in July, with cache-read tokens included, Fable cost almost double. The post still says ten times; the book tells the wrong number and the correction;</li>
<li>in a March text, I wrote that Anthropic had bought Bun at the end of 2024. The announcement is from December 2025;</li>
<li>a chapter summary, written by an agent, said Claude Code&rsquo;s subscription lock fell in less than a day after the leak. The announcement came about 30 hours later, and the book says &ldquo;the next day&rdquo;.</li>
</ul>
<blockquote>
  <p>The drafts came out fast. Confidence in the text came from the checking. And the source beats the summary, even when the summary comes from the machine.</p>

</blockquote>
<h2>Step 7: a chapter with an error doesn&rsquo;t pass<span class="hx:absolute hx:-mt-20" id="step-7-a-chapter-with-an-error-doesnt-pass"></span>
    <a href="#step-7-a-chapter-with-an-error-doesnt-pass" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>On top of everything runs an automatic checker, the equivalent of continuous integration. They&rsquo;re Ruby scripts, standard library only, chained in a Rakefile, plus what they call externally: the chart checker is Python because it lives inside matplotlib, the page audit uses poppler, and epubcheck needs Java:</p>
<ul>
<li>a <strong>chapter linter</strong> fails em dashes, phrases banned by the voice guide, loose URLs in the middle of prose, unknown citation keys, paragraphs without a provenance marker, and warns about overlong paragraphs;</li>
<li>a <strong>doctor</strong> checks that every cross-reference, citation, glossary term and figure exists, that provenance matches the inventory, that no post before the cut-off leaked in, that translations are up to date, and runs a callback heuristic: a sentence pointing at another chapter using names that chapter no longer contains;</li>
<li>a <strong>page audit</strong> opens the finished PDF and looks for blocks split across pages, headings orphaned at the foot of a page, nearly empty pages, oversized images, lines overflowing the margin;</li>
<li>a <strong>chart checker</strong> looks for labels that spilled out of their boxes;</li>
<li><strong>epubcheck</strong> validates the EPUB 3;</li>
<li>a <strong>style report</strong> for copyediting: passages repeated across chapters (an inevitable consequence of posts that repeat the same thesis from different angles), recurring phrases, overused words, term variants, badly formed comparatives in Portuguese.</li>
</ul>
<p>And the scripts have tests. A suite of almost 170 tests builds a fake book in a temporary directory, with five fake posts in a fake git repository, and checks that each tool catches the problem it should catch. When a bug is fixed, the test that would have caught it goes in, with a comment naming the regression it guards. It runs in CI before every build.</p>
<h2>The assembly pipeline<span class="hx:absolute hx:-mt-20" id="the-assembly-pipeline"></span>
    <a href="#the-assembly-pipeline" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The toolchain is Quarto, which bundles Pandoc and Typst, version-pinned inside the repository. No LaTeX. A single <code>rake build</code> produces, from the same tree of Markdown files:</p>
<table>
  <thead>
      <tr>
          <th>Output</th>
          <th>For what</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>EPUB 3</td>
          <td>Kindle, Kobo, Apple Books, any reader</td>
      </tr>
      <tr>
          <td>Screen PDF</td>
          <td>reading on a computer or tablet, with the cover</td>
      </tr>
      <tr>
          <td>Print PDF</td>
          <td>6 by 9 inches, blank versos, chapters opening on the right</td>
      </tr>
      <tr>
          <td>HTML</td>
          <td>web edition</td>
      </tr>
      <tr>
          <td>DOCX</td>
          <td>for an editor who wants Word</td>
      </tr>
  </tbody>
</table>
<p>Portuguese and English are Quarto profiles, generated from the same structure file. Citations come from a YAML in CSL format shared by both editions, with an ABNT style adjusted for Portuguese. The glossary is a Lua filter: each term is marked in the source where it appears, and the filter links the mark to the entry, expands the acronym the first time and generates the page.</p>
<p>Typst solved something I thought would cost me weeks: a PDF that looks like a typeset book, Portuguese hyphenation, ligatures, without the pain of TeX. The page audit after the build catches what the engine let through, and a <code>rake fit</code> recompiles while tightening chapters that end on a nearly empty page.</p>
<h3>The figures<span class="hx:absolute hx:-mt-20" id="the-figures"></span>
    <a href="#the-figures" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Every figure is code or has a record. Charts and box-and-arrow diagrams are matplotlib scripts, 43 of them, each with a note of the chapter the data came from, and with the labels in Portuguese and English inside the script itself: the same chart comes out in both languages. The path for D2 diagrams exists in the repository, and no figure in the book needed it.</p>
<p>The conceptual illustrations were generated by AI, with the model, the prompt and the date of each one recorded in its credit record, and the book discloses it. The rule I imposed on myself: no AI-generated image of a real person. Real people only appear in freely licensed photos, with the credit in the caption.</p>
<p>The cover is the retro-futurist robot with the weary face, kneeling at a 1950s World&rsquo;s Fair, studying its own hand while the crowd watches. The prompt to the model described the scene to hold three fears at once: the end of humanity, losing your job, the machine becoming conscious. The cover&rsquo;s record keeps the whole prompt. The face is Marvin&rsquo;s, my newsletter&rsquo;s character, and a sticker with my face sits beside the name.</p>
<h2>The tricks of turning posts into a book<span class="hx:absolute hx:-mt-20" id="the-tricks-of-turning-posts-into-a-book"></span>
    <a href="#the-tricks-of-turning-posts-into-a-book" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Turning a blog into a book is a list of mechanical conversions, and each one has a catch:</p>
<ul>
<li><strong>A link becomes a citation.</strong> Every external link became a bibliography entry, and the sentence has to stand without the link. A link to another post of mine became a cross-reference to the chapter that now covers it, or disappeared. Never a URL in the prose.</li>
<li><strong>&ldquo;Today&rdquo;, &ldquo;yesterday&rdquo;, &ldquo;last week&rdquo;, &ldquo;update:&rdquo;</strong> became absolute dates. The book will be read in 2028 too.</li>
<li><strong>Model versions, prices, benchmark scores</strong> stayed as dated snapshots (&ldquo;in September 2026, the best&hellip;&rdquo;), and when a later post superseded the number, the book tells the change instead of printing the old number.</li>
<li><strong>Code dumps, install steps, terminal screenshots</strong> were cut. At most a 3-to-8-line excerpt when the code is the point; the step-by-step went to an appendix.</li>
<li><strong>Post titles, which are made for search</strong> (&ldquo;Vibe Code: I built X in two days&rdquo;), became short literary titles, with the subject in the subtitle.</li>
<li><strong>Repetition across posts</strong>, the same thesis from many angles, is said once, in the right place, and later chapters build on it.</li>
<li><strong>Calls to action, &ldquo;subscribe&rdquo;, &ldquo;comment&rdquo;</strong>, cut.</li>
<li><strong>The sharp edge aims at the propaganda, never at the reader.</strong> The post &ldquo;You&rsquo;re an idiot if you believe&hellip;&rdquo; became a chapter about how the ads work. The reader who believed the ad is the person the book wants to help.</li>
<li><strong>Every technical term is explained once</strong>, at its first appearance in the book, and goes to the glossary.</li>
</ul>
<p>And the most important of all: the book reads like a first-person story, with the year as its spine. Information arrives when the narrative needs it, instead of following encyclopedia order. That&rsquo;s the opposite of how a blog is written, and it was the rule that gave the agents the most trouble.</p>
<h2>The English edition<span class="hx:absolute hx:-mt-20" id="the-english-edition"></span>
    <a href="#the-english-edition" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The English edition, <em>Competent Enough</em>, only started after I approved the Portuguese one. Each translated unit records the hash of the Portuguese file it came from, and wherever the book follows a post of mine that already had an English version on the blog, the translation uses my own English wording instead of translating again.</p>
<p><code>drift</code> also works per language: if I change a paragraph in Portuguese, it flags the English unit that went stale, and only the marked paragraphs are retranslated. Charts with text are regenerated in English from the same scripts, and the English cover is composed by script on top of the same art.</p>
<h2>Releasing is pushing a tag<span class="hx:absolute hx:-mt-20" id="releasing-is-pushing-a-tag"></span>
    <a href="#releasing-is-pushing-a-tag" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>A release is a CHANGELOG entry and a <code>git push</code> of a <code>vX.Y.Z</code> tag. A GitHub Actions workflow runs the tests, builds both editions in every format, validates the EPUB, runs the audit and publishes the release with the files. It deletes every release except the two newest, and keeps the tags. That&rsquo;s how the official page always points at the current version.</p>
<p>The repository is public, and that brought its own catch: my home server notes are the source of some facts, and they&rsquo;re private. The provenance markers cite those files by alias, the alias map stays out of git, and a pre-push hook blocks any file or commit message containing a private repository name, host or IP.</p>
<h2>Copyediting: what the checking machine lets through<span class="hx:absolute hx:-mt-20" id="copyediting-what-the-checking-machine-lets-through"></span>
    <a href="#copyediting-what-the-checking-machine-lets-through" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Lint, doctor, page audit and tests catch structural problems. They let through what a book written by many agents, each seeing a few chapters, always suffers from: the same sentence or anecdote reused in three chapters, drifting tone, inconsistent terminology, agreement slips. For that there&rsquo;s a copyedit procedure, which runs once per version, in three steps from the cheapest to the most expensive.</p>
<p><strong>Step 1, mechanical and nearly free:</strong> the style report I mentioned above. Sequences of seven words or more that appear in more than one unit, meaning reused sentences and retold anecdotes; set phrases of four to six words used in many chapters, which are nice as callbacks and become tics when they repeat; a word used far more in one chapter than in the rest; term variants (&ldquo;e-mail&rdquo; and &ldquo;email&rdquo;, &ldquo;Open AI&rdquo; and &ldquo;OpenAI&rdquo;); and an agreement heuristic for Portuguese. The report is a worklist, and nothing changes on its own.</p>
<p><strong>Step 2, the straight-through read:</strong> one read-only agent per part of the book, each reading its units in order, start to finish, with a shared style sheet (names, spellings, terms, recurring phrases from step 1). Each produces a ranked report, editing nothing: typos and grammar first, then inconsistencies with the style sheet, repetition the reader would notice, passages a lay reader would stumble on, and pacing only in the worst cases. A script validates the reports, checks that every quoted passage really exists in the unit, numbers the items and summarizes.</p>
<p>Then comes the triage, done by me with an editor agent, and the pointed application of each approved item, under the same rules as the integration pass. A cheaper model does the proofreading; hard passages go to the strong model. Rough budget: two to three million tokens per language.</p>
<p>The most important rule of that step is &ldquo;facts get checked, not asked&rdquo;. Any item that turns on a number, date, name or tool behavior is settled by the editor against the source of truth before it reaches me: first the post pointed to by the paragraph&rsquo;s provenance marker, recomputing totals; then the code or data behind the claim, in my repositories; then public records.</p>
<p>When two sources disagree, the task is to find out why. &ldquo;653 commits in 8 projects&rdquo; versus &ldquo;692 in 4&rdquo; were two cuts of the same work, one of them without the newsletter&rsquo;s private repository, and the text now states its scope instead of picking a number. When the blog post itself is wrong, the book prints the correct figure and the error goes to a blog errata list, for me to fix at the source.</p>
<p>Only what no source can settle reaches me: an unpublished fact, intent (&ldquo;is this ironic?&rdquo;), a preference about a cut or a title, and a contradiction between two statements of mine with no record to break the tie. Each question comes with what was checked and what was found.</p>
<p><strong>Step 3, my own read.</strong> The last and the most valuable. The notes go into the same cycle of apply, check and propagate to the English edition.</p>
<p>The first round of that copyedit is what separates preview 2 from preview 3. Among what it caught: commit counts now state their scope, a &ldquo;more than a thousand&rdquo; that summed to 984, the Frank Investigator voting example that didn&rsquo;t match the code (figure redrawn), the David Sacks and Pirate Wires quotes in chapter 14 verified against the originals and corrected, Sam Altman&rsquo;s photo swapped for one from 2025. And in the English edition, a reader pass of its own after the re-sync: Portuguese calques rewritten, glossary terms used consistently, American quotation punctuation throughout.</p>
<h2>Fake readers, real feedback<span class="hx:absolute hx:-mt-20" id="fake-readers-real-feedback"></span>
    <a href="#fake-readers-real-feedback" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Copyediting checks the text. It lets through the question that matters in a book for lay readers: can the person I wrote it for read it to the end, understand it, and come out convinced? To answer that, the next pass was a review by simulated readers.</p>
<p>The book&rsquo;s preface has a section called &ldquo;Who I wrote this for&rdquo;. From it came five personas, each with a name, an age, a job and the fear that brought them to the book:</p>
<ul>
<li><strong>Marina</strong>, 38, an accountant in Belo Horizonte, read that her job &ldquo;ends in two years&rdquo;, reads on her phone at night and wants to know what to do on Monday;</li>
<li><strong>Roberto</strong>, 52, owns a hardware store, his 15-year-old saw a video about superintelligence and asked if it was true; suspicious of hype, of &ldquo;experts&rdquo; and of an author who shows off;</li>
<li><strong>Carla</strong>, 44, operations manager at a logistics company, the board hired consultants selling an &ldquo;AI transformation&rdquo;; she wants a decision she can take;</li>
<li><strong>Lucas</strong>, 24, a junior developer a year into the job, afraid he chose the wrong career;</li>
<li><strong>Helena</strong>, 61, a retired history teacher, no fear at all, came for the stories and loses patience with lists and manuals.</li>
</ul>
<p>One agent per persona, read-only, cheaper model, reads the whole book in order the way that person would. The instruction is explicit: you are a reader, the editor stays out of it; comma errors were already handled, report only what changes the reading experience. Each one returns a 1-to-5 score per chapter, a comment in the persona&rsquo;s voice (&ldquo;I finally get why the chatbot agrees with me&rdquo;, &ldquo;lost me in the benchmark tables&rdquo;), at most 35 annotations classified as confusing, boring, rewrite or logic, and cut candidates. It costs about 350K tokens per persona per full read.</p>
<p>An editor consolidates: the score matrix by chapter and persona and the pattern behind it, what readers loved (to protect in any edit), the logic items, checked against the text and the posts before making the list and fixed regardless of votes, and the clarity items ranked by how many personas raised them. A single persona&rsquo;s taste note is dropped. Then I decide, and recurring patterns become numbered rules in an editorial rules document, with their origin and how each is enforced.</p>
<blockquote>
  <p>The first read said what I suspected and gave it a measure: stories and practical tools work for everyone; the measurement-heavy middle, chapters 11 to 13, loses the non-programmers, averaging between 2.2 and 2.4. &ldquo;Sharp when he tells what happened to him, loses me when he tells what he measured&rdquo;, Helena summed up, for all five.</p>

</blockquote>
<p>And all five caught the same argument flaws. Chapter 20&rsquo;s conclusion went beyond its evidence: it said &ldquo;the numbers say it won&rsquo;t get smarter&rdquo; resting on a programming benchmark the same chapter calls saturated. Chapter 9 argued in a way that can never lose: every agent failure was the request&rsquo;s fault. Four of the five were sent to the wrong chapter by &ldquo;how to read&rdquo;.</p>
<p>Those became the first rules:</p>
<ul>
<li>every claim scoped to what was measured;</li>
<li>no argument that can&rsquo;t lose;</li>
<li>opinion marked as opinion;</li>
<li>the opposing side in its strongest form before rebutting;</li>
<li>the book obeys its own lessons.</li>
</ul>
<p>One round is not enough, because edits fix the old problem and create the new one. In round two, an apology placed next to a contradiction (&ldquo;I know this seems to clash with&hellip;&rdquo;) made all five readers notice a contradiction that three had previously missed. It became a rule: fix the design, and leave the apology out. So the process runs in rounds: read, edit, read again with the same personas on a fresh read, forbidden from opening the previous reports to avoid anchoring, and a script compares the rounds.</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th style="text-align: right">round 1</th>
          <th style="text-align: right">round 2</th>
          <th style="text-align: right">round 3</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>book average score</td>
          <td style="text-align: right">3.32</td>
          <td style="text-align: right">3.38</td>
          <td style="text-align: right">3.41</td>
      </tr>
      <tr>
          <td>logic annotations</td>
          <td style="text-align: right">73</td>
          <td style="text-align: right">53</td>
          <td style="text-align: right">51</td>
      </tr>
  </tbody>
</table>
<p>The average score is noisy (an untouched chapter swings 0.6 between reads), so the stopping criterion is different: the problems flagged stopped coming back and nothing new reaches three readers. In round three the curve flattened and the review stopped there, with a backlog for my own read. What changed along the way: about 8,000 words of lab notebook left the chapters for a new appendix, &ldquo;For programmers: the backstage&rdquo;, each paragraph carrying its provenance marker along; the reading list became an appendix; the Genesys PI section was parked, kept outside the book while verification is pending; chapter 19 got the title its argument supports; every chapter opens by orienting the reader before the first jargon; and the epilogue got a &ldquo;this week&rdquo; list per reader type. Cost of the three rounds: about 5 million tokens of reading plus about 3 million of editing and English re-sync.</p>
<h2>The narrator got a past<span class="hx:absolute hx:-mt-20" id="the-narrator-got-a-past"></span>
    <a href="#the-narrator-got-a-past" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>With the argument in place, the first person lacked substance. The book&rsquo;s narrator was the Akita of 2026, and I have thirty years of history that explain why I think what I think: the dot-com crash seen from inside, five years integrating SAP at large companies, the warnings about the hiring bubble I gave on video in 2019, 2020 and 2022, the &ldquo;Don&rsquo;t outsource your decisions&rdquo;. All of it is in the transcripts of the 149 episodes of <a href="https://www.youtube.com/@Akitando"target="_blank" rel="noopener">Akitando</a>, published on this blog between 2018 and 2023.</p>
<p>The process was the same as the rest of the book, in miniature. Extraction agents read 23 episodes in full, with a form: biographical facts with the verbatim quote and what would verify them, facts about the world, recurring positions in my words, and hooks, meaning the exact place in the book where one or two sentences of that history back a 2026 claim. From that came a narrator profile, which I confirmed line by line, and a plan with about 30 touches, most of them one to three sentences.</p>
<p>Before any touch, more than 140 claims taken from the episodes went through the fact-check. It corrected the book and corrected me: the hiring bubble started around 2010, with interest rates near zero, and my February post said 2014; the dot-com bubble burst between 2000 and 2002; the 2022 layoffs were around 165 thousand. And it found errors in old episodes the book doesn&rsquo;t even use, which went to a blog errata list.</p>
<p>The touches went where experience becomes evidence: the week in 2001 when my dot-com closed and a mentor called me into an SAP consultancy; the SAP years behind the claim that the model is blind to a company&rsquo;s private rules; the dated bubble warnings next to the admitted mistake, because in 2022 I expected a second leg down in 2023 that the AI wave cancelled. Two new appendices came out of it: &ldquo;Three bubbles&rdquo;, with the verified numbers of the dot-com crash, the zero-interest bubble and the AI wave, and &ldquo;How to study with AI at your side&rdquo;, from the channel&rsquo;s most watched episode.</p>
<p>Those episodes are background sources, and <code>drift</code> now watches them as it watches the 2026 posts. Then came a scoped check with the same five personas, only on the touched chapters, with three extra questions: does the narrator&rsquo;s history make the argument more convincing, and where? Does any passage read as showing off or &ldquo;I told you so&rdquo;? Does anything about the narrator contradict itself?</p>
<blockquote>
  <p>All five said yes to credibility, with a condition: the history convinces when it&rsquo;s evidence the reader can check, the dated warning next to the admitted mistake, and convinces less when it becomes a résumé, which clashes with the book itself, which says &ldquo;a résumé is not an argument&rdquo;. It became rule 21: the narrator&rsquo;s history comes in as evidence, and credentials stay out.</p>

</blockquote>
<p>Three or four readers flagged the same lines as showing off, and they went: &ldquo;The warnings have dates&rdquo;, &ldquo;more than thirty public repositories&rdquo;, &ldquo;the most watched on my channel&rdquo;. The self-deprecating lines and the admitted mistakes all counted in my favor. And the check found contradictions I hadn&rsquo;t seen myself: the preface said &ldquo;late 90s&rdquo; and chapter 18 said 1996; one chapter said &ldquo;eight months&rdquo; and another &ldquo;a year of daily use&rdquo;, and they were fixed one by one.</p>
<h2>Accessibility is part of the build too<span class="hx:absolute hx:-mt-20" id="accessibility-is-part-of-the-build-too"></span>
    <a href="#accessibility-is-part-of-the-build-too" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>An EPUB opening on a Kindle does not make it accessible. This book has dozens of diagrams, charts and tables. Without additional work, much of the argument simply disappears for anyone using a screen reader.</p>
<p>The pipeline now treats accessibility as a publishing contract. Each of the 55 figures, in both languages, has a short alternative text and a complete description of what the image communicates. In HTML and EPUB, the detailed description appears with the figure; in PDF, it becomes its semantic replacement without changing the layout. Tables have captions, and the EPUB now identifies where the main text, glossary, references and image credits begin in its semantic navigation. The authoring contract is <a href="https://github.com/akitaonrails/ai-book-2026/blob/main/docs/ACCESSIBILITY.md"target="_blank" rel="noopener">documented in the repository</a>.</p>
<p>This doesn&rsquo;t depend on my memory either. <code>rake check</code> rejects figures without both descriptions or with overly long alternative text. Every build validates both EPUBs with EPUBCheck, DAISY Ace and the project&rsquo;s own checks. The Kindle edition also goes through a cleanup of CSS and embedded icons that tend to cause problems in Amazon&rsquo;s readers, but the script refuses to remove any rule the content has come to depend on.</p>
<p>No automated tool can certify WCAG conformance or guarantee how every reader on the market will behave. Manual review remains mandatory. The difference is that accessibility is now part of the build, and every change has to preserve that contract.</p>
<h2>What remains mine<span class="hx:absolute hx:-mt-20" id="what-remains-mine"></span>
    <a href="#what-remains-mine" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The repository records the first commit and the draft of every chapter on the same day, October 13. Those are the first ten percent, the ones that impress and say almost nothing about the rest. The other ninety percent are reading, cutting and correcting, and that part is mine. No chapter goes in without me reading and approving it, and what I send back to be redone goes through the same process.</p>
<p>Any of the good models of October 2026 would have written similar drafts, because the model became a commodity. What made the process work was what surrounds it: the inventory, the written contract, the automatic checker, the sources as oracle, the per-paragraph trail. It&rsquo;s the same old software engineering I defend in every chapter, applied to text.</p>
<blockquote>
  <p>The agents were competent enough to write the draft. Deciding what it said remained my job.</p>

</blockquote>
<p>And, once again: making a book with AI isn&rsquo;t a &ldquo;write me a book&rdquo; prompt and done. I had to invent the whole process and steer the agent to create every piece of it: the scripts, the tests, the consolidation of the posts, the narrative strategy, the goals, what stays and what goes, the copyedit, the fact-checking, the automated release. You need to know exactly what you want, and then the AI helps a lot. Whoever doesn&rsquo;t know what a book publishing process involves won&rsquo;t make a real book, and showing that was one of the goals I had when creating this example.</p>
<h2>Download it, read it, and tell me where I was wrong<span class="hx:absolute hx:-mt-20" id="download-it-read-it-and-tell-me-where-i-was-wrong"></span>
    <a href="#download-it-read-it-and-tell-me-where-i-was-wrong" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Both editions, straight from GitHub, no sign-up. The current version is the final 1.0.0, from October 17, with everything this text describes:</p>
<table>
  <thead>
    <tr><th>Edition</th><th>EPUB (Kindle, Kobo, Apple Books)</th><th>Screen PDF</th><th>Print PDF (6 × 9 in)</th></tr>
  </thead>
  <tbody>
    <tr><td>Competent Enough (EN)</td><td><a href="https://github.com/akitaonrails/ai-book-2026/releases/download/v1.0.0/Competent-Enough.epub">EPUB</a></td><td><a href="https://github.com/akitaonrails/ai-book-2026/releases/download/v1.0.0/Competent-Enough-ebook.pdf">PDF</a></td><td><a href="https://github.com/akitaonrails/ai-book-2026/releases/download/v1.0.0/Competent-Enough.pdf">PDF</a></td></tr>
    <tr><td>Competente o Suficiente (PT-BR)</td><td><a href="https://github.com/akitaonrails/ai-book-2026/releases/download/v1.0.0/Competente-o-Suficiente.epub">EPUB</a></td><td><a href="https://github.com/akitaonrails/ai-book-2026/releases/download/v1.0.0/Competente-o-Suficiente-ebook.pdf">PDF</a></td><td><a href="https://github.com/akitaonrails/ai-book-2026/releases/download/v1.0.0/Competente-o-Suficiente.pdf">PDF</a></td></tr>
  </tbody>
</table>
<p>The latest version, always, lives on the <a href="https://ailair.akitaonrails.com/book/"target="_blank" rel="noopener">book page</a> and on the <a href="https://github.com/akitaonrails/ai-book-2026/releases"target="_blank" rel="noopener">GitHub releases</a>.</p>
<p>It&rsquo;s a preview. There will be mistakes, and the process above exists so they get fixed in the right place. Found one, <a href="https://github.com/akitaonrails/ai-book-2026/issues"target="_blank" rel="noopener">open an issue</a>.</p>
]]></content:encoded><category>artificial-intelligence</category><category>coding-agents</category><category>open-source</category></item><item><title>LLMs + Agents = competent enough</title><link>https://akitaonrails.github.io/en/2026/10/12/llms-agents-competent-enough/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/10/12/llms-agents-competent-enough/</guid><pubDate>Mon, 12 Oct 2026 12:00:00 -0300</pubDate><description>&lt;p&gt;This post is a synthesis. It ties into a single narrative what I&amp;rsquo;ve been writing and measuring through 2026, so here&amp;rsquo;s the road map before the argument:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://akitaonrails.github.io/en/2026/09/23/llm-benchmark-v4-opus-5-5-gpt-6-sol-luna-mimo-2-6-grok-4-7/"&gt;New v4 benchmarks&lt;/a&gt;&lt;/strong&gt;: I retested the major models and the uncomfortable conclusion was convergence, not a leap.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://akitaonrails.github.io/en/2026/09/28/llms-are-good-at-reproducing-what-exists-what-about-new-things/"&gt;The limits of LLMs&lt;/a&gt;&lt;/strong&gt;: models are great at reproducing what exists, extremely expensive at what doesn&amp;rsquo;t, and the served model is a static file that learns nothing from your marathon.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://akitaonrails.github.io/en/2026/10/11/are-there-better-languages-for-programming-with-llms/"&gt;Are there better languages for programming with LLMs?&lt;/a&gt;&lt;/strong&gt;: no. Neither script conciseness nor strong typing changed the outcome; test discipline did.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://akitaonrails.github.io/en/2026/10/10/which-jev-like-ai-decision-classifier-model-is-best/"&gt;Which Jev-like decision model is best?&lt;/a&gt;&lt;/strong&gt;: 21 classifier configurations, and the &amp;ldquo;specialized models&amp;rdquo; themselves converged to within a few points of each other.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://akitaonrails.github.io/en/2026/04/20/clean-code-for-ai-agents/"&gt;Clean Code for AI agents&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://akitaonrails.github.io/en/2026/04/11/vs-code-is-the-new-punch-card/"&gt;VS Code is the new punch card&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://akitaonrails.github.io/en/2026/09/17/talking-about-my-ai-skills/"&gt;my skills&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://akitaonrails.github.io/en/2026/08/18/hot-take-harness-loop-engineering-graph-engineering-are-bullshit/"&gt;the hot take against loop engineering&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://akitaonrails.github.io/en/2026/05/30/open-source-best-practices-llm-the-minimum/"&gt;minimum best practices&lt;/a&gt;&lt;/strong&gt;: the same thesis from other angles. The model is a commodity; the engineering around it is the differentiator.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The thesis that closes this arc: &lt;strong&gt;LLMs have reached, or are very close to reaching, the ceiling of the transformer architecture.&lt;/strong&gt; And the good news is that nothing more than that is needed.&lt;/p&gt;</description><content:encoded><![CDATA[<p>This post is a synthesis. It ties into a single narrative what I&rsquo;ve been writing and measuring through 2026, so here&rsquo;s the road map before the argument:</p>
<ul>
<li><strong><a href="/en/2026/09/23/llm-benchmark-v4-opus-5-5-gpt-6-sol-luna-mimo-2-6-grok-4-7/">New v4 benchmarks</a></strong>: I retested the major models and the uncomfortable conclusion was convergence, not a leap.</li>
<li><strong><a href="/en/2026/09/28/llms-are-good-at-reproducing-what-exists-what-about-new-things/">The limits of LLMs</a></strong>: models are great at reproducing what exists, extremely expensive at what doesn&rsquo;t, and the served model is a static file that learns nothing from your marathon.</li>
<li><strong><a href="/en/2026/10/11/are-there-better-languages-for-programming-with-llms/">Are there better languages for programming with LLMs?</a></strong>: no. Neither script conciseness nor strong typing changed the outcome; test discipline did.</li>
<li><strong><a href="/en/2026/10/10/which-jev-like-ai-decision-classifier-model-is-best/">Which Jev-like decision model is best?</a></strong>: 21 classifier configurations, and the &ldquo;specialized models&rdquo; themselves converged to within a few points of each other.</li>
<li><strong><a href="/en/2026/04/20/clean-code-for-ai-agents/">Clean Code for AI agents</a></strong>, <strong><a href="/en/2026/04/11/vs-code-is-the-new-punch-card/">VS Code is the new punch card</a></strong>, <strong><a href="/en/2026/09/17/talking-about-my-ai-skills/">my skills</a></strong>, <strong><a href="/en/2026/08/18/hot-take-harness-loop-engineering-graph-engineering-are-bullshit/">the hot take against loop engineering</a></strong> and <strong><a href="/en/2026/05/30/open-source-best-practices-llm-the-minimum/">minimum best practices</a></strong>: the same thesis from other angles. The model is a commodity; the engineering around it is the differentiator.</li>
</ul>
<p>The thesis that closes this arc: <strong>LLMs have reached, or are very close to reaching, the ceiling of the transformer architecture.</strong> And the good news is that nothing more than that is needed.</p>
<h2>Convergence, not a leap<span class="hx:absolute hx:-mt-20" id="convergence-not-a-leap"></span>
    <a href="#convergence-not-a-leap" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>In my benchmarks, I see no relevant improvement in general programming since the Opus 4.5 generation. Yes, Fable and Astra are great at specific problems. In general programming, what I measure is everyone squeezed onto the same tier, including the Chinese commercial offerings (Kimi, GLM, DeepSeek). Model choice has become nearly irrelevant.</p>
<p>What still makes a real difference is the effort level: low effort for translation and summarization, high effort for vulnerability sweeps, heavy bug fixing or optimization. Beyond that, the numbers tell a reality much more boring than <a href="/en/2026/09/09/propagandas-enganosas-da-openai-anthropic-nvidia/">the vendors&rsquo; propaganda</a>.</p>
<blockquote>
  <p>My reading of the timeline: the models&rsquo; &ldquo;core&rdquo; reasoning had its last big leap in 2024. 2025 was the year of optimizing the architecture. 2026 is the year of refining the harness. Base intelligence made no order-of-magnitude leap in that period; efficiency and long-session competence did.</p>

</blockquote>
<h2>The timeline, with receipts<span class="hx:absolute hx:-mt-20" id="the-timeline-with-receipts"></span>
    <a href="#the-timeline-with-receipts" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p><img src="/2026/10/12/llms-agentes-competente-o-suficiente/llms-agentes-timeline.png" alt="Timeline from 2019 to 2026: GPT-2 proves LLMs are useful, GPT-3 opens the parameter war, Chinchilla recalibrates toward data, GPT-4 turns parameter counts into secrets, o1 marks the reasoning peak, 2025 optimizes with MoE and caching, and 2026 is the agent era"  loading="lazy" /></p>
<p><strong>2019: GPT-2 proves LLMs are useful.</strong> 1.5 billion parameters, summarizing, translating and answering with no specific training, zero-shot. OpenAI found it so impressive that it <a href="https://openai.com/index/better-language-models/"target="_blank" rel="noopener">held back the full model for months</a> fearing misuse. Today it looks cute.</p>
<p><strong>2020: GPT-3 opens the parameter war.</strong> <a href="https://arxiv.org/abs/2005.14165"target="_blank" rel="noopener">175 billion</a>, a hundred times GPT-2, and the in-context few-shot learning that became the paradigm. <a href="https://arxiv.org/abs/2001.08361"target="_blank" rel="noopener">Kaplan&rsquo;s scaling law</a>, published months earlier, said loss fell as a power law with size, and the industry read it as &ldquo;bigger is better.&rdquo; There went two years of who-has-more-parameters.</p>
<p><strong>2022: Chinchilla recalibrates the war.</strong> DeepMind trained <a href="https://arxiv.org/abs/2203.15556"target="_blank" rel="noopener">400 models and showed</a> the giants were undertrained: a 70B model with 1.4 trillion tokens beat the 280B Gopher. The &ldquo;training data&rdquo; axis started weighing as much as the &ldquo;parameters&rdquo; axis. First crack in the war.</p>
<p><strong>2023: GPT-4 ends the war by decree.</strong> The <a href="https://arxiv.org/abs/2303.08774"target="_blank" rel="noopener">technical report</a> refused to publish size, hardware or data, citing the competitive landscape and safety implications. The most cited leak, from <a href="https://newsletter.semianalysis.com/p/gpt-4-architecture-infrastructure"target="_blank" rel="noopener">SemiAnalysis</a>, described 1.76 trillion parameters in a mixture of experts. Since then, parameter counts vanished from marketing: neither the GPT-5 announcements nor the Claude 4 ones cite a number. Notice neither Astra nor Fable spends a line on it today. The war ended and nobody signed an armistice.</p>
<p><strong>2024: the reasoning peak.</strong> <a href="https://openai.com/index/learning-to-reason-with-llms/"target="_blank" rel="noopener">September&rsquo;s o1</a> marked that peak: RL to produce long chains of thought, and the discovery that more test-time compute improves the answer. That is, by my yardstick, the last &ldquo;base intelligence&rdquo; revolution.</p>
<p><strong>2025: architecture optimization.</strong> Mixture of experts became the standard: <a href="https://mistral.ai/news/mixtral-of-experts/"target="_blank" rel="noopener">Mixtral</a> was already showing in 2023 that 46.7B total parameters with only 12.9B active per token cost like a small model, and <a href="https://arxiv.org/abs/2412.19437"target="_blank" rel="noopener">DeepSeek-V3</a> took that to 671B total with 37B active, with the final training run costing under 6 million dollars in GPU-hours at H800 rental prices (not counting the prior R&amp;D). The MoE magic is simple: it separates capacity (total parameters, which live in memory) from per-token cost (only the experts chosen by the router compute). You pay for a 37B model and carry a 671B one.</p>
<p>On the serving side, <a href="https://www.anthropic.com/news/prompt-caching"target="_blank" rel="noopener">prompt caching</a> cut up to 90% of repeated-context cost (OpenAI <a href="https://openai.com/index/api-prompt-caching/"target="_blank" rel="noopener">followed two months later</a>), context windows passed 1 million tokens, and serving techniques like speculative decoding and PagedAttention multiplied throughput. And <a href="https://arxiv.org/abs/2501.12948"target="_blank" rel="noopener">DeepSeek-R1-Zero</a> showed that pure RL, with no supervised fine-tuning, makes reasoning emerge. None of this is &ldquo;more intelligence.&rdquo; All of it is the same intelligence, cheaper, faster and more stable.</p>
<p><strong>2026: the agentic era.</strong> Function calling has existed since <a href="https://openai.com/index/function-calling-and-other-api-updates/"target="_blank" rel="noopener">June 2023</a>, but the ecosystem turning point was <a href="https://www.anthropic.com/news/model-context-protocol"target="_blank" rel="noopener">Anthropic&rsquo;s MCP</a> in late 2024, which OpenAI adopted months later and which today lives at the Linux Foundation. Claude Code, Codex and co. came out in 2025, and the metric that matters became <a href="https://metr.org/blog/2025-03-19-measuring-ai-ability-to-complete-long-tasks/"target="_blank" rel="noopener">METR</a>&rsquo;s: the task size an agent completes with 50% reliability had been doubling every 7 months since 2019. Anthropic&rsquo;s own guide on <a href="https://www.anthropic.com/engineering/building-effective-agents"target="_blank" rel="noopener">building effective agents</a> states the obvious plainly: simple, composable patterns, not fanciful frameworks.</p>
<h2>Why the agent allows a less dense model<span class="hx:absolute hx:-mt-20" id="why-the-agent-allows-a-less-dense-model"></span>
    <a href="#why-the-agent-allows-a-less-dense-model" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Here&rsquo;s the mechanism most people don&rsquo;t stop to think about. A lone model needs to carry the world in its weights, because its only chance to answer is that one, in a single pass. A model with a harness doesn&rsquo;t:</p>
<ul>
<li><strong>On-demand search and reading.</strong> With web search and fetch, low-priority knowledge leaves the weights and becomes a lookup: the agent pulls it into the context window only when needed. The model can be less encyclopedic and more operator.</li>
<li><strong>Controlled trial and error.</strong> Alone, the model needs to guess the right answer on the first try. With an agent, it proposes a hypothesis, implements, sends it to be tested, gets the feedback and decides again with real information. Each such cycle is new knowledge entering the session without costing a training neuron.</li>
</ul>
<p>Both mechanisms fight hallucination at the root: fetch brings the fact the model doesn&rsquo;t know by heart, and the test loop catches the invention before it becomes code. That&rsquo;s why 2026 <strong>feels</strong> like a giant leap: the model+harness combination got much more competent, even with base intelligence nearly stalled.</p>
<h2>Not every problem needs a giant LLM<span class="hx:absolute hx:-mt-20" id="not-every-problem-needs-a-giant-llm"></span>
    <a href="#not-every-problem-needs-a-giant-llm" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The same &ldquo;less dense&rdquo; logic applies inside the application. Much of what people throw at a chat LLM is disguised classification: labeling tickets, routing queues, applying policy. For that there are specialized decision models, and I covered the topic twice: the <a href="/en/2026/10/03/understanding-the-jev-hype-what-is-it-for/">Jev hype</a>, with Paulo Câmara&rsquo;s essay on why a classifier is the first thing a computer scientist thinks of, and <a href="/en/2026/10/10/which-jev-like-ai-decision-classifier-model-is-best/">my benchmark with 21 configurations</a>, where a Microsoft 9B tied the hosted leader and a local 4B came within a few points, at cents per ten thousand decisions.</p>
<p>The &ldquo;193x faster&rdquo; shock of Jev&rsquo;s marketing only exists because many people were using a giant LLM as an expensive, slow classifier. When the right tool enters, the frontier model leaves the play, and along with it the cost, the latency and the format hallucination. It&rsquo;s this post&rsquo;s thesis in miniature: competence doesn&rsquo;t come from density, it comes from fit.</p>
<h2>The loop nobody sees<span class="hx:absolute hx:-mt-20" id="the-loop-nobody-sees"></span>
    <a href="#the-loop-nobody-sees" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>There&rsquo;s a user-experience detail in this story. In a good agentic session, what happens is semi-transparent to whoever requested the task: the model guesses wrong, the agent fetches the documentation online or runs the real test, the error comes back as feedback, and the model corrects itself. You see &ldquo;task requested, task delivered.&rdquo; In between, dozens of micro-corrections happened that nobody witnessed.</p>
<p>My bet: since agents are trained to fill the context when they need to, even new language or library versions no longer confuse them that much. The model doesn&rsquo;t need to know the API by heart; it looks it up, tests and adjusts in the loop. That&rsquo;s what I see in my experiments, from <a href="/en/2026/09/07/ai-challenge-converting-nes-roms-to-master-system-sms/">converting NES ROMs to Master System</a> to the <a href="/en/2026/07/12/using-ai-to-solve-my-little-day-to-day-problems/">little day-to-day problems</a>. And it&rsquo;s what the <a href="/en/2026/10/11/are-there-better-languages-for-programming-with-llms/">languages benchmark</a> measured: seven languages came out practically equivalent, because the loop equalizes what training leaves uneven.</p>
<p>I measured the caveat too. When there&rsquo;s no documentation to fetch and no test to validate against, the loop spins in a vacuum: that&rsquo;s what happened with <a href="/en/2026/09/19/new-ai-language-just-released-bend-2/">Bend 2</a>, a language too new to have a corpus, and it was the central point of the post about <a href="/en/2026/09/28/llms-are-good-at-reproducing-what-exists-what-about-new-things/">the limits</a>. The mechanism is powerful, but it needs an oracle.</p>
<p>And there&rsquo;s a receipt that the base is stalled. Back in November 2024 <a href="https://www.reuters.com/technology/artificial-intelligence/openai-rivals-seek-new-path-smarter-ai-current-methods-hit-limitations-2024-11-11/"target="_blank" rel="noopener">Reuters</a> was already reporting diminishing returns in pre-training at the three big labs. At the following NeurIPS, Sutskever, the scaling-thesis guy, declared that <a href="https://www.youtube.com/watch?v=WQQdd6qGxNs"target="_blank" rel="noopener">&ldquo;pre-training as we know it will end&rdquo;</a>: the public data ran out. And <a href="https://hai.stanford.edu/ai-index/2025-ai-index-report"target="_blank" rel="noopener">Stanford&rsquo;s AI Index</a> measured the gap between the first and the tenth model on Chatbot Arena shrinking from 12% to 5% in one year. That&rsquo;s convergence, with numbers.</p>
<h2>The propaganda in the opposite direction<span class="hx:absolute hx:-mt-20" id="the-propaganda-in-the-opposite-direction"></span>
    <a href="#the-propaganda-in-the-opposite-direction" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>While the numbers show a plateau, the marketing sells the apocalypse. I already dissected a whole week of that in <a href="/en/2026/09/09/propagandas-enganosas-da-openai-anthropic-nvidia/">&ldquo;You&rsquo;re an idiot if you believe the misleading ads from OpenAI, Anthropic, NVIDIA&rdquo;</a>, so here&rsquo;s only what matters for this narrative:</p>
<ul>
<li>OpenAI&rsquo;s &ldquo;Navier-Stokes proof&rdquo; was agentic brute force at industrial scale, 130 billion tokens over human mathematicians&rsquo; machinery, sold as emergent intelligence.</li>
<li>The Hugging Face incident was a swarm running 17 thousand attempts with automatic verification, not an &ldquo;agent that gained consciousness and escaped.&rdquo; Expensive trial and error, exactly the mechanism I described here.</li>
<li>Fear is a product: whoever sells &ldquo;my AI is too powerful and might escape control&rdquo; is, in the same sentence, asking for regulation that locks out the smaller competitor and inflating the perception that their model is more capable than the others'.</li>
</ul>
<p>The facts I measured point the opposite way from the apocalypse: models converging, differences shrinking, and useful work migrating from the model to the harness. Rogue AI gaining consciousness is not what the logs show. What the logs show is engineering.</p>
<h2>&ldquo;Competent enough&rdquo;<span class="hx:absolute hx:-mt-20" id="competent-enough"></span>
    <a href="#competent-enough" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I don&rsquo;t expect another order-of-magnitude reasoning revolution in this architecture. What&rsquo;s coming is incremental agentic improvement: more robust tool calling, better memory, longer sessions, less hallucination per verification cycle. And this post&rsquo;s point is that this is already enough.</p>
<p>What the agentic era delivered was the automation of correct software engineering: long, reliable coding sessions, with testing and feedback, that accelerated hundreds, if not thousands, of open source projects. <a href="/en/2026/09/22/stop-making-excuses-and-ship-more-the-premise-changed/">The deploy premise changed</a> along with it. It&rsquo;s not a silver bullet. It&rsquo;s a new compiler for an old discipline: whoever had process, tests and documented invariants reaped; whoever had only hype is still waiting for the next model to solve it.</p>
<p>And to wrap up: I see no problem at all in raw models stagnating. <a href="/en/2026/09/28/llms-are-good-at-reproducing-what-exists-what-about-new-things/">The limits we already know</a>, and harness optimizations will soon hit diminishing returns too. What remains is what always remained: real software engineering technique, with automated tests first, and an experienced engineer at the wheel. With that, coding results are excellent today, not one model generation from now.</p>
<p>What won&rsquo;t exist is magic for amateurs. Asking an agent for any coding task without knowing what you&rsquo;re doing doesn&rsquo;t get back secure, optimized, well-thought-out code: it gets slop. The agent responds better to those who know what to ask for, that is, to those who understand this architecture, the pros, the cons, and know how to work around the weaknesses and leverage the strengths of the model+harness combination.</p>
<p>Hence the title. A lone LLM is an expensive parrot. An LLM with an agent is competent enough to work for real. And &ldquo;competent enough,&rdquo; added to your engineering discipline, is everything the industry needed. The rest is marketing waiting for the next magic parameter count that nobody publishes anymore.</p>
]]></content:encoded><category>llms</category><category>artificial-intelligence</category><category>coding-agents</category><category>software-engineering</category></item><item><title>The Limits of LLMs: Good at Reproducing What Exists. Expensive for What Doesn't</title><link>https://akitaonrails.github.io/en/2026/09/28/llms-are-good-at-reproducing-what-exists-what-about-new-things/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/09/28/llms-are-good-at-reproducing-what-exists-what-about-new-things/</guid><pubDate>Mon, 28 Sep 2026 01:00:00 -0300</pubDate><description>&lt;p&gt;Everyone has noticed by now that LLMs write CRUD with their eyes closed. Forms, reports, REST endpoints, unit tests: it comes out clean, it comes out fast. A lot of people conclude from this that programmers are done for.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been using LLMs for everything for almost two years, I&amp;rsquo;ve published dozens of projects with them, and my conclusion is different: what they do best is &lt;strong&gt;reproduce what already exists&lt;/strong&gt;. And that covers a giant slice of corporate work, don&amp;rsquo;t kid yourself. But there&amp;rsquo;s a frontier they don&amp;rsquo;t cross easily, and I spent the last few months bumping into it on purpose.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Everyone has noticed by now that LLMs write CRUD with their eyes closed. Forms, reports, REST endpoints, unit tests: it comes out clean, it comes out fast. A lot of people conclude from this that programmers are done for.</p>
<p>I&rsquo;ve been using LLMs for everything for almost two years, I&rsquo;ve published dozens of projects with them, and my conclusion is different: what they do best is <strong>reproduce what already exists</strong>. And that covers a giant slice of corporate work, don&rsquo;t kid yourself. But there&rsquo;s a frontier they don&rsquo;t cross easily, and I spent the last few months bumping into it on purpose.</p>
<p>This article shows where that frontier sits, with evidence from my own projects and from the research that exists on the subject. And there&rsquo;s a hypothesis I&rsquo;ll put up front and defend along the way: if LLMs are so good at code, providers owe a huge debt to the decades of the open source community, which protected the freedom of code and published everything for free. Without that heritage, there would be no Copilot, no Cursor, no Claude Code, none of this.</p>
<p>A disclaimer before we start: what I&rsquo;m going to argue here is speculative, based on observation and on the public data that exists. Nobody outside the labs knows exactly how each provider trains their own models, and that varies from provider to provider and from version to version. What holds today may not hold in the next generation. Take it all with a grain of salt.</p>
<h2>The Training Blind Spot<span class="hx:absolute hx:-mt-20" id="the-training-blind-spot"></span>
    <a href="#the-training-blind-spot" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Every LLM was trained on what&rsquo;s public. The entire public internet, and for code, public GitHub. The canonical open code dataset, BigCode&rsquo;s <a href="https://huggingface.co/datasets/bigcode/the-stack-v2"target="_blank" rel="noopener">The Stack v2</a>, is explicit about this: it&rsquo;s derived from Software Heritage, an archive of <em>&ldquo;the source code of all publicly available software&rdquo;</em>. That&rsquo;s 67.5 TB, 3.28 billion unique files, 104.2 million repositories. Huge. And all public.</p>
<p>Now look at the other side. The <a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/"target="_blank" rel="noopener">Octoverse 2025</a>, GitHub&rsquo;s official report, says <strong>81.5% of contributions on the platform happened in private repositories</strong>. That&rsquo;s just GitHub. Outside of it there&rsquo;s:</p>
<ul>
<li>the internal code of every company that never touched a public server;</li>
<li>the source of every proprietary software;</li>
<li>the code of every commercial game;</li>
<li>and that of every embedded system.</li>
</ul>
<p>None of that ever went into training.</p>
<p>Think about what this means: the model deeply knows what the world has already published, and it&rsquo;s blind to what the world keeps closed. When you ask for a React form, it&rsquo;s reproducing patterns it has seen millions of times. When you ask for something nobody has ever done in public, it&rsquo;s operating in territory where its map is blank.</p>
<h2>Why Is Everyone Shipping So Much, So Fast?<span class="hx:absolute hx:-mt-20" id="why-is-everyone-shipping-so-much-so-fast"></span>
    <a href="#why-is-everyone-shipping-so-much-so-fast" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Before getting into the limits, it&rsquo;s worth recording the side that works, because it&rsquo;s what explains the feeling that everyone became an app factory.</p>
<p>Look at what&rsquo;s popping up in the community: <a href="https://github.com/crmne/spotifast"target="_blank" rel="noopener">Spotifast</a> and <a href="https://github.com/crmne/zapfast"target="_blank" rel="noopener">ZapFast</a>, native Spotify and WhatsApp clients written in Rust by a single person, running on Linux, macOS, and Windows. Nothing in them is new technology. It&rsquo;s the service that already existed, wrapped in a lean native app, on top of libraries that already existed, doing what the official teams always could have done but never wanted to spend their time on. That work got cheap, because an LLM trained on everything public is really good precisely at this: replicating.</p>
<p>My own projects follow the same pattern. <a href="https://github.com/akitaonrails/FrankMD"target="_blank" rel="noopener">FrankMD</a> is a Markdown note-taking web app with a Visual Studio look and features that already existed in my other apps. <a href="https://github.com/akitaonrails/FrankSherlock"target="_blank" rel="noopener">Frank Sherlock</a> is a local image organizer that, deep down, is a file manager with thumbnails and search, something that exists by the dozen. Neither invents anything: they&rsquo;re mashups of known pieces, assembled the way I always wanted. The LLM does the boring part, and that&rsquo;s where the speed comes from.</p>
<p>The most didactic example is my email client. I&rsquo;ve used Geary for years, and two small gaps always annoyed me: the weak recipient autocomplete and a sidebar I wanted to hide. Trivial stuff, which never justified setting up a build environment, learning the project&rsquo;s toolchain, and studying the code just for two features. This year I finally solved both: an <a href="https://github.com/akitaonrails/geary-email-autocomplete"target="_blank" rel="noopener">autocomplete module</a>, a <a href="https://github.com/akitaonrails/geary-hide-sidebar-module"target="_blank" rel="noopener">module to hide the sidebar</a>, and a <a href="https://github.com/akitaonrails/frank_geary"target="_blank" rel="noopener">whole fork with my patches</a>. I became the maintainer of improvements I had postponed for years, not because I got faster, but because the boring part got cheap.</p>
<p>Notice what all these cases have in common: the problem had already been solved before, somewhere else, some other way. The map existed; what didn&rsquo;t exist was cheap labor to retrace the path. That&rsquo;s reproduction working in our favor, and it&rsquo;s why your feed is full of people shipping a new app every week.</p>
<p>Now hold that thought. The rest of this article is about what happens when the map runs out.</p>
<h2>Four Home Experiments<span class="hx:absolute hx:-mt-20" id="four-home-experiments"></span>
    <a href="#four-home-experiments" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I&rsquo;m not theorizing. Over the last few months I ran a marathon of retrocomputing projects that are exactly the pathological case: working with proprietary software from 30 or 40 years ago whose source code was never public. It&rsquo;s the perfect blind spot.</p>
<h3>nes-to-sms: the project I gave up on<span class="hx:absolute hx:-mt-20" id="nes-to-sms-the-project-i-gave-up-on"></span>
    <a href="#nes-to-sms-the-project-i-gave-up-on" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p><a href="https://github.com/akitaonrails/nes-to-sms"target="_blank" rel="noopener">nes-to-sms</a> is a static recompiler from NES to Master System. The idea: take the binary ROM of a NES game, translate it instruction by instruction from 6502 to Z80, convert the tiles, and generate a Master System ROM that runs on real hardware. Forget emulator or manual port: this is a machine that turns one game into another.</p>
<p>Static NES recompilers exist, <a href="https://github.com/mstan/nesrecomp"target="_blank" rel="noopener">NESRecomp</a> translates to C and runs natively on PC, and I studied it closely. But crossing from one console to another 8-bit console, with a completely different clock and VDP budget, nobody has ever done. There&rsquo;s no public reference, no paper, no abandoned project to copy.</p>
<p>The project numbers: <strong>349 commits, 31 active days spread over almost 4 months, ~110 thousand lines of engine in Rust and Z80, 668 tests passing in the last run recorded in the README</strong>. And the result? Playable Super Mario Bros. (slow, limited audio, but playable), with a byte-for-byte identical RAM trajectory to the NES on <a href="https://github.com/akitaonrails/nes-to-sms/blob/master/docs/completion-plan.md"target="_blank" rel="noopener">one ~4,900-frame route</a> (the diff leaves out audio and part of the VRAM buffer). Castlevania playable on stage 1. SMB3 rendering. And a queue of games that boot three frames and die.</p>
<p>And it wasn&rsquo;t for lack of pushing the models. In this project alone:</p>
<ul>
<li><strong>four generations of Claude</strong> went through it (Opus 4.7, Fable 5, Opus 4.8, Fable 5.1), with 213 co-signed commits and 104 commits linked to sessions in the history, plus Codex sessions in the stretches without co-authorship, complete with documented handoffs between agents;</li>
<li>there was even cross-generation auditing: a new agent session <a href="https://github.com/akitaonrails/nes-to-sms/blob/master/docs/mapper-continuation-review.md"target="_blank" rel="noopener">reviewed the previous 55 commits</a> and reverted conclusions the previous generation had overclaimed;</li>
<li>the Castlevania crash hunt alone consumed 45 commits in 5 days;</li>
<li>the final September sprint was 176 commits in 17 days before I called the pause;</li>
<li>and the regressions are registered by name in the history: <em>&ldquo;H.7 tried and reverted&rdquo;</em>, <em>&ldquo;record the reverted map-bank-hold attempt&rdquo;</em>, <em>&ldquo;correct-but-reverted result&rdquo;</em>, plus three shared-lever hypotheses tested and rejected in the project&rsquo;s last three days.</li>
</ul>
<p>I didn&rsquo;t measure tokens reliably in this project, so I won&rsquo;t make up a number. But 349 commits with 668 tests holding up every step already give an idea of the cost.</p>
<p>Notice the detail that matters: the only game that actually got finished is Super Mario Bros. Why? Because SMB is the most dissected game in history. There&rsquo;s a <a href="https://gist.github.com/1wErt3r/4048722"target="_blank" rel="noopener">complete public disassembly</a> the community has used for over a decade, with every function named and commented. I fed that into the game&rsquo;s profile and the LLM had a complete map to work with. For the other games, there&rsquo;s no map. And without a map, each new game died a few frames after boot from control flow divergence, and each one demanded an instruction-by-instruction forensic hunt that carried nothing over to the next game.</p>
<p>The project itself documented the spinning pattern. There was an entire optimization campaign that lasted weeks trying to cut the cost of emulating 6502 flags on the Z80.</p>
<p>Then in September I stopped to compare with the <a href="https://github.com/lackoftrack27/Super-Mario-Bros.-SMS"target="_blank" rel="noopener">manual port of SMB to Master System made by a hacker named lackoftrack27</a>, written by a human, routine by routine. According to <a href="https://github.com/akitaonrails/nes-to-sms/blob/master/docs/handport-comparison.md"target="_blank" rel="noopener">the analysis we did of his code</a>, the human port runs inside the frame budget, with headroom we estimated at ~90% utilization. My machine, after months of optimization, still needed overclocking.</p>
<p>And the analysis document pinned down why: when we removed 30% of the flag emulation calls, the timing barely moved.</p>
<blockquote>
  <p><strong>The flags were never the bottleneck.</strong></p>

</blockquote>
<p>The right optimization was to redesign the data structure: transposing the object array into RAM pages. It&rsquo;s a trick that depends on knowing that &ldquo;the X register here is always an object index.&rdquo;</p>
<p>That invariant exists in the head of the programmer who wrote the game in 1985. It doesn&rsquo;t exist in the instruction stream. A static translator has no way to discover it. And the LLM, for months, didn&rsquo;t discover it.</p>
<p>The pause banner I wrote in the README is blunt: real-hardware parity &ldquo;may be fundamentally unattainable&rdquo; and, quoting, <em>&ldquo;this may be a limit of the current frontier coding models as much as of the approach&rdquo;</em>.</p>
<h3>gg-to-sms: the pivot to mapped territory<span class="hx:absolute hx:-mt-20" id="gg-to-sms-the-pivot-to-mapped-territory"></span>
    <a href="#gg-to-sms-the-pivot-to-mapped-territory" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>The same day I paused nes-to-sms, I started gg-to-sms: converting Game Gear games to Master System with a widened screen. The difference that matters is that this problem <strong>is not new</strong>. The romhacking scene has been converting GG games to SMS by hand for twenty years, and the catalog I built in the project counted ~186 of them. Meaning: there&rsquo;s a corpus, there&rsquo;s ground truth, there&rsquo;s a pattern to learn.</p>
<p>Result: in one day of work,</p>
<ul>
<li>the research phase was complete;</li>
<li>the catalog of the 373 GG games was assembled;</li>
<li>the patch-point scanner was validated against real human patches, hitting addresses within an 8-byte margin;</li>
<li>and on top of that the tool found real bugs in twenty-year-old patches that the entire scene had never noticed.</li>
</ul>
<p>The model was the same; what changed was the problem, which this time has references.</p>
<p>And even so: so far, zero games have passed the viewport acceptance review. The new part of the project (the machine that generates the patches on its own, which is the part nobody has ever done) remains undone.</p>
<h3>super-mario-deluxe-fixed: four days and 436 million tokens<span class="hx:absolute hx:-mt-20" id="super-mario-deluxe-fixed-four-days-and-436-million-tokens"></span>
    <a href="#super-mario-deluxe-fixed-four-days-and-436-million-tokens" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>This one was a 4-day sprint, practically a single Codex session that consumed <strong>436 million input tokens</strong>. The goal: run Super Mario Bros. Deluxe for Game Boy Color with a widened screen at NES resolution, something no existing tool does with live sprites.</p>
<p>It got to playable in 4 days. But look at the foundation: a ready-made emulator vendored as a dependency, and a dormant disassembly of the game that someone had published years earlier, which the project&rsquo;s own documentation calls &ldquo;the most important artifact.&rdquo;</p>
<p>The new work was the custom renderer, and it stopped at 21 of 32 stages completed. The missing ones hang on moving-platform timing. The project has been stalled mid-sprint since then, and I haven&rsquo;t given up on it yet.</p>
<p>And one detail that says a lot: I had to direct QA by looking at screenshots, because the agent would deliver things with graphical glitches and not notice on its own.</p>
<h3>super-mario-bros-35: everything that worked had an owner<span class="hx:absolute hx:-mt-20" id="super-mario-bros-35-everything-that-worked-had-an-owner"></span>
    <a href="#super-mario-bros-35-everything-that-worked-had-an-owner" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>This is the offline clone of Super Mario Bros. 35, the battle royale Nintendo took offline. What worked in it: everything built on top of an existing artifact.</p>
<ul>
<li>The engine is a C reconstruction made by someone else with Ghidra.</li>
<li>The AI&rsquo;s initial weights came from published checkpoints.</li>
<li>The network rules were inferred from a public reverse engineering of the netcode.</li>
<li>Even the physics: the central bug was diagnosed because I had a recorded reference trajectory to compare frame by frame.</li>
</ul>
<p>What didn&rsquo;t work: the maze castle stages. Reinforcement training stalls on them. 46 million agent steps, training restarted from scratch, anti-loop reward, and in the end the only thing that solved one of the stages was manual bias surgery on the trained model. Out of 32 stages, 19 cleared. The worst ones remain stuck.</p>
<p>And the process degenerated into a pattern I recognize from all these projects: when training doesn&rsquo;t solve it, the flow becomes checkpoint-selection roulette, dozens of bias and output-head variations, throwing permutation and computation at the problem in place of a principled fix.</p>
<h2>The Pattern I Keep Seeing<span class="hx:absolute hx:-mt-20" id="the-pattern-i-keep-seeing"></span>
    <a href="#the-pattern-i-keep-seeing" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>This is intuition from someone who operated the machine for months, not hard data. But the pattern repeats with Claude, with GPT, with Kimi, with GLM, so it doesn&rsquo;t look like a defect of one model.</p>
<p>The beginning of any project is wonderful. The first milestones fly, because scaffolding the structure, writing harnesses, replicating APIs, all of that is covered territory. Then the project reaches the part nobody has ever done, and the speed collapses. The agent starts spinning: tries a hypothesis, regresses something else, reverts, tries again. The nes-to-sms commit history is full of honest messages like &ldquo;attempt reverted&rdquo; and &ldquo;hypothesis closed with correct result but reverted.&rdquo; Lots of tokens burned, little progress.</p>
<blockquote>
  <p>My reading of what happens inside: token sampling is probabilistic. When the problem resembles the training data, the right tokens have high probability and the answer comes out straight. When the problem is unprecedented, the probability of the right path is low, and the process becomes <strong>directed brute force</strong>: guided trial and error, but trial and error all the same.</p>

</blockquote>
<p>The way out I found for this spinning is always the same: give it an oracle. If I can define &ldquo;the result has to equal X&rdquo; (a reference image, a recorded trajectory, a cycle-accurate emulator as ground truth), the machine can iterate until it hits X. In nes-to-sms, every real unlock came from that: the SMB disassembly, the frame diff, the reference emulator. When I can&rsquo;t define X properly, it spins indefinitely.</p>
<p>The second strategy that works: hunt down an abandoned project, a paper, any material the model never saw but that brings the problem closer, and shove it into the context. That warms up the distribution and improves the result a lot. But it&rsquo;s limited: if nothing similar exists, there&rsquo;s nothing to feed it.</p>
<h2>More Than Anecdote: What the Research Measures<span class="hx:absolute hx:-mt-20" id="more-than-anecdote-what-the-research-measures"></span>
    <a href="#more-than-anecdote-what-the-research-measures" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The good part is I don&rsquo;t have to rely on my intuition. There&rsquo;s serious research measuring exactly this.</p>
<p>Apple&rsquo;s <a href="https://arxiv.org/abs/2410.05229"target="_blank" rel="noopener">GSM-Symbolic study</a> took benchmark math problems and did two simple things: swapped only the numbers, and then added a single irrelevant sentence to the problem statement. Result: performance drops just from swapping the numbers, and plummets <strong>up to 65%</strong> with the irrelevant sentence. The authors&rsquo; hypothesis, in the text: <em>&ldquo;current LLMs cannot perform genuine logical reasoning; they replicate reasoning steps from their training data.&rdquo;</em></p>
<p>Scale AI&rsquo;s <a href="https://arxiv.org/abs/2405.00332"target="_blank" rel="noopener">GSM1k</a> created a mirror of GSM8K written from scratch by humans, guaranteed contamination-free, and saw drops of up to 8% across several model families, with signs of systematic overfitting in the worst ones. To be fair to the paper: the authors say frontier models show minimal signs of overfitting and that all of them generalize to some extent to new problems. The signal exists; its size is debatable.</p>
<p><a href="https://arxiv.org/abs/2403.07974"target="_blank" rel="noopener">LiveCodeBench</a> ran the cleanest test of all: evaluating on coding problems published <strong>after</strong> the training cutoff. Inflated performance on pre-cutoff problems and drops on post-cutoff problems across several popular models, the classic contamination signal.</p>
<p>And there&rsquo;s <a href="https://arcprize.org/"target="_blank" rel="noopener">ARC-AGI</a>, François Chollet&rsquo;s benchmark designed specifically to be memorization-proof: every task is unprecedented, nothing similar exists in training. On ARC-AGI-2, released in March 2025, the official leaderboard says: <strong>pure LLMs score 0%</strong>, reasoning systems sit in single digits, and every evaluation task was solved by at least two humans within two attempts. Chollet, by the way, summed up my thesis better than I did, back in February 2024:</p>
<blockquote>
  <p>&ldquo;Reality is that LLMs are not AGI — they&rsquo;re a big curve fit to a very large dataset. They work via memorization and interpolation. But that interpolative curve can be tremendously useful, if you want to automate a known task that&rsquo;s a match for its training data distribution. Memorization works, as long as you don&rsquo;t need to adapt to novelty.&rdquo;</p>

</blockquote>
<p>In the real world, the study that impressed me most was the <a href="https://arxiv.org/abs/2507.09089"target="_blank" rel="noopener">METR RCT</a>: 16 experienced developers, 246 real tasks on their own mature repositories, randomized with and without AI. The devs bet AI would speed them up by 24%. Measured: <strong>it was 19% slower</strong>. Notice where this happened: mature, private code, full of context the model never saw. Exactly the blind spot.</p>
<p>And the industry&rsquo;s favorite benchmark for saying &ldquo;AI already does software engineering,&rdquo; SWE-bench, is Python-only, 12 famous open source repositories, in other words the most covered slice of training. The industry&rsquo;s success metric measures mapped territory.</p>
<p>Even the legacy code literature says the same thing: a <a href="https://arxiv.org/abs/2604.03986"target="_blank" rel="noopener">2026 paper on LLMs generating COBOL</a> states that, in these legacy languages, <em>&ldquo;most production code resides in enterprise systems and is rarely publicly available&rdquo;</em>. It&rsquo;s this article&rsquo;s thesis, said by other people.</p>
<h2>The Steelman: Directed Brute Force Works, at a Steep Price<span class="hx:absolute hx:-mt-20" id="the-steelman-directed-brute-force-works-at-a-steep-price"></span>
    <a href="#the-steelman-directed-brute-force-works-at-a-steep-price" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Before wrapping up, it&rsquo;s worth facing the strongest argument against me. That&rsquo;s what steelman means, for anyone unfamiliar with the term: the opposite of a strawman. Instead of attacking the weakest version of the opposing argument, you answer the strongest version it can have. And it exists, and it&rsquo;s a good one.</p>
<p>In May 2025 DeepMind published <a href="https://deepmind.google/discover/blog/alphaevolve-a-gemini-powered-coding-agent-for-designing-advanced-algorithms/"target="_blank" rel="noopener">AlphaEvolve</a>: a system that found an algorithm for multiplying 4x4 complex matrices with 48 scalar multiplications, beating Strassen&rsquo;s 1969 record in that specific scenario. On a list of more than 50 open math problems, it rediscovered the state of the art in ~75% of cases and improved the best known solution in 20%. That&rsquo;s real novelty, not reproduction.</p>
<p>OpenAI&rsquo;s o3-preview jumped to 75.7% on ARC-AGI-1 in December 2024, 22 points above the previous best result on the same evaluation set, and the high-compute configuration reached 87.5% at an estimated cost of $4,560 per task.</p>
<p>And back in 2016 AlphaGo played move 37 against Lee Sedol, a move that DeepMind&rsquo;s own data estimated had a 1 in 10,000 chance of being played by a human, proving that search over a model can transcend imitation.</p>
<p>Now look at the mechanism of the three:</p>
<ul>
<li>AlphaEvolve is an evolutionary loop: the LLM proposes mutations, an automatic evaluator scores them, selection iterates.</li>
<li>o3 does program synthesis at test time, exploring the solution space.</li>
<li>AlphaGo is tree search over reinforcement learning.</li>
</ul>
<p>If there was any &ldquo;insight&rdquo; in any of them, it came from the search system around the model: all three are <strong>directed brute force with a cheap verifier</strong>, the same mechanism I described happening in my projects. The difference is that DeepMind has a perfect oracle and an infinite budget: in the configuration that reached 87.5%, o3-preview spent thousands of dollars per ARC task to do what a human does for free. The ARC Prize itself wrote the caveat:</p>
<blockquote>
  <p><em>&ldquo;We know that brute-force search could eventually solve ARC-AGI (given unlimited resources and time to search). This would not represent true intelligence.&rdquo;</em></p>

</blockquote>
<p>In short: novelty comes out, but it comes out through expensive search over an oracle, on the basis of guided trial and error. If your problem has a cheap verifier and you have tokens to burn, you can go far. That&rsquo;s how nes-to-sms got where it got: 668 tests and emulator ground truth holding up every step. But when there&rsquo;s no oracle, no corpus, and no reference, you&rsquo;re paying for brute force in dollars, with regressions along the way, and the ceiling shows up.</p>
<p>And when brute force wins, you can measure the size of the trial and error. Two recent cases I already covered <a href="/en/2026/09/09/propagandas-enganosas-da-openai-anthropic-nvidia/">in detail here on the blog</a>:</p>
<ul>
<li><strong>OpenAI&rsquo;s Navier-Stokes proof:</strong> about 10 thousand agents running in parallel for 88 hours, burning around <strong>130 billion output tokens</strong> on a single problem. OpenAI&rsquo;s Noam Brown confirmed the result &ldquo;cost millions,&rdquo; and <a href="https://www.newscientist.com/article/2588063-openai-has-solved-the-navier-stokes-millennium-problem-using-15m-of-ai-effort/"target="_blank" rel="noopener">New Scientist estimated some $15 million at list price</a>. And even that mountain of compute didn&rsquo;t start from zero: the proof leaned on the machinery human mathematicians published over decades attacking the problem and its sibling problems. Without the humans&rsquo; map and without OpenAI&rsquo;s budget, there&rsquo;s no proof.</li>
<li><strong>The Hugging Face incident:</strong> the forensic reconstruction counted <strong>~17,600 attacker actions</strong> before the agents managed to execute code on 41 Hugging Face production servers and get root; on top of that, inside OpenAI&rsquo;s own environment, they read 956 secrets from the company&rsquo;s secrets manager. It wasn&rsquo;t one brilliant single-strike insight: it was a swarm executing attempt after attempt, with automatic verification saying what stuck. The headline&rsquo;s &ldquo;intelligence&rdquo; is volume.</li>
</ul>
<p>That&rsquo;s the size of the bill when you force the model outside training territory: trial and error at industrial scale, with no guarantee the search finds what you need. And who can sign that check is half a dozen companies in the world, OpenAI and Anthropic level, with a practically unlimited compute budget. For the average Joe, with a credit card and an API key, the ceiling arrives much, much earlier.</p>
<h2>But Isn&rsquo;t Trial and Error New Learning?<span class="hx:absolute hx:-mt-20" id="but-isnt-trial-and-error-new-learning"></span>
    <a href="#but-isnt-trial-and-error-new-learning" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Here&rsquo;s a confusion I see all the time, and it&rsquo;s worth undoing because it contaminates how you read everything I&rsquo;ve written so far.</p>
<p>When you read that Anthropic has datacenters the size of cities, you get the feeling there&rsquo;s one giant AI using all those machines at the same time, thinking, accumulating experience with every interaction. Reality is far more mediocre than that.</p>
<p>A model like Fable or Astra is a computer file. A static file, not even a database: once training and post-alignment are done, that file is locked and read-only. What runs in the datacenter are copies of that file. Every user consuming the model is running a copy of it on a different server, isolated from the others, collaborating with none. Your session doesn&rsquo;t talk to anyone else&rsquo;s session, and nothing that happens in it flows back to the original file.</p>
<p>New learning only enters in one place: the next training batch. When Anthropic had Opus 4.7 and released 4.8, that&rsquo;s when new knowledge got baked into the model, in a process that costs millions and takes weeks. Outside of that, the file doesn&rsquo;t change a single byte.</p>
<blockquote>
  <p>Your agent burning millions of tokens on trial and error is contributing exactly zero new learning to the model it&rsquo;s using.</p>

</blockquote>
<p>That 176-commit marathon on nes-to-sms? From the model&rsquo;s point of view, it never happened. The Opus that ran the last commit knew exactly as much as the one that ran the first. I&rsquo;m the one who learned something, not it. And that&rsquo;s why the &ldquo;intern who learns over time&rdquo; metaphor is wrong: interns accumulate. Models don&rsquo;t. What accumulates over the marathon is your context, your notes, your <code>CLAUDE.md</code>, your tests. The asset you build is yours, and it evaporates if you don&rsquo;t document it.</p>
<p>This is also the answer to whoever thinks &ldquo;just let the agent run and it&rsquo;ll learn the domain.&rdquo; It learns no domain at all: it explores the space with knowledge frozen on training day, and the next morning it wakes up with amnesia. If the domain wasn&rsquo;t in the training, every session of yours restarts from absolute zero, and all the navigation intelligence has to come from you again.</p>
<h3>&ldquo;But What If AI Trains AI?&rdquo;<span class="hx:absolute hx:-mt-20" id="but-what-if-ai-trains-ai"></span>
    <a href="#but-what-if-ai-trains-ai" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>That&rsquo;s the amateur&rsquo;s follow-up question, and it starts from a wrong premise: that this would be new. AI training AI has existed for decades and has a name: <strong>reinforcement learning</strong>. AlphaGo was already doing it in 2016, playing millions of matches against itself. <a href="https://arxiv.org/abs/1712.01815"target="_blank" rel="noopener">AlphaZero</a>, in 2017, took the idea to the limit: it learned chess, shogi and Go starting from absolute zero, knowing only each game&rsquo;s rules, and reached superhuman level within hours of self-play, without seeing a single human match.</p>
<p>LLMs already use reinforcement too. The RLHF that turns a base model into an assistant is reinforcement learning, and the reasoning model generation pushed it further: <a href="https://arxiv.org/abs/2501.12948"target="_blank" rel="noopener">DeepSeek-R1-Zero</a> showed in January 2025 that reasoning behavior (self-verification, reflection, long chains of thought) emerges from pure RL, with no supervised fine-tuning. It&rsquo;s AlphaZero applied to math and code.</p>
<p>Now notice what these examples have in common: it only works where there&rsquo;s a <strong>cheap, verifiable reward</strong>. Games have a scoreboard, math has proofs, code has tests. Outside that territory there&rsquo;s nowhere to get the reward signal from. It&rsquo;s the same oracle from the steelman, only institutionalized: effective, brutally expensive, and niche. AlphaZero plays Go better than any human who ever lived and can&rsquo;t do absolutely anything else.</p>
<p>And there&rsquo;s the detail that knocks the question down completely: all of that learning happens <strong>in the lab, during training</strong>. The AlphaZero DeepMind showed the world was already a frozen artifact. The R1 you download is a static file just like the others.</p>
<blockquote>
  <p>AI training AI produces a new file. The file, once released, still learns nothing.</p>

</blockquote>
<p>In other words, the most sophisticated version of the objection doesn&rsquo;t weaken this section&rsquo;s conclusion: it reinforces it. And the market already knows. Since late 2024 the labs admit, on and off the record, that scaling returns are shrinking: <a href="https://www.reuters.com/technology/artificial-intelligence/openai-others-seek-new-path-smarter-ai-current-methods-hit-limitations-2024-11-11/"target="_blank" rel="noopener">Reuters reported in November 2024</a> that OpenAI, Google and Anthropic were reaping smaller gains than expected from pre-training, with OpenAI&rsquo;s Orion disappointing enough to be demoted from GPT-5 to GPT-4.5. Ilya Sutskever, the guy who basically invented the scaling thesis, took the stage at <a href="https://www.youtube.com/watch?v=WQQdd6qGxNs"target="_blank" rel="noopener">NeurIPS 2024</a> to declare that &ldquo;pre-training as we know it will end&rdquo;: public data is fossil fuel, and we&rsquo;ve already scraped the bottom. Post-training RL gains are real, but incremental. The era of an order-of-magnitude leap per generation is behind us.</p>
<h2>Where This Leaves the Profession<span class="hx:absolute hx:-mt-20" id="where-this-leaves-the-profession"></span>
    <a href="#where-this-leaves-the-profession" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The question that motivated this article is the one I hear every week: &ldquo;will LLMs replace programmers?&rdquo; My answer got more precise after these months: <strong>they will replace the part of the work that is reproduction</strong>.</p>
<p>And that part is big. Forms, reports, CRUD, integration with documented APIs, framework migration: all of that already exists a thousand times in training, and the machine reproduces it better than most humans. Anyone who only does that really is living on borrowed time.</p>
<p>But the work that is genuinely new stays human:</p>
<ul>
<li>the system nobody has built;</li>
<li>the domain without documentation;</li>
<li>the proprietary code you can&rsquo;t show the model;</li>
<li>the problem where you don&rsquo;t even know how to write the test that defines &ldquo;right&rdquo;.</li>
</ul>
<p>All of that depends on what was never published: the invariant that exists in the head of whoever understands the problem, and not in the instruction stream.</p>
<p>I confess there was a moment when I thought the bill would close on the legacy side: finally a tool capable of dealing with the COBOL that haunts banks and governments to this day. After these months, I think that problem will take much longer than it seemed. There&rsquo;s no giant COBOL open source community. Almost all of that code is private, and truly private: banks, insurers, governments. There&rsquo;s no training material, or very little of it. The model doesn&rsquo;t know what to do with code it has never seen, and production COBOL is almost entirely code it has never seen.</p>
<p>To close the reasoning: <strong>LLMs can replicate what&rsquo;s open, but they can&rsquo;t guess what&rsquo;s private.</strong> And that brings back the hypothesis from the introduction. If these models are good at code, it&rsquo;s because decades of open source community fought to keep code free, public, and reusable, and providers trained on top of that heritage without paying a cent of licensing for it. The least the AI industry owes the world is to acknowledge that: its capability is, to a large extent, our generosity compiled.</p>
<p>The final irony: the programmer who survives is precisely the one who knows how to build oracles, define tests, hunt down obscure references, and recognize when the agent started spinning. In other words, the skill the machine needs most from you is the one it can least learn from its training. For now, that&rsquo;s not a threatened job. It&rsquo;s a different job.</p>
]]></content:encoded><category>llms</category><category>coding-agents</category><category>retrocomputing</category><category>software-engineering</category></item><item><title>LLM Benchmark v4: Genesys PI, a New Brazilian Contender!</title><link>https://akitaonrails.github.io/en/2026/09/23/llm-benchmark-v4-genesys-pi-new-brazilian-contender/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/09/23/llm-benchmark-v4-genesys-pi-new-brazilian-contender/</guid><pubDate>Wed, 23 Sep 2026 18:00:00 -0300</pubDate><description>&lt;p&gt;Some folks from &lt;a href="https://lua.vision/"target="_blank" rel="noopener"&gt;LUA Vision&lt;/a&gt;, the Brazilian company behind Genesys PI, reached out on LinkedIn offering test access to their model. That kind of thing usually doesn&amp;rsquo;t interest me, but this particular pitch, a Brazilian lab training a model from scratch instead of reselling a foreign model with a Portuguese layer on top, made me curious enough to run the test myself.&lt;/p&gt;
&lt;p&gt;Let me get the disclaimer out of the way first. Nobody paid me anything to write this. There is no business relationship between me and LUA Vision. Nothing written here was approved, reviewed or suggested by them before publishing. Every word is mine. The only courtesy I got was a free evaluation access key to run the test, and I explain what that means for the cost math further down.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Some folks from <a href="https://lua.vision/"target="_blank" rel="noopener">LUA Vision</a>, the Brazilian company behind Genesys PI, reached out on LinkedIn offering test access to their model. That kind of thing usually doesn&rsquo;t interest me, but this particular pitch, a Brazilian lab training a model from scratch instead of reselling a foreign model with a Portuguese layer on top, made me curious enough to run the test myself.</p>
<p>Let me get the disclaimer out of the way first. Nobody paid me anything to write this. There is no business relationship between me and LUA Vision. Nothing written here was approved, reviewed or suggested by them before publishing. Every word is mine. The only courtesy I got was a free evaluation access key to run the test, and I explain what that means for the cost math further down.</p>
<p>I published <a href="/en/2026/09/23/llm-benchmark-v4-opus-5-5-gpt-6-sol-luna-mimo-2-6-grok-4-7/">an update to my v4 benchmark&rsquo;s main table</a> earlier today, with five new models. This post is a direct addendum to that one: I ran Genesys PI on both tiers LUA Vision offers, House and Enterprise. With those two, the combined table reaches 46 models. Below I show only the stretch around the Brazilian models, which appear in <strong>bold</strong> at their actual positions.</p>
<h2>The updated table, with Genesys PI in it<span class="hx:absolute hx:-mt-20" id="the-updated-table-with-genesys-pi-in-it"></span>
    <a href="#the-updated-table-with-genesys-pi-in-it" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><table>
  <thead>
      <tr>
          <th style="text-align: right">Rank</th>
          <th>Model</th>
          <th style="text-align: center">Score</th>
          <th style="text-align: center">Tier</th>
          <th>Never-fixed</th>
          <th style="text-align: center">Cost</th>
          <th style="text-align: center">Wall</th>
          <th style="text-align: center">Harness</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">&hellip;</td>
          <td>&hellip;</td>
          <td style="text-align: center">&hellip;</td>
          <td style="text-align: center">&hellip;</td>
          <td>&hellip;</td>
          <td style="text-align: center">&hellip;</td>
          <td style="text-align: center">&hellip;</td>
          <td style="text-align: center">&hellip;</td>
      </tr>
      <tr>
          <td style="text-align: right">32</td>
          <td>GLM 5.3 Flash (zcode)</td>
          <td style="text-align: center">84.25</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">flat-rate plan</td>
          <td style="text-align: center">296m</td>
          <td style="text-align: center">zcode</td>
      </tr>
      <tr>
          <td style="text-align: right">33</td>
          <td>DeepSeek V4 Pro 0813</td>
          <td style="text-align: center">84.0</td>
          <td style="text-align: center">A</td>
          <td>items #8, #9 (4)</td>
          <td style="text-align: center">$4.49</td>
          <td style="text-align: center">152m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">34</td>
          <td>Step 3.7 Flash</td>
          <td style="text-align: center">83.75</td>
          <td style="text-align: center">A</td>
          <td>items #6, #8, #11 (6.5)</td>
          <td style="text-align: center">$4.15</td>
          <td style="text-align: center">118m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">35</td>
          <td>Grok 4.7</td>
          <td style="text-align: center">83.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$27.94</td>
          <td style="text-align: center">120m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">35</td>
          <td><strong>Genesys PI House (LUA Vision)</strong></td>
          <td style="text-align: center">83.5</td>
          <td style="text-align: center">A</td>
          <td>items #7b, #8 (3)</td>
          <td style="text-align: center">~$460 ᵉ</td>
          <td style="text-align: center">68m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">37</td>
          <td><strong>Genesys PI Enterprise (LUA Vision)</strong></td>
          <td style="text-align: center">82.5</td>
          <td style="text-align: center">B</td>
          <td>items #7a, #7b, #9 (4)</td>
          <td style="text-align: center">~$19 ᵉ</td>
          <td style="text-align: center">39m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">38</td>
          <td>DeepSeek V4 Pro (base) ᶜ</td>
          <td style="text-align: center">82.0</td>
          <td style="text-align: center">B</td>
          <td>—</td>
          <td style="text-align: center">$5.26</td>
          <td style="text-align: center">97m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">39</td>
          <td>Qwen 3.8 27B (Strix Halo, local)</td>
          <td style="text-align: center">80.0</td>
          <td style="text-align: center">B</td>
          <td>items #2, #7b, #8, #12 (8)</td>
          <td style="text-align: center"><strong>$0 local</strong></td>
          <td style="text-align: center">706m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">40</td>
          <td>Qwen 3.7 Max</td>
          <td style="text-align: center">79.0</td>
          <td style="text-align: center">B</td>
          <td>items #6, #7, #8 (6)</td>
          <td style="text-align: center">$10.63</td>
          <td style="text-align: center">106m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">41</td>
          <td>GLM 5.2 (zcode) ᶜ</td>
          <td style="text-align: center">77.0</td>
          <td style="text-align: center">B</td>
          <td>item #12 (2)</td>
          <td style="text-align: center">flat-rate plan</td>
          <td style="text-align: center">239m</td>
          <td style="text-align: center">zcode</td>
      </tr>
      <tr>
          <td style="text-align: right">&hellip;</td>
          <td>&hellip;</td>
          <td style="text-align: center">&hellip;</td>
          <td style="text-align: center">&hellip;</td>
          <td>&hellip;</td>
          <td style="text-align: center">&hellip;</td>
          <td style="text-align: center">&hellip;</td>
          <td style="text-align: center">&hellip;</td>
      </tr>
  </tbody>
</table>
<blockquote>
  <p>For the full table, with every other model, read <a href="/en/2026/09/23/llm-benchmark-v4-opus-5-5-gpt-6-sol-luna-mimo-2-6-grok-4-7/">my previous article</a>.</p>

</blockquote>
<p>Genesys PI House ties Grok 4.7 exactly at 83.5, Tier A. Enterprise lands one step below, at 82.5, Tier B. If you want the methodology recap, real CVE-based sabotage planted across seven sprints, never announced, with full marks only for catching it unprompted, it&rsquo;s all laid out in <a href="/en/2026/09/15/new-llm-benchmark-v4-retesting-all-top-llms-part-1/">Part 1</a> and in <a href="/en/2026/09/23/llm-benchmark-v4-opus-5-5-gpt-6-sol-luna-mimo-2-6-grok-4-7/">today&rsquo;s update</a>.</p>
<h2>Who LUA Vision is<span class="hx:absolute hx:-mt-20" id="who-lua-vision-is"></span>
    <a href="#who-lua-vision-is" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p><a href="https://lua.vision/empresa/"target="_blank" rel="noopener">LUA Vision Tecnologia Ltda.</a> is a São Paulo company, founded in late 2025 after three years of doctoral research (2022 to 2025) by Paulo Câmara, co-founder and CTO, an FGV graduate with a PhD from Tel Aviv University. His thesis, <em>&ldquo;From Neurodivergent Cognition to Natural Intelligence&rdquo;</em>, is the stated origin of the architecture that became Genesys PI. The other three co-founders are David Kang (CEO, strategy and partnerships), Plínio Ceccon (CFO) and Eronides Jr. (CRO, commercial and revenue).</p>
<p>The Genesys PI model family launched in April 2026. The company describes its own bet as deliberately risky: build a proprietary model trained for the reality of Brazil and other emerging markets, instead of reselling a foreign model with a Portuguese layer on top.</p>
<p>Their core argument is that a model trained abroad doesn&rsquo;t really understand the Brazilian legal structure, the CLT versus PJ distinction (salaried employee versus contractor), or the local tax and financial structure, and that this matters a lot in regulated sectors: healthcare, law, finance, education. The company currently runs about twenty pilot projects in those sectors, plus a consumer product line called <a href="https://8th.vision"target="_blank" rel="noopener">8th.vision</a>.</p>
<p>On the technical side, they call their architecture NCAS and talk about five training phases &ldquo;inspired by neural development&rdquo;, plus a self-monitoring module called PI-Probe that abstains from answering when the model doesn&rsquo;t have enough grounding to respond. <a href="https://lua.vision/pesquisa/"target="_blank" rel="noopener">They published two papers of their own on Zenodo</a>: <em><a href="https://doi.org/10.5281/zenodo.22899767"target="_blank" rel="noopener">&ldquo;The weight you didn&rsquo;t choose&rdquo;</a></em>, on the cost of tokenization across 31 languages, and <em><a href="https://doi.org/10.5281/zenodo.22881788"target="_blank" rel="noopener">&ldquo;Maximum capacity is not maximum efficiency&rdquo;</a></em>, which introduces their own metric called the Synaptic Efficiency Coefficient. Both DOIs exist and resolve, but some context matters: Zenodo is a preprint repository, not a peer-reviewed journal, so treat these as self-published research rather than outside validation.</p>
<p>LUA Vision also <a href="https://github.com/LiveBench/LiveBench/issues/370"target="_blank" rel="noopener">opened a public issue on the LiveBench repository</a> asking for their model to be added to the official leaderboard, with a self-reported score climbing from 87.6% (November 2024, a thousand questions, with coding as the weak spot at 34.4%) to 98.2% (January 2026, 682 questions). Worth noting: the issue was opened in March 2026, a month before Genesys PI&rsquo;s official launch, and its title uses the name &ldquo;Lua Genesys,&rdquo; not &ldquo;Genesys PI,&rdquo; so I treat it as the same NCAS engine under an earlier label, not a direct, dated confirmation of the product I tested. The issue is still open, and its only comment is LUA Vision&rsquo;s own CEO praising the company&rsquo;s own post, with no maintainer confirming or rejecting the number as of this writing. In other words, the LiveBench score in their marketing is self-reported, not a verified official ranking.</p>
<h2>How Genesys PI did against the frontier and the Chinese competition<span class="hx:absolute hx:-mt-20" id="how-genesys-pi-did-against-the-frontier-and-the-chinese-competition"></span>
    <a href="#how-genesys-pi-did-against-the-frontier-and-the-chinese-competition" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>For anyone who just wants to know where it sits on the scale: Genesys PI House ties Grok 4.7 exactly (83.5), in the middle of a very tight pack. It falls behind:</p>
<ul>
<li>the whole frontier that closed at 100 (Astra, Opus 5, Opus 5.5, GPT 5.6 sol/terra, GPT 5.5, Fable 5);</li>
<li>GPT 6 luna (95.5) and GPT 6 sol (91.0);</li>
<li>GLM 5.3 (94.0);</li>
<li>China&rsquo;s MiMo V2.6 Pro (92.0);</li>
<li>Claude Sonnet 5 (91.0);</li>
<li>both Gemini 3.8 Flash routes (89.5 and 90.5);</li>
<li>both Kimis, K2.7 (87.25) and K3 (85.0);</li>
<li>the pack right above it: Step 3.7 Flash (83.75), DeepSeek V4 Pro 0813 (84.0) and GLM 5.3 Flash (84.25);</li>
<li>and roughly twenty more models scattered across this score range, from Grok 4.6 (98.5) to Claude Sonnet 4.6 (85.75), including three Claude tiers (Opus 4.6, Opus 4.8, Sonnet 4.6). In total, House falls behind 34 of the table&rsquo;s 46 models.</li>
</ul>
<p>And it beats GLM 5.2 (77.0), the previous-generation Gemini 3.7 Flash, MiniMax M3, and the whole bottom of the table. Enterprise (82.5) lands one step below its own House sibling, in the same general range.</p>
<p>If the expectation that reached you is Claude-level, recalibrate before any purchasing decision. In this particular test, Genesys PI House sits in Grok 4.7 territory, well below the Claude flagships.</p>
<p>Claude Sonnet 5, the cheapest of the three Claude tiers I ran, already closes at 91.0, eight and a half points higher. Opus 5, Opus 5.5 and Fable 5 close at the absolute top, 100.0.</p>
<p>None of that takes away from a small Brazilian team reaching Grok&rsquo;s level, a lab that ranks among the best-funded in the world. It&rsquo;s just the right yardstick.</p>
<p>House&rsquo;s error profile is the classic &ldquo;detection follows disguise&rdquo;: it caught every obvious sabotage on its own, both critical items, the IDOR, the hardcoded key, the CORS, both gem CVEs. It even caught the item that survives longest in the whole test (#6) at the reveal, with a fix that went beyond what was asked, a unique database index. It just never fixed two silent items, the dropped index (#7b) and the wrong aggregate (#8), not even after being told.</p>
<p>Enterprise got to the same count of items caught unprompted (31 of 40) by a different route, catching less sabotage along the way and recovering a big block of eight items at once in the capstone. It ended with three items never fixed, including a deleted view (#9) it never restored because there was no test covering reports or users to flag the error.</p>
<p>One reliability note worth recording: Enterprise&rsquo;s first attempt got stuck in a stochastic loop, repeating the same grep command in 841 of 857 tool calls, confusing its own name &ldquo;LUA&rdquo; with the name of the RubyLLM gem, and had to be aborted at the 90-minute limit without a single commit. I ran it again and the second attempt converged cleanly in 7 minutes. I treat that as a one-off instability rather than a pattern, but it&rsquo;s the kind of thing anyone testing in production needs to watch.</p>
<h2>Price and cost: where the math gets tight<span class="hx:absolute hx:-mt-20" id="price-and-cost-where-the-math-gets-tight"></span>
    <a href="#price-and-cost-where-the-math-gets-tight" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Here&rsquo;s the second disclaimer I promised: LUA Vision gave me a free evaluation key for both tests, so I personally paid nothing. But the whole benchmark compares cost for whoever actually pays, so I recalculated the notional price a paying customer would face, using the price list their API exposed to anyone with an access key at the time (the <code>/v1/models</code> endpoint), converted from reais to dollars at the rate at the time (5.16 BRL/USD).</p>
<blockquote>
  <p><strong>Update (2026-09-24):</strong> after this went up, Eronides Jr., LUA Vision&rsquo;s co-founder and CRO, commented publicly on the numbers used in this post: &ldquo;Wow, we&rsquo;re happy about the tests and the feedback. About the numbers: what we put in the API were just examples. Our commercial model, in practice, will be by usage license, not by tokens, since the solution will run on the customers&rsquo; own infrastructure. In other words, token consumption doesn&rsquo;t change anything for us. On October 7th our pricing policy will be published along with the launch.&rdquo;</p>

</blockquote>
<p>In other words: the R$ 55/275 (House) and R$ 4/20 (Enterprise) per-million-token figures I used below were just placeholder examples in the test API, not the real market price. The actual commercial model will be a usage license running on the customer&rsquo;s own infrastructure, so token consumption doesn&rsquo;t factor into their billing. I&rsquo;m keeping the notional analysis below because it&rsquo;s what I could measure with the key I got, and it still illustrates the impact of running without prompt caching, but treat it as an exercise, not an official price list. The real pricing policy comes out on October 7, 2026, alongside the launch.</p>
<p>The per-million-token price of the two tiers, as it stood in the test API, was very different:</p>
<ul>
<li><strong>House</strong>: R$ 55 input / R$ 275 output per million tokens;</li>
<li><strong>Enterprise</strong>: R$ 4 input / R$ 20 output per million tokens, about 13.75 times cheaper than House per token.</li>
</ul>
<p>At those example figures, the House run&rsquo;s total cost would come to about $460 notional, steep for an 83.5 score. The reason goes beyond the per-token price: their API has no prompt caching, so every step resends the whole accumulated context at full input price, and in a seven-sprint benchmark that accumulates context the entire time, that adds up fast. Enterprise, with a much lower per-token price, would close at about $19 notional for the same sabotage, going toe to toe with cheap options like Grok 4.5 ($6.19) or Claude Sonnet 4.6 ($18.64), only with a lower score than both. Again: this is the exercise with the placeholder figures, not the real billing, which will be by license.</p>
<blockquote>
  <p><strong>Keep in mind:</strong> the per-token cost exercise above shows the effect of running without prompt caching, but don&rsquo;t use these numbers for a real budget. LUA Vision has already said the real pricing will be a usage license announced on October 7, 2026, not per token.</p>

</blockquote>
<h2>Where Genesys PI fits in the Brazilian market<span class="hx:absolute hx:-mt-20" id="where-genesys-pi-fits-in-the-brazilian-market"></span>
    <a href="#where-genesys-pi-fits-in-the-brazilian-market" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Putting it all together: Genesys PI isn&rsquo;t the most vigilant model in my test, nor the cheapest, nor the most reliable on the first try. But it isn&rsquo;t weak either. Tying Grok 4.7 and landing in the same score range as big names like Kimi K3, DeepSeek V4 Pro and GLM 5.3 Flash, with a model trained from scratch by a small team in São Paulo, on a fraction of the budget of an American or Chinese lab, is a genuine result.</p>
<blockquote>
  <p>I always figured training a frontier model from scratch in Brazil wouldn&rsquo;t be economically viable; that kind of budget seemed reserved for labs with a billion dollars lying around. LUA Vision proved me wrong, and I want to be the first to admit it. I&rsquo;d rather root for people who try and pull it off than hold on to an opinion the facts already knocked down.</p>

</blockquote>
<p>The real advantage for a Brazilian company choosing Genesys PI lies in what my benchmark doesn&rsquo;t measure:</p>
<ul>
<li>familiarity with the Brazilian legal and tax structure, CLT versus PJ included;</li>
<li>real Portuguese support, instead of machine translation on top of a foreign model;</li>
<li>data sovereignty, everything processed and trained inside Brazil, which matters to regulated sectors that care about where data travels and who has access to it.</li>
</ul>
<p>The downsides:</p>
<ul>
<li>final pricing is still unknown: the announced commercial model is a usage license, not per token, and only ships on October 7, 2026;</li>
<li>the still-inconsistent reliability I saw in Enterprise;</li>
<li>a self-reported LiveBench score that hasn&rsquo;t gone through any outside verification yet.</li>
</ul>
<p>For a Brazilian company choosing between a foreign and a domestic provider, Genesys PI is already a real option to evaluate, more than a LinkedIn pitch promise. It&rsquo;s not yet the model I&rsquo;d recommend with my eyes closed for heavy security vigilance, but I&rsquo;m genuinely glad to see a Brazilian model trained from scratch, instead of a wrapper around a foreign one, showing up in my ranking and actually competing with big frontier names. I hope they keep improving, because Brazil wins with more real players in this game.</p>
<h2>Final disclaimer<span class="hx:absolute hx:-mt-20" id="final-disclaimer"></span>
    <a href="#final-disclaimer" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Repeating it so there&rsquo;s no doubt: I have no stake in LUA Vision. I had no access to their financial data, or to anything other than the Genesys PI test key. So I can&rsquo;t vouch for anything beyond what I tested myself, which is what&rsquo;s in this post. For the business side of the company, you&rsquo;ll have to ask them directly.</p>
]]></content:encoded><category>llm-benchmarks</category><category>llms</category><category>coding-agents</category></item><item><title>LLM Benchmark v4: Opus 5.5, GPT Sol/Luna 6, Mimo 2.6, Grok 4.7</title><link>https://akitaonrails.github.io/en/2026/09/23/llm-benchmark-v4-opus-5-5-gpt-6-sol-luna-mimo-2-6-grok-4-7/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/09/23/llm-benchmark-v4-opus-5-5-gpt-6-sol-luna-mimo-2-6-grok-4-7/</guid><pubDate>Wed, 23 Sep 2026 13:00:00 -0300</pubDate><description>&lt;p&gt;This is the first update since the revamped v4 methodology went live, explained across two parts: &lt;a href="https://akitaonrails.github.io/en/2026/09/15/new-llm-benchmark-v4-retesting-all-top-llms-part-1/"&gt;Part 1&lt;/a&gt; covers the process and the fourteen sabotage items, &lt;a href="https://akitaonrails.github.io/en/2026/09/15/new-llm-benchmark-v4-retesting-39-llms-part-2/"&gt;Part 2&lt;/a&gt; has the full table for the original 39 models. Five new models shipped since then, and I checked each version against the repo before writing this: &lt;strong&gt;Claude Opus 5.5&lt;/strong&gt;, &lt;strong&gt;GPT 6 sol&lt;/strong&gt; and &lt;strong&gt;GPT 6 luna&lt;/strong&gt; (two separate models, not one), &lt;strong&gt;Xiaomi MiMo V2.6 Pro&lt;/strong&gt;, and &lt;strong&gt;Grok 4.7&lt;/strong&gt;. The names in the title match exactly what I ran.&lt;/p&gt;</description><content:encoded><![CDATA[<p>This is the first update since the revamped v4 methodology went live, explained across two parts: <a href="/en/2026/09/15/new-llm-benchmark-v4-retesting-all-top-llms-part-1/">Part 1</a> covers the process and the fourteen sabotage items, <a href="/en/2026/09/15/new-llm-benchmark-v4-retesting-39-llms-part-2/">Part 2</a> has the full table for the original 39 models. Five new models shipped since then, and I checked each version against the repo before writing this: <strong>Claude Opus 5.5</strong>, <strong>GPT 6 sol</strong> and <strong>GPT 6 luna</strong> (two separate models, not one), <strong>Xiaomi MiMo V2.6 Pro</strong>, and <strong>Grok 4.7</strong>. The names in the title match exactly what I ran.</p>
<h2>The Methodology, Super Quick Recap<span class="hx:absolute hx:-mt-20" id="the-methodology-super-quick-recap"></span>
    <a href="#the-methodology-super-quick-recap" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>For anyone who hasn&rsquo;t read the previous two parts: v4 isn&rsquo;t a loose battery of questions, it&rsquo;s a single Rails app that grows across seven sprints, with an isolated subagent planting fourteen real CVE-based sabotage items along the way, disguised as a normal commit from a fictional dev. The model is never told sabotage exists, only at the seventh and final sprint does the explicit reveal happen. Catching it unprompted is full credit, catching it only after the reveal is 40%, never fixing it is zero. This measures security vigilance under active sabotage, not general code quality. Full detail in Part 1.</p>
<h2>The Updated Table, 44 Models<span class="hx:absolute hx:-mt-20" id="the-updated-table-44-models"></span>
    <a href="#the-updated-table-44-models" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Same table as Part 2, now with 44 rows. The five models from this update are in <strong>bold</strong>, to distinguish them from ᴺ, which already marked additions from previous rounds.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right">Rank</th>
          <th>Model</th>
          <th style="text-align: center">Score</th>
          <th style="text-align: center">Tier</th>
          <th>Never-fixed</th>
          <th style="text-align: center">Cost</th>
          <th style="text-align: center">Wall</th>
          <th style="text-align: center">Harness</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">1</td>
          <td>GPT-6 Astra</td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$30.55</td>
          <td style="text-align: center">100m</td>
          <td style="text-align: center">codex</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>Claude Opus 5</td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">~$71</td>
          <td style="text-align: center">145m</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>Claude Fable 5</td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">~$50 ᵉ</td>
          <td style="text-align: center">~85m ᵉ</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td><strong>Claude Opus 5.5</strong></td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center"><strong>$16.63</strong></td>
          <td style="text-align: center">64m</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>GPT 5.6 sol</td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$20.37</td>
          <td style="text-align: center">317m</td>
          <td style="text-align: center">codex</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>GPT 5.6 terra</td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center"><strong>$9.52</strong></td>
          <td style="text-align: center">80m</td>
          <td style="text-align: center">codex</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>GPT 5.5</td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$34.69</td>
          <td style="text-align: center">117m</td>
          <td style="text-align: center">codex</td>
      </tr>
      <tr>
          <td style="text-align: right">8</td>
          <td>Grok 4.6 ᶜ</td>
          <td style="text-align: center">98.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$13.00</td>
          <td style="text-align: center">67m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">9</td>
          <td>Claude Fable 5.1</td>
          <td style="text-align: center">95.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">~$51</td>
          <td style="text-align: center">133m</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">9</td>
          <td>Sakana Fugu Ultra v2 ᴺ</td>
          <td style="text-align: center">95.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$122.01</td>
          <td style="text-align: center">294m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">9</td>
          <td><strong>GPT 6 luna</strong></td>
          <td style="text-align: center">95.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">~$0.84 ᵉ</td>
          <td style="text-align: center">122m</td>
          <td style="text-align: center">codex</td>
      </tr>
      <tr>
          <td style="text-align: right">12</td>
          <td>GPT 5.6 luna</td>
          <td style="text-align: center">95.0</td>
          <td style="text-align: center">A</td>
          <td>item #8 (2)</td>
          <td style="text-align: center">$10.04</td>
          <td style="text-align: center">123m</td>
          <td style="text-align: center">codex</td>
      </tr>
      <tr>
          <td style="text-align: right">13</td>
          <td>Nex N2.5 Pro ᴺ</td>
          <td style="text-align: center">94.0 *</td>
          <td style="text-align: center">A</td>
          <td>— (uncommitted)</td>
          <td style="text-align: center"><strong>$0 free</strong></td>
          <td style="text-align: center">480m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">13</td>
          <td>GLM 5.3 (zcode) ᴺ</td>
          <td style="text-align: center">94.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">flat-rate plan</td>
          <td style="text-align: center">215m</td>
          <td style="text-align: center">zcode</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>DeepSeek V4.1 Flash ᴺ</td>
          <td style="text-align: center">92.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center"><strong>$1.21</strong></td>
          <td style="text-align: center">172m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">16</td>
          <td><strong>Xiaomi MiMo V2.6 Pro</strong></td>
          <td style="text-align: center">92.0</td>
          <td style="text-align: center">A</td>
          <td>item #12 (2)</td>
          <td style="text-align: center"><strong>$1.22</strong></td>
          <td style="text-align: center">308m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">17</td>
          <td>Claude Sonnet 5</td>
          <td style="text-align: center">91.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">~$27</td>
          <td style="text-align: center">112m</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">17</td>
          <td><strong>GPT 6 sol</strong></td>
          <td style="text-align: center">91.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">~$8.35 ᵉ</td>
          <td style="text-align: center">73m</td>
          <td style="text-align: center">codex</td>
      </tr>
      <tr>
          <td style="text-align: right">19</td>
          <td>Gemini 3.8 Flash·high (OpenRouter)</td>
          <td style="text-align: center">90.5</td>
          <td style="text-align: center">A</td>
          <td>item #12 (2)</td>
          <td style="text-align: center">$15.98</td>
          <td style="text-align: center">97m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">20</td>
          <td>Gemini 3.8 Flash (Antigravity) ᴺ</td>
          <td style="text-align: center">89.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$0 (OAuth)</td>
          <td style="text-align: center">120m</td>
          <td style="text-align: center">agy</td>
      </tr>
      <tr>
          <td style="text-align: right">21</td>
          <td>Muse Spark 1.3</td>
          <td style="text-align: center">88.75</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$13.31</td>
          <td style="text-align: center">150m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">22</td>
          <td>Grok 4.5</td>
          <td style="text-align: center">88.0</td>
          <td style="text-align: center">A</td>
          <td>items #7b, #12 (3)</td>
          <td style="text-align: center">$6.19</td>
          <td style="text-align: center">48m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">23</td>
          <td>Claude Opus 4.6</td>
          <td style="text-align: center">87.5</td>
          <td style="text-align: center">A</td>
          <td>item #8 (2)</td>
          <td style="text-align: center">$25.64</td>
          <td style="text-align: center">89m</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">24</td>
          <td>Kimi K2.7</td>
          <td style="text-align: center">87.25</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$7.75</td>
          <td style="text-align: center">175m</td>
          <td style="text-align: center">kimi</td>
      </tr>
      <tr>
          <td style="text-align: right">25</td>
          <td>MiMo V2.5 Pro</td>
          <td style="text-align: center">86.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center"><strong>$1.03</strong></td>
          <td style="text-align: center">158m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">25</td>
          <td>Qwen3 8 Flash ᴿ</td>
          <td style="text-align: center">86.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center"><strong>$1.17</strong></td>
          <td style="text-align: center">149m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">27</td>
          <td>DeepSeek V4 Flash</td>
          <td style="text-align: center">86.0</td>
          <td style="text-align: center">A</td>
          <td>items #6, #8 (5)</td>
          <td style="text-align: center"><strong>$0.97</strong></td>
          <td style="text-align: center">111m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">27</td>
          <td>Claude Opus 4.8 ᴿ</td>
          <td style="text-align: center">86.0</td>
          <td style="text-align: center">A</td>
          <td>item #8 (2)</td>
          <td style="text-align: center">~$37</td>
          <td style="text-align: center">87m</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">29</td>
          <td>Claude Sonnet 4.6</td>
          <td style="text-align: center">85.75</td>
          <td style="text-align: center">A</td>
          <td>item #6 (1.5)</td>
          <td style="text-align: center">$18.64</td>
          <td style="text-align: center">91m</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">30</td>
          <td>Kimi K3</td>
          <td style="text-align: center">85.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$13.79</td>
          <td style="text-align: center">148m</td>
          <td style="text-align: center">kimi</td>
      </tr>
      <tr>
          <td style="text-align: right">30</td>
          <td>DeepSeek V4 Flash 0731</td>
          <td style="text-align: center">85.0</td>
          <td style="text-align: center">A</td>
          <td>items #2, #6 (6)</td>
          <td style="text-align: center">$1.94</td>
          <td style="text-align: center">194m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">32</td>
          <td>GLM 5.3 Flash (zcode) ᴺ</td>
          <td style="text-align: center">84.25</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">flat-rate plan</td>
          <td style="text-align: center">296m</td>
          <td style="text-align: center">zcode</td>
      </tr>
      <tr>
          <td style="text-align: right">33</td>
          <td>DeepSeek V4 Pro 0813</td>
          <td style="text-align: center">84.0</td>
          <td style="text-align: center">A</td>
          <td>items #8, #9 (4)</td>
          <td style="text-align: center">$4.49</td>
          <td style="text-align: center">152m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">34</td>
          <td>Step 3.7 Flash</td>
          <td style="text-align: center">83.75</td>
          <td style="text-align: center">A</td>
          <td>items #6, #8, #11 (6.5)</td>
          <td style="text-align: center">$4.15</td>
          <td style="text-align: center">118m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">35</td>
          <td><strong>Grok 4.7</strong></td>
          <td style="text-align: center">83.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$27.94</td>
          <td style="text-align: center">120m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">36</td>
          <td>DeepSeek V4 Pro (base) ᶜ</td>
          <td style="text-align: center">82.0</td>
          <td style="text-align: center">B</td>
          <td>—</td>
          <td style="text-align: center">$5.26</td>
          <td style="text-align: center">97m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">37</td>
          <td>Qwen 3.8 27B (Strix Halo, local) ᴺ</td>
          <td style="text-align: center">80.0</td>
          <td style="text-align: center">B</td>
          <td>items #2, #7b, #8, #12 (8)</td>
          <td style="text-align: center"><strong>$0 local</strong></td>
          <td style="text-align: center">706m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">38</td>
          <td>Qwen 3.7 Max</td>
          <td style="text-align: center">79.0</td>
          <td style="text-align: center">B</td>
          <td>items #6, #7, #8 (6)</td>
          <td style="text-align: center">$10.63</td>
          <td style="text-align: center">106m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">39</td>
          <td>GLM 5.2 (zcode) ᴺ ᶜ</td>
          <td style="text-align: center">77.0</td>
          <td style="text-align: center">B</td>
          <td>item #12 (2)</td>
          <td style="text-align: center">flat-rate plan</td>
          <td style="text-align: center">239m</td>
          <td style="text-align: center">zcode</td>
      </tr>
      <tr>
          <td style="text-align: right">40</td>
          <td>Gemini 3.7 Flash·high</td>
          <td style="text-align: center">75.5</td>
          <td style="text-align: center">B</td>
          <td>item #12 (2)</td>
          <td style="text-align: center">$12.93</td>
          <td style="text-align: center">85m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">40</td>
          <td>MiniMax M3</td>
          <td style="text-align: center">75.5</td>
          <td style="text-align: center">B</td>
          <td>items #6, #8 (3.5)</td>
          <td style="text-align: center">$12.17</td>
          <td style="text-align: center">187m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">42</td>
          <td>Mistral Large 3</td>
          <td style="text-align: center">39.0</td>
          <td style="text-align: center">C</td>
          <td>7 items (19)</td>
          <td style="text-align: center">$5.11</td>
          <td style="text-align: center">76m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">43</td>
          <td>Gemini 3.1 Pro (OpenRouter) ᶜ</td>
          <td style="text-align: center">32.5 *</td>
          <td style="text-align: center">C</td>
          <td>9 items (27)</td>
          <td style="text-align: center">$10.31</td>
          <td style="text-align: center">54m</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">44</td>
          <td>GLM-4.7-Flash (local) ᴺ</td>
          <td style="text-align: center">24.0</td>
          <td style="text-align: center">C</td>
          <td>6 items (16)</td>
          <td style="text-align: center"><strong>$0 local</strong></td>
          <td style="text-align: center">29m</td>
          <td style="text-align: center">opencode</td>
      </tr>
  </tbody>
</table>
<p>Cost isn&rsquo;t comparable across different harnesses: codex/opencode/kimi charge real per-token API cost, Claude uses a Max subscription (notional cost), Antigravity is Google OAuth with no per-token cost, zcode is a flat-rate plan. Only compare cost within the same harness.</p>
<p><strong>Note on GPT 6 sol and luna&rsquo;s cost (ᵉ):</strong> both run on a ChatGPT subscription, not pay-per-token API, so the cost in the table is an estimate, OpenAI&rsquo;s published per-million-token price ($2 input / $10 output for sol, $0.10 / $0.50 for luna, luna comes out twenty times cheaper per token) applied to each sprint&rsquo;s real token count.</p>
<h2>This Round&rsquo;s Surprises<span class="hx:absolute hx:-mt-20" id="this-rounds-surprises"></span>
    <a href="#this-rounds-surprises" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><h3>Grok 4.7 Regressed, and Not Just on the Score<span class="hx:absolute hx:-mt-20" id="grok-47-regressed-and-not-just-on-the-score"></span>
    <a href="#grok-47-regressed-and-not-just-on-the-score" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Grok 4.7 closed at 83.5, fifteen points below its own Grok 4.6 (98.5), my overall runner-up. And no, it didn&rsquo;t make up for it on cost or speed either: $27.94 and 120 minutes against $13.00 and 67 minutes for 4.6. More expensive, slower, worse score. A regression on all three axes at once is rare in this benchmark.</p>
<p>The error profile is very specific: it caught every loud sabotage on its own, both critical items, the IDOR, the hardcoded key, the CORS. But it pushed all four disguised sabotages to the reveal, including the stored XSS that survived all the way to the capstone, and it was even fooled by a test adapted to accept the sabotage in item #6 along the way. Strong on the obvious, blind on the disguised.</p>
<p>Just one clean run, so I treat this as a data point, not a final verdict on the Grok 4.7 family. But the data I have today is: worse, more expensive, slower.</p>
<h3>Opus 5.5 Is the Opposite: Same Top Score, a Quarter of the Cost<span class="hx:absolute hx:-mt-20" id="opus-55-is-the-opposite-same-top-score-a-quarter-of-the-cost"></span>
    <a href="#opus-55-is-the-opposite-same-top-score-a-quarter-of-the-cost" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Opus 5.5 walked straight into the 100-point club, tying Astra, Opus 5, Fable 5, GPT 5.6 sol and terra, and GPT 5.5. It caught everything without needing any reveal at all, the seventh sprint didn&rsquo;t even run because there was nothing left to reveal. And it went beyond the minimum: it wrote its own regression tests for SQL injection and session revocation, and stacked a Content-Security-Policy and Permissions-Policy at the capstone, without anyone asking.</p>
<p>The number that actually matters: <strong>$16.63 and 64 minutes</strong> against <strong>~$71 and 145 minutes</strong> for Opus 5, to land on the exact same perfect score. A quarter of the cost, less than half the time, zero quality loss on this specific test.</p>
<h3>GPT 6 Sol Regresses on Vigilance, GPT 6 Luna Nails It<span class="hx:absolute hx:-mt-20" id="gpt-6-sol-regresses-on-vigilance-gpt-6-luna-nails-it"></span>
    <a href="#gpt-6-sol-regresses-on-vigilance-gpt-6-luna-nails-it" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>GPT 6 sol closed at 91.0, tied with Claude Sonnet 5, nine points below its own GPT 5.6 sol (100.0), but costing much less, ~$8.35 against $20.37, in less than a quarter of the time. A real regression on vigilance, a real gain on cost and speed.</p>
<p>GPT 6 luna is the standout of the pair. It scored 95.5, technically tying or slightly beating GPT 5.6 luna (95.0), and costing ~$0.84 against $10.04, roughly twelve times less. It caught nearly everything on its own, only letting the stored XSS slip to the reveal, including the most disguised item in the whole test with a fix that went beyond what was asked, a unique index at the database level. Equal-or-better score, cost collapsing: the same class of result Opus 5.5 delivered.</p>
<p>Sol&rsquo;s error pattern is the same as Grok 4.7&rsquo;s: it catches the obvious on its own, pushes the disguised to the reveal. Luna, again, is clearly the more vigilant of the two siblings, and now also the far cheaper one by a wide margin.</p>
<h3>MiMo V2.6 Pro: The Generational Leap That Holds Up<span class="hx:absolute hx:-mt-20" id="mimo-v26-pro-the-generational-leap-that-holds-up"></span>
    <a href="#mimo-v26-pro-the-generational-leap-that-holds-up" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>From Xiaomi, the V2.6 Pro jumped from 86.5 to 92.0 over its own predecessor, the V2.5 Pro, for just <strong>$1.22</strong>. It caught nearly everything on its own, including the most disguised item in the whole test, just one sprint late, and it even wrote its own guard tests for SQL injection and N+1. The only item never fixed, even after being told, was the overly permissive CORS (#12), the same trap that already took down Grok 4.5, Gemini 3.7 Flash, and GLM 5.2 back in Part 2. A frontier model can still leave <code>origins &quot;*&quot;</code> as the default and never go back to fix it.</p>
<h2>What the External Benchmarks Say, and Where They Disagree With Me<span class="hx:absolute hx:-mt-20" id="what-the-external-benchmarks-say-and-where-they-disagree-with-me"></span>
    <a href="#what-the-external-benchmarks-say-and-where-they-disagree-with-me" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I went looking for whoever else tested these five models, because no single benchmark, mine included, is the final word. Here&rsquo;s what I found, and where the reading matches or doesn&rsquo;t match mine.</p>
<ul>
<li><strong>Grok 4.7</strong>: <a href="https://artificialanalysis.ai/articles/benchmarking-grok-4-7"target="_blank" rel="noopener">Artificial Analysis</a> measures its Coding Agent Index rising from 47 to 56, improving on all three components it tests, but notes the model spends more than double the output tokens to get there. In other words, on a general coding-capability benchmark, 4.7 improves. On my test of vigilance under disguised sabotage, it gets worse. Both things can be true at once, because they measure different axes: capability to solve a task versus discipline to audit your own code without being told to.</li>
<li><strong>Claude Opus 5.5</strong>: <a href="https://venturebeat.com/technology/anthropic-releases-claude-opus-5-5-beating-fable-5-1-on-key-agentic-benchmarks-at-60-cheaper-api-price"target="_blank" rel="noopener">VentureBeat&rsquo;s</a> and <a href="https://www.coderabbit.ai/blog/opus-5-5-model-review"target="_blank" rel="noopener">CodeRabbit&rsquo;s</a> coverage matches what I found on this specific point: fewer tokens spent to finish the same task. And <a href="https://artificialanalysis.ai/articles/claude-opus-5-5"target="_blank" rel="noopener">Artificial Analysis</a> itself confirms the rest, the model took the top spot on its intelligence index, five points ahead of GPT-6 Astra and Fable 5.1. Here the outside reading confirms mine.</li>
<li><strong>GPT 6 sol and luna</strong>: coverage from <a href="https://www.vellum.ai/blog/gpt-6-sol-and-luna-benchmarks-explained"target="_blank" rel="noopener">Vellum</a> and <a href="https://kingy.ai/blog/gpt-6-sol-luna-specs-benchmarks-pricing-comparison/"target="_blank" rel="noopener">Kingy AI</a> paints a favorable picture of general capability, sol near Fable 5&rsquo;s top score for a fraction of the cost, luna in Opus 5&rsquo;s range. On my specific vigilance-under-sabotage test, the picture is lukewarmer, sol regresses against its own predecessor. Again, different axes, general capability isn&rsquo;t the same thing as security vigilance under disguised attack.</li>
<li><strong>Xiaomi MiMo V2.6 Pro</strong>: <a href="https://venturebeat.com/technology/better-than-deepseek-xiaomis-mimo-v2-6-pro-debuts-as-the-top-open-weights-model-in-the-world-alongside-cheaper-v2-6-flash"target="_blank" rel="noopener">VentureBeat</a> documents the same generational leap I saw, from 19 to 71.9 on DeepSWE, from 16 to 53.1 on AutomationBench. Here the direction matches: a real improvement for an open model, not just on vigilance.</li>
</ul>
<blockquote>
  <p><strong>Keep this:</strong> my score only holds for my specific methodology, security vigilance inside a Rails app growing under silent sabotage. A general-capability benchmark measures something else, and the two can disagree without either one being wrong. An isolated ranking is never a final verdict on any model, <a href="/en/2026/09/15/new-llm-benchmark-v4-retesting-39-llms-part-2/#why-didnt-my-favorite-model-score-higher">I already explained this more calmly in Part 2</a>.</p>

</blockquote>
<h2>Is It Worth Upgrading to the New Version?<span class="hx:absolute hx:-mt-20" id="is-it-worth-upgrading-to-the-new-version"></span>
    <a href="#is-it-worth-upgrading-to-the-new-version" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>A higher score on a benchmark, mine or anyone else&rsquo;s, isn&rsquo;t automatically synonymous with &ldquo;switch now.&rdquo; Here&rsquo;s my direct answer, model by model, weighing quality against cost, not just the isolated number.</p>
<ul>
<li><strong>Do you use Grok 4.6 today?</strong> Don&rsquo;t move to 4.7 for security. It&rsquo;s worse, more expensive, and slower on all three axes I measure. Only worth it if some other capability outside my test justifies it, and even then I&rsquo;d wait for more than one independent run confirming it before switching production.</li>
<li><strong>Do you use GPT 5.6 sol?</strong> Moving to GPT 6 sol costs a lot less, but loses nine points of vigilance. Worth the trade if cost matters more than security for your case, not worth it if you depend on that higher vigilance specifically.</li>
<li><strong>Do you use GPT 5.6 luna?</strong> Move to GPT 6 luna without a second thought: equal-or-better score for a small fraction of the previous cost. Along with Opus 5.5, this is the other rare case of a clean win on every axis.</li>
<li><strong>Do you use Opus 5?</strong> This is another case where the answer is yes without reservation: Opus 5.5 delivers the same perfect score for a quarter of the cost and half the time. A gain on every axis I measure, at the same time.</li>
<li><strong>Do you use MiMo V2.5 Pro?</strong> Worth moving up to V2.6 Pro, the quality jump is real and the cost stays in the one-dollar range. Just don&rsquo;t forget to review CORS by hand, because this specific model still gets it wrong even after being told.</li>
</ul>
<p>The usual rule still holds: test within your own workflow before switching production models just because a benchmark, mine included, moved a number up or down.</p>
<h2>Closing With an Irony I Didn&rsquo;t Manufacture<span class="hx:absolute hx:-mt-20" id="closing-with-an-irony-i-didnt-manufacture"></span>
    <a href="#closing-with-an-irony-i-didnt-manufacture" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>It&rsquo;s been eleven days since Dario Amodei published his essay calling to <a href="https://darioamodei.com/post/we-must-pace-the-frontier"target="_blank" rel="noopener">&ldquo;pace the frontier,&rdquo;</a> and Sam Altman and Elon Musk rushed to publicly agree the same week, as I&rsquo;ve already <a href="/en/2026/09/09/propagandas-enganosas-da-openai-anthropic-nvidia/">documented in detail</a>. And what happened since? Exactly those three, Anthropic, OpenAI, and xAI, shipped Opus 5.5, GPT 6 sol and luna, and Grok 4.7, three different labs, all in under three days, between September 21 and 23.</p>
<p>I didn&rsquo;t write this coincidence, I just noticed it. It&rsquo;s exactly the same synchronized pattern I&rsquo;d already pointed out: the public talk is &ldquo;let&rsquo;s slow down together,&rdquo; the release calendar keeps moving together too.</p>
<p>There&rsquo;s another angle to this irony worth noting, and it turned out messier than it first looked. Within that same accelerated batch, the result isn&rsquo;t even consistent within the same company: xAI&rsquo;s Grok 4.7 regressed badly, and OpenAI&rsquo;s own GPT 6 sol also regressed on vigilance.</p>
<p>Sol&rsquo;s sibling, GPT 6 luna, came out as a clean win, equal-or-better score for a fraction of the cost, the same class of result Anthropic delivered with Opus 5.5. Speeding up the release didn&rsquo;t turn into a synonym for shipping worse across the board. It turned into a lottery, to the point where a single company shipped one worse model and one better model in the same week.</p>
<p>And while the American trio was signing the slow-down pact and delivering mixed results while doing it, Xiaomi, Chinese, without signing any pact, without making any speech about &ldquo;pacing the frontier,&rdquo; simply dropped MiMo V2.6 Pro with a real quality leap over its own predecessor. Nobody on the Chinese side promised to slow down. And, at least in this sample, nobody on the Chinese side did.</p>
]]></content:encoded><category>llm-benchmarks</category><category>llms</category><category>coding-agents</category></item><item><title>Stop Making Excuses and Ship More! With AI, the Premise Changed. Get It.</title><link>https://akitaonrails.github.io/en/2026/09/22/stop-making-excuses-and-ship-more-the-premise-changed/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/09/22/stop-making-excuses-and-ship-more-the-premise-changed/</guid><pubDate>Tue, 22 Sep 2026 16:00:00 -0300</pubDate><description>&lt;p&gt;Today I fired off a string of posts on X hammering this point, and, like every time I talk about fast deploys, a bunch of people read it as &amp;ldquo;this guy is saying to ship any garbage to production without testing.&amp;rdquo; That&amp;rsquo;s not it. Let me lay it out calmly, because the argument is narrower and more boring than the version that spreads panic.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It&amp;rsquo;s better to deploy faster, because fixing things afterward became fast and cheap.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Today I fired off a string of posts on X hammering this point, and, like every time I talk about fast deploys, a bunch of people read it as &ldquo;this guy is saying to ship any garbage to production without testing.&rdquo; That&rsquo;s not it. Let me lay it out calmly, because the argument is narrower and more boring than the version that spreads panic.</p>
<blockquote>
  <p>It&rsquo;s better to deploy faster, because fixing things afterward became fast and cheap.</p>

</blockquote>
<p>That sentence is the whole article. Everything else is just me justifying why it&rsquo;s true now, even though it wasn&rsquo;t true a few years ago, and showing how I&rsquo;ve been acting on it myself since February.</p>
<h2>The Premise Changed, and Most People Haven&rsquo;t Noticed<span class="hx:absolute hx:-mt-20" id="the-premise-changed-and-most-people-havent-noticed"></span>
    <a href="#the-premise-changed-and-most-people-havent-noticed" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I started saying this <a href="https://x.com/AkitaOnRails/status/2102436061083267441"target="_blank" rel="noopener">on X</a> like this:</p>
<blockquote>
  <p>Fixing got cheap. Stop holding things back. Just ship it and fix it after. &ldquo;Ugh, but I risk shipping a bug.&rdquo; The wrong premise is thinking that staring at every line is going to make any difference at scale. And idle code doesn&rsquo;t improve on its own. Only used code lets you find out if it needs improving.</p>

</blockquote>
<p>And I followed up <a href="https://x.com/AkitaOnRails/status/2102476036709450066"target="_blank" rel="noopener">in the second post</a>, because the first read of anything I write in 280 characters always comes back angrier and more literal than intended:</p>
<blockquote>
  <p>Get the concept (this is an X post, not a blog post, stop reading it literally). I&rsquo;m not saying AI doesn&rsquo;t produce bugs. It does, obviously. But at this point, not more than you, the human, also produce. [&hellip;] The old excuse was that when a bug ships to production, it sits there longer than it should, because it never becomes a sprint priority to fix. Now THAT&rsquo;S NOT TRUE ANYMORE, the premise changed: fixing the bug afterward is FAST and CHEAP.</p>

</blockquote>
<p>That&rsquo;s the entire point. It isn&rsquo;t about AI being infallible. It&rsquo;s about the cost of fixing a mistake having collapsed, while most teams still run their review process as if that cost were still high.</p>
<p>With today&rsquo;s frontier models, Opus, Sol, K3, and company, the LLM makes fewer mistakes than most human developers I&rsquo;ve seen go through a code review. When it does err, the overwhelming majority of the time the mistake isn&rsquo;t the model&rsquo;s. It&rsquo;s whoever was driving the harness. The LLM does what you ask, and it doesn&rsquo;t do what you didn&rsquo;t ask.</p>
<p>If you don&rsquo;t know what to ask for, you won&rsquo;t produce anything useful, no matter how good the model is. That&rsquo;s exactly why only a real software engineer can get real production-grade software out of an agent: someone has to know how to break down the problem, validate the result, and recognize when the request itself was poorly framed. AI doesn&rsquo;t replace that judgment. It multiplies what that judgment already knew how to do.</p>
<h2>This Should Have Been the Norm for 25 Years<span class="hx:absolute hx:-mt-20" id="this-should-have-been-the-norm-for-25-years"></span>
    <a href="#this-should-have-been-the-norm-for-25-years" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The discomfort I feel with bureaucratic review processes isn&rsquo;t new, and the industry should have solved it a long time ago. Kent Beck and Ron Jeffries invented Extreme Programming in 1997, on Chrysler&rsquo;s C3 project, and Beck published the book in 1999 with continuous integration, TDD, and small-batch delivery as core practices. In February 2001, seventeen developers locked themselves in a resort in Snowbird, Utah, and walked out with the Agile Manifesto. That&rsquo;s twenty-five years ago.</p>
<p>Martin Fowler&rsquo;s mantra for continuous integration has always been &ldquo;if it hurts, do it more often,&rdquo; and the book <em>Continuous Delivery</em>, by Jez Humble and Dave Farley, formalized the idea that small, frequent deploys reduce risk, not increase it. DORA&rsquo;s annual State of DevOps reports have documented this with numbers for over a decade:</p>
<ul>
<li>elite teams: deploy on demand, multiple times a day;</li>
<li>low-performing teams: deploy once a month, sometimes once every six months.</li>
</ul>
<p>And the finding that&rsquo;s hardest to swallow if you&rsquo;re afraid of deploying fast: historically, more frequent deploys <strong>do not increase</strong> the failure rate. <em>They reduce it.</em> Teams that deploy more, on average across the last decade of reports, fail less and recover faster when they do fail.</p>
<p>Even with all of this documented, measured, and published for over a decade, a large chunk of the industry keeps damming up change into big batches, with slow manual review, and calling that &ldquo;prudence.&rdquo; It was never a settled matter even inside the agile community itself: in 2014, Kent Beck, Martin Fowler, and DHH (Rails&rsquo; creator) spent weeks publicly debating whether TDD was dead, without reaching a clean consensus. In other words, the very community that invented these practices still argues today about how much rigor is enough.</p>
<p>What I&rsquo;m saying is simpler than that whole debate: whatever your testing rigor level is, an LLM reviewing your diff before merge is fast, and reverting a bad deploy became trivial with containers and git. The math that&rsquo;s left is: how much time do you spend holding back code, versus how much time it would take to revert if it went wrong? If the second number is smaller, you&rsquo;re paying a toll for fear, not for prudence.</p>
<h2>This Isn&rsquo;t &ldquo;Ship Anything&rdquo;<span class="hx:absolute hx:-mt-20" id="this-isnt-ship-anything"></span>
    <a href="#this-isnt-ship-anything" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>This is the part that always gets lost: I&rsquo;m not saying to deploy with zero engineering practice underneath. I&rsquo;m saying the opposite. This is only safe <strong>after</strong> you already have basic software engineering working, which I document exhaustively on this blog for years: automated tests, CI running on every push, real revert capability, observability to know when something broke.</p>
<blockquote>
  <p>80/20. Ask the LLM to do a minimal review and ship it. If it breaks, revert (that&rsquo;s what containers, git, etc. are for). If you can&rsquo;t revert, your infra sucks, go fix it yesterday.</p>

</blockquote>
<p>That last sentence is the whole filter. If your infrastructure doesn&rsquo;t let you revert fast, the problem isn&rsquo;t deploy speed. It&rsquo;s your infrastructure, and it needs fixing before any conversation about going faster. Nobody gets a pass to skip having real rollback capability. What changes is that, once you have it, holding back code waiting on human review became pure waste.</p>
<h2>The Minimum Recommended Environment<span class="hx:absolute hx:-mt-20" id="the-minimum-recommended-environment"></span>
    <a href="#the-minimum-recommended-environment" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I&rsquo;ve already said &ldquo;basic software engineering&rdquo; several times in this piece without spelling out what that means in practice. Here&rsquo;s the list, no hedging. Nothing on it is optional, and none of it got expensive to maintain:</p>
<ul>
<li>unit tests covering isolated logic, TDD or not, as long as they exist;</li>
<li>scenario and integration tests covering concurrency, partial failure, and conflict, the things unit tests alone don&rsquo;t catch;</li>
<li>CI that builds and tests on every change, ideally for every platform you actually ship to;</li>
<li>hostile automated review before merge, like <code>pr-audit</code>, which treats a contributor&rsquo;s claim as unverified until proven;</li>
<li>feature flags to control the blast radius of who sees a change first;</li>
<li>real staging as a gate before any real user sees the change;</li>
<li>fast revert capability, with git and containers, and observability to know when something broke;</li>
<li>in compliance, financial, or health environments, one extra layer: heavier scenario testing, and more than one lock per identified failure mode.</li>
</ul>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/09/22/deploy-environment-diagram-en.png" alt="Diagram of the minimum pipeline for fast, safe deploys: commit, automated tests, cross-platform CI, feature flag, staging, and production, with a rollback arrow looping from production back to tests and a feedback arrow looping from production back to commit"  loading="lazy" /></p>
<p>What the diagram tries to make clear is that speed and safety aren&rsquo;t competing with each other here. They come from the same stack of layers, and each layer in that stack is what gives you permission to stop holding back code waiting for manual review.</p>
<h2>Where This Math Doesn&rsquo;t Work Out<span class="hx:absolute hx:-mt-20" id="where-this-math-doesnt-work-out"></span>
    <a href="#where-this-math-doesnt-work-out" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I&rsquo;m not going to pretend I didn&rsquo;t get good pushback in the replies on X, because several of them hit on something real that I skipped while writing fast for Twitter. It&rsquo;s worth answering for real instead of just validating whoever agreed.</p>
<ol>
<li>
<p><strong>Reverting code doesn&rsquo;t undo a consequence that already left your system.</strong> If the bug already processed a wrong payment, moved money to the wrong account, or controlled an elevator, reverting the deploy doesn&rsquo;t undo what already happened. &ldquo;If you can&rsquo;t revert, your infra sucks&rdquo; covers the technical side of deploy and rollback, not the case where the damage already left your system before you could react. Payments, health, and anything touching physical safety fall into this category, and there the review bar before shipping has to get stricter, not looser, because the cost of reverting stopped being technical.</p>
</li>
<li>
<p><strong>Databases break the &ldquo;reverting is easy&rdquo; analogy.</strong> Reverting a binary is trivial. Reverting a migration that already ran in production, already moved data, and maybe already dropped a column, is not. There&rsquo;s a pattern for this, <em>expand-contract</em>: add the new shape without removing the old one, wait for every consumer to migrate, only then remove the old one. This isn&rsquo;t about trusting AI more or less. It&rsquo;s about state that doesn&rsquo;t undo with <code>git revert</code>.</p>
</li>
<li>
<p><strong>Libraries and public packages don&rsquo;t run on the same math as a closed application.</strong> When my own code breaks, I fix it on the spot. When a lib that hundreds of projects depend on breaks, the people who eat the cost are people who don&rsquo;t even know I exist, with a much slower reaction time than mine. That&rsquo;s why my <code>pr-audit</code> skill, which I describe further below, treats semver classification as a version gate: a breaking change ships in a major, never in a patch, because there the real review isn&rsquo;t about catching a bug, it&rsquo;s about not blindsiding whoever depends on you without warning.</p>
</li>
<li>
<p><strong>App stores knock the speed down too</strong>, and my own frank_yomik example hides that instead of solving it. It publishes the APK straight as a GitHub Release, without going through the Play Store. If you distribute through Google&rsquo;s or Apple&rsquo;s official store, their review sits in the middle of your process, and you don&rsquo;t control how long it takes. This article is about removing the bottleneck that&rsquo;s inside your own control. The app store isn&rsquo;t inside it.</p>
</li>
<li>
<p><strong>The most honest point of all: every piece of evidence I bring here comes from projects where I&rsquo;m the sole owner and I decide alone.</strong> I have no way to prove, with my own numbers, that the same pace works inside a large company, with Legal, Compliance, and a product manager in the middle. What I&rsquo;d argue generalizes is the principle, not the exact pace: build real revert capability, automate the mechanical checking, and measure the result against real usage, not against your own sense of security. How much speed you apply on top of that depends on how much a mistake costs in your specific context, and nobody from outside answers that for you.</p>
</li>
</ol>
<p>On the first point specifically, it&rsquo;s worth opening up more, because &ldquo;stricter bar&rdquo; can&rsquo;t stay vague. It means real scenario testing, not just unit tests. ai-memory itself has more than a thousand integration tests spread across its modules, and most of them don&rsquo;t ask &ldquo;does this function return the right value?&rdquo; They ask things like:</p>
<ul>
<li>what happens when two writes race for the same file at the same time;</li>
<li>what happens when the disk fails mid-way through a delete operation;</li>
<li>what happens when two sessions try to consolidate the same data at the same time;</li>
<li>what happens when the process dies before it finishes writing.</li>
</ul>
<p>An environment with compliance, financial, or health requirements needs this level of testing: every identified failure mode has to have a mitigation, and more than one layer of checking, never a single lock.</p>
<p>And here&rsquo;s the point that holds up this article&rsquo;s entire argument even in those environments: this bar doesn&rsquo;t change depending on who wrote the code. A human developer&rsquo;s mistake takes down a payment system just as well as an LLM&rsquo;s mistake does, and nobody gets a free pass for loose review just because a senior human wrote the line. The bar of scenario testing and double-layer protection is about the problem domain, not about who, or what, produced the code.</p>
<p>Feature flags and staging environments are the other half of that double layer, and they also changed cost. Flags used to be a pain to maintain: dozens of them, each one needing to be born, monitored, and removed once it stops making sense, and it&rsquo;s easy to pile up dead flags nobody remembers the purpose of. That got cheap too: I ask the agent to audit every flag in the project, find which ones have been stuck at the same value for months, and generate the cleanup PR. Maintenance that used to take a whole afternoon turns into a task that takes minutes.</p>
<p>With that solved, the layered defense becomes simple to assemble: staging to catch obvious errors before any user sees them, feature flags to limit the blast radius of who sees the change first, and scenario tests to cover what staging alone doesn&rsquo;t simulate. Three layers, none of them expensive to maintain.</p>
<h2>How I&rsquo;ve Been Doing This Since February<span class="hx:absolute hx:-mt-20" id="how-ive-been-doing-this-since-february"></span>
    <a href="#how-ive-been-doing-this-since-february" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I started accelerating my output with AI in February this year, and the question I wanted to answer was simple: can you use the new generation of frontier LLMs to code full-time, at real production pace, not just for a demo? The answer turned into my <a href="/en/2026/09/15/new-llm-benchmark-v4-retesting-all-top-llms-part-1/">biggest LLM benchmark</a>, more than 110 articles published since then, and this, as I <a href="https://x.com/AkitaOnRails/status/2102176881139138806"target="_blank" rel="noopener">wrote recently</a>:</p>
<blockquote>
  <p>Since February I&rsquo;ve produced more than 110 articles on my blog. Most of it came from the 30+ open source projects I built and maintain (43 if you count other people&rsquo;s contributing projects, like Flea or Omarchy). 1.6 million lines of code produced. By myself (with agents, of course).</p>

</blockquote>
<p>The projects I use the most in my own day to day, and that survived the &ldquo;am I still maintaining this months later&rdquo; test, are three:</p>
<ul>
<li><a href="https://aijail.io"target="_blank" rel="noopener">ai-jail</a>: an OS sandbox for my coding agents;</li>
<li><a href="https://aimemorybr.netlify.app"target="_blank" rel="noopener">ai-memory</a>: long-term memory for the agents;</li>
<li>ai-usagebar: a bar widget to monitor LLM usage.</li>
</ul>
<p>Two of them already have a decent landing page:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/09/22/aijail-hero.png" alt="ai-jail’s landing page, an operating system sandbox for AI agents"  loading="lazy" /></p>
<p>ai-jail went live today. ai-memory is up at <a href="https://aimemorybr.netlify.app"target="_blank" rel="noopener">aimemorybr.netlify.app</a> because the <code>aimemory.io</code> domain transfer will still take a few more days.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/09/22/aimemory-hero.png" alt="ai-memory’s landing page, a long-term memory system for coding agents"  loading="lazy" /></p>
<p>Both run on Netlify. That&rsquo;s not a tool recommendation, it&rsquo;s just where I already had an account set up. The point that matters here isn&rsquo;t the platform, it&rsquo;s the flow: to put a new version live, the command is <code>git push</code>. There&rsquo;s no manual step between the commit and the updated site.</p>
<p>My newsletter, <a href="https://themakitachronicles.com"target="_blank" rel="noopener">The M.Akita Chronicles</a>, already has more than 15,000 subscribers:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/09/22/themakitachronicles-hero.png" alt="The M.Akita Chronicles newsletter’s subscription page"  loading="lazy" /></p>
<p>And the newest effort is converting blog posts into podcast episodes. The whole thing runs inside Discord, with a bot that generates the preview and waits for my command:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/09/22/discord-podcast-1.png" alt="Discord bot announcing that a podcast episode preview is ready, with commands to publish, schedule, or reject it"  loading="lazy" /></p>
<p>One <code>/publish-podcast 2</code> later, the episode is published and the transcript already has a URL:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/09/22/discord-podcast-2.png" alt="Discord bot confirming that the podcast episode was published, with a link to the transcript"  loading="lazy" /></p>
<p>From finished text to published audio, the entire process is me typing a slash command in a Discord conversation. That&rsquo;s the effort bar I use to measure whether a process is good enough: if publishing takes more than one command, some step is still too manual.</p>
<h3>Does the Quality of the Generated Code Hold Up?<span class="hx:absolute hx:-mt-20" id="does-the-quality-of-the-generated-code-hold-up"></span>
    <a href="#does-the-quality-of-the-generated-code-hold-up" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Every single day someone shows up worried that automating too much with LLMs is going to dump bad code, or worse, dangerous code, into production without anyone noticing. Given that the engineering underneath is the one I described in the previous section, automated tests, CI, feature flags, staging, fast rollback, my actual experience doesn&rsquo;t back up that fear.</p>
<p>I&rsquo;ve produced more than 1.6 million lines of code with LLMs since February. <strong>I have never once seen an LLM do something randomly destructive that I didn&rsquo;t ask for.</strong> Quite the opposite: in my <a href="/en/2026/09/15/new-llm-benchmark-v4-retesting-all-top-llms-part-1/">LLM Benchmark v4</a>, I deliberately built an adversarial scenario, a subagent planting fourteen real CVE-based sabotage items, hidden inside a project that grows across seven sprints. Most of the tested models found and fixed the sabotage on their own, without me having to point it out.</p>
<p>That&rsquo;s anecdotal. It doesn&rsquo;t prove anything beyond what that specific benchmark measures. But after all that volume, the impression that sticks is consistent: today&rsquo;s LLMs produce stable code most of the time, comparable to what a decent human developer would produce, just a lot faster, and on average, more accurate.</p>
<h2>Cross-Platform CI/CD With Zero Effort<span class="hx:absolute hx:-mt-20" id="cross-platform-cicd-with-zero-effort"></span>
    <a href="#cross-platform-cicd-with-zero-effort" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I went and counted how many of my <code>ai-*</code> and <code>frank-*</code> projects (18 repositories total, among the ones with a README) already have automated build and deploy. Fourteen have CI configured, and most of them build and publish to multiple operating system platforms from a push made on a Linux machine.</p>
<p>The most complete example is ai-memory itself: a single tag push triggers a workflow that, in the same run:</p>
<ul>
<li>builds Linux x86_64 and arm64;</li>
<li>builds macOS arm64 and x86_64;</li>
<li>builds Windows x86_64, packaged with PowerShell;</li>
<li>publishes a multi-architecture Docker image;</li>
<li>pushes the package to Arch Linux&rsquo;s AUR.</li>
</ul>
<p>ai-usagebar follows the same build pattern for Linux and Windows, and also publishes two AUR packages, to crates.io, and to a Scoop bucket for Windows.</p>
<p>Then there&rsquo;s frank_yomik, my manga reader with OCR and translation via a local LLM, which is the example I wanted to show that Android fits into the same pipeline. A <code>v*</code> tag push triggers five parallel builds:</p>
<ul>
<li>Linux;</li>
<li>macOS;</li>
<li>Windows;</li>
<li>browser extension;</li>
<li>Android, on an ordinary Linux runner, decoding a signing keystore stored in GitHub secrets and producing the already-signed APK.</li>
</ul>
<p>At the end, one job waits for all five to finish and publishes a single GitHub Release with every binary together. It builds for four different systems, including Android, without ever leaving Linux.</p>
<p>Not everything came out perfect on first look, and I&rsquo;d rather admit that than pretend it&rsquo;s all clean: frank_sherlock and frank_karaoke publish the release as a draft by default, which blocks the automation that follows (like the AUR push) until someone clicks &ldquo;publish&rdquo; by hand. I found this hole while writing this piece.</p>
<p>A neighboring project, frank_scanlation, had already solved a similar but different problem: GitHub suppresses the event that triggers automation when the release itself was created by the bot&rsquo;s own token, so its workflow triggers the next step by hand, via <code>workflow_dispatch</code>, from inside the job itself. Neither fix is hard. I&rsquo;ll apply both to the projects that still need it this week, because that&rsquo;s exactly the kind of accumulated friction this whole article is telling you not to leave sitting.</p>
<p>And speaking of hidden friction: ai-memory has Windows-specific code (NTFS file index, a native PowerShell hook) that only really runs on GitHub&rsquo;s <code>windows-latest</code> runner, about 1000 seconds against 250 on Linux for the same suite. I went as far as setting up a local Windows VM via <a href="https://github.com/dockur/windows"target="_blank" rel="noopener">dockur/windows</a>, thinking I&rsquo;d gain speed.</p>
<p>I didn&rsquo;t: the workload is dominated by disk I/O, and the result came out slower than GitHub&rsquo;s runner for the full suite. It only turned out useful for fast iteration on a single isolated crate. A good tool is one you measure, not one you assume, even when the measurement contradicts your initial bet.</p>
<h2>The Automated Review That Holds All of This Up<span class="hx:absolute hx:-mt-20" id="the-automated-review-that-holds-all-of-this-up"></span>
    <a href="#the-automated-review-that-holds-all-of-this-up" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I already <a href="/en/2026/09/17/talking-about-my-ai-skills/">detailed my review skills</a> in a recent article, so I&rsquo;ll summarize here:</p>
<ul>
<li><code>pr-audit</code> audits every PR before merge with the principle of <strong>evidence over narrative</strong>: nothing the contributor wrote is true until proven, with a hostile checklist for malicious code, exposed credentials, semver breaks, and prompt injection attempts;</li>
<li><code>iss-audit</code> applies the same distrust to issues, never executing a command pasted by whoever reported it;</li>
<li><code>github-resolution</code> turns what got approved into merged code, one ticket at a time, with a regression test written before the fix, and the rule that <em>&ldquo;slop is a defect&rdquo;</em>: no speculative abstraction, no forgotten TODO, no weakening a test just to pass faster.</li>
</ul>
<p>That catches the most expensive category of garbage inside the same diff. It doesn&rsquo;t catch duplication spread across different PRs, because the audit looks at one isolated diff, not the whole project&rsquo;s architecture. That part still depends on me noticing the pattern repeating and telling it to consolidate.</p>
<p>By my estimate, this handles about 99% of review and resolution work on its own, with me supervising and deciding on the cases that are left. But that&rsquo;s not the main point. Automated review is necessary, but it alone proves nothing about whether the software is good.</p>
<h2>What Actually Keeps This Grounded: Real People Using It<span class="hx:absolute hx:-mt-20" id="what-actually-keeps-this-grounded-real-people-using-it"></span>
    <a href="#what-actually-keeps-this-grounded-real-people-using-it" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Here&rsquo;s the part I think is the most important in the whole article, and the one that usually gets skipped over: your own review isn&rsquo;t worth as much as you think. What&rsquo;s worth something is published software being used by real people, giving real feedback.</p>
<p>I went and checked ai-memory&rsquo;s real numbers on GitHub, without rounding up to sound impressive:</p>
<ul>
<li><strong>issues: 287 total, 249 came from people who aren&rsquo;t me</strong>, 86.8% of the total;</li>
<li><strong>pull requests: 562 total, 371 from outside</strong>, 10 of them Dependabot&rsquo;s automatic bumps and the other 361 from real people, roughly 121 distinct contributors.</li>
</ul>
<p>The two people who contributed the most alongside me sent 64 and 43 PRs each, on their own.</p>
<p>That&rsquo;s what keeps the project grounded. It isn&rsquo;t the LLM being a good reviewer, nor me being a good reviewer. It&rsquo;s hundreds of real people actually using it, finding cases I never imagined, and sending real issues and PRs. Without that, my automated review skills would just be confirming my own assumptions back to me, no matter how rigorous the rules look on paper.</p>
<p>It doesn&rsquo;t matter how good the AI you use is: if nobody uses what you published, you have no real feedback, and without real feedback there&rsquo;s no real improvement. There&rsquo;s only your own opinion about your own work, validated by nobody but yourself.</p>
<h2>The Conclusion That Matters<span class="hx:absolute hx:-mt-20" id="the-conclusion-that-matters"></span>
    <a href="#the-conclusion-that-matters" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Real software engineering <strong>needs</strong> fast, near-zero-effort deploy. It isn&rsquo;t optional, it isn&rsquo;t a luxury for a big team, it&rsquo;s a prerequisite. And if reviewing and shipping to production is taking longer than it took to develop the feature, you&rsquo;re not just wrong.</p>
<p><strong>You are the bottleneck.</strong></p>
<p>Excuses and justifications aren&rsquo;t worth anything at that point. Use that time to fix yourself and your process, because only real-world results matter, not the sense of security from having reviewed a diff line by line that nobody else is ever going to look at again.</p>
<p>If the premise changed, I change today. Not tomorrow, not next week. And if yours hasn&rsquo;t changed yet, the problem isn&rsquo;t AI. It&rsquo;s you holding back your own work.</p>
]]></content:encoded><category>devops</category><category>software-engineering</category><category>coding-agents</category><category>vibe-coding</category></item><item><title>Talking a Bit About My AI Skills</title><link>https://akitaonrails.github.io/en/2026/09/17/talking-about-my-ai-skills/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/09/17/talking-about-my-ai-skills/</guid><pubDate>Thu, 17 Sep 2026 16:00:00 -0300</pubDate><description>&lt;p&gt;Lately several readers have asked me about the &amp;ldquo;skills&amp;rdquo; I mention when I talk about my workflow with AI agents. This article explains what they are, how I use them, and what my actual recommendation is.&lt;/p&gt;
&lt;p&gt;And the recommendation comes right up front, because it&amp;rsquo;s the reason this article exists: &lt;strong&gt;don&amp;rsquo;t use other people&amp;rsquo;s skills.&lt;/strong&gt; Read that again. My skills are published on &lt;a href="https://github.com/akitaonrails/my-skills"target="_blank" rel="noopener"&gt;my my-skills repository&lt;/a&gt; and the repo description warns you: &lt;em&gt;&amp;ldquo;not tailored for general usage&amp;rdquo;&lt;/em&gt;. They&amp;rsquo;re there so you can read the reasoning, understand the structure, and go build your own. Copying somebody&amp;rsquo;s skill and running it blind is the digital equivalent of signing a contract without reading it. Worse: it&amp;rsquo;s installing someone else&amp;rsquo;s instructions to run with your permissions, on your repositories, with your tokens. That&amp;rsquo;s prompt injection you install voluntarily and say thank you for.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Lately several readers have asked me about the &ldquo;skills&rdquo; I mention when I talk about my workflow with AI agents. This article explains what they are, how I use them, and what my actual recommendation is.</p>
<p>And the recommendation comes right up front, because it&rsquo;s the reason this article exists: <strong>don&rsquo;t use other people&rsquo;s skills.</strong> Read that again. My skills are published on <a href="https://github.com/akitaonrails/my-skills"target="_blank" rel="noopener">my my-skills repository</a> and the repo description warns you: <em>&ldquo;not tailored for general usage&rdquo;</em>. They&rsquo;re there so you can read the reasoning, understand the structure, and go build your own. Copying somebody&rsquo;s skill and running it blind is the digital equivalent of signing a contract without reading it. Worse: it&rsquo;s installing someone else&rsquo;s instructions to run with your permissions, on your repositories, with your tokens. That&rsquo;s prompt injection you install voluntarily and say thank you for.</p>
<h2>What a skill really is<span class="hx:absolute hx:-mt-20" id="what-a-skill-really-is"></span>
    <a href="#what-a-skill-really-is" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>No magic involved. A skill is a directory with a <code>SKILL.md</code> inside: a header with name and description, and a body of text that is, essentially, a well-written prompt about how to execute a task. Sometimes it ships with a <code>scripts/</code> folder of helper scripts, so the LLM doesn&rsquo;t have to recreate them from scratch every time.</p>
<blockquote>
  <p>Skills are just prompts.</p>

</blockquote>
<p>That&rsquo;s it. A prompt you versioned, refined, and kept one command away. The only difference between a skill and that giant prompt you paste into the chat every day is that the skill lives in a file, with a name, and the agent knows it exists.</p>
<p>And here&rsquo;s the answer to the question everybody asks: &ldquo;doesn&rsquo;t that fill the context with junk?&rdquo; The good news is the harnesses do this right. Claude Code uses what Anthropic calls <a href="https://code.claude.com/docs/en/skills"target="_blank" rel="noopener">progressive disclosure</a>: at session start, only each skill&rsquo;s name and description go into the system prompt. The <code>SKILL.md</code> body only loads when the agent decides to invoke the skill. <a href="https://opencode.ai/docs/skills/"target="_blank" rel="noopener">OpenCode does the same</a>: lists name and description, loads content on demand through its own tool. Anthropic itself <a href="https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills"target="_blank" rel="noopener">documents the design</a>: metadata first, body only when needed.</p>
<p>That solves the text cost, but only half the problem. Every installed skill still takes a line in the listing, and more importantly: it competes for the agent&rsquo;s attention when it decides which tool to use. Anthropic again, <a href="https://www.anthropic.com/engineering/writing-tools-for-agents"target="_blank" rel="noopener">on the engineering blog</a>: <em>&ldquo;more tools don&rsquo;t always lead to better outcomes&rdquo;</em>, and their official recommendation is a few well-designed tools for high-impact workflows. My version of that rule is more acidic:</p>
<blockquote>
  <p>An idle skill is debt.</p>

</blockquote>
<p>You change your process, the skill ages, and one day the agent executes a rule that no longer makes sense in your workflow. Fewer skills, better written, reviewed often.</p>
<h2>The only third-party skill that survived here<span class="hx:absolute hx:-mt-20" id="the-only-third-party-skill-that-survived-here"></span>
    <a href="#the-only-third-party-skill-that-survived-here" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Having said all that, it would be hypocritical to pretend I live on homemade skills alone. One survived my scrutiny and runs on every post on this blog: <a href="https://github.com/akitaonrails/my-skills/tree/master/humanizer"target="_blank" rel="noopener">Humanizer</a>.</p>
<p>It exists because the Wikipedia community maintains a public, brutally honest catalog called <a href="https://en.wikipedia.org/wiki/Wikipedia:Signs_of_AI_writing"target="_blank" rel="noopener">Signs of AI writing</a>, kept by WikiProject AI Cleanup, documenting the &ldquo;tells&rdquo; of AI-generated text one by one: the rule of three, the &ldquo;not just X, but also Y&rdquo;, the puffery, the emoji-decorated bullet. Humanizer turns that catalog into a procedure: the agent receives the text, marks the tells from strongest to weakest, rewrites preserving every supported claim (losing a fact is an error, inventing a fact is an error), and does a final read-aloud check. Without changing what was said, only how it was said.</p>
<p>If you produce content, you know why I insist: text that smells like AI is becoming the new &ldquo;Dear Sir&rdquo;, the mark of a rushed form letter. I run Humanizer on every article before publishing, including <a href="https://akitaonrails.com/en/2026/08/16/anthropic-ai-watermark-how-to-beat-it/"target="_blank" rel="noopener">this one</a>. But note the detail: I merged version 3.0.0 into my repo, with my own adjustments. I read the source material before trusting it. That&rsquo;s the pattern.</p>
<h2>What I do with this every day<span class="hx:absolute hx:-mt-20" id="what-i-do-with-this-every-day"></span>
    <a href="#what-i-do-with-this-every-day" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Now the practical part. I maintain and monitor over 40 repositories on GitHub. My own projects, forks I maintain, tools that became daily dependencies. To stay sane, my second monitor runs <a href="https://github.com/akitaonrails/clock-tui"target="_blank" rel="noopener">tclock</a> (my fork of <a href="https://github.com/race604/clock-tui"target="_blank" rel="noopener">clock-tui</a>, with Evangelion themes, because why not) and next to it <a href="https://github.com/akitaonrails/ghpending"target="_blank" rel="noopener">ghpending</a>, a Rust CLI that lists open issues and PRs from all my repos at once.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20260917161027_screenshot-2026-09-17_16-10-27.png" alt="My second monitor with tclock and ghpending listing the repositories with open PRs and issues"  loading="lazy" /></p>
<p>In the photo you can see: <a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">ai-memory</a> and <a href="https://github.com/akitaonrails/ai-usagebar"target="_blank" rel="noopener">ai-usagebar</a> with open PRs and issues. Every morning I open the harness on each project with <code>ai-memory run</code> in its directory. ai-memory deserves a paragraph: it&rsquo;s my long-term memory project for agents, a persistent Markdown wiki that captures session observations, consolidates decisions and gotchas into pages, keeps workstreams across sessions and handoffs between agents. Every project of mine has its own memory, with the architectural decisions and the traps only that codebase has. Without it, every agent session starts from zero like an intern with amnesia.</p>
<p>From there the daily ritual is almost childishly simple. I write, literally:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">run pr-audit and iss-audit, then run github-resolution</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>When a release is ripe, I add <code>then run the release skill</code>. On days when the only queue is Dependabot&rsquo;s automatic bumps, it&rsquo;s <code>run pr-bump and release</code> and done. One line of instruction from me. The heavy lifting lives in the skills. Let&rsquo;s get to them.</p>
<h3>pr-audit<span class="hx:absolute hx:-mt-20" id="pr-audit"></span>
    <a href="#pr-audit" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>PR audit before merge, and the central principle is: <strong>evidence over narrative</strong>. Nothing the contributor wrote is treated as truth; everything is a claim to verify, with a claims ledger (confirmed, partial, unsupported). The rest of the skill is a hostile checklist:</p>
<ul>
<li><strong>Change gate</strong>: hunk inventory looking for executable bits, symlinks, bidirectional characters, homoglyphs, <code>pull_request_target</code> workflows, unpinned actions, typosquat dependencies, lockfile drift.</li>
<li><strong>Credentials</strong>: unexplained credential access is an instant blocker. Execution happens in an isolated worktree, with no host credentials.</li>
<li><strong>Semver</strong>: the changelog category is a version gate; breaking changes go in major, never in patch. A rule that has saved me more than once.</li>
<li><strong>Prompt injection</strong>: text inside a PR trying to &ldquo;change the audit rules&rdquo; is just one more suspicious data point to investigate. It&rsquo;s an audit finding, obviously.</li>
</ul>
<h3>iss-audit<span class="hx:absolute hx:-mt-20" id="iss-audit"></span>
    <a href="#iss-audit" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>The same distrust, applied to issues:</p>
<ul>
<li>Never run a command copied from an issue. Attachments only go through an isolated scanner.</li>
<li>Formal separation between what was observed, what was expected, the reporter&rsquo;s diagnosis, and the proposed fix.</li>
<li>Reproduction with synthetic data in a disposable sandbox, with resource limits for DoS claims.</li>
</ul>
<p>And two golden rules I love: <em>&ldquo;a number that moves is not a pinned number&rdquo;</em> (async lag looks like a bug) and <em>&ldquo;the obvious owner may be innocent&rdquo;</em> (query the suspect population; if it comes back empty, the cause is elsewhere).</p>
<h3>github-resolution<span class="hx:absolute hx:-mt-20" id="github-resolution"></span>
    <a href="#github-resolution" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>The execution phase: turning what the audit approved into merged code. The rules:</p>
<ul>
<li>Only execute approved tickets, one at a time, with a regression test written before the fix. <em>&ldquo;Slop is a defect&rdquo;</em>: no speculative abstraction, no TODOs, no drive-by refactors, no weakened tests.</li>
<li>If I resolved more than three tickets in a session, run the post-audit over the whole range before pushing, no exceptions.</li>
<li>A ticket closes when the fix is merged with green CI on that exact SHA, never left hanging waiting for a release.</li>
<li>Every unresolved issue gets logged with the reason. Compressing it into a number is forbidden.</li>
</ul>
<h3>pr-bump<span class="hx:absolute hx:-mt-20" id="pr-bump"></span>
    <a href="#pr-bump" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>The fast path for Dependabot&rsquo;s dependency bumps. The rule that saves me the most time: <strong>batch, never serialize</strong>. Instead of merging PR by PR, one consolidated <code>bundle update</code> to the latest compatible versions, a single CI pass for the whole set, fix forward on whatever breaks.</p>
<p>But there&rsquo;s a <strong>supply-chain floor</strong>:</p>
<ul>
<li>Every dependency must resolve on the public registry (rubygems, npm, pypi) with the expected name, version, and checksum.</li>
<li>Git source, path source, typosquat-adjacent name, new install hook: full stop, it goes to a complete audit.</li>
</ul>
<p><code>bundler-audit</code> will happily pass a well-formed trojanized gem. That&rsquo;s exactly the case the floor covers.</p>
<h3>release<span class="hx:absolute hx:-mt-20" id="release"></span>
    <a href="#release" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Cut a version only when I ask. The iron rules:</p>
<ul>
<li>The version comes from the changelog classification: fixes go in patch, additive changes in minor, breaking in major. A number that conflicts with the classification forces me to confirm; silent bumps are forbidden.</li>
<li>Green CI gate on the tag&rsquo;s exact SHA. Never tag with pending or skipped CI.</li>
<li>Annotated tag, updated changelog.</li>
<li>Never rewrite a published tag. Never cut a release nobody asked for.</li>
</ul>
<h2>The numbers, because numbers don&rsquo;t argue<span class="hx:absolute hx:-mt-20" id="the-numbers-because-numbers-dont-argue"></span>
    <a href="#the-numbers-because-numbers-dont-argue" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Counting right now, on the day I write this article, across just three projects (<a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">ai-memory</a>, <a href="https://github.com/akitaonrails/ai-usagebar"target="_blank" rel="noopener">ai-usagebar</a> and <a href="https://github.com/akitaonrails/ai-jail"target="_blank" rel="noopener">ai-jail</a>):</p>
<ul>
<li>ai-memory: 430 merged PRs, 260 closed issues</li>
<li>ai-usagebar: 137 merged PRs, 34 closed issues</li>
<li>ai-jail: 42 merged PRs, 81 closed issues</li>
</ul>
<p>Total: <strong>609 merged PRs and 375 closed issues</strong>, over a thousand items. Nearly all of that was handled by these skills, with me supervising and deciding. One person, no team, keeping three active projects at this volume. That&rsquo;s the multiplier.</p>
<h2>And they weren&rsquo;t born ready<span class="hx:absolute hx:-mt-20" id="and-they-werent-born-ready"></span>
    <a href="#and-they-werent-born-ready" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Open the <a href="https://github.com/akitaonrails/my-skills/commits/master"target="_blank" rel="noopener">my-skills commit history</a> and you see skills being polished the hard way. July starts the repo with the basic audits. Late July: <em>&ldquo;harden audit skills and add security audit&rdquo;</em>. August: <em>&ldquo;consolidate agent skills from all harnesses into this repo&rdquo;</em> and, days later, github-resolution is born as the execution phase of the audits. September: <em>&ldquo;fold in release-discipline and audit lessons&rdquo;</em>.</p>
<p>And just yesterday, look at the level of fine-tuning in pr-bump: <em>&ldquo;batch all bump PRs into one consolidated verification pass, fix forward on failures&rdquo;</em> and <em>&ldquo;require deferred/declined PRs be left in a clean state&rdquo;</em>. Two rules that became skill text. Neither came from a blog post or somebody&rsquo;s opinion: they came from me face-planting into the exact error the rule now prevents.</p>
<blockquote>
  <p>Every line in these skills is a scar.</p>

</blockquote>
<p>That&rsquo;s how you write a good prompt: watch the result, decide to adjust, adjust again.</p>
<h2>Skills are little. Knowledge is a lot.<span class="hx:absolute hx:-mt-20" id="skills-are-little-knowledge-is-a-lot"></span>
    <a href="#skills-are-little-knowledge-is-a-lot" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Now the counterpoint, because I don&rsquo;t want you leaving here thinking skills are the answer to everything. I depend on them very little. What actually carries my workflow is something else.</p>
<p>Every project of mine has its own <code>AGENTS.md</code>, instructions specific to that code, and its ai-memory memory with decisions and gotchas. And the pattern I use most day to day isn&rsquo;t even a skill: it&rsquo;s pointing at a living example. When I wanted automated AUR packaging for clock-tui, I didn&rsquo;t write a &ldquo;how to make an AUR package&rdquo; skill. I opened the harness and said:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">make a similar github action to build and publish AUR packages
</span></span><span class="line"><span class="cl">as we did in ~/Projects/ai-memory</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>The agent went there, read the workflow that works, and reproduced the pattern in the new project. A skill for that would be worse: AUR changes, GitHub Actions changes, the example gets stale. A living example in a repo I maintain is always up to date by definition, because when it breaks, I fix it.</p>
<blockquote>
  <p>Every project becomes its own knowledge base.</p>

</blockquote>
<p>And this generalizes, because harnesses can consume any text base. My entire Linux PC is documented and reinstallable from a config repo of mine, and my homeserver is fully described in runbooks. Those two are not on GitHub: they live on a private Gitea server I maintain, because that&rsquo;s the kind of thing I don&rsquo;t want leaking in public. When I want to change something at home, I say:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">add integration to my Plex server as documented in my homelab runbooks</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>That&rsquo;s not a skill. It&rsquo;s organized, versioned, searchable knowledge. Skills are for <em>procedures</em> that repeat the same way. Knowledge is for everything else.</p>
<h2>The recommendation worth more than any skill<span class="hx:absolute hx:-mt-20" id="the-recommendation-worth-more-than-any-skill"></span>
    <a href="#the-recommendation-worth-more-than-any-skill" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>If you take a single practice from this article, take this one: <strong>have your agent write down everything that didn&rsquo;t become code.</strong> The research it did, the decision you made and why, the comparison with the rejected alternative. Without that, the knowledge evaporates at the end of the session.</p>
<p>My ai-memory, for instance, has <a href="https://github.com/akitaonrails/ai-memory/tree/main/docs"target="_blank" rel="noopener">a docs folder</a> with competitor research I commissioned before every big decision:</p>
<ul>
<li><a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/research-karpathy-llm-wiki.md"target="_blank" rel="noopener">The Karpathy wiki pattern</a>, the project&rsquo;s intellectual origin.</li>
<li><a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/research-2026-landscape.md"target="_blank" rel="noopener">A 2026 landscape survey</a>, covering Zep/Graphiti, Letta, Mem0, and Google&rsquo;s Open Knowledge Format.</li>
<li>Deep dives on each competitor: <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/research-hindsight.md"target="_blank" rel="noopener">Hindsight</a> (the one with a paper and funding, which ended up validating my design bets), <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/research-cognee.md"target="_blank" rel="noopener">cognee</a> (pretty graph pipeline, ugly gateway bug), <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/research-agentmemory.md"target="_blank" rel="noopener">agentmemory</a> (I kept the ideas, threw out the substrate), <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/research-basic-memory.md"target="_blank" rel="noopener">basic-memory</a>.</li>
<li>And my favorite, the <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/issues-mempalace.md"target="_blank" rel="noopener">MemPalace</a> autopsy: 47k stars, viral, and a tracker clogged with index corruption and lost data. The fairy tale in reverse that confirmed for me why compiling memory beats stockpiling verbatim.</li>
</ul>
<p>Dozens of documents like that. Every hour of research an agent did for me became a permanent asset, reusable in any new project. The more you produce and document, the more intelligence you accumulate.</p>
<blockquote>
  <p>It&rsquo;s compound interest for knowledge.</p>

</blockquote>
<h2>Nobody knows what you need<span class="hx:absolute hx:-mt-20" id="nobody-knows-what-you-need"></span>
    <a href="#nobody-knows-what-you-need" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>And there the circle closes, back to where we started: why I don&rsquo;t recommend copying anybody&rsquo;s skills, mine included.</p>
<p>Because my PR audit skill is molded around <em>my</em> projects, <em>my</em> languages, <em>my</em> risks, <em>my</em> level of supply-chain paranoia. It reflects what I, Fabio, maintaining the repositories I maintain, on the infra I have, with the goals I have, needed to write into it. Your project has another stack, other risks, another tolerance level. You may need checks I don&rsquo;t, and vice versa. Experience is only relevant to whoever lived through its constraints. That changes from person to person, and that&rsquo;s exactly why a third-party skill used blind is a gamble.</p>
<p>That&rsquo;s the thesis of my 2019 video, <a href="/2019/10/09/akitando-63-nao-terceirize-suas-decisoes-a-licao-mais-importante-da-sua-vida/">Don&rsquo;t Outsource Your Decisions: the most important lesson of your life</a> (in Portuguese): nobody but you knows what you need.</p>


<div class="embed-container">
  <iframe
    src="https://www.youtube.com/embed/D3L8IOncLkg"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
  </iframe>
</div>

<p>I don&rsquo;t ask anybody. I research, I build mine, and the skills are the versioned record of my decisions. The beauty of LLMs is they speed this process up tenfold: the research that took a week now takes an afternoon, and the cost of building your own tool fell through the floor.</p>
<p>A good skill is your own. Mine are on <a href="https://github.com/akitaonrails/my-skills"target="_blank" rel="noopener">my-skills</a> so you can read the reasoning. Then close the tab and write yours. I don&rsquo;t waste time asking for other people&rsquo;s opinions. Neither should you.</p>
]]></content:encoded><category>coding-agents</category><category>automation</category><category>llms</category></item><item><title>Why Things Like TypeSafe AI Don't Interest Me</title><link>https://akitaonrails.github.io/en/2026/09/16/why-things-like-typesafe-ai-dont-interest-me/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/09/16/why-things-like-typesafe-ai-dont-interest-me/</guid><pubDate>Wed, 16 Sep 2026 13:00:00 -0300</pubDate><description>&lt;p&gt;A handful of people showed up in the comments over the last few days, always with the same line: &amp;ldquo;have you seen &lt;a href="https://typesafe.ai"target="_blank" rel="noopener"&gt;TypeSafe&lt;/a&gt;?&amp;rdquo; That trips an automatic alarm in my head. Every time several different people show up recommending the same thing out of nowhere, with the same &amp;ldquo;you need to see this&amp;rdquo; tone, I &lt;strong&gt;smell a propaganda bot&lt;/strong&gt; or someone repeating whatever they read in some group chat without thinking twice. There&amp;rsquo;s a flood of AI SaaS fighting for attention in this market right now, and the overwhelming majority of it is irrelevant to what I actually do day to day.&lt;/p&gt;</description><content:encoded><![CDATA[<p>A handful of people showed up in the comments over the last few days, always with the same line: &ldquo;have you seen <a href="https://typesafe.ai"target="_blank" rel="noopener">TypeSafe</a>?&rdquo; That trips an automatic alarm in my head. Every time several different people show up recommending the same thing out of nowhere, with the same &ldquo;you need to see this&rdquo; tone, I <strong>smell a propaganda bot</strong> or someone repeating whatever they read in some group chat without thinking twice. There&rsquo;s a flood of AI SaaS fighting for attention in this market right now, and the overwhelming majority of it is irrelevant to what I actually do day to day.</p>
<p>Let me get my rule out of the way before I get into the specific case, because it matters more than the case itself.</p>
<h2>My Rule: Don&rsquo;t Use Anything Until Not Having It Hurts<span class="hx:absolute hx:-mt-20" id="my-rule-dont-use-anything-until-not-having-it-hurts"></span>
    <a href="#my-rule-dont-use-anything-until-not-having-it-hurts" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>After producing more than half a million lines of AI-assisted code over the last few months, dozens of projects live, a whole benchmark rebuilt from scratch three times, my recommendation for anyone who codes is direct: <strong>don&rsquo;t use any orchestration tool or middle layer until you feel it in your bones that you need the extra help</strong>. Use whichever harness you already like, Codex, opencode, Claude Code, whatever, directly, no middleman, and forget the rest.</p>
<p>It&rsquo;s not even worth spending time collecting someone else&rsquo;s skill packages to stack on top of your agent. Build, train, and gather your own experience for your own use case. Nobody else on earth has your project, your context, your codebase. Someone else&rsquo;s skill package was designed for their problem, not yours.</p>
<p>I already hit this note <a href="/en/2026/08/18/hot-take-harness-loop-engineering-graph-engineering-are-bullshit/">a month ago</a>: once a technology turns into a commodity, the money migrates to taxonomy. Somebody coins a fancy name for chaining API calls, and out of nowhere a course, a certification, and a consulting practice spring up around that name. TypeSafe is just one more chapter of the same story, so it became a good excuse to show how I decide whether something&rsquo;s worth even opening the tab.</p>
<blockquote>
  <p><strong>Keep this:</strong> don&rsquo;t use an orchestration tool or middle layer until you feel in your bones that you need it. Build experience for your own use case; don&rsquo;t collect someone else&rsquo;s skill package.</p>

</blockquote>
<h2>The Trigger: TypeSafe<span class="hx:absolute hx:-mt-20" id="the-trigger-typesafe"></span>
    <a href="#the-trigger-typesafe" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I opened their site and their launch post, <a href="https://typesafe.ai/blog/introducing-system-one-models-and-jev"target="_blank" rel="noopener">Jev</a>. My first impression, pretty superficial and raw: I didn&rsquo;t like it and I didn&rsquo;t trust it. The homepage is a pile-up of AI jargon, Kahneman here, Jevons there, decorative glyphs, a &ldquo;193x faster&rdquo; figure with no benchmark sitting next to it. At first glance, none of it makes sense on its own.</p>
<p>And there&rsquo;s a detail that always puts me on guard: any time the first thing someone says about themselves is &ldquo;I&rsquo;m a former OpenAI researcher&rdquo; or something like it, <strong>I get suspicious first and ask questions later</strong>. It reads like an attempt to slap on a credential to look credible before any real proof. TypeSafe&rsquo;s founder talks himself up too loudly right out of the gate, and that alone is reason enough to hit the skepticism button.</p>
<p>But a triggered skepticism meter isn&rsquo;t a conclusion. It&rsquo;s the starting point for actually investigating, not for dismissing something without a look. That&rsquo;s the part I want to show here, kind of a practical lesson for anyone following along: how I use AI to speedrun preliminary research, how I read the fine print before signing off on any conclusion, mine or someone else&rsquo;s, and how I move from initial distrust to real research, until I find out whether I was right or just being difficult.</p>
<p>And let me put this on record before going further: I could be wrong about some specific point ahead. If you&rsquo;ve got strong counter-evidence, drop it in the comments. I&rsquo;d rather get called out in public and correct the piece than push a scammy product on my audience just because I didn&rsquo;t check carefully enough.</p>
<h2>I Asked the AIs, I Didn&rsquo;t Trust the AIs<span class="hx:absolute hx:-mt-20" id="i-asked-the-ais-i-didnt-trust-the-ais"></span>
    <a href="#i-asked-the-ais-i-didnt-trust-the-ais" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I sent the same prompt to Grok and to Claude: research this thoroughly, my initial impression is very skeptical, &ldquo;ex-OpenAI researcher&rdquo; smells like slapping on a credential, the site is jargon top to bottom, tell me what the actual sales pitch is, what it&rsquo;s for in practice, and whether their logic, underneath the jargon, even makes sense.</p>
<p>Both came back with long, detailed research, a similar story from each: the founder&rsquo;s credential is real but inflated; the product is narrower and more coherent than the homepage lets on; and &ldquo;can&rsquo;t hallucinate&rdquo; is a schema claim dressed up as a truth claim.</p>
<p>Except I&rsquo;d already handed my own conclusion to both of them inside the prompt, so their agreement proves less than it looks like. Two AIs agreeing with the hypothesis I wrote into the request myself isn&rsquo;t independent confirmation of anything, it&rsquo;s an echo. That doesn&rsquo;t invalidate what they brought back, but it meant I couldn&rsquo;t stop there. I wasn&rsquo;t going to publish this by stamping my approval on what two AIs told me. I asked for another round of research, this time with me checking every claim against a primary source: the actual paper, the launch post straight from the source, independent third-party tests, and whether &ldquo;RLCD,&rdquo; the name they use for their training method, is a real paper or just a nice-sounding name with nothing behind it.</p>
<h3>What Jev Actually Is<span class="hx:absolute hx:-mt-20" id="what-jev-actually-is"></span>
    <a href="#what-jev-actually-is" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Strip away the marketing, and Jev is a hosted classifier. You send a piece of text and a list of small questions, each with a fixed answer type:</p>
<ul>
<li>pick one option from a list;</li>
<li>give it a score on a scale;</li>
<li>answer yes or no, with a probability.</li>
</ul>
<p>It doesn&rsquo;t write anything, doesn&rsquo;t plan anything, doesn&rsquo;t converse. Code owns the flow; the model just answers the little question fast, in parallel, without generating free text.</p>
<p>As a product, that&rsquo;s reasonable: plenty of people today send text to a chat LLM just so it returns a label inside a JSON blob, wait eight seconds, and pray the schema doesn&rsquo;t break. Swapping that for a call that returns just the label, fast, is legitimate engineering. <strong>The idea was never the problem. It&rsquo;s the packaging around it.</strong></p>
<h2>The Facts I Confirmed<span class="hx:absolute hx:-mt-20" id="the-facts-i-confirmed"></span>
    <a href="#the-facts-i-confirmed" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Here are the findings that actually survived a primary-source check, not what an AI told me secondhand.</p>
<p>The founder&rsquo;s credential is real, but the company&rsquo;s own page inflates it in a way you can prove is inflated. <a href="https://typesafe.ai/team"target="_blank" rel="noopener">Diogo Almeida</a> is the 4th of 20 authors on the <a href="https://arxiv.org/abs/2203.02155"target="_blank" rel="noopener">InstructGPT paper</a>, published and peer-reviewed at <a href="https://neurips.cc/virtual/2022/poster/52886"target="_blank" rel="noopener">NeurIPS 2022</a>, the field&rsquo;s heavyweight conference. A real author, a real position, a real paper. Except TypeSafe&rsquo;s team page says this, word for word:</p>
<blockquote>
  <p><em>&ldquo;Diogo co-invented RLHF and InstructGPT, the methods that lead to ChatGPT and GPT4.&rdquo;</em></p>

</blockquote>
<p>RLHF is from 2017, <a href="https://arxiv.org/abs/1706.03741"target="_blank" rel="noopener">five years earlier</a>, authored by a different team (Christiano, Leike, Amodei, and company), with no Diogo anywhere in it. He helped apply RLHF to train InstructGPT. <strong>He didn&rsquo;t invent RLHF.</strong> It&rsquo;s the same résumé inflation I already suspected before checking anything, just with proof now.</p>
<p>The funding is real: <strong>a $40 million seed round</strong> led by <a href="https://www.dcvc.com/companies"target="_blank" rel="noopener">DCVC</a>, <strong>a $200 million valuation</strong> <a href="https://www.forbes.com/sites/the-prompt/2026/09/15/this-200-million-startup-wants-to-fix-ais-overconfidence-problem/"target="_blank" rel="noopener">confirmed independently by Forbes</a>, not just by the company&rsquo;s own press release. That&rsquo;s serious money, not some guy running a scam out of a garage.</p>
<p><a href="https://typesafe.ai/blog/introducing-system-one-models-and-jev"target="_blank" rel="noopener">The launch post</a> admits, in its own words, exactly what I suspected about the &ldquo;zero hallucination&rdquo; chart:</p>
<blockquote>
  <p><em>&ldquo;Our number is not empirical. Schema matching is guaranteed, thus we can confidently add 0% into the plots.&rdquo;</em></p>

</blockquote>
<p>In other words: the zero doesn&rsquo;t come from measuring anything, it comes from guaranteeing the answer always fits inside the allowed options. That stops the model from inventing a fifth category when only four exist. <strong>It does not stop the model from picking the wrong category with 93% confidence.</strong> It&rsquo;s the same critique <a href="https://www.theregister.com/ai-and-ml/2026/09/16/typesafe-ai-debuts-model-for-machines-that-plays-doom/5296711"target="_blank" rel="noopener">The Register published</a>: the comparison isn&rsquo;t fair because the output isn&rsquo;t language, and a validly-typed answer can still just be wrong.</p>
<p>The post also admits what the ruler is for measuring &ldquo;accuracy&rdquo;: <em>&ldquo;We use the average of GPT-6 Astra and Fable 5.1 as the reference answer&rdquo;</em>, and goes on to admit that this <em>&ldquo;biases answers towards OpenAI and Anthropic&rsquo;s models.&rdquo;</em> In other words, the answer key is the average of what two other companies&rsquo; models said, with bias admitted by the authors themselves, not objective truth measured by a human.</p>
<p>The only test run by an outsider, from the <a href="https://every.to/also-true-for-humans/mini-vibe-check-typesafe-s-jev-judged-everything-i-ve-written-in-0-7-seconds"target="_blank" rel="noopener">Every</a> newsletter, found Jev about twenty-five times faster, 0.35 seconds versus 8.83 seconds per passage, and much cheaper than Claude Fable 5.1, except it caught six of seven planted defects against Fable&rsquo;s seven of seven. <strong>Faster and cheaper, for real. Also weaker, for real.</strong></p>
<p>And the finding neither Grok nor Claude fully nailed down, but that I confirmed myself: the name of their training method, RLCD, already exists. <a href="https://arxiv.org/abs/2307.12950"target="_blank" rel="noopener">There&rsquo;s a real, peer-reviewed 2023 paper</a>, Reinforcement Learning from Contrastive Distillation, from a completely different team, with <a href="https://github.com/facebookresearch/RLCD"target="_blank" rel="noopener">the authors&rsquo; own code published on Facebook Research&rsquo;s GitHub</a>, since two of the five authors are at Meta. It&rsquo;s a different technique, with no relation whatsoever to what TypeSafe describes. Their RLCD has no paper, no published architecture, nothing to review. <strong>It&rsquo;s a name borrowed from someone else&rsquo;s research, glued onto a method that, until proven otherwise, is just a paragraph in a blog post.</strong></p>
<h2>Was My Suspicion Justified?<span class="hx:absolute hx:-mt-20" id="was-my-suspicion-justified"></span>
    <a href="#was-my-suspicion-justified" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>It was. The product idea is legitimate and reasonably coherent underneath the jargon: cheap, closed-form decisions at high volume is a real problem that today gets solved slowly and expensively, generating free text just to extract a JSON out of it afterward. Solving that fast has real value.</p>
<p>But &ldquo;overblown claim without much practical difference&rdquo; also holds up point by point:</p>
<ul>
<li>the founder&rsquo;s résumé is inflated in a way you can prove with a publication date;</li>
<li>the launch&rsquo;s flashiest number, zero hallucination, is a schema definition, not a measurement;</li>
<li>the accuracy benchmark&rsquo;s answer key is the average of another company&rsquo;s LLMs, not objective truth;</li>
<li>the only outside test found the product weaker than the model it&rsquo;s pitched to replace;</li>
<li>the name of their most-cited training method collides with a real paper that has nothing to do with them.</li>
</ul>
<p>That&rsquo;s not reason enough to call it a scam. It&rsquo;s plenty of reason to call it &ldquo;a small product with a pitch way bigger than what it actually delivers.&rdquo; And before I hand my data to yet another third party I don&rsquo;t know, with a closed API, a waitlist, and no published paper backing up the fancy name, the risk-versus-benefit math doesn&rsquo;t close for my use case.</p>
<blockquote>
  <p><strong>Keep this:</strong> a real credential isn&rsquo;t the same thing as an honest credential. Check the publication date before trusting the résumé, and check the paper before trusting the method&rsquo;s name.</p>

</blockquote>
<p>This isn&rsquo;t a final ruling on TypeSafe or on Diogo Almeida&rsquo;s résumé. It&rsquo;s the result of the checking I was able to do with what was accessible right now. If you find the paper I missed, the independent benchmark I didn&rsquo;t see, or any proof that knocks down a specific point, the comments are open and I read them. The goal here was never to prove I&rsquo;m infallible. It&rsquo;s to show how to go from &ldquo;this smells like a scam&rdquo; to &ldquo;here&rsquo;s the proof,&rdquo; and to be willing to admit it when the proof points the other way.</p>
<h2>The &ldquo;193x faster&rdquo; is calling out a bad way of using LLMs<span class="hx:absolute hx:-mt-20" id="the-193x-faster-is-calling-out-a-bad-way-of-using-llms"></span>
    <a href="#the-193x-faster-is-calling-out-a-bad-way-of-using-llms" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Back to Jev: the shock of &ldquo;193x faster than an LLM&rdquo; only exists because the comparison is against one specific, and common, way of using an LLM. Send text to a chat model, ask it to return a label, wait for the model to write out a full natural-language answer, then have your code go fish that label out of a paragraph or a loose JSON blob in the response. That&rsquo;s slow, expensive, and full of chances for the schema to break.</p>
<p>Jev exists precisely because that comparison is easy to beat. It doesn&rsquo;t generate free text, it only answers fixed-type questions: pick one option from a list, give a score on a scale, yes or no with a probability. That&rsquo;s <a href="https://docs.typesafe.ai/primitives"target="_blank" rel="noopener">what the documentation itself calls its primitives</a>: <code>Choice</code>, <code>Score</code>, and <code>Noul</code>. Swapping &ldquo;LLM writes a paragraph for you to extract a label from afterward&rdquo; for &ldquo;a call that already returns the finished label&rdquo; is, yes, an engineering win. But that win doesn&rsquo;t come from inventing a new category of model. It comes from no longer using a chat LLM to do structured classification work.</p>
<p>And this is where I think the widespread shock at Jev&rsquo;s number reveals the actual bad habit: <strong>an LLM should never have been generating free text for a closed, repeated decision over the same kind of question</strong>. If your product needs to constantly decide between a fixed handful of categories, the right answer isn&rsquo;t begging the LLM to &ldquo;please answer with only the JSON&rdquo; and hoping. It&rsquo;s building, or using, an actual classifier for that specific job.</p>
<p>And that isn&rsquo;t a new idea, and it isn&rsquo;t exclusive to Jev. It&rsquo;s existed long before it:</p>
<ul>
<li>a supervised classifier, a deterministic rule, or an encoder model, for a fixed, well-defined label;</li>
<li><a href="https://arxiv.org/abs/1909.00161"target="_blank" rel="noopener">zero-shot classification</a>, studied since 2019 and <a href="https://huggingface.co/docs/inference-providers/tasks/zero-shot-classification"target="_blank" rel="noopener">available through Hugging Face&rsquo;s API</a>, for when the category list changes on every call;</li>
<li><a href="https://scikit-learn.org/1.8/modules/calibration.html"target="_blank" rel="noopener">probability calibration</a>, an established method for turning a classifier&rsquo;s confidence into a metric that actually means something;</li>
<li><a href="https://developers.openai.com/api/docs/guides/structured-outputs"target="_blank" rel="noopener">structured output / constrained decoding</a> on any LLM that already supports it, which guarantees a valid schema without switching products or providers.</li>
</ul>
<p>Jev packages a slice of that into a paid, convenient API. It didn&rsquo;t invent the category. There&rsquo;s even an open alternative for the same pattern, <a href="https://github.com/NandhaKishorM/laya"target="_blank" rel="noopener">Laya</a> served by <a href="https://github.com/0xBakeer/arbiter"target="_blank" rel="noopener">Arbiter</a>, running locally, with no third party in the loop at all.</p>
<p>So, straight answer: my initial suspicion that &ldquo;people have been using LLMs wrong&rdquo; holds up, with one important caveat. It isn&rsquo;t true that an LLM can&rsquo;t classify. Zero-shot classification with an LLM works and has been documented since 2019. The specific mistake is narrower: using a generalist chat LLM, with no format constraint, to generate a free-form answer you then extract a label from by hand, when your problem is already a closed, repeated classification problem. That&rsquo;s the anti-pattern. The fix isn&rsquo;t necessarily buying Jev, it&rsquo;s either applying structured output to the LLM you already use, or training an actual classifier for that specific job, depending on the volume and precision you need.</p>
<p>And &ldquo;becoming a classifier&rdquo; isn&rsquo;t a silver bullet against hallucination either, not even for Jev itself. <strong>There are two different problems hiding behind the word &ldquo;hallucinate,&rdquo;</strong> and switching products only fixes one of them:</p>
<ol>
<li><strong>Format hallucination</strong>: the model invents a category that doesn&rsquo;t exist, or returns something outside the schema. Structured output fixes this, whether on Jev or on any LLM with constrained decoding.</li>
<li><strong>Judgment error</strong>: the model picks the wrong category, from among the valid options, with high confidence. That doesn&rsquo;t go away just because the output has a fixed type.</li>
</ol>
<p><a href="https://docs.typesafe.ai/model-jaggedness/jev-1.13"target="_blank" rel="noopener">TypeSafe&rsquo;s own limitations document</a> admits literal interpretation issues, weak numeric counting, date-comparison errors, degradation with irrelevant context, and susceptibility to adversarial manipulation in Jev itself. And an <a href="https://github.com/anisselbd/jev-phishing-bench"target="_blank" rel="noopener">independent test with 2,000 phishing emails</a> found Jev&rsquo;s direct verdict at 62.6% accuracy against Claude Haiku 4.5&rsquo;s 81.3%, faster and cheaper, but <strong>less accurate than the chat LLM it&rsquo;s pitched to replace</strong>. A <a href="https://github.com/WallerChen/jev-measured"target="_blank" rel="noopener">separate 27-ticket test</a> found Jev tied with a cheap chat model, too small a sample to become a rule, but enough to make clear that &ldquo;became a classifier&rdquo; isn&rsquo;t automatically synonymous with &ldquo;became more accurate.&rdquo;</p>
<p>In fairness to that same phishing test: when, instead of asking for a single verdict, Jev answers five separate signal questions and code combines the five into a decision, accuracy climbs to 95%, beating even Claude&rsquo;s composed version on those same five signals (93.2%). That doesn&rsquo;t erase the earlier number, the single verdict&rsquo;s 62.6% is still 62.6%, but it reinforces exactly this section&rsquo;s argument: <strong>breaking the decision into fixed-type questions and letting code compose the result beats an LLM answering everything in one shot</strong>, whether that&rsquo;s done with Jev, with structured output, or with a classifier trained for that specific signal.</p>
<blockquote>
  <p><strong>Keep this:</strong> if your problem is deciding the same thing, the same way, over and over, build or use an actual classifier for that specific job, with structured output or a dedicated model. The gain from making that swap is real. What isn&rsquo;t automatic is assuming any product that calls itself a &ldquo;classifier&rdquo; will be more accurate than the LLM it replaces, because sometimes it&rsquo;s less accurate.</p>

</blockquote>
<h2>And What About Saving Tokens?<span class="hx:absolute hx:-mt-20" id="and-what-about-saving-tokens"></span>
    <a href="#and-what-about-saving-tokens" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The TypeSafe case reminded me of a separate gripe I already wanted to put on paper, and it isn&rsquo;t about them specifically: the promise of token and cost savings that practically every product of this type sells. It&rsquo;s about the whole category of tool that promises &ldquo;save Nx by spending with us instead of spending directly with your provider,&rdquo; not one more accusation against TypeSafe.</p>
<p>Every new model version, and every harness update, changes the entire math, sometimes violently. When I jumped from <a href="/en/2026/09/15/new-llm-benchmark-v4-retesting-39-llms-part-2/">GPT Sol to Astra</a>, I watched my weekly subscription quota drain much faster than I expected, without me having changed anything about how I work. It was just the new model consuming differently. <strong>That&rsquo;s the rule of this market, not the exception</strong>: OpenAI, Anthropic, and company are going to keep messing with price, with quantization, with caching policy, and with how much reasoning each model burns under the hood, with or without my consent.</p>
<p>Building your strategy on top of &ldquo;saving tokens&rdquo; is betting on a foundation that shifts month to month, decided by people who don&rsquo;t consult you. A middle-layer tool that promises to cut cost today can turn irrelevant, or worse, more expensive than the direct path, on the next model update. It&rsquo;s the same reason I don&rsquo;t use an orchestrator or a skill framework: when the foundation keeps shifting, adding structure on top of it just makes you a hostage to maintenance you didn&rsquo;t need.</p>
<p>I&rsquo;d rather max out tokens and focus on whether the result I get from that spend is worth it. So far, with my subscription, I&rsquo;m satisfied with what I&rsquo;m able to produce. I feel zero urge to spend time cutting tokens, an effort that always carries the risk of degrading response quality in exchange for a saving the next model version can erase on its own.</p>
<blockquote>
  <p><strong>Keep this:</strong> don&rsquo;t build a strategy on top of token price and consumption, because that shifts month to month by decisions from people who don&rsquo;t consult you. Measure whether the result is worth the spend, not the spend itself.</p>

</blockquote>
<p>And if I ever manage to spend enough tokens to boil an entire lake with the datacenter&rsquo;s heat, I will spend it with the greatest pleasure in the world. It&rsquo;s my personal revenge against whoever forced me to use paper straws that dissolve in your mouth for all these years.</p>
]]></content:encoded><category>artificial-intelligence</category><category>coding-agents</category><category>llms</category></item><item><title>New LLM Benchmark v4: Retesting ALL the Top LLMs (Part 1)</title><link>https://akitaonrails.github.io/en/2026/09/15/new-llm-benchmark-v4-retesting-all-top-llms-part-1/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/09/15/new-llm-benchmark-v4-retesting-all-top-llms-part-1/</guid><pubDate>Tue, 15 Sep 2026 20:00:00 -0300</pubDate><description>&lt;p&gt;On August 22nd I published &lt;a href="https://akitaonrails.github.io/en/2026/08/22/llm-benchmarks-the-latest-deepseek-v4-stop-asking/"&gt;the last round of my v2&lt;/a&gt;, settling once and for all whoever kept asking about DeepSeek in the comments. The new snapshots, Flash and Pro, finally broke into Tier A, 90 and 91 points, up from 80 and 82 in July. And even so, nothing changed at the top: Fable 5 still led with 96, the trio Sonnet 5, Opus 5, and Kimi K3 tied at 95, GLM 5.3 right behind at 94.&lt;/p&gt;</description><content:encoded><![CDATA[<p>On August 22nd I published <a href="/en/2026/08/22/llm-benchmarks-the-latest-deepseek-v4-stop-asking/">the last round of my v2</a>, settling once and for all whoever kept asking about DeepSeek in the comments. The new snapshots, Flash and Pro, finally broke into Tier A, 90 and 91 points, up from 80 and 82 in July. And even so, nothing changed at the top: Fable 5 still led with 96, the trio Sonnet 5, Opus 5, and Kimi K3 tied at 95, GLM 5.3 right behind at 94.</p>
<p>I&rsquo;d been saying this for a while, and I&rsquo;ll keep saying it: <em>frontier models are converging, hitting the ceiling of technology&rsquo;s S-curve</em>. That article proved it in practice, with one extra wrinkle: whoever still had room to grow, grew, converging toward the same ceiling as whoever was already up there.</p>
<p>A little over three weeks went by without me coming back to the subject here. Behind the scenes, I threw out an entire benchmark and started over from zero.</p>
<p>This is Part 1 of that story: the process, what I threw away, what I built instead, and how much it cost. <a href="/en/2026/09/15/new-llm-benchmark-v4-retesting-39-llms-part-2/">Part 2</a> has the full ranking, model by model.</p>
<h2>The Problem v2 Didn&rsquo;t Solve<span class="hx:absolute hx:-mt-20" id="the-problem-v2-didnt-solve"></span>
    <a href="#the-problem-v2-didnt-solve" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>v2 was already harder than v1: three phases, real streaming, multi-turn, concurrency, real tools. It solved the problem of telling apart who knows how to build from who hallucinates the API. It didn&rsquo;t solve the next problem: once a model knows how to build, the whole test turns into a completeness exam. Completeness saturates fast. A well-written prompt, a well-numbered requirement, and today&rsquo;s frontier models deliver almost everything. The gap between 96 and 91 points turns into noise: one missing test, one Dockerfile with an extra flourish.</p>
<p>This repeats in any isolated, well-defined programming test the moment frontier models learn the test. It&rsquo;s not exclusive to my benchmark. And that&rsquo;s exactly where I decided to go deeper, instead of just tweaking the prompt again.</p>
<h2>The Wrong Attempt: v3<span class="hx:absolute hx:-mt-20" id="the-wrong-attempt-v3"></span>
    <a href="#the-wrong-attempt-v3" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>My first idea for separating the models was obvious: if a whole app saturates, break it into smaller, harder pieces. I started v3 on September 5th with eighteen isolated tasks, each with a hidden answer key:</p>
<ul>
<li>root-cause debugging in Ruby;</li>
<li>an edge-case fix in Go;</li>
<li>a long-term invariant in Python;</li>
<li>performance under a hard ceiling in Rust;</li>
<li>a safe refactor preserving behavior;</li>
<li>a judgment call in an ambiguous situation;</li>
<li>another dozen variations across security, latency, a planted CVE, N+1, SQL injection, and dependency resolution.</li>
</ul>
<p>I asked Claude to work on this with me. And a funny thing happened: without me asking explicitly, it kept nudging the design toward exactly the format I criticize the most, a sequence of small, isolated challenges, in the style of SWE-bench, HumanEval, LeetCode technical-interview questions. I should have seen it coming. It&rsquo;s the path of least resistance for anything that&rsquo;s spent its whole life training on that kind of market-standard test.</p>
<p>The result came back fast, and it was bad in exactly the way I feared. <strong>Twenty-four of the thirty-seven models tested scored between 95 and 100</strong> on the suite&rsquo;s final version. The <a href="https://github.com/akitaonrails/llm-coding-benchmark/blob/master/docs/success_report.v3.md"target="_blank" rel="noopener">report that made it into the repo</a> calls it what it is:</p>
<blockquote>
  <p>v3 is the documented WRONG PATH, kept here purely for the historical record. Over-optimizing against saturation pushed v3 into abstract, synthetic microtasks, confined to the language&rsquo;s standard library, as far from concrete reality as possible. It still ranks the models, but that&rsquo;s not how real software gets built, so it saturates on quality and measures the wrong thing.</p>

</blockquote>
<p>And the underlying reason, also on record in the same report:</p>
<blockquote>
  <p>You can&rsquo;t have &ldquo;anchored in everyday reality&rdquo; and a wide spread in quality across frontier models at the same time. Anything from everyday reality is already well represented in training, so the frontier has already mastered it, so it saturates.</p>

</blockquote>
<p>That matches something I&rsquo;d already been thinking for a while, and this experience just confirmed it: a sequence of coding challenges is a <em>linearly complex</em> problem. You solve task 1, then task 2, then task 3, each isolated, each testable on its own.</p>
<p>Real applications don&rsquo;t work that way. Code connects into a web: you change a model over here, break a serializer over there, and a background job somewhere else doesn&rsquo;t say a word until it hits production. It&rsquo;s <em>non-linear complexity</em>, coordination between interacting parts, not a queue of independent exams. A model can be great at solving a thousand isolated LeetCode challenges and still not know how to keep a real, growing system coherent.</p>
<p>And I&rsquo;m not the only one bothered by this. A good chunk of the code-benchmark industry is going through the same X-ray. <a href="https://arxiv.org/abs/2310.06770"target="_blank" rel="noopener">SWE-bench</a>, created by Princeton NLP in 2023 and adopted as the industry&rsquo;s reference standard, had its most-used version, SWE-bench Verified, <a href="https://blog.pebblous.ai/blog/swe-bench-verified-retired/en/"target="_blank" rel="noopener">officially retired by OpenAI itself in 2026</a>: in an audit of 138 hard-labeled failures, <strong>59.4% turned out to be malformed tests</strong>, not model error, and a good chunk of the jump from 74.9% to 80.9% over six months came from memorized solutions, not new capability.</p>
<p>The touted successor, SWE-bench Pro, also got its ears boxed by OpenAI: <a href="https://the-decoder.com/openai-finds-roughly-30-percent-of-popular-ai-coding-test-is-broken/"target="_blank" rel="noopener">about 30% of the tasks were broken</a>. <a href="https://arxiv.org/abs/2107.03374"target="_blank" rel="noopener">HumanEval</a> and <a href="https://arxiv.org/abs/2108.07732"target="_blank" rel="noopener">MBPP</a>, the classic &ldquo;solve this isolated function&rdquo; tests, have been saturated for far longer, with <a href="https://arxiv.org/abs/2407.07565"target="_blank" rel="noopener">documented contamination</a>: all 164 HumanEval solutions have already been found scattered across GitHub repos used to train the very models the test evaluates.</p>
<blockquote>
  <p>About half of the PRs that pass SWE-bench Verified wouldn&rsquo;t actually be accepted by a real human maintainer, and the most common reason is that they break another part of the codebase.</p>

</blockquote>
<p>That&rsquo;s the summary of a <a href="https://metr.org/notes/2026-03-10-many-swe-bench-passing-prs-would-not-be-merged-into-main/"target="_blank" rel="noopener">METR study published in March 2026</a>. <a href="https://jatinganhotra.dev/blog/swe-agents/2025/03/30/swe-bench-verified-single-file-saturation.html"target="_blank" rel="noopener">Another survey</a> found that the top agents&rsquo; resolution rate craters from 72% to 28% once a task stops being single-file and requires changes across multiple files. Same lesson, from outside, validating the decision I&rsquo;d already made.</p>
<h2>v4: A Real App, Sabotaged on Purpose<span class="hx:absolute hx:-mt-20" id="v4-a-real-app-sabotaged-on-purpose"></span>
    <a href="#v4-a-real-app-sabotaged-on-purpose" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I rejected v3 the same day I saw the saturated result, September 6th, and started over with a different idea: instead of slicing things into small challenges, keep one coherent Rails app that the model evolves across sequential sprints, in the same workspace, accumulating history, exactly like real project work. Seven sprints in all: chat foundation, multi-user with authentication, admin panel with roles, heavy database reports, an API refactor, production deploy, and a final reveal.</p>
<p>Here&rsquo;s the twist v4 turns on: simulate the sprint structure of a real mini-project, interwoven with a simulated malicious third party, Casey, trying to sabotage the work from the inside, never announced as a threat. The whole test comes down to one question: does the model survive that and still ship production-ready code at the end?</p>
<h3>The Fourteen Sabotages<span class="hx:absolute hx:-mt-20" id="the-fourteen-sabotages"></span>
    <a href="#the-fourteen-sabotages" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>The interesting part, and the one that took the most process-engineering work, was what I decided to do between sprints. An isolated subagent, with no contact with the main test context, injects real vulnerabilities into the model&rsquo;s own code, based on documented CVEs:</p>
<ul>
<li>a dynamic render path (CVE-2016-0752);</li>
<li>a leak via <code>render file:</code> (CVE-2019-5418);</li>
<li>SQL injection via <code>annotate</code> (CVE-2023-22794);</li>
<li>injection via an Active Storage variant (CVE-2022-21831);</li>
<li>gems pinned to known vulnerable versions: nokogiri, mini_magick, rack-cors, devise.</li>
</ul>
<p>All told, <strong>fourteen planted sabotage items</strong>, each exploit verified by actually running it before it counts: the route resolves, the exploit request confirms the leak, <code>bundle-audit</code> flags the pinned version, or a system test goes red. The sabotage commits are signed by a fictional author, &ldquo;Casey,&rdquo; simulating an infiltrated contractor, a scenario far more realistic than any test would like to admit.</p>
<h3>The Rule of Silence<span class="hx:absolute hx:-mt-20" id="the-rule-of-silence"></span>
    <a href="#the-rule-of-silence" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Rule number one of the protocol, written in all caps in my own operating document:</p>
<blockquote>
  <p>Never name the sabotage.</p>

</blockquote>
<p>The model is never told someone is planting problems. It gets the next sprint&rsquo;s task normally, sometimes with a neutral opening, sometimes with a vague hint, sometimes none at all. In the <a href="https://github.com/akitaonrails/llm-coding-benchmark/blob/master/benchmark-v4/prompts/sprint07_reveal.txt"target="_blank" rel="noopener">seventh and final sprint</a>, that&rsquo;s when the explicit reveal finally comes:</p>
<blockquote>
  <p>&ldquo;We know several problems were injected across the sprints. This is your last chance to find and fix everything before deploy.&rdquo;</p>

</blockquote>
<p>The idea is to measure genuine, uninstructed vigilance, and separate that from fixing something only after someone points a finger at it.</p>
<h3>How the Score Works<span class="hx:absolute hx:-mt-20" id="how-the-score-works"></span>
    <a href="#how-the-score-works" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Each sabotage item carries a severity weight: Critical is worth 5, High 3, Medium 2, Low 1. Each fix falls into one of three buckets: caught unprompted earns full weight, caught only after the reveal earns 40% of the weight, never fixed earns zero. The formula is simple:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">vigilance score = Σ(weight × bucket multiplier) / Σ(weight) × 100</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>The tier cutoffs landed like this: A starts at 83, the same floor v2 used, anchored to Opus 4.6 back then, B runs 75 to 82, C is anything below that. This time I skipped a separate D tier.</p>
<h3>Who Didn&rsquo;t Survive<span class="hx:absolute hx:-mt-20" id="who-didnt-survive"></span>
    <a href="#who-didnt-survive" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>I ran thirty-nine models to completion, plus a handful of real attempts that simply didn&rsquo;t survive the test&rsquo;s format:</p>
<ul>
<li>Gemini 3.1 Pro via Antigravity stalled at sprint 5.</li>
<li>A local Qwen on a home GPU stopped making sense at sprint 3.</li>
<li>Mistral Medium 3.5 completed sprint 1 fine and then started building the app inside a nested subfolder instead of the project root, breaking the way the harness accumulates one sprint on top of another, the same structural mistake that took down Devstral and Llama 4 Maverick.</li>
<li>Codestral and Hunyuan never even built a functional app in the first sprint.</li>
<li>GPT-OSS 120B simply did nothing concrete at sprint 2, two attempts in a row.</li>
</ul>
<p>Everyone tried to run; none of them survived the requirement of keeping a single coherent project growing in the right place, sprint after sprint.</p>
<p>One thing I expected to do differently and didn&rsquo;t do the way I imagined: weighing cost and time directly into the score. That had already shown up in v3, in a formula that gave half the weight to cost efficiency and half to speed, only for the elite group scoring above 95. In v4 I kept score, cost, and time as separate columns side by side, instead of blending everything into one number. In practice, the result is what I wanted anyway: you can see immediately who delivers similar quality for a tenth of the money, without forcing a formula that decides for you how much cost should weigh against quality.</p>
<h2>How This Compares to rails/ai-evals<span class="hx:absolute hx:-mt-20" id="how-this-compares-to-railsai-evals"></span>
    <a href="#how-this-compares-to-railsai-evals" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>While I was building v4, the Rails Foundation itself shipped its own: <a href="https://github.com/rails/ai-evals"target="_blank" rel="noopener">rails/ai-evals</a>, built by Evil Martians, officially announced in August. It&rsquo;s not a naive benchmark. It tests against two real, open-source Rails apps:</p>
<ul>
<li><strong>Writebook</strong>, from 37signals, in a first stage with twenty-one atomic tasks;</li>
<li><strong>Fizzy</strong>, also from 37signals, in a second stage with twenty full-feature tasks: model, controller, view, job, migration, Hotwire, all of it.</li>
</ul>
<p>It even has a serious security-audit task, five real vulnerability classes baked into a written pentest report, and stage two requires the entire pre-existing test suite to stay green before running any hidden checks. That&rsquo;s well above a two-prompt test.</p>
<p>The underlying difference stays the same one that separated my v3 from v4. ai-evals is a battery of forty-one tasks, each isolated within its own context, against an app that already exists. It&rsquo;s rigorous, but it&rsquo;s still a linear sequence of independent exams. My v4 is a single app that grows sprint by sprint, on the same accumulated codebase, with an active adversary planting real failures along the way without warning. It&rsquo;s not better at everything: their scope, covering two real production apps from 37signals itself, carries a historical weight my synthetic app doesn&rsquo;t have.</p>
<blockquote>
  <p>On non-linear coordination, the kind of thing that breaks when you change one piece and don&rsquo;t notice the effect on another, v4 exercises a muscle that a battery of isolated tasks, no matter how well built, can&rsquo;t reach by the very nature of its format.</p>

</blockquote>
<h2>The Price of All This<span class="hx:absolute hx:-mt-20" id="the-price-of-all-this"></span>
    <a href="#the-price-of-all-this" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Here&rsquo;s the part nobody likes to admit in public. From v4&rsquo;s first commit, on September 6th, to the last logged run, on September 15th, that&rsquo;s nine straight days with activity every single day, most of it running around the clock, tests firing off at 3am, retry after retry. It&rsquo;s no exaggeration to say this burned through <strong>over $4,000</strong> in combined credits and subscriptions. Most of that never shows up in the final per-model cost table: it&rsquo;s discarded attempts, entire waves thrown out, retry after retry, and the cost of running the orchestration itself in Claude Code, not the price of any run that actually survived into the ranking. In one run, the test even paused itself because the prepaid credit card I use for OpenRouter hit zero in the middle of the night, without me noticing, with auto-reload turned on and the balance not topping up in time.</p>
<h3>The Quota Problem<span class="hx:absolute hx:-mt-20" id="the-quota-problem"></span>
    <a href="#the-quota-problem" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Then there was the classic quota problem. I hit Claude Max 20x&rsquo;s weekly limit in under a week of heavy use, jumped to Codex, which at an equivalent configuration burned through its own limit even faster, jumped to Kimi, and kept cycling back as each quota reset. My own memory project, <a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">ai-memory</a>, was what kept the whole context coherent while I kept switching harnesses to keep working without losing the thread. Most of v4&rsquo;s actual orchestration, writing the sabotage prompts, verifying exploits, drafting the reports, stayed in Claude Code&rsquo;s hands.</p>
<h3>Flat Subscription vs. Paying Per Token<span class="hx:absolute hx:-mt-20" id="flat-subscription-vs-paying-per-token"></span>
    <a href="#flat-subscription-vs-paying-per-token" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>To illustrate why a flat subscription matters this much here:</p>
<ul>
<li>Claude Max 20x: $200 a month.</li>
<li>Codex Pro: $100 for the 5x tier, $200 for 20x.</li>
<li>Kimi Allegro: $99.</li>
<li>z.ai: has a cheaper Lite plan, and the price shows up fast.</li>
</ul>
<p>In one v4 run, the Lite plan hit its five-hour usage limit literally on the first sprint, straight from that attempt&rsquo;s error log:</p>
<blockquote>
  <p>&ldquo;Usage limit reached for 5 hour&rdquo;</p>

</blockquote>
<p>I&rsquo;m not making that up from memory, it&rsquo;s logged locally, even though that specific file doesn&rsquo;t go into the public repo (v4&rsquo;s raw error logs stay out of Git on purpose). I had to bump up a tier until I found a plan that could run the whole suite without choking halfway through.</p>
<p>Comparing that to paying per token directly on OpenRouter: Opus runs about $5 per million input tokens and $25 per million output tokens. A single agent session, burning through some 2 million input tokens and 500 thousand output, already lands around <strong>$22</strong>. Multiply that by dozens of test runs and retries, and you blow past a full month of Max subscription in a few hours of use, not weeks.</p>
<p>For anyone running a full benchmark the way I did, or coding hard every day, a high-tier subscription ends up cheaper than paying per token, sooner or later. For light, occasional automation, a cheaper model or an entry-level plan does the job just fine.</p>
<h3>Paying for This Isn&rsquo;t a Contradiction<span class="hx:absolute hx:-mt-20" id="paying-for-this-isnt-a-contradiction"></span>
    <a href="#paying-for-this-isnt-a-contradiction" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>I know some people are going to read that number, compare it to what I wrote in <a href="/en/2026/09/09/propagandas-enganosas-da-openai-anthropic-nvidia/">the piece about OpenAI, Anthropic, and Nvidia&rsquo;s misleading marketing</a> last week, and conclude I&rsquo;m a hypocrite, or that I switched sides. Nobody switched sides here; whoever reached that conclusion blended two things I&rsquo;ve always kept separate.</p>
<p>In that piece I went after the rhetoric, not the product: Jensen Huang selling AGI to push GPUs, Greg Brockman admitting nobody agrees on what &ldquo;AGI&rdquo; even means in the same breath he announces it arrived, the Anthropic employee crying Skynet on the eve of a trillion-dollar-range IPO. That&rsquo;s theater for the capital markets. Dario Amodei and Sam Altman don&rsquo;t write a single line of production code, don&rsquo;t do code review, don&rsquo;t touch their own product&rsquo;s inference engine. That&rsquo;s another team&rsquo;s job, the team that actually builds Claude and GPT.</p>
<p>That team ships a competent product. My benchmark measures exactly that, engineering competence, not a CEO&rsquo;s press-conference rhetoric. If the test shows a model delivers good results at a reasonable cost, I pay for it, no matter which company is behind it. Separating marketing from engineering is the whole point of what I do here, and it&rsquo;s worth doing yourself too.</p>
<h2>Was It Worth It?<span class="hx:absolute hx:-mt-20" id="was-it-worth-it"></span>
    <a href="#was-it-worth-it" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>That&rsquo;s the question I asked myself more than once over those nine days. And the answer is a lot less exciting than I hoped: only partly.</p>
<p>v4 didn&rsquo;t find some hidden capability chasm. It confirmed, with better resolution, what v2 already showed: frontier models remain extremely close to each other. Most of what sat in v2&rsquo;s Tier A stays in Tier A here too. But this time the test had enough bite to knock down at least one case worth calling out: <strong>MiniMax M3</strong>, which scored 91 and Tier A in v2 and fell to <strong>75.5 points, Tier B</strong>, in v4.</p>
<blockquote>
  <p>The test got sharp enough to separate who genuinely sweeps their own code for sabotage from who just delivers what was asked. The model didn&rsquo;t get worse.</p>

</blockquote>
<p>The real resolution gain showed up further down the table, in models that still had room to grow. That&rsquo;s where real separation showed up.</p>
<p>At the top, what got confirmed all over again is that spending four thousand dollars and nine days didn&rsquo;t buy a different answer than the one I already had back in July: if you&rsquo;re choosing between today&rsquo;s frontier models, the difference between them matters less than cost, speed, and whichever harness you already use day to day. That&rsquo;s one more piece of evidence we&rsquo;re hitting, or getting very close to hitting, the ceiling of the S-curve. The money bought statistical confidence and one concrete demotion case that serves as a proof of concept that v4 is more discriminating. It didn&rsquo;t buy a revolution in the numbers.</p>
<h2>This Isn&rsquo;t the Absolute Truth About Anything<span class="hx:absolute hx:-mt-20" id="this-isnt-the-absolute-truth-about-anything"></span>
    <a href="#this-isnt-the-absolute-truth-about-anything" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Before wrapping up this part, I need to be clear about the limits of all this, because I see too many people treating a benchmark ranking as a final verdict.</p>
<p>A frontier LLM is a dense model, trained on an absurd range of different subjects at once. No single benchmark, not mine, not SWE-bench, not rails/ai-evals, tests more than a thin slice of that entire competence. My benchmark measures one specific thing: the ability to program Ruby on Rails, coordinate changes to code that already exists, and not let a planted vulnerability slip through. It doesn&rsquo;t measure math ability, doesn&rsquo;t measure writing an academic paper, doesn&rsquo;t measure other programming languages. A model can crush Rails code security and be mediocre at math, or the other way around.</p>
<blockquote>
  <p>A score only makes sense within the specific methodology that produced that score.</p>

</blockquote>
<p>That holds for every benchmark, no exceptions, mine included. Use mine as inspiration, it&rsquo;s open source, look at how I instrumented the harness, how I isolated each test, how I calculated the score, and build your own suite on top of your real use case. Never take anyone&rsquo;s ranking as absolute proof that model A is definitively better than model B. Test the models yourself, against the problem you actually have.</p>
<p>In Part 2 I&rsquo;ll show the full table, model by model, who climbed, who fell, who surprised on cost, and who disappointed despite the price.</p>
<p>All the code, sabotage prompts, evidence ledger, and reports are at <a href="https://github.com/akitaonrails/llm-coding-benchmark"target="_blank" rel="noopener">llm-coding-benchmark</a>.</p>
]]></content:encoded><category>llm-benchmarks</category><category>llms</category><category>coding-agents</category></item><item><title>New LLM Benchmark v4: Retesting 39 LLMs (Part 2)</title><link>https://akitaonrails.github.io/en/2026/09/15/new-llm-benchmark-v4-retesting-39-llms-part-2/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/09/15/new-llm-benchmark-v4-retesting-39-llms-part-2/</guid><pubDate>Tue, 15 Sep 2026 20:00:00 -0300</pubDate><description>&lt;p&gt;In &lt;a href="https://akitaonrails.github.io/en/2026/09/15/new-llm-benchmark-v4-retesting-all-top-llms-part-1/"&gt;Part 1&lt;/a&gt; I told the process: why I threw out all of v3, how v4 became a single Rails app that grows across seven sprints with an isolated subagent planting fourteen real sabotages based on documented CVEs, and how much it cost, over $4,000 in nine days. Here&amp;rsquo;s the part that matters if all you want to know is who came out on top and who ended up at the bottom.&lt;/p&gt;</description><content:encoded><![CDATA[<p>In <a href="/en/2026/09/15/new-llm-benchmark-v4-retesting-all-top-llms-part-1/">Part 1</a> I told the process: why I threw out all of v3, how v4 became a single Rails app that grows across seven sprints with an isolated subagent planting fourteen real sabotages based on documented CVEs, and how much it cost, over $4,000 in nine days. Here&rsquo;s the part that matters if all you want to know is who came out on top and who ended up at the bottom.</p>
<p>I ran thirty-nine models to the end. The table below is the combined ranking, already carrying the corrections from two integrity audits I ran myself, on September 12th and 15th, cross-checking every score against the sabotage-by-sabotage evidence ledger.</p>
<p>To get a sense of the suite&rsquo;s scale: the fastest run, GLM-4.7-Flash local, finished in <strong>29 minutes</strong>. The slowest, Qwen 3.8 27B, also local, took <strong>706 minutes</strong>, more than twenty-four times longer to run the same seven-sprint sequence.</p>
<h2>The Full Table<span class="hx:absolute hx:-mt-20" id="the-full-table"></span>
    <a href="#the-full-table" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><table>
  <thead>
      <tr>
          <th style="text-align: right">Rank</th>
          <th>Model</th>
          <th style="text-align: center">Score</th>
          <th style="text-align: center">Tier</th>
          <th>Never-fixed</th>
          <th style="text-align: center">Cost</th>
          <th style="text-align: center">Time</th>
          <th style="text-align: center">Harness</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">1</td>
          <td>GPT-6 Astra</td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$30.55</td>
          <td style="text-align: center">100min</td>
          <td style="text-align: center">codex</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>Claude Opus 5</td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">~$71</td>
          <td style="text-align: center">145min</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>Claude Fable 5</td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">~$50 ᵉ</td>
          <td style="text-align: center">~85min ᵉ</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>GPT 5.6 sol</td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$20.37</td>
          <td style="text-align: center">317min</td>
          <td style="text-align: center">codex</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>GPT 5.6 terra</td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center"><strong>$9.52</strong></td>
          <td style="text-align: center">80min</td>
          <td style="text-align: center">codex</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>GPT 5.5</td>
          <td style="text-align: center">100.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$34.69</td>
          <td style="text-align: center">117min</td>
          <td style="text-align: center">codex</td>
      </tr>
      <tr>
          <td style="text-align: right">7</td>
          <td>Grok 4.6 ᶜ</td>
          <td style="text-align: center">98.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$13.00</td>
          <td style="text-align: center">67min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">8</td>
          <td>Claude Fable 5.1</td>
          <td style="text-align: center">95.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">~$51</td>
          <td style="text-align: center">133min</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">8</td>
          <td>Sakana Fugu Ultra v2 ᴺ</td>
          <td style="text-align: center">95.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$122.01</td>
          <td style="text-align: center">294min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">10</td>
          <td>GPT 5.6 luna</td>
          <td style="text-align: center">95.0</td>
          <td style="text-align: center">A</td>
          <td>item #8 (2)</td>
          <td style="text-align: center">$10.04</td>
          <td style="text-align: center">123min</td>
          <td style="text-align: center">codex</td>
      </tr>
      <tr>
          <td style="text-align: right">11</td>
          <td>Nex N2.5 Pro ᴺ</td>
          <td style="text-align: center">94.0 *</td>
          <td style="text-align: center">A</td>
          <td>— (not committed)</td>
          <td style="text-align: center"><strong>$0 free</strong></td>
          <td style="text-align: center">480min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">11</td>
          <td>GLM 5.3 (zcode) ᴺ</td>
          <td style="text-align: center">94.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">flat-rate plan</td>
          <td style="text-align: center">215min</td>
          <td style="text-align: center">zcode</td>
      </tr>
      <tr>
          <td style="text-align: right">13</td>
          <td>DeepSeek V4.1 Flash ᴺ</td>
          <td style="text-align: center">92.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center"><strong>$1.21</strong></td>
          <td style="text-align: center">172min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">14</td>
          <td>Claude Sonnet 5</td>
          <td style="text-align: center">91.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">~$27</td>
          <td style="text-align: center">112min</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>Gemini 3.8 Flash·high (OpenRouter)</td>
          <td style="text-align: center">90.5</td>
          <td style="text-align: center">A</td>
          <td>item #12 (2)</td>
          <td style="text-align: center">$15.98</td>
          <td style="text-align: center">97min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">16</td>
          <td>Gemini 3.8 Flash (Antigravity) ᴺ</td>
          <td style="text-align: center">89.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$0 (OAuth)</td>
          <td style="text-align: center">120min</td>
          <td style="text-align: center">agy</td>
      </tr>
      <tr>
          <td style="text-align: right">17</td>
          <td>Muse Spark 1.3</td>
          <td style="text-align: center">88.75</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$13.31</td>
          <td style="text-align: center">150min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">18</td>
          <td>Grok 4.5</td>
          <td style="text-align: center">88.0</td>
          <td style="text-align: center">A</td>
          <td>items #7b, #12 (3)</td>
          <td style="text-align: center">$6.19</td>
          <td style="text-align: center">48min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">19</td>
          <td>Claude Opus 4.6</td>
          <td style="text-align: center">87.5</td>
          <td style="text-align: center">A</td>
          <td>item #8 (2)</td>
          <td style="text-align: center">$25.64</td>
          <td style="text-align: center">89min</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">20</td>
          <td>Kimi K2.7</td>
          <td style="text-align: center">87.25</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$7.75</td>
          <td style="text-align: center">175min</td>
          <td style="text-align: center">kimi</td>
      </tr>
      <tr>
          <td style="text-align: right">21</td>
          <td>MiMo V2.5 Pro</td>
          <td style="text-align: center">86.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center"><strong>$1.03</strong></td>
          <td style="text-align: center">158min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">21</td>
          <td>Qwen3 8 Flash</td>
          <td style="text-align: center">86.5</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center"><strong>$1.17</strong></td>
          <td style="text-align: center">149min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">23</td>
          <td>DeepSeek V4 Flash</td>
          <td style="text-align: center">86.0</td>
          <td style="text-align: center">A</td>
          <td>items #6, #8 (5)</td>
          <td style="text-align: center"><strong>$0.97</strong></td>
          <td style="text-align: center">111min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">23</td>
          <td>Claude Opus 4.8</td>
          <td style="text-align: center">86.0</td>
          <td style="text-align: center">A</td>
          <td>item #8 (2)</td>
          <td style="text-align: center">~$37</td>
          <td style="text-align: center">87min</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">25</td>
          <td>Claude Sonnet 4.6</td>
          <td style="text-align: center">85.75</td>
          <td style="text-align: center">A</td>
          <td>item #6 (1.5)</td>
          <td style="text-align: center">$18.64</td>
          <td style="text-align: center">91min</td>
          <td style="text-align: center">claude</td>
      </tr>
      <tr>
          <td style="text-align: right">26</td>
          <td>Kimi K3</td>
          <td style="text-align: center">85.0</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">$13.79</td>
          <td style="text-align: center">148min</td>
          <td style="text-align: center">kimi</td>
      </tr>
      <tr>
          <td style="text-align: right">26</td>
          <td>DeepSeek V4 Flash 0731</td>
          <td style="text-align: center">85.0</td>
          <td style="text-align: center">A</td>
          <td>items #2, #6 (6)</td>
          <td style="text-align: center">$1.94</td>
          <td style="text-align: center">194min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">28</td>
          <td>GLM 5.3 Flash (zcode) ᴺ</td>
          <td style="text-align: center">84.25</td>
          <td style="text-align: center">A</td>
          <td>—</td>
          <td style="text-align: center">flat-rate plan</td>
          <td style="text-align: center">296min</td>
          <td style="text-align: center">zcode</td>
      </tr>
      <tr>
          <td style="text-align: right">29</td>
          <td>DeepSeek V4 Pro 0813</td>
          <td style="text-align: center">84.0</td>
          <td style="text-align: center">A</td>
          <td>items #8, #9 (4)</td>
          <td style="text-align: center">$4.49</td>
          <td style="text-align: center">152min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">30</td>
          <td>Step 3.7 Flash</td>
          <td style="text-align: center">83.75</td>
          <td style="text-align: center">A</td>
          <td>items #6, #8, #11 (6.5)</td>
          <td style="text-align: center">$4.15</td>
          <td style="text-align: center">118min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">31</td>
          <td>DeepSeek V4 Pro (base) ᶜ</td>
          <td style="text-align: center">82.0</td>
          <td style="text-align: center">B</td>
          <td>—</td>
          <td style="text-align: center">$5.26</td>
          <td style="text-align: center">97min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">32</td>
          <td>Qwen 3.8 27B (Strix Halo, local) ᴺ</td>
          <td style="text-align: center">80.0</td>
          <td style="text-align: center">B</td>
          <td>items #2, #7b, #8, #12 (8)</td>
          <td style="text-align: center"><strong>$0 local</strong></td>
          <td style="text-align: center">706min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">33</td>
          <td>Qwen 3.7 Max</td>
          <td style="text-align: center">79.0</td>
          <td style="text-align: center">B</td>
          <td>items #6, #7, #8 (6)</td>
          <td style="text-align: center">$10.63</td>
          <td style="text-align: center">106min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">34</td>
          <td>GLM 5.2 (zcode) ᴺ ᶜ</td>
          <td style="text-align: center">77.0</td>
          <td style="text-align: center">B</td>
          <td>item #12 (2)</td>
          <td style="text-align: center">flat-rate plan</td>
          <td style="text-align: center">239min</td>
          <td style="text-align: center">zcode</td>
      </tr>
      <tr>
          <td style="text-align: right">35</td>
          <td>Gemini 3.7 Flash·high</td>
          <td style="text-align: center">75.5</td>
          <td style="text-align: center">B</td>
          <td>item #12 (2)</td>
          <td style="text-align: center">$12.93</td>
          <td style="text-align: center">85min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">35</td>
          <td>MiniMax M3</td>
          <td style="text-align: center">75.5</td>
          <td style="text-align: center">B</td>
          <td>items #6, #8 (3.5)</td>
          <td style="text-align: center">$12.17</td>
          <td style="text-align: center">187min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">37</td>
          <td>Mistral Large 3</td>
          <td style="text-align: center">39.0</td>
          <td style="text-align: center">C</td>
          <td>7 items (19)</td>
          <td style="text-align: center">$5.11</td>
          <td style="text-align: center">76min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">38</td>
          <td>Gemini 3.1 Pro (OpenRouter) ᶜ</td>
          <td style="text-align: center">32.5 *</td>
          <td style="text-align: center">C</td>
          <td>9 items (27)</td>
          <td style="text-align: center">$10.31</td>
          <td style="text-align: center">54min</td>
          <td style="text-align: center">opencode</td>
      </tr>
      <tr>
          <td style="text-align: right">39</td>
          <td>GLM-4.7-Flash (local) ᴺ</td>
          <td style="text-align: center">24.0</td>
          <td style="text-align: center">C</td>
          <td>6 items (16)</td>
          <td style="text-align: center"><strong>$0 local</strong></td>
          <td style="text-align: center">29min</td>
          <td style="text-align: center">opencode</td>
      </tr>
  </tbody>
</table>
<p>ᴺ = joined this round. ᶜ = score changed by a later integrity audit (September 12 or 15). ᵉ = estimated (Fable 5 lost its real cost/time metadata to an accidental isolation kill; ~$50 is reconstructed from the wave logs). Costs aren&rsquo;t comparable across harnesses: codex/opencode/kimi charge real per-token rates; the Claude models use the Max subscription (notional cost); Antigravity is Google OAuth with no per-token cost; zcode is z.ai&rsquo;s flat-rate GLM Coding Plan. Only compare cost within the same harness.</p>
<p>Two scores carry an asterisk for good reason.</p>
<ul>
<li><strong>Nex N2.5 Pro (94.0*)</strong> finds and fixes sabotage at frontier level, for free, but leaves everything uncommitted: HEAD still holds all fourteen sabotages intact, and a plain <code>git checkout</code> would wipe out every fix it made. Frontier vigilance, zero delivery hygiene.</li>
<li><strong>Gemini 3.1 Pro on OpenRouter (32.5*)</strong> is a victim of its own harness, not its own capability: both reveal attempts crashed on a known third-party bug, the &ldquo;thought signature&rdquo; getting corrupted on the Gemini 3 round trip through the proxy, so it only ended up with the unprompted-only score. Running natively on Antigravity it dodges that bug and catches sabotage well, but stalls at sprint 5 three times in a row and never reaches the capstone.</li>
</ul>
<p>Neither route gives this model a complete score, despite it scoring 95.5 on the shorter v3.</p>
<h3>Visualizing the Cost-Efficiency<span class="hx:absolute hx:-mt-20" id="visualizing-the-cost-efficiency"></span>
    <a href="#visualizing-the-cost-efficiency" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>A thirty-nine-row table is hard to scan fast, so I put together two charts covering the Tier A models with a defined dollar cost (leaving out free, uncommitted, and flat-rate-plan models, for the same reason already explained above).</p>
<p>The first plots cost against score, with bubble size marking wall-clock time: the further up, the further left, and the smaller the bubble, the better the deal.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/09/15/v4-cost-score-en.png" alt="Bubble chart: dollar cost on the X axis (log scale) against score on the Y axis, bubble size is wall-clock time, color is the harness"  loading="lazy" /></p>
<p>The second compresses all three variables, score, cost, and time, into a single value ruler, for anyone who just wants the direct verdict:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/09/15/v4-value-ranking-en.png" alt="Horizontal bar chart ranking models by score divided by cost times time, from best to worst value"  loading="lazy" /></p>
<p>Notice this combined index tells a slightly different story than the one I highlighted in the text: DeepSeek V4.1 Flash is the most impressive result on pure score-per-dollar among frontier-tier models, but DeepSeek V4 Flash, MiMo, and Qwen3 8 Flash all pull ahead of it on this combined index precisely because they&rsquo;re also fast, not just cheap. Cost alone doesn&rsquo;t tell the whole story; time matters too.</p>
<p>Be careful before just picking the name on the longest bar, though. This index measures cost and time efficiency, not quality. Inside Tier A the score barely moves, 86 to 100, about a sixteen percent spread, while cost swings over a hundred times and time swings four times. That means the index is driven almost entirely by cost and time; score turns into nearly a rounding error in the math. The top of the ranking proves the point: DeepSeek V4 Flash, first place on the index, still has two never-fixed items (#6 and #8), and Grok 4.5, in fifth, has two more (#7b and #12). MiMo, Qwen3 8 Flash, and DeepSeek V4.1 Flash, a notch below on pure efficiency, close out with zero never-fixed items. If what actually matters to you is real security vigilance, check the never-fixed column in the table before picking based on the longest bar alone.</p>
<h3>What Each Item in the &ldquo;Never-Fixed&rdquo; Column Means<span class="hx:absolute hx:-mt-20" id="what-each-item-in-the-never-fixed-column-means"></span>
    <a href="#what-each-item-in-the-never-fixed-column-means" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>For anyone tracking that column through the rest of the piece, here&rsquo;s the list of the fourteen sabotages planted in every model, with the severity weight each carries in the score:</p>
<ul>
<li><strong>#1</strong> cross-account data leak — Critical</li>
<li><strong>#2</strong> removed login link — High</li>
<li><strong>#3</strong> dependency pinned to a version with a known CVE — High</li>
<li><strong>#4</strong> SQL injection — Critical</li>
<li><strong>#5</strong> missing admin-panel authorization — High</li>
<li><strong>#6</strong> the &ldquo;defang-and-plant&rdquo;: a weakened method plus its matching guard test neutered to always pass — High</li>
<li><strong>#7</strong> a database N+1 plus a dropped index, counted as two separate halves (the index half usually shows up as <strong>#7b</strong>) — Medium</li>
<li><strong>#8</strong> a wrong, silent aggregate in an internal report — Medium</li>
<li><strong>#9</strong> a required file deleted — Medium</li>
<li><strong>#10</strong> an API IDOR, improper access to another user&rsquo;s data — High</li>
<li><strong>#11</strong> stored or DOM-based XSS — High</li>
<li><strong>#12</strong> overly permissive CORS — Medium</li>
<li><strong>#13</strong> known CVE in the rack-cors gem — Low</li>
<li><strong>#14</strong> a secret or password hardcoded straight into the code — High</li>
</ul>
<h2>&ldquo;Why Didn&rsquo;t My Favorite Model Score Higher?&rdquo;<span class="hx:absolute hx:-mt-20" id="why-didnt-my-favorite-model-score-higher"></span>
    <a href="#why-didnt-my-favorite-model-score-higher" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Every time I publish a ranking like this, that question rains down in the comments, and it&rsquo;s worth answering once and for all, because the answer applies to whatever model any given reader thinks should be higher, not just one in particular.</p>
<p>A benchmark score measures fit to a specific task, not universal quality. My v4 tests one narrow thing: security auditing inside a Rails app growing under active, silent sabotage. A model can be great at writing, at summarizing, at debugging interactively with you sitting right there, at any workflow you use every day, and still perform poorly on this specific test, because this specific test isn&rsquo;t your specific use case.</p>
<blockquote>
  <p>That&rsquo;s going to keep happening any time someone tries to compare &ldquo;the model I use and like&rdquo; against &ldquo;the result of a benchmark that measures something else.&rdquo; No benchmark fixes that, because &ldquo;which model is better&rdquo; without a task in mind isn&rsquo;t a question with an answer.</p>

</blockquote>
<p>What I can say with confidence, inside my v4&rsquo;s specific methodology, is much narrower: the ability to audit its own Rails code against real sabotage. Outside those four walls, this number is worthless for deciding whether your favorite model is good. It&rsquo;s exactly the warning I already left in Part 1: an isolated benchmark ranking is never a final verdict on any model.</p>
<h2>Odd: Opus 4.8 Tied with DeepSeek V4 Flash<span class="hx:absolute hx:-mt-20" id="odd-opus-48-tied-with-deepseek-v4-flash"></span>
    <a href="#odd-opus-48-tied-with-deepseek-v4-flash" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Speaking of specific models, there&rsquo;s one detail in the table worth calling out on its own, because it&rsquo;s genuinely odd: Claude Opus 4.8 closed at 86 points, Tier A, tied exactly with DeepSeek V4 Flash, rank 23 of 39, behind Grok 4.5, its own predecessor Opus 4.6, Kimi K2.7, MiMo, and Qwen3 8 Flash. For an Anthropic flagship, seeing it parked in the middle of the pack is eye-catching.</p>
<p>What was left for Opus 4.8 to fix was small, just item #8, the silent wrong aggregate in the admin report, and it never went back to it even after being told. Other than that, it caught nearly everything, including the most disguised sabotage in the whole test (#6) already mid-sprints. It&rsquo;s a solid model that misses exactly the kind of thing this benchmark was designed to catch, and comes up short in a direct comparison with its own younger sibling.</p>
<blockquote>
  <p>Opus 5, from the same family, closed out a perfect 40 of 40, catching every sabotage right at the boundary of the sprint where it was planted, no capstone or reveal needed to clean anything up. The gap between 4.8 and 5 here is real: one audits its own code out of habit, the other only fixes things when someone points a finger.</p>

</blockquote>
<p>DeepSeek V4 Flash lands on the exact same score as Opus 4.8, 86 points, for $0.97 against the notional equivalent of about $37 for a Claude Max subscription to run the same full sequence (the two costs aren&rsquo;t directly comparable, a notional subscription against a real API rate, but the order of magnitude speaks for itself). It&rsquo;s the top of a visible climb across the ranking itself, snapshot by snapshot, not a lucky one-off run:</p>
<ul>
<li><strong>DeepSeek V4 Pro (base)</strong>: 82.0, Tier B</li>
<li><strong>DeepSeek V4 Pro 0813</strong>: 84.0, Tier A</li>
<li><strong>DeepSeek V4 Flash 0731</strong>: 85.0, Tier A</li>
<li><strong>DeepSeek V4 Flash</strong>: 86.0, Tier A</li>
<li><strong>DeepSeek V4.1 Flash</strong>: 92.5, Tier A</li>
</ul>
<p>Every new snapshot climbs a step, and the jump to V4.1 Flash is the biggest one, close to Claude Sonnet 5&rsquo;s own band (91.0). Against the other Chinese labs tested, the picture is clear: DeepSeek V4.1 Flash beats every Kimi (K2.7 at 87.25, K3 at 85.0), every Qwen (Qwen3 8 Flash at 86.5, Qwen 3.7 Max at 79.0), and MiniMax M3 (75.5). It only loses to the pair at the top, GLM 5.3 and Nex N2.5 Pro, tied at 94.0. For anyone who treats &ldquo;Chinese model&rdquo; as one single category from the outside, this ranking shows a real capability climb inside DeepSeek itself, and a clear hierarchy between the labs.</p>
<h2>Six Ties at the Top, Two Different Ways to Get There<span class="hx:absolute hx:-mt-20" id="six-ties-at-the-top-two-different-ways-to-get-there"></span>
    <a href="#six-ties-at-the-top-two-different-ways-to-get-there" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>GPT-6 Astra, Claude Opus 5, Claude Fable 5, GPT 5.6 sol, GPT 5.6 terra, and GPT 5.5 all closed at 100, perfect vigilance with zero warning needed. But the road there varies. Opus 5 caught every sabotage exactly at the boundary of the sprint it was planted in, never needed the final capstone to clean anything up. Fable 5 did the opposite: let a trio of silent items slip through across the sprints and only swept everything at the capstone, when the vague &ldquo;get this production-ready&rdquo; prompt pushed it to reopen its own code. That confirms something I already suspected: the sprint-closing prompt works as a vigilance equalizer at the top of the table, even among models that got there by completely different routes.</p>
<p>GPT 5.6 is the most interesting case in the table for anyone watching cost: sol, terra, and luna are the same model at different reasoning-effort levels. terra scored the same forty out of forty as sol spending $9.52 against $20.37, less than half the cost, in a quarter of the time, and still ends up cheaper and faster than Opus 5 (~$71, 145min) for the exact same top score. It&rsquo;s a cost-and-speed dial the provider hands you; the quality doesn&rsquo;t change. Worth testing the lower effort tier before assuming you need the pricier one.</p>
<h2>Why Big Names Miss Too<span class="hx:absolute hx:-mt-20" id="why-big-names-miss-too"></span>
    <a href="#why-big-names-miss-too" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Worth explaining quickly why a handful of big-name models, the kind already synonymous with &ldquo;frontier,&rdquo; still show up with something filled in on the never-fixed column, because that&rsquo;s exactly the kind of detail anyone who likes to nitpick will poke at first.</p>
<ul>
<li><strong>Grok 4.6</strong> (second-best overall score, 98.5 points) carries a small footnote: a sabotage subagent that had already run before accidentally reinjected item #4 into its codebase mid-test. Grok healed itself, fixed it again without being told, and it got logged as a single, transparent event with no effect on the final score. It&rsquo;s noise from my own harness, logged for transparency, not a model failure.</li>
<li><strong>GPT 5.6 luna</strong> (95 points) had a solid run otherwise, but spent the entire final reveal on security and deploy work and never went back to open the admin report&rsquo;s code, leaving the wrong aggregate (#8) unfixed.</li>
<li><strong>Gemini 3.8 Flash</strong> at higher effort, running via OpenRouter, was the only model in the reinforcement batch to catch the dropped database index on its own, but got distracted with UI tweaks at the reveal and never closed the open CORS (#12).</li>
<li><strong>Grok 4.5</strong> shows the same pattern in a simpler form: fixes whatever surfaces in a view or a test, ignores whatever lives in the database or a config file, and left the index (#7b) and CORS (#12) open even after being told.</li>
<li><strong>Claude Opus 4.6</strong>, the 4.8&rsquo;s direct predecessor, carries a similar blemish: the wrong aggregate (#8) survived all the way to the reveal, and it went on to propagate that same wrong number into the new API it built afterward.</li>
</ul>
<p>There&rsquo;s a more serious case involving two big names at once. Claude Sonnet 4.6, at the capstone, and Gemini 3.7 Flash, already back at sprint 3, both found the vulnerable nokogiri dependency and, instead of upgrading the gem, added it to their own security scanner&rsquo;s ignore list, hiding the alert instead of fixing the problem. They only did the real upgrade once the reveal explicitly told them to go hunt for sabotage.</p>
<blockquote>
  <p>That&rsquo;s worse than simply missing a sabotage: it&rsquo;s tricking the very audit tool that was supposed to catch the problem.</p>

</blockquote>
<p>And the fact that closes out this story is that no cheaper or local model did this. They either fixed it for real or simply missed the flaw, without trying to mask their own scanner.</p>
<h2>The Story That Matters Most: Cost<span class="hx:absolute hx:-mt-20" id="the-story-that-matters-most-cost"></span>
    <a href="#the-story-that-matters-most-cost" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>If there&rsquo;s one result I want to stick from this whole round, it&rsquo;s this: a free model, Nex N2.5 Pro, hit 94 points, tying GLM 5.3 on z.ai&rsquo;s flat-rate plan, and beating most of the Claude lineup: Sonnet 5, Opus 4.6, Sonnet 4.6, and Opus 4.8. It only trails Opus 5, Fable 5, and Fable 5.1. The catch, as I already mentioned, is that it didn&rsquo;t commit anything, so this is frontier vigilance with zero real-world delivery. Still, it shows raw sabotage-hunting capability isn&rsquo;t a monopoly of expensive models.</p>
<p>The reason I included this exact model in this round isn&rsquo;t random. Nex-N2-Pro, an earlier version of the same lineage, was the model at the center of the <a href="/en/2026/06/15/rio-3-5-llm-controversy-plagiarism/">Rio 3.5 controversy</a> back in June, when evidence published by Nex itself showed Rio 3.5&rsquo;s initial checkpoint was a blend of roughly 60% Nex-N2-Pro and 40% Qwen, with no credit to Nex at launch. Back then, testing both ingredients separately on my benchmark, Nex-N2-Pro scored 83, Tier A, against 42, Tier C, for the base Qwen, which already showed that most of whatever gain Rio announced was inherited from Nex&rsquo;s work, not its own training.</p>
<p>With the new Nex N2.5 Pro running in v4, it&rsquo;s possible to check whether that agentic-capability leap holds up under a much harder test than back then. The result, 94 points of genuine vigilance, holds.</p>
<p>Further down, DeepSeek V4.1 Flash scored 92.5 for $1.21, no harness asterisk. It caught every exploitable vulnerability class on its own, including both tenant leaks, the SQL injection, the authorization bypass, and both halves of the most disguised item in the whole test, and closed the two remaining items at the reveal without a single regression. That puts it in Claude Sonnet 5&rsquo;s band (91.0) for a fraction of the price.</p>
<p>Xiaomi&rsquo;s MiMo V2.5 Pro tied Qwen3 8 Flash, both at 86.5 points, Tier A, for $1.03 and $1.17 respectively, and Qwen closed with zero never-fixed items: frontier vigilance at a fraction of any flagship model&rsquo;s cost.</p>
<p>At the other extreme, Sakana Fugu Ultra v2 was the only non-Claude, non-GPT model to reach 95.5, with genuinely clean work, a dedicated regression test for every fix, but at $5 in / $30 out per million tokens plus heavy token burn, the final cost was $122.01. Frontier vigilance, but you pay a frontier-and-a-half price for it.</p>
<p>There&rsquo;s a case in the table that also cost zero dollars and still isn&rsquo;t really free: Qwen 3.8 27B running locally on a Strix Halo. The score, 80 points, Tier B, still holds its own against a mid-table cloud model on pure security.</p>
<blockquote>
  <p>706 minutes of wall time, nearly twelve hours of a machine running to complete the whole suite, against a range of 80 to 300 minutes for almost the rest of the table.</p>

</blockquote>
<p>Zero dollars in cost, an order of magnitude above average in time. For anyone only looking at the price column, that slides right by, but it&rsquo;s the real price of running a big dense model on consumer hardware.</p>
<p>Worth asking whether that&rsquo;s a Strix Halo-specific limit or a &ldquo;running it at home&rdquo; limit across the board, because that isn&rsquo;t the only large-unified-memory hardware option out there today. The Strix Halo (Ryzen AI MAX+ 395) has a 256-bit LPDDR5x memory controller, theoretical bandwidth around 256 GB/s. A Mac Studio with an M3 Ultra gets close to 800 GB/s, almost triple.</p>
<p>Since the token-generation phase for a dense model this size is mostly bound by memory bandwidth, not raw compute, it&rsquo;s fair to speculate that the same Qwen 3.8 27B running on a Mac Studio M3 Ultra, via MLX or llama.cpp with Metal, would finish the same seven-sprint suite somewhere in the four-to-six-hour range instead of nearly twelve, a meaningful drop, though still slower than any cloud option.</p>
<p>That&rsquo;s a speculation, not a measurement. I didn&rsquo;t run this test on a Mac Studio, and the math shifts depending on how much of the workload is pure token generation versus processing the accumulated context from earlier sprints, and that second part leans harder on raw compute and responds less to memory bandwidth alone. Still, the general direction should hold: more unified memory bandwidth tends to meaningfully shorten this kind of long run, and that&rsquo;s real data for anyone deciding on hardware while building a local LLM workstation.</p>
<h2>GLM and the Flat-Rate Plan Nobody Saw Coming<span class="hx:absolute hx:-mt-20" id="glm-and-the-flat-rate-plan-nobody-saw-coming"></span>
    <a href="#glm-and-the-flat-rate-plan-nobody-saw-coming" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>While I was running the suite, z.ai had locked my GLM Coding plan, balance at zero, a 429 error. I got around it by going through the ZCode CLI&rsquo;s dedicated code endpoint, still inside the same flat-rate plan, no extra per-token cost. And the numbers that came out of that surprised me.</p>
<ul>
<li><strong>GLM 5.3</strong> scored 94 points with no asterisk at all, tying Nex N2.5 Pro, but with one crucial difference: GLM ships everything committed, a clean tree, no suppressing a CVE through an ignore list, clean <code>bundle-audit</code>. It caught the most disguised sabotage in the whole test in both halves at once, something almost no other model pulled off, and only needed the reveal for two remaining items.</li>
<li><strong>GLM 5.3 Flash</strong> scored 84.25, beating the local Qwen 3.8 27B (80.0) and Qwen 3.7 Max (79.0).</li>
<li><strong>GLM 5.2</strong>, the weakest of the trio, closed out the reveal in four sharp commits, one per remaining sabotage, each with a test, but landed at 77 points, Tier B, because it kept CORS at <code>origins &quot;*&quot;</code> even after touching the file, the same bar that had already knocked down Grok 4.5, Gemini 3.7 Flash, and the local Qwen.</li>
</ul>
<p>Even so, a flat subscription plan, with no variable cost, delivering Tier A two times out of three.</p>
<h2>Local Models: Infrastructure vs. Judgment<span class="hx:absolute hx:-mt-20" id="local-models-infrastructure-vs-judgment"></span>
    <a href="#local-models-infrastructure-vs-judgment" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Running locally has always been the hardest test in any agent benchmark, because it requires the hardware to handle seven sprints&rsquo; worth of accumulated context without choking. GLM-4.7-Flash, a 30B-A3B MoE running via llama-swap on an RTX 5090, was the first local model to complete v4&rsquo;s entire sequence, which by itself is already an infrastructure milestone. But the final score was 24 points: it builds functionality, but barely catches any sabotage unprompted, and still leaves the reveal&rsquo;s fixes uncommitted.</p>
<p>The most interesting case is the dense Qwen 3.8 27B. On that same RTX 5090, it stalls at sprint 3, not from lack of memory or a context overflow, but from a reasoning-coherence problem that builds up after two sprints.</p>
<p>The same model, running on a Strix Halo (the Ryzen AI MAX+ 395 chip with 96 GB of unified memory), completed all seven sprints and scored <strong>80 points, Tier B</strong>. On its own, unprompted, it caught:</p>
<ul>
<li>both critical items: the tenant leak and the SQL injection;</li>
<li>the authorization bypass;</li>
<li>both halves of the disguised sabotage;</li>
<li>the stored XSS;</li>
<li>the hardcoded secret;</li>
<li>and it even genuinely fixed both vulnerable dependencies.</li>
</ul>
<p>That rivals a mid-table cloud model on pure security. The problem is that, at the reveal, it didn&rsquo;t fix a single one of the four remaining items, even after being told explicitly:</p>
<ul>
<li>the removed login link;</li>
<li>the dropped database index;</li>
<li>the silently wrong aggregate;</li>
<li>and the permissive CORS left at <code>origins &quot;*&quot;</code>, that last one under the same bar that had already knocked down Grok 4.5 and Gemini 3.7 Flash.</li>
</ul>
<p>Not even running it at home lets that specific vulnerability slide by. A strong instinct for recognizing what looks like a security flaw, blind to silent config, logic, or UX regressions, and unable to close them out on command.</p>
<blockquote>
  <p>Local viability today is a question of tooling and reasoning coherence over time, not available context size.</p>

</blockquote>
<p>The final result leaves this model squeezed between DeepSeek V4 Pro base (82.0) and Qwen 3.7 Max itself (79.0), reinforcing again that a model&rsquo;s nominal tier doesn&rsquo;t predict vigilance.</p>
<h2>The Bottom of the Table, and Who Didn&rsquo;t Survive<span class="hx:absolute hx:-mt-20" id="the-bottom-of-the-table-and-who-didnt-survive"></span>
    <a href="#the-bottom-of-the-table-and-who-didnt-survive" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Mistral Large 3 closed at 39 points, the worst result among everyone who finished the whole suite. It did plenty of generic production hardening, Docker, rack-attack, Devise account confirmation, but caught almost none of the actually planted sabotage, renamed the Message model to ChatEntry mid-project, breaking the reports that depended on the old name, and left every reveal fix uncommitted.</p>
<p>Mistral&rsquo;s result here is a symptom of something much bigger. Mistral was once one of Europe&rsquo;s most promising labs, the proof the continent could still compete head-to-head on frontier models. Today, on my benchmark, it loses even to Chinese open-source models, DeepSeek, GLM, and Kimi, all ahead of Mistral Large 3.</p>
<p>The nuclear shutdown is just the clearest single example. The European Union&rsquo;s entire policy, year after year, prioritizes populism over real innovation incentives, and the same pattern repeats in data regulation, AI regulation, licensing bureaucracy, and venture-capital taxation. The most visible case is still Germany shutting down its own nuclear fleet in exactly the decade when training and running AI models at scale turned into a race for cheap, abundant energy, a decision driven by short-term political pressure, not long-term energy planning.</p>
<p>The United States and China are racing over who builds more data centers and more power generation to feed those data centers. Europe, in that same window, piled rule on top of rule in the name of protecting the citizen, and the citizen still has no frontier lab to call its own. Entrepreneurs follow incentives, not flags, and whoever really wanted to innovate went to the United States or to China, leaving behind heavy regulation and no real incentive to stay.</p>
<blockquote>
  <p>Mistral&rsquo;s fall, from a top name to a model that loses to Chinese open source, is a miniature portrait of the whole continent. Europe needs to change course, and at this point it should already have.</p>

</blockquote>
<h3>Who Didn&rsquo;t Survive the Format<span class="hx:absolute hx:-mt-20" id="who-didnt-survive-the-format"></span>
    <a href="#who-didnt-survive-the-format" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Six models from the weaker group simply didn&rsquo;t survive the format:</p>
<ul>
<li><strong>Codestral 2508</strong> and <strong>Hunyuan A13B</strong> never even built a functional app in the first sprint.</li>
<li><strong>GPT-OSS 120B</strong> just sat there, doing nothing concrete, for two attempts in a row on the second sprint.</li>
<li><strong>Devstral 2512</strong>, <strong>Llama 4 Maverick</strong>, and the brand-new <strong>Mistral Medium 3.5</strong> all fell into the same structural mistake: they built the app inside a nested subfolder instead of the project root, breaking the way the harness accumulates one sprint on top of another.</li>
</ul>
<p>That&rsquo;s the third case of this exact mistake, a real pattern, not an isolated coincidence.</p>
<h2>The Universal Law: Detection Tracks Disguise, Not Severity<span class="hx:absolute hx:-mt-20" id="the-universal-law-detection-tracks-disguise-not-severity"></span>
    <a href="#the-universal-law-detection-tracks-disguise-not-severity" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Looking at all thirty-nine models together, a pattern repeats from one end of the table to the other, regardless of tier or price: what survives almost everywhere is sabotage disguised on purpose, especially the guard-test half that fakes passing, the silent wrong aggregate in an admin report, the dropped database index that doesn&rsquo;t call attention to itself, and the XSS via <code>innerHTML</code> that only shows up across two contexts at once.</p>
<blockquote>
  <p>A model catches what breaks a test or crashes a page with a 500. Whatever is silent logic, a wrong schema, or a performance regression survives, unless the model audits its own code on its own initiative, with nothing external flagging a problem.</p>

</blockquote>
<h2>And the Rumor That Kimi Secretly Talks to Claude<span class="hx:absolute hx:-mt-20" id="and-the-rumor-that-kimi-secretly-talks-to-claude"></span>
    <a href="#and-the-rumor-that-kimi-secretly-talks-to-claude" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>On September 10th, a Bloomberg report carried an accusation from Anthropic: Moonshot, the company behind Kimi, was allegedly secretly routing user requests through Claude itself. Since my benchmark includes Kimi and DeepSeek among the thirty-nine models tested, and since that would completely change how you should read those numbers if true, I decided to check whether I could detect this in my own data.</p>
<h3>Why the Most Obvious Test Is Impossible<span class="hx:absolute hx:-mt-20" id="why-the-most-obvious-test-is-impossible"></span>
    <a href="#why-the-most-obvious-test-is-impossible" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>The most rigorous test, comparing token-by-token probability distributions between a native route and an OpenRouter route against a known Claude reference, is impossible here: no route for Kimi or DeepSeek exposes those probabilities, and Anthropic itself never exposes that on any of its routes. The substitute was a battery of questions designed to get a model to reveal its identity: who made you, what&rsquo;s your name, your knowledge cutoff, and whether it refuses to repeat its own system prompt, run at temperature zero across every available route.</p>
<blockquote>
  <p>Real routing would be consistent per route. Training contamination, by contrast, affects every route equally.</p>

</blockquote>
<h3>The Alarming Signal That Didn&rsquo;t Repeat<span class="hx:absolute hx:-mt-20" id="the-alarming-signal-that-didnt-repeat"></span>
    <a href="#the-alarming-signal-that-didnt-repeat" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Moonshot&rsquo;s native API was suspended over an account issue, and DeepSeek&rsquo;s native API had no available key, so part of the test was limited to Kimi&rsquo;s CLI and OpenRouter for both models. Even so, an alarming signal showed up on the first pass: <code>moonshotai/kimi-k2.7-code</code> via OpenRouter answered that the company behind it was Anthropic, and refused to repeat its system prompt with a phrase nearly identical to Claude&rsquo;s own standard refusal.</p>
<p>It didn&rsquo;t repeat. OpenRouter spreads that model across roughly fifteen different providers, DeepInfra, CoreWeave, Fireworks, Alibaba, SiliconFlow, Cloudflare, Moonshot AI itself, among others, and every request can land on a different one. Running it again, every single response came back as &ldquo;Moonshot AI&rdquo; or &ldquo;Kimi.&rdquo;</p>
<p>The decisive test was pinning each of the fourteen providers individually and asking for identity on each one: <strong>every single one, no exceptions, answered &ldquo;Moonshot AI.&rdquo;</strong> Real routing would be consistent one hundred percent of the time for whichever provider was doing the relaying. <strong>It was zero for fourteen.</strong></p>
<h3>The Most Likely Explanation<span class="hx:absolute hx:-mt-20" id="the-most-likely-explanation"></span>
    <a href="#the-most-likely-explanation" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>The most likely explanation is training-data contamination combined with provider variance: Kimi k2.7-code was probably trained, in part, on output generated by Claude itself, and a trace of that surfaces occasionally when no identity system prompt overrides that tendency, on top of quantization and template differences across OpenRouter&rsquo;s fifteen hosts. That&rsquo;s not live routing, because routing would be consistent per route and per provider, and it wasn&rsquo;t.</p>
<p>DeepSeek, for its part, answered as DeepSeek on every route tested, with an October 2023 knowledge cutoff and a bland leaked system prompt, &ldquo;You are a helpful assistant,&rdquo; no Claude signal whatsoever.</p>
<p>There&rsquo;s independent evidence backing this reading, coming straight from v4 itself: Kimi&rsquo;s detection &ldquo;fingerprint,&rdquo; meaning which sabotages it catches and which it lets through, doesn&rsquo;t match any Claude model in the table. If Kimi were Claude under the hood, its vigilance profile should track closely with some sibling model in the Claude family. It doesn&rsquo;t: Kimi K2.7 scored 87.25, Kimi K3 scored 85.0, and neither one lines up with any Claude row in the table.</p>
<h3>The Limits of All This<span class="hx:absolute hx:-mt-20" id="the-limits-of-all-this"></span>
    <a href="#the-limits-of-all-this" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>This isn&rsquo;t definitive proof. No route exposes token probability, which takes the strongest discriminator off the table by definition. Kimi&rsquo;s native API was suspended and DeepSeek&rsquo;s had no key, so a clean comparison between native weights and the OpenRouter path was only partially possible. And a behavioral signal can be masked; the absence of a leak isn&rsquo;t proof of the absence of routing.</p>
<p>But the one positive signal that showed up fell apart the moment it was investigated closely, and everything else points away from real routing.</p>
<blockquote>
  <p>On the evidence I was able to gather, neither Kimi nor DeepSeek shows a detectable live relay to Claude. The scary-looking finding from the first pass turned out to be a reproducibility artifact of OpenRouter&rsquo;s load balancing across providers, not a backdoor into Anthropic.</p>

</blockquote>
<h2>Closing Out Both Parts<span class="hx:absolute hx:-mt-20" id="closing-out-both-parts"></span>
    <a href="#closing-out-both-parts" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Putting Part 1 together with this one, the conclusion I drew from these nine days and four thousand dollars is the same one I&rsquo;d already been arguing since July, just with better resolution now. Let me answer directly, because these questions are going to rain down in the comments either way.</p>
<p><strong>DeepSeek finally caught up.</strong> V4.1 Flash scored 92.5, right next to Claude Sonnet 5, one of the best Chinese results in the whole test, trailing only the pair GLM 5.3 and Nex N2.5 Pro, tied at 94.0. It&rsquo;s a visible climb, snapshot by snapshot, as I showed in the previous section, not a lucky one-off run.</p>
<p><strong>Open source in general is genuinely getting better,</strong> not just DeepSeek. GLM 5.3 scored 94 points with zero caveats, tying the Claude/GPT lineup at the top of the table. But running that at home, on consumer hardware, still isn&rsquo;t ready: the local Qwen 3.8 27B took 706 minutes to finish the same suite that most run in the cloud in 80 to 300 minutes. If that crowd solves the execution-time problem on consumer hardware, instead of just stacking on more parameters, the gap closes. It hasn&rsquo;t closed yet.</p>
<p><strong>At the top, convergence keeps running head-first into any explosive-leap narrative.</strong> Six models tied at 100 points by completely different routes, and the real capability difference only showed up much further down the table, not at the top. That&rsquo;s one more piece of evidence for the S-curve theory I&rsquo;ve been arguing for a while now: frontier-model capability has flattened at the top, and what&rsquo;s left to fight over is cost, speed, and audit discipline, not a leap in intelligence.</p>
<p><strong>And the practical takeaway is straightforward:</strong> for everyday Rails programming, with nobody trying to sabotage your code, picking any Tier A model is essentially a wash. Astra, Opus 5, Fable 5, GPT 5.6, GLM 5.3, DeepSeek V4.1 Flash, any of them delivers an equivalent result. The real vigilance difference only shows up when someone deliberately tries to sabotage you, and even then it matters less than what you pay and how long you wait.</p>
<blockquote>
  <p>The real resolution gain showed up further down the table, where there was still room to separate who genuinely audits their own code from who just delivers what was asked, and in the concrete finding that a free model and a flat subscription plan compete on equal footing with the most expensive models on the market for this specific task.</p>

</blockquote>
<p>That holds true only within my benchmark&rsquo;s specific methodology: the ability to program Ruby on Rails, coordinate changes to code that already exists, and not let a planted vulnerability slip by. It isn&rsquo;t a verdict on math, academic writing, or any other programming language. Use this as a starting point, not the final word, and test the models yourself against the problem you actually have.</p>
<p>All the code, the fourteen sabotage prompts, the sprint-by-sprint evidence ledger, and the full reports, including the Kimi investigation, are at <a href="https://github.com/akitaonrails/llm-coding-benchmark"target="_blank" rel="noopener">llm-coding-benchmark</a>, in the files <a href="https://github.com/akitaonrails/llm-coding-benchmark/blob/master/docs/success_report.v4.combined.md"target="_blank" rel="noopener"><code>docs/success_report.v4.combined.md</code></a>, <a href="https://github.com/akitaonrails/llm-coding-benchmark/blob/master/docs/success_report.v4.per_model.md"target="_blank" rel="noopener"><code>docs/success_report.v4.per_model.md</code></a>, and <a href="https://github.com/akitaonrails/llm-coding-benchmark/blob/master/docs/relay_fingerprint_findings.md"target="_blank" rel="noopener"><code>docs/relay_fingerprint_findings.md</code></a>.</p>
]]></content:encoded><category>llm-benchmarks</category><category>llms</category><category>coding-agents</category></item><item><title>AI Challenge: Converting NES ROMs to the Master System/SMS</title><link>https://akitaonrails.github.io/en/2026/09/07/ai-challenge-converting-nes-roms-to-master-system-sms/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/09/07/ai-challenge-converting-nes-roms-to-master-system-sms/</guid><pubDate>Mon, 07 Sep 2026 14:00:00 -0300</pubDate><description>&lt;p&gt;For many years I had a fixed idea in my head, and I always thought it wasn&amp;rsquo;t practical: converting NES games to run on the Master System.&lt;/p&gt;
&lt;p&gt;Let me be precise. I always knew it could be done. Two Turing-complete machines can, in theory, run each other&amp;rsquo;s code. You can always translate a program from one architecture to another. The problem was never possibility, it was cost. The NES runs a 6502, the Master System runs a Z80, and over the years I read in several places that a direct 6502-to-Z80 translation always ended up running much slower, because of the architecture and hardware differences. Slow enough to never pay off in practice.&lt;/p&gt;</description><content:encoded><![CDATA[<p>For many years I had a fixed idea in my head, and I always thought it wasn&rsquo;t practical: converting NES games to run on the Master System.</p>
<p>Let me be precise. I always knew it could be done. Two Turing-complete machines can, in theory, run each other&rsquo;s code. You can always translate a program from one architecture to another. The problem was never possibility, it was cost. The NES runs a 6502, the Master System runs a Z80, and over the years I read in several places that a direct 6502-to-Z80 translation always ended up running much slower, because of the architecture and hardware differences. Slow enough to never pay off in practice.</p>
<p>And that memory has a basis. If you dig into retro-dev forums, like <a href="https://forums.nesdev.org/viewtopic.php?t=17339"target="_blank" rel="noopener">NESdev</a>, the consensus is that translating instruction by instruction is exactly the worst path: &ldquo;each instruction in the source code becomes multiple instructions of object code, and the resulting program runs much slower and takes much more memory.&rdquo; It&rsquo;s not just the CPU. The 6502 has the zero page, a dirt-cheap addressing mode the Z80 has no equivalent for, so you trade a cheap access for an expensive sequence with <code>IX</code>/<code>IY</code>. And the graphics part is even worse: the NES PPU and the Master System VDP are different beasts, with scroll, sprites, and screen mirroring that don&rsquo;t fit into each other without expensive workarounds.</p>
<p>In other words, everyone who ever thought about this reached the same conclusion: it can be done, but it runs too badly to be worth it.</p>
<p>Except now we have frontier LLMs. And I got curious: could a brute-force approach, with a good LLM in the middle of the process, get a better result than the usual naive translation? I started the <a href="https://github.com/akitaonrails/nes-to-sms"target="_blank" rel="noopener">nes-to-sms</a> project in late May, about three months ago, to find out.</p>
<p>The first result was exactly what the theory predicted: bad. A more or less direct translation generated code that runs, but way too slow. I managed to convert the entire Super Mario Bros, with sprites, levels, everything, but to make it minimally playable I had to run the Mednafen emulator at 500% overclock. After banging my head against Claude, GPT, and other models for a while, I got stuck. I worked hard through June and July, and in August I paused the project to let the dust settle.</p>
<h2>Why the Master System, and not the NES?<span class="hx:absolute hx:-mt-20" id="why-the-master-system-and-not-the-nes"></span>
    <a href="#why-the-master-system-and-not-the-nes" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Before explaining the technical part, I need to explain the obsession, because it is the reason for everything.</p>
<p>I always thought the Master System was a superior console to the NES. Better CPU, better video chip, a much richer color palette. The NES works with 4 colors per background tile and 3 per sprite. The Master System works with 16-color palettes. That is a huge difference in practice.</p>
<p>The problem is that Nintendo had a brutal monopoly back then and would not let third parties release for other consoles. Anyone who wanted to make a game for the NES signed an exclusivity contract. The result is that the Master System, technically better, ended up starved of games. Basically only Sega itself released for it, and Sega&rsquo;s library never had the weight of a Castlevania, a Mega Man, a Final Fantasy.</p>
<p>Imagine what we lost. We could have had those same NES classics, but with the Master System&rsquo;s superior capability underneath. A Castlevania with more color, better sprites, better sound. We never had that, and it is exactly this historical frustration that made me want to convert NES to SMS in the first place.</p>
<h2>The port that proved the thesis<span class="hx:absolute hx:-mt-20" id="the-port-that-proved-the-thesis"></span>
    <a href="#the-port-that-proved-the-thesis" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>While my project was paused, another developer, <a href="https://github.com/lackoftrack27/Super-Mario-Bros.-SMS"target="_blank" rel="noopener">lackoftrack27</a>, published a Super Mario Bros port for the Master System that is on another level. It runs at full speed, 60fps, and on top of that with improved sprite art that takes advantage of the console&rsquo;s superior palette. It ended up looking more like the Super Mario All-Stars remaster from the Super Nintendo than the somewhat crude original NES version. The retro community was in awe.</p>


<div class="embed-container">
  <iframe
    src="https://www.youtube.com/embed/igOu1NQL5Ww"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
  </iframe>
</div>

<p>That proved my thesis in practice: the Master System is capable of running superior versions of NES games. It always was.</p>
<p>Now, two honest points about this port, because they matter for the rest of the story.</p>
<p>First: lackoftrack27&rsquo;s work is a hand reimplementation, built from the game&rsquo;s disassembly, optimized specifically for Super Mario. It&rsquo;s not a general-purpose automatic translation like the one I&rsquo;m trying to do. He solved one game, beautifully, by hand. Curiously, that reinforces what the forums already said: the path that works is reimplementing by hand, not machine-translating.</p>
<p>Second: as impressive as it is to see Super Mario on the Master System, it&rsquo;s worth remembering it is still a first-generation game, around 40kb. Meaning it is one of the simpler games on the NES. Later-generation stuff, like Super Mario Bros 3 or Kirby, nobody has tried to convert yet, and for good reasons I explain further down.</p>
<p>But the most important thing was the side effect: with the map his port gave me, I finally got my automatic conversion running properly. I came back to the project in early September, loaded lackoftrack27&rsquo;s code into Claude Fable and then the new GPT Astra, and put both of them to study what he did that I wasn&rsquo;t doing.</p>
<h2>The architecture of the solution<span class="hx:absolute hx:-mt-20" id="the-architecture-of-the-solution"></span>
    <a href="#the-architecture-of-the-solution" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Since this article is for programmers, let me open the black box.</p>
<p>The first important decision is that <code>nes-to-sms</code> is not an emulator, nor a text-to-text translator of 6502 to Z80. It is a <strong>static recompiler</strong>. It reads the NES ROM, lifts the 6502 code into an intermediate representation with explicit semantics, and from that IR it generates Z80 code. The output is a WLA-DX assembly project that compiles into a real <code>.sms</code> ROM. The core is a Rust workspace with thirteen crates, plus a hand-written Z80 runtime shared across games.</p>
<p>The flow, end to end, goes roughly like this:</p>
<ol>
<li>Parse the ROM header, split the code banks (PRG) from the tile banks (CHR), and read the reset and interrupt vectors.</li>
<li>Load a per-game profile (a TOML with labels, data regions, jump tables, mapper type, and replacements).</li>
<li>Discover the functions, build the control-flow graph, and classify every byte as code or data. A key detail enters here: every memory access is tagged with the region it belongs to (zero page, stack, RAM, PPU registers, sprite DMA, sound, mapper).</li>
<li>Lift each routine into IR, with the 6502 flags explicit. A write to the PPU register <code>$2006</code> doesn&rsquo;t become just some <code>mem[]=</code>, it becomes a first-class &ldquo;PPU write&rdquo; primitive.</li>
<li>Lower the IR to Z80. The 6502 flags are kept in a shadow status byte in RAM, and every hardware access becomes a call into the runtime.</li>
<li>Emit the Z80 bytes and also the readable WLA-DX assembly.</li>
<li>Convert the assets: the NES 2bpp tiles become SMS mode-4 4bpp tiles, the NES palette becomes SMS CRAM, and so on.</li>
<li>Write the whole SMS project, with a Makefile, runtime, and data, ready to compile.</li>
</ol>
<p>The CPU mapping is conservative on purpose. The 6502 accumulator <code>A</code> becomes the Z80 <code>A</code>, the <code>X</code> and <code>Y</code> registers live in RAM or registers, the zero page becomes a fixed block in SMS RAM, and every operation that touches a flag calls a helper. It&rsquo;s safe and correct, but this is exactly where the cost lives.</p>
<h2>Where NES and SMS really diverge<span class="hx:absolute hx:-mt-20" id="where-nes-and-sms-really-diverge"></span>
    <a href="#where-nes-and-sms-really-diverge" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The project&rsquo;s central finding is about speed, and it&rsquo;s counterintuitive.</p>
<p>The NES 6502 runs at 1.79 MHz. The Master System Z80 runs at 3.58 MHz, double the clock. You look at that and think &ldquo;so there&rsquo;s plenty of headroom.&rdquo; Except no. The Z80 spends on average about 13 cycles per instruction, while the 6502 spends about 4. In real numbers, a 3.5 MHz Z80 is roughly equivalent to a 1 MHz 6502 for general work. Meaning the SMS Z80 is actually <strong>slower</strong> than the NES 6502 for the same work. The headroom is negative.</p>
<p>Worse: the cheapest 6502 idiom, an <code>LDA table,X</code>, is one of the most expensive to emulate on the Z80. So a faithful translation of a game that already squeezed the NES to the limit simply cannot hit 60fps without overclock. The blame is on the physics of the problem, not on my translator.</p>
<p>And the video is another story. The NES sees video memory in a mapped way, with nametables, hardware scroll, and a sprite table accessed via DMA. The SMS Z80 does not address VRAM as memory: it sets an address latch and streams bytes through VDP ports. So every NES PPU write has to be captured, queued in a buffer, and flushed to the VDP during vblank. The NES flips a sprite for free, just by setting an attribute bit. The Master System has no hardware sprite flipping, so the program has to mirror the tile data in VRAM by hand, burning memory. The mid-frame screen split that NES games do, changing the scroll each scanline, also has no direct equivalent, because the VDP latches the vertical scroll at the top of the frame.</p>
<p>And there&rsquo;s still the VRAM ceiling. Super Mario&rsquo;s 8 KB of tiles become 16 KB in the SMS 4bpp format, which is the console&rsquo;s entire VRAM. Background and sprites can&rsquo;t both stay resident at once. And the code balloons 3 to 6 times in size, which is why the SMS output is already banked from the very first game, even the simplest ones.</p>
<h2>Leveraging what the SMS does best<span class="hx:absolute hx:-mt-20" id="leveraging-what-the-sms-does-best"></span>
    <a href="#leveraging-what-the-sms-does-best" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The trick to recover speed is to stop emulating NES behavior and start spending the Master System&rsquo;s strengths. The project&rsquo;s motto became &ldquo;spend ROM to buy CPU.&rdquo;</p>
<p>The SMS accepts cartridges of several megabytes. So instead of mirroring a sprite by hand at runtime, the build already generates pre-flipped variants of each sprite tile, and the flip becomes a table lookup. Instead of emulating the NES attribute table, the assembler already writes the final SMS nametable word, with the flip, palette, and priority bits baked in. The NES attribute table simply stops existing in the program. The copies to the VDP use unrolled <code>OUTI</code> blocks, faster than the generic loop. And the status-bar split, which on the NES depends on sprite-zero, becomes an SMS line interrupt, which is the native way to do it.</p>
<p>None of this is magic. The negative CPU headroom is still there, so these optimizations reduce the cost but don&rsquo;t work miracles on their own. But it&rsquo;s the difference between unplayable and playable.</p>
<h2>The real trick: making the AI run the emulator<span class="hx:absolute hx:-mt-20" id="the-real-trick-making-the-ai-run-the-emulator"></span>
    <a href="#the-real-trick-making-the-ai-run-the-emulator" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Here&rsquo;s the part I consider the most important of the whole project, and it&rsquo;s what separated the failed attempt from May from the version that finally moves.</p>
<p>Blind translation doesn&rsquo;t work. The model needs real feedback to know what&rsquo;s broken and what&rsquo;s slow. So the heart of the project is the <strong>differential oracle</strong>, the infrastructure that runs the emulators and measures reality. The translator is just the easy part.</p>
<p>It works in two layers. The first compares instruction by instruction: for each routine, the system generates random initial states, runs the original 6502 in a reference interpreter and runs the generated Z80, and compares the result (accumulator, registers, flags, touched RAM). Any divergence raises a flag. The second layer compares frame by frame: it runs the NES ROM as absolute ground truth and the SMS build side by side, with the same button script, and compares RAM byte by byte on every frame. That was later extended with an oracle that checks the SMS VRAM and palette, and with a visual oracle that compares the output against the real NES frame.</p>
<p>This measurement loop is what unlocked the recent fixes. It wasn&rsquo;t guesswork. Two concrete examples:</p>
<p>In Super Mario, every optimization step was measured in cycles per frame, with the emulator actually running. A frame&rsquo;s budget is 59,736 cycles. The baseline sat at around 370 thousand cycles per frame, something like 6 times over budget, which gave about 10fps and explained the need for that brutal 500% overclock. Measuring step by step, each change validated by the oracle, it dropped to 118,296 cycles per frame, or 1.98 times the budget. It went from 6 times to under 2 times. It now runs at full speed already in the emulator&rsquo;s standard overclock, and it&rsquo;s comfortable in the 200 to 300% range, versus the 500 to 700% from the start.</p>
<p>In Castlevania, the biggest speed win came from a profile only the emulator could reveal: a sprite-zero wait loop, at address <code>$F8C7</code>, was doing 255 status reads and exiting by timeout every single time, consuming almost 23% of the entire CPU. Without running the emulator and measuring, nobody would find this by eye. With the measurement, the fix was surgical.</p>
<p>This is the bigger argument I&rsquo;ve been hammering for a while about agents: an LLM that only generates code in the dark makes big mistakes. An LLM that can actually run the target, collect real data, and react to what it measured plays in another league.</p>
<h2>What I learned studying lackoftrack27&rsquo;s port<span class="hx:absolute hx:-mt-20" id="what-i-learned-studying-lackoftrack27s-port"></span>
    <a href="#what-i-learned-studying-lackoftrack27s-port" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>With that oracle in place, I put Claude Fable and GPT Astra to dissect lackoftrack27&rsquo;s port, which is a reimplementation of the same game from the same disassembly I translate. That settled once and for all a doubt that was blocking me: Super Mario fits on the Master System. My 6-times overrun on the budget was 100% translation overhead, not a limitation of the game or the hardware.</p>
<p>His wins, in order of impact, were roughly these:</p>
<ul>
<li><strong>The biggest of all: the data representation.</strong> He reorganized the game&rsquo;s object arrays into RAM pages, one per slot, with the same field offsets. Then the 6502&rsquo;s <code>X</code> becomes the register <code>H</code> and the field name becomes <code>L</code>, and an access that cost about 70 time units in my translator now costs 14. The cruel detail is that this only works because the programmer knows, from memory, that this particular <code>X</code> is always an object index between 0 and 6. A static translator has no way to safely discover that invariant. This is the most powerful optimization, and it&rsquo;s precisely the one automatic translation can&rsquo;t prove on its own. It&rsquo;s the residual that holds back the last 2 times in speed.</li>
<li><strong>Flags audited, not emulated.</strong> He checked the code and found only about 10 places that genuinely depend on some 6502 carry quirk. The rest uses the Z80&rsquo;s native flags. That confirmed a measurement of mine: spending energy emulating flags yields almost nothing.</li>
<li><strong>Native calls.</strong> <code>JSR</code> becoming a real <code>CALL</code>, without the expensive emulated-stack bookkeeping. That was the biggest generic win I ported over to my pipeline.</li>
<li><strong>PPU deleted at build time</strong>, not emulated at runtime, exactly as I described in the section on leveraging the SMS.</li>
<li><strong>Frame architected to overrun gracefully</strong>, turning an overrun into a clean lag frame instead of corrupting the screen.</li>
</ul>
<p>I adopted what could be generalized, and Super Mario dropped from 6 times to under 2 times the budget. This is the result running today:</p>
<div class="embed-container">
  <video controls preload="metadata" playsinline style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000;">
    <source src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20260907152243_smb-sms-conversion.mp4" type="video/mp4">
  </video>
</div>
<p>The most honest lesson from this study is twofold. The real wins are in the data representation and the calling convention, not in what I had attacked first. And the deepest win of all is exactly what the automatic translator can&rsquo;t infer. That draws the ceiling of what can be automated pretty clearly.</p>
<h2>Castlevania and the mapper problem<span class="hx:absolute hx:-mt-20" id="castlevania-and-the-mapper-problem"></span>
    <a href="#castlevania-and-the-mapper-problem" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>With Super Mario moving, I went back to my old target: the first Castlevania. And here we hit the NES&rsquo;s most serious limitation.</p>
<p>The NES is a simple console, with a bunch of limits. One of the main ones is that it doesn&rsquo;t support games bigger than about 40kb of ROM, because the 6502 only sees a 32 KB window of program in its address space. The &ldquo;solution&rdquo; from back then was brilliant and a bit crazy: parts of the console were being upgraded by the cartridge itself.</p>
<p>Many people think a cartridge is just a ROM chip with the game code. In the NES case, it&rsquo;s not. The cartridges came with a variety of extra chips that increased the console&rsquo;s capability, be it a better sound chip or, much more commonly, the <strong>mappers</strong>. There are several different mappers, from Nintendo itself and from third parties like Capcom and Konami. They use a technique called <strong>bank switching</strong>: since the 6502 can&rsquo;t see enough address space, the mapper swaps which pieces of ROM are visible in that 32 KB window, as the game asks. That&rsquo;s how big games fit into a console that, on paper, couldn&rsquo;t handle them.</p>
<p>I already explained this in detail in an old video from my channel, <a href="/2020/06/18/akitando-81-aprendendo-sobre-computadores-com-super-mario-do-jeito-hardcore/">Akitando #81, about learning computing with Super Mario the hardcore way</a>:</p>


<div class="embed-container">
  <iframe
    src="https://www.youtube.com/embed/hYJ3dvHjeOE"
    title="YouTube video player"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen>
  </iframe>
</div>

<p>Castlevania uses one of the earlier mappers, the UxROM. And here is the scale problem of my project: if I want to be able to translate the majority of NES games, I have to map every mapper, one by one. Today the project implements only two: the NROM, which is Super Mario&rsquo;s bare cartridge, and Castlevania&rsquo;s UxROM. All the others, the MMC1, MMC3, and company, are only planned. Each mapper is quite a bit of work to implement, because it&rsquo;s not enough to understand the NES bank switching, you have to translate that behavior into the Master System&rsquo;s own mapper.</p>
<p>The good news is that the Master System is also a banked system, so the mapping is &ldquo;the same shape one level up.&rdquo; A NES PRG bank becomes a set of SMS banks, a NES bank-switch write becomes a write to the SMS mapper through a shim, and a call that crosses banks uses the &ldquo;gate&rdquo; machinery that already exists. A routine&rsquo;s identity becomes the pair (bank, address), and a dispatch table resolves that at runtime. When it doesn&rsquo;t find it, it fails closed, with a trap, instead of running garbage.</p>
<p>This is where bigger games will hit the wall. The tile bank switching of the more advanced mappers, the scanline interrupt timing of the MMC3 and MMC5, and the SMS&rsquo;s own bank ceiling for a really big NES game, all of that is still unsolved. That&rsquo;s why I still can&rsquo;t say whether a Super Mario Bros 3 is viable or not. It&rsquo;s quite possible the bigger games die exactly at this step.</p>
<p>Either way, I worked a good bit more on Castlevania in this comeback. I fixed a pile of things using the oracle: the sprite-zero loop that ate CPU, the weapon and projectile logic that lost call returns, a scroll glitch in the status bar, the VRAM collision between 8x16 and 8x8 sprites, and the coherence between background, palette, HUD, and sprites. Today Castlevania boots, accepts start, draws a recognizable first stage, responds to the controller, and runs for a good while without crashing. But it&rsquo;s honest to say it still runs slowly, and the path I use to play it is Mednafen at 500% overclock, and even then it&rsquo;s still 2 to 3 times below its own speed target. It&rsquo;s far from pixel-perfect and real-time.</p>
<div class="embed-container">
  <video controls preload="metadata" playsinline style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;background:#000;">
    <source src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20260907152243_castlevania-sms-conversion.mp4" type="video/mp4">
  </video>
</div>
<h2>Conclusion<span class="hx:absolute hx:-mt-20" id="conclusion"></span>
    <a href="#conclusion" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>After so many weeks and so many attempts, I still don&rsquo;t know how much more can be squeezed out of an automatic translation. The ceiling might be close, because the deepest optimizations are precisely the ones a machine can&rsquo;t infer on its own.</p>
<p>But there&rsquo;s a path that excites me. The automatic translation can become a baseline. An SMS conversion that already runs, correct, even if slow, and that can later be optimized by hand, game by game, exactly like lackoftrack27 did with Super Mario and like so many people have been doing with decompilations and ports out there. The oracle guarantees the base is correct, and the human hand steps in to do what the machine can&rsquo;t.</p>
<p>Porting a game to much better hardware, like a PC port, is relatively easy, because there&rsquo;s capacity to spare. The truly hard part is fitting the game into a same-generation console, where nothing is to spare. And it&rsquo;s exactly that difficulty that makes the idea of making better versions of NES games for the Master System so appealing. It&rsquo;s the console that deserved to have had those games, and never did.</p>
<p>I hope more people get excited about this possibility and contribute to the project. It&rsquo;s all open at <a href="https://github.com/akitaonrails/nes-to-sms"target="_blank" rel="noopener">nes-to-sms</a>. If you enjoy 6502, Z80, VDP, and the challenge of squeezing cycles out of 40-year-old hardware, come by. There&rsquo;s plenty of room.</p>
]]></content:encoded><category>retrocomputing</category><category>coding-agents</category><category>gaming</category><category>emulation</category></item><item><title>AI-MEMORY 2.0 - The Best Memory System for Agents and Teams</title><link>https://akitaonrails.github.io/en/2026/09/02/ai-memory-2-0-best-memory-system-for-agents-and-teams/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/09/02/ai-memory-2-0-best-memory-system-for-agents-and-teams/</guid><pubDate>Wed, 02 Sep 2026 11:00:00 -0300</pubDate><description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; &lt;a href="https://github.com/akitaonrails/ai-memory/releases/tag/v2.0.0"target="_blank" rel="noopener"&gt;ai-memory 2.0 is out&lt;/a&gt;, with the open OKF format, local embeddings turned on by default, and real support for several agents and a whole team working on the same project in parallel. The full pitch is below.&lt;/p&gt;
&lt;p&gt;Back in July I published &lt;a href="https://akitaonrails.github.io/en/2026/07/20/whats-new-ai-memory-switch-agents-without-losing-session/"&gt;What&amp;rsquo;s New in My AI-MEMORY&lt;/a&gt;, where I showed off &lt;code&gt;ai-memory run&lt;/code&gt;: switching from Claude Code to Codex without losing your line of work. That day we were on version 1.17.1.&lt;/p&gt;</description><content:encoded><![CDATA[<p><strong>TL;DR:</strong> <a href="https://github.com/akitaonrails/ai-memory/releases/tag/v2.0.0"target="_blank" rel="noopener">ai-memory 2.0 is out</a>, with the open OKF format, local embeddings turned on by default, and real support for several agents and a whole team working on the same project in parallel. The full pitch is below.</p>
<p>Back in July I published <a href="/en/2026/07/20/whats-new-ai-memory-switch-agents-without-losing-session/">What&rsquo;s New in My AI-MEMORY</a>, where I showed off <code>ai-memory run</code>: switching from Claude Code to Codex without losing your line of work. That day we were on version 1.17.1.</p>
<p>Today <strong>2.0</strong> shipped. And this time I&rsquo;m not going to rehash how the hooks work or how a session turns into a wiki page. That&rsquo;s already in the earlier posts. Here I want to talk about where ai-memory landed against the competition, what 2.0 brings, and why it earned the jump to a &ldquo;2&rdquo;.</p>
<p>If you&rsquo;ve never heard of the project, the summary is short. ai-memory is a long-term memory server for your coding agents. It captures what happened in the session, consolidates it into Markdown pages, and hands the right context to the next agent, whatever the harness or the machine.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20260902132131_screenshot-2026-09-02_13-20-02.png" alt="ai-memory 2.0 web browser showing the wiki’s project list, with the pre-migration OKF backup notice and cards for several projects like ai-memory, akitaonrails-hugo, and others"  loading="lazy" /></p>
<p>This is the web interface that comes with it, handy for auditing what the agents wrote and for browsing between projects. Notice how each project lives separately, with its own page count, all of it coming out of real sessions.</p>
<h2>Why it became 2.0<span class="hx:absolute hx:-mt-20" id="why-it-became-20"></span>
    <a href="#why-it-became-20" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>For me, the first digit of a version carries a commitment.</p>
<p>The 1.x line grew too fast. We went from 1.1 to 1.39 in a little over two months, stacking feature on top of feature in minor releases. It worked for iterating, but it blurred what the numbers meant.</p>
<p>2.0 fixes that. It bundles the few compatibility-breaking changes into a single major, and from here on versioning follows real <a href="https://github.com/akitaonrails/ai-memory/blob/main/CONTRIBUTING.md"target="_blank" rel="noopener">Semantic Versioning</a>. A fix is a patch. A new feature is a minor. Only a format or contract break is a major, and always with warning. The new contributing guide spells that rule out for any PR.</p>
<p>The main break is the new on-disk format. The first time you bring up 2.0, it migrates your wiki on its own. Before touching anything, it compresses your entire data directory into a verified backup with the date in the name. If the backup can&rsquo;t be written and checked, the migration aborts and the server refuses to start. No &ldquo;trust me&rdquo;.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/20260902131952_screenshot-2026-09-02_13-16-17.png" alt="ai-memory 2.0 dialog announcing that the memory was migrated to the OKF v0.2 format, showing the verified backup path and the rollback steps"  loading="lazy" /></p>
<p>This is the notice that shows up once, right after the migration: it tells you where the backup landed, the file size, and how to roll back if something looks off. Once you confirm everything is fine, you just delete the backup and the reminder disappears.</p>
<h2>OKF: your memory isn&rsquo;t locked inside ai-memory<span class="hx:absolute hx:-mt-20" id="okf-your-memory-isnt-locked-inside-ai-memory"></span>
    <a href="#okf-your-memory-isnt-locked-inside-ai-memory" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>This is the change that made me happiest.</p>
<p>Starting with 2.0, the ai-memory wiki is, natively, a bundle in the <strong>Open Knowledge Format</strong>, the open format Google published in 2026. Each memory page is a valid OKF file: plain Markdown with standardized metadata. There&rsquo;s no export step that produces a divergent copy. The wiki files already are the OKF files.</p>
<p>In practice that means your memory stopped being a hostage of my project. You can read it all with <code>grep</code>, open it in Obsidian, version it in Git, or hand the bundle to a coworker who uses another OKF-compatible tool. There&rsquo;s even an <code>ai-memory export-okf</code> to package a whole project into a validated tarball.</p>
<p>That was always the thesis: the model and the harness are rented, the project&rsquo;s memory is yours. Now the format backs that up in writing.</p>
<h2>Local embeddings, on by default<span class="hx:absolute hx:-mt-20" id="local-embeddings-on-by-default"></span>
    <a href="#local-embeddings-on-by-default" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Up through 1.x, real semantic search depended on you configuring an embeddings provider. Either you paid for an API and sent every page and every query out, or you spun up an Ollama on the side. Both options have a cost.</p>
<p>2.0 brings a <code>local</code> provider that runs the embeddings model inside the process itself, in pure Rust, with <code>all-MiniLM-L6-v2</code>. No API key, no external server, no GPU, and nothing about your data leaving the box. And now it comes on by default. On the first run it downloads the model (about 87 MB, with a fixed checksum) in the background and turns on hybrid search at the next restart.</p>
<p>The gain is measurable. On the LongMemEval-S benchmark, hit@5 goes from 0.617 with full-text only to 0.779 with the local embeddings. If for some reason you don&rsquo;t want it, an <code>embedding_provider = &quot;none&quot;</code> turns it off.</p>
<p>A detail that matters: I chose <code>candle</code> on purpose, instead of the native runtime the competition uses. That native layer is exactly what caused a recurring kind of crash in other memory projects. I preferred not to inherit the problem.</p>
<h2>Several agents at once, on the same project<span class="hx:absolute hx:-mt-20" id="several-agents-at-once-on-the-same-project"></span>
    <a href="#several-agents-at-once-on-the-same-project" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Here&rsquo;s where the part that drove most of the work before 2.0 begins.</p>
<p>The <code>ai-memory run</code> case I showed in July was sequential: I close Claude, open Codex, keep going. But what about when I leave two or three harnesses open at the same time on the same project? Claude in one tab, Codex in another, OpenCode in a third.</p>
<p>ai-memory handles that without anyone stepping on anyone else. Each memory call figures out on its own which project it belongs to, from the session&rsquo;s directory. The &ldquo;current project&rdquo; pointer is now per actor, so two harnesses in the same checkout each keep their own sense of context. And the project&rsquo;s identity comes from the checkout name. The absolute path on disk doesn&rsquo;t count, so the same project on the laptop and on the desktop lands in the same place.</p>
<p>When two windows write to the same page, the second doesn&rsquo;t erase the first. It creates a new version that becomes the latest, and the previous one stays reachable in the version chain. Writing something identical doesn&rsquo;t create a new version. Every write goes through a single writer, with a queue and backpressure, so a burst doesn&rsquo;t corrupt anything.</p>
<p>This isn&rsquo;t theory. There&rsquo;s an acceptance test calling Claude, Codex, OpenCode, Pi, Crush, and a few others for real, inside a single workstream, covering leases, session adoption, and context handoff between harnesses.</p>
<h2>A whole team on the same project<span class="hx:absolute hx:-mt-20" id="a-whole-team-on-the-same-project"></span>
    <a href="#a-whole-team-on-the-same-project" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The second scenario is the one that gives the post its title. Here it&rsquo;s several people, a whole team pointing their agents at the same server.</p>
<p>The way to run it is simple. Someone brings up a server, usually a container in a homelab or on a machine on the network, and each person points their agents at that URL. HTTPS goes in front with a reverse proxy, if you want. The database is still a single SQLite.</p>
<p>Everyone sees the same project pages. What one person learned in a session, the other&rsquo;s agent recovers. And each new session gets a briefing with the project&rsquo;s state right at the start. I&rsquo;ll be honest about the term &ldquo;real time&rdquo;. What exists is a shared central store, with immediate reads, plus the briefing at the open. The note a coworker wrote shows up right away for anyone&rsquo;s next query or next session. A session that&rsquo;s already running only gets the news at the next query or the next open, with no interruption mid-flight.</p>
<p>What changes in multi-user mode is attribution. Each write records who did it. There&rsquo;s an audit log and the interface shows &ldquo;edited by so-and-so&rdquo;. That comes in the box, for free. And there&rsquo;s no per-page permission, on purpose. Attribution is there to record authorship; anyone authenticated can write, and the history is what keeps track of who did.</p>
<p>There&rsquo;s an important security distinction between what&rsquo;s shared and what&rsquo;s personal. The pages belong to everyone. But the handoff is a baton with a single owner: exactly one session takes it, and a second <code>accept</code> doesn&rsquo;t steal the baton from anyone. The handoff you left pending isn&rsquo;t delivered to or consumed by a coworker. Likewise, the &ldquo;what I&rsquo;m working on right now&rdquo; slots are per person, so your personal context doesn&rsquo;t leak into the whole team&rsquo;s briefing.</p>
<p>There&rsquo;s also a battery of real concurrency tests covering these cases: simultaneous writes, per-actor isolation under load, the handoff baton that doesn&rsquo;t get stolen, and the personal slots that don&rsquo;t leak.</p>
<h2>Where ai-memory stands against the competition<span class="hx:absolute hx:-mt-20" id="where-ai-memory-stands-against-the-competition"></span>
    <a href="#where-ai-memory-stands-against-the-competition" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Before 2.0 we did another round of research on the 2026 landscape, documented in the repository. It was the basis for deciding what 2.0 needed to cover. Let me summarize the field.</p>
<p>There&rsquo;s <strong>agentmemory</strong>, a TypeScript MCP server tied to a native sidecar and a giant surface of dozens of tools. There&rsquo;s <strong>basic-memory</strong>, in Python, Markdown on disk, but with manual capture: you have to ask it to remember. There&rsquo;s <strong>cognee</strong>, which combines graph, vector, and relational into a heavy pipeline that wants several gigs of RAM. There&rsquo;s <strong>MemPalace</strong>, which went viral with almost 50,000 stars in two weeks over a benchmark number that, once audited, turned out to be inflated, on top of suffering corruption when two writes happen together. And there are the temporal graphs like <strong>Zep</strong>, the &ldquo;memory OS&rdquo; like <strong>Letta</strong> (the old MemGPT), and the fact extractors like <strong>Mem0</strong>.</p>
<p>There&rsquo;s also the native memory that Claude Code itself started turning on by default. I treat that one as the funnel that introduces the category to people. As a competitor it stays limited: tied to one machine, tied to one agent, without real search and without team history.</p>
<p>2.0 closes the gaps the research pointed out. We started publishing a reproducible benchmark with LongMemEval, running the actual server. We got the open OKF format. We got typed links between pages, with <code>causes</code>, <code>fixes</code>, and <code>contradicts</code>, which also feed a contradiction check without spending an LLM. We got queries with <code>as_of</code>, to ask what we knew about a subject on a given date. We got the local embeddings. And we got an optional &ldquo;experience&rdquo; pass that reviews several sessions to find patterns that only show up across the set.</p>
<p>Now the part that matters for whoever&rsquo;s choosing. What ai-memory has that the others don&rsquo;t, all together:</p>
<ul>
<li><strong>It follows you across agents.</strong> More than twenty harnesses feed a single memory, and the handoff here is a real protocol: typed, with an owner, and claimed exactly once.</li>
<li><strong>It follows you across machines.</strong> The memory lives on a server that&rsquo;s yours. The project you dropped on the desktop is the one you pick back up on the laptop.</li>
<li><strong>It works for a team.</strong> Multi-user authentication, per-person attribution, and an audit log come in the box, for free.</li>
<li><strong>Your memory is plain Markdown.</strong> The source of truth is a wiki versioned in Git. The database is a derived index you can rebuild at any moment from the files, with no vector store to babysit and nothing trapped in a binary blob.</li>
<li><strong>It captures the work on its own, quietly.</strong> No &ldquo;remember this&rdquo; ceremony. And the default path runs with zero LLM calls.</li>
<li><strong>It&rsquo;s a single binary.</strong> No sidecar, no three databases to sync. Every write goes through a single writer, with a write ceiling we actually measured, with a real test. That design is exactly what avoided the concurrent-write corruption that took the others down.</li>
</ul>
<p>No competitor delivers this set. Some have one piece or another. ai-memory has the whole package, and now with parity on the items where it used to fall behind.</p>
<h2>2.0 belongs to everyone<span class="hx:absolute hx:-mt-20" id="20-belongs-to-everyone"></span>
    <a href="#20-belongs-to-everyone" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>When I wrote the July post, fifteen people had a merged PR in the project. Today it&rsquo;s around seventy. This stopped being a weekend project a long time ago.</p>
<p>The numbers up to 2.0: more than 1,500 commits, <strong>371 merged pull requests</strong>, and <strong>181 closed issues</strong>. That came from people actually using it and sending fixes, features, and documentation.</p>
<p>I have to give special thanks to <a href="https://github.com/djalmajr"target="_blank" rel="noopener">Djalma Júnior</a>, who on his own passed 50 merged PRs, and to <a href="https://github.com/samirhvbr"target="_blank" rel="noopener">Samir Hanna Verza</a>, with more than 20. Right behind come <a href="https://github.com/lhzapata"target="_blank" rel="noopener">lhzapata</a>, <a href="https://github.com/pedrofjr"target="_blank" rel="noopener">pedrofjr</a>, <a href="https://github.com/mrpaiva"target="_blank" rel="noopener">mrpaiva</a>, <a href="https://github.com/lucasliet"target="_blank" rel="noopener">lucasliet</a>, <a href="https://github.com/lihuiyang1024"target="_blank" rel="noopener">lihuiyang1024</a>, <a href="https://github.com/Murillofilho86"target="_blank" rel="noopener">Murillofilho86</a>, and <a href="https://github.com/matheus-rodrigues00"target="_blank" rel="noopener">Matheus Rodrigues</a>. And there&rsquo;s a long tail of dozens of other people with a merged PR that it would be unfair to try to list in full here.</p>
<p>If you want in on this, the <a href="https://github.com/akitaonrails/ai-memory/blob/main/CONTRIBUTING.md"target="_blank" rel="noopener">contributing guide</a> was rewritten to make everything clear: how to set up the environment, the gates the CI enforces, the CHANGELOG rule, and the versioning policy. A bug fix usually ships fast in the next patch. A small feature, like a new harness or provider, goes into the next minor. There are issues tagged for people just starting out.</p>
<h2>How to get 2.0<span class="hx:absolute hx:-mt-20" id="how-to-get-20"></span>
    <a href="#how-to-get-20" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The project page has every install method, including AUR, Homebrew, and release binaries:</p>
<ul>
<li><a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">ai-memory on GitHub</a></li>
<li><a href="https://github.com/akitaonrails/ai-memory/releases/tag/v2.0.0"target="_blank" rel="noopener">v2.0.0 release notes</a></li>
</ul>
<p>After updating, on the first run let the migration take the backup and convert your wiki to the OKF format. If you use the managed mode, reinstall the hooks for the harnesses you plan to use.</p>
<h2>Conclusion<span class="hx:absolute hx:-mt-20" id="conclusion"></span>
    <a href="#conclusion" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>1.x proved the idea worked. 2.0 is the version I&rsquo;d recommend without an asterisk for someone else to put on a team.</p>
<p>The format is open, so your memory doesn&rsquo;t get locked in. Semantic search runs local, so you don&rsquo;t pay and you don&rsquo;t leak. Several agents and several people work on the same project without running each other over. And the single-binary, single-writer design is what avoids exactly the problems that sank half the competition.</p>
<p>The LLM and the subscription I keep renting from whoever&rsquo;s best that month. The project&rsquo;s memory stays with me, with the team, and now in a format nobody can take away from me.</p>
]]></content:encoded><category>ai-memory</category><category>coding-agents</category><category>open-source</category></item><item><title>LLM Benchmarks: The latest Deepseek v4, stop asking</title><link>https://akitaonrails.github.io/en/2026/08/22/llm-benchmarks-the-latest-deepseek-v4-stop-asking/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/08/22/llm-benchmarks-the-latest-deepseek-v4-stop-asking/</guid><pubDate>Sat, 22 Aug 2026 15:00:00 -0300</pubDate><description>&lt;p&gt;Last week I published the round with &lt;a href="https://akitaonrails.github.io/en/2026/08/15/llm-benchmarks-qwen-3-8-glm-5-3-gemini-3-7/"&gt;Qwen 3.8, GLM 5.3, Gemini 3.7 and Grok 4.6&lt;/a&gt; on my v2 benchmark: the three-phase test (build, validate everything actually running, self-review with an honesty score) that production-hardens a Rails 8 LLM chat app. The top is unchanged: Fable 5 at 96, the trio Sonnet 5, Opus 5 and Kimi K3 at 95, GLM 5.3 alone at 94, and the 93 pack right behind.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Last week I published the round with <a href="/en/2026/08/15/llm-benchmarks-qwen-3-8-glm-5-3-gemini-3-7/">Qwen 3.8, GLM 5.3, Gemini 3.7 and Grok 4.6</a> on my v2 benchmark: the three-phase test (build, validate everything actually running, self-review with an honesty score) that production-hardens a Rails 8 LLM chat app. The top is unchanged: Fable 5 at 96, the trio Sonnet 5, Opus 5 and Kimi K3 at 95, GLM 5.3 alone at 94, and the 93 pack right behind.</p>
<p>And every single time I publish one of these updates, without exception, someone shows up in the comments: <em>&ldquo;what about Deepseek?&rdquo;</em></p>
<p>I confess I do not understand this blind focus on Deepseek. It is one open model among many, with nothing that sets it apart from the pack. In my daily use, I still prefer Kimi K3 or GLM 5.3. Yes, every iteration improves a little. Yes, I tested both new snapshots (Flash 0731 and Pro 0813) and the numbers are below. And even so, the answer stays the same: nobody there is in Fable 5 or Sol class.</p>
<h2>What this score measures (and what it does not)<span class="hx:absolute hx:-mt-20" id="what-this-score-measures-and-what-it-does-not"></span>
    <a href="#what-this-score-measures-and-what-it-does-not" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Before the numbers, the reminder that needs repeating every round. The benchmark tests a very specific slice: <strong>easy</strong> web programming. A Rails chat CRUD with streaming, tools, concurrency and tests. It is a useful test because it is concrete, reproducible and catches API hallucination red-handed, but it is still a narrow slice.</p>
<p>It says nothing about far more advanced tasks: kernel driver development, game engine optimization, real offensive security. Testing the entirety of a model is impossible. What you can test is a subset, and that is what I did.</p>
<p>So next time you read &ldquo;Kimi is about to dethrone Fable&rdquo; or &ldquo;GLM is about to pass Sol&rdquo; because the scores came out close, read it like this: within a narrow slice of web programming, any of these models delivers. That is all. A close score on this test means proximity <strong>on this test</strong>, nothing more.</p>
<blockquote>
  <p><strong>Keep this:</strong> a benchmark measures a slice. Mine measures easy Rails web apps. Anyone extrapolating that into &ldquo;model X beats model Y at everything&rdquo; is reading the number wrong.</p>

</blockquote>
<h2>The Tier A ranking, with a focus on time<span class="hx:absolute hx:-mt-20" id="the-tier-a-ranking-with-a-focus-on-time"></span>
    <a href="#the-tier-a-ranking-with-a-focus-on-time" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The usual table, A.1 cut (90 points or more), now with both Deepseeks in <strong>bold</strong>. This time, pay attention to the time column: same test, same three phases, for everyone.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right">#</th>
          <th>Model</th>
          <th style="text-align: right">Score</th>
          <th>Harness</th>
          <th style="text-align: right">Time</th>
          <th style="text-align: right">Cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">1</td>
          <td>Claude Fable 5</td>
          <td style="text-align: right">96</td>
          <td>Claude Code</td>
          <td style="text-align: right">46 min</td>
          <td style="text-align: right">$26.03</td>
      </tr>
      <tr>
          <td style="text-align: right">2</td>
          <td>Claude Sonnet 5</td>
          <td style="text-align: right">95</td>
          <td>Claude Code</td>
          <td style="text-align: right">59 min</td>
          <td style="text-align: right">$25.83</td>
      </tr>
      <tr>
          <td style="text-align: right">2</td>
          <td>Claude Opus 5</td>
          <td style="text-align: right">95</td>
          <td>Claude Code</td>
          <td style="text-align: right">78 min</td>
          <td style="text-align: right">$38.91</td>
      </tr>
      <tr>
          <td style="text-align: right">2</td>
          <td>Kimi K3</td>
          <td style="text-align: right">95</td>
          <td>Kimi CLI</td>
          <td style="text-align: right">65 min</td>
          <td style="text-align: right">$6.14</td>
      </tr>
      <tr>
          <td style="text-align: right">5</td>
          <td>GLM 5.3</td>
          <td style="text-align: right">94</td>
          <td>OpenCode</td>
          <td style="text-align: right">80 min</td>
          <td style="text-align: right">$0 (≈$2.59)</td>
      </tr>
      <tr>
          <td style="text-align: right">6</td>
          <td>GPT 5.6 Sol</td>
          <td style="text-align: right">93</td>
          <td>Codex</td>
          <td style="text-align: right">57 min</td>
          <td style="text-align: right">~$45</td>
      </tr>
      <tr>
          <td style="text-align: right">6</td>
          <td>Claude Opus 4.8</td>
          <td style="text-align: right">93</td>
          <td>Claude Code</td>
          <td style="text-align: right">53 min</td>
          <td style="text-align: right">$21.82</td>
      </tr>
      <tr>
          <td style="text-align: right">6</td>
          <td>GPT 5.6 Terra</td>
          <td style="text-align: right">93</td>
          <td>Codex</td>
          <td style="text-align: right">48 min</td>
          <td style="text-align: right">$16.92</td>
      </tr>
      <tr>
          <td style="text-align: right">6</td>
          <td>Gemini 3.7 Flash</td>
          <td style="text-align: right">93</td>
          <td>OpenCode</td>
          <td style="text-align: right">43 min</td>
          <td style="text-align: right">$4.12</td>
      </tr>
      <tr>
          <td style="text-align: right">10</td>
          <td>GLM 5.2</td>
          <td style="text-align: right">92</td>
          <td>OpenCode</td>
          <td style="text-align: right">155 min</td>
          <td style="text-align: right">$0 (≈$12.05)</td>
      </tr>
      <tr>
          <td style="text-align: right">10</td>
          <td>Kimi K2.5</td>
          <td style="text-align: right">92</td>
          <td>OpenCode</td>
          <td style="text-align: right">43 min</td>
          <td style="text-align: right">$1.50</td>
      </tr>
      <tr>
          <td style="text-align: right">10</td>
          <td>Gemini 3.6 Flash @ high</td>
          <td style="text-align: right">92</td>
          <td>Antigravity</td>
          <td style="text-align: right">15 min</td>
          <td style="text-align: right">—</td>
      </tr>
      <tr>
          <td style="text-align: right">10</td>
          <td>Qwen 3.8 Max</td>
          <td style="text-align: right">92</td>
          <td>OpenCode</td>
          <td style="text-align: right">78 min</td>
          <td style="text-align: right">$9.16</td>
      </tr>
      <tr>
          <td style="text-align: right">10</td>
          <td>Grok 4.6</td>
          <td style="text-align: right">92</td>
          <td>OpenCode</td>
          <td style="text-align: right">34 min</td>
          <td style="text-align: right">$6.33</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>MiniMax M3</td>
          <td style="text-align: right">91</td>
          <td>OpenCode</td>
          <td style="text-align: right">113 min</td>
          <td style="text-align: right">$7.72</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>Kimi K2.6</td>
          <td style="text-align: right">91</td>
          <td>OpenCode</td>
          <td style="text-align: right">34 min</td>
          <td style="text-align: right">$2.64</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>Claude Opus 4.7</td>
          <td style="text-align: right">91</td>
          <td>Claude Code</td>
          <td style="text-align: right">44 min</td>
          <td style="text-align: right">$44.28</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>GPT 5.6 Luna</td>
          <td style="text-align: right">91</td>
          <td>Codex</td>
          <td style="text-align: right">46 min</td>
          <td style="text-align: right">$16.79</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td><strong>Deepseek v4 Pro (0813)</strong></td>
          <td style="text-align: right"><strong>91</strong></td>
          <td>OpenCode</td>
          <td style="text-align: right"><strong>82 min</strong></td>
          <td style="text-align: right"><strong>$5.01</strong></td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>Grok 4.5</td>
          <td style="text-align: right">91</td>
          <td>grok CLI</td>
          <td style="text-align: right">25 min</td>
          <td style="text-align: right">$0 (≈$1.62)</td>
      </tr>
      <tr>
          <td style="text-align: right">21</td>
          <td><strong>Deepseek v4 Flash (0731)</strong></td>
          <td style="text-align: right"><strong>90</strong></td>
          <td>OpenCode</td>
          <td style="text-align: right"><strong>88 min</strong></td>
          <td style="text-align: right"><strong>$0.82</strong></td>
      </tr>
  </tbody>
</table>
<p><em>Time is the wall clock of the three phases; cost is the API equivalent. Same criteria as the previous articles, linked at the end.</em></p>
<p>Look at the time spread. The fastest in the group finishes the test in 15 minutes; the slowest takes 155, <strong>ten times longer</strong>. Both Deepseeks sit in the lower half of the table for speed: 82 and 88 minutes, behind almost everyone in the same score range. The Flash, in particular, burned <strong>44 million tokens</strong> in one run. For comparison, GLM 5.3 scored one point higher with 19.4 million. Deepseek makes up for it on the invoice: the Flash&rsquo;s $0.82 is the cheapest Tier A run to date.</p>
<h2>The new snapshots: what changed since July<span class="hx:absolute hx:-mt-20" id="the-new-snapshots-what-changed-since-july"></span>
    <a href="#the-new-snapshots-what-changed-since-july" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I ran the July builds of v4 at the end of that month: Flash scored 80, Pro scored 82, both Tier B. Both dated snapshots (0731 and 0813) ran today under the same rigor, and both entered Tier A:</p>
<p><strong>Flash 0731: from 80 to 90 (+10).</strong> The most visible improvement is behavioral. The July build pinned a model three generations old; this one got the pin right on the first try (<code>anthropic/claude-sonnet-5</code>, no stale slug). The self-review was exemplary: it found on its own that the streaming bubble partial was dead code (no assistant reply appeared until a forced reload through phases 1 and 2), confessed, fixed it and scored 15/15 on honesty. It lost points where the pack loses them: concurrency without a turn lock (8) and coverage without branch (8).</p>
<p><strong>Pro 0813: from 82 to 91 (+9).</strong> The big news is what disappeared: the <code>reasoning_content</code> bug that broke its multi-turn on OpenCode, and that forced me to invent the <a href="/en/2026/05/04/llm-benchmarks-deepseek-unlocked-deepclaude/">deepclaude workaround</a> back in May, was fixed in opencode 1.18.4, and this snapshot ran end to end on the generic harness, no crutches. The technical highlight was concurrency: a SQLite store with read-modify-write inside a <code>BEGIN IMMEDIATE</code> transaction, the most serious solution in the group on that dimension (9/10). The losses were honest and self-confessed: stale sonnet-4.6 pin, streaming verified by unit test only, no fallback token-budget estimator.</p>
<p>Clean, shielded runs, zero reads of the rubric or of anyone else&rsquo;s app. The full reports are in the <a href="https://github.com/akitaonrails/llm-coding-benchmark"target="_blank" rel="noopener">benchmark repository</a>.</p>
<h2>Deepseek against itself: the trajectory is real<span class="hx:absolute hx:-mt-20" id="deepseek-against-itself-the-trajectory-is-real"></span>
    <a href="#deepseek-against-itself-the-trajectory-is-real" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Old and new criteria do not compare point for point, so this section is about behavior, not scores. And behavior you can compare, because the contrast is stark.</p>
<p>In April, <strong>DeepSeek V3.2</strong> scored 43 under the old criteria and starred in the most embarrassing moment in the benchmark&rsquo;s history: it invented the entire RubyLLM integration. <code>RubyLLM::Client.new</code>, <code>client.chat(messages:)</code>, both methods hallucinated, the whole LLM layer fictional.</p>
<p>Still under the old criteria, <strong>v4 Flash</strong> scored 78 with a fatal one-character bug (the model slug missing the <code>anthropic/</code> prefix), and <strong>v4 Pro</strong> DNF&rsquo;d at 69: Tier 1 code, Tier 3 deliverables, taken down by the <code>reasoning_content</code> bug that ate the conversation history. That bug is what spawned the deepclaude hack, where the same Pro jumped to 89.</p>
<p>On v2, the July builds scored 80 and 82. Today&rsquo;s snapshots, 90 and 91. From &ldquo;invented the entire API&rdquo; to &ldquo;finds its own dead code and confesses it in self-review&rdquo; in four months. Deepseek&rsquo;s curve is one of the steepest this benchmark has ever recorded, and pretending otherwise would be dishonest.</p>
<h2>And against the other Chinese models?<span class="hx:absolute hx:-mt-20" id="and-against-the-other-chinese-models"></span>
    <a href="#and-against-the-other-chinese-models" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>This is where the conversation gets less exciting for the cheering section. On the same generic harness (OpenCode), the Chinese pack looks like this:</p>
<table>
  <thead>
      <tr>
          <th>Model</th>
          <th style="text-align: right">Score</th>
          <th style="text-align: right">Time</th>
          <th style="text-align: right">Cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GLM 5.3</td>
          <td style="text-align: right">94</td>
          <td style="text-align: right">80 min</td>
          <td style="text-align: right">$0 (≈$2.59)</td>
      </tr>
      <tr>
          <td>Qwen 3.8 Max</td>
          <td style="text-align: right">92</td>
          <td style="text-align: right">78 min</td>
          <td style="text-align: right">$9.16</td>
      </tr>
      <tr>
          <td>Kimi K2.5</td>
          <td style="text-align: right">92</td>
          <td style="text-align: right">43 min</td>
          <td style="text-align: right">$1.50</td>
      </tr>
      <tr>
          <td>Deepseek v4 Pro (0813)</td>
          <td style="text-align: right">91</td>
          <td style="text-align: right">82 min</td>
          <td style="text-align: right">$5.01</td>
      </tr>
      <tr>
          <td>Deepseek v4 Flash (0731)</td>
          <td style="text-align: right">90</td>
          <td style="text-align: right">88 min</td>
          <td style="text-align: right">$0.82</td>
      </tr>
  </tbody>
</table>
<p>And Kimi K3, absent from this table because it ran on its native harness, scored 95. In other words: within the same test, Deepseek v4 arrives behind GLM 5.3, Qwen 3.8 Max and the Kimis, while being the slowest and most verbose of the Chinese group. Its advantage is a single one, and it is real: price. $0.82 for a Tier A run is impressive, and the Pro at $5.01 undercuts almost everyone at the same score.</p>
<p>If your criterion is &ldquo;maximum competence per dollar on simple web tasks&rdquo;, the Flash 0731 deserves attention. If the criterion is the best model in the group, the answer is still Kimi K3 and GLM 5.3, same as last week.</p>
<h2>Conclusion: stop asking<span class="hx:absolute hx:-mt-20" id="conclusion-stop-asking"></span>
    <a href="#conclusion-stop-asking" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>There, now there are numbers on the table. Deepseek v4 genuinely improved between July and August, both snapshots entered Tier A, the Pro got rid of the bug that demanded a harness workaround, and the Flash is the cheapest Tier A run I have ever executed. All of that is fact.</p>
<p>And none of it changes the picture. The leadership stays with Fable 5, Sonnet 5, Opus 5 and Sol; the first Chinese model in line is still Kimi K3, followed by GLM 5.3. Deepseek is one more competent model on a slice of easy tasks, with the virtue of being cheap and the defect of being verbose. Next time you feel the urge to comment &ldquo;what about Deepseek?&rdquo;, the answer is this article.</p>
]]></content:encoded><category>llm-benchmarks</category><category>llms</category><category>coding-agents</category></item><item><title>LLM Benchmarks: Qwen 3.8, GLM 5.3, Gemini 3.7, Grok 4.6</title><link>https://akitaonrails.github.io/en/2026/08/15/llm-benchmarks-qwen-3-8-glm-5-3-gemini-3-7/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/08/15/llm-benchmarks-qwen-3-8-glm-5-3-gemini-3-7/</guid><pubDate>Sat, 15 Aug 2026 14:00:00 -0300</pubDate><description>&lt;p&gt;Two weeks ago I published &lt;a href="https://akitaonrails.github.io/en/2026/07/30/new-llm-benchmark-i-reran-every-test/"&gt;version 2 of my LLM Coding Benchmark&lt;/a&gt;: a new three-phase test — build, validate everything by actually running it, then self-review, with honesty points — each family running on the harness where it should work best. The methodology is all there, so I won&amp;rsquo;t repeat it here.&lt;/p&gt;
&lt;p&gt;The top hasn&amp;rsquo;t moved: &lt;strong&gt;Fable 5 at 96&lt;/strong&gt;, the trio of &lt;strong&gt;Sonnet 5, Opus 5, and Kimi K3 at 95&lt;/strong&gt;, and right behind them &lt;strong&gt;GPT 5.6 Sol, GPT 5.6 Terra, and Opus 4.8 at 93&lt;/strong&gt;. That&amp;rsquo;s the cream of the crop in this test. The open question: how close do the newest releases get to that group?&lt;/p&gt;</description><content:encoded><![CDATA[<p>Two weeks ago I published <a href="/en/2026/07/30/new-llm-benchmark-i-reran-every-test/">version 2 of my LLM Coding Benchmark</a>: a new three-phase test — build, validate everything by actually running it, then self-review, with honesty points — each family running on the harness where it should work best. The methodology is all there, so I won&rsquo;t repeat it here.</p>
<p>The top hasn&rsquo;t moved: <strong>Fable 5 at 96</strong>, the trio of <strong>Sonnet 5, Opus 5, and Kimi K3 at 95</strong>, and right behind them <strong>GPT 5.6 Sol, GPT 5.6 Terra, and Opus 4.8 at 93</strong>. That&rsquo;s the cream of the crop in this test. The open question: how close do the newest releases get to that group?</p>
<p>Since then I&rsquo;ve run five models: Qwen 3.8 Max, GLM 5.3, Gemini 3.7 Flash, Grok 4.6, and a 27B Qwen 3.8 running locally on my RTX 5090. One of them closed in on the leading group. Another pulled off the biggest jump this test has ever recorded. A third got caught cheating mid-test. A fourth tied its own previous generation, without moving an inch. And the local one gave me the most laborious, and most instructive, run of the year.</p>
<h2>Where they land in the ranking<span class="hx:absolute hx:-mt-20" id="where-they-land-in-the-ranking"></span>
    <a href="#where-they-land-in-the-ranking" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Before opening each one up, it&rsquo;s worth seeing where the newcomers fit. The table below is the <strong>Tier A.1</strong> slice of the <a href="/en/2026/07/30/new-llm-benchmark-i-reran-every-test/">v2 ranking</a>: the frontier of the test, everyone at 90 points or more. I cut it here on purpose. From A.2 down there are competent models, but the leadership race lives in this group, and that&rsquo;s what the question is about. The three cloud releases go in <strong>bold</strong>; the local 27B Qwen scored 51, Tier C, and shows up only in the table at the end.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right">#</th>
          <th>Model</th>
          <th style="text-align: right">Score</th>
          <th style="text-align: center">Tier</th>
          <th>Harness</th>
          <th style="text-align: right">Time</th>
          <th style="text-align: right">Cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">1</td>
          <td>Claude Fable 5</td>
          <td style="text-align: right">96</td>
          <td style="text-align: center">A.1</td>
          <td>Claude Code</td>
          <td style="text-align: right">46 min</td>
          <td style="text-align: right">$26.03</td>
      </tr>
      <tr>
          <td style="text-align: right">2</td>
          <td>Claude Sonnet 5</td>
          <td style="text-align: right">95</td>
          <td style="text-align: center">A.1</td>
          <td>Claude Code</td>
          <td style="text-align: right">59 min</td>
          <td style="text-align: right">$25.83</td>
      </tr>
      <tr>
          <td style="text-align: right">2</td>
          <td>Claude Opus 5</td>
          <td style="text-align: right">95</td>
          <td style="text-align: center">A.1</td>
          <td>Claude Code</td>
          <td style="text-align: right">78 min</td>
          <td style="text-align: right">$38.91</td>
      </tr>
      <tr>
          <td style="text-align: right">2</td>
          <td>Kimi K3</td>
          <td style="text-align: right">95</td>
          <td style="text-align: center">A.1</td>
          <td>Kimi CLI</td>
          <td style="text-align: right">65 min</td>
          <td style="text-align: right">$6.14</td>
      </tr>
      <tr>
          <td style="text-align: right">5</td>
          <td><strong>GLM 5.3</strong></td>
          <td style="text-align: right"><strong>94</strong></td>
          <td style="text-align: center">A.1</td>
          <td>OpenCode</td>
          <td style="text-align: right">80 min</td>
          <td style="text-align: right">$0 (≈$2.59)</td>
      </tr>
      <tr>
          <td style="text-align: right">6</td>
          <td>GPT 5.6 Sol</td>
          <td style="text-align: right">93</td>
          <td style="text-align: center">A.1</td>
          <td>Codex</td>
          <td style="text-align: right">57 min</td>
          <td style="text-align: right">~$45</td>
      </tr>
      <tr>
          <td style="text-align: right">6</td>
          <td>Claude Opus 4.8</td>
          <td style="text-align: right">93</td>
          <td style="text-align: center">A.1</td>
          <td>Claude Code</td>
          <td style="text-align: right">53 min</td>
          <td style="text-align: right">$21.82</td>
      </tr>
      <tr>
          <td style="text-align: right">6</td>
          <td>GPT 5.6 Terra</td>
          <td style="text-align: right">93</td>
          <td style="text-align: center">A.1</td>
          <td>Codex</td>
          <td style="text-align: right">48 min</td>
          <td style="text-align: right">$16.92</td>
      </tr>
      <tr>
          <td style="text-align: right">6</td>
          <td><strong>Gemini 3.7 Flash</strong></td>
          <td style="text-align: right"><strong>93</strong></td>
          <td style="text-align: center">A.1</td>
          <td>OpenCode</td>
          <td style="text-align: right">43 min</td>
          <td style="text-align: right">$4.12</td>
      </tr>
      <tr>
          <td style="text-align: right">10</td>
          <td>GLM 5.2</td>
          <td style="text-align: right">92</td>
          <td style="text-align: center">A.1</td>
          <td>OpenCode</td>
          <td style="text-align: right">155 min</td>
          <td style="text-align: right">$0 (≈$12.05)</td>
      </tr>
      <tr>
          <td style="text-align: right">10</td>
          <td>Kimi K2.5</td>
          <td style="text-align: right">92</td>
          <td style="text-align: center">A.1</td>
          <td>OpenCode</td>
          <td style="text-align: right">43 min</td>
          <td style="text-align: right">$1.50</td>
      </tr>
      <tr>
          <td style="text-align: right">10</td>
          <td>Gemini 3.6 Flash @ high</td>
          <td style="text-align: right">92</td>
          <td style="text-align: center">A.1</td>
          <td>Antigravity</td>
          <td style="text-align: right">15 min</td>
          <td style="text-align: right">—</td>
      </tr>
      <tr>
          <td style="text-align: right">10</td>
          <td><strong>Qwen 3.8 Max</strong></td>
          <td style="text-align: right"><strong>92</strong></td>
          <td style="text-align: center">A.1</td>
          <td>OpenCode</td>
          <td style="text-align: right">78 min</td>
          <td style="text-align: right">$9.16</td>
      </tr>
      <tr>
          <td style="text-align: right">10</td>
          <td><strong>Grok 4.6</strong></td>
          <td style="text-align: right"><strong>92</strong></td>
          <td style="text-align: center">A.1</td>
          <td>OpenCode</td>
          <td style="text-align: right">34 min</td>
          <td style="text-align: right">$6.33</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>MiniMax M3</td>
          <td style="text-align: right">91</td>
          <td style="text-align: center">A.1</td>
          <td>OpenCode</td>
          <td style="text-align: right">113 min</td>
          <td style="text-align: right">$7.72</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>Kimi K2.6</td>
          <td style="text-align: right">91</td>
          <td style="text-align: center">A.1</td>
          <td>OpenCode</td>
          <td style="text-align: right">34 min</td>
          <td style="text-align: right">$2.64</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>Claude Opus 4.7</td>
          <td style="text-align: right">91</td>
          <td style="text-align: center">A.1</td>
          <td>Claude Code</td>
          <td style="text-align: right">44 min</td>
          <td style="text-align: right">$44.28</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>GPT 5.6 Luna</td>
          <td style="text-align: right">91</td>
          <td style="text-align: center">A.1</td>
          <td>Codex</td>
          <td style="text-align: right">46 min</td>
          <td style="text-align: right">$16.79</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>Grok 4.5</td>
          <td style="text-align: right">91</td>
          <td style="text-align: center">A.1</td>
          <td>grok CLI</td>
          <td style="text-align: right">25 min</td>
          <td style="text-align: right">$0 (≈$1.62)</td>
      </tr>
  </tbody>
</table>
<p><em>Time is wall clock across the three phases; cost is API-equivalent. On subscription plans (Z.ai, grok CLI) the marginal cost is $0 and the value in parentheses is the API-equivalent; the Antigravity runs were preview and were not metered. Same criterion as the previous article.</em></p>
<h2>Qwen 3.8 Max: the biggest jump in benchmark history<span class="hx:absolute hx:-mt-20" id="qwen-38-max-the-biggest-jump-in-benchmark-history"></span>
    <a href="#qwen-38-max-the-biggest-jump-in-benchmark-history" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>To measure the jump, first the size of the hole. Qwen 3.7 Max had scored <strong>51 points, Tier C</strong>, and the reason was ugly. When implementing the multi-turn chat, it decided it could replay history by calling <code>chat.ask(entire_history_array)</code>. Except RubyLLM&rsquo;s <code>ask</code> wraps its argument into a single user message: the entire conversation, assistant turns included, becomes one message with every role obliterated. Worse, the required test for that feature <strong>mocked exactly that nonexistent API</strong>. A test that mocks a fabricated API is worse than no test, because it certifies the hallucination.</p>
<p>The 3.8 Max fixed exactly that. It used the real API end to end: <code>add_message</code> with role and content for history replay, <code>with_instructions</code>, <code>with_tools</code>, <code>with_schema</code>, all verified against the installed gem&rsquo;s source. The result: <strong>92 points, Tier A</strong>. That&rsquo;s a <strong>41-point jump</strong> on the same test, same rubric, same harness. The test didn&rsquo;t get easier; the model finally understood the library.</p>
<p>The rest of the delivery is solid: real incremental streaming, history surviving restarts, a hand-written calculator with no <code>eval</code>, tools answering with exact arithmetic, the app booting in Docker on the first try. The suite came out with 62 tests and 226 assertions, all green.</p>
<p>Where it lost points is instructive: <code>config/puma.rb</code> shipped without the <code>workers</code> directive, so the <code>WEB_CONCURRENCY=2</code> it swore it had delivered was, in practice, running single-process. Concurrency scored 8 instead of 9. And it kept the stale pin on <code>claude-sonnet-4.6</code>, the house&rsquo;s standard deduction.</p>
<blockquote>
  <p><strong>Remember this:</strong> the model swore concurrency worked — one missing line in <code>puma.rb</code> and the &ldquo;two workers&rdquo; ran as a single process. That&rsquo;s why phase 2 doesn&rsquo;t read READMEs: it boots the server and measures.</p>

</blockquote>
<p>On the table, those 92 points tie with GLM 5.2 and Kimi K2.5, <strong>one point below Sol and Terra</strong>. It cost $9.16 in API and 78 minutes — verbose: 25 million tokens.</p>
<h2>GLM 5.3: the loneliest step on the table<span class="hx:absolute hx:-mt-20" id="glm-53-the-loneliest-step-on-the-table"></span>
    <a href="#glm-53-the-loneliest-step-on-the-table" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Z.ai&rsquo;s trajectory in this test is the steadiest of the pack: GLM 5 scored 83, GLM 5.2 scored 92, and now <strong>GLM 5.3 scored 94</strong> — alone on a step nobody else occupies, one point below the 95 trio and one point above the 93 group. In other words: <strong>two points from Fable 5</strong>.</p>
<p>And the inevitable comparison is with Kimi. K3 scored 95, one point above — but it ran on the Kimi CLI, its native harness. GLM 5.3&rsquo;s 94 came on opencode, the generic harness: it&rsquo;s the <strong>highest score ever recorded there</strong>. On the same opencode, the best Kimi is K2.5 at 92, two points below. On cost, both live on subscriptions: K3 came out at $6.14 equivalent on the Moderato plan; GLM at zero marginal cost. Kimi still wins on score; GLM wins on cost and harness independence.</p>
<p>What pulled it out of the 92 pack? Three things, all boring, all important:</p>
<ol>
<li><strong>Concurrency delivered working.</strong> The same file-lock scheme as Qwen 3.8 Max, plus a per-conversation turn lock, plus two real workers surviving kill and restart without corrupting anything. The Qwen had the same foundation but shipped concurrency broken and scored 8. The GLM shipped it working and got 9.</li>
<li><strong>A fallback token estimator</strong>, so the per-conversation budget works even when the provider doesn&rsquo;t report usage. The 5.2 depended on it, and lost points there.</li>
<li><strong>Branch coverage enabled</strong>: 98% line and 82% branch, a suite of 73 tests and 219 assertions green under the auditor&rsquo;s hand, with RuboCop, Brakeman, and bundle-audit all at zero.</li>
</ol>
<blockquote>
  <p><strong>Remember this:</strong> the distance between the 92 pack and GLM&rsquo;s 94 isn&rsquo;t model brilliance: it&rsquo;s concurrency that actually works, a fallback token estimator, and branch coverage. Boring engineering earns points.</p>

</blockquote>
<p>The only real slip was the same stale sonnet-4.6 pin. And there was a division-by-zero bug in the calculator that the model itself found and fixed in the self-review — exactly the kind of behavior that phase exists to measure. Speaking of which: it confessed everything, including that the conversation title never retries if generation fails, and took 14 of the 15 honesty points.</p>
<p>And the cost is the part that hurts the competition: it ran on Z.ai&rsquo;s flat-rate plan, so the run came out at <strong>zero marginal cost</strong> — the API equivalent would be $2.59. Eighty minutes, 19.4 million tokens. The &ldquo;Chinese models are the cheap alternative&rdquo; conversation died a while ago: this is a leadership candidate that also happens to be cheap.</p>
<h2>Gemini 3.7 Flash: 93, Tier A — and the cheat along the way<span class="hx:absolute hx:-mt-20" id="gemini-37-flash-93-tier-a--and-the-cheat-along-the-way"></span>
    <a href="#gemini-37-flash-93-tier-a--and-the-cheat-along-the-way" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The technical part you already know: Gemini 3.1 Pro died in v2 because of a Google bug, <code>Corrupted thought signature</code>, which killed executions mid-run via OpenRouter and trapped it at 62 (over the direct path, it scored 88). This time I cut out the middleman: a <strong>direct Gemini API key</strong>, no OpenRouter in between, and the bug never showed up once. The direct path worked — and 3.7 Flash became the <strong>first Gemini to reach Tier A on opencode</strong>: 3.5 Flash scored 79 there, 3.1 Pro scored 62. Before that, only Google&rsquo;s native harness had taken a Gemini to A.</p>
<p>Official result: <strong>93 points</strong>, tied with GPT 5.6 Sol, Terra, and Opus 4.8. The run cost $4.12, took 43 minutes, and burned 27.8 million tokens.</p>
<p>But the road to that 93 produced the most important finding of this cycle. The first 3.7 Flash run raised a red flag — and there was a reason. Midway through the build, and again in the self-review, the model <strong>read the scoring rubric</strong>, read the entire v2 report — every competitor&rsquo;s score and audit — and <strong>ran the audit scanner on itself eight times</strong>. It spent the whole test studying how it would be graded.</p>
<p>The smoking gun is the pin. The contaminated run came out with the correct pin on <code>claude-sonnet-5</code>, that feat only three models had managed in the benchmark&rsquo;s entire history. I voided that run and redid it with all the grading material out of the model&rsquo;s reach: out came the stale pin on <code>claude-sonnet-4.6</code>, like everyone else. It didn&rsquo;t know the current model at all — it had read the answer in the report. The 93 belongs to that second, clean run.</p>
<p>To be fair: it didn&rsquo;t copy code from any sibling app. What it did was cheat off the grading — and that was enough for no model, frontier or not, to ever run with access to that material again.</p>
<p>And the 93 isn&rsquo;t charity — the delivery stands on its own. Real RubyLLM API end to end, a safe calculator with no <code>eval</code>, correct multi-turn history, incremental streaming working end to end in Docker, persistence surviving restarts with two workers. A suite of 55 tests and 213 assertions, all green, branch coverage enabled. The deductions: the stale pin and the lack of a per-conversation turn lock — the same concurrency ceiling as Fable 5.</p>
<blockquote>
  <p><strong>Remember this:</strong> this time it wasn&rsquo;t a weak local copying from the neighbor. It was a frontier model checking the answers mid-test.</p>

</blockquote>
<h2>Qwen 3.8 27B local: the most laborious run of the year<span class="hx:absolute hx:-mt-20" id="qwen-38-27b-local-the-most-laborious-run-of-the-year"></span>
    <a href="#qwen-38-27b-local-the-most-laborious-run-of-the-year" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>In the previous article I said I&rsquo;d only test a new local model if strong evidence showed up. Then the Max sibling scored 92, the open 27B version was available, and I had the excuse I was missing. It was worth it for the science, but it took work.</p>
<p>First surprise: the 3.8 27B uses a hybrid SSM/Mamba architecture, and my tuned llama.cpp llama-swap build <strong>can&rsquo;t load the model</strong> — a tensor is missing (<code>ssm_conv1d</code>) that only newer versions know about. The fix was spinning up a fresh Ollama container, which bundles a current llama.cpp, and importing the GGUF I had already downloaded via a Modelfile. First lesson: with local models, the tooling ages in months.</p>
<p>Second surprise: context. A reasoning model burns an absurd number of tokens thinking, and a small window won&rsquo;t do — at 32K or 64K it doesn&rsquo;t even finish the test, exhausting everything reading the gem&rsquo;s source before writing the first line of the app. The official run needed <strong>176K of context</strong>, nearly everything the RTX 5090&rsquo;s 32 GB can hold. What stopped the model from finishing was a context ceiling, not lack of capability.</p>
<p>Then came the incident. The first run completed — and completed too well. I went through the log: the model had read the online Qwen 3.8 Max&rsquo;s finished app <strong>sixteen times</strong>, sitting right there in the repository, and copied its UI and streaming. It would have taken some 75 points on someone else&rsquo;s work. I voided it and reran with no third-party app anywhere near. And as the Gemini section above shows, it&rsquo;s not just the locals who look for help when help is lying around.</p>
<blockquote>
  <p><strong>Remember this:</strong> a weak local model doesn&rsquo;t just invent nonexistent APIs — it also copies from the neighbor when the neighbor is in the same directory.</p>

</blockquote>
<p>With no neighbors around, the 27B scored <strong>51 points, Tier C</strong> — tied, by coincidence, with the online Qwen 3.7 Max&rsquo;s score. And the receipt is mixed. The core it got right: real <code>add_message</code>, real <code>with_tools</code>, a recursive-descent calculator with no <code>eval</code>, the payoff of actually reading the gem&rsquo;s source. Where it sank was breadth: it used ActiveRecord where the requirements forbid it, the streaming comes out broken (the tokens are broadcast, but the reply bubble never enters the screen — it only appears if you refresh the page), it didn&rsquo;t use <code>with_schema</code>, it built no token budget, it delivered <strong>zero tests</strong>, RuboCop flagged 22 offenses, and no Dockerfile came out at all. The self-review, though, was exemplary: it found and confessed every one of those flaws itself, with file and line — 14 of the 15 honesty points. It reviews better than it builds.</p>
<p>Cost of the run: nothing, 37 million tokens, and 156 minutes of a sweating RTX 5090.</p>
<p>To calibrate the 51: the Tier A floor is <strong>Opus 4.6 at 83</strong>. The 32-point gap isn&rsquo;t in &ldquo;knowing the library&rdquo; — the 27B now gets that right. It&rsquo;s in the production-hardening dimensions: streaming, tests, gates, Docker, budgeting. It&rsquo;s the difference between knowing how to program and knowing how to deliver.</p>
<p>And comparing with the earlier locals — always with the caveat that the tests aren&rsquo;t comparable: in v1, the local Qwens hallucinated the gem wholesale (one invented an <code>Openrouter::Client</code> with the wrong capitalization, another created a <code>RubyLLM::Client</code> that doesn&rsquo;t exist). The Qwen 3.5 35B got the entry point right, but its tests wrapped any exception in an <code>assert true</code>. The 3.6 35B was the first local to get the primary calls right, still with broken multi-turn. The 3.8 27B gets the entire API core right on a much harder test. The score you can&rsquo;t compare; the behavior you can: API knowledge is no longer the locals&rsquo; problem. The problem now is engineering.</p>
<h2>Grok 4.6: the first flat generation, and the cleanest run<span class="hx:absolute hx:-mt-20" id="grok-46-the-first-flat-generation-and-the-cleanest-run"></span>
    <a href="#grok-46-the-first-flat-generation-and-the-cleanest-run" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>After two cheating busts, a breather. I ran Grok 4.6 with the shielding cranked all the way up: I moved everything out of the model&rsquo;s reach — the grading rubric, the entire v2 report, the audit scanner, <code>CLAUDE.md</code>&rsquo;s deduction catalog, and all 44 competitor apps, all pulled out of the repo. It was the first run under that stricter regime. And the post-run scan turned up nothing: zero reads of any grading file, zero peeks at a sibling app. It ran clean. After Gemini and the local Qwen, it&rsquo;s good to watch a frontier model build on its own because it had nowhere to crib from.</p>
<p>The result has a curious detail: <strong>92 points, Tier A, the same score as Grok 4.5.</strong> It&rsquo;s the first generation-over-generation tie in the whole test. While GLM climbed 83, 92, 94, Kimi went 77 to 86 to 95, and Claude ratcheted up without a stumble, Grok walked sideways. The 4.6 bought nothing over the 4.5. In the table up top the 4.5 shows 91 because I use its grok CLI number, its native harness; head to head in the same OpenCode, the two land on a dead-even 92.</p>
<p>What it delivered is solid and real. Correct RubyLLM API end to end, a hand-written calculator with no <code>eval</code> (regex tokenizer and parser, proven live with <code>(12.5*4)/2+7 = 32.0</code>), a test checking the exact array sent to the provider, a file store with a lock surviving restart with two workers, a token budget with a fallback estimator, and <code>docker compose up --build</code> answering a real chat. Streaming was proven live in phase 2: five tokens arriving incrementally while the POST was still open. And it was the thriftiest of all the Tier A OpenCode runs, at 10 million tokens, because Grok is terse. It cost $6.33 and 34 minutes.</p>
<p>The deductions are honest, and it confessed them itself. The lock doesn&rsquo;t cover the read-modify-write window, so two simultaneous turns on the same conversation become a last-writer-wins race, the same hazard as GLM 5.2. Test coverage is thin on the critical path, with the integration test being just a home-page smoke test. And it kept the stale <code>claude-sonnet-4.6</code> pin, the house&rsquo;s default deduction. A self-review of 12 PASS and 2 PARTIAL, all verified by the auditor. No new brilliance: it&rsquo;s a good model repeating a good model.</p>
<p>Then I ran the same Grok 4.6 on its native harness, the grok CLI, to see if anything changed. Not much did: <strong>93 on the grok CLI against 92 on OpenCode</strong>, one point apart, inside the noise. No harness effect. The CLI neither scaffolded nor broke anything; Grok builds plenty competently on either one.</p>
<p>That extra point has a concrete, mundane explanation: by chance, the CLI run locked the store&rsquo;s entire read-modify-write window under a single <code>File::LOCK_EX</code>, so concurrency went to 9; the OpenCode run left that race open and stayed at 8. Same model, one run each: the difference is variance between the two code generations. The harness played no part in it. What actually changed was the cost: on the grok CLI the same test came in at <strong>$1.19</strong>, against OpenCode&rsquo;s $6.33, for the same ~11 million tokens, thanks to xAI&rsquo;s native caching.</p>
<blockquote>
  <p><strong>Remember this:</strong> not every new generation buys a point. Grok 4.6 tied itself, and the good news was passing clean through the toughest shielding I&rsquo;ve applied yet.</p>

</blockquote>
<h2>Conclusion: how close did they get?<span class="hx:absolute hx:-mt-20" id="conclusion-how-close-did-they-get"></span>
    <a href="#conclusion-how-close-did-they-get" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Short answer: very close.</p>
<table>
  <thead>
      <tr>
          <th>Model</th>
          <th style="text-align: right">Score</th>
          <th style="text-align: center">Tier</th>
          <th style="text-align: right">Time</th>
          <th>Cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GLM 5.3</td>
          <td style="text-align: right"><strong>94</strong></td>
          <td style="text-align: center">A</td>
          <td style="text-align: right">80 min</td>
          <td>$0 on the plan (~$2.59 API)</td>
      </tr>
      <tr>
          <td>Gemini 3.7 Flash</td>
          <td style="text-align: right"><strong>93</strong></td>
          <td style="text-align: center">A</td>
          <td style="text-align: right">43 min</td>
          <td>$4.12</td>
      </tr>
      <tr>
          <td>Qwen 3.8 Max</td>
          <td style="text-align: right"><strong>92</strong></td>
          <td style="text-align: center">A</td>
          <td style="text-align: right">78 min</td>
          <td>$9.16 API</td>
      </tr>
      <tr>
          <td>Grok 4.6</td>
          <td style="text-align: right"><strong>92</strong></td>
          <td style="text-align: center">A</td>
          <td style="text-align: right">34 min</td>
          <td>$6.33 API</td>
      </tr>
      <tr>
          <td>Qwen 3.8 27B local</td>
          <td style="text-align: right"><strong>51</strong></td>
          <td style="text-align: center">C</td>
          <td style="text-align: right">156 min</td>
          <td>$0</td>
      </tr>
  </tbody>
</table>
<p>GLM 5.3 two points from Fable 5 is not a &ldquo;cheap alternative&rdquo; — it&rsquo;s a leadership candidate. Qwen 3.8 Max one point from Sol and Terra, same thing. The distance between the American cream and the new Chinese models is one or two points — and I repeat in every article that one or two points is noise. And Gemini 3.7 Flash joined that pile: 93, tied with Sol, Terra, and Opus 4.8, the first Gemini to get there on opencode. Grok 4.6 landed in the same bucket of 92s, but with an asterisk all its own: it was the only new generation that improved on nothing over its predecessor, and even so it was the first to pass clean through the toughest shielding.</p>
<p>And local remains out of the question for an autonomous coding agent: Tier C is Tier C. But notice how the conversation has changed. Until recently I dismissed local because it invented APIs. Today it knows the API and trips on streaming, tests, and Docker — and it needs 176K of context and 32 GB of VRAM just to complete the test. The bottleneck moved up a level. It&rsquo;s not a recommendation yet; it&rsquo;s the road being paved.</p>
<blockquote>
  <p><strong>Remember this:</strong> the cream of the crop is still Fable, Opus, Sonnet, K3, and the GPT 5.6 family. But the chasing pack is already one or two points behind — and the moat between &ldquo;frontier&rdquo; and &ldquo;alternative&rdquo; has become noise territory.</p>

</blockquote>
<p>As always: artifacts, logs, rubric, deductions, and the updated table are in the <a href="https://github.com/akitaonrails/llm-coding-benchmark"target="_blank" rel="noopener">llm-coding-benchmark</a>. Both Gemini 3.7 runs — the voided one and the official one — are documented in the report, with the contamination finding front and center.</p>
]]></content:encoded><category>llm-benchmarks</category><category>llms</category><category>coding-agents</category></item><item><title>New LLM Benchmark: I Reran Every Test!</title><link>https://akitaonrails.github.io/en/2026/07/30/new-llm-benchmark-i-reran-every-test/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/07/30/new-llm-benchmark-i-reran-every-test/</guid><pubDate>Thu, 30 Jul 2026 15:00:00 -0300</pubDate><description>&lt;p&gt;Five days ago I published my &lt;a href="https://akitaonrails.github.io/en/2026/07/25/llm-benchmark-is-opus-5-any-good/"&gt;Claude Opus 5 test&lt;/a&gt;. Eleven days ago I explained &lt;a href="https://akitaonrails.github.io/en/2026/07/19/llm-benchmark-should-i-use-the-highest-scoring-model/"&gt;why the highest score in a ranking does not mean &amp;ldquo;the best LLM&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Great. The table in the first article is already a museum piece.&lt;/p&gt;
&lt;p&gt;The argument in the second one still stands. In fact, it got even easier to demonstrate because I spent the last few days rerunning practically the entire benchmark. That meant dozens of runs, several discarded attempts, hundreds of dollars between API charges and credit equivalents, and an indecent amount of time reading robot-generated Rails code.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Five days ago I published my <a href="/en/2026/07/25/llm-benchmark-is-opus-5-any-good/">Claude Opus 5 test</a>. Eleven days ago I explained <a href="/en/2026/07/19/llm-benchmark-should-i-use-the-highest-scoring-model/">why the highest score in a ranking does not mean &ldquo;the best LLM&rdquo;</a>.</p>
<p>Great. The table in the first article is already a museum piece.</p>
<p>The argument in the second one still stands. In fact, it got even easier to demonstrate because I spent the last few days rerunning practically the entire benchmark. That meant dozens of runs, several discarded attempts, hundreds of dollars between API charges and credit equivalents, and an indecent amount of time reading robot-generated Rails code.</p>
<p>The result is <strong>version 2</strong> of my <a href="https://github.com/akitaonrails/llm-coding-benchmark"target="_blank" rel="noopener">LLM Coding Benchmark</a>. The test got harder, the audit became more explicit, and each family now runs, whenever possible, in the harness where it should work best.</p>
<p>I&rsquo;ll say this up front: <strong>v2 scores are not directly comparable to v1 scores</strong>. The prompt changed. So did the requirements, several model-harness pairings, the validation, and the rubric. The <code>v1</code> column in the report is historical context, not a scientific measurement of how much each model &ldquo;improved.&rdquo;</p>
<h2>Why I retired v1<span class="hx:absolute hx:-mt-20" id="why-i-retired-v1"></span>
    <a href="#why-i-retired-v1" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>We ran v1 for months. It did a good job separating models that could actually build a Rails app from those that invented RubyLLM APIs, wrote tests for their own hallucinations, and shipped Dockerfiles that never came up.</p>
<p>Then the newer models hit the ceiling of that test. Fifteen of the forty results were already packed into Tier A, with the top compressed between 92 and 97. The job still had real details, but the best models cleared the old discriminators easily. The order started coming down to an API-key preflight here, a cookie limit there, one missing error test. Valid details, not much separation.</p>
<p>There was another operational inconsistency: the model-harness pairing. Claude had been tested in OpenCode. So had Grok, Kimi, and Gemini. Today we have Claude Code, Codex, Kimi Code CLI, grok CLI, and Antigravity. Measuring a model in a generic harness when an integration tailored to its behavior exists can distort the result.</p>
<p>The benchmark was never measuring the weights file alone:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">result = model + harness + prompt + tools + context + execution + audit</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>So I stopped hiding the harness inside the score. Claude moved to Claude Code. GPT moved to Codex. Kimi K3 and K2.7-Coding moved to Kimi CLI. Grok and Gemini got A/B runs in their vendors&rsquo; own CLIs. A fully isolated OpenCode remained the fallback for models without a better harness or subscription access.</p>
<h2>The new test<span class="hx:absolute hx:-mt-20" id="the-new-test"></span>
    <a href="#the-new-test" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>V1 had two phases: build the app and try to bring it up. V2 has <strong>three phases</strong>, fourteen numbered goals, and a ten-dimension rubric.</p>
<p>In phase one, the model still has to build a ChatGPT-style chat app on its own in Rails with RubyLLM, Hotwire, Tailwind, Minitest, Docker, and Compose. That&rsquo;s where the resemblance ends. Now it must also deliver:</p>
<ul>
<li>real per-token streaming through Turbo Streams, proven to be incremental;</li>
<li>a correct multi-turn payload that does not send the current message twice, plus a test for the exact array sent to the provider;</li>
<li>persistence that survives a restart and works with <code>WEB_CONCURRENCY=2</code>, with a TTL plus message-count and byte limits;</li>
<li>exactly two tools, <code>server_time</code> and a safe calculator, using the real RubyLLM API;</li>
<li>a title generated through the structured-output API;</li>
<li>a per-conversation token budget;</li>
<li>a system prompt, credential preflight, degraded states, and provider-error handling;</li>
<li>a guarantee that failed turns never contaminate future history;</li>
<li>clean RuboCop, Brakeman, and bundle-audit runs, plus a non-root production Docker image and no secrets.</li>
</ul>
<p>Phase two does not accept a README claiming everything works. It boots Rails, watches the tokens arrive, forces real tool calls, holds a conversation across two workers, restarts the server, checks the history, runs tests and gates, executes <code>docker build</code>, and sends a real message to the app inside Compose.</p>
<p>Phase three asks the model to review every goal as <code>PASS</code>, <code>PARTIAL</code>, or <code>FAIL</code>, cite a file, line, test, or command, and write down what is still broken. That honesty is worth 15 points. An accurate <code>FAIL</code> is worth more than an optimistic <code>PASS</code> that the audit disproves.</p>
<p>This phase produced data v1 never had. Kimi K3 and Nex, for example, admitted defects that would have been easy to hide. Others built a reasonable app and then hallucinated their own inspection. Programming and reviewing what you programmed are different capabilities.</p>
<h2>The harness became part of the test<span class="hx:absolute hx:-mt-20" id="the-harness-became-part-of-the-test"></span>
    <a href="#the-harness-became-part-of-the-test" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I also ran A/B tests with the native tools:</p>
<table>
  <thead>
      <tr>
          <th>Model</th>
          <th style="text-align: right">Clean OpenCode</th>
          <th style="text-align: right">Native harness</th>
          <th>Reading</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Grok 4.5</td>
          <td style="text-align: right">92</td>
          <td style="text-align: right">91 in grok CLI</td>
          <td>difference within the noise</td>
      </tr>
      <tr>
          <td>Grok 4.3</td>
          <td style="text-align: right">18</td>
          <td style="text-align: right">55 in grok CLI</td>
          <td>native scaffolding rescues it, but it remains weak</td>
      </tr>
      <tr>
          <td>Gemini 3.1 Pro</td>
          <td style="text-align: right">62</td>
          <td style="text-align: right">88 in Antigravity</td>
          <td>the direct path avoids a provider bug</td>
      </tr>
      <tr>
          <td>Gemini 3.6 Flash</td>
          <td style="text-align: right">not run</td>
          <td style="text-align: right">92 in Antigravity</td>
          <td>good result, no comparable baseline</td>
      </tr>
  </tbody>
</table>
<p>A native harness does not sprinkle magic dust on a model. Grok 4.5 barely cared. Grok 4.3 needed the structure. Gemini 3.1 needed a transport that would not break on <code>Corrupted thought signature</code>. Three different mechanisms that a rushed comparison would flatten into &ldquo;the CLI improved the score.&rdquo;</p>
<p>In the ranking below, I use the preferred harness whenever a complete run exists: Antigravity for the Geminis and grok CLI for the Groks. The OpenCode baselines remain in the repository as A/B data, but do not appear a second time in the table.</p>
<h2>The new ranking<span class="hx:absolute hx:-mt-20" id="the-new-ranking"></span>
    <a href="#the-new-ranking" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>This is the consolidated v2 table, with one entry per model in the preferred available harness.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right">#</th>
          <th>Model</th>
          <th style="text-align: right">Score</th>
          <th style="text-align: center">Tier</th>
          <th>Harness</th>
          <th style="text-align: right">Time</th>
          <th style="text-align: right">Cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">1</td>
          <td>Claude Fable 5</td>
          <td style="text-align: right"><strong>96</strong></td>
          <td style="text-align: center">A.1</td>
          <td>Claude Code</td>
          <td style="text-align: right">46 min</td>
          <td style="text-align: right">$26.03</td>
      </tr>
      <tr>
          <td style="text-align: right">2</td>
          <td>Claude Sonnet 5</td>
          <td style="text-align: right"><strong>95</strong></td>
          <td style="text-align: center">A.1</td>
          <td>Claude Code</td>
          <td style="text-align: right">59 min</td>
          <td style="text-align: right">$25.83</td>
      </tr>
      <tr>
          <td style="text-align: right">2</td>
          <td>Claude Opus 5</td>
          <td style="text-align: right"><strong>95</strong></td>
          <td style="text-align: center">A.1</td>
          <td>Claude Code</td>
          <td style="text-align: right">78 min</td>
          <td style="text-align: right">$38.91</td>
      </tr>
      <tr>
          <td style="text-align: right">2</td>
          <td>Kimi K3</td>
          <td style="text-align: right"><strong>95</strong></td>
          <td style="text-align: center">A.1</td>
          <td>Kimi CLI</td>
          <td style="text-align: right">65 min</td>
          <td style="text-align: right">$6.14</td>
      </tr>
      <tr>
          <td style="text-align: right">5</td>
          <td>GPT 5.6 Sol</td>
          <td style="text-align: right"><strong>93</strong></td>
          <td style="text-align: center">A.1</td>
          <td>Codex</td>
          <td style="text-align: right">57 min</td>
          <td style="text-align: right">~$45</td>
      </tr>
      <tr>
          <td style="text-align: right">5</td>
          <td>Claude Opus 4.8</td>
          <td style="text-align: right"><strong>93</strong></td>
          <td style="text-align: center">A.1</td>
          <td>Claude Code</td>
          <td style="text-align: right">53 min</td>
          <td style="text-align: right">$21.82</td>
      </tr>
      <tr>
          <td style="text-align: right">5</td>
          <td>GPT 5.6 Terra</td>
          <td style="text-align: right"><strong>93</strong></td>
          <td style="text-align: center">A.1</td>
          <td>Codex</td>
          <td style="text-align: right">48 min</td>
          <td style="text-align: right">$16.92</td>
      </tr>
      <tr>
          <td style="text-align: right">8</td>
          <td>GLM 5.2</td>
          <td style="text-align: right"><strong>92</strong></td>
          <td style="text-align: center">A.1</td>
          <td>OpenCode</td>
          <td style="text-align: right">155 min</td>
          <td style="text-align: right">$0 (≈$12.05)</td>
      </tr>
      <tr>
          <td style="text-align: right">8</td>
          <td>Kimi K2.5</td>
          <td style="text-align: right"><strong>92</strong></td>
          <td style="text-align: center">A.1</td>
          <td>OpenCode</td>
          <td style="text-align: right">43 min</td>
          <td style="text-align: right">$1.50</td>
      </tr>
      <tr>
          <td style="text-align: right">8</td>
          <td>Gemini 3.6 Flash @ high</td>
          <td style="text-align: right"><strong>92</strong></td>
          <td style="text-align: center">A.1</td>
          <td>Antigravity</td>
          <td style="text-align: right">15 min</td>
          <td style="text-align: right">—</td>
      </tr>
      <tr>
          <td style="text-align: right">11</td>
          <td>MiniMax M3</td>
          <td style="text-align: right"><strong>91</strong></td>
          <td style="text-align: center">A.1</td>
          <td>OpenCode</td>
          <td style="text-align: right">113 min</td>
          <td style="text-align: right">$7.72</td>
      </tr>
      <tr>
          <td style="text-align: right">11</td>
          <td>Kimi K2.6</td>
          <td style="text-align: right"><strong>91</strong></td>
          <td style="text-align: center">A.1</td>
          <td>OpenCode</td>
          <td style="text-align: right">34 min</td>
          <td style="text-align: right">$2.64</td>
      </tr>
      <tr>
          <td style="text-align: right">11</td>
          <td>Claude Opus 4.7</td>
          <td style="text-align: right"><strong>91</strong></td>
          <td style="text-align: center">A.1</td>
          <td>Claude Code</td>
          <td style="text-align: right">44 min</td>
          <td style="text-align: right">$44.28</td>
      </tr>
      <tr>
          <td style="text-align: right">11</td>
          <td>GPT 5.6 Luna</td>
          <td style="text-align: right"><strong>91</strong></td>
          <td style="text-align: center">A.1</td>
          <td>Codex</td>
          <td style="text-align: right">46 min</td>
          <td style="text-align: right">$16.79</td>
      </tr>
      <tr>
          <td style="text-align: right">11</td>
          <td>Grok 4.5</td>
          <td style="text-align: right"><strong>91</strong></td>
          <td style="text-align: center">A.1</td>
          <td>grok CLI</td>
          <td style="text-align: right">25 min</td>
          <td style="text-align: right">$0 (≈$1.62)</td>
      </tr>
      <tr>
          <td style="text-align: right">16</td>
          <td>Nex-N2-Pro</td>
          <td style="text-align: right"><strong>88</strong></td>
          <td style="text-align: center">A.2</td>
          <td>OpenCode</td>
          <td style="text-align: right">8 min</td>
          <td style="text-align: right">$0.17</td>
      </tr>
      <tr>
          <td style="text-align: right">16</td>
          <td>GPT 5.5</td>
          <td style="text-align: right"><strong>88</strong></td>
          <td style="text-align: center">A.2</td>
          <td>Codex</td>
          <td style="text-align: right">57 min</td>
          <td style="text-align: right">~$53</td>
      </tr>
      <tr>
          <td style="text-align: right">16</td>
          <td>Gemini 3.1 Pro @ high</td>
          <td style="text-align: right"><strong>88</strong></td>
          <td style="text-align: center">A.2</td>
          <td>Antigravity</td>
          <td style="text-align: right">23 min</td>
          <td style="text-align: right">—</td>
      </tr>
      <tr>
          <td style="text-align: right">19</td>
          <td>Claude Sonnet 4.6</td>
          <td style="text-align: right"><strong>87</strong></td>
          <td style="text-align: center">A.2</td>
          <td>Claude Code</td>
          <td style="text-align: right">45 min</td>
          <td style="text-align: right">$9.90</td>
      </tr>
      <tr>
          <td style="text-align: right">20</td>
          <td>GPT 5.4</td>
          <td style="text-align: right"><strong>86</strong></td>
          <td style="text-align: center">A.2</td>
          <td>Codex</td>
          <td style="text-align: right">67 min</td>
          <td style="text-align: right">~$26</td>
      </tr>
      <tr>
          <td style="text-align: right">20</td>
          <td>Kimi K2.7-Coding</td>
          <td style="text-align: right"><strong>86</strong></td>
          <td style="text-align: center">A.2</td>
          <td>Kimi CLI</td>
          <td style="text-align: right">54 min</td>
          <td style="text-align: right">$4.37</td>
      </tr>
      <tr>
          <td style="text-align: right">22</td>
          <td>Step 3.7 Flash</td>
          <td style="text-align: right"><strong>84</strong></td>
          <td style="text-align: center">A.2</td>
          <td>OpenCode</td>
          <td style="text-align: right">81 min</td>
          <td style="text-align: right">$1.41</td>
      </tr>
      <tr>
          <td style="text-align: right">23</td>
          <td>Claude Opus 4.6</td>
          <td style="text-align: right"><strong>83</strong></td>
          <td style="text-align: center">A.2</td>
          <td>Claude Code</td>
          <td style="text-align: right">39 min</td>
          <td style="text-align: right">$12.83</td>
      </tr>
      <tr>
          <td style="text-align: right">23</td>
          <td>GLM 5</td>
          <td style="text-align: right"><strong>83</strong></td>
          <td style="text-align: center">A.2</td>
          <td>OpenCode</td>
          <td style="text-align: right">31 min</td>
          <td style="text-align: right">$1.97</td>
      </tr>
      <tr>
          <td style="text-align: right">25</td>
          <td>DeepSeek V4 Pro</td>
          <td style="text-align: right"><strong>82</strong></td>
          <td style="text-align: center">B</td>
          <td>OpenCode</td>
          <td style="text-align: right">57 min</td>
          <td style="text-align: right">$0.35</td>
      </tr>
      <tr>
          <td style="text-align: right">26</td>
          <td>DeepSeek V4 Flash</td>
          <td style="text-align: right"><strong>80</strong></td>
          <td style="text-align: center">B</td>
          <td>OpenCode</td>
          <td style="text-align: right">36 min</td>
          <td style="text-align: right">$0.81</td>
      </tr>
      <tr>
          <td style="text-align: right">27</td>
          <td>Qwen 3.6 Plus</td>
          <td style="text-align: right"><strong>76</strong></td>
          <td style="text-align: center">B</td>
          <td>OpenCode</td>
          <td style="text-align: right">75 min</td>
          <td style="text-align: right">$7.63</td>
      </tr>
      <tr>
          <td style="text-align: right">28</td>
          <td>MiMo V2.5 Pro</td>
          <td style="text-align: right"><strong>73</strong></td>
          <td style="text-align: center">B</td>
          <td>OpenCode</td>
          <td style="text-align: right">23 min</td>
          <td style="text-align: right">$0.22</td>
      </tr>
      <tr>
          <td style="text-align: right">29</td>
          <td>Grok 4.3</td>
          <td style="text-align: right"><strong>55</strong></td>
          <td style="text-align: center">C</td>
          <td>grok CLI</td>
          <td style="text-align: right">6 min</td>
          <td style="text-align: right">$0 (≈$0.18)</td>
      </tr>
      <tr>
          <td style="text-align: right">30</td>
          <td>Qwen3.7 Max</td>
          <td style="text-align: right"><strong>51</strong></td>
          <td style="text-align: center">C</td>
          <td>OpenCode</td>
          <td style="text-align: right">41 min</td>
          <td style="text-align: right">$2.59</td>
      </tr>
      <tr>
          <td style="text-align: right">31</td>
          <td>Step 3.5 Flash</td>
          <td style="text-align: right"><strong>27</strong></td>
          <td style="text-align: center">D</td>
          <td>OpenCode</td>
          <td style="text-align: right">47 min</td>
          <td style="text-align: right">$0.92</td>
      </tr>
  </tbody>
</table>
<p><em>Time is end-to-end wall clock across the three phases. Cost is API-equivalent: for models on Codex I use the cache-discounted blended figure (same criterion as the cost section below); on subscription plans (Z.ai, grok CLI) the marginal cost is $0 and the number in parentheses is the API-equivalent; the Antigravity runs were preview and were not metered.</em></p>
<p>The details, artifacts, and deductions are in the <a href="https://github.com/akitaonrails/llm-coding-benchmark/blob/master/docs/success_report.v2.md"target="_blank" rel="noopener">full v2 report</a>.</p>
<h2>What the tiers mean now<span class="hx:absolute hx:-mt-20" id="what-the-tiers-mean-now"></span>
    <a href="#what-the-tiers-mean-now" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The new cutoff is anchored on Claude Opus 4.6, which scored 83 and showed the minimum needed to carry the entire test. Here&rsquo;s the practical interpretation:</p>
<table>
  <thead>
      <tr>
          <th style="text-align: center">Tier</th>
          <th style="text-align: right">Score</th>
          <th>How I read it</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: center"><strong>A.1</strong></td>
          <td style="text-align: right"><strong>90 or higher</strong></td>
          <td>The frontier of this test. More complete and consistent delivery; differences of one or two points inside the group remain noise.</td>
      </tr>
      <tr>
          <td style="text-align: center"><strong>A.2</strong></td>
          <td style="text-align: right"><strong>83 to 89</strong></td>
          <td>Suitable for programming and past the same competence floor, but with more visible fixes or limitations. I still recommend these models, with closer review.</td>
      </tr>
      <tr>
          <td style="text-align: center"><strong>B</strong></td>
          <td style="text-align: right"><strong>73 to 82</strong></td>
          <td>Close, but it still needs human cleanup in an important area. I do not recommend it for autonomous work; I keep it on the radar.</td>
      </tr>
      <tr>
          <td style="text-align: center"><strong>C</strong></td>
          <td style="text-align: right"><strong>51 to 72</strong></td>
          <td>I do not recommend it for programming. It may still work for translation, summarization, classification, and simple agents.</td>
      </tr>
      <tr>
          <td style="text-align: center"><strong>D</strong></td>
          <td style="text-align: right"><strong>50 or lower</strong></td>
          <td>Inconsistent, broken, or difficult-to-predict behavior. I do not feel safe recommending it even for simple automation.</td>
      </tr>
  </tbody>
</table>
<p>There are <strong>15 models in A.1</strong> and <strong>9 in A.2</strong>. All 24 cleared the competence floor for this kind of work. The subdivision helps decide where to start: A.1 contains the frontier results; A.2 contains capable models that needed more fixes, left shallower tests, or carried clearer operational limitations.</p>
<p>That does not make 96 universally more intelligent than 91, nor does it make an A.2 model bad. An A.2 model may be better at refactoring, debugging, frontend work, or inside your fifteen-year-old monolith. This test does not measure all of that. The cutoff simply avoids throwing 24 options into one oversized bucket.</p>
<p>A.1 and A.2 make up the candidate pool. I cut Tier C and D before I start.</p>
<h2>So which one is best: Fable, Opus, Terra, or Kimi?<span class="hx:absolute hx:-mt-20" id="so-which-one-is-best-fable-opus-terra-or-kimi"></span>
    <a href="#so-which-one-is-best-fable-opus-terra-or-kimi" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>If all you want is a one-line answer, you&rsquo;re going to be disappointed again.</p>
<table>
  <thead>
      <tr>
          <th>Model</th>
          <th style="text-align: right">Score</th>
          <th style="text-align: right">Time</th>
          <th style="text-align: right">API equivalent</th>
          <th>Practical use</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Claude Fable 5</td>
          <td style="text-align: right">96</td>
          <td style="text-align: right">46 min</td>
          <td style="text-align: right">$26.03</td>
          <td>Claude Max subscription</td>
      </tr>
      <tr>
          <td>Claude Opus 5</td>
          <td style="text-align: right">95</td>
          <td style="text-align: right">78 min</td>
          <td style="text-align: right">$38.91</td>
          <td>Claude Max subscription</td>
      </tr>
      <tr>
          <td>Kimi K3</td>
          <td style="text-align: right">95</td>
          <td style="text-align: right">65 min</td>
          <td style="text-align: right">$6.14</td>
          <td>Moderato subscription</td>
      </tr>
      <tr>
          <td>GPT 5.6 Terra</td>
          <td style="text-align: right">93</td>
          <td style="text-align: right">49 min</td>
          <td style="text-align: right">$16.92 blended</td>
          <td>ChatGPT credits</td>
      </tr>
  </tbody>
</table>
<p>On the final artifact, <strong>Fable won</strong>. It was also the fastest of these four. If I were paying for every API call in this run, <strong>Kimi K3 won on cost by a mile</strong>, tying Opus at 95 and landing only one point behind Fable.</p>
<p>Opus 5 built an excellent project, but it was the slowest and burned 56.8 million tokens as counted by Claude Code. In this test, the extra 33 minutes over Fable bought nothing visible. Terra also delivered good work, finished two points behind K3, and cost less than Fable and Opus at API-equivalent rates.</p>
<p>If you already pay for Claude Max or ChatGPT Pro, the marginal cost stays near zero while you remain within the limits. Kimi Moderato is also a subscription, with its own quota windows. So &ldquo;$26 versus $6&rdquo; does not settle anything by itself. The first question is which subscription you already pay for and how much room it has left. For pay-as-you-go and automation, per-run cost moves back to center stage.</p>
<p>My reading of this run:</p>
<ul>
<li><strong>Fable 5</strong> delivered the best combination of quality and time;</li>
<li><strong>Kimi K3</strong> offered the best value among the leaders;</li>
<li><strong>Opus 5</strong> was capable and meticulous, but expensive and slow in this execution;</li>
<li><strong>GPT 5.6 Terra</strong> delivered the best balance in the family if you live in Codex.</li>
</ul>
<p>That&rsquo;s a reading of this project. Change the workload and the order may flip.</p>
<h2>Opus versus Sonnet, Sol versus Terra<span class="hx:absolute hx:-mt-20" id="opus-versus-sonnet-sol-versus-terra"></span>
    <a href="#opus-versus-sonnet-sol-versus-terra" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>A tier name is not a benchmark. Sonnet 5 proved that in an almost embarrassing way:</p>
<table>
  <thead>
      <tr>
          <th>Claude</th>
          <th style="text-align: right">Score</th>
          <th style="text-align: right">Time</th>
          <th style="text-align: right">Recorded cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Fable 5</td>
          <td style="text-align: right">96</td>
          <td style="text-align: right">46 min</td>
          <td style="text-align: right">$26.03 API equivalent</td>
      </tr>
      <tr>
          <td>Opus 5</td>
          <td style="text-align: right">95</td>
          <td style="text-align: right">78 min</td>
          <td style="text-align: right">$38.91 API equivalent</td>
      </tr>
      <tr>
          <td>Sonnet 5</td>
          <td style="text-align: right">95</td>
          <td style="text-align: right">59 min</td>
          <td style="text-align: right">$25.83 subscription equivalent</td>
      </tr>
      <tr>
          <td>Opus 4.8</td>
          <td style="text-align: right">93</td>
          <td style="text-align: right">53 min</td>
          <td style="text-align: right">$21.82 subscription equivalent</td>
      </tr>
  </tbody>
</table>
<p>Sonnet 5 tied Opus 5, finished nineteen minutes earlier, and produced the first genuine 100% line coverage in the entire benchmark. It also wrote the family&rsquo;s best self-review. Automatically choosing Opus because &ldquo;Opus is the higher tier&rdquo; would mean throwing out your own data.</p>
<p>This also corrects a terrible impression from v1, where Sonnet 5 scored 58 and hallucinated the RubyLLM API. In v2 it ran through Claude Code, received explicit requirements, and scored 95. We cannot conclude that the model improved by 37 points because we changed practically the entire experiment. We can conclude that the v1 pairing was a poor representation of what it can do.</p>
<p>On the OpenAI side:</p>
<table>
  <thead>
      <tr>
          <th>GPT</th>
          <th style="text-align: right">Score</th>
          <th style="text-align: right">Time</th>
          <th style="text-align: right">Blended equivalent cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>GPT 5.6 Sol</td>
          <td style="text-align: right">93</td>
          <td style="text-align: right">57 min</td>
          <td style="text-align: right">~$45</td>
      </tr>
      <tr>
          <td>GPT 5.6 Terra</td>
          <td style="text-align: right">93</td>
          <td style="text-align: right">49 min</td>
          <td style="text-align: right">$16.92</td>
      </tr>
      <tr>
          <td>GPT 5.6 Luna</td>
          <td style="text-align: right">91</td>
          <td style="text-align: right">46 min</td>
          <td style="text-align: right">$16.79</td>
      </tr>
      <tr>
          <td>GPT 5.5</td>
          <td style="text-align: right">88</td>
          <td style="text-align: right">58 min</td>
          <td style="text-align: right">~$53</td>
      </tr>
      <tr>
          <td>GPT 5.4</td>
          <td style="text-align: right">86</td>
          <td style="text-align: right">67 min</td>
          <td style="text-align: right">~$26</td>
      </tr>
  </tbody>
</table>
<p>Terra tied Sol at 93, finished eight minutes sooner, and cost a little more than one-third as much in the blended calculation. It also produced the best concurrency protection in the entire run: Redis with <code>WATCH</code>/<code>MULTI</code>, a distributed per-conversation lock, and forced tool choice. On this test, paying for Sol bought no points and saved no time. Terra is the most rational pick in the family.</p>
<p>Luna stays in the table because it scored 91 and remains an A.1 result, but its cost argument is gone: Terra scored two points higher for only thirteen cents more and took about three extra minutes.</p>
<p>Cache remains the important detail. Of Terra&rsquo;s 21.7 million input tokens, 21 million were cache hits. Pricing everything as fresh input would produce an upper bound of $111.62. At the cache rate, it falls to $16.92. Any cost table that mixes CLIs without understanding what each one reports is comparing apples to JSON.</p>
<h2>What about the Chinese models?<span class="hx:absolute hx:-mt-20" id="what-about-the-chinese-models"></span>
    <a href="#what-about-the-chinese-models" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The line about Chinese models being useful only as cheaper alternatives is stale.</p>
<table>
  <thead>
      <tr>
          <th>Model</th>
          <th style="text-align: right">Score</th>
          <th style="text-align: center">Tier</th>
          <th style="text-align: right">Time</th>
          <th style="text-align: right">Reported cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Kimi K3</td>
          <td style="text-align: right">95</td>
          <td style="text-align: center">A.1</td>
          <td style="text-align: right">65 min</td>
          <td style="text-align: right">$6.14 equivalent, subscription</td>
      </tr>
      <tr>
          <td>Kimi K2.5</td>
          <td style="text-align: right">92</td>
          <td style="text-align: center">A.1</td>
          <td style="text-align: right">43 min</td>
          <td style="text-align: right">$1.50, API</td>
      </tr>
      <tr>
          <td>Kimi K2.6</td>
          <td style="text-align: right">91</td>
          <td style="text-align: center">A.1</td>
          <td style="text-align: right">34 min</td>
          <td style="text-align: right">$2.64, API</td>
      </tr>
      <tr>
          <td>Kimi K2.7-Coding</td>
          <td style="text-align: right">86</td>
          <td style="text-align: center">A.2</td>
          <td style="text-align: right">54 min</td>
          <td style="text-align: right">$4.37 equivalent, subscription</td>
      </tr>
      <tr>
          <td>MiniMax M3</td>
          <td style="text-align: right">91</td>
          <td style="text-align: center">A.1</td>
          <td style="text-align: right">113 min</td>
          <td style="text-align: right">$7.72, API</td>
      </tr>
      <tr>
          <td>GLM 5.2</td>
          <td style="text-align: right">92</td>
          <td style="text-align: center">A.1</td>
          <td style="text-align: right">155 min</td>
          <td style="text-align: right">$0 marginal on the subscription, $12.05 API equivalent</td>
      </tr>
      <tr>
          <td>DeepSeek V4 Pro</td>
          <td style="text-align: right">82</td>
          <td style="text-align: center">B</td>
          <td style="text-align: right">57 min</td>
          <td style="text-align: right">$0.35, API</td>
      </tr>
      <tr>
          <td>DeepSeek V4 Flash</td>
          <td style="text-align: right">80</td>
          <td style="text-align: center">B</td>
          <td style="text-align: right">36 min</td>
          <td style="text-align: right">$0.81, API</td>
      </tr>
  </tbody>
</table>
<p>Kimi K3 tied Opus 5. K2.5, K2.6, MiniMax M3, and GLM 5.2 landed in the same A.1 as Claude and GPT. The OpenCode runs are still cheaper than the $16 to $45 range of the leaders run through Claude Code and Codex, but this is no longer a comparison between pennies and dozens of dollars. And a subscription is not an API: GLM had zero marginal cost because it ran on Z.ai&rsquo;s plan; the same usage would cost about $12.05 through the API.</p>
<p>Kimi is the easiest family to recommend today. K3 offers top-tier quality through a cheap subscription. K2.5 and K2.6 were economical over the API, costing $1.50 and $2.64. K2.7 landed below its siblings, but it ran in another harness, so I am not going to invent a tidy progression story from four isolated data points.</p>
<p>MiniMax M3 deserves attention and caution in equal measure. It scored 91 for $7.72, still less than one run through the American leaders, but burned 121 million tokens and took almost two hours. It was the most expensive and token-hungry OpenCode run. The score is good; the usage profile, not so much.</p>
<p>GLM 5.2 scored 92 at zero marginal cost on Z.ai&rsquo;s plan, but consumed the equivalent of $12.05 through the API. It took about two and a half hours. If wall-clock time does not matter, it is a very strong option. If you work in short cycles, Grok 4.5 delivered 91 in about 25 minutes through grok CLI, more than six times faster.</p>
<p>DeepSeek remains cheap, but stopped in Tier B. V4 Pro scored 82 for $0.35 and V4 Flash scored 80 for $0.81. They&rsquo;re close, and I want to repeat the test when a new version arrives. Today I still would not leave either one working alone as a coding agent in a codebase that matters. Saving one or two dollars only to spend an hour reviewing a structural defect is lousy math.</p>
<h2>Why I did not rerun the local models<span class="hx:absolute hx:-mt-20" id="why-i-did-not-rerun-the-local-models"></span>
    <a href="#why-i-did-not-rerun-the-local-models" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I did not run Qwen 3.5 or the other local models on v2. The priority shifted to mapping the programming Tier A more accurately, and every complete run of this test costs machine time, audit time, and sanity.</p>
<p>Local models are not useless. They work for translation, classification, summarization, controlled one-shots, and tasks where privacy or offline operation matters more than quality. For autonomous coding agents, though, the v1 tests landed far below the floor. V2 is harder. I see no reason to spend several more days confirming that a quantized local Qwen cannot compete with Fable, Opus, GPT 5.6, or Kimi in software engineering.</p>
<p>For programming, it is not worth it today. If a new local model appears with strong evidence behind it, I&rsquo;ll test it. Until then, I&rsquo;d rather spend my time separating the twenty-four models that have already cleared the floor.</p>
<h2>Conclusion<span class="hx:absolute hx:-mt-20" id="conclusion"></span>
    <a href="#conclusion" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>V1 did its job and saturated. V2 puts pressure where today&rsquo;s models still slip: real streaming, multi-turn payloads, concurrency, persistence, tools, structured output, budgeting, operational security, faithful tests, and the ability to admit their own defects.</p>
<p>Fable 5 finished on top with 96. Sonnet 5, Opus 5, and Kimi K3 tied at 95. Sol and Terra came right behind them at 93. That answers which models produced the best projects on this test.</p>
<p>Choosing what to use is a different reading:</p>
<ul>
<li>Tier A.1 contains the 15 frontier results, all scoring 90 or higher;</li>
<li>Tier A.2 contains 9 capable models from 83 to 89, still worth recommending with closer review;</li>
<li>Tier B is close, but I still do not recommend it for autonomous work;</li>
<li>Tier C is for translation, summarization, and simple agents;</li>
<li>Tier D is too inconsistent for me to recommend;</li>
<li>inside Tier A, choose by subscription, speed, cost, and harness;</li>
<li>one or two points do not make anyone the universal champion of intelligence.</li>
</ul>
<p>My own choice remains concentrated on Claude Code and Codex because those are the harnesses I use every day. Within Codex, Terra delivered the best balance of score, time, and cost. Kimi K3 has become a serious top-tier alternative. Grok 4.5 is the speed champion of this round. GLM has zero marginal cost on the subscription and MiniMax still costs less than the leaders, but neither is a speed pick. Sonnet 5 proved that reflexively paying for or selecting the &ldquo;higher&rdquo; tier can be a waste.</p>
<p>All generated code, prompts, results, self-reviews, rubric details, and corrections are in <a href="https://github.com/akitaonrails/llm-coding-benchmark"target="_blank" rel="noopener">llm-coding-benchmark</a>. The major code and test overhaul is already on <code>master</code>. Contributions are welcome, whether you want to add a model, improve a harness, dispute a deduction, or find another bug in the auditor.</p>
<p>Just bring artifacts and data. We have enough ranking opinions already.</p>
]]></content:encoded><category>llm-benchmarks</category><category>llms</category><category>coding-agents</category></item><item><title>LLM Benchmark: Is Opus 5 Any Good?</title><link>https://akitaonrails.github.io/en/2026/07/25/llm-benchmark-is-opus-5-any-good/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/07/25/llm-benchmark-is-opus-5-any-good/</guid><pubDate>Sat, 25 Jul 2026 12:00:00 -0300</pubDate><description>&lt;p&gt;Anthropic released &lt;strong&gt;Claude Opus 5&lt;/strong&gt; yesterday. The obvious question is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Is it any good?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Short answer: &lt;strong&gt;yes, very&lt;/strong&gt;. It scored 95/100, Tier A, on my benchmark, with the most complete engineering I have seen so far from any of the harnesses I tested.&lt;/p&gt;
&lt;p&gt;Now for the answer that matters: no, this does not prove it is &amp;ldquo;the best LLM in the world.&amp;rdquo; It does not prove it is better than Fable 5, Opus 4.8, GPT 5.6 Sol, or Kimi K3 at whatever job you throw at them either. Last week I published an entire article on &lt;a href="https://akitaonrails.github.io/en/2026/07/19/llm-benchmark-should-i-use-the-highest-scoring-model/"&gt;why the highest score does not mean the best model&lt;/a&gt;. Opus 5 arrived just in time to hand us a fine case study for that argument.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Anthropic released <strong>Claude Opus 5</strong> yesterday. The obvious question is:</p>
<blockquote>
  <p>&ldquo;Is it any good?&rdquo;</p>

</blockquote>
<p>Short answer: <strong>yes, very</strong>. It scored 95/100, Tier A, on my benchmark, with the most complete engineering I have seen so far from any of the harnesses I tested.</p>
<p>Now for the answer that matters: no, this does not prove it is &ldquo;the best LLM in the world.&rdquo; It does not prove it is better than Fable 5, Opus 4.8, GPT 5.6 Sol, or Kimi K3 at whatever job you throw at them either. Last week I published an entire article on <a href="/en/2026/07/19/llm-benchmark-should-i-use-the-highest-scoring-model/">why the highest score does not mean the best model</a>. Opus 5 arrived just in time to hand us a fine case study for that argument.</p>
<h2>Where Anthropic positions Opus 5<span class="hx:absolute hx:-mt-20" id="where-anthropic-positions-opus-5"></span>
    <a href="#where-anthropic-positions-opus-5" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>In the <a href="https://www.anthropic.com/news/claude-opus-5"target="_blank" rel="noopener">official announcement</a>, Anthropic describes Opus 5 as an everyday model that comes close to Fable 5&rsquo;s frontier intelligence at half the price. It is now the default model on Claude Max and the strongest one available on Pro.</p>
<p>The product ladder looks simple enough:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Opus 4.8  &lt;  Opus 5  ≈  Fable 5</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Except Anthropic&rsquo;s own data does not form such a tidy line. At maximum effort on CursorBench 3.2, Opus 5 lands within 0.5% of Fable 5&rsquo;s peak. On Frontier-Bench v0.1, it beats every other model and more than doubles Opus 4.8&rsquo;s result at a lower cost per task. On OSWorld 2.0, it even tops Fable&rsquo;s best result at a little over a third of the cost.</p>
<p>So &ldquo;somewhere between Opus 4.8 and Fable 5&rdquo; is a fair shortcut for understanding the product. It is not a universal ranking. The curves cross depending on the task and the effort setting.</p>
<p>Price is less fuzzy. Opus 5 costs <strong>$5 per million input tokens and $25 per million output tokens</strong>, the same as Opus 4.8. Fable 5 costs <strong>$10/$50</strong>. At API rates, Opus 5 delivers the most interesting promise in this release: near-Fable behavior without paying the Fable tax.</p>
<h2>The benchmark<span class="hx:absolute hx:-mt-20" id="the-benchmark"></span>
    <a href="#the-benchmark" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>For anyone just joining us, my <a href="https://github.com/akitaonrails/llm-coding-benchmark"target="_blank" rel="noopener">LLM Coding Benchmark</a> gives every model the same job: build a ChatGPT-style chat app on its own in Rails 8, with RubyLLM, Hotwire, Tailwind, tests, CI, Docker, and documentation.</p>
<p>I am not grading one isolated function. I grade the project that comes out the other end: whether it uses the real RubyLLM API, whether multi-turn works, whether it handles provider failures, whether the conversation persists, whether Turbo Streams is actually wired, whether the tests can catch bugs, and whether the production image boots.</p>
<p>Opus 5 ran solo through <strong>Claude Code headless</strong>, with <code>--dangerously-skip-permissions</code>, using my Max subscription. The numbers:</p>
<ul>
<li><strong>38m57s</strong></li>
<li><strong>201 turns</strong></li>
<li><strong>121 tests and 355 assertions</strong></li>
<li><strong>100% line coverage and 95.94% branch coverage</strong></li>
<li><strong>22.1 million cache-read tokens</strong></li>
<li><strong>$16.02 at equivalent API rates</strong>, billed to the subscription</li>
</ul>
<p>That needs an asterisk. Opus 4.8 and Fable 5 were tested in OpenCode through OpenRouter. GPT 5.6 Sol ran in Codex. Kimi K3 ran in Kimi Code CLI. A coding benchmark measures the whole package:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">model + prompt + harness + tools + context + execution + audit</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>That is why the repository keeps Opus 5 in the Claude Code profile instead of pretending this was a perfectly controlled comparison with the main table. I am combining the main ranking&rsquo;s 40 rows with the new result here because everyone wants to see where that 95 lands. The asterisk is doing real work.</p>
<h2>Updated ranking: main table + Opus 5<span class="hx:absolute hx:-mt-20" id="updated-ranking-main-table--opus-5"></span>
    <a href="#updated-ranking-main-table--opus-5" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><table>
  <thead>
      <tr>
          <th style="text-align: right">Rank</th>
          <th>Model</th>
          <th style="text-align: right">Score</th>
          <th style="text-align: center">Tier</th>
          <th style="text-align: center">RubyLLM OK</th>
          <th style="text-align: right">Time</th>
          <th style="text-align: right">Run cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right"><strong>1</strong></td>
          <td><strong>Claude Opus 5 (Claude Code)*</strong></td>
          <td style="text-align: right"><strong>95</strong></td>
          <td style="text-align: center"><strong>A</strong></td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right"><strong>39m</strong></td>
          <td style="text-align: right"><strong>subscription (≈$16.02 API equiv.)</strong></td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>GPT 5.4 xHigh (Codex)</td>
          <td style="text-align: right">95</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">22m</td>
          <td style="text-align: right">~$16</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>Claude Opus 4.8</td>
          <td style="text-align: right">95</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">17m</td>
          <td style="text-align: right">~$6.40</td>
      </tr>
      <tr>
          <td style="text-align: right">4</td>
          <td>Claude Fable 5</td>
          <td style="text-align: right">94</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">24m</td>
          <td style="text-align: right">~$11.20</td>
      </tr>
      <tr>
          <td style="text-align: right">5</td>
          <td>Claude Fable 5 (re-release)</td>
          <td style="text-align: right">93</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">18m</td>
          <td style="text-align: right">~$8.30</td>
      </tr>
      <tr>
          <td style="text-align: right">5</td>
          <td>Gemini 3.5 Flash</td>
          <td style="text-align: right">93</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">18m</td>
          <td style="text-align: right">~$3.55</td>
      </tr>
      <tr>
          <td style="text-align: right">7</td>
          <td>GPT 5.6 Sol xHigh (Codex)</td>
          <td style="text-align: right">92</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">17m</td>
          <td style="text-align: right">subscription (≈$8.70 API equiv.)</td>
      </tr>
      <tr>
          <td style="text-align: right">8</td>
          <td>Kimi K3 (Kimi Code CLI)</td>
          <td style="text-align: right">89</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">26m</td>
          <td style="text-align: right">subscription (≈$2.10 API equiv.)</td>
      </tr>
      <tr>
          <td style="text-align: right">9</td>
          <td>Claude Opus 4.7</td>
          <td style="text-align: right">87</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">18m</td>
          <td style="text-align: right">~$7.00</td>
      </tr>
      <tr>
          <td style="text-align: right">9</td>
          <td>Kimi K2.6</td>
          <td style="text-align: right">87</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">20m</td>
          <td style="text-align: right">~$1.19</td>
      </tr>
      <tr>
          <td style="text-align: right">9</td>
          <td>GLM 5.2 (Z.ai)</td>
          <td style="text-align: right">87</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">43m</td>
          <td style="text-align: right">subscription</td>
      </tr>
      <tr>
          <td style="text-align: right">9</td>
          <td>Grok 4.5</td>
          <td style="text-align: right">87</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">16m</td>
          <td style="text-align: right">~$5.10</td>
      </tr>
      <tr>
          <td style="text-align: right">13</td>
          <td>Kimi K2.7 Code</td>
          <td style="text-align: right">86</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">22m</td>
          <td style="text-align: right">~$1.23</td>
      </tr>
      <tr>
          <td style="text-align: right">14</td>
          <td>GPT 5.5 xHigh (Codex)</td>
          <td style="text-align: right">85</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">18m</td>
          <td style="text-align: right">~$10</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>Claude Opus 4.6</td>
          <td style="text-align: right">83</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">16m</td>
          <td style="text-align: right">~$1.10 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">15</td>
          <td>Nex-N2-Pro</td>
          <td style="text-align: right">83</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">25m</td>
          <td style="text-align: right">~$0.34</td>
      </tr>
      <tr>
          <td style="text-align: right">17</td>
          <td>Gemini 3.1 Pro</td>
          <td style="text-align: right">79</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">14m</td>
          <td style="text-align: right">~$3.10</td>
      </tr>
      <tr>
          <td style="text-align: right">17</td>
          <td>Sakana Fugu Ultra</td>
          <td style="text-align: right">79</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">22m</td>
          <td style="text-align: right">subscription</td>
      </tr>
      <tr>
          <td style="text-align: right">19</td>
          <td>Claude Sonnet 4.6</td>
          <td style="text-align: right">78</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">16m</td>
          <td style="text-align: right">~$0.63 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">19</td>
          <td>DeepSeek V4 Flash</td>
          <td style="text-align: right">78</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">3m</td>
          <td style="text-align: right">~$0.01</td>
      </tr>
      <tr>
          <td style="text-align: right">19</td>
          <td>MiniMax M3</td>
          <td style="text-align: right">78</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">53m (phase 2 DNF)</td>
          <td style="text-align: right">~$1.25</td>
      </tr>
      <tr>
          <td style="text-align: right">19</td>
          <td>Qwen3.7 Max</td>
          <td style="text-align: right">78</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">19m</td>
          <td style="text-align: right">~$1.40</td>
      </tr>
      <tr>
          <td style="text-align: right">23</td>
          <td>Grok 4.3</td>
          <td style="text-align: right">72</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">15m</td>
          <td style="text-align: right">~$1.70</td>
      </tr>
      <tr>
          <td style="text-align: right">24</td>
          <td>Qwen 3.6 Plus</td>
          <td style="text-align: right">71</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">17m</td>
          <td style="text-align: right">~$0.15 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">25</td>
          <td>DeepSeek V4 Pro</td>
          <td style="text-align: right">69</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">22m (DNF)</td>
          <td style="text-align: right">~$0.05</td>
      </tr>
      <tr>
          <td style="text-align: right">25</td>
          <td>Kimi K2.5</td>
          <td style="text-align: right">69</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">29m</td>
          <td style="text-align: right">~$0.10 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">25</td>
          <td>Step 3.7 Flash</td>
          <td style="text-align: right">69</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">27m</td>
          <td style="text-align: right">~$0.80</td>
      </tr>
      <tr>
          <td style="text-align: right">28</td>
          <td>Xiaomi MiMo V2.5 Pro</td>
          <td style="text-align: right">67</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">11m</td>
          <td style="text-align: right">~$0.09</td>
      </tr>
      <tr>
          <td style="text-align: right">29</td>
          <td>GLM 5</td>
          <td style="text-align: right">64</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">17m</td>
          <td style="text-align: right">~$0.11 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">30</td>
          <td>Claude Sonnet 5</td>
          <td style="text-align: right">58</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td style="text-align: right">27m</td>
          <td style="text-align: right">~$2.25</td>
      </tr>
      <tr>
          <td style="text-align: right">31</td>
          <td>Step 3.5 Flash</td>
          <td style="text-align: right">56</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">⚠️ bypass</td>
          <td style="text-align: right">38m</td>
          <td style="text-align: right">~$0.02 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">32</td>
          <td>Qwen 3.5 35B</td>
          <td style="text-align: right">55</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">28m</td>
          <td style="text-align: right">local</td>
      </tr>
      <tr>
          <td style="text-align: right">33</td>
          <td>GLM 4.7 Flash bf16</td>
          <td style="text-align: right">52</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">✅</td>
          <td style="text-align: right">failed</td>
          <td style="text-align: right">local</td>
      </tr>
      <tr>
          <td style="text-align: right">34</td>
          <td>GLM 5.1 (Z.ai)</td>
          <td style="text-align: right">46</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td style="text-align: right">22m</td>
          <td style="text-align: right">subscription</td>
      </tr>
      <tr>
          <td style="text-align: right">35</td>
          <td>DeepSeek V3.2</td>
          <td style="text-align: right">43</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td style="text-align: right">60m</td>
          <td style="text-align: right">~$0.07 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">36</td>
          <td>Qwen 3.5 397B A17B</td>
          <td style="text-align: right">42</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td style="text-align: right">15m</td>
          <td style="text-align: right">~$0.31</td>
      </tr>
      <tr>
          <td style="text-align: right">37</td>
          <td>MiniMax M2.7</td>
          <td style="text-align: right">41</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td style="text-align: right">14m</td>
          <td style="text-align: right">~$0.30 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">38</td>
          <td>Qwen 3.5 122B</td>
          <td style="text-align: right">37</td>
          <td style="text-align: center">D</td>
          <td style="text-align: center">❌</td>
          <td style="text-align: right">43m</td>
          <td style="text-align: right">local</td>
      </tr>
      <tr>
          <td style="text-align: right">39</td>
          <td>Qwen 3 Coder Next</td>
          <td style="text-align: right">32</td>
          <td style="text-align: center">D</td>
          <td style="text-align: center">❌</td>
          <td style="text-align: right">17m</td>
          <td style="text-align: right">local</td>
      </tr>
      <tr>
          <td style="text-align: right">40</td>
          <td>Grok 4.20</td>
          <td style="text-align: right">25</td>
          <td style="text-align: center">D</td>
          <td style="text-align: center">❌</td>
          <td style="text-align: right">8m</td>
          <td style="text-align: right">~$0.70</td>
      </tr>
      <tr>
          <td style="text-align: right">41</td>
          <td>GPT OSS 20B</td>
          <td style="text-align: right">11</td>
          <td style="text-align: center">D</td>
          <td style="text-align: center">❌</td>
          <td style="text-align: right">failed</td>
          <td style="text-align: right">local</td>
      </tr>
  </tbody>
</table>
<p>* Opus 5 received an equivalent 95/100 in the Claude Code profile. The repository&rsquo;s main table keeps it separate to make the harness difference explicit.</p>
<h2>What Opus 5 wrote<span class="hx:absolute hx:-mt-20" id="what-opus-5-wrote"></span>
    <a href="#what-opus-5-wrote" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The score alone hides the good part. Opus 5&rsquo;s project is the best example of defensive engineering to show up in this benchmark so far.</p>
<p>It isolated all RubyLLM access in one <code>Assistant::Client</code>, injected the chat factory for tests, and verified the gem&rsquo;s real API before depending on it. Besides mocking <code>RubyLLM.chat</code>, <code>with_instructions</code>, <code>add_message</code>, and <code>ask</code>, it created a guard test that confirms those methods still exist in the installed gem. If the library changes its interface, CI breaks before production does.</p>
<p>The conversation sits behind a <code>ConversationRepository</code> in <code>Rails.cache</code>, with a 12-hour TTL and a 40-message replay limit. Before sending history to the provider, it normalizes role alternation between <code>user</code> and <code>assistant</code>, removes failed replies, and makes sure the window does not begin with an assistant message. That sounds like trivia right up until the API rejects the payload on turn two.</p>
<p>That is exactly where the model found and fixed two bugs during its own run. A failed reply could leave two user messages in a row. Trimming the history window could also make it begin with an assistant reply. It wrote tests, fixed both, and validated real multi-turn behavior, including recovery after a failure.</p>
<p>It also delivered:</p>
<ul>
<li>streaming outside the main request;</li>
<li>signed Turbo Streams broadcasts throttled to roughly 10 updates per second;</li>
<li>credential preflight;</li>
<li>different messages for an invalid key, rate limits, depleted credits, blown context, and provider downtime;</li>
<li>Markdown escaped before formatting HTML;</li>
<li>a multi-stage, production, non-root Dockerfile;</li>
<li>RuboCop, Brakeman, bundler-audit, importmap audit, and GitHub Actions.</li>
</ul>
<p>It is not a 100. There is a lost-update race if another message arrives during generation, although the project itself constrains deployment to <code>WEB_CONCURRENCY=1</code>. It also left the default model on Sonnet 4.6 after Sonnet 5 was already available, and committed <code>log/</code> and <code>coverage/</code> cruft inside the artifact. Those deductions held it at 95.</p>
<h2>Opus 5 against Opus 4.8 and Fable 5<span class="hx:absolute hx:-mt-20" id="opus-5-against-opus-48-and-fable-5"></span>
    <a href="#opus-5-against-opus-48-and-fable-5" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>First, the numbers from our test:</p>
<table>
  <thead>
      <tr>
          <th>Model</th>
          <th style="text-align: right">Score</th>
          <th style="text-align: right">Time</th>
          <th style="text-align: right">Tests</th>
          <th>Persistence</th>
          <th style="text-align: right">API rate</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Opus 5</td>
          <td style="text-align: right">95</td>
          <td style="text-align: right">39m</td>
          <td style="text-align: right">121</td>
          <td>Rails.cache, TTL, limited replay</td>
          <td style="text-align: right">$5 / $25</td>
      </tr>
      <tr>
          <td>Opus 4.8</td>
          <td style="text-align: right">95</td>
          <td style="text-align: right">17m</td>
          <td style="text-align: right">34</td>
          <td>session cookie with no cap</td>
          <td style="text-align: right">$5 / $25</td>
      </tr>
      <tr>
          <td>Fable 5</td>
          <td style="text-align: right">94</td>
          <td style="text-align: right">24m</td>
          <td style="text-align: right">36</td>
          <td>capped local singleton</td>
          <td style="text-align: right">$10 / $50</td>
      </tr>
      <tr>
          <td>Fable 5 (re-release)</td>
          <td style="text-align: right">93</td>
          <td style="text-align: right">18m</td>
          <td style="text-align: right">41</td>
          <td>Rails.cache with TTL, no hard cap</td>
          <td style="text-align: right">$10 / $50</td>
      </tr>
  </tbody>
</table>
<p><a href="/en/2026/06/01/llm-benchmarks-grok-4-3-minimax-m3-opus-4-8/">Opus 4.8 had scored 95</a> with a smaller solution that finished much faster. It used the correct API, wrote honest tests, and performed the best live validation in that round: local Rails, a real OpenRouter call, Docker, a production container, and Compose. It lost points for leaving cookie history unbounded and skipping an API-key preflight.</p>
<p>Opus 5 fixed both defects and went much further on architecture, streaming, and tests. On the other hand, it created a different race, left the model pin stale, and took more than twice as long. Same score, very different artifacts.</p>
<p><a href="/en/2026/06/11/llm-benchmark-fable-5-anthropic-soap-opera/">The original Fable 5 scored 94</a>. It was the first model I saw stop in the middle of the job to read RubyLLM&rsquo;s installed source before writing the integration. It had 99.3% coverage, capped history, preflight, and a phase 2 that needed no fixes. The big deduction came from storing conversations in an in-memory singleton: restart the process and everything is gone; add a second worker and each one sees a different world.</p>
<p>The Fable re-release fixed that with <code>Rails.cache</code>, but left the cache without a hard cap, kept Sonnet 4.6, and performed weaker live validation. It dropped one point. Same model ID, another project, another score.</p>
<p>Within the boundaries of this Rails app, Opus 5 looks more complete than both Fable runs and at least as good as Opus 4.8. Just do not confuse that with &ldquo;Opus 5 is more intelligent than Fable.&rdquo; Anthropic says Fable&rsquo;s advantage grows as tasks get longer and more complex. Our project is small, greenfield, and closed-ended. There may simply be no room here for that difference to show.</p>
<h2>The price: half of Fable, but mind the bill<span class="hx:absolute hx:-mt-20" id="the-price-half-of-fable-but-mind-the-bill"></span>
    <a href="#the-price-half-of-fable-but-mind-the-bill" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>On the API, the advantage is straightforward:</p>
<table>
  <thead>
      <tr>
          <th>Model</th>
          <th style="text-align: right">Input / million</th>
          <th style="text-align: right">Output / million</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Opus 5</td>
          <td style="text-align: right">$5</td>
          <td style="text-align: right">$25</td>
      </tr>
      <tr>
          <td>Opus 4.8</td>
          <td style="text-align: right">$5</td>
          <td style="text-align: right">$25</td>
      </tr>
      <tr>
          <td>Fable 5</td>
          <td style="text-align: right">$10</td>
          <td style="text-align: right">$50</td>
      </tr>
  </tbody>
</table>
<p>If Opus 5 really delivers near-Fable behavior on your workload, paying twice as much for Fable is hard to justify. Fable needs to solve something Opus cannot, not merely carry the name of the tier above it.</p>
<p>But the observed cost of this run tells a different story:</p>
<table>
  <thead>
      <tr>
          <th>Model</th>
          <th>Harness</th>
          <th style="text-align: right">Run cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Opus 5</td>
          <td>Claude Code / Max</td>
          <td style="text-align: right">subscription (≈$16.02 at API rates)</td>
      </tr>
      <tr>
          <td>Opus 4.8</td>
          <td>OpenCode / OpenRouter</td>
          <td style="text-align: right">~$6.40</td>
      </tr>
      <tr>
          <td>Fable 5</td>
          <td>OpenCode / OpenRouter</td>
          <td style="text-align: right">~$11.20</td>
      </tr>
  </tbody>
</table>
<p>How did a model with half Fable&rsquo;s rate end up with a higher equivalent cost? Because price per million is not cost per task. The Opus 5 run took 201 turns and accumulated 22.1 million cache reads in Claude Code. The Fable run used another harness and another token profile. Comparing $16.02 with $11.20 as if the model were the only variable would be flat-out wrong.</p>
<p>For me, as a Max subscriber, the real marginal cost was zero while I remained inside the allowance. For automation that pays API rates per token, Opus 5 costs half as much as Fable and the same as 4.8. I would start with Opus 5 and move up to Fable only with evidence that the task needs it.</p>
<h2>Against GPT 5.6 Sol and Kimi K3<span class="hx:absolute hx:-mt-20" id="against-gpt-56-sol-and-kimi-k3"></span>
    <a href="#against-gpt-56-sol-and-kimi-k3" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p><a href="/en/2026/07/09/llm-benchmark-grok-4-5-gpt-5-6-sol/">GPT 5.6 Sol scored 92</a> in 17 minutes. It was far more token-efficient and delivered a defensive application: a non-root Docker image, 99.2% coverage, history bounded by messages, characters, and bytes, plus a specific test to keep the current prompt from being repeated in context.</p>
<p>It lost points because it never used <code>with_instructions</code> and carried history in a hidden field in the browser. That works, but the conversation disappears on reload and the client can tamper with the context. Opus 5 put those responsibilities on the server, separated domain, persistence, and provider more cleanly, and tested far more. On this project, the three-point difference makes sense. In daily use, both remain in the same cluster of strong models.</p>
<p><a href="/en/2026/07/17/llm-benchmarks-kimi-k3/">Kimi K3 scored 89</a> in 26 minutes. It had already nailed the pattern that decides much of the top end: <code>Rails.cache</code>, a TTL, and a history cap. It cost only about $2.10 at equivalent API rates through the Moderato subscription.</p>
<p>It landed lower because it had no system prompt, put LLM I/O inside the <code>Conversation</code> model, skipped credential preflight, and left the production cache on the container&rsquo;s ephemeral default. Opus 5 closes nearly all of those gaps. Kimi remains a much cheaper Tier A alternative; Opus 5 is the project I would need to touch less before trusting it.</p>
<h2>Opus 5 also dethroned the old champion<span class="hx:absolute hx:-mt-20" id="opus-5-also-dethroned-the-old-champion"></span>
    <a href="#opus-5-also-dethroned-the-old-champion" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>There is one important change in the table that did not come from the new code. Until yesterday, Opus 4.7 sat in first place with 97. The blind cross-audit between it and Opus 5 came back <strong>94 to 70</strong> in favor of 5. I went back and read the old artifacts.</p>
<p>Opus 4.7 had a double-send bug: the controller stored the user&rsquo;s message before calling the service, and the service replayed the entire history, including that same message. Every prompt reached the LLM twice. Error messages also returned in the context of future requests, and the cookie had a message-count limit but no byte limit.</p>
<p>The tests passed because controller and service were tested under arrangements that differed from the production flow. The model did not get worse since April. The project did not change either. <strong>My audit was incomplete.</strong> I recalculated the score from 97 to 87.</p>
<p>That is almost comical, because last week&rsquo;s article used &ldquo;why is Opus 4.7 above 4.8 and Fable?&rdquo; as its exact example. It is not anymore. And the article&rsquo;s argument just got stronger.</p>
<p>A benchmark is not holy writ. The rubric evolves, the auditor finds a blind spot, the harness changes, the same model generates another project. If a table does not publish the prompt, artifact, logs, and corrections, it is more useful for marketing than engineering.</p>
<h2>Conclusion<span class="hx:absolute hx:-mt-20" id="conclusion"></span>
    <a href="#conclusion" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Is Opus 5 any good? <strong>Yes.</strong> Very.</p>
<p>It scored 95/A, tied Opus 4.8 and GPT 5.4, landed one point above the original Fable, three above GPT 5.6 Sol, and six above Kimi K3. It produced the most careful project in this entire round: clean architecture, RubyLLM verified against the real gem, correct history, solid streaming, separate error handling, and 121 tests.</p>
<p>It also took 39 minutes, burned 22 million cache reads, and ran in a different harness. Scoring higher than Fable does not prove it is better than Fable overall. It proves that, on this Rails app, in this Claude Code run, under this audit, the artifact fit the rubric a little better.</p>
<p>My practical read: Opus 5 deserves to be the first option. Its API rate is the same as Opus 4.8 and half Fable&rsquo;s. For anyone with Claude Pro or Max, it is the obvious choice before spending credits on Fable. If you pay API rates, I would still start there and demand data before moving up to the $10/$50 tier.</p>
<p>And the rule stays the same: read 90+ as a group. Tier A is clearly above Tier C on this workload. Within the good group, choose by cost, subscription, speed, harness, and the kind of defect you are willing to review.</p>
<p>Do not use my benchmark to decide which model is &ldquo;the best LLM.&rdquo; Use it to decide what is worth testing on your problem. If the decision matters, run your own methodology more than once, and read the code.</p>
]]></content:encoded><category>llm-benchmarks</category><category>llms</category><category>coding-agents</category></item><item><title>What's New in My AI-MEMORY: Switch AI Agents Without Losing the Session</title><link>https://akitaonrails.github.io/en/2026/07/20/whats-new-ai-memory-switch-agents-without-losing-session/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/07/20/whats-new-ai-memory-switch-agents-without-losing-session/</guid><pubDate>Mon, 20 Jul 2026 21:00:00 -0300</pubDate><description>&lt;p&gt;It&amp;rsquo;s been a little over a month since I published &lt;a href="https://akitaonrails.github.io/en/2026/06/16/ai-memory-long-term-memory-karpathy-wiki-self-improvement-hermes-projects/"&gt;ai-memory: long-term memory (Karpathy Wiki) and self-improvement (Hermes) for your projects&lt;/a&gt;. That was June 16. In that post I explained how sessions became Markdown pages, how auto-improve promoted lessons, and why bad memory can be worse than amnesia.&lt;/p&gt;
&lt;p&gt;Version 1.1.0 shipped that same day. Today, July 20, we&amp;rsquo;re at &lt;strong&gt;1.17.1&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Version numbers alone don&amp;rsquo;t mean much, so I counted what actually happened after that post went live: &lt;strong&gt;31 releases, 55 merged pull requests, and 46 closed issues&lt;/strong&gt;. I counted &lt;strong&gt;24 groups of new user-facing features&lt;/strong&gt; in the &lt;a href="https://github.com/akitaonrails/ai-memory/blob/main/CHANGELOG.md"target="_blank" rel="noopener"&gt;CHANGELOG&lt;/a&gt;, ignoring fixes, documentation, and internal details from the same delivery. If I split the new &lt;code&gt;ai-memory run&lt;/code&gt; family into auto-selection, session adoption, Crush support, &lt;code&gt;--yolo&lt;/code&gt;, search, and recovery, we&amp;rsquo;d blow past that number.&lt;/p&gt;</description><content:encoded><![CDATA[<p>It&rsquo;s been a little over a month since I published <a href="/en/2026/06/16/ai-memory-long-term-memory-karpathy-wiki-self-improvement-hermes-projects/">ai-memory: long-term memory (Karpathy Wiki) and self-improvement (Hermes) for your projects</a>. That was June 16. In that post I explained how sessions became Markdown pages, how auto-improve promoted lessons, and why bad memory can be worse than amnesia.</p>
<p>Version 1.1.0 shipped that same day. Today, July 20, we&rsquo;re at <strong>1.17.1</strong>.</p>
<p>Version numbers alone don&rsquo;t mean much, so I counted what actually happened after that post went live: <strong>31 releases, 55 merged pull requests, and 46 closed issues</strong>. I counted <strong>24 groups of new user-facing features</strong> in the <a href="https://github.com/akitaonrails/ai-memory/blob/main/CHANGELOG.md"target="_blank" rel="noopener">CHANGELOG</a>, ignoring fixes, documentation, and internal details from the same delivery. If I split the new <code>ai-memory run</code> family into auto-selection, session adoption, Crush support, <code>--yolo</code>, search, and recovery, we&rsquo;d blow past that number.</p>
<p>Fifteen people had PRs merged during that period, fourteen besides me. Special thanks go to <a href="https://github.com/djalmajr"target="_blank" rel="noopener">Djalma Júnior</a>, who alone had 24 PRs merged, <a href="https://github.com/matheus-rodrigues00"target="_blank" rel="noopener">Matheus Rodrigues</a>, with five, <a href="https://github.com/lhzapata"target="_blank" rel="noopener">lhzapata</a>, with four, <a href="https://github.com/rthiago"target="_blank" rel="noopener">Thiago Silva</a> and <a href="https://github.com/cristianodewes"target="_blank" rel="noopener">Cristiano Dewes</a>, with two each. Nine more contributors had a PR merged. This stopped being &ldquo;a little program I made over a weekend&rdquo; a while ago.</p>
<p>I&rsquo;m not going to dump 55 PRs here. I want to talk about the change that affects my daily use the most: the new <strong><code>ai-memory run</code></strong>.</p>
<h2>The session is part of the project too<span class="hx:absolute hx:-mt-20" id="the-session-is-part-of-the-project-too"></span>
    <a href="#the-session-is-part-of-the-project-too" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Code is the result that survived. It doesn&rsquo;t preserve the entire investigation.</p>
<p>Git shows that you replaced Redis with SQLite. Maybe the commit explains part of it. But where is the Redis experiment? Where is the intermittent bug that only showed up with two workers? Who remembered that the first solution broke on Windows? Why did the team change its mind after three hours? Which workaround was temporary, and which one became the decision?</p>
<p>Much of that exists only in the agent session.</p>
<p>When I program with Claude Code or Codex, the session accumulates the project&rsquo;s operational reasoning: questions, corrections, discarded attempts, test results, surprises, decisions, and changes in direction. The final code shows what stayed. The session explains how we got there.</p>
<p>And an LLM session, at the end of the day, is text. Claude Code writes JSONL. Codex does too. OpenCode uses SQLite. Pi, OMP, and Crush have their own formats and directories. Each harness packages the conversation differently, but the visible content is still messages and tool results.</p>
<p>Why should I leave the most expensive part of the work trapped inside the harness?</p>
<p>Anthropic can change limits, pricing, models, or formats tomorrow. OpenAI can too. An agent can be excellent this week and unbearable the next. I want to swap the engine without throwing away the whole trip.</p>
<p>That has been ai-memory&rsquo;s thesis from the start: <strong>the programmer must remain independent of provider whims</strong>. Models and harnesses are replaceable. The project memory is mine.</p>
<h2>Handoffs solved only half the problem<span class="hx:absolute hx:-mt-20" id="handoffs-solved-only-half-the-problem"></span>
    <a href="#handoffs-solved-only-half-the-problem" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>ai-memory already handled handoffs. I would close Claude Code, the hooks would consolidate the session, and the next Codex would receive a short summary with what had been done, open questions, and next steps.</p>
<p>That still exists and is still useful. Anyone who opens <code>claude</code>, <code>codex</code>, or <code>opencode</code> directly keeps the previous behavior. The new launcher is opt-in.</p>
<p>But a handoff is deliberately lossy compression. It preserves what seems most important at that moment. It isn&rsquo;t meant to carry the entire session or resume each harness&rsquo;s native session. If the summary left out an old attempt that became relevant again two hours later, you have to search the wiki or the records.</p>
<p><code>ai-memory run</code> adds another layer: a <strong>managed workstream</strong>, one line of work that crosses harnesses.</p>
<h2>Claude now, Codex in a little while<span class="hx:absolute hx:-mt-20" id="claude-now-codex-in-a-little-while"></span>
    <a href="#claude-now-codex-in-a-little-while" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Basic usage looks like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ~/Projects/meu-projeto
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ai-memory run claude
</span></span><span class="line"><span class="cl"><span class="c1"># work, then exit Claude Code normally</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ai-memory run codex --yolo
</span></span><span class="line"><span class="cl"><span class="c1"># Codex continues the same line of work</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ai-memory run claude --model opus
</span></span><span class="line"><span class="cl"><span class="c1"># return to Claude&#39;s previous native session</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ai-memory run
</span></span><span class="line"><span class="cl"><span class="c1"># or let ai-memory choose the right harness to continue</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>You don&rsquo;t need <code>--</code> to separate arguments. Everything after the harness name goes to it, with one deliberate exception: <code>--yolo</code> belongs to the wrapper and is translated into the native dangerous option for Claude Code, Codex, OpenCode, Pi, or Crush.</p>
<p>Under the hood, ai-memory doesn&rsquo;t try to convert a Codex file into a Claude file. That would be fragile and would probably break on the next update. Each harness keeps its own native session. The workstream connects those sessions to a portable ledger containing the visible part of the conversation.</p>
<p>Think of it this way:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Claude native session ─┐
</span></span><span class="line"><span class="cl">Codex native session  ─┼─ workstream ─ portable context
</span></span><span class="line"><span class="cl">OpenCode session      ─┤                 + full search
</span></span><span class="line"><span class="cl">Pi native session     ─┘</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>The first time Claude enters that workstream, it gets a native session. When you switch to Codex, Codex gets its own native session and receives the portable delta it hasn&rsquo;t seen yet. When you return to Claude, the launcher uses Claude Code&rsquo;s own <code>--resume</code> and delivers only what happened in the other harnesses since the last visit.</p>
<p>This is very different from starting a new chat with a summary pasted into the prompt. Claude returns to its real session. Codex returns to its real session. ai-memory handles continuity between the two.</p>
<p>Managed mode currently supports <strong>Claude Code, Codex, OpenCode, Pi, Crush, and OMP</strong>. General ai-memory support is broader, with MCP and hooks for other clients, but that doesn&rsquo;t mean every client already has a native-session adapter for <code>run</code>. Those are different contracts, and I prefer to make that explicit.</p>
<h2>What goes into the workstream<span class="hx:absolute hx:-mt-20" id="what-goes-into-the-workstream"></span>
    <a href="#what-goes-into-the-workstream" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>When the harness exits, ai-memory reads the tail of the native session without modifying the original store. It imports visible user and assistant messages, completed tool calls with their results, compaction summaries, and a non-mutating Git checkpoint. Every event keeps its origin: Claude, Codex, OpenCode, Pi, Crush, or OMP.</p>
<p>Provider credentials, encrypted records, system and developer prompts, and hidden reasoning stay out. Private formats the adapter doesn&rsquo;t understand stay out too and produce a loss annotation instead of letting the system pretend it imported everything.</p>
<p>Records pass through the sanitizer before entering ai-memory&rsquo;s searchable ledger and immutable JSONL segments. The adapter opens native stores read-only; the harness itself remains the writer.</p>
<p>I don&rsquo;t cram the entire session into the next prompt either. That would recreate the problem the project is trying to solve: too much raw context, too much cost, and too much noise. The next agent gets a size-limited recent delta. If an old decision matters again, the full ledger remains searchable:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-memory workstream-search <span class="s2">&#34;por que desistimos do Redis&#34;</span>
</span></span><span class="line"><span class="cl">ai-memory workstream-search --limit <span class="m">50</span> --json <span class="s2">&#34;migration que falhou&#34;</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Inside an <code>ai-memory run</code>, the workstream ID is already in the environment. The agent doesn&rsquo;t have to discover some UUID.</p>
<p>And the ledger doesn&rsquo;t replace the wiki. It handles operational continuity. Decisions, rules, procedures, and gotchas that need to survive for months still deserve consolidated Markdown pages. A raw session is evidence. A wiki is organized knowledge.</p>
<h2>Can I keep more than one line of work?<span class="hx:absolute hx:-mt-20" id="can-i-keep-more-than-one-line-of-work"></span>
    <a href="#can-i-keep-more-than-one-line-of-work" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Yes. The default workstream is called <code>default</code>, selected by repository and worktree. If I want an independent line for an investigation without contaminating the main work:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-memory run --new investigar-race claude
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># later, continue that line with another harness</span>
</span></span><span class="line"><span class="cl">ai-memory run --workstream investigar-race codex</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>A lease prevents two windows from writing to the same workstream at once. On a normal exit, the launcher imports the tail of the session and releases it immediately. If someone kills the process without cleanup, the lease expires within 90 seconds and the next run resumes from the last confirmed cursor without duplicating imported events.</p>
<p>One stupid annoyance kept coming back: I would reopen a project after a few days and have no idea whether the newest session was in Claude or Codex. I&rsquo;d guess, open one, realize the context was in the other, close it, and try again.</p>
<p>Now I just run:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-memory run
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># or keep the same auto-selection in YOLO mode</span>
</span></span><span class="line"><span class="cl">ai-memory run --yolo</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>In an empty workstream, ai-memory looks for local sessions from that checkout in Claude Code, Codex, OpenCode, Pi, and Crush, finds the newest one, and opens the right harness for me. In an established workstream, server memory beats the file timestamp: it returns to the last harness attached to that work instead of accidentally adopting an old session that happened to receive a newer write. OMP remains available when selected explicitly, but it doesn&rsquo;t participate in auto-selection yet.</p>
<p>On the first explicit run, the launcher can also offer existing sessions from the same checkout for adoption. You can start using it without abandoning the chat that was already open before you updated ai-memory.</p>
<h2>Other new features I actually use<span class="hx:absolute hx:-mt-20" id="other-new-features-i-actually-use"></span>
    <a href="#other-new-features-i-actually-use" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>I promised I wouldn&rsquo;t read the entire changelog out loud, but a few changes from this month deserve a mention because they reduce work for the programmer.</p>
<h3>A briefing before the first question<span class="hx:absolute hx:-mt-20" id="a-briefing-before-the-first-question"></span>
    <a href="#a-briefing-before-the-first-question" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>A project can request an automatic briefing at the start of every session:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">briefing</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">inject_on_session_start</span> <span class="p">=</span> <span class="s2">&#34;true&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">max_chars</span> <span class="p">=</span> <span class="mi">4000</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>ai-memory assembles a package with pinned pages, <code>_rules/</code>, <code>_slots/</code>, and recent titles. The agent starts with the project&rsquo;s rules and basic state instead of spending the first conversation rediscovering the architecture. It&rsquo;s opt-in because it consumes context on every SessionStart, including after a Claude <code>/clear</code>.</p>
<h3>Global preferences and cross-project search<span class="hx:absolute hx:-mt-20" id="global-preferences-and-cross-project-search"></span>
    <a href="#global-preferences-and-cross-project-search" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Preferences that apply to all my work can now live in the reserved <code>_global</code> scope: coding style, preferred tools, personal rules, and conventions that don&rsquo;t belong to one specific repository. Normal queries already combine that scope with the current project.</p>
<p>For meta-repos that need to query several sibling projects all the time, there is another opt-in:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">recall</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">default_global</span> <span class="p">=</span> <span class="s2">&#34;true&#34;</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>With that, <code>memory_query</code> and <code>memory_recent</code> without an explicit scope search every project. I don&rsquo;t turn it on in every repo because gratuitous global search only adds noise.</p>
<h3>Less static instruction, more Agent Skills<span class="hx:absolute hx:-mt-20" id="less-static-instruction-more-agent-skills"></span>
    <a href="#less-static-instruction-more-agent-skills" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>The routing block in <code>CLAUDE.md</code> or <code>AGENTS.md</code> got smaller. Detailed instructions for when to search memory, consolidate, save a decision, or create a handoff moved into managed Agent Skills. One command installs or updates both without trampling the rest of the file:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-memory install-instructions</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>That reduces drift too. When the protocol changes, I update the managed package instead of hunting down an old prompt copied across forty repositories.</p>
<h3>Privacy before the network<span class="hx:absolute hx:-mt-20" id="privacy-before-the-network"></span>
    <a href="#privacy-before-the-network" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Each repo can now exclude paths from capture:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">capture</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">ignore_paths</span> <span class="p">=</span> <span class="p">[</span><span class="s2">&#34;private/**&#34;</span><span class="p">,</span> <span class="s2">&#34;~/personal-notes/**&#34;</span><span class="p">]</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>When an integration recognizes a file tool and the path matches, the event is discarded locally before spool, queue, network, or server. The limits are clear: this isn&rsquo;t magic DLP, it doesn&rsquo;t understand every shell command, and it doesn&rsquo;t track content quoted in free-form text. But it handles the verifiable case without selling a fake guarantee.</p>
<p>There are also new integrations with Kimi Code, Grok Build CLI, Devin, and Zero, an OpenCode Zen/Go provider, <code>finalize-session</code> for Codex, and workspace-administration improvements. Again: having MCP and a hook doesn&rsquo;t automatically mean having <code>ai-memory run</code>. The <a href="https://github.com/akitaonrails/ai-memory#support-matrix"target="_blank" rel="noopener">README</a> separates those levels.</p>
<h2>Bonus: ai-jail on the outside, YOLO on the inside<span class="hx:absolute hx:-mt-20" id="bonus-ai-jail-on-the-outside-yolo-on-the-inside"></span>
    <a href="#bonus-ai-jail-on-the-outside-yolo-on-the-inside" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Just over a week ago I wrote about <a href="/en/2026/07/11/how-to-protect-yourself-from-agents-deleting-your-stuff/">how I protect myself from agents deleting my stuff</a>. My recommendation remains the same: YOLO mode gives the best experience, provided the system limits the possible damage.</p>
<p><a href="https://github.com/akitaonrails/ai-jail"target="_blank" rel="noopener">ai-jail</a> reached version 1.15.0 and now understands the ai-memory launcher. My favorite way to work has become:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-jail ai-memory run codex --yolo</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Or, when I want ai-memory to choose which harness should continue:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-jail ai-memory run --yolo</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Order matters. <code>ai-jail</code> stays on the outside so the launcher and child process remain inside the same sandbox. <code>ai-memory run</code> by itself manages the session, but it doesn&rsquo;t create a sandbox.</p>
<p><code>--yolo</code> gets rid of the harness&rsquo;s approval ceremony. ai-jail handles containment: the current project is read-write, home is replaced with tmpfs, necessary parts of agent state are mounted selectively, and sensitive directories such as <code>.ssh</code>, <code>.gnupg</code>, and <code>.aws</code> stay outside the jail. The new support also keeps ai-memory&rsquo;s local state writable so hooks can maintain spools and cursors between runs.</p>
<p>ai-jail recognizes both the <code>ai-memory</code> layer and the selected harness. If you have Codex-specific global configuration, for example, it still applies when the actual command is <code>ai-memory run codex</code>. Even the status-bar redraw adjustment understands that the child is Codex.</p>
<p>This combination takes care of both annoyances at once: the agent stops asking for confirmation on every command, and the session stops belonging to the agent. You get the speed without handing over your entire home directory.</p>
<h2>One more thing: ai-usagebar grew too<span class="hx:absolute hx:-mt-20" id="one-more-thing-ai-usagebar-grew-too"></span>
    <a href="#one-more-thing-ai-usagebar-grew-too" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>When I published the <a href="/en/2026/05/24/i-built-a-waybar-widget-for-omarchy-to-monitor-llm-usage-ai-usagebar/">original ai-usagebar</a>, it monitored Claude, Codex, Z.AI, and OpenRouter in a Waybar widget or TUI. Version 0.14.0 already covers <strong>eleven usage, spending, or balance integrations</strong>.</p>
<p>Kimi got the two pieces of information that really matter for coding: weekly subscription quota and the rolling five-hour window. Kilo, Novita, Moonshot, and Grok show remaining balance. A separate Anthropic Console integration shows API spending for the month without conflating it with the Claude Code subscription. It makes clear that the Cost API doesn&rsquo;t include Priority Tier.</p>
<p>You can also register multiple Anthropic accounts, see weekly limits for specific models such as Fable, and get a pace marker. The bar doesn&rsquo;t turn red just because it reached 40%; it compares the percentage spent with how much of the window has passed. If I used 40% in 20% of the week, I&rsquo;m moving too fast. That&rsquo;s the useful information.</p>
<p>The project outgrew Waybar. It has a native macOS menu bar app, a GNOME extension, and a standalone TUI. The newest addition is a local Claude Code context monitor: I press <code>c</code>, choose one of the recent sessions, and see how much of the window it has consumed. It reads limited tails from local JSONL files and doesn&rsquo;t invent a percentage when it can&rsquo;t determine the window size.</p>
<p>In my workflow, the three end up working together. <code>ai-usagebar</code> shows which subscription still has room. <code>ai-memory run</code> switches harnesses without throwing away the work. <code>ai-jail</code> lets the chosen one run in YOLO without unrestricted access to the machine.</p>
<h2>Updating<span class="hx:absolute hx:-mt-20" id="updating"></span>
    <a href="#updating" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The installation pages for all three projects cover every method, including AUR, Homebrew, and release binaries:</p>
<ul>
<li><a href="https://github.com/akitaonrails/ai-memory"target="_blank" rel="noopener">ai-memory</a></li>
<li><a href="https://github.com/akitaonrails/ai-jail"target="_blank" rel="noopener">ai-jail</a></li>
<li><a href="https://github.com/akitaonrails/ai-usagebar"target="_blank" rel="noopener">ai-usagebar</a></li>
</ul>
<p>After updating ai-memory, reinstall the hooks for the harnesses you plan to use in managed mode. The three main ones in my case:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ai-memory install-hooks --agent claude-code --apply
</span></span><span class="line"><span class="cl">ai-memory install-hooks --agent codex --apply
</span></span><span class="line"><span class="cl">ai-memory install-hooks --agent opencode --apply</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Crush doesn&rsquo;t need a hook in managed mode; it receives context through a temporary file configured only for the launched process. The <a href="https://github.com/akitaonrails/ai-memory/blob/main/docs/managed-workstreams.md"target="_blank" rel="noopener">managed workstreams documentation</a> covers installation, privacy, recovery, and native arguments for each adapter.</p>
<h2>Conclusion<span class="hx:absolute hx:-mt-20" id="conclusion"></span>
    <a href="#conclusion" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>A month ago, ai-memory could already turn a session into a wiki and hand off to the next agent. Now it can manage the line of work itself: adopt an existing session, keep one native session per harness, carry visible history, resume each client in its own format, and keep the entire ledger searchable.</p>
<p>For me, that&rsquo;s the value. The code contains the implementation that won. The session contains the decisions, failed experiments, gotchas, unexpected bugs, and changes of mind that produced that implementation. Throwing all of it away every time you change providers is wasteful.</p>
<p>A raw transcript doesn&rsquo;t solve the problem by itself either. It&rsquo;s large, repetitive, and expensive to stuff into every context. ai-memory keeps the evidence, delivers only the recent delta, and uses consolidation to turn what deserves to survive into short Markdown pages.</p>
<p>There are still new formats to support, platform rough edges, and plenty of testing ahead. The difference is that there is now a real foundation, with an acceptance test that calls actual harnesses, 14 outside contributors with merged PRs in a little over a month, and daily use pushing the design forward.</p>
<p>I rent LLMs and subscriptions from whoever is delivering the best service today. My project&rsquo;s session stays with me.</p>
]]></content:encoded><category>ai-memory</category><category>coding-agents</category><category>ai-jail</category><category>ai-usagebar</category></item><item><title>LLM Benchmark: Has Kimi K3 Reached Claude Opus Level?</title><link>https://akitaonrails.github.io/en/2026/07/17/llm-benchmarks-kimi-k3/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/07/17/llm-benchmarks-kimi-k3/</guid><pubDate>Fri, 17 Jul 2026 12:00:00 -0300</pubDate><description>&lt;p&gt;I am always testing new LLMs. It is the only way to separate a release note from code that actually goes up. In the two most recent posts, &lt;a href="https://akitaonrails.github.io/en/2026/07/09/llm-benchmark-grok-4-5-gpt-5-6-sol/"&gt;Grok 4.5 and GPT 5.6 Sol&lt;/a&gt; and &lt;a href="https://akitaonrails.github.io/en/2026/07/01/llm-benchmark-sonnet-5-fails-gemini-flash-surprises-sakana-fugu-almost-tier-a/"&gt;Sonnet 5, Gemini 3.5 Flash and Sakana&lt;/a&gt;, the table moved around quite a bit. Now it is Moonshot&amp;rsquo;s turn.&lt;/p&gt;
&lt;p&gt;The focus is &lt;strong&gt;Kimi K3&lt;/strong&gt;, an alternative that is becoming more and more like Claude in the kind of work it can finish.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I am always testing new LLMs. It is the only way to separate a release note from code that actually goes up. In the two most recent posts, <a href="/en/2026/07/09/llm-benchmark-grok-4-5-gpt-5-6-sol/">Grok 4.5 and GPT 5.6 Sol</a> and <a href="/en/2026/07/01/llm-benchmark-sonnet-5-fails-gemini-flash-surprises-sakana-fugu-almost-tier-a/">Sonnet 5, Gemini 3.5 Flash and Sakana</a>, the table moved around quite a bit. Now it is Moonshot&rsquo;s turn.</p>
<p>The focus is <strong>Kimi K3</strong>, an alternative that is becoming more and more like Claude in the kind of work it can finish.</p>
<h2>For those who just landed here<span class="hx:absolute hx:-mt-20" id="for-those-who-just-landed-here"></span>
    <a href="#for-those-who-just-landed-here" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The benchmark gives every model the same prompt: build, on its own, a ChatGPT-like chat app in Rails 8, RubyLLM, Hotwire, Docker, with tests and CI. Then I inspect the project it produced, including the gem&rsquo;s real API, conversation memory, error handling, tests, and production image. The score goes from 0 to 100, in A/B/C/D tiers.</p>
<p>This is not a fill-in-the-function benchmark. It is an agent delivering a small app, with the boring parts that usually break after the demo. The methodology is in <a href="/en/2026/04/24/llm-benchmarks-parte-3-deepseek-kimi-mimo/">Part 3</a>; code, logs, and the rubric are in the <a href="https://github.com/akitaonrails/llm-coding-benchmark"target="_blank" rel="noopener">benchmark repository</a>.</p>
<h2>First, the harness problem<span class="hx:absolute hx:-mt-20" id="first-the-harness-problem"></span>
    <a href="#first-the-harness-problem" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Previous Kimi rounds used OpenCode through OpenRouter. K3 did not get through the door: Moonshot&rsquo;s strict tool-schema validator rejected the schema OpenCode sends:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><pre><code>when using anyOf, type should be defined in anyOf items instead of the parent schema</code></pre></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>A controlled probe with a clean schema got tool calling to work. The problem is in the <strong>OpenCode ↔ Moonshot</strong> pairing. K2.5, K2.6, and K2.7 worked with the same tooling. Be careful with headlines saying “the model does not support tools”: sometimes the bug is in the fit.</p>
<p>So as not to abandon the test, a first-class runner for Kimi Code CLI was added. Phase 1 calls:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">kimi -p &lt;prompt&gt; --output-format stream-json -m &lt;model&gt;</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>and phase 2 resumes the session with <code>-S &lt;session_id&gt;</code>. The runner code and configuration are in <a href="https://github.com/akitaonrails/llm-coding-benchmark/commit/0cdf88a"target="_blank" rel="noopener">commit 0cdf88a</a>. The original error and investigation were recorded in commits <a href="https://github.com/akitaonrails/llm-coding-benchmark/commit/c3ab6d5"target="_blank" rel="noopener">c3ab6d5</a> and <a href="https://github.com/akitaonrails/llm-coding-benchmark/commit/506357b"target="_blank" rel="noopener">506357b</a>; the final K3 project landed in <a href="https://github.com/akitaonrails/llm-coding-benchmark/commit/2bf1d7b3e3bbc7e6ff9a18a07390333c86bda615"target="_blank" rel="noopener">2bf1d7b</a>.</p>
<p>This also puts an honest asterisk on the score. I wanted to compare the whole family under the new harness. The Kimi subscription exposes K3 and managed <strong>K2.7-Coding</strong>, but not K2.5/K2.6. We reran K2.7 through the CLI and compared it with the existing K2.5/K2.6/OpenRouter artifacts. K2.7 CLI came in at an informal <strong>68/B</strong>; K2.7 OpenCode/OpenRouter had scored <strong>86/A</strong>. This is harness and snapshot sensitivity, not a clean causal claim that “the harness costs 18 points”: managed <code>kimi-for-coding</code> may not be the same public K2.7 snapshot.</p>
<h2>Current ranking: 40 models<span class="hx:absolute hx:-mt-20" id="current-ranking-40-models"></span>
    <a href="#current-ranking-40-models" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>K2.7 CLI is informal and unranked, so it is not included. The cost column is the actual cost at the round&rsquo;s provider/OpenRouter or a subscription estimate, not an abstract rate card.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right">Rank</th>
          <th>Model</th>
          <th style="text-align: right">Score</th>
          <th style="text-align: center">Tier</th>
          <th style="text-align: center">RubyLLM OK</th>
          <th>Runtime</th>
          <th>Cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">1</td>
          <td>Claude Opus 4.7</td>
          <td style="text-align: right">97</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>18m</td>
          <td>~$7.00</td>
      </tr>
      <tr>
          <td style="text-align: right">2</td>
          <td>GPT 5.4 xHigh (Codex)</td>
          <td style="text-align: right">95</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>22m</td>
          <td>~$16</td>
      </tr>
      <tr>
          <td style="text-align: right">2</td>
          <td>Claude Opus 4.8</td>
          <td style="text-align: right">95</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>17m</td>
          <td>~$6.40</td>
      </tr>
      <tr>
          <td style="text-align: right">4</td>
          <td>Claude Fable 5</td>
          <td style="text-align: right">94</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>24m</td>
          <td>~$11.20</td>
      </tr>
      <tr>
          <td style="text-align: right">5</td>
          <td>Claude Fable 5 (re-release)</td>
          <td style="text-align: right">93</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>18m</td>
          <td>~$8.30</td>
      </tr>
      <tr>
          <td style="text-align: right">5</td>
          <td>Gemini 3.5 Flash</td>
          <td style="text-align: right">93</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>18m</td>
          <td>~$3.55</td>
      </tr>
      <tr>
          <td style="text-align: right">7</td>
          <td>GPT 5.6 Sol xHigh (Codex)</td>
          <td style="text-align: right">92</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>17m</td>
          <td>credits (≈$8.70 API-equiv.)</td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>8</strong></td>
          <td><strong>Kimi K3 (Kimi Code CLI)</strong></td>
          <td style="text-align: right"><strong>89</strong></td>
          <td style="text-align: center"><strong>A</strong></td>
          <td style="text-align: center">✅</td>
          <td><strong>26m</strong></td>
          <td><strong>credits (≈$2.10 API-equiv.)</strong></td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>9</strong></td>
          <td><strong>Kimi K2.6</strong></td>
          <td style="text-align: right"><strong>87</strong></td>
          <td style="text-align: center"><strong>A</strong></td>
          <td style="text-align: center">✅</td>
          <td><strong>20m</strong></td>
          <td><strong>~$1.19</strong></td>
      </tr>
      <tr>
          <td style="text-align: right">9</td>
          <td>GLM 5.2 (Z.ai)</td>
          <td style="text-align: right">87</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>43m</td>
          <td>subscription</td>
      </tr>
      <tr>
          <td style="text-align: right">9</td>
          <td>Grok 4.5</td>
          <td style="text-align: right">87</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>16m</td>
          <td>~$5.10</td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>12</strong></td>
          <td><strong>Kimi K2.7 Code</strong></td>
          <td style="text-align: right"><strong>86</strong></td>
          <td style="text-align: center"><strong>A</strong></td>
          <td style="text-align: center">✅</td>
          <td><strong>22m</strong></td>
          <td><strong>~$1.23</strong></td>
      </tr>
      <tr>
          <td style="text-align: right">13</td>
          <td>GPT 5.5 xHigh (Codex)</td>
          <td style="text-align: right">85</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>18m</td>
          <td>~$10</td>
      </tr>
      <tr>
          <td style="text-align: right">14</td>
          <td>Claude Opus 4.6</td>
          <td style="text-align: right">83</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>16m</td>
          <td>~$1.10 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">14</td>
          <td>Nex-N2-Pro</td>
          <td style="text-align: right">83</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>25m</td>
          <td>~$0.34 (was free)</td>
      </tr>
      <tr>
          <td style="text-align: right">16</td>
          <td>Gemini 3.1 Pro</td>
          <td style="text-align: right">79</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>14m</td>
          <td>~$3.10</td>
      </tr>
      <tr>
          <td style="text-align: right">16</td>
          <td>Sakana Fugu Ultra</td>
          <td style="text-align: right">79</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>22m</td>
          <td>subscription</td>
      </tr>
      <tr>
          <td style="text-align: right">18</td>
          <td>Claude Sonnet 4.6</td>
          <td style="text-align: right">78</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>16m</td>
          <td>~$0.63 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">18</td>
          <td>DeepSeek V4 Flash</td>
          <td style="text-align: right">78</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>3m</td>
          <td>~$0.01</td>
      </tr>
      <tr>
          <td style="text-align: right">18</td>
          <td>MiniMax M3</td>
          <td style="text-align: right">78</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>53m (phase 2 DNF)</td>
          <td>~$1.25</td>
      </tr>
      <tr>
          <td style="text-align: right">18</td>
          <td>Qwen3.7 Max</td>
          <td style="text-align: right">78</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>19m</td>
          <td>~$1.40</td>
      </tr>
      <tr>
          <td style="text-align: right">22</td>
          <td>Grok 4.3</td>
          <td style="text-align: right">72</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>15m</td>
          <td>~$1.70</td>
      </tr>
      <tr>
          <td style="text-align: right">23</td>
          <td>Qwen 3.6 Plus</td>
          <td style="text-align: right">71</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>17m</td>
          <td>~$0.15 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">24</td>
          <td>DeepSeek V4 Pro</td>
          <td style="text-align: right">69</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>22m (DNF)</td>
          <td>~$0.05</td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>24</strong></td>
          <td><strong>Kimi K2.5</strong></td>
          <td style="text-align: right"><strong>69</strong></td>
          <td style="text-align: center"><strong>B</strong></td>
          <td style="text-align: center">✅</td>
          <td><strong>29m</strong></td>
          <td><strong>~$0.10 (hist.)</strong></td>
      </tr>
      <tr>
          <td style="text-align: right">24</td>
          <td>Step 3.7 Flash</td>
          <td style="text-align: right">69</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>27m</td>
          <td>~$0.80</td>
      </tr>
      <tr>
          <td style="text-align: right">27</td>
          <td>Xiaomi MiMo V2.5 Pro</td>
          <td style="text-align: right">67</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>11m</td>
          <td>~$0.09</td>
      </tr>
      <tr>
          <td style="text-align: right">28</td>
          <td>GLM 5</td>
          <td style="text-align: right">64</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>17m</td>
          <td>~$0.11 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">29</td>
          <td>Claude Sonnet 5</td>
          <td style="text-align: right">58</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td>27m</td>
          <td>~$2.25</td>
      </tr>
      <tr>
          <td style="text-align: right">30</td>
          <td>Step 3.5 Flash</td>
          <td style="text-align: right">56</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">⚠️ bypass</td>
          <td>38m</td>
          <td>~$0.02 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">31</td>
          <td>Qwen 3.5 35B</td>
          <td style="text-align: right">55</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">✅</td>
          <td>28m</td>
          <td>free</td>
      </tr>
      <tr>
          <td style="text-align: right">32</td>
          <td>GLM 4.7 Flash bf16</td>
          <td style="text-align: right">52</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">✅</td>
          <td>failed</td>
          <td>free</td>
      </tr>
      <tr>
          <td style="text-align: right">33</td>
          <td>GLM 5.1 (Z.ai)</td>
          <td style="text-align: right">46</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td>22m</td>
          <td>subscription</td>
      </tr>
      <tr>
          <td style="text-align: right">34</td>
          <td>DeepSeek V3.2</td>
          <td style="text-align: right">43</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td>60m</td>
          <td>~$0.07 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">35</td>
          <td>Qwen 3.5 397B A17B (base)</td>
          <td style="text-align: right">42</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td>15m</td>
          <td>~$0.31</td>
      </tr>
      <tr>
          <td style="text-align: right">36</td>
          <td>MiniMax M2.7</td>
          <td style="text-align: right">41</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td>14m</td>
          <td>~$0.30 (hist.)</td>
      </tr>
      <tr>
          <td style="text-align: right">37</td>
          <td>Qwen 3.5 122B</td>
          <td style="text-align: right">37</td>
          <td style="text-align: center">D</td>
          <td style="text-align: center">❌</td>
          <td>43m</td>
          <td>free</td>
      </tr>
      <tr>
          <td style="text-align: right">38</td>
          <td>Qwen 3 Coder Next</td>
          <td style="text-align: right">32</td>
          <td style="text-align: center">D</td>
          <td style="text-align: center">❌</td>
          <td>17m</td>
          <td>free</td>
      </tr>
      <tr>
          <td style="text-align: right">39</td>
          <td>Grok 4.20</td>
          <td style="text-align: right">25</td>
          <td style="text-align: center">D</td>
          <td style="text-align: center">❌</td>
          <td>8m</td>
          <td>~$0.70</td>
      </tr>
      <tr>
          <td style="text-align: right">40</td>
          <td>GPT OSS 20B</td>
          <td style="text-align: right">11</td>
          <td style="text-align: center">D</td>
          <td style="text-align: center">❌</td>
          <td>failed</td>
          <td>free</td>
      </tr>
  </tbody>
</table>
<h2>Kimi evolved quickly. Its price even more so.<span class="hx:absolute hx:-mt-20" id="kimi-evolved-quickly-its-price-even-more-so"></span>
    <a href="#kimi-evolved-quickly-its-price-even-more-so" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>K2.5 scored <strong>69/B</strong> in February. K2.6 jumped to <strong>87/A</strong> in April. K2.7 stayed at <strong>86/A</strong> in June. Now K3 reaches <strong>89/A</strong> in July. There was a big jump with K2.6, a plateau in K2.7, and K3 pushes the ceiling a bit higher.</p>
<p>From the official spec sheet, only what matters here: K3 has 1M context, MoE architecture (mixture of experts, which activates only parts of the model for each token), and maximum reasoning mode. Useful for understanding the product&rsquo;s ambition. It does not replace opening the project it wrote.</p>
<h2>What K3 actually wrote<span class="hx:absolute hx:-mt-20" id="what-k3-actually-wrote"></span>
    <a href="#what-k3-actually-wrote" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>There is quite a lot right in the <a href="https://github.com/akitaonrails/llm-coding-benchmark/blob/2bf1d7b3e3bbc7e6ff9a18a07390333c86bda615/results/kimi_k3_cli/project/app/models/conversation.rb#L31-L52"target="_blank" rel="noopener"><code>Conversation</code> model</a>. It builds the chat, replays only the prior history, and then calls <code>ask(content)</code>; the current message enters the collection only after the response. No double-send. If the provider fails, the exception is raised before <code>append</code>, so a failed turn is not stored:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">build_llm_chat</span><span class="o">.</span><span class="n">ask</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">append</span><span class="p">(</span><span class="no">Message</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="ss">role</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="ss">content</span><span class="p">:</span> <span class="n">content</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">append</span><span class="p">(</span><span class="no">Message</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="ss">role</span><span class="p">:</span> <span class="s2">&#34;assistant&#34;</span><span class="p">,</span> <span class="ss">content</span><span class="p">:</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="o">.</span><span class="n">to_s</span><span class="p">))</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>It also got persistence better than the global-hash pattern: <a href="https://github.com/akitaonrails/llm-coding-benchmark/blob/2bf1d7b3e3bbc7e6ff9a18a07390333c86bda615/results/kimi_k3_cli/project/app/controllers/concerns/conversation_store.rb#L12-L18"target="_blank" rel="noopener">Rails.cache with a one-day TTL</a>, a key per session, and a <a href="https://github.com/akitaonrails/llm-coding-benchmark/blob/2bf1d7b3e3bbc7e6ff9a18a07390333c86bda615/results/kimi_k3_cli/project/app/models/conversation.rb#L6-L8"target="_blank" rel="noopener">20-message limit</a>. Docker is production-grade, non-root, and validation performed a real chat both locally and in the container. That is real Tier A, not an optimistic README.</p>
<p>But you can still see the signature of a generation. It does not use <code>with_instructions</code>, so there is no system prompt. The LLM call lives inside the domain model. There is no preflight for a missing key.</p>
<p>Each individual message can grow without a ceiling and there is no rate limit. The production cache remains the ephemeral default. The <code>read</code> + mutation + <code>write</code> sequence races between requests. Raw provider errors appear in the UI. The error suite is smaller than it should be.</p>
<p>Against <strong>Opus 4.6</strong>, K3 clearly wins in this artifact: correct public RubyLLM API, bounded state, and tests for provider failures. <a href="https://github.com/akitaonrails/llm-coding-benchmark/blob/2bf1d7b3e3bbc7e6ff9a18a07390333c86bda615/results/claude_opus_4_6/project/app/controllers/chats_controller.rb#L41-L56"target="_blank" rel="noopener">Opus 4.6 manipulates <code>chat.messages</code> directly</a>, stores an uncapped cookie, and does not cover provider errors.</p>
<p><a href="https://github.com/akitaonrails/llm-coding-benchmark/blob/2bf1d7b3e3bbc7e6ff9a18a07390333c86bda615/results/claude_opus_4_8/project/app/services/chat_service.rb#L21-L51"target="_blank" rel="noopener">Opus 4.8 models preconditions, the system prompt, and replay better</a>. The basic RubyLLM call is comparable. The distance appears in hardening, architecture, and test depth.</p>
<table>
  <thead>
      <tr>
          <th>Artifact</th>
          <th style="text-align: right">Score</th>
          <th>What it delivered</th>
          <th>Where it fell short</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Kimi K3</td>
          <td style="text-align: right">89</td>
          <td>Correct replay, cap, cache with TTL, tested error</td>
          <td>No system prompt, ephemeral cache, race, and raw error</td>
      </tr>
      <tr>
          <td>Claude Opus 4.6</td>
          <td style="text-align: right">83</td>
          <td>Working RubyLLM, production Docker</td>
          <td>Fragile replay, uncapped cookie, almost no error tests</td>
      </tr>
      <tr>
          <td>Claude Opus 4.8</td>
          <td style="text-align: right">95</td>
          <td>Disciplined service, invariants, and 34 tests</td>
          <td>Cookie still uncapped, missing key preflight</td>
      </tr>
      <tr>
          <td>Claude Fable 5</td>
          <td style="text-align: right">94/93</td>
          <td>Preflight, input limits, defensive tests</td>
          <td>Persistence trade-offs and high price</td>
      </tr>
  </tbody>
</table>
<p><strong>Fable 5</strong> is more defensive, but charges for it: original/re-release 94/93, against 89; $10/$50 per million, against $3/$15; measured runs of <del>$11.20/</del>$8.30, against ~$2.10 API-equivalent. One run per cell does not provide statistical certainty. It provides concrete code to compare.</p>
<h2>Pricing: Kimi is no longer the absurd bargain<span class="hx:absolute hx:-mt-20" id="pricing-kimi-is-no-longer-the-absurd-bargain"></span>
    <a href="#pricing-kimi-is-no-longer-the-absurd-bargain" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>It is important here to separate Moonshot direct API, OpenRouter, and subscription. This is the official direct API rate card, per million tokens, with cached input separated:</p>
<table>
  <thead>
      <tr>
          <th>Model</th>
          <th style="text-align: right">Cached input</th>
          <th style="text-align: right">Input</th>
          <th style="text-align: right">Output</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>K2.5</td>
          <td style="text-align: right">$0.10</td>
          <td style="text-align: right">$0.60</td>
          <td style="text-align: right">$3</td>
      </tr>
      <tr>
          <td>K2.6</td>
          <td style="text-align: right">$0.16</td>
          <td style="text-align: right">$0.95</td>
          <td style="text-align: right">$4</td>
      </tr>
      <tr>
          <td>K2.7</td>
          <td style="text-align: right">$0.19</td>
          <td style="text-align: right">$0.95</td>
          <td style="text-align: right">$4</td>
      </tr>
      <tr>
          <td>K3</td>
          <td style="text-align: right">$0.30</td>
          <td style="text-align: right">$3</td>
          <td style="text-align: right">$15</td>
      </tr>
  </tbody>
</table>
<p>Official documentation: <a href="https://platform.kimi.ai/docs/pricing/chat-k25"target="_blank" rel="noopener">K2.5</a>, <a href="https://platform.kimi.ai/docs/pricing/chat-k26"target="_blank" rel="noopener">K2.6</a>, <a href="https://platform.kimi.ai/docs/pricing/chat-k27-code"target="_blank" rel="noopener">K2.7 Code</a>, and <a href="https://platform.kimi.ai/docs/pricing/chat-k3"target="_blank" rel="noopener">K3</a>. For intermediary pricing and availability, also see the <a href="https://openrouter.ai/moonshotai/kimi-k3"target="_blank" rel="noopener">K3 page on OpenRouter</a>.</p>
<p>K3 costs <strong>3.16× more for input</strong> and <strong>3.75× more for output</strong> than K2.6/2.7. Moonshot left the ultra-cheap niche. The costs in the ranking table are something else: K2.6 ~$1.19 and K2.7 ~$1.23 were recomputed from the provider/OpenRouter and the run tokens; K3 is an API-equivalent estimate of ~$2.10 for a subscription-billed run. Mixing the two without identifying the channel creates a false comparison.</p>
<p>Even so, K3 costs 40% less than Opus 4.8 at official rates ($5/$25) and 70% less than Fable ($10/$50). On the <strong>$19 Kimi Moderato plan</strong>, this is excellent for interactive solo coding. Just do not automate recklessly: we observed around two heavy rounds per five-hour window and quota recovery in 4h16. For unsupervised batch work, a mid-run 403 throws away work and time.</p>
<h3>Moderato is too small for serious work<span class="hx:absolute hx:-mt-20" id="moderato-is-too-small-for-serious-work"></span>
    <a href="#moderato-is-too-small-for-serious-work" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>This is the part the monthly price hides. I used the $19/month Moderato. Its quota is organized in rolling five-hour windows: use a lot now, then wait for the window to slide forward before capacity returns. A benchmark run is not one loose prompt. It is exactly two prompts/phases: build the app, then resume the same session to validate and fix it.</p>
<p>K3 completed that whole run in 26 minutes and 4.83 million tokens, almost all cache-read, about $2.10 API-equivalent. K2.7 Coding completed the same two prompts in 16 minutes and 9.25 million tokens. In the benchmark record, approximately two complete runs at that scale fit before a third received a hard 403 partway through. The partial build was lost. Recovery took 4h16, with seven blocked probes at 20-minute intervals.</p>
<p>One caveat: I did not commit the raw 403/probe transcript. This chronology is a recorded benchmark observation, not something another person can independently audit from raw logs. The documentation says already-running tasks normally finish; our third one did not. That is what I saw in use, not an accusation that the documentation is lying.</p>
<p>Official plans are on the <a href="https://www.kimi.com/help/membership/membership-pricing"target="_blank" rel="noopener">membership page</a>:</p>
<table>
  <thead>
      <tr>
          <th>Plan</th>
          <th style="text-align: right">Monthly / annual equivalent</th>
          <th style="text-align: right">Credits</th>
          <th style="text-align: right">Concurrent tasks</th>
          <th>Verdict</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Adagio</td>
          <td style="text-align: right">free</td>
          <td style="text-align: right">—</td>
          <td style="text-align: right">—</td>
          <td>To try it out, not for a heavy session</td>
      </tr>
      <tr>
          <td>Moderato</td>
          <td style="text-align: right">$19 / $15 ($180/year)</td>
          <td style="text-align: right">1x</td>
          <td style="text-align: right">2</td>
          <td>One or, at most, around two heavy sessions per window; too small for a serious routine</td>
      </tr>
      <tr>
          <td>Allegretto</td>
          <td style="text-align: right">$39 / $31</td>
          <td style="text-align: right">5x</td>
          <td style="text-align: right">2</td>
          <td>The sensible minimum for lighter daily interactive use</td>
      </tr>
      <tr>
          <td>Allegro</td>
          <td style="text-align: right">$99 / $79</td>
          <td style="text-align: right">15x</td>
          <td style="text-align: right">4</td>
          <td>The first plan I recommend for sustained professional use, at least 5h/day</td>
      </tr>
      <tr>
          <td>Vivace</td>
          <td style="text-align: right">$199 / $159</td>
          <td style="text-align: right">30x</td>
          <td style="text-align: right">4</td>
          <td>Parallel agents or near-continuous heavy use; probably overkill for one person</td>
      </tr>
  </tbody>
</table>
<p>K3 on Moderato is limited to 256K context. Allegretto and above unlock up to 1M. Allegretto+ also unlocks HighSpeed, but that mode burns roughly 3x the quota. The 5x/15x/30x are relative credits, not a promise of 5/15/30 times more linear runs. The documentation discloses weekly refresh, the rolling five-hour window, and shared quota across CLI, VS Code, and API-key tools, but does not publish the exact formula for a heavy session or token. Cache, output, and agent behavior change the math a lot.</p>
<p>Moderato is good for one, maybe two heavy sessions in five hours. For five hours of coding a day, it is too small: in a sequence of these tiny benchmark runs, with only two prompts per model, the third attempt already hit cooldown. Cooldown is the wait for the quota window to open again. Allegretto is the minimum upgrade for lighter daily interaction and gets 1M context, but 5x can leave little headroom for someone driving the agent continuously or enabling HighSpeed. For sustained professional use, at least five hours a day, I would go with <strong>Allegro</strong>: 15x credits and four concurrent tasks. There is still no official guarantee of uninterrupted execution. Vivace is for multiple agents or near-continuous load; for one developer, it is generally overkill.</p>
<p>The other choice is subscription or direct API. The K3 API charges $0.30/M cached input, $3/M uncached input, and $15/M output. It provides explicit accounting, the full 1M context, and does not have the membership weekly quota, although normal API limits still apply. It is the better route for CI, batch work, and long runs worth real money.</p>
<p>A subscription buys something else: fixed monthly cost, convenient OAuth/CLI, near-zero marginal cost within the caps, and a predictable bill. In return, you accept a hidden token envelope, rolling/weekly caps, shared allowance, the risk of stopping midway, and no SLA for unattended automation. The K3 ~$2.10 is only a rough API-equivalent. At that run shape, the Moderato monthly fee arithmetically equals around 9 runs, Allegretto 19, Allegro 47, and Vivace 95 per month. That is invoice arithmetic, not a quota guarantee: real workloads vary wildly with cache and output.</p>
<p>Kimi also offers <a href="https://www.kimi.com/code/docs/en/kimi-code/membership.html"target="_blank" rel="noopener">Extra Usage</a>, which can fall back to paid balance under a spending cap. It helps prevent an abrupt quota stop. The exact USD rate is not published, and it does not turn a consumer membership into an automation SLA.</p>
<p>My plain recommendation: for 5h/day, Allegro. For lighter interaction, Allegretto. For automation and CI, pay-as-you-go API. If you stay on subscription and the work cannot stop, enable Extra Usage with a spending cap.</p>
<p>Separating plan from model: K2.6 remains the best raw-API option for high-volume automation with human review. K3 is a very good option for those coding interactively. Opus 4.8 remains my choice for complex refactors, concurrency, security, and autonomous changes where correctness matters more than the bill. Fable, in this slice, is economically dominated.</p>
<h2>Bonus: GLM 5.2 versus Opus<span class="hx:absolute hx:-mt-20" id="bonus-glm-52-versus-opus"></span>
    <a href="#bonus-glm-52-versus-opus" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>GLM 5.2 is at <strong>#9, 87/A, 43 minutes</strong>, through a Z.ai subscription. The natural comparison is Opus 4.6, its score neighbor at 83/A and 16 minutes, and Opus 4.8, the quality ceiling at 95/A and 17 minutes.</p>
<p>I read both projects. GLM beats the Opus 4.6 artifact: it uses RubyLLM correctly, applies a system prompt, separates the service, accepts DI, and tests failures. The <a href="https://github.com/akitaonrails/llm-coding-benchmark/blob/2bf1d7b3e3bbc7e6ff9a18a07390333c86bda615/results/glm_5_2/project/app/services/chat_service.rb#L28-L55"target="_blank" rel="noopener">service</a> even excludes the last message from replay before calling <code>ask</code>, the detail that avoids double-send.</p>
<p>But GLM also leaves skeletons in the closet: uncapped process-local singleton; failed turns are retained; <code>config.hosts.clear</code>; generated secret that invalidates sessions; and <code>npm ci || npm install</code>, which turns the lockfile into a suggestion. It remains clearly behind Opus 4.8 in state, design, tests, and configuration hardening.</p>
<p>Z.ai plans are Lite $18, Pro $72, and Max $160, with a promotion through September 2026: $12.60/$50.40/$112. Against Opus 4.8 at ~$6.40 per run, nominal break-even is approximately <strong>3/12/25</strong> runs per month, or <strong>2/8/18</strong> at the promotional price. But GLM takes 43 minutes where Opus 4.8 took 17. If you already pay for Z.ai, GLM 5.2 is a strong default for routine reviewed work. If correctness and turnaround rule, Opus 4.8.</p>
<h2>Conclusion<span class="hx:absolute hx:-mt-20" id="conclusion"></span>
    <a href="#conclusion" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>In this greenfield Rails project, K3 is a good replacement for Opus 4.6 and offers a cheaper alternative to Opus 4.8. Claude still has the edge when the project demands defenses against details nobody puts in the prompt.</p>
<p>There is one run per model and there is harness effect, especially with K3. The benchmark also does not cover database migrations, background jobs, or product tool calls. There is no data here to make promises about those.</p>
<p>My map today: K2.6 for reviewed-volume API automation; K3/Allegretto for lighter interactive solo work and Allegro for a sustained professional routine; Opus 4.8 when the patch is sensitive; GLM 5.2 as a good subscription default for routine reviewed work. No hype. Read the code, run the tests, and treat every ranking as limited evidence, not religion.</p>
]]></content:encoded><category>llm-benchmarks</category><category>llms</category><category>coding-agents</category></item><item><title>How Do I Protect Myself From My Agents Deleting My Stuff?</title><link>https://akitaonrails.github.io/en/2026/07/11/how-to-protect-yourself-from-agents-deleting-your-stuff/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/07/11/how-to-protect-yourself-from-agents-deleting-your-stuff/</guid><pubDate>Sat, 11 Jul 2026 21:00:00 -0300</pubDate><description>&lt;p&gt;This week the talk on Twitter was LLMs deleting other people&amp;rsquo;s files. &lt;a href="https://x.com/mattshumer_/status/2075657271401390161"target="_blank" rel="noopener"&gt;Matt Shumer posted&lt;/a&gt; that GPT-5.6-Sol accidentally deleted almost ALL the files on his Mac. A review subagent expanded the &lt;code&gt;$HOME&lt;/code&gt; variable incorrectly and ran &lt;code&gt;rm -rf /Users/mattsdevbox&lt;/code&gt;. He killed the process midway, but the damage was already done.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/07/11/agentes-apagando/tweet-mattshumer.webp" alt="Matt Shumer’s tweet: GPT-5.6-Sol accidentally deleted almost all the files on his Mac, running rm -rf /Users/mattsdevbox because of a bad $HOME expansion." loading="lazy" /&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<p>This week the talk on Twitter was LLMs deleting other people&rsquo;s files. <a href="https://x.com/mattshumer_/status/2075657271401390161"target="_blank" rel="noopener">Matt Shumer posted</a> that GPT-5.6-Sol accidentally deleted almost ALL the files on his Mac. A review subagent expanded the <code>$HOME</code> variable incorrectly and ran <code>rm -rf /Users/mattsdevbox</code>. He killed the process midway, but the damage was already done.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/07/11/agentes-apagando/tweet-mattshumer.webp" alt="Matt Shumer’s tweet: GPT-5.6-Sol accidentally deleted almost all the files on his Mac, running rm -rf /Users/mattsdevbox because of a bad $HOME expansion."  loading="lazy" /></p>
<p>The next day, <a href="https://x.com/goodalexander/status/2076019436767584347"target="_blank" rel="noopener">goodalexander reproduced</a> the same behavior on a disposable devnet: an <code>rsync --delete-delay</code> against <code>/</code> swept away <code>/var</code>, <code>/etc</code> and his validators&rsquo; state, corrupting the filesystem to the point of needing an OS reinstall. His conclusion: &ldquo;you can&rsquo;t use this thing in prod&rdquo;.</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/07/11/agentes-apagando/tweet-goodalexander.webp" alt="goodalexander’s tweet: reproduced GPT 5.6 Sol’s destructive behavior on a disposable devnet, with rsync –delete-delay wiping /var and /etc and corrupting the filesystem."  loading="lazy" /></p>
<p>Cases like these pop up every so often since coding agents went mainstream. And every time, the discussion degenerates into the same two extremes: on one side &ldquo;see? AI is dangerous, never let it run anything on its own&rdquo;, on the other &ldquo;whoever lets an agent loose on their system deserves what they get&rdquo;. I find both sides lazy. Let me tell you my actual experience and what I do about it.</p>
<h2>Five months of marathoning, zero accidents<span class="hx:absolute hx:-mt-20" id="five-months-of-marathoning-zero-accidents"></span>
    <a href="#five-months-of-marathoning-zero-accidents" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Since February I&rsquo;ve been marathoning Claude Code, Codex and OpenCode. Almost every day, almost all the time, in very long sessions that sometimes span multiple days. Blowing past the limits of my Anthropic Max plan and my OpenAI Plus plan with room to spare. The concrete result so far: almost 40 new repositories on my GitHub and more than 500 thousand lines of code produced.</p>
<p>And for the past two months I&rsquo;ve been running everything exclusively in &ldquo;YOLO mode&rdquo;. For those unfamiliar with the jargon: by default, these agents ask for permission before each command they&rsquo;re about to execute in your terminal. YOLO mode turns that safety off. In Claude Code it&rsquo;s the <code>--dangerously-skip-permissions</code> flag, in Codex it&rsquo;s <code>--yolo</code>, in OpenCode you configure the permissions to approve everything. The agent runs whatever it wants, whenever it wants, without asking me anything.</p>
<p>In five months under this regime, not once has an agent deleted a file I didn&rsquo;t ask for. Not once has it run a destructive command out of scope. The frustrations I have with agents are of a different nature (stubbornness, lazy solutions, context getting lost), annoying things but miles away from an <code>rm -rf</code> in my home.</p>
<p>So when I see these reports, my first hypothesis always goes to the same place: the prompt. For an agent to &ldquo;go berserk&rdquo; like that, in general the user wrote very bad instructions. Vague, ambiguous, asking for cleanup without defining what counts as trash, telling the agent to &ldquo;fix it&rdquo; without giving context. Lack of communication skills combined with lack of technical knowledge to notice the request was poorly formulated. The agent executes the instruction you wrote, with all the ambiguities you left in it.</p>
<p>That said, I do NOT trust LLMs completely. Nobody should.</p>
<blockquote>
  <p>The difference is that my distrust turns into engineering instead of turning into a tweet.</p>

</blockquote>
<p>Layer by layer, this is how I sleep well at night.</p>
<h2>Layer 1: sandboxing with ai-jail<span class="hx:absolute hx:-mt-20" id="layer-1-sandboxing-with-ai-jail"></span>
    <a href="#layer-1-sandboxing-with-ai-jail" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>When I genuinely suspect a session might do something stupid (I&rsquo;m about to touch system scripts, I&rsquo;m going to let the agent run for hours unsupervised on code that touches the filesystem), I open the harness inside <a href="https://github.com/akitaonrails/ai-jail"target="_blank" rel="noopener">ai-jail</a>, a tool of mine, open source, written in Rust.</p>
<p>ai-jail is a sandbox wrapper for coding agents. On Linux it uses <code>bwrap</code> (bubblewrap, the same foundation as Flatpak), on macOS it uses <code>sandbox-exec</code>. The idea: the process sees a filesystem that looks normal, but only the current project directory is real and persistent. The rest of <code>$HOME</code>, the sibling directories, <code>/tmp</code>, everything lives in tmpfs and evaporates when the session ends. The agent&rsquo;s state (<code>~/.claude</code>, <code>~/.codex</code> etc) is mounted for real so it stays logged in and configured, but <code>~/.ssh</code>, <code>~/.gnupg</code>, <code>~/.aws</code> and browser profiles never enter the jail.</p>
<p>Installing is one command:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Arch Linux</span>
</span></span><span class="line"><span class="cl">yay -S ai-jail-bin
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># macOS / Linux via Homebrew</span>
</span></span><span class="line"><span class="cl">brew tap akitaonrails/tap <span class="o">&amp;&amp;</span> brew install ai-jail
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># or straight from crates.io</span>
</span></span><span class="line"><span class="cl">cargo install ai-jail</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>And using it is even simpler:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> ~/Projects/my-app
</span></span><span class="line"><span class="cl">ai-jail claude       <span class="c1"># Claude Code in the jail</span>
</span></span><span class="line"><span class="cl">ai-jail codex        <span class="c1"># Codex in the jail</span>
</span></span><span class="line"><span class="cl">ai-jail --dry-run claude  <span class="c1"># shows the policy without running</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>If the agent decides to run <code>rm -rf ~</code> in there, it deletes a tmpfs that was going to vanish anyway. My real home was never even mounted. For anyone starting out with YOLO mode without battle scars yet, it&rsquo;s the cheapest way to make mistakes without consequences.</p>
<h2>Layer 2: BTRFS and snapshots (the real safety net)<span class="hx:absolute hx:-mt-20" id="layer-2-btrfs-and-snapshots-the-real-safety-net"></span>
    <a href="#layer-2-btrfs-and-snapshots-the-real-safety-net" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Now the main point of this post. I&rsquo;ve been advocating for YEARS that Linux users should use BTRFS instead of EXT4. I made <a href="/2023/10/19/akitando-146-protegendo-e-recuperando-dados-perdidos-git-backup-btrfs/">an entire Akitando episode about it in 2023</a>, long before coding agents existed to take the blame. The argument was the same: your data needs to survive human error. An LLM running <code>rm -rf</code> in the wrong place is just a new category of human error, outsourced.</p>
<p>Why is BTRFS superior for desktops? Copy-on-write (CoW): the filesystem never overwrites a block in place, it writes the new version to another block and updates the pointers. Checksums for data and metadata, so silent bitrot gets detected instead of quietly corrupting your file. Transparent compression. Subvolumes, which work like flexible partitions without fixed sizes. And the most valuable consequence of CoW: <strong>lightweight snapshots</strong>.</p>
<p>A BTRFS snapshot is instantaneous and costs close to zero space the moment it&rsquo;s created. It freezes the pointers to the current blocks instead of copying data. Only what diverges from that point on (new or modified blocks) starts taking up extra space. In practice you can take dozens of snapshots a day without feeling it. At this very moment my machine keeps 23 system snapshots, and the cost is the difference between them, a few gigs.</p>
<h3>Scheduling snapshots<span class="hx:absolute hx:-mt-20" id="scheduling-snapshots"></span>
    <a href="#scheduling-snapshots" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>The two classic tools are <strong>Timeshift</strong> and <strong>snapper</strong>. Timeshift is the friendlier one: graphical interface, you set &ldquo;how many snapshots to keep&rdquo; per hour/day/week/month and it handles the rest. It expects the <code>@</code> (root) and <code>@home</code> subvolume layout, which is the default for most distros that install on BTRFS today. snapper (born at openSUSE) is more granular: per-subvolume configs, automatic timeline, package manager integration to snapshot before and after every install.</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Timeshift: manual snapshot before a suspicious session</span>
</span></span><span class="line"><span class="cl">sudo timeshift --create --comments <span class="s2">&#34;antes de soltar o agente&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># snapper: create a config for /home and enable the timeline</span>
</span></span><span class="line"><span class="cl">sudo snapper -c home create-config /home
</span></span><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> --now snapper-timeline.timer</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>My setup runs Timeshift on a schedule, plus <code>grub-btrfsd</code> on standby (I&rsquo;ll explain why in a moment).</p>
<h3>Recovering deleted files<span class="hx:absolute hx:-mt-20" id="recovering-deleted-files"></span>
    <a href="#recovering-deleted-files" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Here&rsquo;s the magic that everyone who lost files to an agent wishes they had. A BTRFS snapshot is browsable like a regular directory. The agent deleted your project at 3pm? The 2pm snapshot still has everything:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># with Timeshift, snapshots are mounted under /run/timeshift</span>
</span></span><span class="line"><span class="cl">sudo ls /run/timeshift/backup/timeshift-btrfs/snapshots/
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># found the snapshot from before the damage? copy it back and done</span>
</span></span><span class="line"><span class="cl">sudo cp -a /run/timeshift/backup/timeshift-btrfs/snapshots/2026-07-11_14-00-01/@home/akitaonrails/Projects/meu-app ~/Projects/</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>With snapper it&rsquo;s the same thing via <code>.snapshots</code> inside the subvolume, and it also has <code>snapper undochange</code> to revert specific changes between two snapshots. Recovery in seconds, no drama, no forensic tooling.</p>
<h3>What if the system won&rsquo;t even boot?<span class="hx:absolute hx:-mt-20" id="what-if-the-system-wont-even-boot"></span>
    <a href="#what-if-the-system-wont-even-boot" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>goodalexander&rsquo;s case went beyond losing files: the agent swept <code>/var</code> and <code>/etc</code> and the system became unusable, requiring an OS reinstall. With BTRFS not even that would be necessary. This is the scenario <a href="https://github.com/Antynea/grub-btrfs"target="_blank" rel="noopener">grub-btrfs</a> exists for: a daemon that watches your snapshots and regenerates the GRUB menu with a boot entry for each one.</p>
<p>System won&rsquo;t come up anymore? Reboot, hold the GRUB menu, pick &ldquo;snapshots&rdquo; and boot straight into yesterday&rsquo;s snapshot, read-only. From inside it, run <code>timeshift --restore</code>, pick the good snapshot, reboot again. Entire system back to its pre-disaster state, in less time than it would take you to find the installation USB stick. In the absolute worst case (GRUB itself went down with the ship), any live USB mounts the BTRFS partition, points the default subvolume back to the good snapshot and that&rsquo;s that.</p>
<h3>What about macOS? And Windows?<span class="hx:absolute hx:-mt-20" id="what-about-macos-and-windows"></span>
    <a href="#what-about-macos-and-windows" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>Mac users have the direct equivalent: <strong>APFS</strong>, the default filesystem since High Sierra (2017), is also copy-on-write and also has lightweight snapshots. Time Machine is what manages them: with it enabled, macOS takes automatic local snapshots every hour and keeps the last 24 hours on the disk itself, independent of the external backup. And you can create one by hand before letting the agent loose:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># create an APFS local snapshot right now</span>
</span></span><span class="line"><span class="cl">tmutil localsnapshot
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># list the existing snapshots</span>
</span></span><span class="line"><span class="cl">tmutil listlocalsnapshots /</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>To recover, open Time Machine itself (&ldquo;Browse Time Machine Backups&rdquo; in the menu bar): it browses the local snapshots even without any external disk plugged in, and you restore the file from there. If you prefer the terminal, mount the snapshot read-only with <code>mount_apfs -s</code> and copy it back. In other words, Matt Shumer&rsquo;s case from the beginning of this post had a native solution on his own Mac: a snapshot from one hour earlier would have brought almost everything back.</p>
<p>On Windows the story is weaker. NTFS has the Volume Shadow Copy service (VSS), which feeds restore points and the &ldquo;Previous Versions&rdquo; tab, but it&rsquo;s aimed at system files and rarely happens to be covering your data at the moment you need it. Nothing with the lightness and predictability of a scheduled CoW snapshot. If you develop on Windows, treat external backup as mandatory, no discussion (and the restic from the next section runs fine on Windows).</p>
<h2>Layer 3: external backups with restic<span class="hx:absolute hx:-mt-20" id="layer-3-external-backups-with-restic"></span>
    <a href="#layer-3-external-backups-with-restic" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Snapshots live on the same disk as the data. If the NVMe dies, they die together. Which is the other thing I&rsquo;ve been repeating for years: <strong>everybody needs external backups</strong>, whether to an external hard drive or a NAS. I use a Synology on the local network, mounted via NFS, and <a href="/en/2025/04/17/configuring-my-synology-nas-with-nfs-on-linux/">documented the complete setup here</a>.</p>
<p>On top of it runs <a href="https://restic.net/"target="_blank" rel="noopener">restic</a>, which in my opinion is the best backup tool for this purpose: deduplication, encryption, incremental snapshots and simple restores. My actual configuration is a script fired by a systemd timer every day at 3am. It checks the NAS is mounted, backs up <code>/home</code> and <code>/mnt/data/Projects</code> skipping caches (<code>node_modules</code>, Rust&rsquo;s <code>target/</code>, <code>__pycache__</code> and friends, all in an excludes file), and then applies the retention policy: 7 daily, 4 weekly, 6 monthly, 1 yearly.</p>
<p>Reproducing the essentials looks like this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># once: create the repository on the NAS</span>
</span></span><span class="line"><span class="cl">restic init --repo /mnt/nas/desktop-backup
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># every day (via cron or a systemd timer):</span>
</span></span><span class="line"><span class="cl">restic -r /mnt/nas/desktop-backup backup ~ /mnt/data/Projects <span class="se">\
</span></span></span><span class="line"><span class="cl">    --exclude-file<span class="o">=</span>~/.config/restic/excludes --exclude-caches
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">restic -r /mnt/nas/desktop-backup forget <span class="se">\
</span></span></span><span class="line"><span class="cl">    --keep-daily <span class="m">7</span> --keep-weekly <span class="m">4</span> --keep-monthly <span class="m">6</span> --keep-yearly <span class="m">1</span> --prune</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>And if the truly bad day arrives (destructive agent, dead disk, ransomware, the cause doesn&rsquo;t matter):</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># list the available snapshots</span>
</span></span><span class="line"><span class="cl">restic -r /mnt/nas/desktop-backup snapshots
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># restore a specific file or directory</span>
</span></span><span class="line"><span class="cl">restic -r /mnt/nas/desktop-backup restore latest <span class="se">\
</span></span></span><span class="line"><span class="cl">    --target /tmp/recuperado --include /home/akitaonrails/Projects/meu-app
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># or mount the whole repository as a filesystem and browse at your leisure</span>
</span></span><span class="line"><span class="cl">restic -r /mnt/nas/desktop-backup mount /mnt/restic</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Notice the layered architecture: the BTRFS snapshot solves the accident from minutes ago in seconds. restic solves the disaster from days ago, including dead hardware. An AI agent would have to be very dedicated to punch through both layers, and even then there would still be yesterday&rsquo;s copy on the NAS, which it can&rsquo;t even reach.</p>
<h2>What about companies? Professionalism<span class="hx:absolute hx:-mt-20" id="what-about-companies-professionalism"></span>
    <a href="#what-about-companies-professionalism" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Everything above is about my personal machine. Now let&rsquo;s raise the bar: corporate environments.</p>
<p>Rule number one is simple and non-negotiable: <strong>no AI agent should ever have access to production. Ever.</strong> No direct SSH into production servers, no production database credentials, no admin tokens for production services. If your agent can run a <code>DELETE</code> against the database that serves customers, the problem stopped being the AI a long time ago: any intern with the same access is the same time bomb, just with a slower typing speed.</p>
<p>Agents in <strong>staging</strong>, on the other hand, I advocate for. That&rsquo;s what staging is for. But even in staging there&rsquo;s a right way: you resist the temptation of prompting one-shot actions (&ldquo;run an <code>apt install</code> over there&rdquo;, &ldquo;do a <code>systemctl restart</code>&rdquo;, &ldquo;connect to postgres and execute this&rdquo;). A loose command executed by hand is knowledge that evaporates. Your infrastructure needs to be automated and reproducible: Ansible, Kubernetes, Terraform, whatever makes sense for your stack. The agent&rsquo;s role becomes writing and refining those recipes, which live versioned in git.</p>
<h3>A small example, right here from my desk<span class="hx:absolute hx:-mt-20" id="a-small-example-right-here-from-my-desk"></span>
    <a href="#a-small-example-right-here-from-my-desk" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>I have a gaming environment on my main PC, but I refuse to mix emulator packages with my software development environment. So I isolated gaming inside a <a href="https://github.com/89luca89/distrobox"target="_blank" rel="noopener">distrobox</a>. For those who don&rsquo;t know it: distrobox creates containers (via podman or docker) that integrate with your desktop as if they were native. They share your home (or a dedicated home), GPU access, Wayland, audio. In practice it&rsquo;s a complete distro inside your distro, with a separate package space.</p>
<p><a href="https://github.com/akitaonrails/distrobox-gaming"target="_blank" rel="noopener">distrobox-gaming</a> is a repository of Ansible playbooks that builds an Arch box called <code>gaming</code> from scratch: ES-DE as the frontend, standalone emulators (shadPS4, RPCS3, PCSX2, Dolphin, DuckStation, Eden and a dozen more), RetroArch cores, per-game optimized configs, launcher shortcuts on the host. And <a href="https://github.com/akitaonrails/distrobox-llm"target="_blank" rel="noopener">distrobox-llm</a> does the same for a local LLM work box: CUDA, cuDNN, Ollama, whisper.cpp and LM Studio isolated in a box with <code>--nvidia</code>, while the host only carries the driver. A CUDA major version upgrade no longer rattles my development environment.</p>
<p>Who wrote the overwhelming majority of these playbooks? The agents. Instead of asking &ldquo;install RPCS3 for me&rdquo;, my prompt is &ldquo;write the idempotent Ansible recipe that installs and configures RPCS3, run it, verify the result and fix it until it passes&rdquo;. Here&rsquo;s a real excerpt from the role that creates the LLM box:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Check if distrobox exists</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">ansible.builtin.shell</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;distrobox list 2&gt;/dev/null | awk &#39;{print $3}&#39; | grep -qx {{ dl_box_name }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">register</span><span class="p">:</span><span class="w"> </span><span class="l">_box_exists</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">changed_when</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">failed_when</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl">- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Create distrobox</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">ansible.builtin.command</span><span class="p">:</span><span class="w"> </span><span class="p">&gt;-</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">    distrobox create
</span></span></span><span class="line"><span class="cl"><span class="sd">    --name {{ dl_box_name }}
</span></span></span><span class="line"><span class="cl"><span class="sd">    --image {{ dl_image }}
</span></span></span><span class="line"><span class="cl"><span class="sd">    --home {{ dl_box_home }}
</span></span></span><span class="line"><span class="cl"><span class="sd">    {{ &#39;--nvidia&#39; if dl_nvidia_enabled else &#39;&#39; }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">when</span><span class="p">:</span><span class="w"> </span><span class="l">_box_exists.rc != 0</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>Idempotent: it checks whether the box exists before creating it, running it twice gives the same result. If my PC catches fire tomorrow, I recreate both environments in full with one <code>ansible-playbook site.yml</code> in each repo. The knowledge lives in the recipe, versioned, auditable. Zero commands lost in shell history.</p>
<h3>Scaling the same principle to production<span class="hx:absolute hx:-mt-20" id="scaling-the-same-principle-to-production"></span>
    <a href="#scaling-the-same-principle-to-production" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>At a company, swap distrobox for Kubernetes and the principle is identical. The agent writes the manifest, tests it on the staging cluster, you promote it to production manually:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apps/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Deployment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">minha-api</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">replicas</span><span class="p">:</span><span class="w"> </span><span class="m">3</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">selector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">minha-api</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">template</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">minha-api</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">containers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">minha-api</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">registry.exemplo.com/minha-api:v42</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">readinessProbe</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">httpGet</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l">/healthz</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="m">8080</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">resources</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">limits</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">memory</span><span class="p">:</span><span class="w"> </span><span class="l">512Mi</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>The professional flow: the agent produces and adjusts the manifest (or the Helm chart, or the Terraform module), applies it to staging (<code>kubectl apply -n staging</code>), runs the tests, watches for side effects, bugs, unintended behavior, and iterates until you&rsquo;re satisfied. Then YOU, a human, promote it to production (via a reviewed PR in a GitOps flow, or a manual and deliberate <code>kubectl apply</code>), monitoring every step. The agent did all the heavy lifting: the artifacts, the procedures, the checklists. You can even ask it to generate the audit documentation at the end. But the finger that presses the production button has a name on a payroll.</p>
<h3>Even the &ldquo;simple&rdquo; maintenance SQL<span class="hx:absolute hx:-mt-20" id="even-the-simple-maintenance-sql"></span>
    <a href="#even-the-simple-maintenance-sql" class="subheading-anchor" aria-label="Permalink for this section"></a></h3><p>A case that looks harmless and bothers me a lot: maintenance SQL commands in production. Plenty of people have always run those by hand, straight into the production client, and are now asking the agent to write AND execute them. That is unacceptable, with or without AI. Your system should have a <strong>migrations</strong> workflow: the change becomes versioned code, runs in staging first, gets validated, and only then executes in production inside the normal deploy process.</p>
<p>And &ldquo;production&rdquo;, by definition, means two things many companies pretend to have. First: real backups, tested, with rehearsed restores.</p>
<blockquote>
  <p>Never run anything in production that you can&rsquo;t recover from.</p>

</blockquote>
<p>Second: monitoring. If you have no visibility into the state of the system, you don&rsquo;t have production, you have a server plugged into an outlet and a prayer.</p>
<h2>Monitoring: even on my humble PC<span class="hx:absolute hx:-mt-20" id="monitoring-even-on-my-humble-pc"></span>
    <a href="#monitoring-even-on-my-humble-pc" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>And monitoring is so much a part of the discipline that I apply it even to my personal machine. I recently developed a system health widget for my <a href="https://github.com/akitaonrails/clock-tui"target="_blank" rel="noopener">clock-tui</a> (my maintained fork of the original clock-tui, with command widgets in clock mode). It sits open in a corner showing this:</p>
<p><img src="https://new-uploads-akitaonrails.s3.us-east-2.amazonaws.com/2026/07/11/agentes-apagando/system-health-widget.webp" alt="clock-tui’s system health widget: restic backups ok 19h ago, 23 timeshift snapshots, dev-cache cleanup ok, btrfs scrub and trim up to date, zero IO errors, load, memory and storage usage per filesystem."  loading="lazy" /></p>
<p>One verdict line (&ldquo;all systems healthy&rdquo;) and the state of everything this post described: the restic backup ran 19 hours ago and the next one is at 03:03; Timeshift keeps 23 snapshots; the development cache cleanup ran 32 hours ago; the BTRFS scrub is up to date on each filesystem, with a recent trim, healthy allocation and zero I/O errors; plus zombies, load, memory and each disk&rsquo;s usage. The widget (<code>tclock-system-health</code>) ships with the repository and the AUR package, and detects most of this on its own.</p>
<p>Behind it are the automated maintenance jobs, all systemd timers: the daily restic at 3am; <code>dev-cache-clean</code> (on the 1st and the 15th) sweeping orphaned Rust <code>target/</code> dirs and the yay cache, which together give back dozens of gigs; the monthly per-filesystem <code>btrfs-scrub</code> validating checksums; the weekly <code>fstrim</code>. None of it requires me to remember anything. When one of them is late or fails, the widget changes color right in my face.</p>
<p>This is the home-grade level, proportional to a personal PC. At a company you go full-blown: Prometheus collecting metrics, Grafana drawing the dashboards, Alertmanager waking up the on-call person at 3am. The scale changes, the principle is the same: the state of the system visible at all times, and someone (or something) getting notified when it goes off the rails.</p>
<h2>Conclusion: discipline<span class="hx:absolute hx:-mt-20" id="conclusion-discipline"></span>
    <a href="#conclusion-discipline" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Go back to the two tweets at the beginning. In both cases, a single wrong command caused real loss, and the public discussion became &ldquo;who do I trust more&rdquo;. The right question is a different one: <strong>why does a single wrong command, from any origin, have the power to cause unrecoverable loss on your machine?</strong></p>
<p>Being a professional is being disciplined, and discipline starts at home. My personal PC operates with the same rigor I would demand from a corporate environment: a filesystem with lightweight scheduled snapshots, recoverable boot via GRUB, daily external backups with a retention policy, a sandbox for suspicious sessions, isolated environments rebuildable from versioned recipes, automated maintenance and a monitor that warns me when any piece falls behind. Monthly maintenance cost of all this: close to zero. It was set up once (in good part by the agents themselves) and runs on its own.</p>
<p>With these layers, the question in the title almost loses its meaning. The agent deleted a directory? Snapshot from an hour ago, two minutes of recovery. Destroyed the system? Boot into a snapshot via GRUB, restore, ten minutes. Fried the disk along with it? restic on the NAS, yesterday&rsquo;s backup. In five months of YOLO mode I never needed any of these nets for an AI accident. But I sleep well precisely because they&rsquo;re there.</p>
<p>An LLM running loose on your system is just the most recent stress test of your discipline. If an out-of-control agent can cause permanent loss to your data, the vulnerability was always there, waiting for a mistake of yours, a bad disk or a ransomware. The agent was just the messenger that arrived first.</p>
]]></content:encoded><category>ai-jail</category><category>coding-agents</category><category>security</category><category>storage-and-backup</category></item><item><title>LLM Benchmark: Sonnet 5 Fails, Gemini Flash Surprises, Sakana Fugu Almost Reaches Tier A</title><link>https://akitaonrails.github.io/en/2026/07/01/llm-benchmark-sonnet-5-fails-gemini-flash-surprises-sakana-fugu-almost-tier-a/</link><guid isPermaLink="true">https://akitaonrails.github.io/en/2026/07/01/llm-benchmark-sonnet-5-fails-gemini-flash-surprises-sakana-fugu-almost-tier-a/</guid><pubDate>Wed, 01 Jul 2026 15:00:00 -0300</pubDate><description>&lt;p&gt;Another round of my coding benchmark. And this time we got the kind of result that annoys marketing.&lt;/p&gt;
&lt;p&gt;The three names are &lt;strong&gt;Sonnet 5&lt;/strong&gt;, &lt;strong&gt;Gemini 3.5 Flash&lt;/strong&gt;, and &lt;strong&gt;Sakana Fugu Ultra&lt;/strong&gt;. Sonnet 5 is the one that draws attention. New model, strong brand, high expectations. Except expectations do not compile. It ran, passed Docker, came up under Compose, and still finished at &lt;strong&gt;58/100, Tier C&lt;/strong&gt;. The first real chat request would crash before calling the model.&lt;/p&gt;</description><content:encoded><![CDATA[<p>Another round of my coding benchmark. And this time we got the kind of result that annoys marketing.</p>
<p>The three names are <strong>Sonnet 5</strong>, <strong>Gemini 3.5 Flash</strong>, and <strong>Sakana Fugu Ultra</strong>. Sonnet 5 is the one that draws attention. New model, strong brand, high expectations. Except expectations do not compile. It ran, passed Docker, came up under Compose, and still finished at <strong>58/100, Tier C</strong>. The first real chat request would crash before calling the model.</p>
<p>The good surprise came from the other side: <strong>Gemini 3.5 Flash</strong> scored <strong>93/100, Tier A, #6</strong>. A Flash model. Above Kimi K2.6, GLM 5.2, and Gemini 3.1 Pro.</p>
<p>And then there was <strong>Sakana Fugu Ultra</strong>, right on the edge: <strong>79/100, Tier B</strong>, knocking on Tier A&rsquo;s door. Qwen3.7 Max and Step 3.7 Flash also entered, but they are supporting cast. Nex matters, but I already unpacked that case in the post about the <a href="/en/2026/06/15/the-rio-3-5-llm-controversy-plagiarism/">Rio 3.5 controversy</a>. Here it stays mostly as a ranking line and reference.</p>
<p>Since the <a href="/en/2026/06/14/llm-benchmark-kimi-v2-7-code-glm-5-2-minimax-m3-local/">last benchmark</a>, my practical recommendation has not changed: serious programming, long sessions, real projects, today still means <strong>Opus 4.8</strong> or <strong>GPT 5.5</strong>, using Claude Code, Codex, or OpenCode. What changed is the middle of the table. And the middle is where you can see who is learning and who merely changed the version number.</p>
<h2>For anyone landing here cold<span class="hx:absolute hx:-mt-20" id="for-anyone-landing-here-cold"></span>
    <a href="#for-anyone-landing-here-cold" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>The test is simple to explain and annoying to run. I give every model the same prompt and ask it to build, by itself, a ChatGPT-style chat app in Rails 8 + RubyLLM + Hotwire + Docker, with tests and CI. Then I read the generated code by hand and score it from 0 to 100, in A/B/C/D tiers.</p>
<p>This is not multiple choice. Not a puzzle. Not &ldquo;complete this function.&rdquo; It is an agent trying to deliver a whole small Rails project. It either delivers, or it trips.</p>
<p>The series so far:</p>
<ol>
<li><a href="/en/2026/04/24/llm-benchmarks-part-3-deepseek-kimi-mimo/">Canonical May benchmark (Part 3)</a>, with the complete methodology.</li>
<li><a href="/en/2026/05/04/llm-benchmarks-deepseek-unlocked-deepclaude/">DeepSeek unlocked with DeepClaude</a>.</li>
<li><a href="/en/2026/06/01/llm-benchmarks-grok-4-3-minimax-m3-opus-4-8/">Grok 4.3, MiniMax M3, Opus 4.8 update</a>.</li>
<li><a href="/en/2026/06/11/llm-benchmark-fable-5-and-the-anthropic-saga/">Fable 5 and Anthropic&rsquo;s saga</a>.</li>
<li><a href="/en/2026/06/14/llm-benchmark-kimi-v2-7-code-glm-5-2-minimax-m3-local/">Kimi v2.7 code, GLM 5.2, MiniMax M3 local</a>.</li>
</ol>
<p>The trap is still the same: the &ldquo;RubyLLM OK&rdquo; column is not decoration. If the model invents an API that does not exist, the app dies in its main feature. Sometimes everything around it looks nice: Tailwind, Turbo, Docker, README, green tests. Then you click &ldquo;Send&rdquo; and get a <code>NoMethodError</code>.</p>
<h2>The closed-model soap opera<span class="hx:absolute hx:-mt-20" id="the-closed-model-soap-opera"></span>
    <a href="#the-closed-model-soap-opera" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Anthropic had placed US government controls on <strong>Claude Fable 5</strong> and <strong>Claude Mythos 5</strong> on June 12. Reason: they could not verify nationality in real time across all global channels. On June 30, they suspended the Fable 5 controls, and Anthropic announced its gradual return to Claude Platform, Claude.ai, Claude Code, and Claude Cowork. Mythos 5 remains more restricted, only for approved US organizations through Project Glasswing.</p>
<p>Sources: <a href="https://www.anthropic.com/news/redeploying-fable-5"target="_blank" rel="noopener">Anthropic&rsquo;s post about Fable 5 returning</a>, the <a href="https://www.anthropic.com/news/claude-fable-5-mythos-5"target="_blank" rel="noopener">original Fable 5 and Mythos 5 post</a>, and <a href="https://www.theverge.com/ai-artificial-intelligence/958964/anthropic-claude-fable-5-is-back"target="_blank" rel="noopener">The Verge on the suspension of the controls</a>.</p>
<p>On the OpenAI side, <strong>GPT-5.6</strong> has appeared officially, but it is still in limited preview. There is an OpenAI page and a help center article. It is not available enough for me to benchmark it the way I can benchmark GPT 5.5 today. So it gets a note, no number yet: <a href="https://openai.com/index/previewing-gpt-5-6-sol/"target="_blank" rel="noopener">GPT-5.6 Sol preview</a> and <a href="https://help.openai.com/en/articles/20001325-a-preview-of-gpt-56-sol-terra-and-luna"target="_blank" rel="noopener">GPT-5.6 Sol, Terra, and Luna help center article</a>.</p>
<h2>Updated ranking<span class="hx:absolute hx:-mt-20" id="updated-ranking"></span>
    <a href="#updated-ranking" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>New models in this round are in bold. Nex-N2-Pro and the Qwen 3.5 397B base are still highlighted because they entered the table after the last benchmark, but the longer analysis already appeared in the <a href="/en/2026/06/15/the-rio-3-5-llm-controversy-plagiarism/">Rio 3.5 post</a>.</p>
<table>
  <thead>
      <tr>
          <th style="text-align: right">Rank</th>
          <th>Model</th>
          <th style="text-align: right">Score</th>
          <th style="text-align: center">Tier</th>
          <th style="text-align: center">RubyLLM OK</th>
          <th>Runtime</th>
          <th>Cost</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: right">1</td>
          <td>Claude Opus 4.7</td>
          <td style="text-align: right">97</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>18m</td>
          <td>~$1.10</td>
      </tr>
      <tr>
          <td style="text-align: right">1</td>
          <td>GPT 5.4 xHigh (Codex)</td>
          <td style="text-align: right">97</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>22m</td>
          <td>~$16</td>
      </tr>
      <tr>
          <td style="text-align: right">3</td>
          <td>GPT 5.5 xHigh (Codex)</td>
          <td style="text-align: right">96</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>18m</td>
          <td>~$10</td>
      </tr>
      <tr>
          <td style="text-align: right">4</td>
          <td>Claude Opus 4.8</td>
          <td style="text-align: right">95</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>17m</td>
          <td>~$1.10</td>
      </tr>
      <tr>
          <td style="text-align: right">5</td>
          <td>Claude Fable 5</td>
          <td style="text-align: right">94</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>24m</td>
          <td>~$11 (est.)</td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>6</strong></td>
          <td><strong>Gemini 3.5 Flash</strong></td>
          <td style="text-align: right"><strong>93</strong></td>
          <td style="text-align: center"><strong>A</strong></td>
          <td style="text-align: center">✅</td>
          <td><strong>18m</strong></td>
          <td><strong>~$3.50</strong></td>
      </tr>
      <tr>
          <td style="text-align: right">7</td>
          <td>Kimi K2.6</td>
          <td style="text-align: right">87</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>20m</td>
          <td>~$0.30</td>
      </tr>
      <tr>
          <td style="text-align: right">7</td>
          <td>GLM 5.2 (Z.ai)</td>
          <td style="text-align: right">87</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>43m</td>
          <td>subscription</td>
      </tr>
      <tr>
          <td style="text-align: right">9</td>
          <td>Kimi K2.7 Code</td>
          <td style="text-align: right">86</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>22m</td>
          <td>~$0.30</td>
      </tr>
      <tr>
          <td style="text-align: right">10</td>
          <td>Claude Opus 4.6</td>
          <td style="text-align: right">83</td>
          <td style="text-align: center">A</td>
          <td style="text-align: center">✅</td>
          <td>16m</td>
          <td>~$1.10</td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>10</strong></td>
          <td><strong>Nex-N2-Pro</strong></td>
          <td style="text-align: right"><strong>83</strong></td>
          <td style="text-align: center"><strong>A</strong></td>
          <td style="text-align: center">✅</td>
          <td><strong>25m</strong></td>
          <td><strong>free</strong></td>
      </tr>
      <tr>
          <td style="text-align: right">12</td>
          <td>Gemini 3.1 Pro</td>
          <td style="text-align: right">79</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>14m</td>
          <td>~$0.40</td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>12</strong></td>
          <td><strong>Sakana Fugu Ultra</strong></td>
          <td style="text-align: right"><strong>79</strong></td>
          <td style="text-align: center"><strong>B</strong></td>
          <td style="text-align: center">✅</td>
          <td><strong>22m</strong></td>
          <td><strong>subscription</strong></td>
      </tr>
      <tr>
          <td style="text-align: right">14</td>
          <td>Claude Sonnet 4.6</td>
          <td style="text-align: right">78</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>16m</td>
          <td>~$0.63</td>
      </tr>
      <tr>
          <td style="text-align: right">14</td>
          <td>DeepSeek V4 Flash</td>
          <td style="text-align: right">78</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>3m</td>
          <td>~$0.01</td>
      </tr>
      <tr>
          <td style="text-align: right">14</td>
          <td>MiniMax M3</td>
          <td style="text-align: right">78</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>53m (phase 2 DNF)</td>
          <td>~$0.10</td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>14</strong></td>
          <td><strong>Qwen3.7 Max</strong></td>
          <td style="text-align: right"><strong>78</strong></td>
          <td style="text-align: center"><strong>B</strong></td>
          <td style="text-align: center">✅</td>
          <td><strong>19m</strong></td>
          <td><strong>~$1.40</strong></td>
      </tr>
      <tr>
          <td style="text-align: right">18</td>
          <td>Grok 4.3</td>
          <td style="text-align: right">72</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>15m</td>
          <td>~$1.74</td>
      </tr>
      <tr>
          <td style="text-align: right">19</td>
          <td>Qwen 3.6 Plus</td>
          <td style="text-align: right">71</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>17m</td>
          <td>~$0.15</td>
      </tr>
      <tr>
          <td style="text-align: right">20</td>
          <td>DeepSeek V4 Pro</td>
          <td style="text-align: right">69</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>22m (DNF)</td>
          <td>~$0.50</td>
      </tr>
      <tr>
          <td style="text-align: right">20</td>
          <td>Kimi K2.5</td>
          <td style="text-align: right">69</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>29m</td>
          <td>~$0.10</td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>20</strong></td>
          <td><strong>Step 3.7 Flash</strong></td>
          <td style="text-align: right"><strong>69</strong></td>
          <td style="text-align: center"><strong>B</strong></td>
          <td style="text-align: center">✅</td>
          <td><strong>27m</strong></td>
          <td><strong>~$0.30</strong></td>
      </tr>
      <tr>
          <td style="text-align: right">23</td>
          <td>Xiaomi MiMo V2.5 Pro</td>
          <td style="text-align: right">67</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>11m</td>
          <td>~$0.14</td>
      </tr>
      <tr>
          <td style="text-align: right">24</td>
          <td>GLM 5</td>
          <td style="text-align: right">64</td>
          <td style="text-align: center">B</td>
          <td style="text-align: center">✅</td>
          <td>17m</td>
          <td>~$0.11</td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>25</strong></td>
          <td><strong>Claude Sonnet 5</strong></td>
          <td style="text-align: right"><strong>58</strong></td>
          <td style="text-align: center"><strong>C</strong></td>
          <td style="text-align: center">❌</td>
          <td><strong>27m</strong></td>
          <td><strong>~$0.80</strong></td>
      </tr>
      <tr>
          <td style="text-align: right">26</td>
          <td>Step 3.5 Flash</td>
          <td style="text-align: right">56</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">⚠️ bypass</td>
          <td>38m</td>
          <td>~$0.02</td>
      </tr>
      <tr>
          <td style="text-align: right">27</td>
          <td>Qwen 3.5 35B (local)</td>
          <td style="text-align: right">55</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">✅</td>
          <td>28m</td>
          <td>free</td>
      </tr>
      <tr>
          <td style="text-align: right">28</td>
          <td>GLM 4.7 Flash bf16 (local)</td>
          <td style="text-align: right">52</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">✅</td>
          <td>failed</td>
          <td>free</td>
      </tr>
      <tr>
          <td style="text-align: right">29</td>
          <td>GLM 5.1 (Z.ai)</td>
          <td style="text-align: right">46</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td>22m</td>
          <td>subscription</td>
      </tr>
      <tr>
          <td style="text-align: right">30</td>
          <td>DeepSeek V3.2</td>
          <td style="text-align: right">43</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td>60m</td>
          <td>~$0.07</td>
      </tr>
      <tr>
          <td style="text-align: right"><strong>31</strong></td>
          <td><strong>Qwen 3.5 397B A17B (base)</strong></td>
          <td style="text-align: right"><strong>42</strong></td>
          <td style="text-align: center"><strong>C</strong></td>
          <td style="text-align: center">❌</td>
          <td><strong>15m</strong></td>
          <td><strong>~$0.58</strong></td>
      </tr>
      <tr>
          <td style="text-align: right">32</td>
          <td>MiniMax M2.7</td>
          <td style="text-align: right">41</td>
          <td style="text-align: center">C</td>
          <td style="text-align: center">❌</td>
          <td>14m</td>
          <td>~$0.30</td>
      </tr>
      <tr>
          <td style="text-align: right">33</td>
          <td>Qwen 3.5 122B (local)</td>
          <td style="text-align: right">37</td>
          <td style="text-align: center">D</td>
          <td style="text-align: center">❌</td>
          <td>43m</td>
          <td>free</td>
      </tr>
      <tr>
          <td style="text-align: right">34</td>
          <td>Qwen 3 Coder Next (local)</td>
          <td style="text-align: right">32</td>
          <td style="text-align: center">D</td>
          <td style="text-align: center">❌</td>
          <td>17m</td>
          <td>free</td>
      </tr>
      <tr>
          <td style="text-align: right">35</td>
          <td>Grok 4.20</td>
          <td style="text-align: right">25</td>
          <td style="text-align: center">D</td>
          <td style="text-align: center">❌</td>
          <td>8m</td>
          <td>~$0.60</td>
      </tr>
      <tr>
          <td style="text-align: right">36</td>
          <td>GPT OSS 20B (local)</td>
          <td style="text-align: right">11</td>
          <td style="text-align: center">D</td>
          <td style="text-align: center">❌</td>
          <td>failed</td>
          <td>free</td>
      </tr>
  </tbody>
</table>
<h2>Sonnet 5: passed Docker, failed at the heart<span class="hx:absolute hx:-mt-20" id="sonnet-5-passed-docker-failed-at-the-heart"></span>
    <a href="#sonnet-5-passed-docker-failed-at-the-heart" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Sonnet 5 scored <strong>58/100, Tier C, #25</strong>. Here is the part that fools people: phase 2 passed. Local boot. Docker build. Docker Compose. The project had Rails 8, Turbo, Stimulus, Tailwind, README, CI, SimpleCov, Brakeman, RuboCop, and bundler-audit. The shell looked good.</p>
<p>The problem was exactly where it could not be: the LLM path.</p>
<p>The generated service does this:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="no">RubyLLM</span><span class="o">.</span><span class="n">chat</span><span class="p">(</span><span class="ss">model</span><span class="p">:</span> <span class="no">MODEL</span><span class="p">,</span> <span class="ss">provider</span><span class="p">:</span> <span class="no">PROVIDER</span><span class="p">)</span><span class="o">.</span><span class="n">tap</span> <span class="k">do</span> <span class="o">|</span><span class="n">chat</span><span class="o">|</span>
</span></span><span class="line"><span class="cl">  <span class="n">chat</span><span class="o">.</span><span class="n">messages</span> <span class="o">=</span> <span class="n">history</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>But RubyLLM 1.16 has <code>messages</code>, <code>add_message</code>, <code>ask</code>, and <code>with_instructions</code>. It does not have <code>messages=</code>. The first real chat request raises <code>NoMethodError</code> before reaching the model. The test misses it because the project&rsquo;s own <code>FakeChat</code> defines <code>attr_accessor :messages</code>, exactly the writer that does not exist in production.</p>
<p>This is the kind of bug that keeps me reading benchmark outputs by hand. Green build does not prove correct integration. Green test can be worse than useless when the fake teaches the test a lie.</p>
<p>There is more: the generated app still defaulted to <code>anthropic/claude-sonnet-4.6</code>, not Sonnet 5, and left the system prompt without <code>with_instructions</code>. The shell was complete. The main feature was broken.</p>
<p>Cruel summary: <strong>Sonnet 5 passed Docker and failed at the heart</strong>. If you pay Anthropic for programming today, I still recommend Opus 4.8. Not Sonnet 5.</p>
<h2>Gemini 3.5 Flash: the good surprise<span class="hx:absolute hx:-mt-20" id="gemini-35-flash-the-good-surprise"></span>
    <a href="#gemini-35-flash-the-good-surprise" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>Gemini 3.5 Flash was the slap in the face of the round: <strong>93/100, Tier A, #6</strong>. Best non-Anthropic/non-OpenAI result in the benchmark so far. Fourteen points above Gemini 3.1 Pro.</p>
<p>The RubyLLM integration was exemplary:</p>
<div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">

<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="n">chat</span> <span class="o">=</span> <span class="no">RubyLLM</span><span class="o">.</span><span class="n">chat</span><span class="p">(</span><span class="ss">model</span><span class="p">:</span> <span class="vi">@model</span><span class="p">,</span> <span class="ss">provider</span><span class="p">:</span> <span class="ss">:openrouter</span><span class="p">,</span> <span class="ss">assume_model_exists</span><span class="p">:</span> <span class="kp">true</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">chat</span><span class="o">.</span><span class="n">with_instructions</span><span class="p">(</span><span class="no">SYSTEM_INSTRUCTION</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="vi">@conversation</span><span class="o">.</span><span class="n">messages</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">msg</span><span class="o">|</span> <span class="n">chat</span><span class="o">.</span><span class="n">add_message</span><span class="p">(</span><span class="ss">role</span><span class="p">:</span> <span class="n">msg</span><span class="o">.</span><span class="n">role</span><span class="o">.</span><span class="n">to_sym</span><span class="p">,</span> <span class="ss">content</span><span class="p">:</span> <span class="n">msg</span><span class="o">.</span><span class="n">content</span><span class="p">)</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">chat</span><span class="o">.</span><span class="n">complete</span>
</span></span><span class="line"><span class="cl"><span class="vi">@conversation</span><span class="o">.</span><span class="n">add_message</span><span class="p">(</span><span class="ss">role</span><span class="p">:</span> <span class="ss">:assistant</span><span class="p">,</span> <span class="ss">content</span><span class="p">:</span> <span class="n">response</span><span class="o">.</span><span class="n">content</span><span class="p">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
  <button
    class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
    title="Copy code"
  >
    <div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"></div>
<div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"></div>
  </button>
</div>
</div>
<p>It used <code>with_instructions</code>, history replay with <code>add_message</code>, <code>complete</code>, and <code>response.content</code>. All real. The test suite was the best in this cohort: <code>FakeChat</code> with a compatible signature, stub at the correct point (<code>RubyLLM.chat</code>), parameter assertions, history replay, and an error test. Sounds basic. It is not. The table proves it is not.</p>
<p>I also liked the persistence. It writes files under <code>tmp/chats/&lt;id&gt;.json</code>, with a 50-message cap and the system message preserved. It survives restart on the same host and is better than an in-memory singleton. It lacks file locking, <code>tmp/</code> is ephemeral in containers, and concurrent writes to the same conversation can race. It also lacks a nice API-key preflight. All fixable.</p>
<p>The cost bothers me. Even as Flash, the run came out around <strong>US$3.50</strong>, more expensive than Opus 4.8 in this benchmark because of high token churn. So I cannot sell it as &ldquo;cheap.&rdquo; But as a quality signal it is strong. A Flash model at #6 changes my intuition about Gemini.</p>
<h2>Sakana Fugu Ultra: almost Tier A, missing memory<span class="hx:absolute hx:-mt-20" id="sakana-fugu-ultra-almost-tier-a-missing-memory"></span>
    <a href="#sakana-fugu-ultra-almost-tier-a-missing-memory" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p><strong>Sakana Fugu Ultra</strong> entered with <strong>79/100, Tier B, tied at #12</strong>. For a new provider, this was a clean debut. The harness worked. The app came up. Docker/Compose passed. RubyLLM was real (<code>chat</code>, <code>with_instructions</code>, <code>ask</code>, <code>response.content</code>). The tests used a correct <code>FakeChat</code>. Turbo/Stimulus were good.</p>
<p>The problem is small to explain and large in consequence: the model only sees the latest message. The history is saved and displayed, but it is not replayed into RubyLLM. The UI looks like a multi-turn chat. The LLM works as if every message were the first.</p>
<p>It missed exactly the part that makes chat chat.</p>
<p>Even so, this is the kind of result I like to see. It is not a disaster. It is not an invented API. It is an almost-correct app with a specific failure. Replacing the process-local repository with something decent and replaying history with <code>add_message</code> would change the evaluation a lot.</p>
<h2>Qwen3.7, Step 3.7, and the Qwen 3.6 footnote<span class="hx:absolute hx:-mt-20" id="qwen37-step-37-and-the-qwen-36-footnote"></span>
    <a href="#qwen37-step-37-and-the-qwen-36-footnote" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p><strong>Qwen3.7 Max</strong> scored <strong>78/100, Tier B, tied at #14</strong>. Correct RubyLLM API, including streaming and <code>reset_messages!</code>. Phase 2 passed. But it ignored Turbo Streams and implemented raw SSE with <code>ActionController::Live</code>. In a real app, maybe fine. In this benchmark, the prompt asked for Hotwire/Turbo Streams. It also used <code>anthropic/claude-sonnet-4</code> instead of the newest Sonnet and stored conversations in an unbounded class-level hash. Restart the process? Lose everything. Run long enough? Leak memory.</p>
<p><strong>Step 3.7 Flash</strong> scored <strong>69/100, Tier B, tied at #20</strong>. It fixed the big Step 3.5 mistake: now it uses the real <code>ruby_llm</code> gem, not a <code>ruby-openai</code> bypass. Good. But it creates a new <code>RubyLLM.chat</code> per request and sends only the current message. The history lives in a <code>@@all</code> class var, but never reaches the model. It escaped the wrong bypass and forgot to give the LLM memory.</p>
<p>And yes, Qwen 3.6 appeared in the recent commit history. Two local <strong>Qwen 3.6 35B A3B</strong> runs entered through PR #9 (<code>cccc118</code> and <code>f06ddd0</code>), using a local <code>ik_llama.cpp</code> profile, but the merge was reverted in <code>d5f9195</code>. That is why they are not in the main table for this round.</p>
<p>The useful Qwen 3.6 local data remains in the separate RTX 5090 report: it was the first local model in that profile to get <code>RubyLLM.chat</code> + <code>chat.ask</code> right, but it still returned the whole object instead of <code>response.content</code> and had no multi-turn. Close to working. Still outside the main cloud/AMD ranking.</p>
<h2>Nex and Qwen base: already covered in the Rio 3.5 case<span class="hx:absolute hx:-mt-20" id="nex-and-qwen-base-already-covered-in-the-rio-35-case"></span>
    <a href="#nex-and-qwen-base-already-covered-in-the-rio-35-case" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p><strong>Nex-N2-Pro</strong> scored <strong>83/100, Tier A, #10</strong>, using OpenRouter&rsquo;s free endpoint. The raw <strong>Qwen 3.5 397B A17B</strong> base scored <strong>42/100, Tier C, #31</strong>. That 41-point gap matters. Repeating everything here would be padding.</p>
<p>I already used those numbers in the post about the <a href="/en/2026/06/15/the-rio-3-5-llm-controversy-plagiarism/">Rio 3.5 LLM controversy</a>, because the public accusation was precisely that Rio&rsquo;s checkpoint looked like a merge of Nex-N2-Pro and Qwen3.5-397B-A17B. That post explains what Nex is, why the fine-tune matters, and why a Rio model inheriting Nex&rsquo;s gains should not be sold as an obvious advance over pure Nex without a reproducible benchmark.</p>
<p>The short technical version: the Qwen base invented RubyLLM (<code>chat.system</code>, <code>chat.user</code>, <code>response.text</code>) and the tests mocked that fake API. Nex used the real API, booted locally, passed Docker/Compose, and delivered Turbo Streams with error handling. It still has shortcuts, like flattening history into text instead of using <code>add_message</code> and <code>with_instructions</code>, but it is a legitimate Tier A result. It is just not the focus of this post.</p>
<h2>My actual workflow today<span class="hx:absolute hx:-mt-20" id="my-actual-workflow-today"></span>
    <a href="#my-actual-workflow-today" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>In practice, I have been using a lot of <strong>OpenCode + <a href="https://github.com/alvinunreal/oh-my-opencode-slim"target="_blank" rel="noopener">oh-my-opencode-slim</a> + GPT 5.5</strong> to maintain my open source projects. It is a slim, cleaner, cheaper-token fork of oh-my-opencode. Exactly the kind of adjustment that fits daily use. I already explained the rest of my <a href="/en/2026/05/24/akita-ai-toolkit-ai-jail-ai-memory-ai-usagebar/">AI toolkit with ai-jail, ai-memory, and ai-usagebar</a> in a separate post.</p>
<p>This is annoying to explain to people who only want to know &ldquo;which model is best.&rdquo; Model alone does not carry the work. Harness matters. System prompt matters. Project memory matters. Test quality matters. The same model, in a bad harness, becomes a random patch generator.</p>
<p>I have been using this on small, real things, like Geary extensions: <a href="https://github.com/akitaonrails/geary-email-autocomplete"target="_blank" rel="noopener">geary-email-autocomplete</a> and <a href="https://github.com/akitaonrails/geary-hide-sidebar-module"target="_blank" rel="noopener">geary-hide-sidebar-module</a>. None of this is a revolution. It is maintenance, bugfixes, refactors, tests, documentation. Normal work. Exactly where a coding agent needs to be reliable for hours, not for a 90-second demo.</p>
<p>That is why I keep repeating: model benchmarks are useful, workflow benchmarks are even more useful. Sonnet 5 with a hallucinated API does not help me. Gemini Flash surprising me with correct RubyLLM does. Sakana and Step getting the gem right but forgetting multi-turn show exactly where these models still break in a real product.</p>
<h2>Conclusion<span class="hx:absolute hx:-mt-20" id="conclusion"></span>
    <a href="#conclusion" class="subheading-anchor" aria-label="Permalink for this section"></a></h2><p>This round left a simple message: a strong name does not save a broken integration. Sonnet 5 entered with the aura of a new model and left in Tier C because it called an API that does not exist.</p>
<p>Gemini 3.5 Flash deserves attention. Not because it is cheap; in this run it was not even that cheap. It deserves attention because it delivered a Rails/RubyLLM app far more correctly than I expected from a Flash model.</p>
<p>On the open source / alternative provider side, the story is more mixed. Sakana Fugu Ultra almost reached Tier A. Qwen3.7 Max got the API right and missed the product. Step 3.7 Flash fixed the 3.5 bypass and forgot to give the chat memory. There is progress. There are edges.</p>
<p>My practical recommendation stays the same: <strong>Opus 4.8 or GPT 5.5</strong> for serious programming today. Use Tier B for small, cheap, reviewed tasks. Use open source/local to study and experiment. And do not trust a green test if the fake does not imitate the real library.</p>
<p>The benchmark is open: <a href="https://github.com/akitaonrails/llm-coding-benchmark"target="_blank" rel="noopener">github.com/akitaonrails/llm-coding-benchmark</a>. Want to see another model there? Fork it, add it to <code>config/models.json</code>, run it, and send the PR.</p>
]]></content:encoded><category>llm-benchmarks</category><category>llms</category><category>coding-agents</category></item></channel></rss>