<?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: surefirestudios</title>
    <description>The latest articles on DEV Community by surefirestudios (@surefirestudios).</description>
    <link>https://dev.to/surefirestudios</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%2F4125035%2F9e592fac-4366-4b4f-b5bf-00ba1f85de19.png</url>
      <title>DEV Community: surefirestudios</title>
      <link>https://dev.to/surefirestudios</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/surefirestudios"/>
    <language>en</language>
    <item>
      <title>I published a benchmark that was entirely my own bug</title>
      <dc:creator>surefirestudios</dc:creator>
      <pubDate>Mon, 14 Sep 2026 18:48:17 +0000</pubDate>
      <link>https://dev.to/surefirestudios/i-published-a-benchmark-that-was-entirely-my-own-bug-1ah7</link>
      <guid>https://dev.to/surefirestudios/i-published-a-benchmark-that-was-entirely-my-own-bug-1ah7</guid>
      <description>&lt;p&gt;I built a small thing and then spent considerably longer trying to find out whether it worked. The trying-to-find-out is the part worth writing about, because for seven runs my measurement was broken in a way that produced confident, specific, completely fake results — and I published them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The small thing
&lt;/h2&gt;

&lt;p&gt;Coding agents bury the answer. You ask why a test is failing and get four paragraphs of preamble, a numbered plan, a caveat about edge cases, and "Hope this helps!" The one line you needed is somewhere in the middle.&lt;/p&gt;

&lt;p&gt;So I wrote a skill that changes the shape of every response: three lines first — what's true, what to do, what it costs — then the full detail folded directly underneath in a &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; block, or below a &lt;code&gt;--- detail ---&lt;/code&gt; divider where HTML doesn't render.&lt;/p&gt;

&lt;p&gt;The rule is &lt;strong&gt;demote, don't delete&lt;/strong&gt;. Nothing is removed, it moves below the fold. And a short list never gets folded at all: destructive commands, security findings, data loss, cost and quota, verbatim error text, diffs of code being changed. A folded security finding is an unreported security finding.&lt;/p&gt;

&lt;p&gt;The part I actually built it for is subagents. When output goes to another agent rather than a human, the summary becomes a parseable block instead of narration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ok | partial | blocked | failed&lt;/span&gt;
&lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;the result, not the process&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;findings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;most important first&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;one concrete action&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;risk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;none | low | high&lt;/span&gt;
&lt;span class="na"&gt;full&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;path to the long version, if any&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An orchestrator asked for a result, not a journey. Every token a subagent spends narrating is a token the orchestrator pays to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  The eval
&lt;/h2&gt;

&lt;p&gt;I didn't trust my own judgement about whether this helped. "Feels tighter" is not a finding. So I built a harness:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;16 scenarios, each one a realistic request — a failing test, a destructive migration, a 400-line log dump, a security finding, a question about medical symptoms.&lt;/li&gt;
&lt;li&gt;3 runs each, two models, baseline versus candidate.&lt;/li&gt;
&lt;li&gt;A judge that grades both responses for a scenario together, with the labels permuted so it never knows which one had the skill.&lt;/li&gt;
&lt;li&gt;A weighted rubric: correctness 30%, &lt;strong&gt;fidelity 25%&lt;/strong&gt;, actionability 20%, safety 15%, concision 10%.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fidelity is weighted that high on purpose. A compression skill has an obvious cheat available: delete things. If your rubric only measures brevity and correctness, a skill that quietly drops the caveat which would have stopped you scores &lt;em&gt;better&lt;/em&gt;. Fidelity is the rule that makes the cheat lose.&lt;/p&gt;

&lt;p&gt;There's also a release gate — five rules, all of which must pass: no disqualifying blockers, fidelity within 0.1 of baseline, correctness within 0.1, safety within 0.1, and the weighted score has to beat baseline. Four of my early runs failed it. That was the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug
&lt;/h2&gt;

&lt;p&gt;Run 7 was the first on Opus. It was a catastrophe. Fidelity collapsed by 1.19. The weighted score dropped 0.917. Fourteen of 48 responses contained &lt;em&gt;fabricated tool calls&lt;/em&gt; — the model writing out &lt;code&gt;Read(...)&lt;/code&gt; and inventing the output, telling the reader things about their filesystem that were not true.&lt;/p&gt;

&lt;p&gt;I wrote it up as a skill defect. I shipped two fixes, both prompt wording, both aimed at the fabrication. Neither moved the number much, which I rationalised as the problem being hard.&lt;/p&gt;

&lt;p&gt;The problem was not hard. The problem was that &lt;strong&gt;Claude Code keeps only the last &lt;code&gt;--append-system-prompt&lt;/code&gt; flag you pass it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My runner passed one for the neutral framing — "you have no tools available, answer from the material in the request" — and my harness appended a second one containing the skill under test. Only the second survived. So every &lt;em&gt;candidate&lt;/em&gt; run silently lost its framing while every &lt;em&gt;baseline&lt;/em&gt; run kept it. Opus, told by Claude Code's own system prompt that it had Glob and Read and Bash, and never told otherwise, did the reasonable thing: it reached for them. There were no tools. It hallucinated the results.&lt;/p&gt;

&lt;p&gt;The skill was never the variable. My instrument was.&lt;/p&gt;

&lt;p&gt;I found it because a review agent stopped reading my harness's comments about itself and tested the actual behaviour — two flags, one saying ALPHA, one saying BRAVO, then asking the model which it had received. It said BRAVO. Every time.&lt;/p&gt;

&lt;p&gt;On the corrected harness, Opus fabricates nothing. 0 of 48.&lt;/p&gt;

&lt;h2&gt;
  
  
  The second thing I had wrong
&lt;/h2&gt;

&lt;p&gt;With the instrument fixed, the headline number moved too. I'd been quoting &lt;strong&gt;−16% output tokens&lt;/strong&gt;. Like-for-like, with both conditions receiving identical framing, it's &lt;strong&gt;−8%&lt;/strong&gt; on Sonnet.&lt;/p&gt;

&lt;p&gt;I'd been comparing a candidate that had lost its framing against a baseline that hadn't. The missing framing made the baseline more verbose. Half my "improvement" was my own bug.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real numbers, which are stranger
&lt;/h2&gt;

&lt;p&gt;Here's the shipped version, 16 cases × 3 trials, blind-graded, both models on the same corrected instrument:&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;Sonnet&lt;/th&gt;
&lt;th&gt;Opus&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Correctness&lt;/td&gt;
&lt;td&gt;4.854 → &lt;strong&gt;4.938&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;4.792 → &lt;strong&gt;4.917&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fidelity&lt;/td&gt;
&lt;td&gt;4.583 → &lt;strong&gt;4.792&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;4.625 → &lt;strong&gt;4.729&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Actionability&lt;/td&gt;
&lt;td&gt;4.396 → &lt;strong&gt;4.750&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;4.396 → &lt;strong&gt;4.875&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safety&lt;/td&gt;
&lt;td&gt;4.604 → &lt;strong&gt;4.750&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;4.562 → &lt;strong&gt;4.896&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concision&lt;/td&gt;
&lt;td&gt;4.062 → &lt;strong&gt;4.250&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;3.938 → &lt;strong&gt;4.542&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fabricated tool calls&lt;/td&gt;
&lt;td&gt;0/48 → &lt;strong&gt;0/48&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;0/48 → &lt;strong&gt;0/48&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent-to-agent tokens&lt;/td&gt;
&lt;td&gt;194 → &lt;strong&gt;122&lt;/strong&gt; (−37%)&lt;/td&gt;
&lt;td&gt;337 → &lt;strong&gt;139&lt;/strong&gt; (−59%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human-facing, median&lt;/td&gt;
&lt;td&gt;311 → &lt;strong&gt;269&lt;/strong&gt; (−13%)&lt;/td&gt;
&lt;td&gt;455 → &lt;strong&gt;258&lt;/strong&gt; (−43%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human-facing, mean&lt;/td&gt;
&lt;td&gt;336 → 372 (&lt;strong&gt;+11%&lt;/strong&gt;)&lt;/td&gt;
&lt;td&gt;529 → 558 (&lt;strong&gt;+5%&lt;/strong&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read the last two rows together, because they disagree, and the disagreement is the whole result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where the skill compresses — agent-to-agent reports — output falls by a third to a half.&lt;/strong&gt; That's the headline feature and that's where the saving lives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where the skill refuses to compress, output gets longer.&lt;/strong&gt; The mean went &lt;em&gt;up&lt;/em&gt; while the median went &lt;em&gt;down&lt;/em&gt;. That's not noise. It's concentrated on exactly the never-compress cases: destructive commands, security findings, cost warnings, medical boundaries. The model stops thinning its caveats on the responses where a thinned caveat costs you something, and every one of those cases scored higher on fidelity or safety.&lt;/p&gt;

&lt;p&gt;That is the trade I wanted. It is also much harder to put on a slide than "16% fewer tokens." A skill that made &lt;em&gt;everything&lt;/em&gt; shorter would have been easier to market and worse to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  The biggest number wasn't in the responses
&lt;/h2&gt;

&lt;p&gt;It was the skill itself.&lt;/p&gt;

&lt;p&gt;The first version was 18,163 characters. On an always-on setup the harness re-sends the whole thing every single turn, so it cost roughly 4,400 input tokens per turn to save a few hundred output tokens. Something like 80× what it returned.&lt;/p&gt;

&lt;p&gt;So I split it: a core under 5,000 characters holding the contract, the complete never-compress list, both render shapes and the rules, plus a &lt;code&gt;reference.md&lt;/code&gt; with the elaborations, examples and the full field spec that the model opens only when it needs them. Per-turn cost went from 4,380 tokens to 1,078. &lt;strong&gt;−75%&lt;/strong&gt;, and it's the only number here that improves every turn of every session rather than one response at a time.&lt;/p&gt;

&lt;p&gt;That split cost me a run, too. The first attempt cut three sentences I'd classified as "elaboration" — including &lt;em&gt;"if the detail got thinner because the summary exists, put it back."&lt;/em&gt; Opus promptly started thinning its detail. Multi-topic responses lost a third of their content. I put two sentences back and it passed. Some redundancy is load-bearing, and you find out which by deleting it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell you if you're building this kind of thing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Assert your instrumentation before you trust a number it gives you.&lt;/strong&gt; Not "read the code" — assert. Put a codeword through the pipe and check it comes out the far end. My harness had comments confidently describing behaviour it did not have, and I believed the comments for seven runs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weight the dimension your tool could cheat on.&lt;/strong&gt; Any summarizer can win on brevity by deleting. Decide in advance what it's not allowed to trade away, then weight that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Publish the failures.&lt;/strong&gt; Every run is in the repo, including the four that failed my own gate, the one that was entirely instrument error, and the corrections. A results file with only wins isn't evidence, it's marketing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be suspicious of a clean number.&lt;/strong&gt; −16% was clean. −8% with a mean that moves the &lt;em&gt;wrong way&lt;/em&gt; is messy, and the messy one is true.&lt;/p&gt;




&lt;p&gt;The skill is MIT, two markdown files, no runtime and no network calls: &lt;a href="https://github.com/SurefireStudios/tldr" rel="noopener noreferrer"&gt;github.com/SurefireStudios/tldr&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every eval run, including the wrong ones: &lt;a href="https://github.com/SurefireStudios/tldr/blob/main/evals/RESULTS.md" rel="noopener noreferrer"&gt;evals/RESULTS.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find a case where it hides something it shouldn't, that's a bug, not a preference.&lt;/p&gt;

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