<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Llm on Electric Nexus</title><link>https://arkoniak.com/tags/llm/</link><description>Recent content in Llm on Electric Nexus</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Tue, 20 Oct 2026 13:00:00 +0300</lastBuildDate><atom:link href="https://arkoniak.com/tags/llm/index.xml" rel="self" type="application/rss+xml"/><item><title>Exerakt: Calibrating Jev</title><link>https://arkoniak.com/posts/exerakt-jev-calibration/</link><pubDate>Tue, 20 Oct 2026 13:00:00 +0300</pubDate><guid>https://arkoniak.com/posts/exerakt-jev-calibration/</guid><description>What 204 questions asked to both Jev and Claude showed: Jev is almost never confidently wrong, it is unsure on the questions that need careful reading, and the data says almost nothing about how well it catches problems.</description><content:encoded><![CDATA[<p>The previous posts mentioned that every question Jev answers in the pipeline is also put to Claude,
and that Claude decides while this calibration is on. Here is what that comparison showed.</p>
<h2 id="how-jev-answers">How Jev answers</h2>
<p>Jev does not answer yes or no. For each question, for example &ldquo;does every function belong to the
module&rsquo;s stated responsibility&rdquo;, it gives the probability that the answer is yes. The pipeline turns
that into a decision with two thresholds: 0.85 or more is yes, 0.3 or less is no, and everything in
between is a gray zone. While calibration is on, Claude answers the same questions, and the
comparison shows where the thresholds should be.</p>
<h2 id="what-204-questions-showed">What 204 questions showed</h2>
<p>Over all runs so far Jev got 204 such questions about the code of 28 cards: six project rules and
the criteria of each card.</p>
<p>Where Jev was confident, it agreed with Claude every time except once. That one case was the rule
about errors: failures have to be typed errors, not booleans or strings.</p>
<p>The uncertainty is not spread evenly. On the rule &ldquo;the code cannot panic&rdquo; 11 of 23 answers fell
into the gray zone, and on the rule about typed errors also 11 of 23. On a rule like &ldquo;the code
implements the general rule from the task, not the values from the tests&rdquo; there was no gray zone at
all. So Jev is careful exactly on the questions where the answer needs a close reading of the code.
For these two rules the threshold could be lowered to 0.3 or 0.4, and Jev would agree with Claude
almost everywhere.</p>
<p>The second use of Jev is classifying failures: should the card be retried, or should it go back to
Claude. Here Jev and Claude agreed in 31 of 34 cases, and all three disagreements were the same: Jev
said the model is going in circles and the card should go back, Claude said it was a typo and worth
another attempt. Jev is more pessimistic and sends cards back more often than needed.</p>
<p>Over all this time Jev cost about one cent and Claude as the judge about 2.70 dollars.</p>
<h2 id="the-catch">The catch</h2>
<p>The numbers above look very good, but there is a catch in them. Claude said &ldquo;yes, the code follows
the rule&rdquo; in 201 of 204 cases. By the time code reaches Jev it already compiles, clippy has nothing
to say, the mechanical rules hold and the tests pass. Code like that rarely breaks a rule, so there
were only three violations in the whole set.</p>
<p>This means that the high agreement mostly shows that both Jev and Claude find the code fine. How well Jev catches a problem these data almost cannot show, because there were almost
no problems to catch.</p>
<p>And this is the main thing I take from the calibration. In the current setup everything around Jev,
Rust&rsquo;s compiler, clippy and the frozen tests, makes such a solid base that Jev as a gate turns out to
be almost unnecessary. This is one of the things that made me reconsider Jev&rsquo;s role in this
project, but that is for a later post.</p>
]]></content:encoded></item><item><title>Exerakt: What Bonsai Does With Frozen Tests</title><link>https://arkoniak.com/posts/exerakt-bonsai/</link><pubDate>Tue, 20 Oct 2026 12:00:00 +0300</pubDate><guid>https://arkoniak.com/posts/exerakt-bonsai/</guid><description>How the local Bonsai model did as the executor over 28 cards: the logic was almost always right, and almost every failure was code that did not compile. And the mistake I made in how I ran it.</description><content:encoded><![CDATA[<p>When I set up the pipeline, I was worried that Bonsai would write poor code. An independent review
said it plans well and codes poorly in agentic tasks, so the whole scheme was built to compensate:
fixed signatures, frozen tests, and a task small enough to fit in one or two files.</p>
<p>In hindsight I can see that I made a big mistake here. I ran Bonsai not as an agent but purely as a
text generator: one request per attempt, no tools, the answer is the full content of the files it
changes. Now the mistake looks obvious, but in the first iteration I did not give this difference
much weight. The numbers below are about that setup.</p>
<h2 id="the-numbers">The numbers</h2>
<p>By now Bonsai has gone through 28 cards in 34 runs. All 28 were accepted in the end, 12 of them on
the first attempt of the first run. Six cards went back to Claude at least once.</p>
<p>More interesting is where the failed attempts failed. Every attempt goes through the same checks in
the same order: the files it touched, compilation and clippy, the project&rsquo;s rules, the tests, and
Jev. Over all runs:</p>
<ul>
<li>27 failed attempts stopped at compilation and clippy;</li>
<li>4 at formatting;</li>
<li>3 at Jev;</li>
<li>none at the tests.</li>
</ul>
<p>When Bonsai&rsquo;s code compiled, the logic was almost always right.</p>
<h2 id="what-went-wrong">What went wrong</h2>
<p>About two thirds of the compilation failures were code that does not compile at all. The most
typical one is a method that does not exist, like this check of an id&rsquo;s first character:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="k">if</span><span class="w"> </span><span class="n">input</span><span class="p">.</span><span class="n">first</span><span class="p">()</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="sc">&#39;@&#39;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span></code></pre></div><p>Slices have <code>first()</code>, strings do not. The same happened with <code>is_ascii_digits</code> and with a
<code>normalized</code> method on one of our own types. The rest were the places where Rust is hard: moving a value out from behind a reference, a temporary that does not live long enough,
a function that returns a value where <code>Ok(value)</code> is expected. The remaining third were clippy&rsquo;s
style remarks, such as two nested <code>if</code>s that can be one.</p>
<p>Claude and Jev classify every failure, and 30 of 34 were classified as trivial: a typo, a wrong
method name, a missing import.</p>
<p>The most expensive failure was of a different kind, and it was in the previous post. A card asked
for date calculations and named the algorithm without writing it down. Bonsai spent its whole
budget twice trying to derive the formulas and did not produce any code. Where it had to know
something rather than write something, it had no way to find out.</p>
<p>My conclusion after all these runs was this: Bonsai has no problem with how to write code, but there
is a lot it does not know. And
in the setup I chose it had no way to check: it could not look up a signature in a dependency or run
the compiler before answering. It learned about a missing method only from the next attempt&rsquo;s
error list.</p>
<h2 id="what-changed">What changed</h2>
<p>Bonsai&rsquo;s prompt did not change: it is the same as on the first run. What changed were the cards.
After the first step Claude got two rules for writing them: a known algorithm is written out, not
named, and every signature is checked against the project&rsquo;s rules before the card is cut. In the
runs since 19 October the first attempt compiles in 6 of 9 runs, against 7 of 25 before. Maybe the
better written cards are the reason, but the cards themselves are different and the numbers are
small, so I cannot say that for sure.</p>
<p>The orchestrator also runs <code>clippy --fix</code> before the clippy check now, so clippy&rsquo;s style remarks
that it can fix by itself would no longer cost an attempt. Since it was added, it has not had
anything to fix.</p>
<p>All of this cost about four hours of Bonsai&rsquo;s time for 28 cards, most of it spent on reasoning
tokens.</p>
<p>Running Bonsai as an agent, with tools and the compiler inside the loop, is still ahead. The next
post is about Jev and how much its answers can be trusted.</p>
]]></content:encoded></item><item><title>Exerakt: How the Models Work Together</title><link>https://arkoniak.com/posts/exerakt-pipeline/</link><pubDate>Sun, 18 Oct 2026 20:00:00 +0300</pubDate><guid>https://arkoniak.com/posts/exerakt-pipeline/</guid><description>How Claude, Jev and a local Bonsai model are put together into one pipeline, and what its first run showed: most failures that looked like the executor&amp;rsquo;s were mine.</description><content:encoded><![CDATA[<p>Once I knew what to build and with what, the next question was how to organise it. The idea of
Claude, Jev and Bonsai working together is clear on paper, but how does it work in practice? What is
called when and in which order, who depends on whom, and who checks whom?</p>
<h2 id="the-plan">The plan</h2>
<p>The work goes from the top down, in three levels. The whole client is split into milestones, each
ending in something that runs end to end: first a client that can only read, then one that can
write, then accounts, threads, and so on. When a milestone starts, Claude splits it into steps, and
when a step starts, Claude splits it into cards. Detail is added only one level ahead: only the
milestone we are working on is split into steps, and only the current step is split into cards.
This is called rolling wave planning. Every step ends with a review, and the review may change the
plan for the next steps, so there is no detailed plan for work that the earlier work can still
change. But there is always a more or less clear picture of what lies ahead and what is still left
to do. The diagram below shows the whole cycle.</p>
<pre class="mermaid">flowchart TD
    M[&#34;Milestone&lt;br/&gt;(e.g. a client that can write)&#34;] --&gt;|Claude splits the current milestone| S[Steps]
    S --&gt;|Claude splits the current step| C[&#34;Cards: signatures,&lt;br/&gt;frozen tests, task&#34;]
    C --&gt; L[[&#34;Card loop&lt;br/&gt;(Bonsai writes, checks, Jev decides)&#34;]]
    L --&gt; R[Step review by Claude]
    R --&gt;|next step| S
    R -.-&gt;|may change the plan| M</pre><p>The unit of work is a card: one small task for the executor (normally Bonsai), usually a few functions in one file.
Before a card goes anywhere, Claude has already written everything around it: the types and
function signatures with empty bodies, the module&rsquo;s description, and the tests. The tests are
frozen. Bonsai sees the task, the files it may change and the tests, and fills in the bodies. If a
test file changes by a single byte, the attempt does not count, so the model cannot pass a test by
rewriting it. For a model working on its own this is the most important guard.</p>
<p>The cards are run by an orchestrator, a separate program that Claude wrote. For each
card it asks Bonsai for code and then checks the result, cheapest checks first:</p>
<ol>
<li>Did the model touch only the files it was allowed to touch?</li>
<li>Does it compile, and does clippy have nothing to say?</li>
<li>Does the code break any of the project&rsquo;s mechanical rules, such as which crate may depend on
which?</li>
<li>Do the tests pass?</li>
<li>Only then Jev: questions that a machine cannot check, like &ldquo;does the code do what the task
describes&rdquo; or &ldquo;does every function belong to the module&rsquo;s stated responsibility&rdquo;.</li>
</ol>
<p>The first four checks cost nothing and are exact, so Jev only sees code that already
works. When a check fails, the errors go back to Bonsai for another attempt. Jev also looks at
the failure and decides whether it is worth retrying (a typo, a wrong method name) or whether the
card should go back to Claude (the task itself looks wrong, or the model is going in circles).
After three failed attempts the card goes back to Claude anyway. The second diagram shows one
card&rsquo;s way through this loop.</p>
<pre class="mermaid">flowchart TD
    B[Bonsai writes the code] --&gt; G1{&#34;Only the allowed&lt;br/&gt;files changed?&#34;}
    G1 --&gt;|yes| G2{&#34;Compiles,&lt;br/&gt;clippy clean?&#34;}
    G2 --&gt;|yes| G3{&#34;Project rules&lt;br/&gt;hold?&#34;}
    G3 --&gt;|yes| G4{&#34;Tests pass?&#34;}
    G4 --&gt;|yes| J{&#34;Jev: does the code&lt;br/&gt;do what the task says?&#34;}
    J --&gt;|yes| A[Accepted, merged into the step]
    J -.-&gt;|not sure| JD[Claude as judge]
    JD -.-&gt; A
    G1 &amp; G2 &amp; G3 &amp; G4 &amp; J --&gt;|no| F{&#34;Jev: what kind&lt;br/&gt;of failure?&#34;}
    F --&gt;|&#34;typo, local mistake:&lt;br/&gt;errors go back&#34;| B
    F --&gt;|&#34;card looks wrong,&lt;br/&gt;model goes in circles,&lt;br/&gt;attempts used up&#34;| E[Back to Claude]</pre><p>There is one more participant for the start. When I searched for how Jev is used, I found the
recommendation to calibrate it on your own tasks before relying on it fully. So Claude was added as
a judge: every question Jev answers is also put to Claude, and while this calibration is on,
Claude&rsquo;s answer decides (the dashed arrows in the second diagram). On the first step Jev cost about 300
times less than Claude for the same questions, which is the reason to want it to take over.</p>
<p>Bonsai (<a href="https://prismml.com/news/bonsai-2-27b">Bonsai 2 27B</a> by PrismML) was chosen for a
simple reason: on my machine, with one 12 GB graphics card, it had a reasonable balance between
speed and quality, about 56 tokens per second with 128K tokens of context. A better candidate
could probably be found, but at that moment it was a model that definitely worked, had a good
context size, and I did not want to spend time searching for another one.</p>
<p>An independent review of Bonsai said that it plans well and codes poorly in agentic tasks. Fixed
signatures and frozen tests were meant to compensate for exactly that: the model does not have to
design anything, only to fill in bodies until the tests pass.</p>
<h2 id="the-first-run">The first run</h2>
<p>The first step was the client&rsquo;s model: pure view state, room list, timeline, dates, previews. Six
cards, 75 frozen tests. One card of six passed on the first attempt, one more on the second, and four
came back to Claude.</p>
<p>When I looked at why, only one of the four was Bonsai&rsquo;s failure: it converged on the answer,
but ran out of attempts on the way. The other three were not its fault:</p>
<ul>
<li>The orchestrator itself had a bug. Bonsai&rsquo;s code had passed every check, and the last thing left
was to ask Claude, as the judge, the same questions Jev had answered. That request failed: the
orchestrator named each question after the project rule it checks, with names like <code>R:S4</code>, and
the colon is not allowed in the format Claude&rsquo;s interface expects for these answers. So a correct
card came back as a failure.</li>
<li>One card asked for a function that returns <code>bool</code> when an operation fails. The project&rsquo;s own rules
say that failures are typed errors. Bonsai followed the card, and Jev correctly rejected the
code for breaking the rules.</li>
<li>One card asked for date calculations and said &ldquo;use Hinnant&rsquo;s algorithm&rdquo;, without writing the
algorithm down. Bonsai spent its whole token budget twice trying to derive it and did not produce
a single line of code.</li>
</ul>
<p>So in this scheme the architect&rsquo;s mistakes look like the executor&rsquo;s mistakes. A badly written card
shows up as a failed attempt, and from the outside it is hard to tell which side is wrong.</p>
<h2 id="what-changed">What changed</h2>
<p>The fixes went to where the problems were. The orchestrator got its bug fixed and a check that
catches it before a run. The card with <code>bool</code> returns a typed error now. The date card got the
formulas themselves, checked against Python&rsquo;s <code>datetime</code> for every year from 1 to 9999. And the
process for writing cards got two new rules: a known algorithm is written out, not named, and
every signature is checked against the project&rsquo;s rules before the card is cut.</p>
<p>The more general lesson is that the pipeline has to tell these failures apart. That is why Jev
classifies every failure, and why &ldquo;the card itself looks wrong&rdquo; goes straight back to Claude
instead of costing Bonsai more attempts.</p>
<p>What Bonsai itself does with the cards it gets is the subject of the next post.</p>
]]></content:encoded></item></channel></rss>