<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: chpomob</title>
    <description>The latest articles on DEV Community by chpomob (@chpomob).</description>
    <link>https://dev.to/chpomob</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4061247%2F54622b31-6793-4119-8177-0a86d3d57157.png</url>
      <title>DEV Community: chpomob</title>
      <link>https://dev.to/chpomob</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chpomob"/>
    <language>en</language>
    <item>
      <title>I Benchmarked Two Local LLMs on Real Dev Work — Qwopus 27B vs Muse Glimmer 30B</title>
      <dc:creator>chpomob</dc:creator>
      <pubDate>Tue, 11 Aug 2026 15:22:01 +0000</pubDate>
      <link>https://dev.to/chpomob/i-benchmarked-two-local-llms-on-real-dev-work-qwopus-27b-vs-muse-glimmer-30b-36ni</link>
      <guid>https://dev.to/chpomob/i-benchmarked-two-local-llms-on-real-dev-work-qwopus-27b-vs-muse-glimmer-30b-36ni</guid>
      <description>&lt;h1&gt;
  
  
  I Benchmarked Two Local LLMs on Real Dev Work — Qwopus 27B vs Muse Glimmer 30B
&lt;/h1&gt;

&lt;p&gt;Two open-weight models, one 20 GB GPU, two real development tasks, and a third model as the referee. Here is what actually happened when I made Qwopus 3.6 27B and Meta's Muse Glimmer 30B implement a bug fix and then a full feature in my own project.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;Both models ran fully local on an AMD Radeon RX 7900 XT (20 GB VRAM) via a llama.cpp multi-model router (one OpenAI-compatible endpoint, GGUF models, &lt;code&gt;load-mode=dio&lt;/code&gt; — more on why below). Each model was driven by the pi CLI in non-interactive mode with &lt;code&gt;--thinking high&lt;/code&gt;. A third model — Codex, through a disciplined stdin wrapper — reviewed both outputs and gave the verdict.&lt;/p&gt;

&lt;p&gt;The fairness method was simple but strict:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;One task&lt;/strong&gt;, described in a markdown spec, copied byte-identical into two isolated git clones of my project.&lt;/li&gt;
&lt;li&gt;Each model worked in &lt;strong&gt;its own clone, its own branch&lt;/strong&gt;, never seeing the other's work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Objective verification&lt;/strong&gt; by script: existing test suite + new tests + production build.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-review by Codex&lt;/strong&gt;, examining both branches against the same criteria.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The test project: &lt;strong&gt;Jeu de Cochons&lt;/strong&gt; (a "Pass the Pigs" dice game, vanilla JS PWA on Vite + Vitest) — real code, real tests, no toy repo.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Qwopus 3.6 27B&lt;/th&gt;
&lt;th&gt;Muse Glimmer 30B&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Source&lt;/td&gt;
&lt;td&gt;Community fine-tune of Qwen 3.6&lt;/td&gt;
&lt;td&gt;Meta (distilled from Muse Spark)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Size&lt;/td&gt;
&lt;td&gt;27B&lt;/td&gt;
&lt;td&gt;29.6B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quant&lt;/td&gt;
&lt;td&gt;IQ4_XS (~15 GB)&lt;/td&gt;
&lt;td&gt;UD-Q4_K_XL (~14.8 GB)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Round 1 — fixing a regression (short task)
&lt;/h2&gt;

&lt;p&gt;The project had a broken PWA: a commit that added a &lt;code&gt;/jeu-de-cochons/&lt;/code&gt; base path for GitHub Pages had broken &lt;strong&gt;3 service-worker tests&lt;/strong&gt; (manifest, precache, offline navigation fallback). Task: fix the regression &lt;strong&gt;without touching the tests&lt;/strong&gt;, keep the other 84 green.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Qwopus&lt;/th&gt;
&lt;th&gt;Muse&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PWA tests (11)&lt;/td&gt;
&lt;td&gt;11/11 ✅&lt;/td&gt;
&lt;td&gt;11/11 ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full suite (87)&lt;/td&gt;
&lt;td&gt;87/87 ✅&lt;/td&gt;
&lt;td&gt;87/87 ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Files touched&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Diff size&lt;/td&gt;
&lt;td&gt;+4/−4&lt;/td&gt;
&lt;td&gt;+4/−4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wall time&lt;/td&gt;
&lt;td&gt;~8.5 min&lt;/td&gt;
&lt;td&gt;~21 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leftover artifacts&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;one &lt;code&gt;.bak&lt;/code&gt; file&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The remarkable result: both models produced a byte-identical diff.&lt;/strong&gt; Same diagnosis (a lost capture group in the asset-discovery regex that crashed precache), same manifest fix, same minimal solution. Codex called it a perfect tie on code — but rejected both on a latent conflict neither model noticed: reverting the manifest to &lt;code&gt;/&lt;/code&gt; breaks the &lt;code&gt;/jeu-de-cochons/&lt;/code&gt; production deployment (404 icons). The tests hardcode the root path; the deployment lives under a subpath. That contradiction was visible in the task itself, and only the reviewer caught it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson #1:&lt;/strong&gt; on a short, well-bounded task, the two models are interchangeable. Muse thought 2.5× longer and produced the same bytes. You need a richer task to separate them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Round 2 — a full feature (solo mode vs AI)
&lt;/h2&gt;

&lt;p&gt;Add a &lt;strong&gt;single-player mode against an AI opponent&lt;/strong&gt;: menu selection, bot identity in game state, a &lt;em&gt;thoughtful&lt;/em&gt; decision strategy (a pure function choosing to re-roll or bank based on turn score and game situation), automatic bot turns with human controls disabled, unit + integration tests, no regressions, build passing.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Qwopus&lt;/th&gt;
&lt;th&gt;Muse&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Existing tests&lt;/td&gt;
&lt;td&gt;84 ✅&lt;/td&gt;
&lt;td&gt;84 ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New tests written&lt;/td&gt;
&lt;td&gt;18 (12 unit + 6 integration)&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total green&lt;/td&gt;
&lt;td&gt;102/105&lt;/td&gt;
&lt;td&gt;91/94&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wall time&lt;/td&gt;
&lt;td&gt;~32 min&lt;/td&gt;
&lt;td&gt;~26 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leftover artifacts&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;uncommitted &lt;code&gt;dist/&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The AI strategies they designed:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Qwopus — adaptive threshold:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bank at 25 pts by default (justified by ~78% rewarding rolls)&lt;/li&gt;
&lt;li&gt;Bank at 15 pts when leading (play it safe, protect the advantage)&lt;/li&gt;
&lt;li&gt;Bank immediately when the turn wins the game&lt;/li&gt;
&lt;li&gt;Bot identity: explicit &lt;code&gt;isBot&lt;/code&gt; flag on the player&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Muse — fixed threshold:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Constant 15 pts, bank immediately when winning is reachable&lt;/li&gt;
&lt;li&gt;Cleanly handles ROLLING/DECIDING phases and eliminated players&lt;/li&gt;
&lt;li&gt;Bot identity: &lt;strong&gt;inferred from the display name&lt;/strong&gt; ("Ordinateur")&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Codex verdict:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criterion&lt;/th&gt;
&lt;th&gt;Qwopus&lt;/th&gt;
&lt;th&gt;Muse&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;AI strategy&lt;/strong&gt; (primary)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8/10&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Architecture&lt;/td&gt;
&lt;td&gt;8/10&lt;/td&gt;
&lt;td&gt;6/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Robustness&lt;/td&gt;
&lt;td&gt;7/10&lt;/td&gt;
&lt;td&gt;5/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minimalism&lt;/td&gt;
&lt;td&gt;6/10&lt;/td&gt;
&lt;td&gt;7/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tests&lt;/td&gt;
&lt;td&gt;8/10&lt;/td&gt;
&lt;td&gt;4/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verdict&lt;/td&gt;
&lt;td&gt;CONDITIONAL&lt;/td&gt;
&lt;td&gt;CONDITIONAL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Winner: Qwopus.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What actually separated them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The strategy.&lt;/strong&gt; Qwopus exploited the game situation (adaptive threshold, conservative when ahead). Muse used a fixed, barely-justified threshold — even though the spec explicitly asked for a thoughtful strategy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bot modeling.&lt;/strong&gt; Qwopus passed an explicit flag. Muse derived &lt;code&gt;isBot&lt;/code&gt; from the localized name — meaning a human player named "Ordinateur" in multiplayer would silently become an AI. A real bug, confirmed in the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The tests.&lt;/strong&gt; Qwopus covered both sides of the thresholds, victory, leading, trailing, determinism (18 tests). Muse wrote 7 — and one of them, titled "returns null for non-bot player", actually asserts the opposite (&lt;code&gt;not.toBeNull()&lt;/code&gt;), with a comment documenting the contradiction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robustness.&lt;/strong&gt; Muse's deferred callback doesn't re-validate game state, game-over, or the current player before acting (risk of an exception after returning to the menu). Qwopus re-validates everything when the timer fires.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Qwopus's own flaws, to be fair: its solo menu requires filling two human-name fields before swapping the second for the bot (blocking if you only fill one), the "~78%" claim had no math behind it, and its bot timer isn't cleared on menu exit (guarded, but not cleaned up).&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Round 1 (short fix)&lt;/th&gt;
&lt;th&gt;Round 2 (feature)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Winner&lt;/td&gt;
&lt;td&gt;Tie&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Qwopus&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deciding factor&lt;/td&gt;
&lt;td&gt;none (identical diffs)&lt;/td&gt;
&lt;td&gt;strategy + tests + robustness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time&lt;/td&gt;
&lt;td&gt;Qwopus 2.5× faster&lt;/td&gt;
&lt;td&gt;Qwopus slightly slower (but more code)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;On short tasks, these models are interchangeable.&lt;/strong&gt; Raw "reasoning power" doesn't show in a well-bounded bug fix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On a full feature, the difference lands exactly where you'd hope&lt;/strong&gt;: domain understanding (the strategy), modeling rigor (explicit flag vs name-matching), and test discipline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The reviewer model earns its place.&lt;/strong&gt; Codex caught the latent manifest/base-path conflict both models missed in round 1, and the real bugs in round 2 (name-derived bot, inverted test, non-defensive callback).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thinking longer doesn't predict quality.&lt;/strong&gt; Muse spent 2.5× more time in round 1 for identical output, and 20% less time in round 2 for a worse result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The harness matters as much as the models.&lt;/strong&gt; Isolated clones, identical specs, existing tests as a non-negotiable contract, and a third-party reviewer are what make the comparison honest and reproducible.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Practical notes from the trenches
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A speculative-decoding drafter added ~80 s to every model load in my multi-model setup — for a router that swaps models, dropping it was strictly better.&lt;/li&gt;
&lt;li&gt;Large GGUFs froze on load with the ROCm backend (known issue #19482, an amdgpu SVM bug). The fix that worked: &lt;code&gt;--load-mode dio&lt;/code&gt; (direct I/O), which both avoids the bug and loads 3–8× faster.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reproduce it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Project: &lt;a href="https://github.com/chpomob/jeu-de-cochons" rel="noopener noreferrer"&gt;github.com/chpomob/jeu-de-cochons&lt;/a&gt; (Pass the Pigs PWA, Vite + Vitest)&lt;/li&gt;
&lt;li&gt;Serve: llama.cpp in router mode (one OpenAI-compatible endpoint, multiple GGUF models)&lt;/li&gt;
&lt;li&gt;Agents: pi CLI (&lt;code&gt;pi -p --provider llama-router --model &amp;lt;model&amp;gt; --thinking high "&amp;lt;task&amp;gt;"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Reviewer: Codex via a disciplined stdin wrapper&lt;/li&gt;
&lt;li&gt;Method: 2 git clones → identical spec → each implements → verification script (tests + build) → cross-review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Honesty clauses: this is a single run per model per task, not a statistical benchmark. Both tasks came from one small project, and the Codex review is one reviewer's judgment. The numbers are real and were verified against the artifacts, but treat them as a data point — not a ranking of these models in general.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>ai</category>
      <category>opensource</category>
      <category>benchmark</category>
    </item>
    <item>
      <title>A friend dared me to build Pass the Pigs during the apéro. Two LLMs reviewed my plan.</title>
      <dc:creator>chpomob</dc:creator>
      <pubDate>Mon, 03 Aug 2026 19:47:02 +0000</pubDate>
      <link>https://dev.to/chpomob/a-friend-dared-me-to-build-pass-the-pigs-during-the-apero-two-llms-reviewed-my-plan-3132</link>
      <guid>https://dev.to/chpomob/a-friend-dared-me-to-build-pass-the-pigs-during-the-apero-two-llms-reviewed-my-plan-3132</guid>
      <description>&lt;h1&gt;
  
  
  A friend dared me to build Pass the Pigs during the apéro. Two LLMs reviewed my plan.
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Or: a non-technical friend wanted to see what AI could do. He watched it plan — and watched two AIs shred the plan.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The challenge
&lt;/h2&gt;

&lt;p&gt;It happened at an apéritif, in front of a non-technical friend who wanted to see what AI could do. We were playing le jeu de cochons (Pass the Pigs) — the apéro game where you throw two tiny pigs, they land in one of seven positions, and you push your luck against the scoreboard. He picked it up, turned to me, and dared: "go on — make an app out of it. Right now. Show me what AI can do."&lt;/p&gt;

&lt;p&gt;The desktop wakes up. Challenge accepted. It looks trivial. It is not.&lt;/p&gt;

&lt;p&gt;My concept was "one-line to code": give an LLM a short prompt, let it plan, let it build, ship it. A modern party trick.&lt;/p&gt;

&lt;p&gt;Honesty clause #1: it wasn't literally one line. It took a few short exchanges — still almost no hand-holding from me, but I won't pretend it was a single prompt. The pigs are simple, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  The prompts (zero engineering)
&lt;/h2&gt;

&lt;p&gt;The prompts were apéro-grade: casual, naive, written in French over drinks — no templates, no role-play framing, no few-shot examples, no chain-of-thought coaxing. Translated from the originals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The spec ask: &lt;em&gt;"I'd like you to analyze this game — &lt;a href="https://fr.wikipedia.org/wiki/Jeu_de_cochons" rel="noopener noreferrer"&gt;https://fr.wikipedia.org/wiki/Jeu_de_cochons&lt;/a&gt; — and think about how to turn it into a game. Don't code anything: just analyze the rules and define what would need to be done, in product-definition mode."&lt;/em&gt; — the entire game description was one Wikipedia link; the model read the rules itself.&lt;/li&gt;
&lt;li&gt;The plan ask: &lt;em&gt;"I like approach B, detail it, prepare an initial dev plan to get a playable game, bug-free, tested and robust, that reproduces the base game's experience as faithfully as possible… give me that plan so I can have it reviewed. If the review is bad, I'll have a bad image of deepseek pro."&lt;/em&gt; — my entire incentive system, in one sentence.&lt;/li&gt;
&lt;li&gt;The review ask: &lt;em&gt;"Do an adversarial review of this plan, with Codex as the lead and Claude as secondary, with 2 loops."&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the whole prompt-engineering budget: zero. No magic incantations — the quality came from the process: two independent models, a gate at every stage, disagreement as a signal. Anyone can type these three prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The catch
&lt;/h2&gt;

&lt;p&gt;Pass the Pigs has a famously ambiguous rulebook, and the game is really about &lt;em&gt;probabilities&lt;/em&gt; — when to bank, when to roll again. The scoring semantics (Bon Jambon, Cochon à Cheval, Pig Out, the "Somme" rules) are exactly where a happy few-lines plan goes to die.&lt;/p&gt;

&lt;p&gt;So instead of trusting the plan those few prompts produced, I ran it through an adversarial review pipeline, orchestrated by Hermes Agent — the framework where these skills live. My Hermes runs on DeepSeek Flash for orchestration: the cheap part of the loop. The real work is done by the two specialist models — the plan was written by Codex as the architect, then reviewed independently by Claude Fable 5 as the inspector; a synthesis pass merged, categorized, and ranked their findings.&lt;/p&gt;

&lt;p&gt;The cost story is deliberately mundane: the whole loop ran on basic consumer plans — a €20/month Claude subscription and a €20/month Codex subscription, each model's turn scheduled inside its quota window. No API credits, no enterprise accounts. The pipeline is designed to fit inside the limits a hobbyist already pays for.&lt;/p&gt;

&lt;p&gt;Neither model is special, either: the pipeline accepts any LLM CLI on either side — Claude, Codex, Gemini, GLM, or fully local models served by llama.cpp (my Hermes already routes to local models). The only real requirement is two &lt;em&gt;different&lt;/em&gt; model families: two copies of the same model share the same blind spots, and the whole point is a second opinion that isn't a copy of your first one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Reviewer&lt;/th&gt;
&lt;th&gt;Findings&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Codex alone (architect)&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Fable 5 alone (inspector)&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Both, merged&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;16 unique findings&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;3 findings were found independently by both models&lt;/strong&gt; — the highest-confidence class. All three are &lt;em&gt;major&lt;/em&gt; bugs in the probability model.&lt;/li&gt;
&lt;li&gt;6 more reached consensus after discussion; 4 were partial (agreement on the issue, disagreement on severity); 3 were genuinely disputed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The duo found &lt;strong&gt;+5 findings over the best single model&lt;/strong&gt; (16 vs 11), and — more important than the count — the two models &lt;em&gt;independently converged on exactly the three most dangerous bugs&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The timeline (one apéro)
&lt;/h2&gt;

&lt;p&gt;Everything started at the apéritif and finished the next morning — the session log tells the story: dare at 21:12, plan and adversarial review that night, then a quota wall (one of the two subscriptions ran out mid-loop), and I went to bed while the pipeline kept running. A playable build was committed at 01:38; the real finish came in the morning, when the GitHub Pages URL needed one more fix at 10:32 (the classic Vite base-path 404) — so the first people to try the link that morning saw nothing. Five commits across an evening, a night, and a morning. The commit for the playable version reads, in part:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Moteur de règles complet (push-your-luck, probabilités calibrées) … 73 tests (unitaires + calibration 1M tirages + Playwright E2E) — Build Vite ~16KB gzip. Développé via adversarial dev loop (Codex DEV + Claude Fable 5 REVIEW)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An apéritif game that fits in 16KB gzipped, tested 73 ways, calibrated against a million simulated rolls — and the project's own commit history credits the adversarial loop. The full review trail (647-line plan, both models' findings, synthesis) is committed right next to the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The full chain (spec → plan → code)
&lt;/h2&gt;

&lt;p&gt;The plan review was one gate in a chain. The session opened with a spec pass — the product-definition analysis of the game's rules (scoring table, the three possible approaches, the four traps of going digital) — and everything downstream ran on it. After the plan was corrected, the code itself went through the same two-model loop, phase by phase (that's what adversarial-code-loop is for). The last phase's review caught two real major bugs the test suite had missed — in fact, the tests were asserting the buggy behavior: player names were HTML-escaped at the wrong layer (a name like &lt;code&gt;A&amp;amp;B &amp;lt;Bob&amp;gt;&lt;/code&gt; was stored and displayed as &lt;code&gt;A&amp;amp;amp;B &amp;amp;lt;Bob&amp;amp;gt;&lt;/code&gt;), and the localStorage high-score loader trusted unvalidated names. Both fixed, the tests corrected, all 73 green.&lt;/p&gt;

&lt;p&gt;Spec → plan → code: every stage is a gate where two independent models disagree in your place. That's the chaining the skills encode — adversarial-spec drafts the stage, adversarial-plan gates it, adversarial-code-loop keeps the code honest.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three findings both models caught
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The flank probabilities don't add up.&lt;/strong&gt; The plan assigned 12.25% to &lt;em&gt;each&lt;/em&gt; of two flank outcomes — but the two outcomes together total 12.25%, not 24.5%. A player's whole luck-push strategy was built on a doubled probability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The override rule silently kills a result.&lt;/strong&gt; Sequential checks for Bon Jambon / Cochon à Cheval overrides change the effective distribution — Cochon à Cheval ends up at 0.78% unless modeled as a disjoint probability partition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Jambon rule contradicts itself.&lt;/strong&gt; One section of the plan treats Bon Jambon as a turn-ending catastrophe; another treats it as a negative score clamped with &lt;code&gt;Math.max(0, score)&lt;/code&gt;. The game's most exciting rule was unimplementable as specified.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A single model can flag these. A single model cannot &lt;em&gt;confirm&lt;/em&gt; them. Two models converging on the same bug is the closest thing to a second opinion you can get from an LLM — and it cost nothing but one extra review pass.&lt;/p&gt;

&lt;p&gt;Honesty clause #2: the review made the probabilities &lt;em&gt;internally consistent&lt;/em&gt; — it did not make them &lt;em&gt;true&lt;/em&gt;. The corrected values still come from the models' reasoning, not from rolling actual pigs. The tests do run a million-roll calibration, but those are &lt;em&gt;simulated&lt;/em&gt; rolls: they stress-test the code, not the physics of real pigs. I am genuinely not sure the produced probabilities are right; they need calibration against real throwing data before I'd trust the strategy advice the game displays.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part nobody talks about: the disputes
&lt;/h2&gt;

&lt;p&gt;The adversarial setup does something a solo review can't: it produces &lt;em&gt;disagreement&lt;/em&gt;. Three findings ended up disputed — e.g., "can &lt;code&gt;nextPlayer()&lt;/code&gt; loop forever if everyone is eliminated?" — where the reviewer called it a real bug and the architect showed it's unreachable under valid transitions.&lt;/p&gt;

&lt;p&gt;That dispute signal is precious: it tells you exactly which parts of your plan are genuinely ambiguous and need a human decision, instead of silently shipping your assumptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honesty clause #3
&lt;/h2&gt;

&lt;p&gt;More findings ≠ better, if they're noise. The 16 findings were categorized precisely because of that: 3 cross-validated, 6 consensus, 4 partial, 3 disputed. The 13 that survived discussion were real, and the plan (v1.1) was corrected around them — probability model reworked, scoring made explicit, state transitions centralized — &lt;strong&gt;before a single line of game code was written&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The apéritif game went from dare to playable build by the end of the night — built from a plan that two models shredded, argued about, and rebuilt. That's the "few prompts to code" I actually want: a couple of short exchanges in, a reviewed, correct plan out.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tools: &lt;a href="https://github.com/chpomob/adversarial-code-loop" rel="noopener noreferrer"&gt;adversarial-code-loop&lt;/a&gt; (build → review → fix pipeline, model-agnostic, one-line installer), &lt;a href="https://github.com/chpomob/adversarial-plan" rel="noopener noreferrer"&gt;adversarial-plan&lt;/a&gt;, &lt;a href="https://github.com/chpomob/adversarial-spec" rel="noopener noreferrer"&gt;adversarial-spec&lt;/a&gt; — all orchestrated by &lt;a href="https://github.com/NousResearch/hermes-agent" rel="noopener noreferrer"&gt;Hermes Agent&lt;/a&gt;. The game — &lt;a href="https://chpomob.github.io/jeu-de-cochons/" rel="noopener noreferrer"&gt;play it&lt;/a&gt;, &lt;a href="https://github.com/chpomob/jeu-de-cochons" rel="noopener noreferrer"&gt;read the code&lt;/a&gt; — plan v1.1 after review, full review artifacts in &lt;code&gt;review/&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
