<?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: Don Johnson</title>
    <description>The latest articles on DEV Community by Don Johnson (@copyleftdev).</description>
    <link>https://dev.to/copyleftdev</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%2F965504%2Fd5dcc14b-c050-4183-a25e-c54e006eb6b2.png</url>
      <title>DEV Community: Don Johnson</title>
      <link>https://dev.to/copyleftdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/copyleftdev"/>
    <language>en</language>
    <item>
      <title>My QUIC transport had never once been executed. Here's what happened when I ran it.</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Wed, 19 Aug 2026 03:35:06 +0000</pubDate>
      <link>https://dev.to/copyleftdev/my-quic-transport-had-never-once-been-executed-heres-what-happened-when-i-ran-it-24ge</link>
      <guid>https://dev.to/copyleftdev/my-quic-transport-had-never-once-been-executed-heres-what-happened-when-i-ran-it-24ge</guid>
      <description>&lt;p&gt;I've written before about SMESH, a coordination protocol modelled on mycorrhizal networks — the fungal web that lets trees in a forest warn each other about drought and disease with nothing in charge of the network. Signals diffuse, decay on their own, and get reinforced when independently confirmed. Consensus emerges instead of being orchestrated.&lt;/p&gt;

&lt;p&gt;That was the idea. This post is about the part where I found out whether it worked.&lt;/p&gt;

&lt;h2&gt;
  
  
  The transport that had never run
&lt;/h2&gt;

&lt;p&gt;SMESH has had a QUIC transport in it for a while. Roughly 500 lines: a quinn endpoint that is simultaneously server and client, self-signed certs, length-prefixed bincode frames over unidirectional streams, an accept loop that spawns per-connection and per-stream tasks, connection pooling.&lt;/p&gt;

&lt;p&gt;Every test passed. The workspace was green. I could point at &lt;code&gt;smesh-runtime/src/transport.rs&lt;/code&gt; and say "yes, it does peer-to-peer."&lt;/p&gt;

&lt;p&gt;Then I grepped for who actually constructed it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; &lt;span class="s2"&gt;"QuicTransport"&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'*.rs'&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
smesh-runtime/src/transport.rs:177:pub struct QuicTransport &lt;span class="o"&gt;{&lt;/span&gt;
smesh-runtime/src/transport.rs:192:impl QuicTransport &lt;span class="o"&gt;{&lt;/span&gt;
smesh-runtime/src/lib.rs:16:pub use transport::&lt;span class="o"&gt;{&lt;/span&gt;QuicTransport, ...&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Its own definition, and a re-export. Nothing else in the workspace had ever instantiated it. No binary opened a socket. &lt;code&gt;SmeshRuntime&lt;/code&gt; imported &lt;code&gt;TransportConfig&lt;/code&gt;, stored it in a struct field, and never looked at it again.&lt;/p&gt;

&lt;p&gt;I had a networking layer with tests, docs, and zero executions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three bugs in the first twenty minutes
&lt;/h2&gt;

&lt;p&gt;I wrote an integration test that starts two runtimes, has one dial the other, and asserts a signal crosses. Here is what fell out before it went green.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. It panicked on the first call.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Could not automatically determine the process-level CryptoProvider
from Rustls crate features.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rustls 0.23 refuses to pick a crypto backend when more than one is compiled in, and quinn pulls in both through its own feature set. Every call to &lt;code&gt;QuicTransport::new&lt;/code&gt; would have panicked for anyone, ever. Nobody noticed because nobody had called it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Dialled connections were write-only.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;connect()&lt;/code&gt; stored the connection in the pool but only the accept loop pumped incoming streams — and the accept loop only sees connections you &lt;em&gt;accepted&lt;/em&gt;. So a node that dialled out could send, and would never receive anything back. A QUIC connection is bidirectional regardless of who dialled it; my code only acted like it half the time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Unbounded allocation from an attacker-controlled length prefix.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_be_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len_buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;   &lt;span class="c1"&gt;// &amp;lt;- no&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;max_message_size&lt;/code&gt; was in the config struct. It was never read. Send a 4 GiB length prefix and the process allocates 4 GiB.&lt;/p&gt;

&lt;p&gt;None of these are clever bugs. They're the bugs you get for free the first time code meets a socket, and the only reason they survived is that the code had never met a socket.&lt;/p&gt;

&lt;h2&gt;
  
  
  The harder problem: my protocol was wrong
&lt;/h2&gt;

&lt;p&gt;Fixing the plumbing was the easy half. The real issue was that my diffusion algorithm quietly assumed something no distributed system can assume.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Network::tick&lt;/code&gt; expands a signal's reach one hop per tick by walking the graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;node_id&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;reached&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;hypha&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.hyphae&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.nodes&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;hypha&lt;/span&gt;&lt;span class="py"&gt;.to&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="nf"&gt;.should_relay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;remaining_hops&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;frontier&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hypha&lt;/span&gt;&lt;span class="py"&gt;.to&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read that again. It iterates every node's adjacency, calls every node's relay policy, and mutates one global &lt;code&gt;reached_nodes&lt;/code&gt; set on a shared signal. It's a breadth-first search from a god's-eye view of the entire graph.&lt;/p&gt;

&lt;p&gt;That works beautifully in one process. In a real mesh, &lt;strong&gt;no node can see that graph.&lt;/strong&gt; Porting it meant three corrections, and each one turned out to be a genuine bug rather than a porting detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Correction 1: independent conclusions were being thrown away
&lt;/h3&gt;

&lt;p&gt;Signals are content-addressed — the hash is derived from what is being claimed. So when two agents independently reach the same conclusion, they produce the same hash.&lt;/p&gt;

&lt;p&gt;My &lt;code&gt;emit()&lt;/code&gt; saw the hash already present locally and treated it as a duplicate. It dropped it.&lt;/p&gt;

&lt;p&gt;That is exactly backwards. Two parties independently agreeing is not redundant data — it is the &lt;em&gt;only&lt;/em&gt; evidence the system has that a claim is real. Discarding it destroys the thing the protocol exists to measure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="cd"&gt;/// Signals are content-addressed, so a node that independently reaches a&lt;/span&gt;
&lt;span class="cd"&gt;/// conclusion another node already published lands on the same hash. That&lt;/span&gt;
&lt;span class="cd"&gt;/// is treated as *corroboration*: this node is added as an attester and the&lt;/span&gt;
&lt;span class="cd"&gt;/// merged claim still goes out, because our agreement is news to everyone&lt;/span&gt;
&lt;span class="cd"&gt;/// who has not heard it. Swallowing it as a duplicate would silently&lt;/span&gt;
&lt;span class="cd"&gt;/// discard the only evidence that two parties concur.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Correction 2: I was counting messengers, not witnesses
&lt;/h3&gt;

&lt;p&gt;Reinforcement attributed the claim to whoever handed me the message. In a gossip mesh, one finding relayed by five nodes then looks like five corroborators.&lt;/p&gt;

&lt;p&gt;The party that attests to a claim is its &lt;em&gt;origin&lt;/em&gt;, not the peer that passed it along. Relaying is not agreeing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Correction 3: gossip needs a merge rule, not a broadcast rule
&lt;/h3&gt;

&lt;p&gt;Once attestation is a set, the rule that makes gossip converge is simple and pleasant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Merge the two attester sets. Anything the sender knew that we did&lt;/span&gt;
&lt;span class="c1"&gt;// not is new information, and new information is worth passing on.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;attesters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attester&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;incoming_attesters&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt;&lt;span class="nf"&gt;.contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attester&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="nf"&gt;.reinforce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attester&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Forward if and only if your own knowledge grew. That single rule is the loop breaker (a message teaching you nothing goes no further), the convergence mechanism (the set is grow-only, so it's a CRDT), and the anti-entropy repair (re-asserting carries your accumulated view, so a node that missed a round catches up).&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I nearly got wrong on purpose
&lt;/h2&gt;

&lt;p&gt;Here is the subtlety that makes the whole thing work, and it looks like a mistake in the source.&lt;/p&gt;

&lt;p&gt;The signal builder folds the origin node into the content hash if you give it one. So when an agent publishes a claim, you must &lt;strong&gt;not&lt;/strong&gt; set the origin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;SignalType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Alert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.payload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assertion&lt;/span&gt;&lt;span class="nf"&gt;.canonical_bytes&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="nf"&gt;.confidence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;finding&lt;/span&gt;&lt;span class="py"&gt;.confidence&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// .origin() deliberately NOT called&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you set it, every agent gets a different hash for the same claim and correlation becomes impossible. The address has to be the &lt;em&gt;claim&lt;/em&gt;, not the &lt;em&gt;claimant&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The corollary is that evidence cannot travel in the payload. Each agent's evidence differs, so putting it in would make every hash unique and break the mechanism. The payload is just the assertion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"checkout-api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"claim"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"degraded"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Evidence stays local and goes to the log. The mesh carries assertions; it does not carry arguments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five witnesses, none of whom can see the problem
&lt;/h2&gt;

&lt;p&gt;To actually test any of this, I built a scenario where the answer cannot be reached alone.&lt;/p&gt;

&lt;p&gt;Five analyst processes watch the same fleet of services. Each can see exactly one kind of telemetry, and nothing else:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;agent&lt;/th&gt;
&lt;th&gt;sees&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;latency&lt;/td&gt;
&lt;td&gt;p99 response times&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;errors&lt;/td&gt;
&lt;td&gt;error rates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;saturation&lt;/td&gt;
&lt;td&gt;pool and CPU utilisation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;traces&lt;/td&gt;
&lt;td&gt;retry rates, span queueing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deploys&lt;/td&gt;
&lt;td&gt;release events&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A deploy cuts &lt;code&gt;checkout-api&lt;/code&gt;'s connection pool from 200 to 20. The pool pins, requests queue, callers time out.&lt;/p&gt;

&lt;p&gt;Now every agent sees a piece of it, and two of them are actively misleading. &lt;code&gt;errors&lt;/code&gt; sees &lt;code&gt;payments-api&lt;/code&gt; throwing 503s and would blame it — but payments is a victim, its own pool and CPU are fine. &lt;code&gt;latency&lt;/code&gt; sees four services slow at once and can't say which is causal. Only &lt;code&gt;deploys&lt;/code&gt; can see there was a release, and a release on its own means nothing; software ships all day.&lt;/p&gt;

&lt;p&gt;I also planted two decoys with a single witness each — an unrelated CPU spike, a brief latency blip — because a system that agrees with everything is not consensus, it's an echo.&lt;/p&gt;

&lt;p&gt;They run as five real OS processes on five ports over real encrypted QUIC, in a ring-plus-chord topology so messages actually have to be relayed to cross the mesh. Peer discovery is off, or gossip quietly converts any topology into a full mesh and there's nothing left to watch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;smesh orchestrate &lt;span class="nt"&gt;--out&lt;/span&gt; runs/latest
&lt;span class="go"&gt;
  spawned latency     pid 2452744  127.0.0.1:9301  dials 9302,9303
  spawned errors      pid 2452745  127.0.0.1:9302  dials 9303
  spawned saturation  pid 2452746  127.0.0.1:9303  dials 9304
  spawned traces      pid 2452747  127.0.0.1:9304  dials 9305
  spawned deploys     pid 2452748  127.0.0.1:9305  dials 9301
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;what the mesh concluded
  checkout-api          CONSENSUS at 16.9s · 5 attesters · seen by 5 nodes
  payments-api          no consensus (3/4 concerns)
  edge-gateway          no consensus (1/4 concerns)
  notification-worker   no consensus (1/4 concerns)
  session-store         no consensus (1/4 concerns)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cause separated from symptom separated from noise. The loud, obvious suspect was held at three witnesses and never promoted. The decoys were never rejected by anything — they simply went uncorroborated and decayed out. Nobody voted, and nothing was in charge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the run replayable, and then checking that claim
&lt;/h2&gt;

&lt;p&gt;I wanted to visualise this, which meant the log had to be good enough to reconstruct the run exactly. Each process writes newline-delimited JSON against a shared run epoch: every emission, every per-peer send, every receipt, every relay decision including the probability and the die roll that resolved it, and a full field snapshot every 500ms so decay curves are &lt;em&gt;observed&lt;/em&gt; rather than modelled.&lt;/p&gt;

&lt;p&gt;Then I did the part I'd recommend to anyone building a log you intend to trust: I wrote a validator that checks the log against itself. Sequence gaps, time going backwards, snapshots referencing signals that were never received, consensus declared without the receipts to justify it.&lt;/p&gt;

&lt;p&gt;It caught a real bug on its first run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FAIL  latency: first event is peer_connected, not node_started
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A peer completed the handshake in the gap between binding the endpoint and writing the node's identity line. The fix was to move the identity write inside the mesh startup, before any loop spawns. I would never have found that by looking at the picture — the picture would just have been subtly wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is still wrong
&lt;/h2&gt;

&lt;p&gt;Being honest about the edges, because "it works" is a claim that needs a boundary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;origin_node_id&lt;/code&gt; is unauthenticated.&lt;/strong&gt; It's a string on the wire, and the trust model gates relay probability on it. Spoofing another agent's identity is currently free. Ed25519-signing the origin hash closes it and is the next real piece of work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The content hash is truncated to 64 bits.&lt;/strong&gt; Fine against accident, not against an adversary looking for collisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The telemetry in the demo is synthetic.&lt;/strong&gt; Deliberately: a seeded fixture means the run reproduces byte-for-byte on any machine, which is what makes a visualisation worth trusting. The coordination is not synthetic — real processes, real sockets, probabilistic relay.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  See it move
&lt;/h2&gt;

&lt;p&gt;The full narrated walkthrough is the cover video on this post, or here: &lt;a href="https://youtu.be/kmCzwSBqu_s" rel="noopener noreferrer"&gt;https://youtu.be/kmCzwSBqu_s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It opens on the forest the protocol is stolen from, then goes inside the recorded run: five agents, six encrypted links, every dot on screen a real message read back from the log rather than animated for effect.&lt;/p&gt;

&lt;p&gt;If you take one thing from this: &lt;strong&gt;code that has never been executed is not code, it's a plan.&lt;/strong&gt; Mine had tests, docs, and a clean &lt;code&gt;cargo clippy&lt;/code&gt;, and it would have panicked on the first line for every user. The tests were testing that the plan was internally consistent.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/copyleftdev/smesh-rust" rel="noopener noreferrer"&gt;github.com/copyleftdev/smesh-rust&lt;/a&gt; · Rust · MIT/Apache-2.0&lt;/p&gt;

</description>
      <category>rust</category>
      <category>distributedsystems</category>
      <category>networking</category>
      <category>ai</category>
    </item>
    <item>
      <title>Shipping Assumptions: A Reliability Stack for AI-Generated Code</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Sun, 16 Aug 2026 22:56:25 +0000</pubDate>
      <link>https://dev.to/copyleftdev/shipping-assumptions-a-reliability-stack-for-ai-generated-code-3p9f</link>
      <guid>https://dev.to/copyleftdev/shipping-assumptions-a-reliability-stack-for-ai-generated-code-3p9f</guid>
      <description>&lt;p&gt;The code looked good. It linted cleanly. The shallow tests passed. Everyone felt—&lt;em&gt;vibed&lt;/em&gt;—that we had built the right thing.&lt;/p&gt;

&lt;p&gt;Then the edge case appeared in production.&lt;/p&gt;

&lt;p&gt;The developer treated it as normal operating procedure: bugs happen, tickets arrive, patches ship. QA was asked why they had not caught it. But QA never received a model of the system—only an implementation full of assumptions they were expected to reverse-engineer.&lt;/p&gt;

&lt;p&gt;This is becoming the defining failure mode of AI-assisted development. We can generate code faster than we can understand the systems it creates. The danger is no longer confined to a bad function or an obvious syntax error. It lives in the space between components: boundaries, state transitions, failure modes, and invariants.&lt;/p&gt;

&lt;p&gt;We are not merely shipping code. We are shipping assumptions we can no longer see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean code is not a coherent system
&lt;/h2&gt;

&lt;p&gt;A linter can tell us whether code follows a set of local rules. A test can tell us whether selected examples produce the expected result. Neither can tell us what the system must preserve unless someone states it first.&lt;/p&gt;

&lt;p&gt;An invariant is one of those statements: a condition that must remain true across every valid state of the system. An account balance cannot be changed without a corresponding transaction. A private object cannot become public without authorization. Two successful writes cannot silently erase one another.&lt;/p&gt;

&lt;p&gt;When invariants remain implicit, clean code can still assemble into an incoherent system. Each component may look reasonable in isolation while the failure waits in a transition, a retry, a race, or a boundary nobody thought to draw.&lt;/p&gt;

&lt;p&gt;That is the space AI-assisted development is rapidly filling with code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The layer we buried
&lt;/h2&gt;

&lt;p&gt;There was no golden age in which every developer wrote a formal specification before touching an editor. Most teams did not. Earlier software was full of hidden assumptions too, and nostalgia has a habit of removing the inconvenient parts of the past.&lt;/p&gt;

&lt;p&gt;But the field did develop disciplines for reasoning above the code: architectural models, state machines, formal specifications, model checking, fault injection, and deterministic simulation. We tended to reserve them for systems where failure was obviously expensive. Everywhere else, rigor was treated as a cost to minimize.&lt;/p&gt;

&lt;p&gt;Then implementation became cheaper. Frameworks hid machinery. Packages compressed years of expertise into an import. That brought enormous benefits, but it also made it possible to build systems without seeing very far beneath their surfaces.&lt;/p&gt;

&lt;p&gt;Generative AI accelerates the same trade. It can produce a plausible implementation before a team has agreed on what the system is. When nobody externalizes that intent, the generated code becomes the design by default. QA receives the consequences downstream.&lt;/p&gt;

&lt;p&gt;The missing layer is not more code review. It is a shared model between human intent and machine output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three models, three questions
&lt;/h2&gt;

&lt;p&gt;No single technique covers that layer. A useful stack needs to answer three different questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. C4: What exists, and how does it relate?
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://c4model.com/" rel="noopener noreferrer"&gt;C4 model&lt;/a&gt; gives software teams a hierarchy for visualizing a system: context, containers, components, and code. It works like a map with zoom levels. At the widest view, we see the system, its users, and neighboring systems. Zooming in reveals applications, data stores, services, components, and relationships.&lt;/p&gt;

&lt;p&gt;The point is not to produce four mandatory diagrams for every project. The official guidance notes that &lt;a href="https://c4model.com/diagrams" rel="noopener noreferrer"&gt;context and container diagrams are sufficient for many teams&lt;/a&gt;. The point is to make boundaries discussable.&lt;/p&gt;

&lt;p&gt;That matters because generated code is locally persuasive. A service can look complete while its ownership is unclear. An API can look tidy while its trust boundary is invisible. C4 gives development and QA the same structural map before either group has to infer the system from a repository.&lt;/p&gt;

&lt;p&gt;AI can help draft that map from requirements or an existing codebase. It should not get the final word. Humans still need to ask whether the map describes the system they intend to operate.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. TLA+: What may happen, and what must remain true?
&lt;/h3&gt;

&lt;p&gt;C4 shows structure, but structure alone cannot express behavior. It does not tell us which states are valid, which transitions are permitted, or which conditions must survive every interleaving.&lt;/p&gt;

&lt;p&gt;That is where &lt;a href="https://lamport.azurewebsites.net/tla/high-level-view.html" rel="noopener noreferrer"&gt;TLA+&lt;/a&gt; fits. Leslie Lamport describes it as a language for precise, high-level models above the code level, especially for concurrent and distributed systems. Its TLC model checker can explore behaviors and find traces that violate the properties we claim should hold.&lt;/p&gt;

&lt;p&gt;TLA+ forces a different conversation. Instead of asking, “Does this function work?” we ask, “What can the system do from this state, and is every reachable result acceptable?”&lt;/p&gt;

&lt;p&gt;The notation may be formal, but AI can reduce the entry cost: drafting a first specification, translating plain-language promises into candidate invariants, explaining counterexample traces, and helping a team refine the model. The human job is to decide whether those promises are actually the right ones. A model that formalizes the wrong intent is merely precise about the wrong system.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. DST: Does the implementation honor the model?
&lt;/h3&gt;

&lt;p&gt;A correct model does not prove that the production code implements it correctly. We still need the implementation to fight back.&lt;/p&gt;

&lt;p&gt;Deterministic simulation testing, or DST, runs real implementation code in a controlled world. Time, randomness, scheduling, networks, storage, and faults become inputs that a simulator can manipulate. When a generated scenario causes a failure, its seed makes the run reproducible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tigerbeetle/tigerbeetle/blob/main/docs/ARCHITECTURE.md" rel="noopener noreferrer"&gt;TigerBeetle’s VOPR&lt;/a&gt; is a striking example. It can simulate a cluster on a single thread, accelerate time, and inject storage faults. TigerBeetle makes an important distinction in its architecture documentation: model checking can expose errors in an algorithm, while simulation exercises the specific implementation and its underlying assumptions.&lt;/p&gt;

&lt;p&gt;The three layers complement one another:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;C4 maps the system. TLA+ states what must remain true. DST tries to make it false.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A workflow for abundant code
&lt;/h2&gt;

&lt;p&gt;This does not need to become a new ceremony in which teams maintain enormous diagrams and specifications that immediately drift out of date. The models have to participate in the engineering loop.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State the promises in plain language.&lt;/strong&gt; Before generating implementation, write down what the system must always preserve and what it must never permit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Draw the boundaries.&lt;/strong&gt; Use C4 to identify users, external systems, containers, components, data stores, and the relationships where assumptions cross from one owner to another.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Model the risky behavior.&lt;/strong&gt; Use TLA+ where concurrency, ordering, retries, permissions, or state transitions make the promises difficult to reason about informally.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generate from reviewed intent.&lt;/strong&gt; Let AI produce implementation and tests only after people have challenged the structural and behavioral models.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Attack the implementation deterministically.&lt;/strong&gt; Put risky dependencies—time, randomness, scheduling, networks, or storage—under control. Generate hostile scenarios, preserve their seeds, and replay every failure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feed reality back into the models.&lt;/strong&gt; Production observations and simulation failures reveal assumptions the team missed. Update the invariants, then update the implementation and tests. Detect drift rather than allowing the model to become historical decoration.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Not every application needs a simulator as sophisticated as VOPR or a large TLA+ specification. The lightweight version might be one context diagram, one container diagram, five written invariants, a small model for the riskiest transition, and a seeded test harness around it.&lt;/p&gt;

&lt;p&gt;The goal is not maximal formality. It is to give every important assumption an address.&lt;/p&gt;

&lt;h2&gt;
  
  
  Everything is mission-critical to someone
&lt;/h2&gt;

&lt;p&gt;Imagine a grandmother uses AI to vibe-code a family photo album. This is not a financial ledger or a flight-control system. Yet the application makes real promises:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Original photographs must never be destroyed.&lt;/li&gt;
&lt;li&gt;Private photographs must never be exposed accidentally.&lt;/li&gt;
&lt;li&gt;Captions and chronology must survive every edit.&lt;/li&gt;
&lt;li&gt;Two family members must not overwrite each other’s changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of them matter.&lt;/p&gt;

&lt;p&gt;Her C4 model can be small: a person, an application, an identity provider, local storage, cloud storage, and a sharing boundary. Her TLA+ model does not need to describe the entire product; it can focus on concurrent edits, deletion, or permissions. A deterministic harness can simulate two devices going offline, editing the same album, reconnecting in different orders, and retrying interrupted uploads.&lt;/p&gt;

&lt;p&gt;This stack was once associated with mission-critical engineering because rigor was expensive. But AI has changed the economics. If implementation now comes almost freely, why should rigor remain a luxury?&lt;/p&gt;

&lt;p&gt;Criticality is not determined by infrastructure scale. It is determined by the consequence of failure to the person who trusted the system.&lt;/p&gt;

&lt;p&gt;Everything is mission-critical to someone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrieval, not retreat
&lt;/h2&gt;

&lt;p&gt;It is tempting to tell the history of software as a simple decay: once we understood the machine, then we specialized, then we configured packages, and now we prompt a model to do even that for us.&lt;/p&gt;

&lt;p&gt;That story is emotionally recognizable and historically incomplete. Modern developers are not less intelligent, and abstraction is not the enemy. The deeper problem is that valuable disciplines became buried beneath convenience. We kept the outputs while losing contact with some of the reasoning that produced them.&lt;/p&gt;

&lt;p&gt;This is where nostalgia can be useful. Not as a demand to reconstruct an imagined past, but as a diagnostic signal. It tells us that something in the present has become difficult to see or value.&lt;/p&gt;

&lt;p&gt;Computer science has left us breadcrumbs: C4, TLA+, state-machine thinking, deterministic simulators, small composable tools, and decades of systems literature. AI can help excavate that inheritance. It can explain unfamiliar notation, recover architectural knowledge from old code, draft models, generate harnesses, and make specialized techniques approachable to ordinary teams.&lt;/p&gt;

&lt;p&gt;That is retrieval, not retreat.&lt;/p&gt;

&lt;p&gt;The answer to faster code generation may be older, deeper modeling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Humans own the promises
&lt;/h2&gt;

&lt;p&gt;Shared models also repair an organizational failure.&lt;/p&gt;

&lt;p&gt;Without them, a developer hands QA an implementation full of implicit decisions. QA runs the checks it can see. An edge case reaches production, and the organization asks why testing missed it. The assumption moves downstream, and the blame moves with it.&lt;/p&gt;

&lt;p&gt;With a structural map and explicit invariants, QA no longer has to guess what the developer meant. Testers can challenge the promises, identify missing states, design hostile scenarios, and feed new discoveries back into the model. Quality becomes a shared act of reasoning rather than a final gate operated by the last team in line.&lt;/p&gt;

&lt;p&gt;That restores a form of human value AI cannot generate for us. Our value was never only in typing every line. It is in deciding what a system is for, recognizing who can be harmed, making its promises visible, and accepting responsibility when they are broken.&lt;/p&gt;

&lt;p&gt;Fewer people should be able to dismiss a failure by saying, “The AI wrote it.”&lt;/p&gt;

&lt;p&gt;Generation does not transfer responsibility. If we decide what a system is for, accept its output, and release it into someone’s life, the promises it breaks are still ours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI may produce the code. Humans own the promises.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: This article was developed with AI assistance through an iterative editorial process. The argument, examples, editorial direction, and responsibility for accuracy remain with the human author.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>testing</category>
      <category>programming</category>
    </item>
    <item>
      <title>Write down every guarantee before you write any code</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Tue, 11 Aug 2026 03:35:29 +0000</pubDate>
      <link>https://dev.to/copyleftdev/write-down-every-guarantee-before-you-write-any-code-21oi</link>
      <guid>https://dev.to/copyleftdev/write-down-every-guarantee-before-you-write-any-code-21oi</guid>
      <description>&lt;p&gt;Here is every promise a to-do list makes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VARIABLE tasks

Init == tasks = [i \in Ids |-&amp;gt; "absent"]

Add(i)      == tasks[i] = "absent" /\ tasks' = [tasks EXCEPT ![i] = "open"]
Complete(i) == tasks[i] = "open"   /\ tasks' = [tasks EXCEPT ![i] = "done"]
Reopen(i)   == tasks[i] = "done"   /\ tasks' = [tasks EXCEPT ![i] = "open"]
Delete(i)   == tasks[i] # "absent" /\ tasks' = [tasks EXCEPT ![i] = "absent"]

ClearCompleted ==
  /\ \E i \in Ids : tasks[i] = "done"
  /\ tasks' = [i \in Ids |-&amp;gt; IF tasks[i] = "done" THEN "absent" ELSE tasks[i]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not a summary. Not the important ones. &lt;strong&gt;All of them.&lt;/strong&gt; A task cannot go from&lt;br&gt;
absent straight to done. Clearing completed items leaves the open ones alone.&lt;br&gt;
You cannot delete something that was never there. Nine lines, and when you've&lt;br&gt;
read them you have read the entire contract.&lt;/p&gt;

&lt;p&gt;Now go find that list for the system you work on.&lt;/p&gt;

&lt;p&gt;You can't. It doesn't exist. It's distributed across a test suite that asserts&lt;br&gt;
outcomes rather than rules, some validation scattered through handlers, and the&lt;br&gt;
memory of whoever's been there longest. The guarantees are real — your users&lt;br&gt;
depend on every one of them — and there is no file you can open to see them.&lt;/p&gt;

&lt;p&gt;That's the gap I want to talk about, because you can close it in an afternoon,&lt;br&gt;
and because something has changed recently that makes closing it pay for itself.&lt;/p&gt;
&lt;h2&gt;
  
  
  The prime mark and two operators
&lt;/h2&gt;

&lt;p&gt;That's most of the syntax, so let's get it out of the way.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tasks'&lt;/code&gt; means "tasks, in the next state." &lt;code&gt;/\&lt;/code&gt; is &lt;em&gt;and&lt;/em&gt;. &lt;code&gt;\E&lt;/code&gt; is "there&lt;br&gt;
exists." A definition like &lt;code&gt;Complete(i)&lt;/code&gt; is a formula relating the current state&lt;br&gt;
to the next one — read it out loud: &lt;em&gt;the task is open, and afterwards it is&lt;br&gt;
done.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's it. That's the language, near enough, for this purpose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/copyleftdev/tlatools-rs/tree/main/demo/todo" rel="noopener noreferrer"&gt;The real file&lt;/a&gt; adds about eight lines of scaffolding around what you saw:&lt;br&gt;
a module header, a &lt;code&gt;TypeOK&lt;/code&gt; saying a task is always in exactly one of the three&lt;br&gt;
states, and the two lines that tie the actions together —&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Next == \/ \E i \in Ids : Add(i) \/ Complete(i) \/ Reopen(i) \/ Delete(i)
        \/ ClearCompleted

Spec == Init /\ [][Next]_tasks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Next&lt;/code&gt; is "any one of the moves happens." &lt;code&gt;Spec&lt;/code&gt; is "start legally, and then only&lt;br&gt;
ever make legal moves." That second line turns out to matter more than it looks,&lt;br&gt;
and I'll come back to it.&lt;/p&gt;

&lt;p&gt;Notice what isn't in there. No database. No HTTP. No mention of whether the&lt;br&gt;
button is blue or whether completion is optimistic in the UI. A specification&lt;br&gt;
isn't a program and doesn't compile to one — it's a formula that says which&lt;br&gt;
state changes are permitted. Everything else is out of scope by construction,&lt;br&gt;
which is exactly why the list can be nine lines and still be complete.&lt;/p&gt;

&lt;p&gt;And notice &lt;code&gt;ClearCompleted&lt;/code&gt; has two halves: the button only exists when&lt;br&gt;
something is done, &lt;strong&gt;and&lt;/strong&gt; it leaves everything else alone. Two separate&lt;br&gt;
promises in one action. Hold that thought.&lt;/p&gt;
&lt;h2&gt;
  
  
  The list is short, finite, and worth arguing about
&lt;/h2&gt;

&lt;p&gt;The objection I expect is that a real system's list would be enormous.&lt;/p&gt;

&lt;p&gt;It's smaller than you think, because it's a list of &lt;em&gt;rules&lt;/em&gt;, not behaviours. The&lt;br&gt;
behaviours are combinatorial — nine states here, and a real system has&lt;br&gt;
astronomically many. The rules that generate them are not. Five actions cover&lt;br&gt;
every to-do list that has ever been correct.&lt;/p&gt;

&lt;p&gt;It's also the part of the design worth arguing about. When two engineers&lt;br&gt;
disagree about whether reopening a completed task should be allowed, that&lt;br&gt;
argument currently happens in a code review, in a comment thread, three weeks&lt;br&gt;
after someone already built one of the answers. Written as a spec, the argument&lt;br&gt;
takes four minutes and happens before anyone opens an editor.&lt;/p&gt;

&lt;p&gt;That's the &lt;a href="https://cacm.acm.org/research/how-amazon-web-services-uses-formal-methods/" rel="noopener noreferrer"&gt;AWS result&lt;/a&gt;, really. They wrote up their experience in CACM in&lt;br&gt;
2015 and the headline everyone quotes is about proving systems correct. The part&lt;br&gt;
that actually replicates is quieter: &lt;strong&gt;writing the spec found bugs before any&lt;br&gt;
code existed&lt;/strong&gt; — in systems their best engineers had already designed and&lt;br&gt;
reviewed. Not bugs the tests missed. Bugs the &lt;em&gt;design&lt;/em&gt; had, findable by writing&lt;br&gt;
the guarantees down and reading them back.&lt;/p&gt;

&lt;p&gt;This is forty-year-old technology, and most of us skipped it because it looked&lt;br&gt;
like homework. TLA+ is Leslie Lamport's; the temporal logic underneath it landed&lt;br&gt;
in &lt;a href="https://dl.acm.org/doi/10.1145/177492.177726" rel="noopener noreferrer"&gt;TOPLAS in 1994&lt;/a&gt;, the language and tools got a &lt;a href="https://lamport.azurewebsites.net/tla/book.html" rel="noopener noreferrer"&gt;book in 2002&lt;/a&gt;,&lt;br&gt;
and Lamport picked up the &lt;a href="https://amturing.acm.org/award_winners/lamport_1205376.cfm" rel="noopener noreferrer"&gt;2013 Turing Award&lt;/a&gt; along the way. (Not &lt;em&gt;for&lt;/em&gt;&lt;br&gt;
TLA+, worth saying, since people get this wrong: the citation is logical clocks,&lt;br&gt;
safety and liveness, replicated state machines, sequential consistency. TLA+ is&lt;br&gt;
downstream of that work, not the reason for the medal.)&lt;/p&gt;

&lt;p&gt;Its reputation for being academic is partly earned and mostly out of date. You&lt;br&gt;
do not need the proof system. You do not need to verify anything. You need the&lt;br&gt;
part where you write the guarantees down.&lt;/p&gt;
&lt;h2&gt;
  
  
  What changed
&lt;/h2&gt;

&lt;p&gt;Writing the list has always been worth it and has always been easy to defer,&lt;br&gt;
because the code was going to be written slowly by people who mostly remembered&lt;br&gt;
the rules.&lt;/p&gt;

&lt;p&gt;That is no longer the situation. Something else is writing the code now, quickly,&lt;br&gt;
and it does not remember anything. It has never met your system's rules and has&lt;br&gt;
no way to infer the ones that aren't in the file it's looking at. It will write&lt;br&gt;
something plausible.&lt;/p&gt;

&lt;p&gt;Plausible is the problem. Plausible code passes review — this is where "looks&lt;br&gt;
good to me" comes from, and it was always an honest confession: the reviewer is&lt;br&gt;
reporting that nothing jumped out, because checking against the full set of&lt;br&gt;
invariants was never an option. Nobody had the list.&lt;/p&gt;

&lt;p&gt;So: write the list. Then check the generated code against it, mechanically,&lt;br&gt;
every time. That second half needs a tool.&lt;/p&gt;
&lt;h2&gt;
  
  
  tlatools-rs
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;tlatools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A TLA+ parser and evaluator in Rust. Not a model checker — it doesn't explore&lt;br&gt;
anything. It answers questions about states you already have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Spec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Todo.tla"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;eval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Evaluator&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;eval&lt;/span&gt;&lt;span class="nf"&gt;.holds_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Init"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// legal starting state?&lt;/span&gt;
&lt;span class="n"&gt;eval&lt;/span&gt;&lt;span class="nf"&gt;.step_allowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Next"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// legal step?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The loop is three pieces. &lt;strong&gt;You write the list&lt;/strong&gt; — short, arguable, and it&lt;br&gt;
barely changes. &lt;strong&gt;The agent writes the implementation&lt;/strong&gt; — any language, any&lt;br&gt;
framework, any speed. &lt;strong&gt;A script walks the implementation and asks the list&lt;br&gt;
about every step it takes.&lt;/strong&gt; That third piece is thirty lines: ask the&lt;br&gt;
implementation what it can do, do each of those things, record where you landed,&lt;br&gt;
repeat until nothing new turns up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./check.py impl/correct.py
&lt;span class="go"&gt;The implementation refines the specification.
9 states and 35 steps, all permitted.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nine states because there are two tasks and three states each. A real app has&lt;br&gt;
more, and the walk is the expensive part, not the checking.&lt;/p&gt;
&lt;h2&gt;
  
  
  Two bugs the list catches
&lt;/h2&gt;

&lt;p&gt;Here's an agent-plausible one. The completion handler takes an id and marks it&lt;br&gt;
done. It doesn't check the task was open — why would it, the button only shows&lt;br&gt;
up on open tasks. (The button. Not the handler.)&lt;/p&gt;

&lt;p&gt;This is exactly the bug that survives review. It reads correctly. The missing&lt;br&gt;
check is missing somewhere you aren't looking.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./check.py impl/completes_anything.py
&lt;span class="go"&gt;The implementation takes a step the specification does not permit.

  from   a=absent, b=absent
  doing  complete(a)
  to     a=done, b=absent

The closest the specification came:
  Add(i = "a") was available, but does not produce that state,
    because tasks' = [tasks EXCEPT ![i] = Open] does not hold (1 of its 2 clauses hold)
  Complete(i = "a") was not available here,
    because tasks[i] = Open does not hold (1 of its 2 clauses hold)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second line is the bug, named: &lt;code&gt;Complete&lt;/code&gt; requires the task to be open, and&lt;br&gt;
it wasn't. It's a ranked shortlist rather than a single guess — &lt;code&gt;Add&lt;/code&gt; also nearly&lt;br&gt;
fits from this state, and saying so is more honest than pretending to know which&lt;br&gt;
one you meant.&lt;/p&gt;

&lt;p&gt;Now the other one. &lt;code&gt;ClearCompleted&lt;/code&gt; — the action with two promises. This&lt;br&gt;
implementation keeps the first and breaks the second. It clears the whole list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./check.py impl/clear_removes_everything.py
&lt;span class="go"&gt;  from   a=open, b=done
  doing  clear_completed
  to     a=absent, b=absent

The closest the specification came:
  ClearCompleted was available, but does not produce that state,
&lt;/span&gt;&lt;span class="gp"&gt;    because tasks' = [i \in Ids |-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;IF tasks[i] &lt;span class="o"&gt;=&lt;/span&gt; Done THEN Absent ELSE tasks[i]]
&lt;span class="go"&gt;    does not hold (1 of its 2 clauses hold)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;"Was not available here" versus "was available, but does not produce that&lt;br&gt;
state."&lt;/strong&gt; Different sentences because they're different bugs. One is a missing&lt;br&gt;
guard. The other is a correct guard and a wrong effect — which is worse, because&lt;br&gt;
the button &lt;em&gt;looks&lt;/em&gt; like it works. You'd demo it. You'd ship it. Someone would&lt;br&gt;
lose a task they hadn't finished.&lt;/p&gt;

&lt;p&gt;The tool can tell them apart because it knows which failing clause mentions the&lt;br&gt;
next state. Neither bug is exotic. Both are invisible to a test suite that&lt;br&gt;
checks outcomes, and both are named instantly by a list you wrote in nine lines.&lt;/p&gt;
&lt;h2&gt;
  
  
  Feedback in the language the rule was written in
&lt;/h2&gt;

&lt;p&gt;You cannot fix what you cannot describe, and neither can a model.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Tests failed." — Try again. Randomly.&lt;/li&gt;
&lt;li&gt;"Expected &lt;code&gt;{a: open}&lt;/code&gt;, got &lt;code&gt;{a: absent}&lt;/code&gt;." — Better. Now infer the rule.&lt;/li&gt;
&lt;li&gt;"&lt;code&gt;ClearCompleted&lt;/code&gt; was available, but does not produce that state, because
&lt;code&gt;tasks' = [i \in Ids |-&amp;gt; IF tasks[i] = Done THEN Absent ELSE tasks[i]]&lt;/code&gt; does
not hold." — The action, the condition, and the state it was in.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That third one is a prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And I measured whether it helps an agent, and it didn't — not detectably.&lt;/strong&gt;&lt;br&gt;
200 tasks, each attempted with an uninformative retry and with the failure text&lt;br&gt;
fed back: 90.5% [85.6–93.8] against 92.5% [88.0–95.4], McNemar exact p=0.125.&lt;br&gt;
That is a null. On the formal-reasoning subset the gap was 46.2% → 69.2%, which&lt;br&gt;
looks like something, except n=13 and p=0.25, which means it looks like&lt;br&gt;
something in the way small numbers often do.&lt;/p&gt;

&lt;p&gt;I'm reporting it because I ran it. The honest state of the claim: the mechanism&lt;br&gt;
is sound, the message is strictly more information than a boolean, and I have no&lt;br&gt;
evidence it moves the pass rate. If you were going to adopt this because "agents&lt;br&gt;
do better with good errors" — don't, yet. Adopt it because &lt;strong&gt;you&lt;/strong&gt; now have the&lt;br&gt;
list, and something checks it.&lt;/p&gt;
&lt;h2&gt;
  
  
  The list as a grader
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;tlatools check&lt;/code&gt; takes a JSON job — spec, states, steps, constants — and returns&lt;br&gt;
a verdict with an exit status: &lt;code&gt;0&lt;/code&gt; it refines, &lt;code&gt;1&lt;/code&gt; it doesn't, &lt;code&gt;2&lt;/code&gt; the question&lt;br&gt;
was malformed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tlatools check job.json &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Point it at N candidate implementations and it tells you which satisfy the list&lt;br&gt;
and, for the ones that don't, exactly where they diverge. If you're generating&lt;br&gt;
code, evaluating models, or grading a benchmark, that's a grader with no rubric&lt;br&gt;
to write and no partial credit to argue about. The list &lt;em&gt;is&lt;/em&gt; the rubric.&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;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;init&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;is the starting state legal?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;refines&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;is every step one the spec permits?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;coverage&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;does the implementation reach the outcomes it should?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That third one exists because refinement alone is satisfied perfectly by an&lt;br&gt;
implementation that does nothing. Ask me how I know.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can you trust the checker?
&lt;/h2&gt;

&lt;p&gt;Fair question to ask of anything that grades your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It agrees with the reference implementation.&lt;/strong&gt; Over a labelled corpus of 39&lt;br&gt;
cases — six implementations that must pass, thirty-three seeded bugs that must&lt;br&gt;
each be caught — its verdicts are byte-identical to Java TLC's, including &lt;em&gt;which&lt;/em&gt;&lt;br&gt;
of the three checks catches which bug.&lt;/p&gt;

&lt;p&gt;Getting that diff empty taught me something I'd otherwise have shipped wrong,&lt;br&gt;
and it's the best argument in this article for writing guarantees down precisely.&lt;/p&gt;

&lt;p&gt;Remember &lt;code&gt;Spec == Init /\ [][Next]_tasks&lt;/code&gt;, the line I said would matter. Those&lt;br&gt;
brackets are load-bearing: &lt;code&gt;[Next]_tasks&lt;/code&gt; means &lt;em&gt;&lt;code&gt;Next&lt;/code&gt;, **or nothing changed&lt;/em&gt;**.&lt;br&gt;
Stuttering is always permitted, in every TLA+ specification ever written. I had&lt;br&gt;
been checking bare &lt;code&gt;Next&lt;/code&gt;, so any implementation that idled or retried got&lt;br&gt;
flagged for a step the spec explicitly allows.&lt;/p&gt;

&lt;p&gt;Fixing that made one seeded bug survive: a transfer from a bank account to&lt;br&gt;
itself. Which felt like a regression, until I read the spec again. A&lt;br&gt;
self-transfer nets to zero. It changes nothing. It &lt;strong&gt;is&lt;/strong&gt; a stuttering step, and&lt;br&gt;
the spec says stuttering is fine — so that implementation genuinely satisfies&lt;br&gt;
the list, and the benchmark and I had both been wrong about it. Catching that&lt;br&gt;
one needs an abstraction where the operation is visible in the state at all. You&lt;br&gt;
cannot tighten a refinement check into seeing something the state space doesn't&lt;br&gt;
record.&lt;/p&gt;

&lt;p&gt;Hand TLC the same &lt;code&gt;[Next]_vars&lt;/code&gt; obligation and it passes that mutant too. The&lt;br&gt;
agreement holds; what moved was my understanding of what I'd written down. The&lt;br&gt;
list is only as good as your reading of it, and a tool that disagrees with you&lt;br&gt;
is doing you a favour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It reads the language.&lt;/strong&gt; 1,256 of the 1,258 specifications in three public&lt;br&gt;
TLA+ corpora: the examples repo, the community modules, and the TLA+ tools' own&lt;br&gt;
test suite. The two it doesn't read are two that SANY, the official parser,&lt;br&gt;
doesn't read either. How every one of those files is read is recorded in&lt;br&gt;
&lt;code&gt;golden/&lt;/code&gt;, so a change names the files it changed instead of moving a number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's checked in the boring ways.&lt;/strong&gt; 166 tests, clippy-pedantic clean, and a&lt;br&gt;
robustness suite that feeds back every prefix and every dropped line of every&lt;br&gt;
fixture — because a parser that panics on a half-saved file is a parser you&lt;br&gt;
can't put in a loop. &lt;code&gt;tla-syntax&lt;/code&gt; and &lt;code&gt;tla-eval&lt;/code&gt; have no external dependencies at&lt;br&gt;
all.&lt;/p&gt;

&lt;h2&gt;
  
  
  About TLC, precisely
&lt;/h2&gt;

&lt;p&gt;TLC is the model checker TLA+ ships with. It explores: from your initial state,&lt;br&gt;
apply every action, walk the reachable state space looking for a violation.&lt;br&gt;
That's the right question when you're designing a protocol and don't yet know&lt;br&gt;
what your system can do.&lt;/p&gt;

&lt;p&gt;Here you already have the implementation, so the question is different — are&lt;br&gt;
&lt;em&gt;these&lt;/em&gt; steps, the ones the code just took, permitted by the list?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLC can be asked that.&lt;/strong&gt; I want to be precise, because I had this wrong in an&lt;br&gt;
earlier draft and someone would have caught it: you encode the steps as data,&lt;br&gt;
write a plain safety invariant asserting each one is enabled, and run the&lt;br&gt;
checker. No liveness property, no engineered failure. On the to-do spec it finds&lt;br&gt;
the bad step in 0.78 seconds. There's published work doing this properly —&lt;br&gt;
&lt;a href="https://arxiv.org/abs/2404.16075" rel="noopener noreferrer"&gt;&lt;em&gt;Validating Traces of Distributed Programs Against TLA+ Specifications&lt;/em&gt;&lt;/a&gt;&lt;br&gt;
by Cirstea, Kuppe, Loillier and Merz, and Kuppe maintains the TLA+ tools. If you&lt;br&gt;
want trace validation on a production system, start there.&lt;/p&gt;

&lt;p&gt;What's left is narrower, and true. TLC tells you &lt;em&gt;that&lt;/em&gt; the step is illegal, not&lt;br&gt;
&lt;em&gt;which conjunct&lt;/em&gt; failed. And that 0.78 s is almost entirely JVM boot and SANY&lt;br&gt;
parse, paid again on every query — fine once, not fine in a loop that runs on&lt;br&gt;
every agent edit.&lt;/p&gt;

&lt;p&gt;Structured blame instead of a boolean, at a couple of orders of magnitude less&lt;br&gt;
latency. That's the pitch. These compose; they don't compete.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it won't do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It's not a model checker.&lt;/strong&gt; If you want to know what states your system can
reach, use TLC.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It doesn't verify your program.&lt;/strong&gt; It checks the transitions you hand it. If
your walk misses a path, nothing checks that path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your list can be wrong.&lt;/strong&gt; It's what you argued about, not what's true. I
could have written &lt;code&gt;ClearCompleted&lt;/code&gt; to clear everything, and then the "buggy"
implementation would be the correct one. The list being short and readable is
the only defence, which is an argument for keeping it short and readable.&lt;/li&gt;
&lt;li&gt;Integers are 64-bit, real arithmetic isn't implemented, temporal formulas are
refused rather than guessed at, and TLAPS proofs are skipped.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/copyleftdev/tlatools-rs
&lt;span class="nb"&gt;cd &lt;/span&gt;tlatools-rs
cargo build &lt;span class="nt"&gt;--release&lt;/span&gt;
demo/todo/check.py demo/todo/impl/completes_anything.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The whole demo is &lt;a href="https://github.com/copyleftdev/tlatools-rs/tree/main/demo/todo" rel="noopener noreferrer"&gt;&lt;code&gt;demo/todo&lt;/code&gt;&lt;/a&gt; — the spec above, three implementations,&lt;br&gt;
and the script that checks them. CI runs it on every push, so if it's broken&lt;br&gt;
when you get there, that's a bug and I'd like to hear about it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;crates:&lt;/strong&gt; &lt;a href="https://crates.io/crates/tlatools" rel="noopener noreferrer"&gt;tlatools&lt;/a&gt; · &lt;a href="https://crates.io/crates/tla-eval" rel="noopener noreferrer"&gt;tla-eval&lt;/a&gt; · &lt;a href="https://crates.io/crates/tla-syntax" rel="noopener noreferrer"&gt;tla-syntax&lt;/a&gt; · &lt;a href="https://crates.io/crates/tla-oracle" rel="noopener noreferrer"&gt;tla-oracle&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;source:&lt;/strong&gt; &lt;a href="https://github.com/copyleftdev/tlatools-rs" rel="noopener noreferrer"&gt;github.com/copyleftdev/tlatools-rs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;docs:&lt;/strong&gt; &lt;a href="https://docs.rs/tla-eval" rel="noopener noreferrer"&gt;docs.rs/tla-eval&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have a TLA+ file it reads wrongly, that's the most useful thing you can&lt;br&gt;
send me.&lt;/p&gt;




&lt;p&gt;Start with one. Pick the part of your system where a wrong state change would&lt;br&gt;
actually hurt — the money, the permissions, the thing with a state machine&lt;br&gt;
nobody fully trusts. Write down what it's allowed to do. It'll take an afternoon&lt;br&gt;
and it will be shorter than you expect.&lt;/p&gt;

&lt;p&gt;You'll find something while writing it. Everyone does; that's the AWS result and&lt;br&gt;
it isn't subtle. And then you'll have the file — the one that doesn't exist for&lt;br&gt;
any system you currently work on — and everything written afterwards, by you or&lt;br&gt;
by a machine, can be checked against it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rust</category>
      <category>formalmethods</category>
      <category>testing</category>
    </item>
    <item>
      <title>The Shape of Failure: Before You Blame the AI</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Sat, 01 Aug 2026 21:12:51 +0000</pubDate>
      <link>https://dev.to/copyleftdev/the-shape-of-failure-before-you-blame-the-ai-5358</link>
      <guid>https://dev.to/copyleftdev/the-shape-of-failure-before-you-blame-the-ai-5358</guid>
      <description>&lt;p&gt;Every automated system receives a particular shape of the world.&lt;/p&gt;

&lt;p&gt;That shape is expressed through records, documents, events, exceptions, and missing values. If the designers have not identified those forms—and the ways they can become malformed—the machine inherits their ignorance and reproduces it at scale.&lt;/p&gt;


&lt;div class="crayons-card c-embed"&gt;

  &lt;br&gt;
&lt;strong&gt;The question is not simply whether the AI failed.&lt;/strong&gt;

&lt;p&gt;The useful question is whether the human-built system knew what success meant, knew the shape of its data, and knew how to recognize when it was wrong.&lt;br&gt;

&lt;/p&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Start with the shape of the data
&lt;/h2&gt;

&lt;p&gt;Before selecting a model, draw the workflow as a sequence of data transformations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What enters each stage?&lt;/li&gt;
&lt;li&gt;In what form and from what source?&lt;/li&gt;
&lt;li&gt;Which values are valid, absent, duplicated, stale, delayed, or contradictory?&lt;/li&gt;
&lt;li&gt;How will each violation be detected?&lt;/li&gt;
&lt;li&gt;What must the workflow do next?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each data shape needs a corresponding failure model. An unknown here is not merely uncertainty for the machine; it is a measurement failure in the organization.&lt;/p&gt;

&lt;p&gt;The remedy is to collect the missing data or explicitly design for its absence. Otherwise, the system is being asked to operate in a world its designers have not described.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stabilize the deliverable
&lt;/h2&gt;

&lt;p&gt;A system cannot be stabilized around a target that continues to move.&lt;/p&gt;

&lt;p&gt;The deliverable must be more than an aspiration written in a prompt. It should be expressed as observable conditions and anchored to a representative corpus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;examples that are acceptable;&lt;/li&gt;
&lt;li&gt;examples that are unacceptable;&lt;/li&gt;
&lt;li&gt;examples that are genuinely ambiguous.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Human reviewers should first demonstrate that they can apply those distinctions consistently. If they cannot agree on what success looks like, the model is not being measured against a specification. It is being measured against human disagreement disguised as one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The model is not the system
&lt;/h2&gt;

&lt;p&gt;Only then does it become meaningful to place an AI model inside the workflow.&lt;/p&gt;

&lt;p&gt;The model is one transformation among many:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input
  → validation
  → retrieval
  → normalization
  → model inference
  → output validation
  → policy checks
  → human action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Each transition can discard meaning or introduce error. The fluency of the final response makes the model the most conspicuous suspect, but conspicuousness is not causality.&lt;/p&gt;

&lt;p&gt;To assign blame intelligently, observe the entire chain and test every boundary where information is received or transformed.&lt;/p&gt;
&lt;h2&gt;
  
  
  Mutation testing attacks confidence itself
&lt;/h2&gt;

&lt;p&gt;Conventional tests ask whether software succeeds under conditions its authors anticipated. Mutation testing reverses that pressure.&lt;/p&gt;

&lt;p&gt;It deliberately introduces small faults—reversing a condition, moving a boundary, substituting a value, or removing an operation—and asks whether the test suite notices.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;killed mutant&lt;/strong&gt; caused at least one test to fail.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;surviving mutant&lt;/strong&gt; changed the program without the tests objecting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The resulting score is not proof of correctness. It measures how sensitive the tests are to the generated changes.&lt;/p&gt;

&lt;p&gt;In the companion implementation, the focused safety-contract run produced:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;observed&amp;nbsp;mutation&amp;nbsp;sensitivity&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;43&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;generated&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;43&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;killed&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;That number has meaning only because the measurement boundary is explicit: the run scores the small kernel containing the workflow's acceptance predicates. It does not pretend that prompt punctuation or CLI wording is part of the safety contract.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Why the first mutation run mattered
  &lt;br&gt;
The first broad run generated 374 mutations across the package. Of those, 185 survived. Many changed prompt text, trace wording, and gateway plumbing that the tests did not claim to specify.

&lt;p&gt;That was not an embarrassing result to conceal. It revealed an unstable definition of the deliverable. The mutation boundary was then narrowed to the safety-critical contract, and tests were strengthened around exact acceptance boundaries. The experiment therefore reenacted the article's argument: a metric becomes meaningful only after humans define what is being measured.&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Carry the same pressure through the AI workflow
&lt;/h2&gt;

&lt;p&gt;The mutation principle should not stop at source code.&lt;/p&gt;

&lt;p&gt;Remove an expected field. Corrupt a format. Supply stale or contradictory source material. Interrupt retrieval. Perturb an instruction. Substitute a fluent but incorrect model response.&lt;/p&gt;

&lt;p&gt;At every boundary, ask whether the surrounding system detects the disturbance, abstains, falls back, or routes the case to a human.&lt;/p&gt;

&lt;p&gt;The reference implementation makes this flow explicit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;shape_failures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shape_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;shape_failures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;escalate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shape_failures&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;evidence_failure&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;evidence_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;corpus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;evidence_failure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;escalate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;evidence_failure&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;criticism&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;critic_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;review&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;criticism&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;escalate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;criticism&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The actual implementation uses four deliberately small agents:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A &lt;strong&gt;shape agent&lt;/strong&gt; rejects malformed or unmodeled input.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;evidence agent&lt;/strong&gt; retrieves the matching corpus and detects contradictions.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;model agent&lt;/strong&gt; proposes a structured, cited decision through OpenRouter.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;critic agent&lt;/strong&gt; verifies the decision against citations, confidence thresholds, and a computable policy oracle.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The model is useful, but it is never permitted to define its own success criteria.&lt;/p&gt;
&lt;h2&gt;
  
  
  What the executable experiment found
&lt;/h2&gt;

&lt;p&gt;The checked local verification produced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;86 passing tests;&lt;/li&gt;
&lt;li&gt;43 of 43 mutations killed in the safety-contract kernel;&lt;/li&gt;
&lt;li&gt;one clean control accepted;&lt;/li&gt;
&lt;li&gt;all seven injected data, corpus, and model faults detected;&lt;/li&gt;
&lt;li&gt;zero model calls when bad input or contradictory evidence made inference unsafe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://hypothesis.readthedocs.io/en/latest/stateful.html" rel="noopener noreferrer"&gt;Hypothesis&lt;/a&gt; generates both data and sequences of workflow mutations. &lt;a href="https://mutmut.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;Mutmut&lt;/a&gt; changes the safety-contract source. &lt;a href="https://openrouter.ai/docs/guides/features/structured-outputs" rel="noopener noreferrer"&gt;OpenRouter&lt;/a&gt; supplies the optional live model boundary using a strict JSON Schema response.&lt;/p&gt;

&lt;p&gt;The OpenRouter call is intentionally optional because it uses an external service and may incur cost. The deterministic safety oracle does not depend on network access, a particular provider, or a favorable model response.&lt;/p&gt;
&lt;h2&gt;
  
  
  Agreement is another output, not an oracle
&lt;/h2&gt;

&lt;p&gt;Once the single-model boundary was stable, I added a second weave around it. Four model families received the same structured request and the same policy evidence. Each worked independently: no model saw another model's answer. Every response then crossed the same citation checks, confidence threshold, and computable policy oracle.&lt;/p&gt;

&lt;p&gt;The live run used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;openai/gpt-5.4-nano&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;google/gemini-3.5-flash-lite&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deepseek/deepseek-v4-flash-0731&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mistralai/mistral-small-2603&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eight scenarios produced 32 model observations. Twenty-seven matched the oracle and passed the contract, but only four scenarios achieved unanimous contract acceptance.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;OpenAI&lt;/th&gt;
&lt;th&gt;Gemini&lt;/th&gt;
&lt;th&gt;DeepSeek&lt;/th&gt;
&lt;th&gt;Mistral&lt;/th&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Eligible control&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;0.78&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;accept&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eligible paraphrase&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;0.74&lt;/code&gt;, rejected&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;0.99&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;review&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instruction inside customer data&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;0.74&lt;/code&gt;, rejected&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;escalate &lt;code&gt;0.95&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;review&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Last eligible day&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;0.86&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;deny &lt;code&gt;1.0&lt;/code&gt;, rejected&lt;/td&gt;
&lt;td&gt;review&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maximum eligible amount&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;0.78&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;approve &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;accept&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One day late&lt;/td&gt;
&lt;td&gt;deny &lt;code&gt;0.86&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;deny &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;deny &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;deny &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;accept&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One cent over&lt;/td&gt;
&lt;td&gt;deny &lt;code&gt;0.90&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;deny &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;deny &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;escalate &lt;code&gt;0.99&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;review&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-refundable policy&lt;/td&gt;
&lt;td&gt;deny &lt;code&gt;0.86&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;deny &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;deny &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;deny &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;accept&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is not a leaderboard. It is one small experiment against one explicit contract. Gemini and DeepSeek passed all eight cases in this run. OpenAI selected the oracle action in all eight, but its confidence fell below the human-set &lt;code&gt;0.75&lt;/code&gt; threshold twice. Mistral abstained twice and made one incorrect decision at the exact, inclusive day boundary.&lt;/p&gt;

&lt;p&gt;Those are different failure shapes with different remedies. A wrong boundary decision challenges reasoning or prompt clarity. An abstention challenges workflow capacity and escalation cost. A low-confidence rejection challenges calibration and the threshold chosen by the organization. None can be repaired merely by declaring that three models outvoted the fourth.&lt;/p&gt;


&lt;div class="crayons-card c-embed"&gt;

  &lt;br&gt;
&lt;strong&gt;Agreement measures convergence, not correctness.&lt;/strong&gt;

&lt;p&gt;If every model repeats the same unsupported answer, the deterministic contract must still reject it. If one model dissents for a defensible reason, majority voting must not erase the evidence.&lt;br&gt;

&lt;/p&gt;
&lt;/div&gt;



&lt;p&gt;The weave also exposed instability that a single run would have concealed. In an earlier pass, the same OpenAI model gave the control &lt;code&gt;0.90&lt;/code&gt; confidence instead of &lt;code&gt;0.78&lt;/code&gt;, and escalated the one-day-late case at &lt;code&gt;0.62&lt;/code&gt; instead of denying it at &lt;code&gt;0.86&lt;/code&gt;. Temperature zero reduced one source of variation; it did not turn a remote generative service into a mathematical function.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  A provider failure is not a reasoning failure
  &lt;br&gt;
The pilot included &lt;code&gt;anthropic/claude-haiku-4.5&lt;/code&gt;, but that route failed at the model boundary in all eight requests. The workflow escalated without leaking upstream details. I replaced the route with Mistral for the final decision comparison rather than silently counting eight transport or adapter failures as eight reasoning failures.

&lt;p&gt;That distinction is the thesis again: identify the boundary at which the failure becomes observable before deciding what deserves blame.&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Different models did help us understand more—but only because the data shape, policy oracle, and rejection rules already existed. Without those controls, the experiment would have produced four persuasive rationales and no principled way to interpret their disagreement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/copyleftdev/the-shape-of-failure/tree/main/computational-expression" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Run the single-model and multi-model computational expressions&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  When is it truly an AI failure?
&lt;/h2&gt;

&lt;p&gt;Only after this discipline has been applied does the phrase &lt;em&gt;AI failure&lt;/em&gt; acquire useful meaning.&lt;/p&gt;

&lt;p&gt;If the input was well formed, the deliverable was stable, the supporting components behaved correctly, and the model still violated a known requirement, then the model failed within the conditions established for it.&lt;/p&gt;

&lt;p&gt;But if the data was absent, the target disputed, retrieval defective, or safeguards unable to recognize error, the model may merely be the place where an earlier failure became visible. Calling that an AI failure does not improve the system. It interrupts the feedback by which the organization might learn.&lt;/p&gt;

&lt;p&gt;A generative model is an engine of learned resemblance. It can produce behavior that looks remarkably like understanding, but resemblance cannot carry responsibility. People choose the objective, define acceptable evidence, engineer the transitions, and decide what happens when uncertainty enters the system.&lt;/p&gt;

&lt;p&gt;Before declaring that the AI failed, demonstrate that the system knew what success meant, knew the shape of its world, and knew how to recognize when it was wrong.&lt;/p&gt;

&lt;p&gt;If it did not, the failure began long before the model answered.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The complete experiment includes the agent weave, independent multi-model comparison, property-based tests, stateful tests, mutation configuration, deterministic fault-injection CLI, verification record, and OpenRouter gateway.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>python</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>I Had a Lot of Fun Building a Linux Packet Flight Recorder</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Tue, 28 Jul 2026 00:05:35 +0000</pubDate>
      <link>https://dev.to/copyleftdev/i-had-a-lot-of-fun-building-a-linux-packet-flight-recorder-k44</link>
      <guid>https://dev.to/copyleftdev/i-had-a-lot-of-fun-building-a-linux-packet-flight-recorder-k44</guid>
      <description>&lt;p&gt;Some projects begin with a roadmap. &lt;code&gt;skbx&lt;/code&gt; began with me falling into a Linux&lt;br&gt;
networking rabbit hole and enjoying it much more than I expected.&lt;/p&gt;

&lt;p&gt;The question was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Where did this packet actually go?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer was not.&lt;/p&gt;

&lt;p&gt;A packet can pass through network namespaces, routing decisions, Netfilter,&lt;br&gt;
traffic control, XDP programs, tunnels, clones, copies, and drop paths. A&lt;br&gt;
packet capture at one interface can be completely correct while still showing&lt;br&gt;
only one part of that journey.&lt;/p&gt;

&lt;p&gt;I wanted to see more of the journey. Then I wanted to save what I saw, replay&lt;br&gt;
it later without root, and know whether the capture itself had lost&lt;br&gt;
observations.&lt;/p&gt;

&lt;p&gt;That became &lt;a href="https://github.com/copyleftdev/skbx" rel="noopener noreferrer"&gt;skbx&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;skbx&lt;/code&gt; is a Linux packet-path flight recorder built with Rust and CO-RE eBPF.&lt;/p&gt;

&lt;p&gt;During a live capture, it observes kernel networking functions and writes an&lt;br&gt;
append-only JSONL evidence stream. Afterward, that stream can be replayed and&lt;br&gt;
inspected without loading another eBPF program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;live traffic
    ↓
CO-RE eBPF observations
    ↓
bounded traceq JSONL
    ↓
replay → route patterns → explain an event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It can observe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;kernel functions handling an &lt;code&gt;sk_buff&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;packet clones, copies, copy-on-write, and XDP-to-SKB transitions;&lt;/li&gt;
&lt;li&gt;TC and XDP program entry and exit;&lt;/li&gt;
&lt;li&gt;tunnels and inner packet tuples;&lt;/li&gt;
&lt;li&gt;kernel-reported drop reasons;&lt;/li&gt;
&lt;li&gt;selected BPF helper and map activity;&lt;/li&gt;
&lt;li&gt;capture loss, decoding failures, and output failures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a replacement for tcpdump or Wireshark. Those tools are excellent&lt;br&gt;
when the question is about packet bytes and protocols at a capture point.&lt;br&gt;
&lt;code&gt;skbx&lt;/code&gt; is for questions about the path through the local Linux kernel.&lt;/p&gt;

&lt;p&gt;It is also not the first tool to follow packets through that path. The project&lt;br&gt;
is explicitly inspired by&lt;br&gt;
&lt;a href="https://github.com/cilium/pwru" rel="noopener noreferrer"&gt;pwru&lt;/a&gt;, which showed how useful broad eBPF&lt;br&gt;
packet tracing can be.&lt;/p&gt;

&lt;p&gt;The part I especially wanted to explore was the evidence after the live&lt;br&gt;
terminal stopped scrolling.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why call it a flight recorder?
&lt;/h2&gt;

&lt;p&gt;Live tracing is useful, but incident work often continues after the privileged&lt;br&gt;
session has ended.&lt;/p&gt;

&lt;p&gt;Someone else may need to inspect the capture. We may want to compare it with a&lt;br&gt;
successful request. We may need to cite one exact event in a bug report. An&lt;br&gt;
automation or AI system may need structured input, but it should not be allowed&lt;br&gt;
to invent observations that were never captured.&lt;/p&gt;

&lt;p&gt;So the native &lt;code&gt;skbx&lt;/code&gt; stream, called &lt;code&gt;traceq&lt;/code&gt;, has an envelope:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;capture_start
event
event
...
capture_end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Every event receives a stable handle:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event:111111111111111111111111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Replay groups ordered events into bounded route patterns, which receive their&lt;br&gt;
own handles:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;route:1c0201e74424e253f8363577
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The footer matters as much as the events. It records the stop reason and&lt;br&gt;
reliability counters for kernel reservation failures, tracer recursion misses,&lt;br&gt;
read failures, userspace decoding and enrichment failures, and output&lt;br&gt;
failures.&lt;/p&gt;

&lt;p&gt;If the footer is absent, the artifact is incomplete. If the tracer lost&lt;br&gt;
observations, that uncertainty stays attached to the result.&lt;/p&gt;

&lt;p&gt;I like this property because tracing software is also software. It should not&lt;br&gt;
silently act omniscient.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing it
&lt;/h2&gt;

&lt;p&gt;The live tracer currently supports Linux on x86_64 and arm64. It needs Rust&lt;br&gt;
1.85 or newer, Clang/LLVM with the BPF backend, &lt;code&gt;bpftool&lt;/code&gt;, libelf, libpcap, and&lt;br&gt;
a kernel exposing &lt;code&gt;/sys/kernel/btf/vmlinux&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On Ubuntu, the native packages are:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"linux-tools-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  clang llvm libelf-dev libpcap-dev pkg-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;On Debian:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  bpftool clang llvm libelf-dev libpcap-dev pkg-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then install the CLI directly from GitHub:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--git&lt;/span&gt; https://github.com/copyleftdev/skbx &lt;span class="nt"&gt;--locked&lt;/span&gt; skbx-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Before attaching anything, &lt;code&gt;doctor&lt;/code&gt; checks the host:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;skbx doctor &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;plan&lt;/code&gt; goes one step further. It shows exactly which functions would be&lt;br&gt;
attached without performing the attachment:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;skbx plan &lt;span class="nt"&gt;--filter-func&lt;/span&gt; &lt;span class="s1"&gt;'ip.*'&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That separation turned out to be useful while building the project. A missing&lt;br&gt;
kernel capability should be visible before a privileged capture begins, not&lt;br&gt;
silently approximated afterward.&lt;/p&gt;
&lt;h2&gt;
  
  
  Capturing a first packet
&lt;/h2&gt;

&lt;p&gt;Here is a small ICMP capture:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;skbx capture &lt;span class="nt"&gt;--probe&lt;/span&gt; ip_rcv &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--duration&lt;/span&gt; 10 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; trace.jsonl &lt;span class="se"&gt;\&lt;/span&gt;
  icmp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;While it runs, create some traffic in another terminal:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping &lt;span class="nt"&gt;-c&lt;/span&gt; 3 1.1.1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The capture is deliberately bounded. It has a finite duration and event limit&lt;br&gt;
instead of assuming that an unbounded trace is safe.&lt;/p&gt;

&lt;p&gt;After it finishes, replay does not require root:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;skbx replay trace.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Replay summarizes the functions, processes, packet identities, route patterns,&lt;br&gt;
consensus, outliers, and reliability state. Given the same valid JSONL input,&lt;br&gt;
it produces a byte-identical summary.&lt;/p&gt;

&lt;p&gt;If an event looks interesting, retrieve it with its surrounding same-packet&lt;br&gt;
evidence:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;skbx explain trace.jsonl event:&amp;lt;handle&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The repository includes a small contract fixture containing an &lt;code&gt;ip_rcv&lt;/code&gt; event&lt;br&gt;
followed by &lt;code&gt;kfree_skb_reason&lt;/code&gt;. Replaying that fixture produces a route shaped&lt;br&gt;
like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"handle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"route:1c0201e74424e253f8363577"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"functions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"ip_rcv"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"kfree_skb_reason"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"truncated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"outlier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That output was generated by the current CLI from the checked-in test fixture;&lt;br&gt;
it is not illustrative pseudodata.&lt;/p&gt;
&lt;h2&gt;
  
  
  Use case: what happened to a website request?
&lt;/h2&gt;

&lt;p&gt;This is the use case I keep returning to.&lt;/p&gt;

&lt;p&gt;Suppose &lt;code&gt;curl&lt;/code&gt; starts an HTTPS request and eventually times out. A capture on&lt;br&gt;
the client can answer questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did the request enter the local TCP and IP output paths?&lt;/li&gt;
&lt;li&gt;Which interfaces and namespaces were associated with it?&lt;/li&gt;
&lt;li&gt;Was its mark changed?&lt;/li&gt;
&lt;li&gt;Did a TC or XDP program handle it?&lt;/li&gt;
&lt;li&gt;Was it transformed or placed into a tunnel?&lt;/li&gt;
&lt;li&gt;Did the local kernel report a drop?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That evidence can clear or implicate the client host.&lt;/p&gt;

&lt;p&gt;It cannot prove what happened inside the ISP or on the target server. To prove&lt;br&gt;
those parts, we need observations from those vantage points. That limitation&lt;br&gt;
is important: the absence of a local drop is not proof that a remote host&lt;br&gt;
received the packet.&lt;/p&gt;

&lt;p&gt;The useful result is a smaller, evidence-backed search area:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;client host evidence
        ↓
observed departure boundary
        ↓
ISP / transit inference
        ↓
target-host evidence, if available
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I would rather know exactly where my evidence ends than have a tool produce a&lt;br&gt;
confident story about systems it could not observe.&lt;/p&gt;
&lt;h2&gt;
  
  
  Use case: a packet disappears inside the host
&lt;/h2&gt;

&lt;p&gt;“The network dropped it” can hide several very different failures.&lt;/p&gt;

&lt;p&gt;A host may reject a packet through a normal kernel path. A TC classifier or&lt;br&gt;
XDP program may return a drop action. A packet may be consumed during teardown.&lt;br&gt;
A transformation may cause the packet we were following to continue under a&lt;br&gt;
different kernel object.&lt;/p&gt;

&lt;p&gt;For focused TCP drop questions, a small bpftrace program may be the fastest&lt;br&gt;
answer. For packet contents, I still reach for tcpdump or Wireshark.&lt;/p&gt;

&lt;p&gt;I reach for &lt;code&gt;skbx&lt;/code&gt; when I do not yet know which local subsystem owns the&lt;br&gt;
failure, or when I want to preserve the ordered path rather than one drop&lt;br&gt;
event.&lt;/p&gt;
&lt;h2&gt;
  
  
  Use case: follow transformations instead of losing the trail
&lt;/h2&gt;

&lt;p&gt;Linux does not promise that one logical packet corresponds to one&lt;br&gt;
&lt;code&gt;struct sk_buff&lt;/code&gt; address for its entire lifetime.&lt;/p&gt;

&lt;p&gt;Packets can be cloned, copied, or changed through copy-on-write. XDP frames can&lt;br&gt;
later become SKBs. Tunnels introduce outer and inner packet identities.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;skbx&lt;/code&gt; uses bounded, capture-local lineage state to connect those transitions.&lt;br&gt;
The provenance remains explicit: an event records whether it matched the&lt;br&gt;
original filter or was included because it belonged to a packet already being&lt;br&gt;
tracked.&lt;/p&gt;

&lt;p&gt;For example, a marked packet can be followed with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;skbx capture &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--filter-mark&lt;/span&gt; 0x2a &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--filter-track-skb&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; trace.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The important word here is &lt;em&gt;capture-local&lt;/em&gt;. A lineage identifier is not a&lt;br&gt;
distributed trace ID, and it should not be presented as one.&lt;/p&gt;
&lt;h2&gt;
  
  
  Use case: capture once, investigate without root
&lt;/h2&gt;

&lt;p&gt;Loading and attaching eBPF programs is privileged work. Reading a JSONL file&lt;br&gt;
does not need to be.&lt;/p&gt;

&lt;p&gt;That makes a simple handoff possible:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An operator checks the plan and performs a bounded capture.&lt;/li&gt;
&lt;li&gt;The capture ends and writes its reliability footer.&lt;/li&gt;
&lt;li&gt;The artifact is copied to a normal development or analysis environment.&lt;/li&gt;
&lt;li&gt;Another person replays it and cites exact &lt;code&gt;event:&lt;/code&gt; or &lt;code&gt;route:&lt;/code&gt; handles.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is useful for incident handoffs and bug reports, but it is also useful for&lt;br&gt;
learning. I can capture a small experiment once and inspect it repeatedly&lt;br&gt;
without keeping probes attached while I try to understand the result.&lt;/p&gt;
&lt;h2&gt;
  
  
  Use case: give an AI evidence instead of a mystery
&lt;/h2&gt;

&lt;p&gt;One of my stranger motivations was making the CLI friendly to both operators&lt;br&gt;
and software agents.&lt;/p&gt;

&lt;p&gt;Before touching the host, an agent can ask the executable what it supports:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;skbx describe &lt;span class="nt"&gt;--format&lt;/span&gt; json
skbx schema
skbx doctor &lt;span class="nt"&gt;--json&lt;/span&gt;
skbx plan &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The native engine remains the source of truth. An AI system may summarize a&lt;br&gt;
route or explain a captured event, but the event must already exist in the&lt;br&gt;
trace. Machine output stays on standard output, diagnostics stay on standard&lt;br&gt;
error, and unsupported capabilities remain explicit.&lt;/p&gt;

&lt;p&gt;This does not make an AI explanation automatically correct. It gives the&lt;br&gt;
explanation something concrete to cite and gives a human a way to check it.&lt;/p&gt;
&lt;h2&gt;
  
  
  The engineering parts I enjoyed
&lt;/h2&gt;

&lt;p&gt;The obvious fun was seeing packets move through functions I had previously&lt;br&gt;
treated as boxes in a diagram.&lt;/p&gt;

&lt;p&gt;The less obvious fun was designing the boundaries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;discovering valid &lt;code&gt;struct sk_buff *&lt;/code&gt; arguments from the target kernel's BTF
instead of guessing from function names;&lt;/li&gt;
&lt;li&gt;keeping kernel-side state and work bounded;&lt;/li&gt;
&lt;li&gt;moving JSON encoding, symbolization, and filesystem work out of the eBPF hot
path;&lt;/li&gt;
&lt;li&gt;making probe planning inspectable before attachment;&lt;/li&gt;
&lt;li&gt;separating raw observation from later explanation;&lt;/li&gt;
&lt;li&gt;treating partial output as incomplete instead of “probably good enough”;&lt;/li&gt;
&lt;li&gt;making replay deterministic enough to use in tests and automation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those constraints made the tool more interesting to build. They also gave me a&lt;br&gt;
better mental model of what an observability tool can honestly claim.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it does not know
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;skbx&lt;/code&gt; only observes what the running kernel and selected probes expose.&lt;/p&gt;

&lt;p&gt;It does not see inside an ISP. It does not see a remote host unless it runs&lt;br&gt;
there too. It is not a packet-content replacement for Wireshark. Kernel&lt;br&gt;
configuration, BTF availability, permissions, hidden addresses, unsupported&lt;br&gt;
signatures, and capture loss can all limit the evidence.&lt;/p&gt;

&lt;p&gt;Those limitations are part of the interface rather than footnotes.&lt;/p&gt;

&lt;p&gt;I am still exploring where this project is most useful. The best next input is&lt;br&gt;
not “looks cool,” although I will happily take that. It is a packet path the&lt;br&gt;
tool cannot explain yet, together with the kernel version, exact command,&lt;br&gt;
&lt;code&gt;doctor --json&lt;/code&gt; output, and reliability footer.&lt;/p&gt;

&lt;p&gt;The source, installation instructions, architecture notes, and field guides&lt;br&gt;
are in the repository:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/copyleftdev" rel="noopener noreferrer"&gt;
        copyleftdev
      &lt;/a&gt; / &lt;a href="https://github.com/copyleftdev/skbx" rel="noopener noreferrer"&gt;
        skbx
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Agent-first Linux packet-path tracing with Rust/eBPF: bounded evidence, deterministic replay, and packet routes with receipts.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/copyleftdev/skbx/assets/skbx-banner.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fcopyleftdev%2Fskbx%2FHEAD%2Fassets%2Fskbx-banner.svg" alt="skbx — packet paths, with receipts" width="100%"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;a href="https://github.com/copyleftdev/skbx/actions/workflows/ci.yml" rel="noopener noreferrer"&gt;&lt;img alt="CI" src="https://github.com/copyleftdev/skbx/actions/workflows/ci.yml/badge.svg"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/copyleftdev/skbx/LICENSE" rel="noopener noreferrer"&gt;&lt;img alt="License: AGPL-3.0-or-later" src="https://camo.githubusercontent.com/b2e30aa49de2b7e9ed97c80fef29aa69b83dfa9107727a161410eb683f8b5982/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4147504c2d2d332e302d2d6f722d2d6c617465722d633866363662"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/254bab6b138d90ff96803f899a8402f6bcf45c4d90545dafdc1ae7b8b9fd029c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d4c696e75782d356465346430"&gt;&lt;img alt="Linux" src="https://camo.githubusercontent.com/254bab6b138d90ff96803f899a8402f6bcf45c4d90545dafdc1ae7b8b9fd029c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d4c696e75782d356465346430"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/acab62d447ccb697fec83a4c79b65ed6c1a46df4a749c4fa9a6ba8196ddcc601/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f727573742d312e38352532422d396238636666"&gt;&lt;img alt="Rust 1.85+" src="https://camo.githubusercontent.com/acab62d447ccb697fec83a4c79b65ed6c1a46df4a749c4fa9a6ba8196ddcc601/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f727573742d312e38352532422d396238636666"&gt;&lt;/a&gt;
  &lt;a href="https://tokentip.to/@copyleftdev" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Tip my tokens" src="https://camo.githubusercontent.com/f92620b71c800bad06aa383e6121303dcec9489bc3dc37885d99b2cae8cacb71/68747470733a2f2f746f6b656e7469702e746f2f62616467652f636f70796c6566746465762e7376673f6c6f676f3d31"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;skbx&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code&gt;skbx&lt;/code&gt; shows where a packet went inside Linux—and keeps the receipts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://copyleftdev.github.io/skbx/" rel="nofollow noopener noreferrer"&gt;Follow a packet through the flight recorder →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Field guides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://copyleftdev.github.io/skbx/guides/trace-a-website-request.html" rel="nofollow noopener noreferrer"&gt;Trace a website request across your Linux host, ISP, and target&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://copyleftdev.github.io/skbx/guides/debug-linux-packet-drops.html" rel="nofollow noopener noreferrer"&gt;Debug a Linux packet drop with replayable eBPF evidence&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It observes kernel networking functions, TC/XDP programs, packet
transformations, tunnels, drops, and selected BPF helper activity with
Rust and CO-RE eBPF. Every observation lands in a bounded, replayable evidence
stream with stable handles and explicit loss telemetry.&lt;/p&gt;
&lt;p&gt;Use it when “the packet disappeared” is not a sufficient incident report.&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;capture → event:8c6f… → replay → route:21b4… → explain
            evidence          pattern          context
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Inspired by &lt;a href="https://github.com/cilium/pwru" rel="noopener noreferrer"&gt;pwru&lt;/a&gt;, rebuilt around an
agent-first contract: deterministic observations, machine-readable
capabilities, bounded state, and no invented evidence.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;The short version&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You need to…&lt;/th&gt;
&lt;th&gt;skbx gives you…&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;See the kernel path of an SKB&lt;/td&gt;
&lt;td&gt;BTF-discovered kprobes with exact function evidence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Follow clones, copies, COW, and XDP-to-SKB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/copyleftdev/skbx" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;If you try it, I would love to know which networking question you used it to&lt;br&gt;
answer—and where its evidence stopped.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;AI-assistance disclosure: I built and tested &lt;code&gt;skbx&lt;/code&gt;. I used OpenAI Codex to&lt;br&gt;
research adjacent writing, challenge the article's positioning, edit this&lt;br&gt;
draft, verify its commands and example output against the repository, and&lt;br&gt;
generate the cover illustration. I reviewed the technical claims and remain&lt;br&gt;
responsible for their accuracy.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>networking</category>
      <category>ai</category>
      <category>devops</category>
    </item>
    <item>
      <title>389 Tests Passed. NIST Still Caught the Bug.</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Sat, 25 Jul 2026 06:17:51 +0000</pubDate>
      <link>https://dev.to/copyleftdev/389-tests-passed-nist-still-caught-the-bug-37jh</link>
      <guid>https://dev.to/copyleftdev/389-tests-passed-nist-still-caught-the-bug-37jh</guid>
      <description>&lt;p&gt;I gave an AI agent a calculator because I wanted one hard, inspectable point&lt;br&gt;
inside a probabilistic workflow.&lt;/p&gt;

&lt;p&gt;The model could interpret the request and explain the result. The calculator&lt;br&gt;
would perform the computation. It seemed like a clean division of labor.&lt;/p&gt;

&lt;p&gt;Then I changed one multiplication sign into addition.&lt;/p&gt;

&lt;p&gt;The calculator still passed 389 of the 390 tests in its Rust library harness.&lt;br&gt;
The sole failure compared its answer with NIST's certified results for the&lt;br&gt;
Longley regression dataset.&lt;/p&gt;

&lt;p&gt;That bothered me more than a completely broken build would have. I had treated&lt;br&gt;
deterministic computation as safer than asking a language model to improvise&lt;br&gt;
arithmetic. But deterministic does not mean trustworthy. A program can return&lt;br&gt;
the same wrong answer forever.&lt;/p&gt;

&lt;p&gt;“Source of truth” suddenly felt too comfortable. Before an AI agent delegates&lt;br&gt;
authority to a tool, that authority should be challenged—and remain revocable&lt;br&gt;
by evidence.&lt;/p&gt;

&lt;p&gt;The calculator is only the specimen. The larger idea is a way to place&lt;br&gt;
inspectable, replayable instruments inside probabilistic systems.&lt;/p&gt;
&lt;h2&gt;
  
  
  The useful boundary is generation versus execution
&lt;/h2&gt;

&lt;p&gt;The interesting distinction is not model weights versus a “real CPU.” Model&lt;br&gt;
inference also runs on processors, and language models can learn genuine&lt;br&gt;
arithmetic procedures. The useful boundary is between &lt;strong&gt;generating an answer&lt;/strong&gt;&lt;br&gt;
and &lt;strong&gt;executing a defined operation under a tested contract&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Research on &lt;a href="https://proceedings.mlr.press/v202/gao23f.html" rel="noopener noreferrer"&gt;Program-Aided Language Models&lt;br&gt;
(PAL)&lt;/a&gt; makes a related split:&lt;br&gt;
the language model reads and decomposes a natural-language problem, while a&lt;br&gt;
runtime such as a Python interpreter executes the generated program. The model&lt;br&gt;
contributes flexible interpretation; the runtime contributes executable&lt;br&gt;
semantics.&lt;/p&gt;

&lt;p&gt;That is the division I want in an agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At the &lt;strong&gt;semantic edge&lt;/strong&gt;, the model interprets the request, chooses a
procedure, identifies relevant quantities, and explains the result.&lt;/li&gt;
&lt;li&gt;At the &lt;strong&gt;computational edge&lt;/strong&gt;, a narrow tool validates inputs, applies
specified operations, enforces limits, and returns structured output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This does not make the whole agent deterministic, and it does not make the&lt;br&gt;
model unnecessary. The agent can still choose the wrong tool, supply the wrong&lt;br&gt;
arguments, misunderstand units, or misread the result.&lt;/p&gt;

&lt;p&gt;The promise is smaller: one claim becomes inspectable, replayable, and&lt;br&gt;
independently testable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The opposite of probabilistic is not trustworthy. It is repeatable.&lt;/p&gt;

&lt;p&gt;A CPU can be precisely wrong.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Why NIST became my external witness
&lt;/h2&gt;

&lt;p&gt;Calibration cannot be entirely self-referential. The implementation should not&lt;br&gt;
be the sole author of its own expected answers.&lt;/p&gt;

&lt;p&gt;That is why I chose NIST—not because government authority turns a result into&lt;br&gt;
mathematical truth, but because NIST has a long institutional practice of&lt;br&gt;
building shared, independently evaluated references.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.nist.gov/pml/owm/about-owm/owm-background-and-history" rel="noopener noreferrer"&gt;Congress established the National Bureau of Standards in&lt;br&gt;
1901&lt;/a&gt; to&lt;br&gt;
strengthen the United States' measurement infrastructure. The &lt;a href="https://www.nist.gov/srd/srd-definition" rel="noopener noreferrer"&gt;Standard&lt;br&gt;
Reference Data Act of&lt;br&gt;
1968&lt;/a&gt; authorized a federal program to&lt;br&gt;
collect, critically evaluate, publish, and distribute standardized scientific&lt;br&gt;
and technical reference data. NBS &lt;a href="https://www.nist.gov/timeline" rel="noopener noreferrer"&gt;became NIST in&lt;br&gt;
1988&lt;/a&gt;. In 1999, that lineage reached statistical&lt;br&gt;
software through the &lt;a href="https://www.itl.nist.gov/div898/strd/" rel="noopener noreferrer"&gt;Statistical Reference Datasets&lt;br&gt;
project&lt;/a&gt;, usually shortened to StRD.&lt;/p&gt;

&lt;p&gt;StRD pairs datasets with certified expected values for specific statistical&lt;br&gt;
procedures. Its collection includes generated and real-world cases of varying&lt;br&gt;
difficulty. For linear procedures, NIST carried &lt;a href="https://www.nist.gov/itl/sed/products-services/statistical-reference-data-sets-strd" rel="noopener noreferrer"&gt;500 digits through its&lt;br&gt;
calculations&lt;/a&gt;&lt;br&gt;
so ordinary floating-point representation error would not become the&lt;br&gt;
benchmark.&lt;/p&gt;

&lt;p&gt;Longley is a small but numerically challenging linear-regression dataset in&lt;br&gt;
that collection. Its certified results gave my tests something the&lt;br&gt;
implementation could not manufacture for itself: an expected answer produced&lt;br&gt;
outside the code under test.&lt;/p&gt;

&lt;p&gt;That qualification matters. StRD does &lt;strong&gt;not&lt;/strong&gt; certify Oddly Exact, prove the&lt;br&gt;
statistics engine correct, or make the software traceable to NIST. NIST&lt;br&gt;
explicitly says the datasets are an aid for evaluating software and that &lt;a href="https://www.itl.nist.gov/div898/strd/general/faq.html" rel="noopener noreferrer"&gt;no&lt;br&gt;
mechanism establishes software&lt;br&gt;
traceability&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The reference data was not an oracle for the entire program. It was an&lt;br&gt;
independent witness for the calculations it covered.&lt;/p&gt;
&lt;h2&gt;
  
  
  Test the tests
&lt;/h2&gt;

&lt;p&gt;Example-based tests ask whether familiar inputs still produce familiar&lt;br&gt;
outputs. Mutation testing asks a more uncomfortable question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If I introduce a small, plausible defect, does the suite notice?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I used &lt;code&gt;cargo-mutants&lt;/code&gt; to replace multiplication with addition in the&lt;br&gt;
multiple-regression standard-error calculation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- residual_std_dev * sum_sq.sqrt()
&lt;/span&gt;&lt;span class="gi"&gt;+ residual_std_dev + sum_sq.sqrt()
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The mutation preserved valid Rust, valid types, and a plausible-looking numeric&lt;br&gt;
result. In the library harness, 389 of 390 tests still passed. The assertion&lt;br&gt;
against NIST's Longley values was the sole failure.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://gist.github.com/copyleftdev/277e48079658f6f89deb2254701ebcf7" rel="noopener noreferrer"&gt;public mutation&lt;br&gt;
record&lt;/a&gt;&lt;br&gt;
preserves the exact command, environment, result, and the limit of what that&lt;br&gt;
experiment establishes:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;I cannot claim Longley was the only test in the entire repository capable of&lt;br&gt;
catching the mutation; the run stopped after the failed library harness. I can&lt;br&gt;
claim something narrower and more useful: hundreds of tests tolerated a&lt;br&gt;
semantically broken formula, while an assertion anchored to independently&lt;br&gt;
produced values rejected it.&lt;/p&gt;

&lt;p&gt;A green test count is evidence only to the extent that those tests would turn&lt;br&gt;
red when the implementation meaningfully changes. Mutation testing measures&lt;br&gt;
that sensitivity instead of admiring the count.&lt;/p&gt;
&lt;h2&gt;
  
  
  Challenge the contract around the answer
&lt;/h2&gt;

&lt;p&gt;The formula mutation challenged numerical meaning. My next audit challenged&lt;br&gt;
the promises around the calculation: what the tool accepts, what it refuses,&lt;br&gt;
and how much work it will perform.&lt;/p&gt;

&lt;p&gt;The first crack was a contradiction between the advertised contract and the&lt;br&gt;
executable one. The generated JSON Schema forbade additional properties, but&lt;br&gt;
the Rust deserializer silently accepted an unknown field at the request root&lt;br&gt;
and another inside an expression node.&lt;/p&gt;

&lt;p&gt;The answer was still numerically correct. That did not make the behavior&lt;br&gt;
harmless. A caller validating against the schema saw a stricter instrument than&lt;br&gt;
a caller speaking directly to the binary. A misspelled or misunderstood field&lt;br&gt;
could disappear without warning.&lt;/p&gt;

&lt;p&gt;For an agent-facing tool, silently interpreting a different contract is itself&lt;br&gt;
a correctness defect.&lt;/p&gt;

&lt;p&gt;The second crack was a resource boundary. The expression engine limited things&lt;br&gt;
such as integer size, expression depth, and precision. The optimization&lt;br&gt;
interface, however, accepted grid resolution and iteration counts without upper&lt;br&gt;
ceilings.&lt;/p&gt;

&lt;p&gt;I requested a grid search with one billion sample points. The pre-repair binary&lt;br&gt;
produced no JSON before an external one-second watchdog terminated it. The tool&lt;br&gt;
had input validation, but it had not earned the bounded-work guarantee I&lt;br&gt;
thought I had built.&lt;/p&gt;

&lt;p&gt;Those failures became permanent regression requests. The deserializer now&lt;br&gt;
rejects unknown fields at both levels. The optimizer now publishes and enforces&lt;br&gt;
ceilings of 100,000 iterations and 1,000,000 grid points. The same billion-point&lt;br&gt;
request returns a typed &lt;code&gt;resource_limit&lt;/code&gt; response before entering the search.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://gist.github.com/copyleftdev/28ed6931c6174099b21db54846f72b65" rel="noopener noreferrer"&gt;contract challenge&lt;br&gt;
Gist&lt;/a&gt;&lt;br&gt;
is a runnable replay of all three repaired cases:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;That script is more valuable than a screenshot of a green run. It lets another&lt;br&gt;
observer cross-examine the boundary directly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Repair is the next claim to attack
&lt;/h2&gt;

&lt;p&gt;A new guard is only another claim until the tests prove they care about it.&lt;/p&gt;

&lt;p&gt;After repairing the optimizer limits, I selected every mutation&lt;br&gt;
&lt;code&gt;cargo-mutants&lt;/code&gt; generated for the two new validators. Eleven mutations tried to&lt;br&gt;
remove the checks, replace them with unconditional success, or alter their&lt;br&gt;
boundary comparisons. The tests caught all eleven.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://gist.github.com/copyleftdev/9b9afe1b1173217d92a4cb0ede2278d0" rel="noopener noreferrer"&gt;focused optimizer mutation&lt;br&gt;
record&lt;/a&gt;&lt;br&gt;
captures the selection and outcome:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;That completed the loop:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;claim → attack → fail → repair → mutate → replay&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If I published only the final green suite, you would see confidence. By&lt;br&gt;
preserving the changed operator, the request that hung, the contract&lt;br&gt;
contradiction, the repair, and the mutations that tried to undo it, I can show&lt;br&gt;
a reason for confidence.&lt;/p&gt;

&lt;p&gt;The scar is part of the calibration record.&lt;/p&gt;

&lt;h2&gt;
  
  
  A five-layer challenge stack for agent tools
&lt;/h2&gt;

&lt;p&gt;Oddly Exact is one calculator, but the method travels. Before giving a narrow&lt;br&gt;
tool authority inside an agent workflow, I now ask five questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Is the contract explicit and executable?&lt;/strong&gt; The schema, parser, runtime,&lt;br&gt;
limits, and failure modes must agree. Documentation the executable does not&lt;br&gt;
enforce is only a suggestion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Is there an independent reference?&lt;/strong&gt; In this statistical case, NIST StRD&lt;br&gt;
moved selected expected answers outside my implementation. Another domain&lt;br&gt;
might use a standards specification, a reference implementation, a verified&lt;br&gt;
corpus, or a separately derived test oracle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Which properties should survive across many inputs?&lt;/strong&gt; Property-based tests&lt;br&gt;
generate cases and check laws rather than memorizing individual examples.&lt;br&gt;
One Oddly Exact property checks that translating every value in a sample by&lt;br&gt;
a large exact offset leaves sample variance unchanged within a tight&lt;br&gt;
floating-point tolerance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Can the tests detect plausible corruption?&lt;/strong&gt; Mutation testing changes&lt;br&gt;
operators, comparisons, return values, and guards. A surviving mutation does&lt;br&gt;
not prove the implementation is wrong; it exposes a behavior change the&lt;br&gt;
suite cannot currently distinguish.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Are failures bounded, typed, and replayable?&lt;/strong&gt; An agent must distinguish a&lt;br&gt;
rejected computation from an unavailable tool. Division by zero, resource&lt;br&gt;
exhaustion, malformed JSON, and a crashed process should not collapse into&lt;br&gt;
the same ambiguous failure.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These layers do different jobs. External references challenge specific&lt;br&gt;
answers. Properties challenge behavior across an input space. Mutations&lt;br&gt;
challenge the tests themselves. Contract and resource attacks challenge the&lt;br&gt;
boundary around all of it.&lt;/p&gt;

&lt;p&gt;None provides universal correctness. Together they create a narrower and more&lt;br&gt;
useful result: evidence that a particular tool deserves provisional authority&lt;br&gt;
for validated requests inside a declared contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  A source under challenge
&lt;/h2&gt;

&lt;p&gt;For a validated request inside that contract, the tool's structured result can&lt;br&gt;
serve as the agent's operational source of truth.&lt;/p&gt;

&lt;p&gt;That is a runtime role, not a claim of infallibility. If the agent encounters a&lt;br&gt;
disagreement, it can inspect the arguments, surface the conflict, or consult&lt;br&gt;
another independently trusted tool. It should not quietly replace a structured&lt;br&gt;
result with fresh prose arithmetic.&lt;/p&gt;

&lt;p&gt;The trust relationship runs in opposite directions at different times:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;While building the tool, the developer should distrust it aggressively.&lt;/li&gt;
&lt;li&gt;Inside a contract the tool has earned, the agent should respect its answer or
its typed refusal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;New evidence can always return the tool to the first phase. That is a &lt;strong&gt;source&lt;br&gt;
under challenge&lt;/strong&gt;: trusted in operation, open to appeal, and always one&lt;br&gt;
counterexample away from revision.&lt;/p&gt;

&lt;p&gt;The beautiful thing is not that source code is truth.&lt;/p&gt;

&lt;p&gt;The beautiful thing is that source code can be cross-examined.&lt;/p&gt;

&lt;p&gt;I did not end this experiment with a calculator an AI agent can trust forever.&lt;br&gt;
I ended it with something more useful: &lt;a href="https://github.com/copyleftdev/agent-calc" rel="noopener noreferrer"&gt;a calculator whose authority can be&lt;br&gt;
revoked by evidence&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;AI tools assisted with editorial research and revision. I verified the&lt;br&gt;
technical claims and stand behind the final text.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>tooling</category>
      <category>rust</category>
    </item>
    <item>
      <title>Give Your Coding Agent a Deterministic Vulnerability Oracle</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Tue, 21 Jul 2026 15:04:00 +0000</pubDate>
      <link>https://dev.to/copyleftdev/give-your-coding-agent-a-deterministic-vulnerability-oracle-4ngc</link>
      <guid>https://dev.to/copyleftdev/give-your-coding-agent-a-deterministic-vulnerability-oracle-4ngc</guid>
      <description>&lt;p&gt;AI agents can write code, run tests, inspect dependencies, and open pull requests. But when they encounter a vulnerable package, their security reasoning often collapses into a web search, an opaque API score, or whatever the model remembers from training.&lt;/p&gt;

&lt;p&gt;The problem is not simply missing vulnerability data. It is the contract between the agent and its harness—the automation layer that supplies tools, executes commands, and interprets results. If “no match” silently becomes “safe,” stale intelligence looks current, or a network failure resembles an empty result, the agent can produce a confident answer without trustworthy evidence.&lt;/p&gt;

&lt;p&gt;I designed VulnGraph around a different premise: turn continuously changing vulnerability intelligence into a deterministic local primitive. &lt;a href="https://github.com/copyleftdev/vulngraph-data" rel="noopener noreferrer"&gt;&lt;code&gt;vulngraph-data&lt;/code&gt;&lt;/a&gt; compiles upstream security sources into verified, content-addressed snapshots. &lt;a href="https://github.com/copyleftdev/vulngraph-cli" rel="noopener noreferrer"&gt;&lt;code&gt;vulngraph-cli&lt;/code&gt;&lt;/a&gt; installs those snapshots and checks CVEs, package versions, or entire lockfiles offline.&lt;/p&gt;

&lt;p&gt;The result is a security tool shaped for both humans and machines: an accepted snapshot and target produce the same verdict; every verdict carries typed evidence; stale data fails explicitly; and &lt;code&gt;unknown&lt;/code&gt; is never misrepresented as clean.&lt;/p&gt;

&lt;p&gt;This article explains the design decisions behind that contract and shows how to embed VulnGraph into agent and harness workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  The dangerous gap between “not found” and “safe”
&lt;/h2&gt;

&lt;p&gt;Suppose an agent is reviewing a dependency update. It needs to answer a seemingly simple question: &lt;em&gt;Is this version safe to ship?&lt;/em&gt; A useful answer depends on distinctions that are easy for a harness to erase.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What happened&lt;/th&gt;
&lt;th&gt;A careless harness concludes&lt;/th&gt;
&lt;th&gt;What the contract must preserve&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The package exists and the version is outside every affected range&lt;/td&gt;
&lt;td&gt;No vulnerabilities found&lt;/td&gt;
&lt;td&gt;&lt;code&gt;not-affected&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The package is absent from the dataset&lt;/td&gt;
&lt;td&gt;No vulnerabilities found&lt;/td&gt;
&lt;td&gt;&lt;code&gt;unknown&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The local snapshot is too old&lt;/td&gt;
&lt;td&gt;The last result is probably fine&lt;/td&gt;
&lt;td&gt;A freshness failure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The tool cannot open or verify its data&lt;/td&gt;
&lt;td&gt;Empty result&lt;/td&gt;
&lt;td&gt;An operational or integrity error&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are not cosmetic labels. They lead to different agent actions: proceed, investigate, refresh the data, or stop the workflow. Once a harness flattens them into a Boolean, the model cannot recover the missing meaning through better prompting.&lt;/p&gt;

&lt;p&gt;Here is the distinction in practice. One command checks an exploited CVE, a real package version, and a package the snapshot has never observed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vulngraph check CVE-2024-4577 npm:lodash@4.17.15 npm:no-such-package@1.0.0
&lt;span class="go"&gt;
  CVE-2024-4577
  verdict: ACTIVELY EXPLOITED  (confidence 0.99)
  action:  patch now
  reasons: CRITICAL_SEVERITY, HIGH_EXPLOIT_PROBABILITY,
           KNOWN_EXPLOITED, PUBLIC_EXPLOIT, ...
  cvss:    9.8
  epss:    100.0%
  kev:     listed

  npm:lodash@4.17.15
  verdict: PROOF OF CONCEPT  (confidence 0.96)
  action:  prioritize
  package: npm:lodash — 6 CVE(s) affect this version

  npm:no-such-package@1.0.0
  verdict: UNKNOWN  (confidence 0.00)
  action:  investigate
  reasons: NOT_OBSERVED

  snapshot: sha256:41ee5fbbf58f0a46b99234af89c5388e5f27e0dcd3dbd52298bcd2c2d87ca90e
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output does not ask the agent to infer policy from prose. It supplies a disposition, an action, stable reason codes, confidence, and the exact snapshot that produced the result. The human-readable rendering is useful in a terminal; &lt;code&gt;--json&lt;/code&gt; exposes the same distinctions through a versioned machine envelope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Split changing intelligence from deterministic execution
&lt;/h2&gt;

&lt;p&gt;Vulnerability intelligence changes every day. Agent execution still needs to be reproducible. I separated those concerns instead of allowing every check to fetch and reconcile live data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CVE List V5 · EPSS · CISA KEV · exploit sources · ATT&amp;amp;CK · OSV · …
                              │
                              ▼
                    vulngraph-data
              fetch → normalize → build → verify
                              │
                              ▼
            immutable data-YYYYMMDD release
       manifest + checksums + content snapshot_id
                              │
                  vulngraph update
                              ▼
             verified local snapshot
                              │
          vulngraph check --offline --json
                              ▼
                  agent or harness
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://github.com/copyleftdev/vulngraph-data" rel="noopener noreferrer"&gt;&lt;code&gt;vulngraph-data&lt;/code&gt;&lt;/a&gt; repository owns the nondeterministic edge: retrieving bulk publications from upstream sources and reconciling them into one graph. Its output is deterministic. Identical inputs produce byte-identical semantic files, and their hashes produce a &lt;code&gt;snapshot_id&lt;/code&gt; that names the graph by content. If a daily build has no semantic change, there is no new release.&lt;/p&gt;

&lt;p&gt;The release artifact is the distribution boundary. A consumer does not need the raw source collection or the machinery that built it. It receives a fixed database archive and a manifest recording the snapshot identity, file hashes, source freshness, graph format, and engine revision.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/copyleftdev/vulngraph-cli" rel="noopener noreferrer"&gt;&lt;code&gt;vulngraph-cli&lt;/code&gt;&lt;/a&gt; owns the deterministic side. &lt;code&gt;vulngraph update&lt;/code&gt; downloads a release into a staging area, verifies the archive checksum and every file hash, recomputes the snapshot identity, checks format compatibility, sanity-opens the graph, and only then activates it. Failed updates cannot replace the last verified snapshot.&lt;/p&gt;

&lt;p&gt;After activation, checks do not touch the network. The snapshot becomes an explicit input to the decision:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;verdict = policy(snapshot_id, target)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no wall clock, random value, model call, or remote response inside that function. Once a snapshot passes the freshness and integrity preflight, the same snapshot and target give a developer laptop, a CI job, and an agent sandbox the same verdict.&lt;/p&gt;

&lt;h2&gt;
  
  
  A harness workflow that does not guess
&lt;/h2&gt;

&lt;p&gt;A reliable integration has three phases. Only the update phase needs network access; discovery and checks are stable interfaces that the harness can validate.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Discover the contract
&lt;/h3&gt;

&lt;p&gt;Do not make the agent reverse-engineer help text. Let the harness inspect the machine-readable capability document and the bundled JSON Schemas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vulngraph &lt;span class="nt"&gt;--json&lt;/span&gt; capabilities
vulngraph schema &lt;span class="nb"&gt;command
&lt;/span&gt;vulngraph schema observation
vulngraph schema status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;capabilities&lt;/code&gt; declares the commands, output schema versions, exit codes, and two behavioral guarantees: checks are offline and deterministic. A harness can validate support during startup instead of discovering an incompatibility halfway through a run.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Refresh and preflight outside the restricted step
&lt;/h3&gt;

&lt;p&gt;Install or refresh the snapshot in a setup job that is allowed to use the network:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vulngraph update
vulngraph &lt;span class="nt"&gt;--json&lt;/span&gt; status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then mount or cache the resulting VulnGraph home directory inside the agent environment. This makes network access a controlled data-provisioning concern instead of an ambient capability available during every security decision.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;status&lt;/code&gt; reports whether a snapshot is installed, its identity, its integrity, and its freshness. A dataset older than fourteen days is not merely accompanied by a warning: &lt;code&gt;check&lt;/code&gt; refuses to answer and exits with code &lt;code&gt;4&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Check the artifact the agent is actually changing
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;check&lt;/code&gt; command accepts individual CVEs, package coordinates, and dependency files. Pointing it at a lockfile expands every dependency and applies the same version-range policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vulngraph &lt;span class="nt"&gt;--offline&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt; check package-lock.json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; vulngraph.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI recognizes lockfiles from npm, Yarn, pnpm, Cargo, Bundler, Poetry, pip, Go, Composer, Maven, Gradle, and Pipenv. The abridged JSON response below shows the stable envelope:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vulngraph.command.v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"check"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"partial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"snapshot_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha256:41ee5fbb…"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vulngraph.observation.v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"package"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm:lodash@4.17.15"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"verdict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"disposition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"proof-of-concept"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.96&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prioritize"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"reason_codes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"ATTACK_MAPPED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"HIGH_SEVERITY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"MULTISOURCE_CORROBORATION"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"PUBLIC_EXPLOIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"SEVERITY_SCORED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"VERSION_IN_AFFECTED_RANGE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"WEAKNESS_CLASSIFIED"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"warnings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"metrics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"elapsed_us"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;781250&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important separation is that VulnGraph &lt;strong&gt;observes; it does not gate&lt;/strong&gt;. A successful check exits with &lt;code&gt;0&lt;/code&gt; even when it finds an actively exploited vulnerability. Exit codes describe whether the tool completed reliably; the harness applies organizational policy to the returned dispositions.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Disposition&lt;/th&gt;
&lt;th&gt;Evidence&lt;/th&gt;
&lt;th&gt;Sensible default harness action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;actively-exploited&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Listed in CISA KEV&lt;/td&gt;
&lt;td&gt;Block or require an explicit emergency exception&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;weaponized&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Public exploit and very high EPSS&lt;/td&gt;
&lt;td&gt;Block or require security approval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;proof-of-concept&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;At least one public exploit&lt;/td&gt;
&lt;td&gt;Prioritize remediation and require review&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scored&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CVSS or EPSS evidence, no public exploit&lt;/td&gt;
&lt;td&gt;Apply the repository's severity policy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;recorded&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Known record without stronger risk signals&lt;/td&gt;
&lt;td&gt;Monitor and retain the evidence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;not-affected&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Known package outside all affected ranges&lt;/td&gt;
&lt;td&gt;Proceed for this snapshot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;unknown&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Target absent from the snapshot&lt;/td&gt;
&lt;td&gt;Investigate; never translate to clean&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This split keeps probabilistic reasoning in the right place. The harness deterministically decides which states require a stop, review, or escalation. The agent then uses the evidence to explain the finding, inspect reachability, propose the smallest safe upgrade, and communicate the trade-off to a human.&lt;/p&gt;

&lt;h2&gt;
  
  
  A minimal Node.js harness
&lt;/h2&gt;

&lt;p&gt;The following wrapper turns the versioned VulnGraph envelope into one of five local workflow decisions. It does not ask the model whether an operational failure is acceptable, and it never treats an unrecognized disposition as approval.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;spawnSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:child_process&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;binary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VULNGRAPH_BIN&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vulngraph&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;package-lock.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;spawnSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--offline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;check&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;envelope&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;envelope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`vulngraph returned invalid JSON: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Exit codes describe tool reliability, not vulnerability severity.&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;VulnGraph snapshot is stale; refresh before continuing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;envelope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`VulnGraph failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;envelope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;envelope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vulngraph.command.v1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unsupported schema: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;envelope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;actively-exploited&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;weaponized&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;proof-of-concept&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;review&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scored&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;review&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;recorded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;monitor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;not-affected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;proceed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unknown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;investigate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decisions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;envelope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;disposition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disposition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;verdict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disposition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;investigate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reason_codes&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;evidence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;snapshotId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;envelope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snapshot_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;decisions&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decisions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;decision&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exitCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This is our harness policy, not a VulnGraph exit code.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;evidence&lt;/code&gt; object is what I would place in the agent's context. The prompt can remain narrow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Review the attached vulnerability evidence for this dependency change.

- Never describe `unknown` as safe or clean.
- Preserve the snapshot ID in your report.
- Explain the reason codes in plain language.
- Check whether each affected dependency is reachable from the changed code.
- Propose the smallest compatible upgrade, but do not edit files until approved.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The deterministic layer establishes what was observed and which policy branch applies. The agent contributes the work it is good at: repository-specific investigation, explanation, remediation planning, and communication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design lessons for agent-facing security tools
&lt;/h2&gt;

&lt;p&gt;Building the graph was only half the problem. Making it safe for automation required treating the interface as part of the security model.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Make ignorance a first-class result.&lt;/strong&gt; &lt;code&gt;unknown&lt;/code&gt; must survive every layer from data lookup to terminal output to agent context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Return evidence, not just a score.&lt;/strong&gt; A verdict should carry stable reasons and source observations that a human can audit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate update time from decision time.&lt;/strong&gt; Network retrieval belongs in a controlled provisioning phase; checks should be local and reproducible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identify the data behind every answer.&lt;/strong&gt; A content-derived snapshot ID turns “what did the scanner know?” into an answerable question.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Let tools describe their contract.&lt;/strong&gt; Capabilities, schemas, freshness, and exit semantics should be machine-readable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep gating policy outside the observation tool.&lt;/strong&gt; Different repositories have different risk tolerances. The harness should own that policy explicitly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An agent does not become trustworthy because it receives more tokens or a longer system prompt. It becomes more trustworthy when its environment preserves distinctions, constrains side effects, and supplies evidence through contracts that cannot silently change meaning.&lt;/p&gt;

&lt;p&gt;That is the role I designed VulnGraph to play: not an autonomous security authority, but a fast, local, auditable source of vulnerability evidence that gives agents and their harnesses something solid to reason from.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build and release pipeline: &lt;a href="https://github.com/copyleftdev/vulngraph-data" rel="noopener noreferrer"&gt;&lt;code&gt;copyleftdev/vulngraph-data&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Offline CLI: &lt;a href="https://github.com/copyleftdev/vulngraph-cli" rel="noopener noreferrer"&gt;&lt;code&gt;copyleftdev/vulngraph-cli&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; I designed VulnGraph. This article and its cover were created with AI assistance. I reviewed the technical claims against the linked repositories and live CLI output.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If this open-source work is useful to you, you can support its continued development:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tokentip.to/@copyleftdev" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftokentip.to%2Fbadge%2Fcopyleftdev.svg%3Flogo%3D1" alt="Tip copyleftdev with tokens on TokenTip" width="218" height="20"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>devsecops</category>
      <category>tooling</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Sat, 18 Jul 2026 17:47:12 +0000</pubDate>
      <link>https://dev.to/copyleftdev/-3c00</link>
      <guid>https://dev.to/copyleftdev/-3c00</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/copyleftdev/the-last-honest-abstraction-why-ai-coding-isnt-the-end-of-engineering-213e" class="crayons-story__hidden-navigation-link"&gt;The Last Honest Abstraction: Why AI Coding Isn't the End of Engineering&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/copyleftdev" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F965504%2Fd5dcc14b-c050-4183-a25e-c54e006eb6b2.png" alt="copyleftdev profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/copyleftdev" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Don Johnson
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Don Johnson
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
                
              
              &lt;div id="story-author-preview-content-4168323" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/copyleftdev" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F965504%2Fd5dcc14b-c050-4183-a25e-c54e006eb6b2.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Don Johnson&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/copyleftdev/the-last-honest-abstraction-why-ai-coding-isnt-the-end-of-engineering-213e" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 17&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/copyleftdev/the-last-honest-abstraction-why-ai-coding-isnt-the-end-of-engineering-213e" id="article-link-4168323"&gt;
          The Last Honest Abstraction: Why AI Coding Isn't the End of Engineering
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/discuss"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;discuss&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/softwaredevelopment"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;softwaredevelopment&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/copyleftdev/the-last-honest-abstraction-why-ai-coding-isnt-the-end-of-engineering-213e" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;17&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/copyleftdev/the-last-honest-abstraction-why-ai-coding-isnt-the-end-of-engineering-213e#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              6&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>The Last Honest Abstraction: Why AI Coding Isn't the End of Engineering</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Fri, 17 Jul 2026 16:47:19 +0000</pubDate>
      <link>https://dev.to/copyleftdev/the-last-honest-abstraction-why-ai-coding-isnt-the-end-of-engineering-213e</link>
      <guid>https://dev.to/copyleftdev/the-last-honest-abstraction-why-ai-coding-isnt-the-end-of-engineering-213e</guid>
      <description>&lt;p&gt;&lt;em&gt;Why every generation thinks the next programmer understands less—and why AI changes the burden of proof, not the need for engineering.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Developers can't even explain their own code anymore."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you've spent any time around software lately, you've probably seen some version of that argument.&lt;/p&gt;

&lt;p&gt;The culprit, we're told, is AI.&lt;/p&gt;

&lt;p&gt;Developers are prompting language models, accepting generated code, and shipping software they couldn't possibly explain line by line. Somewhere between autocomplete and autonomous agents, we supposedly crossed a professional line. We traded craftsmanship for convenience.&lt;/p&gt;

&lt;p&gt;It sounds like a new argument.&lt;/p&gt;

&lt;p&gt;It's one of the oldest in computing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before We Go Any Further...
&lt;/h2&gt;

&lt;p&gt;Before I make my case, I want to pay homage to a rare breed of engineer.&lt;/p&gt;

&lt;p&gt;You know who you are.&lt;/p&gt;

&lt;p&gt;You're the people who can look at compiler output and immediately tell when an optimization didn't quite land. You read assembly like most people read JavaScript. You understand calling conventions, cache locality, virtual memory, branch prediction, linker behavior, and processor architecture—and you can still build elegant software without turning every project into a dissertation.&lt;/p&gt;

&lt;p&gt;You're rare.&lt;/p&gt;

&lt;p&gt;And you've quietly carried this industry for decades.&lt;/p&gt;

&lt;p&gt;Many of the abstractions the rest of us rely on exist because someone like you spent years wrestling with complexity until everyone else could work one layer higher.&lt;/p&gt;

&lt;p&gt;Every generation has its handful of engineers who descend into the deepest layers of the machine, then return carrying tools that allow the rest of us to build something higher.&lt;/p&gt;

&lt;p&gt;This article isn't arguing against mastery.&lt;/p&gt;

&lt;p&gt;It's a thank-you to the people who made abstraction possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every Layer Was Once Considered Cheating
&lt;/h2&gt;

&lt;p&gt;Again and again, computing has moved upward by adding layers.&lt;/p&gt;

&lt;p&gt;Machine code gave way to assembly for most programming. Someone inevitably complained that assembly programmers weren't "real programmers" because they no longer had to manipulate raw binary.&lt;/p&gt;

&lt;p&gt;Higher-level languages followed. Compilers hid more of what the processor was &lt;em&gt;actually&lt;/em&gt; doing. Managed memory, virtual machines, dynamic languages, frameworks, cloud platforms, containers, and orchestration systems each took another category of complexity and moved it behind an interface.&lt;/p&gt;

&lt;p&gt;And now...&lt;/p&gt;

&lt;p&gt;AI.&lt;/p&gt;

&lt;p&gt;The technologies aren't a single, tidy lineage. They abstract different problems, and old layers rarely disappear. But the cultural pattern repeats:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Do they &lt;em&gt;really&lt;/em&gt; understand what's happening underneath?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The nouns change.&lt;/p&gt;

&lt;p&gt;The complaint doesn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Myth of the Complete Programmer
&lt;/h2&gt;

&lt;p&gt;Here's an uncomfortable truth.&lt;/p&gt;

&lt;p&gt;Most software has never been written by people who fully understood every layer beneath it.&lt;/p&gt;

&lt;p&gt;That isn't criticism.&lt;/p&gt;

&lt;p&gt;It's reality.&lt;/p&gt;

&lt;p&gt;Ask an application developer to explain exactly how their operating system schedules threads.&lt;/p&gt;

&lt;p&gt;Ask them why their compiler emitted a particular optimization.&lt;/p&gt;

&lt;p&gt;Ask them to walk through every page-table translation.&lt;/p&gt;

&lt;p&gt;Ask them to trace how cache behavior affected one production slowdown.&lt;/p&gt;

&lt;p&gt;Ask them to explain every TCP retransmission or every filesystem recovery after an unexpected shutdown.&lt;/p&gt;

&lt;p&gt;Some can.&lt;/p&gt;

&lt;p&gt;Most can't.&lt;/p&gt;

&lt;p&gt;And yet...&lt;/p&gt;

&lt;p&gt;The software still ships.&lt;/p&gt;

&lt;p&gt;Not because understanding stopped mattering, but because software engineering evolved around abstractions with bounded responsibilities and increasingly testable guarantees.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Entire Purpose of Engineering
&lt;/h2&gt;

&lt;p&gt;Engineering has never been about refusing abstraction.&lt;/p&gt;

&lt;p&gt;It's been about earning it.&lt;/p&gt;

&lt;p&gt;Every abstraction represents an enormous investment of human understanding. Someone had to master the ugly details so the next engineer could focus on solving a different problem.&lt;/p&gt;

&lt;p&gt;A civil engineer need not manufacture every bolt before designing a bridge, but must know which loads it can bear. Software abstractions work the same way: we delegate construction, not accountability.&lt;/p&gt;

&lt;p&gt;Requiring every software engineer to hand-write machine code before building a web application wouldn't protect craftsmanship.&lt;/p&gt;

&lt;p&gt;Progress wouldn't slow down.&lt;/p&gt;

&lt;p&gt;It would stop.&lt;/p&gt;

&lt;p&gt;Abstractions aren't shortcuts.&lt;/p&gt;

&lt;p&gt;They're accumulated knowledge.&lt;/p&gt;

&lt;p&gt;They're understanding, compressed into reusable form.&lt;/p&gt;

&lt;p&gt;That's not laziness.&lt;/p&gt;

&lt;p&gt;That's civilization.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AI Actually Changed
&lt;/h2&gt;

&lt;p&gt;AI did change something.&lt;/p&gt;

&lt;p&gt;Just not what many people think.&lt;/p&gt;

&lt;p&gt;A conventional compiler is expected to produce reproducible output from fixed inputs. A language model samples from probabilities. A compiler hides implementation behind a defined system; a model proposes implementation without guaranteeing that the proposal is correct.&lt;/p&gt;

&lt;p&gt;That makes AI a less trustworthy abstraction by default—not an invalid one. It means the engineer must supply the trust boundary through review, tests, observability, constraints, and a willingness to reject plausible-looking output.&lt;/p&gt;

&lt;p&gt;The real shift is that authorship is becoming an even weaker proxy for understanding—and an even less useful signal of correctness.&lt;/p&gt;

&lt;p&gt;For decades, many engineers subconsciously equated "I wrote it" with "I understand it."&lt;/p&gt;

&lt;p&gt;Those were never the same thing.&lt;/p&gt;

&lt;p&gt;We've all inherited libraries. We've all trusted frameworks. We've all depended on operating systems we didn't write. We've all deployed software built on millions of lines of code authored by strangers.&lt;/p&gt;

&lt;p&gt;AI simply made that reality impossible to ignore.&lt;/p&gt;

&lt;p&gt;The responsibility hasn't disappeared.&lt;/p&gt;

&lt;p&gt;It's moved.&lt;/p&gt;

&lt;p&gt;Instead of taking familiarity as evidence because you typed every character yourself, you establish confidence by inspecting the design, challenging assumptions, measuring behavior, and validating outcomes.&lt;/p&gt;

&lt;p&gt;This doesn't absolve the engineer of understanding. It changes the required depth. You may not need to explain every generated line from memory, but you do need to understand the system's boundaries, invariants, dependencies, and failure modes well enough to be accountable for what it does.&lt;/p&gt;

&lt;p&gt;That's engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Judgment Is Becoming the Scarce Resource
&lt;/h2&gt;

&lt;p&gt;The best engineers I've met have never impressed me with how quickly they type.&lt;/p&gt;

&lt;p&gt;They impress me with how quickly they notice something feels wrong.&lt;/p&gt;

&lt;p&gt;They can review a thousand lines and, through experience, stop at the seven that deserve attention. They know where abstractions leak. They know when benchmarks are lying. They know when a beautiful architecture is solving yesterday's problem.&lt;/p&gt;

&lt;p&gt;They ask better questions than everyone else.&lt;/p&gt;

&lt;p&gt;AI doesn't replace that.&lt;/p&gt;

&lt;p&gt;If anything, it magnifies its importance.&lt;/p&gt;

&lt;p&gt;Syntax gets cheaper.&lt;/p&gt;

&lt;p&gt;Judgment becomes priceless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standing on Invisible Giants
&lt;/h2&gt;

&lt;p&gt;There's a beautiful irony here.&lt;/p&gt;

&lt;p&gt;The engineers most qualified to criticize abstraction are often the same people who built it: compiler engineers, kernel developers, database architects, networking pioneers, language designers, and chip architects.&lt;/p&gt;

&lt;p&gt;They spent years making impossibly complicated systems disappear behind clean interfaces—not because they wanted everyone staring at the gears, but because they wanted the rest of us to keep building.&lt;/p&gt;

&lt;p&gt;Every abstraction they created became another floor in a building nobody could have constructed alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Last Honest Abstraction
&lt;/h2&gt;

&lt;p&gt;Every generation believes the abstraction immediately beneath them was the last honest one.&lt;/p&gt;

&lt;p&gt;Assembly programmers point to machine code.&lt;/p&gt;

&lt;p&gt;C programmers point to assembly.&lt;/p&gt;

&lt;p&gt;Framework skeptics point to handwritten C.&lt;/p&gt;

&lt;p&gt;Now AI skeptics point to handwritten code.&lt;/p&gt;

&lt;p&gt;Ten years from now, someone will publish an article insisting developers don't even understand what their autonomous software factories are doing.&lt;/p&gt;

&lt;p&gt;Someone else will nod and say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Back in my day, we actually wrote the prompts ourselves."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the cycle will begin again.&lt;/p&gt;

&lt;p&gt;Because the history of software has never been the history of losing understanding.&lt;/p&gt;

&lt;p&gt;It's been the history of redistributing it.&lt;/p&gt;

&lt;p&gt;A relatively small number of extraordinary engineers venture into the deepest layers, wrestle complexity into submission, and transform hard-earned understanding into abstractions that millions of others can build upon without mastering every detail beneath them.&lt;/p&gt;

&lt;p&gt;Those abstractions aren't evidence that engineering is dying.&lt;/p&gt;

&lt;p&gt;They're evidence that engineering succeeded.&lt;/p&gt;

&lt;p&gt;Progress has never required everyone to understand everything.&lt;/p&gt;

&lt;p&gt;It has always required enough people to understand each layer deeply enough to build the next one—and everyone who uses that layer to understand its promises and failure modes well enough to take responsibility for the result.&lt;/p&gt;

&lt;p&gt;The rest of us stand on their shoulders.&lt;/p&gt;

&lt;p&gt;And someday, if we do our jobs well enough, someone else will stand on ours.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Editorial note: This article was refined with AI-assisted editorial review, and its cover illustration was generated with AI. The argument, factual review, and final wording remain the author's responsibility.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>discuss</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>A Vibe Is Not a Verdict: I Built a Tool That's Allowed to Say 'I Don't Know'</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Mon, 13 Jul 2026 19:37:38 +0000</pubDate>
      <link>https://dev.to/copyleftdev/a-vibe-is-not-a-verdict-i-built-a-tool-thats-allowed-to-say-i-dont-know-4foe</link>
      <guid>https://dev.to/copyleftdev/a-vibe-is-not-a-verdict-i-built-a-tool-thats-allowed-to-say-i-dont-know-4foe</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A tool should do one thing, do it well, and — this is the part everyone forgets — know exactly where its knowledge ends.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I built &lt;code&gt;kilo&lt;/code&gt; for a morning like this one. I just didn't know the morning would come this soon.&lt;/p&gt;




&lt;h2&gt;
  
  
  The message that was waiting for me
&lt;/h2&gt;

&lt;p&gt;I woke up, poured the coffee, and did the thing you're not supposed to do before you're fully awake: I opened my messages. And there it was, sitting at the top of the inbox like it had been placed there on purpose — a cold recruiter pitch.&lt;/p&gt;

&lt;p&gt;An "exciting opportunity" for a Quality Engineer role at an aerospace firm. Warm, professional, faintly urgent. &lt;em&gt;Please click the link below to view the job description and apply.&lt;/em&gt; The link was a long tracking URL, the kind with an opaque token and &lt;code&gt;source&lt;/code&gt; and &lt;code&gt;method&lt;/code&gt; parameters stapled to the end.&lt;/p&gt;

&lt;p&gt;And then the signature. One "recruiter" who claimed, in a single line, to be a physical therapist, a call-centre manager, an e-commerce power seller, a freight dispatcher — half a dozen unrelated trades piled into one job title, now, apparently, placing quality engineers at an aerospace company. That's not a résumé. That's a slot machine.&lt;/p&gt;

&lt;p&gt;There it was: the exact situation I wrote the tool for, delivered to my inbox before I'd finished the coffee.&lt;/p&gt;

&lt;p&gt;Because here's what would normally happen next. My gut says &lt;strong&gt;scam&lt;/strong&gt;. My gut is usually right. But "usually right" is how you eventually click the one link that isn't. A gut feeling is a vibe, and a vibe is not a verdict. That frustration is precisely why, months ago, I sat down and wrote &lt;code&gt;kilo&lt;/code&gt; — a way to stop feeling about an address and start knowing about it. So this morning wasn't an annoyance. It was the experiment finally running itself.&lt;/p&gt;

&lt;p&gt;I put the coffee down and opened a terminal.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I actually built, and why
&lt;/h2&gt;

&lt;p&gt;Let me back up and tell you what &lt;code&gt;kilo&lt;/code&gt; is, because the design is the whole argument.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/copyleftdev/kilocheck" rel="noopener noreferrer"&gt;&lt;strong&gt;KiloCheck&lt;/strong&gt;&lt;/a&gt; is an offline IP-reputation engine. One binary. ~12MB. Written in Rust. Its entire worldview is a four-stage pipeline: &lt;strong&gt;ingest&lt;/strong&gt; a signed, versioned threat release → &lt;strong&gt;normalize&lt;/strong&gt; typed observations → &lt;strong&gt;compile&lt;/strong&gt; an immutable local index → &lt;strong&gt;check&lt;/strong&gt; IPs against it. Cryptographically verified going in. Zero network calls coming out.&lt;/p&gt;

&lt;p&gt;I made it offline on purpose. An ordinary check never reaches an intelligence API. When I'm triaging something sketchy, I don't want my queries leaking, I don't want to tip anyone off, and I want the same answer at 3AM on a plane as I get at my desk. The threat knowledge is baked into a signed local snapshot. The check is just a lookup against evidence I already trust.&lt;/p&gt;

&lt;p&gt;Install is a checksum and a copy — the way a tool should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/copyleftdev/kilocheck/v0.2.0/scripts/install.sh | sh
kilo update      &lt;span class="c"&gt;# pulls the signed data release → prints "Claims  3160"&lt;/span&gt;
kilo status &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;span class="c"&gt;# → "integrity": "verified", "freshness": "fresh"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was the tool. This was the morning. Time to point one at the other.&lt;/p&gt;




&lt;h2&gt;
  
  
  The experiment, step one: turn the lure into a number
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;kilo&lt;/code&gt; answers exactly one question — &lt;em&gt;is this IP a known bad actor?&lt;/em&gt; — so first I had to turn that tracking link into an address. That's &lt;code&gt;dig&lt;/code&gt;'s whole job: resolve the hostname behind the URL down to the IP actually serving it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dig +short &amp;lt;the-redirect-host&amp;gt;
203.0.113.90
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I asked my tool the question I built it to answer. This is the moment the experiment either validates the design or embarrasses me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kilo check 203.0.113.90 &lt;span class="nt"&gt;--json&lt;/span&gt; | jq &lt;span class="s1"&gt;'.data[0].verdict'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"disposition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"recommended_action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"monitor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reason_codes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"NOT_OBSERVED"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;NOT_OBSERVED&lt;/code&gt;. Confidence &lt;code&gt;0.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And I grinned, because this is exactly the behavior I designed for — and the exact behavior a worse tool would have gotten wrong.&lt;/p&gt;

&lt;p&gt;Think about the pressure in that moment. I clearly think it's a scam. The vibe is overwhelming. A tool built to please its operator would have felt that pressure and handed me a scary red verdict to confirm what I already believed. &lt;code&gt;kilo&lt;/code&gt; refuses. It says: &lt;em&gt;I have no evidence about this address, and I am not going to invent some to make you feel clever.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That refusal is the single most important thing I built into it. &lt;strong&gt;A tool has to know the difference between "safe," "bad," and "I don't know" — and it has to refuse to smear them together.&lt;/strong&gt; Missing, unknown, stale, incomplete, unsafe: five distinct states in my model, not three shades of the same shrug. This morning it chose the honest one under maximum temptation to lie.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step two: prove it can still bite
&lt;/h2&gt;

&lt;p&gt;An honest "I don't know" is only worth something if the same tool can say a hard "yes." If &lt;code&gt;kilo&lt;/code&gt; returned &lt;code&gt;unknown&lt;/code&gt; for everything, it wouldn't be humble — it'd be broken. So I ran the control, right there in my pajamas: the suspicious host, a known command-and-control node, and a boring public DNS resolver, all in one shot. Distilled from the JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;203.0.113.90      → unknown   monitor   NOT_OBSERVED        (0 sources)
162.243.103.246   → CRITICAL  block     COMMAND_AND_CONTROL (1 source, conf 0.99)
8.8.8.8           → unknown   monitor   NOT_OBSERVED        (0 sources)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There. A known C2 node gets &lt;code&gt;critical / block / 0.99&lt;/code&gt; with provenance attached. The public resolver and the suspicious host both get a calm &lt;code&gt;NOT_OBSERVED&lt;/code&gt;. No false alarms on clean infrastructure, no missed alarm on a real one. The experiment held: &lt;strong&gt;the tool's silence means something precisely because its alarm means something.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step three: the twist my own tool pointed me toward
&lt;/h2&gt;

&lt;p&gt;So the infra came back clean. Was my gut wrong? No — it was pointed at the wrong target. And that's the part I didn't see coming.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kilo&lt;/code&gt;'s honest negative didn't close the case. It &lt;em&gt;moved&lt;/em&gt; it. "The danger is not in this infrastructure" is a coordinate — it told me to go look somewhere else. So I followed the rest of the trail with the neighbors on my toolbelt.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl&lt;/code&gt; followed the redirect — headers only, I never touched the body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;302&lt;/span&gt; &lt;span class="ne"&gt;→ /&amp;lt;captcha-gate&amp;gt;?...&amp;amp;source=...&amp;amp;method=...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;openssl&lt;/code&gt; read the cert straight off the wire: a real, correctly issued certificate for a legitimate, well-known job-traffic aggregator. And a quick lookup closed the loop: the aerospace company in the pitch is real, with genuine engineering openings, and the tracking link was an affiliate &lt;em&gt;click-tracker&lt;/em&gt; redirecting through the aggregator's own anti-click-fraud gate. No payload. No credential harvest. No bad IP anywhere in the chain.&lt;/p&gt;

&lt;p&gt;So what was the actual threat? It was never in the packets. It was the sender — a freelance lead-gen spammer blasting affiliate commission links across social platforms, wearing a recruiter costume stitched together from half a dozen unrelated careers.&lt;/p&gt;

&lt;p&gt;And here's why I'm writing this at all: &lt;strong&gt;my own tool solved the case by refusing to pretend.&lt;/strong&gt; Its &lt;code&gt;0.0&lt;/code&gt; sent me away from a malware rabbit hole and toward the social-engineering signal where the truth actually lived. If &lt;code&gt;kilo&lt;/code&gt; had cried wolf on clean infrastructure to match my mood, I'd have wasted the morning dissecting a job board. Because it stayed honest, it handed me the thread on the first pull.&lt;/p&gt;

&lt;p&gt;That is the exact experiment I wrote the tool to run. And it passed.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the morning actually taught me
&lt;/h2&gt;

&lt;p&gt;The recruiter was never the point. The shape of the morning was.&lt;/p&gt;

&lt;p&gt;I didn't solve this with one brilliant tool. I solved it with a chain of small, honest ones: &lt;code&gt;dig&lt;/code&gt; turned a name into an address so &lt;code&gt;kilo&lt;/code&gt; had something to check; &lt;code&gt;kilo&lt;/code&gt;'s honest negative reframed the question so &lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;openssl&lt;/code&gt; knew where to look. And every one of them spoke &lt;strong&gt;stable JSON&lt;/strong&gt; — so I was consuming &lt;em&gt;contracts&lt;/em&gt;, not parsing prose. Exit codes matter. Schemas matter. Failure stays legible.&lt;/p&gt;

&lt;p&gt;That's the manifesto I keep coming back to as I build these things: &lt;strong&gt;contracts, not vibes.&lt;/strong&gt; When I pipe &lt;code&gt;kilo check --json&lt;/code&gt; into &lt;code&gt;jq&lt;/code&gt;, I'm having a typed conversation with reality. I can't hallucinate a verdict, because the verdict arrives as a signed struct with its provenance stapled on.&lt;/p&gt;

&lt;p&gt;It's the difference between a tool that sounds right and one that is right:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A gut feeling is an opinion. A sharp, composable, honest toolbelt is a witness.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And witnesses — unlike hunches — can say the three most valuable words in this whole trade: &lt;strong&gt;"I don't know."&lt;/strong&gt; Then go find out.&lt;/p&gt;

&lt;p&gt;Steal the pattern if it's useful:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Small, single-purpose tools that speak stable JSON&lt;/strong&gt; compose into something no chatty do-everything API can match.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Honesty beats confidence.&lt;/strong&gt; A tool that returns &lt;code&gt;unknown&lt;/code&gt; under pressure is worth ten that guess to please you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Let the negatives navigate.&lt;/strong&gt; The most useful result of the entire morning was a &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So the next time a link makes your gut twitch, don't argue with the vibe. Resolve it, and ask a tool that's allowed to say nothing.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kilo&lt;/code&gt; didn't catch a scam — there wasn't one, just spam in a lab coat. It did something I value more: it told me the truth about what it knew, drew a hard line around what it didn't, and pointed me at where the real answer was hiding.&lt;/p&gt;

&lt;p&gt;I built a 12MB binary to say &lt;em&gt;"not observed"&lt;/em&gt; without flinching, on the exact morning I most wanted it to lie. It didn't. That's the whole experiment. That's why I built it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kilo check &amp;lt;your-suspicions-here&amp;gt; &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;Tooling in this piece: &lt;a href="https://github.com/copyleftdev/kilocheck" rel="noopener noreferrer"&gt;KiloCheck&lt;/a&gt; · the eternal &lt;code&gt;dig&lt;/code&gt; / &lt;code&gt;openssl&lt;/code&gt; / &lt;code&gt;curl&lt;/code&gt;. The story is real; the identifying details have been filed off.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rust</category>
      <category>cli</category>
      <category>security</category>
    </item>
    <item>
      <title>The AI Cost-Modeling Handbook: I let Claude do the modeling, but never the arithmetic</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Wed, 01 Jul 2026 02:51:48 +0000</pubDate>
      <link>https://dev.to/copyleftdev/the-ai-cost-modeling-handbook-i-let-claude-do-the-modeling-but-never-the-arithmetic-3h95</link>
      <guid>https://dev.to/copyleftdev/the-ai-cost-modeling-handbook-i-let-claude-do-the-modeling-but-never-the-arithmetic-3h95</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Every "what's the cheapest model?" thread online is people trading vibes. I got tired of it, so I built a pipeline that pulls &lt;em&gt;live, cited&lt;/em&gt; prices and runs the numbers through an &lt;strong&gt;exact-rational math kernel&lt;/strong&gt; — no floating-point drift, no LLM hallucinating a multiplication. Then I pointed it at eight of the cost questions every agent builder actually faces. Here's everything it found, and the repo so you can re-run all of it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are two kinds of LLM cost advice. The first is a benchmark leaderboard with a price column, which tells you nothing about &lt;em&gt;your&lt;/em&gt; workload. The second is a confident tweet that's quietly wrong because someone multiplied a per-million price by the wrong token count in their head.&lt;/p&gt;

&lt;p&gt;I wanted a third kind: a model you can &lt;strong&gt;audit&lt;/strong&gt;. Re-run it and you get bit-identical numbers, with the source of every input price one file away. This article is the result — a tour through eight cost decisions, each answered with real money math, and each one teaching something that intuition gets wrong.&lt;/p&gt;

&lt;p&gt;Let's start with the question that kicked it off.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cold open: what's the most cost-effective model to run an agent on?
&lt;/h2&gt;

&lt;p&gt;The setup: I run &lt;a href="https://github.com/NousResearch/hermes-agent" rel="noopener noreferrer"&gt;Hermes Agent&lt;/a&gt;, a model-agnostic agent framework, and I wanted the cheapest token provider to drive it. Not cheapest &lt;em&gt;per token&lt;/em&gt; — cheapest &lt;strong&gt;per unit of quality&lt;/strong&gt;, because a model that flubs tool calls and retries can cost more than a pricier reliable one.&lt;/p&gt;

&lt;p&gt;So the metric is &lt;strong&gt;blended cost ÷ agentic-quality-score&lt;/strong&gt;. Blended cost uses a production-agentic token mix (more on that below); quality is a normalized agentic score (mean of BFCL / τ²-bench / SWE-bench Verified). Filters: open-weights, prompt caching, no-train.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model @ Provider&lt;/th&gt;
&lt;th&gt;Blended $/1M&lt;/th&gt;
&lt;th&gt;Quality&lt;/th&gt;
&lt;th&gt;$/quality (×1000)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DeepSeek V3.2 @ OpenRouter&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.1145&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;77&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.49&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek V3.2 @ DeepInfra&lt;/td&gt;
&lt;td&gt;0.1951&lt;/td&gt;
&lt;td&gt;77&lt;/td&gt;
&lt;td&gt;2.53&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MiniMax M2 @ MiniMax&lt;/td&gt;
&lt;td&gt;0.2629&lt;/td&gt;
&lt;td&gt;73&lt;/td&gt;
&lt;td&gt;3.60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GLM-4.6 @ z.ai&lt;/td&gt;
&lt;td&gt;0.5276&lt;/td&gt;
&lt;td&gt;71&lt;/td&gt;
&lt;td&gt;7.43&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kimi K2 @ DeepInfra&lt;/td&gt;
&lt;td&gt;0.6613&lt;/td&gt;
&lt;td&gt;66&lt;/td&gt;
&lt;td&gt;10.02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek R1 @ DeepInfra&lt;/td&gt;
&lt;td&gt;0.6519&lt;/td&gt;
&lt;td&gt;54&lt;/td&gt;
&lt;td&gt;12.07&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;DeepSeek V3.2 wins decisively&lt;/strong&gt; — it's both the highest-quality open model in the set &lt;em&gt;and&lt;/em&gt; near the cheapest, because its output token price is absurdly low for its tier. The emerging best deal (pending a quality test) is &lt;strong&gt;DeepSeek V4 Flash on Fireworks&lt;/strong&gt; at $0.0896/1M blended — cheapest in the field, with ZDR-by-default and a 50% batch discount.&lt;/p&gt;

&lt;p&gt;That's a useful answer. But the &lt;em&gt;interesting&lt;/em&gt; part is everything that question opens up. If you can split traffic across providers, what's the optimal mix? Should you self-host instead? Is the "smart expensive model" actually cheaper once you count its thinking tokens? Each of those is a chapter.&lt;/p&gt;

&lt;p&gt;First, how this is built.&lt;/p&gt;




&lt;h2&gt;
  
  
  The toolchain: research agents + an exact-math kernel
&lt;/h2&gt;

&lt;p&gt;The pipeline has two halves, and the whole point is that &lt;strong&gt;the LLM never touches the arithmetic.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Research agents gather live, cited inputs.&lt;/strong&gt; Token prices in 2026 move monthly — half the models in my training data are already legacy. So every price and benchmark in this guide came from a research agent doing live web search/fetch, returning a structured table with source URLs and observation dates. Those land in &lt;code&gt;data/&lt;/code&gt; (&lt;code&gt;pricing.md&lt;/code&gt;, &lt;code&gt;quality.md&lt;/code&gt;, &lt;code&gt;gpu.md&lt;/code&gt;, &lt;code&gt;frontier.md&lt;/code&gt;, &lt;code&gt;decline.md&lt;/code&gt;), each one auditable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. An exact-rational kernel does the math.&lt;/strong&gt; I used &lt;a href="https://github.com/copyleftdev/agent-calc" rel="noopener noreferrer"&gt;&lt;code&gt;agent-calc&lt;/code&gt;&lt;/a&gt;, an AI-native computation kernel that works in exact rationals — &lt;code&gt;3/5 × 1,000,000&lt;/code&gt; returns &lt;code&gt;600000&lt;/code&gt;, not &lt;code&gt;599999.9999998&lt;/code&gt;. It exposes typed domains: &lt;code&gt;rational&lt;/code&gt;, &lt;code&gt;linear&lt;/code&gt; (LP), &lt;code&gt;finance&lt;/code&gt; (NPV/amortization), &lt;code&gt;solve&lt;/code&gt; (algebra), &lt;code&gt;stats&lt;/code&gt; (distributions), &lt;code&gt;polynomial&lt;/code&gt;, &lt;code&gt;interval&lt;/code&gt; (uncertainty arithmetic). Every chapter below drives a different one.&lt;/p&gt;

&lt;p&gt;Why bother? Because cost models are exactly where floating-point lies and LLMs fumble: tiny per-token prices, huge token counts, compounding rates. When an answer is "self-hosting breaks even at 87.2% utilization," you want that to be &lt;em&gt;computed&lt;/em&gt;, not vibed. And the secret structure of this guide is that each chapter answers a money question &lt;strong&gt;and&lt;/strong&gt; exercises one kernel domain — it's a cost-modeling handbook that doubles as a tour of exact computation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The shared workload model
&lt;/h3&gt;

&lt;p&gt;Every chapter uses one production-agentic token profile, because agent tool-loops are wildly input-heavy:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Share of tokens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fresh input&lt;/td&gt;
&lt;td&gt;21.25%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cached input&lt;/td&gt;
&lt;td&gt;63.75%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output&lt;/td&gt;
&lt;td&gt;15%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That's an 85/15 input/output split with 75% of input being a cache hit (the system prompt, tools, and skills get re-sent every tool-loop step). Blended price = &lt;code&gt;0.2125·in + 0.6375·cached + 0.15·out&lt;/code&gt;. Chapter 7 explains &lt;em&gt;why&lt;/em&gt; this profile is forced on you; Chapter 6 explains why the cache hit rate is so high. For now, take it as the workload.&lt;/p&gt;




&lt;h2&gt;
  
  
  Chapter 1 — Optimal multi-provider routing (a linear program)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvvob8hq7fsafn5kvk3sn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvvob8hq7fsafn5kvk3sn.png" alt="The cost-of-privacy frontier: cost stays flat until 40% US-jurisdiction traffic, rises steeply after 60%, and hits an infeasible wall at 87.2%" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You don't have to pick one provider. Run a cheap one for the bulk, escalate elsewhere when constraints demand. The optimal split — minimize spend subject to a quality floor, per-endpoint capacity caps, and a &lt;strong&gt;US-jurisdiction floor θ&lt;/strong&gt; — is a literal linear program. &lt;code&gt;agent-calc&lt;/code&gt; solves it (&lt;code&gt;solve_lp&lt;/code&gt;), then I re-verify the winning allocation's cost in exact rationals (the LP solver is f64; the headline number shouldn't be).&lt;/p&gt;

&lt;p&gt;Sweeping the privacy knob θ traces a &lt;strong&gt;cost-of-privacy frontier&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;US floor θ&lt;/th&gt;
&lt;th&gt;min $/1M&lt;/th&gt;
&lt;th&gt;$/mo @ 1B&lt;/th&gt;
&lt;th&gt;allocation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0.00–0.40&lt;/td&gt;
&lt;td&gt;0.1468&lt;/td&gt;
&lt;td&gt;$146.77&lt;/td&gt;
&lt;td&gt;A=0.60, B=0.40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.60&lt;/td&gt;
&lt;td&gt;0.1629&lt;/td&gt;
&lt;td&gt;$162.89&lt;/td&gt;
&lt;td&gt;A=0.40, B=0.60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.80&lt;/td&gt;
&lt;td&gt;0.2716&lt;/td&gt;
&lt;td&gt;$271.61&lt;/td&gt;
&lt;td&gt;A=0.20, B=0.60, F=0.13, H=0.07&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;0.872&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.3116&lt;/td&gt;
&lt;td&gt;$311.59&lt;/td&gt;
&lt;td&gt;A=0.13, B=0.60, F=0.27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;≥ 0.873&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;INFEASIBLE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;the privacy wall&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three things intuition misses:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The first 40% of US-jurisdiction traffic is free&lt;/strong&gt; — the cost-optimal blend already lands there, because the cheapest provider is capped at 60% and the overflow falls on a US endpoint anyway.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The marginal cost of privacy is convex&lt;/strong&gt; — 40→60% is cheap; past 60% the quality floor forces in weaker fillers and the bill nearly doubles by 87%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There's a hard wall at 87.2%.&lt;/strong&gt; Only &lt;em&gt;one&lt;/em&gt; high-quality US endpoint exists in this menu; beyond its capacity the math is infeasible. To break the wall you need a second high-quality US provider, or you accept single-point-of-failure risk.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Chapter 2 — Self-host vs. serverless: it's a utilization question
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwcvw2d7zq4z6pknvnvkd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwcvw2d7zq4z6pknvnvkd.png" alt="Break-even utilization by hardware and procurement: every rented and Hopper config needs &gt;100% utilization (impossible); only owned 8×B200 wins at 72%" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everyone's instinct: "at some volume, renting GPUs beats per-token APIs." The reframe that changes everything: &lt;strong&gt;a self-hosted node costs the same at 5% load or 95% load&lt;/strong&gt;, while the API scales linearly with tokens. So it's not a &lt;em&gt;dollar&lt;/em&gt; break-even — it's a &lt;strong&gt;break-even utilization&lt;/strong&gt;: how busy must the box stay to win?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;u* = node_$/mo × 1e6 / (capacity_tokens/mo × API_$/1M)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;u* &amp;gt; 100%&lt;/code&gt;, self-hosting loses &lt;em&gt;even at full tilt&lt;/em&gt;. Modeling DeepSeek V3.2 (8-GPU node) against DeepInfra's $0.195/1M, with &lt;code&gt;agent-calc&lt;/code&gt; handling the owned-hardware amortization (&lt;code&gt;finance&lt;/code&gt;) and the exact &lt;code&gt;u*&lt;/code&gt; (&lt;code&gt;eval&lt;/code&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hardware / procurement&lt;/th&gt;
&lt;th&gt;break-even u*&lt;/th&gt;
&lt;th&gt;verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;8×H200, rent on-demand&lt;/td&gt;
&lt;td&gt;531%&lt;/td&gt;
&lt;td&gt;never&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8×H200, own (amortized)&lt;/td&gt;
&lt;td&gt;220%&lt;/td&gt;
&lt;td&gt;never&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8×B200, rent reserved&lt;/td&gt;
&lt;td&gt;174%&lt;/td&gt;
&lt;td&gt;never&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;8×B200, own (amortized)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;72%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;the only winner&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For a commodity model this cheap on the API, &lt;strong&gt;renting GPUs loses in every configuration&lt;/strong&gt; — the serverless provider batches across thousands of tenants to hit a utilization you can't. The &lt;em&gt;only&lt;/em&gt; config that wins is &lt;strong&gt;owned Blackwell silicon kept above ~72% utilization 24/7&lt;/strong&gt; (~56B tokens/month of steady load). And against the falling API floor ($0.0896/1M), even that roughly doubles its break-even. The takeaway: &lt;strong&gt;self-host for privacy, control, or latency — not to cut the token bill.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Chapter 3 — The reasoning-token tax
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8xxq79ayjh348gzugle6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8xxq79ayjh348gzugle6.png" alt="DeepSeek R1's cost-per-solved climbs steeply with reasoning burn, always far above the DeepSeek V3.2 champion line — even at zero thinking" width="799" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reasoning models emit hidden "thinking" tokens, billed at the output rate. A 600-token answer can bill 7,800. Does the higher success rate justify the burn? The honest unit isn't $/token — it's &lt;strong&gt;cost per &lt;em&gt;solved&lt;/em&gt; task&lt;/strong&gt; = attempt cost ÷ success rate.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;agent-calc&lt;/code&gt; computing exact costs (&lt;code&gt;eval&lt;/code&gt;) and the break-even success rate (&lt;code&gt;solve&lt;/code&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;k (think mult.)&lt;/th&gt;
&lt;th&gt;$/solved&lt;/th&gt;
&lt;th&gt;×champion&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DeepSeek V3.2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.17m&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.00×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MiniMax M2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4.03m&lt;/td&gt;
&lt;td&gt;1.27×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kimi K2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;8.79m&lt;/td&gt;
&lt;td&gt;2.77×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GLM-4.6&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;13.77m&lt;/td&gt;
&lt;td&gt;4.35×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek R1&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;36.80m&lt;/td&gt;
&lt;td&gt;11.61×&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;(&lt;code&gt;m&lt;/code&gt; = milli-dollars = $0.001/task.)&lt;/p&gt;

&lt;p&gt;The killer result: &lt;strong&gt;DeepSeek R1 would need a 627% success rate&lt;/strong&gt; to match V3.2's cost-per-solved — mathematically impossible. Even a &lt;em&gt;perfect&lt;/em&gt; R1 stays far more expensive, because its per-attempt token burn alone exceeds V3.2's entire cost-per-solved. The sweep confirms it: even at k=0 (zero thinking), R1 is still 2.6× the champion.&lt;/p&gt;

&lt;p&gt;The rule: &lt;strong&gt;the reasoning tax only pays when output tokens are cheap.&lt;/strong&gt; Thinking is a multiplier on the output price. Pay $2.15/M and ×12 and you've built the most expensive possible way to solve a task; pay $0.38/M and the same multiplier barely registers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Chapter 4 — The retry cascade
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxrhx8db0avuhf5ybz3o4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxrhx8db0avuhf5ybz3o4.png" alt="Cost-per-solved vs coverage: cascades sit down-and-right of both single-model strategies — higher coverage at a fraction of premium-only cost" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You don't need one model for every task. Run a &lt;strong&gt;cheap&lt;/strong&gt; model on everything, &lt;strong&gt;escalate&lt;/strong&gt; to a reliable premium model only on the residual failures. &lt;code&gt;agent-calc&lt;/code&gt; computes the escalation probability (&lt;code&gt;stats/binomial_pmf&lt;/code&gt;) and the exact expected cost (&lt;code&gt;eval&lt;/code&gt;).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;cost/solved&lt;/th&gt;
&lt;th&gt;coverage&lt;/th&gt;
&lt;th&gt;% → premium&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cheap-only (DeepSeek V3.2)&lt;/td&gt;
&lt;td&gt;3.17m&lt;/td&gt;
&lt;td&gt;77.0%&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Premium-only (Claude Opus 4.8)&lt;/td&gt;
&lt;td&gt;82.96m&lt;/td&gt;
&lt;td&gt;88.0%&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cascade V3.2 → Opus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;19.78m&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;97.2%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;23%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cascade V3.2 → Gemini → Opus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;13.52m&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;99.5%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The cascade beats premium-only on &lt;strong&gt;both&lt;/strong&gt; axes: higher coverage (97% vs 88%) at a quarter the cost, because only 23% of tasks reach the expensive model. Adding a mid-tier pushes coverage to 99.5% while &lt;em&gt;cutting&lt;/em&gt; cost further — the cheap+mid tiers absorb 95.6% of traffic, so the $73m Opus call fires on 4.4% of tasks.&lt;/p&gt;

&lt;p&gt;And the trap to avoid: &lt;strong&gt;retrying the &lt;em&gt;same&lt;/em&gt; model never changes cost-per-solved&lt;/strong&gt; (it stays C/p), and for deterministic failures it doesn't even raise coverage. Only escalating to a &lt;em&gt;different, stronger&lt;/em&gt; model moves the needle. "Just add retries" is a no-op; "add a tier" is the win. (The cost advantage survives even strong failure correlation — 3.6× cheaper than premium-only even when the premium rarely rescues what the cheap model botched.)&lt;/p&gt;




&lt;h2&gt;
  
  
  Chapter 5 — The NPV of waiting
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc4iqu00jzc28s7c4vds3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc4iqu00jzc28s7c4vds3.png" alt="12-month NPV: pay-go beats a 30%-off commit for fast-declining commodity prices (−23%) but loses for sticky frontier prices (+22%)" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A provider offers a discounted &lt;em&gt;reserved&lt;/em&gt; rate if you commit for a year. Locking it in feels prudent — but token prices fall fast, and you might be locking yourself &lt;em&gt;above&lt;/em&gt; where pay-go will be in six months. This is a present-value problem: NPV the committed cash-flow stream against the declining pay-go stream (&lt;code&gt;agent-calc finance/net_present_value&lt;/code&gt;), and find the &lt;strong&gt;break-even decline rate&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The decisive input is that price decline depends entirely on what you hold fixed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fixed-quality&lt;/strong&gt; (same capability getting cheaper): &lt;strong&gt;~80%/yr&lt;/strong&gt; (a16z/Epoch).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontier&lt;/strong&gt; (always run the best): &lt;strong&gt;~30%/yr&lt;/strong&gt;, sometimes flat or rising.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At a 30%-off, 12-month commit:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workload&lt;/th&gt;
&lt;th&gt;central decline&lt;/th&gt;
&lt;th&gt;winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fixed-quality&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;80%/yr&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;pay-go (−23%)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Frontier&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;30%/yr&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;commit (+22%)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And the break-even decline grid shows committing &lt;strong&gt;never&lt;/strong&gt; wins for commodity models (80%/yr exceeds every reservable discount's break-even), while longer terms always make it worse: a 30% discount breaks even at 57.8%/yr over 12 months but only &lt;strong&gt;24.5%/yr over 36 months&lt;/strong&gt;. The rule: &lt;strong&gt;reserve where prices are sticky (frontier); ride the curve where they fall fast (commodity). Never sign a 3-year inference commit in a market falling &amp;gt;25%/yr.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Chapter 6 — Prompt-cache ROI
&lt;/h2&gt;

&lt;p&gt;Caching looks free, but a cache &lt;em&gt;write&lt;/em&gt; often costs more than a normal input token (Anthropic charges up to 2×), while reads are cheap. So it's a bet: pay the write premium to save on reads, and it only pays if you reuse enough before the cache expires. The break-even reuse count is &lt;code&gt;N* = (write − read)/(in − read)&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;break-even N*&lt;/th&gt;
&lt;th&gt;savings ceiling&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DeepInfra / DeepSeek / OpenAI / Fireworks (no write fee)&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;50–90%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anthropic Opus 5-min TTL (1.25× write)&lt;/td&gt;
&lt;td&gt;1.28&lt;/td&gt;
&lt;td&gt;90%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anthropic Opus 1-hr TTL (2× write)&lt;/td&gt;
&lt;td&gt;2.11&lt;/td&gt;
&lt;td&gt;90%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Caching pays almost immediately&lt;/strong&gt; — most providers from the second call, even the harshest write premium by the third. The &lt;em&gt;read&lt;/em&gt; multiplier sets the long-run ceiling (0.1×-read → 90% savings; 0.5×-read → 50%), so for cache-heavy loops that's the number that compounds. Using &lt;code&gt;agent-calc&lt;/code&gt;'s &lt;code&gt;interval&lt;/code&gt; domain, an 8k-token agent prefix reused an uncertain 3–20 times costs $0.088–0.156 cached vs $0.12–0.80 uncached — &lt;strong&gt;80% off at the high end&lt;/strong&gt;, even with a 2× write premium. This is why the guide's 75% cache-hit assumption holds: agent loops reuse a large prefix 10–20× per task.&lt;/p&gt;




&lt;h2&gt;
  
  
  Chapter 7 — Agent-loop compounding (the O(K²) tax)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F21w6ks9gq0t46u62gijj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F21w6ks9gq0t46u62gijj.png" alt="Cumulative input cost vs loop length: naive grows quadratically, caching halves the constant but stays quadratic, compaction turns it linear" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why is that reused prefix so large? Because a multi-turn agent re-sends its growing context every step — at step &lt;em&gt;k&lt;/em&gt;, the input is the base prompt plus &lt;em&gt;every prior tool call and result&lt;/em&gt;. Per-step input grows linearly, so &lt;strong&gt;cumulative input over a K-step task grows quadratically&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cumulative over K = (δ/2)·K² + (B − δ/2)·K
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;agent-calc&lt;/code&gt; evaluates that polynomial exactly (&lt;code&gt;polynomial/evaluate&lt;/code&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;K steps&lt;/th&gt;
&lt;th&gt;cum tokens&lt;/th&gt;
&lt;th&gt;naive $&lt;/th&gt;
&lt;th&gt;cached $&lt;/th&gt;
&lt;th&gt;compacted $&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;147,500&lt;/td&gt;
&lt;td&gt;0.0384&lt;/td&gt;
&lt;td&gt;0.0220&lt;/td&gt;
&lt;td&gt;0.0384&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;2,237,500&lt;/td&gt;
&lt;td&gt;0.5817&lt;/td&gt;
&lt;td&gt;0.3015&lt;/td&gt;
&lt;td&gt;0.3267&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;8,225,000&lt;/td&gt;
&lt;td&gt;2.1385&lt;/td&gt;
&lt;td&gt;1.0896&lt;/td&gt;
&lt;td&gt;0.6907&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A 100-step task isn't 10× a 10-step task — it's &lt;strong&gt;56×&lt;/strong&gt;. Your 50th tool call's input costs 10× your first. &lt;strong&gt;Caching bends the curve (lowers the constant); only compaction breaks it&lt;/strong&gt; — capping the context window turns the quadratic linear, and the gap widens without bound as loops get longer. They compose: cached &lt;em&gt;and&lt;/em&gt; compacted is read-rate pricing on a linear token count. For any loop past ~20 steps, do both.&lt;/p&gt;

&lt;p&gt;This closes the loop on the whole guide: the quadratic re-send is exactly why agent workloads are so input-heavy and so cache-dependent — the entire shared workload profile falls out of this one chapter.&lt;/p&gt;




&lt;h2&gt;
  
  
  The cheat sheet
&lt;/h2&gt;

&lt;p&gt;Everything above, compressed to decisions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decision&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Which model?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cheap efficient hybrid (DeepSeek V3.2-class). Cheap output + high success beats everything on cost-per-solved.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;One provider or many?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Blend via LP. First ~40% of any jurisdiction/diversity constraint is usually free.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Self-host?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No — for cost. Renting always loses for commodity models; only owned next-gen hardware at &amp;gt;72% utilization wins. Self-host for privacy/control.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reasoning model?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Only if its output tokens are cheap. A pricey heavy reasoner can be mathematically uncatchable on cost-per-solved.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Retries?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cascade to a &lt;em&gt;different&lt;/em&gt;, stronger model — never retry the same one. 3 tiers ≈ 99.5% coverage at ~6× lower cost than going straight to frontier.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Commit to reserved capacity?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Only for sticky frontier prices, short terms. Never for commodity models in a market falling 50–90%/yr.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Caching?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Always, for any reused prefix. Pays from call 2–3. Prefer 0.1×-read providers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Long agent loops?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cap the context window (compaction) past ~20 steps, or pay quadratically.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;The whole thing is &lt;a href="https://github.com/copyleftdev/rational" rel="noopener noreferrer"&gt;a repo&lt;/a&gt;. Each chapter is a self-contained script that shells out to &lt;a href="https://github.com/copyleftdev/agent-calc" rel="noopener noreferrer"&gt;&lt;code&gt;agent-calc&lt;/code&gt;&lt;/a&gt;; each input price lives in &lt;code&gt;data/&lt;/code&gt; with a source URL and observation date.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/copyleftdev/rational
make all       &lt;span class="c"&gt;# re-run every chapter&lt;/span&gt;
make ch04      &lt;span class="c"&gt;# or just one&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same inputs → bit-identical outputs, every time. The LLM did the modeling and pulled the data. The math kernel did the math. That division of labor is the only reason I trust any number in this article — and it's the part I'd encourage you to steal.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>costoptimization</category>
      <category>agents</category>
    </item>
    <item>
      <title>AI Didn't Invent Slop. It Only Made It Infinite.</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Sat, 27 Jun 2026 00:01:32 +0000</pubDate>
      <link>https://dev.to/copyleftdev/ai-didnt-invent-slop-it-only-made-it-infinite-21o4</link>
      <guid>https://dev.to/copyleftdev/ai-didnt-invent-slop-it-only-made-it-infinite-21o4</guid>
      <description>&lt;p&gt;Every generation believes it is witnessing the death of taste.&lt;/p&gt;

&lt;p&gt;The printing press was going to flood the world with trash. The cheap camera was going to destroy photography. The internet was going to drown serious thought in blogs, forums, spam, and noise. Smartphones were going to turn every sacred moment into a blurry rectangle.&lt;/p&gt;

&lt;p&gt;Now artificial intelligence, we are told, has brought us to the final collapse: endless images, endless songs, endless essays, endless pull requests that compile and ship and mean nothing.&lt;/p&gt;

&lt;p&gt;We call it AI slop.&lt;/p&gt;

&lt;p&gt;And to be fair, much of it deserves the name.&lt;/p&gt;

&lt;p&gt;You can feel it when you see it. The over-polished fantasy portrait. The too-perfect lighting. The fake article that says everything and means nothing. And if you write software: the 600-line PR that passes CI and no human can explain. The README generated by a machine that has never run the code. The test suite with 100% coverage that asserts only that the mock returned the mock.&lt;/p&gt;

&lt;p&gt;It is work nobody will remember making.&lt;/p&gt;

&lt;p&gt;It has texture but no conviction. Output, but no memory of why.&lt;/p&gt;

&lt;p&gt;But AI did not invent slop.&lt;/p&gt;

&lt;p&gt;It only made it infinite.&lt;/p&gt;

&lt;h2&gt;
  
  
  We Have Been Here Before
&lt;/h2&gt;

&lt;p&gt;There was a time when a photograph meant something simply because it was difficult to make.&lt;/p&gt;

&lt;p&gt;A camera was not just an object. It was a ritual. Film had to be bought. Shots had to be chosen. Light had to be respected. Mistakes cost money. The photographer carried the burden of scarcity.&lt;/p&gt;

&lt;p&gt;Then cameras became cheap, then digital, then they entered every pocket on Earth. Suddenly, humanity became a species of photographers. We photographed lunch, and mirrors, and sunsets we barely watched. We created billions of images, most of them forgotten before the day ended.&lt;/p&gt;

&lt;p&gt;Photography did not die.&lt;/p&gt;

&lt;p&gt;But the average photograph became meaningless.&lt;/p&gt;

&lt;p&gt;That distinction matters. The medium survived. The scarcity did not.&lt;/p&gt;

&lt;p&gt;No one calls it "camera slop," but perhaps we should have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slop Is What Happens When Creation Becomes Cheap
&lt;/h2&gt;

&lt;p&gt;This is the uncomfortable truth underneath the AI panic:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Whenever the cost of creation collapses, the volume of mediocre work explodes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is not a flaw unique to artificial intelligence. It is one of the oldest patterns in media history — and it has names. Sturgeon's Law already told us that ninety percent of everything is forgettable. What changes, across eras, is only how cheaply we can manufacture the ninety percent.&lt;/p&gt;

&lt;p&gt;When printing became cheaper, the world got pamphlets, propaganda, gossip sheets, and disposable novels. When desktop publishing arrived, everyone became a designer. When blogging platforms arrived, everyone became a columnist. When GitHub made it trivial to publish code, every weekend produced ten thousand repos that would never see a second commit.&lt;/p&gt;

&lt;p&gt;Every tool that democratizes creation also democratizes mediocrity.&lt;/p&gt;

&lt;p&gt;That sounds cruel, but it is not. It is simply math. When the gates open, more people enter. Most are beginners. Many are opportunists. Some are brilliant. The room gets louder before it gets better.&lt;/p&gt;

&lt;p&gt;AI is not breaking that pattern. AI is accelerating it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slop Is a Taste Crisis, Not a Technology Crisis
&lt;/h2&gt;

&lt;p&gt;The real danger of AI slop is not that machines can make things.&lt;/p&gt;

&lt;p&gt;The danger is that humans may stop caring whether the things are worth making.&lt;/p&gt;

&lt;p&gt;That is the disease. Not automation. Indifference.&lt;/p&gt;

&lt;p&gt;Slop is not defined by the fact that AI was used. It is defined by the absence of intention. A human can make slop with a camera. A human can make slop with a paintbrush. A human can make slop with vim and forty years of experience and a million-dollar budget.&lt;/p&gt;

&lt;p&gt;Slop is not a medium. Slop is a relationship to creation.&lt;/p&gt;

&lt;p&gt;It is what happens when the goal is output instead of meaning. Velocity instead of correctness. Shipped instead of understood.&lt;/p&gt;

&lt;p&gt;The machine did not create that hunger. The machine simply feeds it faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  The System Loves Slop
&lt;/h2&gt;

&lt;p&gt;Slop thrives because the systems around us reward frequency.&lt;/p&gt;

&lt;p&gt;Merge faster. Chase the metric. Bump the contribution graph. Worship the green build. Close the ticket. Remove the silence where thinking used to live.&lt;/p&gt;

&lt;p&gt;AI fits perfectly into this economy because AI is tireless. It does not sleep, or get bored, or stare at a failing test for three days before finding the one assumption that was wrong from the start.&lt;/p&gt;

&lt;p&gt;The pipeline wants endless output. AI can provide it.&lt;/p&gt;

&lt;p&gt;That marriage — between machine generation and a culture that measures motion instead of meaning — is where slop becomes industrial. Not because AI is evil. Because infinite production met infinite distribution, and nobody in the middle asked whether any of it mattered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Copilot Did Not Make You an Engineer
&lt;/h2&gt;

&lt;p&gt;A cheap camera allowed anyone to take a picture. It did not make everyone a photographer.&lt;/p&gt;

&lt;p&gt;A laptop allowed anyone to make music. It did not make everyone a musician.&lt;/p&gt;

&lt;p&gt;A blog allowed anyone to publish. It did not make everyone a thinker.&lt;/p&gt;

&lt;p&gt;Copilot lets anyone generate working code. It does not make everyone an engineer.&lt;/p&gt;

&lt;p&gt;This is where the confusion begins. We keep mistaking access for mastery.&lt;/p&gt;

&lt;p&gt;The tool can produce the surface of a thing. It can mimic the genre, satisfy the linter, pass the tests it also wrote. It can imitate the grammar of competence.&lt;/p&gt;

&lt;p&gt;But engineering is not merely code that runs.&lt;/p&gt;

&lt;p&gt;It is selection, restraint, and the refusal to write the clever abstraction that will rot in eighteen months — even though the model offered it, ready to paste, today. It is a human being deciding that one design matters more than another and being able to say &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;AI can generate a thousand implementations in an hour.&lt;/p&gt;

&lt;p&gt;The engineer is the one who knows which one should not exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scarce Resource Was Never the Tool
&lt;/h2&gt;

&lt;p&gt;For decades we confused engineering value with the difficulty of execution.&lt;/p&gt;

&lt;p&gt;The person who could write tight assembly possessed rare power. The person who could wrangle pointers, or hold a distributed system in their head, or make the build green, possessed rare power.&lt;/p&gt;

&lt;p&gt;But technology has a way of eating technique. Again and again, the machine absorbs what once required years of specialized execution. And every time, people panic and say the craft is dead.&lt;/p&gt;

&lt;p&gt;But the craft is not dead. It moves.&lt;/p&gt;

&lt;p&gt;When execution becomes easier, taste becomes more important. When production becomes abundant, judgment becomes more important.&lt;/p&gt;

&lt;p&gt;When everyone can generate a pull request, the real question becomes: who can read it? Who can see the load-bearing line? Who can look at infinite plausible code and say, &lt;em&gt;"Not that. This."&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  But Abundance Is Not the Enemy of Craft
&lt;/h2&gt;

&lt;p&gt;Here is the part the optimists get right and the part they get wrong.&lt;/p&gt;

&lt;p&gt;The right part: every explosion of mediocrity also expands the possibility of genius. Cheap cameras gave us billions of forgettable images — and handed visual language to people who would never have entered a photography school. Home studios created oceans of bad music — and gave us bedroom producers who reshaped global sound. The early web buried us in spam — and also gave us Linux, Wikipedia, and Stack Overflow, each built from the same flood of amateur contribution that produced the junk.&lt;/p&gt;

&lt;p&gt;Democratization tends to move in waves. The first wave is noise. The second is imitation. The third discovers what the medium is actually for.&lt;/p&gt;

&lt;p&gt;The wrong part — the part the optimists wave away — is that the third wave is not guaranteed. Plenty of ecosystems hit the noise wave and simply stayed there, or died: local newspapers did not ascend to some higher form, they collapsed and did not come back. "It worked out before" is not a law of nature. It is a bet. The honest claim is narrower: abundance &lt;em&gt;makes a better equilibrium possible&lt;/em&gt;. It does not deliver one. Someone has to do the choosing.&lt;/p&gt;

&lt;h2&gt;
  
  
  But Won't the Machine Just Do the Choosing Too?
&lt;/h2&gt;

&lt;p&gt;This is the strongest objection to everything above, so let's not dodge it.&lt;/p&gt;

&lt;p&gt;Every earlier democratization left one thing untouched: a human layer that decided what was good. The press multiplied books, but humans still chose what to read. The camera multiplied images, but humans still chose what to hang on the wall. The scarce resource could shift to judgment precisely because judgment stayed ours.&lt;/p&gt;

&lt;p&gt;AI attacks both sides of that deal at once. It floods faster than any reviewer can read — and it is being trained, right now, to &lt;em&gt;do&lt;/em&gt; the reviewing: to rank, to critique, to pick the better of two diffs. If the machine can write the thousand implementations, why can't it choose the one that should exist?&lt;/p&gt;

&lt;p&gt;Partly, it can. Taste is not magic. Much of it is pattern, and patterns are trainable. An honest version of this argument has to concede that "humans simply judge better" is a moat that will not hold — the same way "humans simply write assembly better" did not hold.&lt;/p&gt;

&lt;p&gt;But there is a remainder, and it is not a skill. It is accountability.&lt;/p&gt;

&lt;p&gt;Someone has to be the one who says &lt;em&gt;ship it&lt;/em&gt; and owns what comes next — the outage, the breach, the regression that reaches a million users, the quiet harm nobody modeled. A system can rank the options. It cannot be answerable for the choice. The engineer who clicks merge is not just exercising sharper judgment than the generator; they are the human a consequence can attach to.&lt;/p&gt;

&lt;p&gt;So the moat is not "we judge better." That one erodes. The moat is "we are responsible." Discernment is the craft you sharpen. Accountability is the part the machine structurally cannot take, because responsibility requires someone who can actually be held to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Engineer Becomes an Editor of Infinity
&lt;/h2&gt;

&lt;p&gt;The next great technical skill may not be generation. It may be discernment exercised under that responsibility.&lt;/p&gt;

&lt;p&gt;We already have a name for the work: &lt;strong&gt;review.&lt;/strong&gt; And it is moving from the chore at the edge of the job to the center of it.&lt;/p&gt;

&lt;p&gt;Watch what AI does to a team. It lifts a junior's &lt;em&gt;output&lt;/em&gt; to senior-looking quality almost overnight — clean, idiomatic, plausible. It does not lift their &lt;em&gt;judgment&lt;/em&gt; at the same rate. So the senior becomes the bottleneck, reviewing an infinite stream of confident, well-formatted diffs from people (and models) who cannot yet see what is wrong with them. "LGTM" stops being a rubber stamp and becomes the most dangerous sentence in the codebase. The reviewer becomes the rate limiter on quality for the entire organization.&lt;/p&gt;

&lt;p&gt;That is the job now. Not typing faster. Reading better.&lt;/p&gt;

&lt;p&gt;The engineer of the next decade is part architect, part editor, part skeptic — someone who can run the machine without serving it, who generates without limit, then cuts without mercy. Someone with memory. Someone with scars from the last system that paged them at 3 a.m.&lt;/p&gt;

&lt;p&gt;Because when any code can be written instantly, the most valuable thing you can do is refuse to merge most of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slop Is the Shadow of Democratization
&lt;/h2&gt;

&lt;p&gt;AI slop is real. It is everywhere — feeds, marketplaces, search results, issue trackers, and the diff you have to review this afternoon.&lt;/p&gt;

&lt;p&gt;But it is not an alien substance. It is the shadow that appears whenever creation becomes easier than judgment. Scarcity used to do some of our filtering for us: difficulty kept the repo smaller, cost slowed people down, the sheer friction of writing it yourself meant you mostly wrote what you meant. Now that friction is gone, and the burden shifts back to us. We have to decide what matters.&lt;/p&gt;

&lt;p&gt;The cheap camera did not destroy photography. It destroyed the illusion that every photograph was precious. AI will not destroy engineering. It will destroy the illusion that every act of generation is creative.&lt;/p&gt;

&lt;p&gt;And maybe that is necessary. Maybe we are being forced to admit what was always true: the magic was never in the tool. The magic was in the seeing and the choosing — in taking the chaos of a problem and shaping it into something that says:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I was here. I understood this. This mattered.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the age of infinite slop, that may become the rarest thing of all.&lt;/p&gt;




&lt;h2&gt;
  
  
  Notes on the Argument
&lt;/h2&gt;

&lt;p&gt;This is a historical argument, not a technological one, and it is a synthesis rather than a discovered law — so here is the lineage it rests on, made explicit so you can check it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sturgeon's Law&lt;/strong&gt; — "ninety percent of everything is crap." The baseline claim that most output in any field is forgettable. (&lt;a href="https://en.wikipedia.org/wiki/Sturgeon%27s_law" rel="noopener noreferrer"&gt;ref&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clay Shirky's "mass amateurization"&lt;/strong&gt; — when you remove the barrier to publishing, you don't get less junk, you get "publish, then filter": the filtering moves &lt;em&gt;downstream&lt;/em&gt;, onto the reader. This essay's "engineer as editor" is that filter, relocated to code. (&lt;a href="https://en.wikipedia.org/wiki/Clay_Shirky" rel="noopener noreferrer"&gt;ref&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Jevons paradox&lt;/strong&gt; — making something cheaper to produce raises total consumption rather than lowering it. Cheaper creation means &lt;em&gt;more&lt;/em&gt; creation, not less — now widely invoked for AI. (&lt;a href="https://en.wikipedia.org/wiki/Jevons_paradox" rel="noopener noreferrer"&gt;ref&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The concrete parallels are well documented: the printing press produced a flood of cheap Reformation pamphlets alongside its enduring works (&lt;a href="https://en.wikipedia.org/wiki/Pamphlet_wars" rel="noopener noreferrer"&gt;ref&lt;/a&gt;); consumer and smartphone photography pushed the world past a trillion-plus photos a year (&lt;a href="https://www.statista.com/chart/10913/number-of-photos-taken-worldwide/" rel="noopener noreferrer"&gt;ref&lt;/a&gt;); desktop publishing democratized design (and gave us the "ransom note" era), while content farms like Demand Media industrialized algorithmic filler until Google's Panda update was built to bury it (&lt;a href="https://variety.com/2013/biz/news/epic-fail-the-rise-and-fall-of-demand-media-1200914646/" rel="noopener noreferrer"&gt;ref&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The argument deliberately holds two ideas at once: &lt;strong&gt;democratization of creation&lt;/strong&gt; (good — more people gain the tools) and &lt;strong&gt;a decline in average quality&lt;/strong&gt; (the expected cost when participation grows from thousands to millions). They are complementary, not contradictory. Reasonable people can disagree with where it lands. The point is to offer a frame for the debate, not to claim it is settled.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Note on Collaboration
&lt;/h2&gt;

&lt;p&gt;This essay was written through a collaboration between a human author and AI. The ideas, the thesis, the structure, and every editorial decision came from a human; AI was used as a thinking partner and drafting tool, and the historical claims above were checked against the sources cited.&lt;/p&gt;

&lt;p&gt;Writers have always worked with tools — editors, dictionaries, research assistants, cameras, compilers, spell checkers, search engines. AI is another one, albeit a remarkably capable one. The quality of a work has never been determined solely by the sophistication of the tool that helped make it. It has always been determined by the quality of the thinking behind it.&lt;/p&gt;

&lt;p&gt;Judge this essay by its reasoning. Not by the instrument used to write it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Disclosed per &lt;a href="https://dev.to/devteam/guidelines-for-ai-assisted-articles-on-dev-17n6"&gt;DEV's guidelines for AI-assisted articles&lt;/a&gt;.)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>discuss</category>
      <category>codequality</category>
    </item>
  </channel>
</rss>
