<?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>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;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&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>
    <item>
      <title>Cogs and Sparks: Who Wins When Machines Learn to Speak Human</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Sat, 13 Jun 2026 22:57:15 +0000</pubDate>
      <link>https://dev.to/copyleftdev/cogs-and-sparks-who-wins-when-machines-learn-to-speak-human-43dc</link>
      <guid>https://dev.to/copyleftdev/cogs-and-sparks-who-wins-when-machines-learn-to-speak-human-43dc</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Disclosure: this article was written from my own thesis and lived experience, then shaped and edited with AI assistance. I reviewed the argument, revised the structure, and stand behind the ideas here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For most of the digital age, humans had to learn how to think like machines.&lt;/p&gt;

&lt;p&gt;We memorized syntax. We learned rigid menus, brittle interfaces, command lines, templates, ticket flows, and rules that punished ambiguity. We trained ourselves to break imagination into tiny mechanical instructions because computers could not meet us halfway.&lt;/p&gt;

&lt;p&gt;To make technology useful, we first had to translate ourselves into its language.&lt;/p&gt;

&lt;p&gt;That translation did not just shape software. It shaped people.&lt;/p&gt;

&lt;p&gt;The modern workplace rewarded the person who could become a little machine-like: precise, procedural, reliable, consistent, patient with repetition, able to memorize commands and tolerate the tedious work required to keep the system moving.&lt;/p&gt;

&lt;p&gt;Those people mattered. They still matter.&lt;/p&gt;

&lt;p&gt;They were the cogs.&lt;/p&gt;

&lt;p&gt;And for a long time, being a good cog was a survival strategy.&lt;/p&gt;

&lt;p&gt;But AI changes the direction of adaptation.&lt;/p&gt;

&lt;p&gt;For the first time, machines are learning to move toward us. They are learning language, context, style, pattern, intent, image, tone, code, conversation, and approximation. They are still flawed. They still hallucinate. They still need judgment, taste, and correction.&lt;/p&gt;

&lt;p&gt;But the direction is unmistakable.&lt;/p&gt;

&lt;p&gt;The machine is no longer asking only:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can you speak machine?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is beginning to ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can you show me what you mean?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That shift changes who gets leverage.&lt;/p&gt;

&lt;p&gt;The old world favored the cog.&lt;/p&gt;

&lt;p&gt;The new world favors the spark.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cog Was Never the Problem
&lt;/h2&gt;

&lt;p&gt;A cog is not an insult.&lt;/p&gt;

&lt;p&gt;Cogs are dependable. Cogs execute. Cogs maintain order. Cogs remember how the system works when everyone else is chasing novelty. Cogs show up. They keep the lights on. They learn the process and repeat it with precision.&lt;/p&gt;

&lt;p&gt;Every serious system needs cogs.&lt;/p&gt;

&lt;p&gt;The problem is not the cog.&lt;/p&gt;

&lt;p&gt;The problem is a world that taught people the safest way to survive was to become only a cog.&lt;/p&gt;

&lt;p&gt;For decades, technical leverage lived behind gates. If you could not code, you could not build software. If you could not design, you could not ship a product experience. If you could not navigate the tools, you needed someone else to translate your idea into execution.&lt;/p&gt;

&lt;p&gt;That gatekeeping was not always malicious. Much of it was just mechanical reality. Computers were powerful, but they were not generous. You had to meet them on their terms.&lt;/p&gt;

&lt;p&gt;So the system rewarded people who could memorize the terms.&lt;/p&gt;

&lt;p&gt;But many people never fit that world cleanly.&lt;/p&gt;

&lt;p&gt;They were visual thinkers in text-only systems. Writers in spreadsheet cultures. Artists trapped behind tool complexity. Teachers with product instincts but no engineering team. Generalists who could see connections but lacked the credentialed path to execute them.&lt;/p&gt;

&lt;p&gt;They were sparks in a cog-shaped world.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Spark Does
&lt;/h2&gt;

&lt;p&gt;A spark sees possibility before there is a process.&lt;/p&gt;

&lt;p&gt;A spark experiments before there is permission.&lt;/p&gt;

&lt;p&gt;A spark can look at two unrelated things and feel the bridge between them before they can fully explain it.&lt;/p&gt;

&lt;p&gt;Sparks ask strange questions. They remix. They test. They wander. They notice tone, friction, story, behavior, emotion, and timing.&lt;/p&gt;

&lt;p&gt;Sparks are artists, writers, designers, teachers, builders, founders, comedians, strategists, researchers, tinkerers, and curious people who were often told they were impractical because their value did not fit the spreadsheet.&lt;/p&gt;

&lt;p&gt;In the old world, sparks often needed cogs to translate them.&lt;/p&gt;

&lt;p&gt;In the AI world, sparks get a new kind of leverage.&lt;/p&gt;

&lt;p&gt;AI lowers the cost of execution. It can draft, summarize, code, calculate, organize, translate, simulate, critique, generate, and iterate. It can turn a vague sketch into a prototype, a paragraph into a campaign, a napkin idea into a working demo, a conversation into a plan.&lt;/p&gt;

&lt;p&gt;That does not make the work automatic.&lt;/p&gt;

&lt;p&gt;It moves the bottleneck.&lt;/p&gt;

&lt;p&gt;The question is no longer only:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Who can perform the task?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The question becomes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Who can imagine the right thing worth doing?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Bottleneck Moves Upward
&lt;/h2&gt;

&lt;p&gt;When execution gets cheaper, taste gets more expensive.&lt;/p&gt;

&lt;p&gt;When syntax gets easier, judgment matters more.&lt;/p&gt;

&lt;p&gt;When tools can produce ten versions in seconds, the valuable person is not the one impressed by abundance. It is the one who can tell which version is alive.&lt;/p&gt;

&lt;p&gt;That is the real AI transition.&lt;/p&gt;

&lt;p&gt;Not from human to machine.&lt;/p&gt;

&lt;p&gt;From memorization to judgment.&lt;/p&gt;

&lt;p&gt;From task completion to problem framing.&lt;/p&gt;

&lt;p&gt;From obedience to direction.&lt;/p&gt;

&lt;p&gt;From labor as identity to creation as leverage.&lt;/p&gt;

&lt;p&gt;The person who can only follow instructions will increasingly compete with machines that follow instructions faster.&lt;/p&gt;

&lt;p&gt;The person who can create better instructions, better constraints, better questions, better taste, and better visions becomes more powerful.&lt;/p&gt;

&lt;p&gt;This is why the spark matters.&lt;/p&gt;

&lt;p&gt;A spark does not merely ask an AI to make something. A spark senses what is missing. A spark knows when the output is technically correct but emotionally dead. A spark can say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No, not that. Make it quieter. Make it sharper. Make it feel like a system designed by someone who has actually lived this problem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is not button-pushing.&lt;/p&gt;

&lt;p&gt;That is direction.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Developers
&lt;/h2&gt;

&lt;p&gt;Developers are in a strange position because we are both protected and exposed by this shift.&lt;/p&gt;

&lt;p&gt;We understand the machinery better than most people. That matters. AI-generated code still needs review, architecture, debugging, security judgment, and production discipline. The machine can create plausible code faster than it can understand consequences.&lt;/p&gt;

&lt;p&gt;But we should not mistake that for safety.&lt;/p&gt;

&lt;p&gt;If our value is only that we remember syntax, our value is shrinking.&lt;/p&gt;

&lt;p&gt;If our value is that we can reason about systems, frame problems, notice edge cases, understand users, evaluate tradeoffs, and build things that survive contact with reality, our value compounds.&lt;/p&gt;

&lt;p&gt;The best developer in the AI era is not the one who refuses the tool.&lt;/p&gt;

&lt;p&gt;It is also not the one who blindly trusts it.&lt;/p&gt;

&lt;p&gt;It is the one who can use the tool without surrendering judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cog Has to Remap
&lt;/h2&gt;

&lt;p&gt;If you were trained by the old world, this shift can feel insulting.&lt;/p&gt;

&lt;p&gt;You spent years learning the hard way. You memorized commands. You built discipline. You earned your scars. Now a beginner can prompt a machine and get something that looks, at first glance, like the thing you worked years to produce.&lt;/p&gt;

&lt;p&gt;That reaction is understandable.&lt;/p&gt;

&lt;p&gt;But resentment is a bad strategy.&lt;/p&gt;

&lt;p&gt;The cog does not need to disappear. The cog needs to remap.&lt;/p&gt;

&lt;p&gt;Here are the shifts I think matter most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From certainty to experimentation. In the old world, being right early was rewarded. In the AI world, discovery often comes from fast comparison.&lt;/li&gt;
&lt;li&gt;From memorization to judgment. Facts are easier to retrieve. Syntax is easier to generate. But judgment remains scarce.&lt;/li&gt;
&lt;li&gt;From task completion to problem framing. A weak frame creates polished garbage. A strong frame creates leverage.&lt;/li&gt;
&lt;li&gt;From obedience to imagination. When machines can produce correct-enough work quickly, direction becomes practical.&lt;/li&gt;
&lt;li&gt;From effort to impact. If something becomes easier, it does not become meaningless. It means the value moves upward.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The question is not whether you can still do the hard thing manually.&lt;/p&gt;

&lt;p&gt;The question is whether you can aim the system toward something worth building.&lt;/p&gt;

&lt;h2&gt;
  
  
  The New Creative Class Is Broader Than We Think
&lt;/h2&gt;

&lt;p&gt;The painter who could not code can now prototype an app.&lt;/p&gt;

&lt;p&gt;The writer who could not design can now shape a visual world.&lt;/p&gt;

&lt;p&gt;The teacher who could not afford a product team can now build a learning experience.&lt;/p&gt;

&lt;p&gt;The mechanic can become an automation builder.&lt;/p&gt;

&lt;p&gt;The founder without funding can test the first version before asking anyone for permission.&lt;/p&gt;

&lt;p&gt;The future may not belong only to the people who were best at computers.&lt;/p&gt;

&lt;p&gt;It may belong to the people who were best at being human, now armed with computers that can finally keep up.&lt;/p&gt;

&lt;p&gt;This does not mean technical skill stops mattering.&lt;/p&gt;

&lt;p&gt;Deep expertise still matters. Engineering still matters. Precision still matters. In fact, expertise may matter more because AI can produce confident nonsense at scale. Someone has to know what good looks like.&lt;/p&gt;

&lt;p&gt;But the ceiling rises for people who were previously blocked by technical gates.&lt;/p&gt;

&lt;p&gt;The next great product designer might be a poet.&lt;/p&gt;

&lt;p&gt;The next great software founder might be a teacher.&lt;/p&gt;

&lt;p&gt;The next great systems thinker might be someone who never called themselves technical because the old tools made them feel stupid.&lt;/p&gt;

&lt;p&gt;They were not stupid.&lt;/p&gt;

&lt;p&gt;They were early to a world that had not built the right interface yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hybrid Wins
&lt;/h2&gt;

&lt;p&gt;The spark alone is not enough.&lt;/p&gt;

&lt;p&gt;Unfocused creativity becomes noise. Ideas without discipline become vapor. Taste without execution becomes performance.&lt;/p&gt;

&lt;p&gt;The cog alone is not enough either.&lt;/p&gt;

&lt;p&gt;Perfect execution of the wrong thing is still waste. Process without imagination becomes maintenance of a dying machine.&lt;/p&gt;

&lt;p&gt;The people who win are hybrids.&lt;/p&gt;

&lt;p&gt;They have the discipline of the cog and the imagination of the spark. They can execute, but they can also question the premise. They can use the tool, but they are not hypnotized by it. They can move fast without confusing motion for meaning.&lt;/p&gt;

&lt;p&gt;The cog must learn to spark.&lt;/p&gt;

&lt;p&gt;The spark must learn to aim.&lt;/p&gt;

&lt;p&gt;And the best builders will become both: precise enough to finish, imaginative enough to invent, and adaptable enough to keep changing as the tools change.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Machine Is Bending Toward Us
&lt;/h2&gt;

&lt;p&gt;The great mistake is to treat AI as merely a faster machine for old work.&lt;/p&gt;

&lt;p&gt;That is the shallow reading.&lt;/p&gt;

&lt;p&gt;The deeper reading is that AI changes who gets to participate. It gives language, imagination, taste, and judgment a new kind of leverage. It lets people who were once trapped outside the machinery step closer to the center.&lt;/p&gt;

&lt;p&gt;For years, humans had to bend toward the machine.&lt;/p&gt;

&lt;p&gt;Now the machine is bending toward humans.&lt;/p&gt;

&lt;p&gt;That is not the end of human value.&lt;/p&gt;

&lt;p&gt;It is the beginning of a different test.&lt;/p&gt;

&lt;p&gt;Not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can you remember the command?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can you tolerate the process?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can you make yourself small enough to fit the machine?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can you see what is possible?&lt;/p&gt;

&lt;p&gt;Can you tell what is good?&lt;/p&gt;

&lt;p&gt;Can you aim the spark before it burns out?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the work now.&lt;/p&gt;




&lt;p&gt;AI-assistance note: I used AI to help structure and edit this essay, but the central argument, final review, and publication responsibility are mine.&lt;/p&gt;

&lt;p&gt;Topics: #AI #Programming #DeveloperCareer #Creativity&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Stop Feeding Agents Raw Data</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Tue, 09 Jun 2026 06:05:05 +0000</pubDate>
      <link>https://dev.to/copyleftdev/stop-feeding-agents-raw-data-2kif</link>
      <guid>https://dev.to/copyleftdev/stop-feeding-agents-raw-data-2kif</guid>
      <description>&lt;p&gt;I used to think the problem was the agent.&lt;/p&gt;

&lt;p&gt;I would hand it a large JSON export and ask a reasonable question: what changed, what looks risky, what should we investigate before release?&lt;/p&gt;

&lt;p&gt;It would find something. It always found something.&lt;/p&gt;

&lt;p&gt;But it missed fields. It over-indexed on irrelevant values. It hallucinated patterns in JSON that weren't there. It noticed one dramatic-looking record and ignored the boring distribution that made the record meaningful. So I tried the usual fixes: stricter prompts, longer instructions, bigger context windows, more examples.&lt;/p&gt;

&lt;p&gt;The real problem was simpler.&lt;/p&gt;

&lt;p&gt;I was handing the agent noisy context.&lt;/p&gt;

&lt;p&gt;Not bad data. Bad context.&lt;/p&gt;

&lt;p&gt;Raw structured data is full of repetition, incidental shape, schema noise, nulls, IDs, timestamps, nested boilerplate, and fields that only mean something in aggregate. Humans struggle with that. Agents do too.&lt;/p&gt;

&lt;p&gt;If you paste a huge API response, GitHub export, log dump, CSV, or source tree into a model and ask it to "find what matters," you are asking the model to do two jobs at once:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Measure the data.&lt;/li&gt;
&lt;li&gt;Reason about the measurements.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Those are different jobs.&lt;/p&gt;

&lt;p&gt;Vajra is my attempt to split them apart.&lt;/p&gt;

&lt;p&gt;Before the model reasons, Vajra measures. Before the agent plans, Vajra reduces the raw input into evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Agent Context Problem
&lt;/h2&gt;

&lt;p&gt;The default agent workflow is still too close to copy and paste.&lt;/p&gt;

&lt;p&gt;Give the agent a repository. Give it a JSON dump. Give it a pile of logs. Give it a directory of semi-structured files. Then ask it to infer structure, identify anomalies, detect drift, preserve evidence, and decide what to do next.&lt;/p&gt;

&lt;p&gt;That sounds powerful, but it is a bad division of labor.&lt;/p&gt;

&lt;p&gt;Agents are useful for interpretation, synthesis, planning, and tradeoff analysis. They are not the best tool for counting every path in a nested document, computing entropy across values, comparing two distributions, detecting type instability, or producing a repeatable fingerprint of a shape.&lt;/p&gt;

&lt;p&gt;Those jobs should be done by boring software.&lt;/p&gt;

&lt;p&gt;Reliable software.&lt;/p&gt;

&lt;p&gt;Software that returns the same answer every time.&lt;/p&gt;

&lt;p&gt;That is the layer I wanted in front of the agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Vajra Does
&lt;/h2&gt;

&lt;p&gt;Vajra is a Rust CLI and library for analyzing structured data. It started from a simple frustration with large JSON, then grew into a signal layer for things agents routinely ingest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;structured data like JSON, NDJSON, YAML, CSV, and TSV&lt;/li&gt;
&lt;li&gt;operational artifacts like Markdown, PDF text, CPU profiles, and strace logs&lt;/li&gt;
&lt;li&gt;repositories, GitHub exports, and source code parsed through tree-sitter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not fuzzy summarization. The goal is stable measurement.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vajra inspect payload.json
vajra stats events.ndjson
vajra anomalies batch.json
vajra drift baseline.json current.json
vajra essence payload.json &lt;span class="nt"&gt;--profile&lt;/span&gt; ai &lt;span class="nt"&gt;--format&lt;/span&gt; compact-ai &lt;span class="nt"&gt;--budget&lt;/span&gt; 500 &lt;span class="nt"&gt;--redact&lt;/span&gt;
vajra inspect src/main.rs &lt;span class="nt"&gt;--input-format&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="nt"&gt;--lang&lt;/span&gt; rust &lt;span class="nt"&gt;--semantic-paths&lt;/span&gt;
vajra governance commits.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That gives you paths, types, fingerprints, entropy, cardinality, outliers, rarity, schema drift, source-code structure, contributor concentration, and compact essences that are designed to be read by humans or agents.&lt;/p&gt;

&lt;p&gt;The important word is stable.&lt;/p&gt;

&lt;p&gt;Same input. Same config. Same version. Same result.&lt;/p&gt;

&lt;p&gt;That matters more than it sounds.&lt;/p&gt;

&lt;p&gt;If an agent is going to call a tool, update a plan, make a recommendation, and then call the tool again after a change, the tool cannot behave like a mood ring. It has to be an instrument.&lt;/p&gt;

&lt;h2&gt;
  
  
  Raw Data Is Not Context
&lt;/h2&gt;

&lt;p&gt;Here is the mistake I kept making.&lt;/p&gt;

&lt;p&gt;I treated "available to the model" as equivalent to "usable by the model."&lt;/p&gt;

&lt;p&gt;They are not the same.&lt;/p&gt;

&lt;p&gt;A 5 MB JSON export may fit in a context window. That does not mean it is good context. Most of those tokens may be repeated object structure, duplicated IDs, common timestamps, low-signal values, or fields whose meaning only appears after aggregate analysis.&lt;/p&gt;

&lt;p&gt;Vajra turns that raw input into a smaller set of measured claims.&lt;/p&gt;

&lt;p&gt;Instead of giving an agent every record and hoping it notices that one path is unstable, give it a measured signal shaped like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Path: $.claims[*].status
Dominant type: string
Cardinality: 7
Entropy: 1.82
Rare values: reversed_manual, pending_external_review
Null rate: 0.00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of asking it to eyeball schema drift between two payloads, give it a drift report shaped like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Removed path: $.member.coverage.plan_id
Added path: $.member.coverage.policy_ref
Type changed: $.claim.amount string -&amp;gt; number
Distribution drift: $.claim.status high
Severity: critical
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of making it inspect a full repository export, give it project-health signals such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bus factor: 2
Contributor concentration: high
One-commit contributor rate: 0.61
Most active author share: 0.44
Velocity trend: declining
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These examples are representative shapes, not a promise that every command emits exactly these lines. The point is the workflow: let the tool compute the measurements, then let the agent reason from them.&lt;/p&gt;

&lt;p&gt;Now the agent can do the work it is actually useful for.&lt;/p&gt;

&lt;p&gt;It can reason about consequences. It can ask whether the drift is intentional. It can propose a migration plan. It can decide what evidence belongs in a report. It can open an issue with the relevant fields instead of a blob of raw data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure, Then Reason
&lt;/h2&gt;

&lt;p&gt;The agentic workflow I want looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;raw data / repo / logs / API export
    -&amp;gt; deterministic analysis
    -&amp;gt; compact evidence bundle
    -&amp;gt; agent reasoning
    -&amp;gt; action plan or code change
    -&amp;gt; re-analysis
    -&amp;gt; verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That loop is different from the usual paste-and-hope loop.&lt;/p&gt;

&lt;p&gt;The agent has fewer reasons to infer measurements from raw records. It gets to reason from measured facts.&lt;/p&gt;

&lt;p&gt;Vajra can sit before the model and decide what deserves attention. It compresses without pretending to be creative. It surfaces anomalies without pretending every anomaly is automatically important. It preserves paths and evidence so the agent can point back to the data.&lt;/p&gt;

&lt;p&gt;That is the difference between a summary and an instrument.&lt;/p&gt;

&lt;p&gt;A summary says, "Something changed."&lt;/p&gt;

&lt;p&gt;An instrument says, "This path changed, this value distribution moved, this type is unstable, and here is the evidence."&lt;/p&gt;

&lt;h2&gt;
  
  
  A Concrete Agent Workflow
&lt;/h2&gt;

&lt;p&gt;Imagine an agent responsible for reviewing a GitHub project before a release.&lt;/p&gt;

&lt;p&gt;The naive version gets a large export of issues, pull requests, commits, and releases. It tries to infer project health from raw records. It may notice recent failures, but miss contributor concentration. It may summarize issue titles, but miss stale ownership patterns. It may produce a confident report with weak evidence.&lt;/p&gt;

&lt;p&gt;The Vajra version starts by measuring first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vajra ingest-github owner/repo &lt;span class="nt"&gt;--output&lt;/span&gt; .vajra/repo
vajra governance .vajra/repo/commits.json &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .vajra/governance.json
vajra core-team .vajra/repo/commits.json &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .vajra/core-team.json
vajra anomalies .vajra/repo/issues.json &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .vajra/issue-anomalies.json
vajra essence .vajra/repo/issues.json &lt;span class="nt"&gt;--profile&lt;/span&gt; ai &lt;span class="nt"&gt;--format&lt;/span&gt; compact-ai &lt;span class="nt"&gt;--redact&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .vajra/issues.essence.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the agent does not need to start by reading everything.&lt;/p&gt;

&lt;p&gt;It reads the measurements.&lt;/p&gt;

&lt;p&gt;Instead of producing a vague release memo, it can flag specific evidence-backed risks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ownership concentrated in two maintainers&lt;/li&gt;
&lt;li&gt;unusual issue clusters before release&lt;/li&gt;
&lt;li&gt;repeated labels or states that deserve triage&lt;/li&gt;
&lt;li&gt;fields that changed shape across exports&lt;/li&gt;
&lt;li&gt;anomalies that need business context before they are treated as problems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the agent recommends action, the action can be checked.&lt;/p&gt;

&lt;p&gt;Did the generated report cite the right paths? Did the relevant anomaly disappear or become explainable? Did a migration remove the type instability? Did the same input produce the same output after a refactor?&lt;/p&gt;

&lt;p&gt;That is the kind of feedback loop agents need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Determinism Matters
&lt;/h2&gt;

&lt;p&gt;Agentic systems are already probabilistic at the reasoning layer. The tools around them should not add unnecessary randomness.&lt;/p&gt;

&lt;p&gt;If a tool summarizes differently every time, the agent's plan changes for reasons that are hard to debug. If a score cannot be decomposed, the agent cannot explain it. If a drift report is not stable, CI cannot trust it. If a fingerprint changes because object keys were ordered differently, the tool is measuring formatting noise instead of structure.&lt;/p&gt;

&lt;p&gt;Vajra is built around boring constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deterministic ordering&lt;/li&gt;
&lt;li&gt;stable fingerprints&lt;/li&gt;
&lt;li&gt;explicit paths&lt;/li&gt;
&lt;li&gt;explainable scores&lt;/li&gt;
&lt;li&gt;profile-driven reduction&lt;/li&gt;
&lt;li&gt;no silent mutation of source data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is not glamorous. It is what makes the output usable as agent context.&lt;/p&gt;

&lt;p&gt;Agents do not just need more context. They need context they can trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Does Not Solve
&lt;/h2&gt;

&lt;p&gt;This layer does not make judgment disappear.&lt;/p&gt;

&lt;p&gt;Vajra can measure structure and distributions. It does not decide whether an anomaly is business-important. It can flag contributor concentration. It cannot know whether that concentration is a temporary release push, an organizational risk, or just how a small project works.&lt;/p&gt;

&lt;p&gt;Compact essences are evidence bundles. They are not replacements for source data when auditability, legal review, or incident response requires the original records.&lt;/p&gt;

&lt;p&gt;And if sensitive data is involved, it should be redacted or minimized before it is sent to any model or external service. That is why the CLI supports &lt;code&gt;--redact&lt;/code&gt;, but the operational policy still belongs to you.&lt;/p&gt;

&lt;p&gt;The point is not to remove human or agent judgment.&lt;/p&gt;

&lt;p&gt;The point is to stop wasting judgment on work that deterministic tools can do better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where This Goes
&lt;/h2&gt;

&lt;p&gt;Serious agent systems will not be built from prompts alone.&lt;/p&gt;

&lt;p&gt;They need toolchains that produce reproducible intermediate artifacts. They need ways to shrink context without losing evidence. They need stable measurements before interesting reasoning.&lt;/p&gt;

&lt;p&gt;That is the bet behind Vajra.&lt;/p&gt;

&lt;p&gt;Not that agents should know everything.&lt;/p&gt;

&lt;p&gt;That agents should be handed better instruments.&lt;/p&gt;

&lt;p&gt;Because when you stop feeding agents raw data, you give them a better job:&lt;/p&gt;

&lt;p&gt;reasoning from evidence.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rust</category>
      <category>agents</category>
      <category>data</category>
    </item>
    <item>
      <title>The Container Runtime Nobody Told You About (And Four Others)</title>
      <dc:creator>Don Johnson</dc:creator>
      <pubDate>Tue, 26 May 2026 20:19:00 +0000</pubDate>
      <link>https://dev.to/copyleftdev/the-container-runtime-nobody-told-you-about-and-four-others-25e1</link>
      <guid>https://dev.to/copyleftdev/the-container-runtime-nobody-told-you-about-and-four-others-25e1</guid>
      <description>&lt;p&gt;Here's something the container ecosystem doesn't say loudly enough: &lt;strong&gt;runc is not the only option, and for a growing number of production workloads, it's the wrong one.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AWS Lambda doesn't run your function in a Docker container. It runs it in a Firecracker microVM. Fly.io's Machines? Firecracker fork. Google's multi-tenant GKE nodes? gVisor. Cloudflare Workers? WASM. These companies didn't reach for exotic runtimes because they were bored — they reached for them because the default isolation model was insufficient for their threat model, their latency requirements, or both.&lt;/p&gt;

&lt;p&gt;This article takes one tiny Go HTTP server and runs it through all five of them: &lt;strong&gt;runc/distroless, gVisor, Kata + QEMU, Kata + Firecracker, and WASM/WASI&lt;/strong&gt;. You'll see exactly what changes (almost nothing), what the real numbers look like, and — most importantly — which runtime belongs in which situation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; gVisor, Kata, and Firecracker all run the &lt;em&gt;exact same 3 MB OCI image&lt;/em&gt; — only &lt;code&gt;--runtime=X&lt;/code&gt; changes. WASM is a different compilation target entirely. Cold-start ranges from ~20 ms (runc) to ~500 ms (Kata/QEMU), with Firecracker splitting the difference at ~125 ms. Request latency overhead at steady state is shockingly small across all of them. The real cost is memory and compatibility, not throughput.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The App
&lt;/h2&gt;

&lt;p&gt;Before the runtimes, the subject. A Go HTTP server with one meaningful endpoint:&lt;/p&gt;


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


&lt;p&gt;&lt;code&gt;RUNTIME_NAME&lt;/code&gt; is injected at &lt;code&gt;docker run&lt;/code&gt; time. Everything else — Go version, arch, PID, uptime — is live from inside whatever sandbox is holding it. When the runtime changes, the response field tells the story.&lt;/p&gt;




&lt;h2&gt;
  
  
  Runtime 1: Distroless + runc
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What it is
&lt;/h3&gt;

&lt;p&gt;The default Docker runtime (&lt;code&gt;runc&lt;/code&gt;) but with a &lt;a href="https://github.com/GoogleContainerTools/distroless" rel="noopener noreferrer"&gt;distroless&lt;/a&gt; base image. No shell, no package manager, no &lt;code&gt;apt&lt;/code&gt;, no &lt;code&gt;curl&lt;/code&gt;. Just the Go binary and CA certificates.&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;The image comes out at 3.0 MB.&lt;/strong&gt; Alpine would be ~18 MB. Ubuntu ~80 MB.&lt;/p&gt;

&lt;h3&gt;
  
  
  The honest security story
&lt;/h3&gt;

&lt;p&gt;Distroless does not change your isolation model. The container still shares the host kernel. What it does is remove every tool an attacker would use after a successful exploit — no shell to drop into, no package manager to pull more tools from, no &lt;code&gt;/tmp&lt;/code&gt; scripts to run. You're not preventing the breach; you're making the post-breach environment hostile.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ultimate use cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Internal microservices in a trusted, single-tenant cluster&lt;/li&gt;
&lt;li&gt;GitOps pipelines where &lt;em&gt;you&lt;/em&gt; control every image in the registry&lt;/li&gt;
&lt;li&gt;Replacing fat Alpine images — the size drop alone is worth it&lt;/li&gt;
&lt;li&gt;The security baseline every team should hit before adding runtime overhead&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Runtime 2: gVisor (&lt;code&gt;runsc&lt;/code&gt;)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What it is
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://gvisor.dev" rel="noopener noreferrer"&gt;gVisor&lt;/a&gt; ships a user-space Linux kernel called the Sentry — written in Go — that runs alongside your container. Every syscall your container makes goes to the Sentry. The host kernel never sees your container's syscalls.&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="c"&gt;# Same 3 MB image. One flag.&lt;/span&gt;
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--runtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;runsc &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;RUNTIME_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gvisor &lt;span class="se"&gt;\&lt;/span&gt;
  micro-containers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The Sentry re-implements the Linux ABI. In &lt;code&gt;ptrace&lt;/code&gt; mode it intercepts via ptrace; the newer &lt;code&gt;Systrap&lt;/code&gt; mode (shipped 2023, ~2× faster) uses seccomp to intercept. Either way, a kernel exploit in your container cannot reach the host kernel — there is no direct path.&lt;/p&gt;
&lt;h3&gt;
  
  
  The honest security story
&lt;/h3&gt;

&lt;p&gt;gVisor's threat model is &lt;strong&gt;syscall isolation&lt;/strong&gt;. A container escape via a kernel CVE (your &lt;code&gt;dirty_pipe&lt;/code&gt;, your &lt;code&gt;runc&lt;/code&gt; breakout) is stopped at the Sentry. But gVisor is not a VM — the container still shares memory, CPU, and the host's network stack at some layers. It's a strong sandbox, not a hard boundary.&lt;/p&gt;
&lt;h3&gt;
  
  
  2025 state of the world
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GKE Sandbox&lt;/strong&gt; is gVisor, enabled with a single node pool annotation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Systrap mode&lt;/strong&gt; is now the default — nearly removes the performance cliff that made early gVisor a tough sell&lt;/li&gt;
&lt;li&gt;GPU support is production-ready for A100/H100 via vGPU passthrough — relevant if you're sandboxing AI inference workloads&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Ultimate use cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD runners&lt;/strong&gt; — the #1 production use case. GitHub Actions self-hosted, GitLab runners, Buildkite agents that execute arbitrary user pipelines. You don't control the code; gVisor limits the blast radius.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ML inference APIs&lt;/strong&gt; where users submit model weights or custom code — you can't trust what's in those pickles&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SaaS plugin execution&lt;/strong&gt; — any platform that lets users run custom logic (Zapier-style automations, Retool actions, webhook processors)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud IDE backends&lt;/strong&gt; — Codespace-style environments where each user gets a container that feels like root&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Runtime 3: Kata Containers (QEMU VMM)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  What it is
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://katacontainers.io" rel="noopener noreferrer"&gt;Kata Containers&lt;/a&gt; boots a lightweight QEMU MicroVM per container. Your app runs inside a VM with its own kernel. containerd sees an OCI runtime; your process sees a dedicated Linux instance.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--runtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kata-runtime &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;RUNTIME_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kata-qemu &lt;span class="se"&gt;\&lt;/span&gt;
  micro-containers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The host sees a &lt;code&gt;qemu-system-x86_64&lt;/code&gt; process — nothing inside leaks out. The container image is mounted via virtiofs. The kernel boundary is real.&lt;/p&gt;
&lt;h3&gt;
  
  
  The honest security story
&lt;/h3&gt;

&lt;p&gt;Kata/QEMU is the only option here that provides a &lt;strong&gt;true hardware-enforced boundary&lt;/strong&gt; between container and host. gVisor is software isolation. Kata is a VM. If your threat model requires that a kernel exploit inside the container cannot affect the host, Kata is the answer.&lt;/p&gt;
&lt;h3&gt;
  
  
  2025 state of the world
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kata 3.x&lt;/strong&gt; ships with confidential container support: Intel TDX and AMD SEV-SNP give you hardware-attested memory encryption. The host operator can't inspect container memory — relevant for regulated data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Hypervisor&lt;/strong&gt; is now a supported VMM alternative to QEMU, lighter and faster to boot&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confidential Containers (CoCo)&lt;/strong&gt; as a CNCF project wraps Kata + hardware attestation into a first-class primitive — watch this space&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Ultimate use cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PCI-DSS, HIPAA, FedRAMP&lt;/strong&gt; — when the compliance checklist literally says "VM-level isolation," Kata is the only container runtime that checks that box without running actual VMs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Financial services&lt;/strong&gt; — trade processing, settlement systems, anything touching payment card data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Healthcare data pipelines&lt;/strong&gt; — PHI processing where you need a kernel boundary in the audit trail&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-tenant databases&lt;/strong&gt; — giving each tenant a database that physically cannot escape its VM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Government/defense workloads&lt;/strong&gt; — environments where the security control plane doesn't trust the container runtime&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Runtime 4: Kata + Firecracker VMM
&lt;/h2&gt;
&lt;h3&gt;
  
  
  What it is
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://firecracker-microvm.github.io" rel="noopener noreferrer"&gt;Firecracker&lt;/a&gt; was built by AWS in 2018 specifically for Lambda and Fargate. It replaces QEMU as Kata's VMM. The device model is stripped to the minimum a serverless function needs: one network interface, one block device, one serial port. No BIOS. No PCI bus. No USB enumeration. No legacy device emulation of any kind.&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="c"&gt;# Kata reads configuration-fc.toml and invokes Firecracker instead of QEMU&lt;/span&gt;
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--runtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kata-fc &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;RUNTIME_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kata-firecracker &lt;span class="se"&gt;\&lt;/span&gt;
  micro-containers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Cold start drops from ~500 ms (QEMU) to &lt;strong&gt;~125 ms&lt;/strong&gt;. Memory overhead drops by nearly half.&lt;/p&gt;
&lt;h3&gt;
  
  
  The honest security story
&lt;/h3&gt;

&lt;p&gt;Same VM isolation guarantee as Kata/QEMU — a dedicated kernel per container. The tradeoff for the speed gain is device compatibility: no GPU passthrough, no USB, fewer PCIe options. For stateless functions, you don't need any of that.&lt;/p&gt;
&lt;h3&gt;
  
  
  2025 state of the world
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Firecracker 1.7+&lt;/strong&gt; — production-stable, used in billions of Lambda invocations per day. AWS open-sourced it and it ships new major versions regularly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fly.io Machines&lt;/strong&gt; use a Firecracker fork as the core primitive — every &lt;code&gt;fly machine run&lt;/code&gt; is a microVM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Serverless Aurora&lt;/strong&gt; uses Firecracker to isolate query execution environments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confidential Firecracker&lt;/strong&gt; is in active development — combining Firecracker's boot speed with AMD SEV memory encryption&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Ultimate use cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Serverless function platforms&lt;/strong&gt; — this is what Firecracker was made for. If you're building the next Lambda, Railway, or Render, Firecracker is the substrate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI/ML inference bursts&lt;/strong&gt; — LLM inference is bursty; Firecracker's 125 ms cold start makes scale-to-zero viable. A GPU instance spun up with Firecracker can take traffic in under a second.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Short-lived test runners&lt;/strong&gt; — each test run gets a clean VM, boots in 125 ms, exits, gets GC'd. No shared state, no contamination between runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-tenant job queues&lt;/strong&gt; — background jobs that process user-submitted data. Firecracker gives you VM isolation at a price point runc used to own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preview environments&lt;/strong&gt; — spin up a full-stack environment for each PR, destroy it on merge. The economics work at ~125 ms boot + minimal memory overhead.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Runtime 5: WASM / WASI preview1
&lt;/h2&gt;
&lt;h3&gt;
  
  
  What it is
&lt;/h3&gt;

&lt;p&gt;The binary is compiled to WebAssembly with Go's WASI target — an entirely different binary, an entirely different image:&lt;/p&gt;


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




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


&lt;p&gt;The resulting image: &lt;strong&gt;3.1 MB scratch base + one &lt;code&gt;.wasm&lt;/code&gt; binary&lt;/strong&gt;. The sandbox is enforced at the language-runtime level — no syscalls, capabilities explicitly granted by the host.&lt;/p&gt;

&lt;h3&gt;
  
  
  The honest HTTP story
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;net/http&lt;/code&gt; doesn't work in WASI preview1. The spec has no socket API. This demo outputs JSON to stdout. That's not a cop-out — it's the current state of the standard. The &lt;a href="https://github.com/WebAssembly/wasi-http" rel="noopener noreferrer"&gt;wasi-http proposal&lt;/a&gt; shipped as part of WASI 0.2, which is ratified. Fermyon Spin 2.x implements it today. Go's WASI 0.2 support is in progress.&lt;/p&gt;

&lt;h3&gt;
  
  
  2025 state of the world
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WASI 0.2 (Component Model)&lt;/strong&gt; is ratified and shipping in wasmtime, WasmEdge, and Fastly Compute. &lt;code&gt;wasi-http&lt;/code&gt; is a real, stable interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker+Wasm is GA&lt;/strong&gt; in Docker Desktop 4.27+ — run a WASM container with &lt;code&gt;--platform=wasi/wasm&lt;/code&gt; and a containerd shim&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fermyon Spin 2.x&lt;/strong&gt; compiles Go to WASM with a full HTTP server abstraction — the framework paper over the WASI/HTTP gap today&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WasmPlugin in Kubernetes&lt;/strong&gt; — Envoy and Istio support WASM plugins for custom policy, auth, and observability logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extism&lt;/strong&gt; — a cross-language WASM plugin framework that lets you embed sandboxed user code in any Go/Rust/Python host&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Ultimate use cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Edge functions&lt;/strong&gt; — Cloudflare Workers, Fastly Compute, Deno Deploy, and Vercel Edge Functions are all WASM at the bottom. The same binary runs in London, Singapore, and São Paulo with no containers to spin up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-platform CLI tools&lt;/strong&gt; — compile once, run on Linux/macOS/Windows/browser with no CGO, no cross-compilation matrix&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandboxed plugin systems&lt;/strong&gt; — give users scriptable extensions with a real capability boundary. Zellij (terminal multiplexer) uses WASM plugins; VS Code extensions are moving this direction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business logic in the browser + server&lt;/strong&gt; — tax calculation, pricing rules, validation logic that needs to run identically client-side and server-side&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI prompt/response filters&lt;/strong&gt; — fast, sandboxed, hot-reloadable logic at the edge before a request hits your inference endpoint&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Numbers
&lt;/h2&gt;

&lt;p&gt;All OCI runtimes run the same 3 MB distroless image. The distroless/runc row is measured hardware; microVM rows are reference numbers from project documentation — run &lt;code&gt;make bench-md&lt;/code&gt; for your own numbers.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Runtime&lt;/th&gt;
&lt;th&gt;Image&lt;/th&gt;
&lt;th&gt;Cold Start&lt;/th&gt;
&lt;th&gt;p50&lt;/th&gt;
&lt;th&gt;p95&lt;/th&gt;
&lt;th&gt;Memory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;distroless / runc&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.0 MB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~20 ms¹&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.28 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.41 ms&lt;/td&gt;
&lt;td&gt;6.9 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gVisor (runsc)&lt;/td&gt;
&lt;td&gt;3.0 MB&lt;/td&gt;
&lt;td&gt;~50 ms&lt;/td&gt;
&lt;td&gt;~0.5 ms&lt;/td&gt;
&lt;td&gt;~1.0 ms&lt;/td&gt;
&lt;td&gt;~18 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kata / QEMU&lt;/td&gt;
&lt;td&gt;3.0 MB&lt;/td&gt;
&lt;td&gt;~500 ms&lt;/td&gt;
&lt;td&gt;~0.8 ms&lt;/td&gt;
&lt;td&gt;~1.5 ms&lt;/td&gt;
&lt;td&gt;~52 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kata / Firecracker&lt;/td&gt;
&lt;td&gt;3.0 MB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~125 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~0.7 ms&lt;/td&gt;
&lt;td&gt;~1.3 ms&lt;/td&gt;
&lt;td&gt;~28 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WASM (wasmtime)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.1 MB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;N/A²&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;¹ First run ~174 ms (overlay FS init); subsequent ~20 ms on warm cache.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;² WASM has no HTTP server in wasip1; exec time ~8 ms for the stdout variant.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Three things the numbers tell you that prose doesn't:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Image size is not the story.&lt;/strong&gt; All five runtimes land at 3–3.1 MB. Switching from runc to Firecracker doesn't touch your image pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Latency overhead at steady state is negligible.&lt;/strong&gt; Even inside a Kata VM, p50 latency is under 1 ms. The isolation boundary costs you cold-start and memory, not throughput. If you're worried about runtime overhead on a running service, stop — that's not where the overhead lives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Firecracker hits the practical sweet spot.&lt;/strong&gt; 125 ms is the number AWS decided was fast enough for Lambda. 500 ms (QEMU) is where users start feeling it. Firecracker lands right where microVM isolation becomes viable for interactive-latency workloads.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Decision Framework
&lt;/h2&gt;

&lt;p&gt;Stop asking "which is more secure?" Start asking "what's my threat model?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your tenants are you.&lt;/strong&gt; You control every image, every workload, every user. → runc + distroless. Fast, simple, no overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your tenants are your users, but you control the runtime environment.&lt;/strong&gt; CI runners, SaaS execution engines. → &lt;strong&gt;gVisor&lt;/strong&gt;. Drop-in, no KVM, syscall isolation stops the most common container escapes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You have compliance paperwork that says "VM-level isolation."&lt;/strong&gt; → &lt;strong&gt;Kata + QEMU&lt;/strong&gt;. The only option that satisfies an auditor asking for a kernel boundary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You're building a platform.&lt;/strong&gt; Functions, jobs, preview environments, AI inference. Cold-start matters. → &lt;strong&gt;Kata + Firecracker&lt;/strong&gt;. This is the production-proven answer for platforms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your code runs everywhere, or users supply the code.&lt;/strong&gt; Edge compute, plugins, sandboxed scripts. → &lt;strong&gt;WASM/WASI&lt;/strong&gt;. The sandbox is portable; the isolation model is capability-based, not kernel-based.&lt;/p&gt;




&lt;h2&gt;
  
  
  Run It Yourself
&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/micro-containers
&lt;span class="nb"&gt;cd &lt;/span&gt;micro-containers

make check        &lt;span class="c"&gt;# see what's installed&lt;/span&gt;
make bench-fast   &lt;span class="c"&gt;# quick smoke-test with 20 samples&lt;/span&gt;
make bench-md     &lt;span class="c"&gt;# full benchmark → Markdown table&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each runtime has an &lt;code&gt;install.sh&lt;/code&gt; in &lt;code&gt;runtimes/&amp;lt;name&amp;gt;/&lt;/code&gt;. The benchmark driver skips unavailable runtimes and tells you exactly what to install.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Source, Dockerfiles, benchmark driver, and install scripts: &lt;a href="https://github.com/copyleftdev/micro-containers" rel="noopener noreferrer"&gt;copyleftdev/micro-containers&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>go</category>
      <category>devops</category>
      <category>security</category>
    </item>
  </channel>
</rss>
