<?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: Ernesto Herrera Salinas</title>
    <description>The latest articles on DEV Community by Ernesto Herrera Salinas (@ernestohs).</description>
    <link>https://dev.to/ernestohs</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%2F784815%2Fd5daef24-3e99-433f-819f-5b37dfac6558.png</url>
      <title>DEV Community: Ernesto Herrera Salinas</title>
      <link>https://dev.to/ernestohs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ernestohs"/>
    <language>en</language>
    <item>
      <title>Binding members to a persona without magic</title>
      <dc:creator>Ernesto Herrera Salinas</dc:creator>
      <pubDate>Sun, 12 Jul 2026 02:34:17 +0000</pubDate>
      <link>https://dev.to/ernestohs/binding-members-to-a-persona-without-magic-foj</link>
      <guid>https://dev.to/ernestohs/binding-members-to-a-persona-without-magic-foj</guid>
      <description>&lt;p&gt;Automatic coherence sounds like magic, and magic in a library is a liability.&lt;br&gt;
The entire job in this part of the design was making it trustworthy: it has to fire when it should, stay silent when it should not, and be explainable when you ask. Several decisions, one theme.&lt;/p&gt;
&lt;h2&gt;
  
  
  Binding: automatic, with an explicit escape
&lt;/h2&gt;

&lt;p&gt;First, how does a member get attached to its object's persona? I shipped two paths on purpose.&lt;/p&gt;

&lt;p&gt;The primary path is automatic. Semantic inference, which already recognizes &lt;code&gt;FirstName&lt;/code&gt; and &lt;code&gt;Email&lt;/code&gt;, binds those members to the object's persona, so &lt;code&gt;Lie&amp;lt;Customer&amp;gt;.Generate()&lt;/code&gt; comes out coherent with zero configuration. That is the seed/demo win, and it has to be the default because it is the only thing that reaches the headline one-liner.&lt;/p&gt;

&lt;p&gt;The escape path is explicit: a &lt;code&gt;d.Person&lt;/code&gt; accessor you can read inside a &lt;code&gt;With&lt;/code&gt; or &lt;code&gt;Derive&lt;/code&gt; rule when you want precision. It is a complement, not a replacement, and an explicit rule always overrides the automatic binding.&lt;/p&gt;
&lt;h2&gt;
  
  
  Where it lives: a stage, not a patch
&lt;/h2&gt;

&lt;p&gt;Coherence is not bolted onto the semantic matcher. It is its own resolver stage on the ordered pipeline I pre-paid for earlier in the series, driven by an entity descriptor that maps roles to facets. That choice is what allows the same machinery to later serve &lt;code&gt;Address&lt;/code&gt; and &lt;code&gt;Company&lt;/code&gt; by adding a descriptor instead of rewriting the matcher. It also gives &lt;code&gt;Explain()&lt;/code&gt; a real, first-class thing to report.&lt;/p&gt;
&lt;h2&gt;
  
  
  Detection: borrow the truth you already have
&lt;/h2&gt;

&lt;p&gt;Now the part that decides whether the whole feature is trustworthy. How does the engine know &lt;code&gt;FirstName&lt;/code&gt; is a person facet and &lt;code&gt;Name&lt;/code&gt; on a &lt;code&gt;Product&lt;/code&gt; is not?&lt;/p&gt;

&lt;p&gt;The tempting move is to give the persona its own table of names it owns. I did not do that, because then two tables can drift. Instead, the persona piggybacks the existing semantic candidate table: a member binds to a facet when the semantic candidate it already wins is one the persona claims. One source of truth, no drift. And the existing model-hint disambiguation comes along for free:&lt;br&gt;
&lt;code&gt;Product.Name&lt;/code&gt; already resolves to a product-name candidate, never a person one, so coherence inherits that false-positive avoidance without writing a line of new&lt;br&gt;
guarding.&lt;/p&gt;
&lt;h2&gt;
  
  
  Activation: gate on evidence
&lt;/h2&gt;

&lt;p&gt;The last question is: when does an object get a persona at all? Always-on would be reckless. So activation reuses the inference mode the library already exposes (&lt;code&gt;Conservative&lt;/code&gt;, &lt;code&gt;Balanced&lt;/code&gt;, &lt;code&gt;Aggressive&lt;/code&gt;) as an evidence dial, and counts corroborating role members:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Conservative: needs a name anchor (FirstName/LastName/FullName)
Balanced:     a name anchor, or two correlated members
Aggressive:   one matched member is enough
Disabled:     never
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is a build-time pre-pass, not a per-member check, and it self-limits the two-people collapse from the last post: prefixed, ambiguous members score low, so the mistaken merge only happens under &lt;code&gt;Aggressive&lt;/code&gt;, where you asked for reach.&lt;/p&gt;

&lt;p&gt;(Two smaller decisions ride along here: the explicit &lt;code&gt;d.Person&lt;/code&gt; is a fixed snapshot of properties, not a generator, so reads inside a rule line up with the&lt;br&gt;
auto-bound members; and reading it on an object with no activated persona materializes one lazily. That lazy draw is the one order-dependent corner in an otherwise eager design, and it is documented as such.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;Automatic behavior earns trust by reusing the system's existing truth and gating on evidence, not by inventing a parallel guesser that can drift or misfire. Magic&lt;br&gt;
you can explain is just a feature. Magic you cannot is a support ticket.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;I have been hand-waving one contractual detail: when exactly does a persona draw its random values from the stream? In a deterministic library, that is not a detail at all. Next post: the PRNG draw-tape, eager versus lazy.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>showdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Fake data that is not obviously fake</title>
      <dc:creator>Ernesto Herrera Salinas</dc:creator>
      <pubDate>Thu, 09 Jul 2026 00:38:35 +0000</pubDate>
      <link>https://dev.to/ernestohs/fake-data-that-is-not-obviously-fake-2pck</link>
      <guid>https://dev.to/ernestohs/fake-data-that-is-not-obviously-fake-2pck</guid>
      <description>&lt;p&gt;Back in the audit, I flagged a tension I had created for myself: I called seed and&lt;br&gt;
demo data a co-equal job, then pointed the whole roadmap at composition, which&lt;br&gt;
barely serves it. This post is where I start paying that off. It begins with an&lt;br&gt;
ugly little object.&lt;/p&gt;

&lt;p&gt;Here is what zero-config inference produces today, for a customer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  FirstName: "Maria",
  LastName:  "Garcia",
  FullName:  "John Smith",          // unrelated to First/Last
  Email:     "k7zp@example.net",    // unrelated to the name
  Username:  "blue-tiger-441"       // unrelated again
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a unit test, nobody cares. Any plausible string is fine. But for seed data in&lt;br&gt;
a demo database, this looks broken. A human reads it in two seconds and knows it&lt;br&gt;
is fake. And this is precisely the job composition cannot help with, because&lt;br&gt;
composition is about structure (which definition builds a nested object), and this&lt;br&gt;
is about correlation between flat scalar fields. Different problem, different&lt;br&gt;
machinery.&lt;/p&gt;
&lt;h2&gt;
  
  
  The idea: a persona
&lt;/h2&gt;

&lt;p&gt;The fix is an idea Bogus already has, called &lt;code&gt;Person&lt;/code&gt;: a coherent bundle generated&lt;br&gt;
once, where the fields agree because they all come from the same underlying&lt;br&gt;
identity. Munchausen's version has to be deterministic and inferred rather than&lt;br&gt;
hand-wired, but the core is the same. There is a hidden &lt;code&gt;Person&lt;/code&gt; for the object,&lt;br&gt;
and &lt;code&gt;FirstName&lt;/code&gt;, &lt;code&gt;Email&lt;/code&gt;, and &lt;code&gt;FullName&lt;/code&gt; are facets of it, not independent&lt;br&gt;
guesses.&lt;/p&gt;
&lt;h2&gt;
  
  
  The load-bearing fork: what is one identity?
&lt;/h2&gt;

&lt;p&gt;The first real decision is the one that sets the mental model for everything after&lt;br&gt;
it: in an object graph, which members share a single persona?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;SalesRep&lt;/span&gt; &lt;span class="n"&gt;Rep&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SalesRep&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A: object-scoped. Persona boundary equals object boundary.
   Customer.FirstName/LastName/Email -&amp;gt; Customer's persona (one identity)
   Rep.Name/Rep.Email                -&amp;gt; Rep's own persona  (a different identity)

B: role-scoped. Group by a member-name prefix, so two people flat on one object
   stay distinct (CustomerName vs SalesRepName).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I chose object-scoped. It is predictable, it needs no name-parsing heuristics, and&lt;br&gt;
the boundary is something the user can already see in their own type. A nested&lt;br&gt;
object simply gets its own identity, which is almost always what you want.&lt;/p&gt;

&lt;p&gt;Object-scoping has a known sharp edge. If someone flattens two people onto one&lt;br&gt;
type, &lt;code&gt;Order { CustomerName, SalesRepName }&lt;/code&gt;, object-scoping makes them the same&lt;br&gt;
person. That is wrong, and I did not pretend otherwise. I deferred role grouping&lt;br&gt;
as a later refinement and made the collapse diagnosable through &lt;code&gt;Explain()&lt;/code&gt;, which&lt;br&gt;
will happily report "four members bound to one Person" so you can see it.&lt;/p&gt;

&lt;p&gt;The reason I was comfortable deferring it: object-scoping already beats AutoBogus&lt;br&gt;
for the common case, a single identity per object, which is most of the win. The&lt;br&gt;
flat-two-people shape is a denormalized DTO that no tool handles automatically&lt;br&gt;
today. So the principled default ships now, and the differentiator can come later&lt;br&gt;
without repainting the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;Coherence is not "better random values." It is a shared source of truth that&lt;br&gt;
several fields read from. And the first decision in any system like that is the&lt;br&gt;
boundary question: what counts as one identity? Pick the boundary your users can&lt;br&gt;
already see, and be honest about the case it gets wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;A persona is only useful if members actually attach to it, and the attaching has&lt;br&gt;
to be trustworthy rather than magic. Next post: binding members to a persona&lt;br&gt;
without magic, including how the engine decides a field is a person at all.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>showdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Paying for the future on purpose</title>
      <dc:creator>Ernesto Herrera Salinas</dc:creator>
      <pubDate>Tue, 07 Jul 2026 19:13:24 +0000</pubDate>
      <link>https://dev.to/ernestohs/paying-for-the-future-on-purpose-epj</link>
      <guid>https://dev.to/ernestohs/paying-for-the-future-on-purpose-epj</guid>
      <description>&lt;p&gt;There is a category of design decision where the cheap option for the version you are shipping quietly mortgages the version after it. With a solo project and no deadline, I kept choosing to pay now. Here are the two clearest  ases, and the principle that connected them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-pay one: structure over shortcuts
&lt;/h2&gt;

&lt;p&gt;Composition adds rules to members. A collection member, for instance, might use a child definition for its elements, hold between two and five of them, and be null&lt;br&gt;
ten percent of the time. v1.1 only needs the first of those. v1.2 wants all three stacked on one member. So how should a member hold its rules?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A: one rule per member, conflicts unless whitelisted.
   Stacking N features needs an O(N^2) compatibility matrix.

B: a member is a record of independent facets (element, size, null-probability).
   Stacking is free; only two rules of the SAME facet conflict.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Option A is less code for v1.1 today. Option B introduces a facet record now, for a feature that only uses one facet, which feels like over-building. I took B&lt;br&gt;
anyway. The same logic applied one layer up: resolution became an ordered pipeline of stages rather than a stack of hardcoded &lt;code&gt;if&lt;/code&gt; branches, so v1.2 can insert a stage by position instead of rewriting the branch.&lt;/p&gt;

&lt;p&gt;The reason is the brief, not taste. Feature growth is an explicit goal, and there is no deadline. The design doc itself had concluded that the cheap options are the&lt;br&gt;
only thing that would force v1.2 to reopen composition. When you can see the roadmap that clearly and you are not racing a clock, paying the structural cost&lt;br&gt;
once is strictly better than paying interest on it every release. (This pipeline, it turns out, becomes the host for the entire coherence feature later in the series. The pre-pay compounded in my favor faster than I expected.)&lt;/p&gt;
&lt;h2&gt;
  
  
  Pre-pay two: a default that fails loudly
&lt;/h2&gt;

&lt;p&gt;The second case is about composition boundaries. If you compose a reusable customer definition into an order, and that customer is silent about how money is generated, should a money rule you set on the order reach inside the customer?&lt;/p&gt;

&lt;p&gt;Two pure answers, and the choice is really about how each one fails.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hermetic: the rule seals at the boundary. The customer generates its own way.
ambient:  the rule flows in. The customer's money becomes yours.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ambient is convenient right up until it is not. The failure mode is that a distant ancestor silently mutates a fixture you wrote and tested, and you find out by&lt;br&gt;
auditing the whole chain. Hermetic fails the other way: your rule under-reaches, you see the wrong value at your own call site, and the fix is local. Local and diagnosable beats non-local and silent. So the default is hermetic: a composed definition is a sealed contract.&lt;/p&gt;

&lt;p&gt;But hermetic under-reaches on purpose, and sometimes you really do mean "every money value in this whole graph is in euros, no exceptions." For that I reserved&lt;br&gt;
an escape valve, &lt;code&gt;UseDeep&lt;/code&gt;, that a consumer writes explicitly and that always wins, penetrating any boundary. The fork there was whether reach should be the&lt;br&gt;
consumer's call (&lt;code&gt;UseDeep&lt;/code&gt;) or the author's  (&lt;code&gt;Sealed&lt;/code&gt;/&lt;code&gt;Open&lt;/code&gt; on the definition). I took a hybrid: sealed by default so authors get safe contracts for free, plus a consumer &lt;code&gt;UseDeep&lt;/code&gt; that overrides anything. Two concepts, but each is in the hands of the person who knows the intent. &lt;code&gt;UseDeep&lt;/code&gt; is greppable and visible at the call&lt;br&gt;
site, which keeps even the ambient-style power loud rather than silent. Its shape is reserved now and ships in a later point release, so the default can never paint&lt;br&gt;
it out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;When you can see the feature roadmap and you are not under deadline, pay your structural debt down before it compounds. The brief is what tells you whether you&lt;br&gt;
can afford to. And when you pick a default, choose the one whose failure mode is local and visible, not the one whose convenience hides the bug several layers up.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;That is the composition thread settled. Now the threads switch. The next question is not how objects compose, it is whether the data inside them looks real at all.&lt;/p&gt;

&lt;p&gt;Next post: fake data that is not obviously fake.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>showdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Reconciling a public API that drifted</title>
      <dc:creator>Ernesto Herrera Salinas</dc:creator>
      <pubDate>Sun, 05 Jul 2026 21:11:47 +0000</pubDate>
      <link>https://dev.to/ernestohs/reconciling-a-public-api-that-drifted-1652</link>
      <guid>https://dev.to/ernestohs/reconciling-a-public-api-that-drifted-1652</guid>
      <description>&lt;p&gt;The audit found that my two binding documents disagreed about the v1.1 composition API. Closing that gap was not paperwork. A public method is a promise you can almost never take back, so reconciling the surface meant making real choices and living with them.&lt;/p&gt;

&lt;p&gt;Some quick context on what composition is. It lets a definition control how the nested objects inside a generated graph are produced: "every &lt;code&gt;Address&lt;/code&gt; in this order graph uses this address definition," or "this specific member uses that child definition." The surface in flux covered type-scoped, member-scoped, and element-scoped binding, plus substituting a concrete type for an abstract member.&lt;/p&gt;

&lt;p&gt;Three forks had to be settled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fork one: the name
&lt;/h2&gt;

&lt;p&gt;The element-scoped method was &lt;code&gt;UseEach&lt;/code&gt; in the binding doc and &lt;code&gt;UseElements&lt;/code&gt; in the design doc. Tiny, but public, so it gets a real decision. I kept &lt;code&gt;UseEach&lt;/code&gt;. It was the name in the top-authority document already, and it reads cleanly next to&lt;br&gt;
its siblings: &lt;code&gt;Use&lt;/code&gt; for a type, &lt;code&gt;UseEach&lt;/code&gt; for the elements of a collection. Not every fork is deep. Some are just "pick one on purpose and stop relitigating it."&lt;/p&gt;
&lt;h2&gt;
  
  
  Fork two: the shape
&lt;/h2&gt;

&lt;p&gt;This one mattered. The binding doc had a single-generic member binding plus a separate &lt;code&gt;UseAs&lt;/code&gt; method for substituting a concrete type for an abstraction. The design doc had folded both into one two-generic method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before: two verbs&lt;/span&gt;
&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TChild&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;UseAs&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TAbstraction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TImplementation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;UseAs&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TAbstraction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TImplementation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// after: one verb, abstract-capable&lt;/span&gt;
&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TMember&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TConcrete&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;def&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;TConcrete&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TMember&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I took the folded shape. The generic constraint carries abstract substitution for free: for a concrete member, &lt;code&gt;TMember&lt;/code&gt; and &lt;code&gt;TConcrete&lt;/code&gt; infer to the same type, so existing calls are unchanged, and for an interface-typed member the second generic&lt;br&gt;
supplies the concrete definition. One verb instead of three, and the type system does the work that a separate method used to. &lt;code&gt;UseAs&lt;/code&gt; disappeared.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fork three: how much to ship
&lt;/h2&gt;

&lt;p&gt;The folded &lt;code&gt;Use&lt;/code&gt; handles abstract members one at a time. The binding doc also promised a type-level version: "every &lt;code&gt;IParty&lt;/code&gt; in this graph is a &lt;code&gt;Person&lt;/code&gt;," one registration, graph-wide. I deferred it.&lt;/p&gt;

&lt;p&gt;The reasons were concrete. The compiler cannot infer both type arguments for the type-level form, so every call would spell them out. It needs a conflict rule for two concretes registered against one abstraction. And it quietly nudges users toward expecting random polymorphic selection, which is a different feature&lt;br&gt;
entirely. It is cheap to add later and expensive to walk back, so it waits. In v1.1, abstract substitution is member-scoped and element-scoped only.&lt;/p&gt;

&lt;p&gt;I also added one new diagnostic, &lt;code&gt;LIE012&lt;/code&gt;, for an unsupported composition target (binding to a collection shape the library cannot materialize), since the existing diagnostic registry had no fitting code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing the why into the contract
&lt;/h2&gt;

&lt;p&gt;The part I am most glad I did: I recorded all of this as a "Revision 2.2 amendment" inside &lt;code&gt;API_DESIGN.md&lt;/code&gt; itself. Not in a side note, not in a commit message, in the binding document, next to the surface it changed. The amendment says what folded into what, what was deferred and why, and that the type-level form is an additive follow-up.&lt;/p&gt;

&lt;p&gt;The contract and the design doc finally describe the same API, and the next person to read either one will find the reasoning attached to the decision instead of having to reconstruct it, or worse, rediscover the conflict I just closed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;A public API is a promise, and drift between your contract and your design is a quiet way to break it. Reconcile deliberately, prefer the change that is additive and lets the type system carry the load, defer the expensive-to-reverse pieces, and write the why into the contract so it does not drift again.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;With the surface honest, the deeper composition decisions were waiting, the ones that were not about taste at all. They were decided by the brief: solo, no deadline, quality over speed. Next post, paying for the future on purpose.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>showdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Auditing my own frozen design</title>
      <dc:creator>Ernesto Herrera Salinas</dc:creator>
      <pubDate>Sat, 04 Jul 2026 01:33:00 +0000</pubDate>
      <link>https://dev.to/ernestohs/auditing-my-own-frozen-design-3bed</link>
      <guid>https://dev.to/ernestohs/auditing-my-own-frozen-design-3bed</guid>
      <description>&lt;p&gt;With the rigor lane chosen, the disciplined next move was not to design anything.&lt;/p&gt;

&lt;p&gt;It was to reread my own v1.0 design documents, the ones I had stamped "binding," as if a slightly hostile consultant were reading them for the first time. I am glad I did, because the audit found a contradiction sitting inside my own contracts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The contradiction
&lt;/h2&gt;

&lt;p&gt;The trouble is that &lt;code&gt;API_DESIGN.md&lt;/code&gt; had sketched the v1.1 composition surface months ago, and the active composition design doc had kept evolving past it, into a genuinely better shape. So two documents I had both called authoritative now described different public APIs for the same feature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API_DESIGN.md (binding):   UseEach&amp;lt;TChild, TCollection&amp;gt;(...) + a separate UseAs(...)
Composition design doc:    UseEach&amp;lt;TElement, TConcrete&amp;gt;(...), abstract folded into Use, no UseAs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the kind of bug that does not crash anything and does not show up in a test. It just sits there until a contributor follows the authority order, builds the surface the top document describes, and ships the wrong API. Documentation that drifts is worse than no documentation, because it still carries the badge of truth.&lt;/p&gt;

&lt;p&gt;That was finding one, and it became the next post: reconcile the surface, deliberately pick the winner, and write down why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two more things the audit surfaced
&lt;/h2&gt;

&lt;p&gt;While I was reading hostile, two strategic gaps emerged that had nothing to do with the surface conflict.&lt;/p&gt;

&lt;p&gt;The first is a tension between my own answers. I had said the two jobs, test fixtures and seed/demo data, are co-equal. But the planned v1.1 anchor, composition, almost entirely serves the test-fixture and rigor job. It does very little for the seed/demo job. The thing that makes seed/demo data compelling without breadth is in-locale realism and coherence: a customer whose name, email,&lt;br&gt;
and date of birth actually agree. My own positioning note listed exactly those as current gaps. So I had declared a job co-equal, and then pointed the whole roadmap elsewhere. That gap is the reason the back half of this series exists.&lt;/p&gt;

&lt;p&gt;The second is a ceiling I had built on purpose and then half forgotten. The zero-config path, &lt;code&gt;Lie&amp;lt;Customer&amp;gt;.Generate()&lt;/code&gt;, is permanently non-configurable by contract. That is what makes the process-wide plan cache safe. But every extension mechanism- datasets, locales, data packs, providers- is definition-scoped. The consequence: a third-party data package can only enrich the defined path, never the headline one-liner. And the headline one-liner is the adoption hook. So the extensibility story, the thing that is supposed to scale the ecosystem, structurally cannot touch the feature people would actually adopt me for. That is not necessarily wrong, but it is a thing to decide on purpose, not to discover later.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lesson
&lt;/h2&gt;

&lt;p&gt;None of these three were design mistakes exactly. The surface conflict was drift.&lt;/p&gt;

&lt;p&gt;The coherence gap was a roadmap that had quietly diverged from the stated goals.&lt;/p&gt;

&lt;p&gt;The extensibility ceiling was a correct tradeoff I needed to hold consciously. But all three were invisible until I read my own contracts adversarially.&lt;/p&gt;

&lt;p&gt;The takeaway I keep coming back to: a "binding" document is only binding if it is periodically tested against the design that is actually happening. An authority that is never audited is just a stale opinion wearing a badge. Reread your own contracts as a stranger before you build on them, because the most expensive bugs&lt;br&gt;
are the ones your documents agree to.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The first finding was a live contradiction between two binding documents, and it was the cheapest to close. Next post: reconciling a public API that drifted, which meant making real, permanent surface choices, and recording the why inside the contract itself.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>showdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Why I am not cloning Bogus</title>
      <dc:creator>Ernesto Herrera Salinas</dc:creator>
      <pubDate>Fri, 03 Jul 2026 01:06:00 +0000</pubDate>
      <link>https://dev.to/ernestohs/why-i-am-not-cloning-bogus-4332</link>
      <guid>https://dev.to/ernestohs/why-i-am-not-cloning-bogus-4332</guid>
      <description>&lt;p&gt;v1.0 of Munchausen shipped. Before I designed a single v1.1 feature, I made myself answer the most uncomfortable question a .NET mock-data library can face: how far am I from Bogus?&lt;/p&gt;

&lt;p&gt;Bogus is the giant in this space. It has been around for a decade; it has fifty locales; it has datasets for finance, company, hacker-speak, and music; and it has the community to match. If "be like Bogus" is the goal, the honest answer to my question is "years away, and I am one person." That is a depressing place to start a roadmap, so I sat with it until I realized I was asking the wrong&lt;br&gt;
question.&lt;/p&gt;
&lt;h2&gt;
  
  
  Two axes, not one
&lt;/h2&gt;

&lt;p&gt;Bogus and Munchausen are not the same kind of tool measured at different sizes.&lt;/p&gt;

&lt;p&gt;They sit on different axes.&lt;/p&gt;

&lt;p&gt;One axis is breadth. Bogus is rules-first: you write a rule per property, and in exchange you get enormous content, locales, and ecosystem. That is years of curation and a community, not a clever architecture.&lt;/p&gt;

&lt;p&gt;The other axis is rigor. Munchausen is inference-first. You hand it a type, and it generates an owned deterministic generator, leaning on semantic inference, eager validation, an &lt;code&gt;Explain()&lt;/code&gt; report, and a compiled performance model. The same task looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bogus: rules-first&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Faker&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RuleFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RuleFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RuleFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Internet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FirstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LastName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSeed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Munchausen: inference-first&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Lie&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="nf"&gt;Generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once I drew the two axes, the real peers came into focus. The library that generates an object graph from nothing is not Bogus, it is AutoFixture and AutoBogus. That is the company I am actually keeping.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fork
&lt;/h2&gt;

&lt;p&gt;So the strategic decision was a fork, and it is genuinely two different products.&lt;/p&gt;

&lt;p&gt;Option A: chase Bogus on its home turf. Invest in locales, dataset breadth, coherent personas, ecosystem. This is the road to adoption &lt;em&gt;against Bogus&lt;/em&gt;, and it is the right road if breadth is the bet. It is also content and community work, mostly, and it would take a solo developer a very long time to even look credible.&lt;/p&gt;

&lt;p&gt;Option B: own the rigor lane. Go all-in on being the best deterministic, explainable, zero-config generator, a category Bogus does not really compete in.&lt;br&gt;
The competitors to beat here are AutoFixture and AutoBogus, and on this axis Munchausen already leads or ties.&lt;/p&gt;

&lt;h2&gt;
  
  
  The choice, and the why
&lt;/h2&gt;

&lt;p&gt;I chose B. Own the rigor lane, and deliberately cede breadth to Bogus.&lt;/p&gt;

&lt;p&gt;The reasoning is about where a solo project with no deadline can actually win.&lt;br&gt;
Breadth is content and ecosystem: you beat it with a team and ten years.&lt;br&gt;
Rigor is architecture: determinism, explainability, a compiled plan, zero-config inference. That is the kind of advantage one person can build and defend, because it is design, not catalog size.&lt;/p&gt;

&lt;p&gt;The part that took me the longest to accept is that "adoption" and "cede breadth" are not in conflict, as long as "adoption" means winning a category rather than winning Bogus's category. I am not trying to be the library you reach for when you need realistic German addresses. I am trying to be the default for people who care about their generated data being reproducible, inspectable, and configured by inference rather than by a hundred hand-written rules. Bogus does not compete there.&lt;/p&gt;

&lt;p&gt;Two more things fell out of this, and I wrote them down so every later decision could be checked against them.&lt;/p&gt;

&lt;p&gt;First, Munchausen has to serve two roles as co-equals: test fixtures (where any plausible value is fine) and seed or demo data (where the data must look real and internally consistent). That second job is the one that usually needs breadth, so ceding breadth puts pressure on a different lever entirely, making the in-locale&lt;br&gt;
data genuinely coherent. I flagged that tension on purpose. It becomes the whole back half of this series.&lt;/p&gt;

&lt;p&gt;Second, "scalable" had to be pinned down, because it pulls in several directions at once. For this project it means four things: extensibility, performance, contributor approachability, and feature growth without breaking the locked public surface.&lt;/p&gt;

&lt;p&gt;That is the brief, and it is the rubric I now hold every decision against:&lt;br&gt;
deterministic, explainable, zero-config; displace AutoFixture and AutoBogus, not Bogus; both jobs co-equal; scale four ways; built solo, no deadline, quality over speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;Do not benchmark yourself against the market leader's strengths. Find the axis where your advantage is structural rather than accumulated, and commit to being the best there. Half the hard decisions get easier once you can say out loud what you are choosing not to be.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;With the lane chosen, the obvious next move was to read my own frozen v1.0 design against it with fresh, slightly hostile eyes. That audit found a contradiction hiding inside my own binding documents, which is where the next post starts.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>showdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Designing Munchausen v1.1 in public</title>
      <dc:creator>Ernesto Herrera Salinas</dc:creator>
      <pubDate>Wed, 01 Jul 2026 00:27:02 +0000</pubDate>
      <link>https://dev.to/ernestohs/designing-munchausen-v11-in-public-3dle</link>
      <guid>https://dev.to/ernestohs/designing-munchausen-v11-in-public-3dle</guid>
      <description>&lt;p&gt;I am picking Munchausen back up.&lt;/p&gt;

&lt;p&gt;This is an old project of mine: a .NET mock-data library with the modest ambition of generating useful fake data from your types without asking you to write a rule for every property. I already took it through a v1.0 foundation series, starting with the traditional first step of any responsible software project: deleting code&lt;br&gt;
and breaking the build on purpose.&lt;/p&gt;

&lt;p&gt;Now I want to revive it, not because anyone is waiting for a quarterly roadmap, but because I still like the problem. I like the tiny design arguments. I like deciding where a public API should bend and where it should refuse. I like the part of software where nothing exists yet except a few constraints and the dangerous belief&lt;br&gt;
that this time the abstractions will behave.&lt;/p&gt;

&lt;p&gt;So this series is for me, and it is for fun.&lt;/p&gt;

&lt;p&gt;Also, if the Baron is going to do anything in public, I may as well design in public too.&lt;/p&gt;
&lt;h2&gt;
  
  
  What v1.1 is about
&lt;/h2&gt;

&lt;p&gt;Munchausen v1.0 is the foundation: deterministic generation, semantic inference, &lt;code&gt;Build()&lt;/code&gt; validation, &lt;code&gt;Generate()&lt;/code&gt;, datasets, and an &lt;code&gt;Explain()&lt;/code&gt; surface that makes the automatic parts inspectable.&lt;/p&gt;

&lt;p&gt;v1.1 asks what the library has to become if it wants to be more than a convenient object generator. The work has two main threads.&lt;/p&gt;

&lt;p&gt;The first is composition: how one definition controls the nested objects inside a generated graph. If an &lt;code&gt;Order&lt;/code&gt; has a &lt;code&gt;Customer&lt;/code&gt;, and that customer has addresses, collections, abstractions, and reusable child definitions, the library needs a surface that can express those relationships without becoming a maze of rules.&lt;/p&gt;

&lt;p&gt;The second is coherence: making generated data agree with itself. A customer named Maria should not have a full name of John Smith and an unrelated email address.&lt;br&gt;
An address should not combine a city, state, and postal code from three different places. For tests, any plausible value is often enough. For seed data, demos, and screenshots, incoherent data looks broken.&lt;/p&gt;

&lt;p&gt;Those two threads sound separate. They are not entirely separate. Composition changes object boundaries, and coherence depends on object boundaries. That is where the interesting design work lives.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why design gets its own series
&lt;/h2&gt;

&lt;p&gt;These posts are design records, not release notes. Most of the work here is deciding what should exist before writing the code that ships it.&lt;/p&gt;

&lt;p&gt;Each article will follow the same shape: the problem, the options, the choice, and the reason. I want the rejected options in the record too, because a design without the alternatives is hard to trust later. If I decide not to build something yet, I will say why. If I reserve a public surface for later, I will write that down too.&lt;/p&gt;

&lt;p&gt;The goal is not to make the decisions look inevitable. The goal is to make them reviewable.&lt;/p&gt;

&lt;p&gt;That matters more on a hobby project than it sounds. When nobody is forcing a deadline, the easy failure mode is not shipping the wrong thing under pressure. It is drifting, forgetting why a decision was made, then rediscovering the same fork three weekends later with worse notes. Writing the design down is how I keep the project honest with future me, who is technically the maintainer and also the most&lt;br&gt;
likely person to ask, "why did I do this?"&lt;/p&gt;
&lt;h2&gt;
  
  
  The rules of the game
&lt;/h2&gt;

&lt;p&gt;Munchausen is not going to beat Bogus by becoming a smaller Bogus. Bogus owns breadth: locales, datasets, categories, and years of ecosystem. Munchausen's lane is rigor: deterministic output, explainable inference, zero-config generation, a compiled plan, and failures that are local and diagnosable.&lt;/p&gt;

&lt;p&gt;That gives me the rubric for the whole series:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deterministic, explainable, zero-config
better than AutoFixture and AutoBogus on inference-first generation
not a Bogus clone
test fixtures and seed/demo data as co-equal jobs
solo project, no deadline, quality over speed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every v1.1 decision has to survive that rubric. If a feature makes the library broader but less explainable, that is suspect. If a shortcut helps one release but forces the next one to reopen the same surface, that is suspect too.&lt;/p&gt;

&lt;p&gt;I want a design that can be reviewed cold. Someone should be able to read this series later and understand not just what v1.1 intends to do, but why the shape is the way it is. That someone might be another engineer. More likely, it will be me, after forgetting the entire argument and acting surprised by my own repository.&lt;/p&gt;

&lt;p&gt;That means writing down the uncomfortable parts: where the public API drifted, why some convenient features are deferred, where automatic behavior becomes too magic, and what remains unresolved. The reasoning is part of the product. If the design is&lt;br&gt;
going to be rigorous, the record of the design has to be rigorous too.&lt;/p&gt;

&lt;p&gt;The first decision is strategic: before I design any v1.1 feature, I need to decide what kind of library Munchausen is trying to be, and what kind it is deliberately not trying to be.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>showdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>The Iron Man Protocol: Turning Agent Mistakes Into Durable Engineering Feedback</title>
      <dc:creator>Ernesto Herrera Salinas</dc:creator>
      <pubDate>Fri, 26 Jun 2026 22:00:00 +0000</pubDate>
      <link>https://dev.to/ernestohs/the-iron-man-protocol-turning-agent-mistakes-into-durable-engineering-feedback-15kf</link>
      <guid>https://dev.to/ernestohs/the-iron-man-protocol-turning-agent-mistakes-into-durable-engineering-feedback-15kf</guid>
      <description>&lt;h2&gt;
  
  
  How a Team Can Make a Coding Agent Improve Without Retraining It
&lt;/h2&gt;

&lt;p&gt;Tony Stark does not get stronger by force of will. He gets stronger because he is an engineer who treats every failed suit as evidence: he records what broke, changes the armor, adds a safeguard, and tests the next version under harder conditions. The suit does not learn. &lt;strong&gt;Stark learns, and the suit carries the lesson forward.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That distinction is the whole point of this article, so it is worth being precise about who plays which role. A coding agent like Codex is the suit. Your team is Stark. Codex does not update its model weights when it misunderstands a repository convention, skips a test, or patches the wrong file. That interaction does not retrain the underlying model. But the &lt;em&gt;system around&lt;/em&gt; the agent can be re-engineered after failures so the next run carries the lesson:&lt;/p&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%2Fcyzflogkmhe6tzwarkwq.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%2Fcyzflogkmhe6tzwarkwq.png" alt="Iron Man Protocol" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That loop is the Iron Man Protocol. The rest of this article is how to run it without it collapsing under its own weight.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who This Is For
&lt;/h2&gt;

&lt;p&gt;This article is for teams using a coding agent for repository work, code review, CI fixes, migrations, generated-code workflows, and other repeated engineering tasks, especially anyone who has watched the same agent mistake happen twice and wants something stronger than "please remember next time."&lt;/p&gt;

&lt;p&gt;The named surfaces below (&lt;code&gt;AGENTS.md&lt;/code&gt;, skills, hooks, memories, evals) are spelled the way Codex spells them. Many coding-agent platforms expose comparable primitives, though names, locations, and enforcement behavior differ. Treat "Codex" throughout as the concrete example, not as the only possible implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The One Idea That Matters
&lt;/h2&gt;

&lt;p&gt;Make the next failure harder to repeat by changing the environment, not by exhorting the model.&lt;/p&gt;

&lt;p&gt;This rests on a single research finding, stated once: &lt;strong&gt;language models are unreliable at correcting their own reasoning when the only signal is their own reflection.&lt;/strong&gt; They improve far more dependably when given an external, executable signal: a failing test, a trace, a CI log, a reviewer comment, a concrete rule. [4][5] The nuance matters: self-correction is not worthless; it works when the model can &lt;em&gt;check&lt;/em&gt; its work against something real. [1] So the engineering goal is not "tell the agent to reflect harder." It is "put a real signal in front of the agent."&lt;/p&gt;

&lt;p&gt;That is the difference between a weak loop and a strong one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Weak:   Think harder and avoid that mistake again.

Strong: Reproduce the failing case, find the root cause, patch the smallest
        responsible code path, add a regression test, update the repository
        rule if this convention recurs, and rerun the relevant suite.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The strong loop hands the agent evidence. It turns a mistake into a constraint. Everything below is machinery for producing those constraints, and for removing them once they stop paying rent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Research, Briefly
&lt;/h2&gt;

&lt;p&gt;A few results carry this argument:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Self-correction has limits.&lt;/strong&gt; Models often fail to fix their own reasoning without a reliable external signal. [4][5] This is the reason the protocol refuses to depend on the model "noticing" its mistake.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verbal feedback can persist across attempts.&lt;/strong&gt; Reflexion showed agents improving without weight updates by storing linguistic feedback from prior tries. [2] That is the mechanism the protocol industrializes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A growing, reusable skill library compounds.&lt;/strong&gt; Voyager paired execution feedback and self-verification with an ever-expanding skill set. [8] Tests, skills, hooks, evals, and &lt;code&gt;AGENTS.md&lt;/code&gt; are that skill library for a coding agent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Software-engineering benchmarks reinforce the practical shape: coding agents need repository context, usable tools, good localization, and validation loops. [9][10] Agentless adds a useful caution: simpler structured pipelines for localization, repair, and patch validation can outperform more autonomous loops. [11] The lesson is not "maximize autonomy." It is "build reliable feedback channels."&lt;/p&gt;

&lt;p&gt;Adjacent research on iterative refinement, tool-using agents, and search-style reasoning is relevant to the broader agent landscape, but it is not the core proof for this protocol. [3][6][7] Model-level approaches such as process supervision, reasoning bootstrapping, and reinforcement learning for self-correction may improve future models, but most teams cannot touch training-time systems. [18][19][20] For day-to-day engineering teams, the leverage stays in the environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "Learning" Actually Means Here
&lt;/h2&gt;

&lt;p&gt;Three kinds of learning, only one of which you control:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kind&lt;/th&gt;
&lt;th&gt;Where it lives&lt;/th&gt;
&lt;th&gt;Lifespan&lt;/th&gt;
&lt;th&gt;Your leverage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Training-time&lt;/td&gt;
&lt;td&gt;The model weights&lt;/td&gt;
&lt;td&gt;Permanent&lt;/td&gt;
&lt;td&gt;Almost none&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;In-context&lt;/td&gt;
&lt;td&gt;The current thread&lt;/td&gt;
&lt;td&gt;Until the thread ends&lt;/td&gt;
&lt;td&gt;Real but temporary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;System-level&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The repo, CI, instructions, skills&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Until you retire it&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;High: this is the protocol&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If the agent fixes a bug after seeing a failing test, it improved &lt;em&gt;in the session&lt;/em&gt;. If the repository now carries a regression test that blocks that bug from returning, the &lt;em&gt;system&lt;/em&gt; improved. The Iron Man Protocol is entirely about that third row.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Protocol
&lt;/h2&gt;

&lt;p&gt;Seven steps. The seventh is the one most "lessons learned" systems forget, and the reason most of them rot.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Capture the failure
&lt;/h3&gt;

&lt;p&gt;Do not let the failure live only in a chat transcript. Record it while the evidence is fresh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Mistake Record&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Date / Task:
&lt;span class="p"&gt;-&lt;/span&gt; What the agent did / What was wrong:
&lt;span class="p"&gt;-&lt;/span&gt; How it was detected:
&lt;span class="p"&gt;-&lt;/span&gt; Root cause:
&lt;span class="p"&gt;-&lt;/span&gt; Correct behavior:
&lt;span class="p"&gt;-&lt;/span&gt; Durable artifact needed (test / rule / skill / hook / memory / eval):
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is compression, not bureaucracy: a confusing interaction becomes a reusable lesson.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Diagnose along two axes
&lt;/h3&gt;

&lt;p&gt;Earlier versions of this protocol used a flat list of seven failure "types." That list leaks: real failures rarely sit in one bucket. The worked example below is a context failure &lt;em&gt;and&lt;/em&gt; a verification failure at once. Diagnose along two orthogonal axes instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Context axis:&lt;/strong&gt; did the agent lack something it needed to know? A convention, dependency, product rule, hidden workflow step?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verification axis:&lt;/strong&gt; did the agent fail to &lt;em&gt;check&lt;/em&gt; what it changed? Wrong test, skipped lint/typecheck, no reproduction, missed regression?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most mistakes score on both. The axes matter because they point to different artifacts: context gaps become &lt;strong&gt;knowledge&lt;/strong&gt; (an &lt;code&gt;AGENTS.md&lt;/code&gt; rule, a skill); verification gaps become &lt;strong&gt;enforcement&lt;/strong&gt; (a test, a hook, a CI check). The familiar labels, such as bad localization, over-broad change, tool misuse, review miss, and memory gap, are common positions on these two axes, not separate categories.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Choose the durable artifact
&lt;/h3&gt;

&lt;p&gt;The rule: &lt;strong&gt;never store an important lesson only as prose in a conversation.&lt;/strong&gt; Match the artifact to the failure:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Failure&lt;/th&gt;
&lt;th&gt;Durable upgrade&lt;/th&gt;
&lt;th&gt;Use when&lt;/th&gt;
&lt;th&gt;Do &lt;strong&gt;not&lt;/strong&gt; use when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Recurring repo convention&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;AGENTS.md&lt;/code&gt; rule&lt;/td&gt;
&lt;td&gt;It should govern future work in the repo/subtree.&lt;/td&gt;
&lt;td&gt;It is temporary, personal, or better enforced by a test.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skipped validation&lt;/td&gt;
&lt;td&gt;Hook / CI check / test command&lt;/td&gt;
&lt;td&gt;The same check keeps getting missed.&lt;/td&gt;
&lt;td&gt;It is noisy, slow, or not yet well understood.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Behavioral bug&lt;/td&gt;
&lt;td&gt;Regression test&lt;/td&gt;
&lt;td&gt;The issue is user-visible and reproducible.&lt;/td&gt;
&lt;td&gt;It is not yet deterministic enough to encode.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repeated multi-step task&lt;/td&gt;
&lt;td&gt;Skill&lt;/td&gt;
&lt;td&gt;The task has repeatable steps, references, or scripts.&lt;/td&gt;
&lt;td&gt;One sentence in &lt;code&gt;AGENTS.md&lt;/code&gt; is enough.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stable local preference&lt;/td&gt;
&lt;td&gt;Memory&lt;/td&gt;
&lt;td&gt;It helps future local sessions only.&lt;/td&gt;
&lt;td&gt;It must bind a team or repo; use checked-in rules.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent-behavior failure&lt;/td&gt;
&lt;td&gt;Eval case&lt;/td&gt;
&lt;td&gt;You need to measure whether behavior improved.&lt;/td&gt;
&lt;td&gt;You have no harness, expected behavior, or scoring.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sequence/handoff failure&lt;/td&gt;
&lt;td&gt;Trace + postmortem&lt;/td&gt;
&lt;td&gt;The lesson depends on ordering or context.&lt;/td&gt;
&lt;td&gt;A small test or rule already captures it.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Codex-specific surfaces have sharp edges. &lt;code&gt;AGENTS.md&lt;/code&gt; is durable repository guidance. [12] Memories are optional local recall, not a system of record for mandatory team policy. [13] Skills are reusable workflows. [14] Hooks are lifecycle automation and require configuration and trust review. [15] Evals require a defined task, expected behavior, harness, and scoring method. [16][17]&lt;/p&gt;

&lt;p&gt;Every artifact you add is a liability as well as an asset: it must be maintained, it consumes attention or context, and it can go stale. Add it deliberately, and tag it so Step 7 can find it later.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Make the lesson verifiable
&lt;/h3&gt;

&lt;p&gt;A lesson is only as good as the evidence the agent can check it against. This is the highest-leverage move in the protocol, so be ruthless about specificity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Weak:    - Be careful with authentication.
Strong:  - When editing OAuth callback handling, run &lt;span class="sb"&gt;`npm test -- auth callback`&lt;/span&gt;
           and verify expired-state rejection.

Weak:    - Do not break migrations.
Strong:  - When changing DB migrations, include rollback coverage and run
           &lt;span class="sb"&gt;`make test-migrations`&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A strong instruction names a &lt;strong&gt;trigger&lt;/strong&gt; ("when editing X"), an &lt;strong&gt;action&lt;/strong&gt; ("run Y"), and an &lt;strong&gt;observable result&lt;/strong&gt; ("verify Z"). The agent can follow specific rules and check specific evidence; it cannot reliably operationalize a vague warning. If you can write only one artifact per failure, write this one.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Patch the workflow, not just the code
&lt;/h3&gt;

&lt;p&gt;After every fix, ask: &lt;em&gt;what should exist now so this class of mistake is less likely next time?&lt;/em&gt; Step 3 &lt;em&gt;chooses&lt;/em&gt; the artifact; Step 5 &lt;em&gt;wires it in&lt;/em&gt;: checked into the repo, referenced from &lt;code&gt;AGENTS.md&lt;/code&gt;, enforced in CI, packaged as a skill, or run by a configured hook. A lesson that is not wired into the workflow is just a nicer transcript.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. End with evidence, when the change warrants it
&lt;/h3&gt;

&lt;p&gt;Consequential or correctness-affecting changes should close with evidence. Trivial edits should not; forcing a ceremony on every keystroke just trains people to rubber-stamp it. When it matters, the final report answers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What changed, and what failure was reproduced?&lt;/li&gt;
&lt;li&gt;What check now passes that previously failed?&lt;/li&gt;
&lt;li&gt;What durable artifact was added, updated, &lt;strong&gt;or retired&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;What risk remains?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. Retire what no longer earns its place
&lt;/h3&gt;

&lt;p&gt;This is the step that keeps the protocol from defeating itself. A pure "capture every lesson" ratchet ends exactly where the agent performs worst: a bloated &lt;code&gt;AGENTS.md&lt;/code&gt; that dilutes its own context window, a slow and flaky regression suite, and rules that contradict each other. Durability without pruning is just accumulation.&lt;/p&gt;

&lt;p&gt;Give the system a maintenance budget and a retirement rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Budget the surfaces.&lt;/strong&gt; Cap &lt;code&gt;AGENTS.md&lt;/code&gt;, for example by requiring the active rules to fit on one screen of scoped, action-oriented lines. When you add a rule that pushes past the cap, retire, merge, or demote an older one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Date and review.&lt;/strong&gt; Tag each artifact with the failure it came from and the last time it fired. Review instruction files monthly, or whenever a rule causes confusion. Sweep for artifacts that have not triggered, no longer apply, or duplicate a stronger check.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resolve conflicts at write time.&lt;/strong&gt; Before adding a rule, search the existing ones. If the new rule contradicts or supersedes an existing rule, edit in place rather than appending a second voice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefer enforcement over prose.&lt;/strong&gt; A CI check is more self-checking than prose because failure creates a visible signal. But checks also get flaky, slow, and obsolete, so they need the same retirement discipline as instructions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Retirement is not optional cleanup; it is what makes "durable" mean &lt;em&gt;load-bearing&lt;/em&gt; rather than &lt;em&gt;permanent&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Minimal Template
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Iron Man Protocol Entry&lt;/span&gt;
&lt;span class="gu"&gt;## Failure        - what happened / how detected&lt;/span&gt;
&lt;span class="gu"&gt;## Diagnosis      - root cause / context-axis + verification-axis scoring&lt;/span&gt;
&lt;span class="gu"&gt;## Upgrade        - code or test change / instruction update / skill|hook|memory|eval&lt;/span&gt;
&lt;span class="gu"&gt;## Verification   - command run / result / remaining risk&lt;/span&gt;
&lt;span class="gu"&gt;## Bookkeeping    - artifact id + date added; rule it replaces, if any&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The point is not a long incident report for every small issue. It is to avoid losing the lesson, and to leave a trail Step 7 can prune.&lt;/p&gt;

&lt;h2&gt;
  
  
  How You Know It Is Working
&lt;/h2&gt;

&lt;p&gt;The protocol's own thesis is that assertion is weak and evidence is strong, so it must hold itself to the same standard. Do not claim the protocol works. Measure it.&lt;/p&gt;

&lt;p&gt;The minimum viable version is a mistake log with tags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; 2026-06-10: schema-client-drift / context + verification / fixed by check-generated
&lt;span class="p"&gt;-&lt;/span&gt; 2026-06-18: missed-auth-test / verification / fixed by AGENTS rule + test command
&lt;span class="p"&gt;-&lt;/span&gt; 2026-06-25: bad-localization / context / fixed by routing note in AGENTS.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the log exists, track three simple signals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repeat-failure rate:&lt;/strong&gt; how often a &lt;em&gt;previously captured&lt;/em&gt; failure class recurs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Artifact hit-rate:&lt;/strong&gt; how often each durable artifact catches a real problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Surface budget:&lt;/strong&gt; size of &lt;code&gt;AGENTS.md&lt;/code&gt;, suite runtime, and number of active rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If repeat failures stay flat, the artifacts are not changing behavior. If artifacts never fire, they are retirement candidates, not trophies. If surface budget climbs monotonically, your retirement step is broken.&lt;/p&gt;

&lt;p&gt;A worked example follows. It is &lt;strong&gt;illustrative, not evidence&lt;/strong&gt;. Substitute your own numbers from a real incident, because a real before/after is the only thing that proves the loop pays off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked Example (illustrative)
&lt;/h2&gt;

&lt;p&gt;A task adds a &lt;code&gt;preferred_locale&lt;/code&gt; field to an account API response. The code looks fine and backend tests pass, but CI fails later because the generated TypeScript client still expects the old shape. A reviewer notes this has happened before.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Diagnosis.&lt;/strong&gt; Context axis: the schema-to-client generation step was invisible in the prompt and the repo rules. Verification axis: no drift check ran before the change was considered done. Both axes, one incident.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;, before -&amp;gt; after.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; Run backend tests before opening a PR.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; When changing API schema files, run &lt;span class="sb"&gt;`make clients`&lt;/span&gt; and commit the regenerated
  client in the same change.
&lt;span class="p"&gt;-&lt;/span&gt; After clients regenerate, run &lt;span class="sb"&gt;`make check-generated`&lt;/span&gt; before stopping.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Enforcement.&lt;/strong&gt; Add or confirm a &lt;code&gt;make check-generated&lt;/code&gt; drift check in CI that fails when schema changes are not reflected in generated client files. The check is the primary guard; the prose rule tells the agent when to run it before CI does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verification.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; Reproduced: &lt;span class="sb"&gt;`make check-generated`&lt;/span&gt; failed before regeneration.
&lt;span class="p"&gt;-&lt;/span&gt; Repair: ran &lt;span class="sb"&gt;`make clients`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; Result: &lt;span class="sb"&gt;`make check-generated`&lt;/span&gt; passed; schema, mapper, and generated client all changed.
&lt;span class="p"&gt;-&lt;/span&gt; Remaining risk: a future schema package with a different generator would need the rule extended to name it.
&lt;span class="p"&gt;-&lt;/span&gt; Bookkeeping: schema-client-drift-2026-06; supersedes the bare "run backend tests" line.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 7 follow-through.&lt;/strong&gt; Because the drift check now enforces the behavior in CI, the prose rule is the weaker, higher-maintenance copy. At the next sweep, consider trimming the &lt;code&gt;AGENTS.md&lt;/code&gt; lines to a single pointer: "schema changes are gated by &lt;code&gt;make check-generated&lt;/code&gt; in CI." That keeps the green check, not the paragraph, closest to the source of truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  A 30-Minute Start
&lt;/h2&gt;

&lt;p&gt;Pick one recurring failure from the last week. Write one mistake entry. Add or update one regression test, validation command, or CI check that would have caught it. Add one concrete, triggered &lt;code&gt;AGENTS.md&lt;/code&gt; rule that says exactly when to run that check. Rerun the validation and record the result.&lt;/p&gt;

&lt;p&gt;Then, if instructions already exist, delete, merge, demote, or mark one stale rule for later review. You have now run the full loop, including retirement, on a single failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Avoid
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Be more careful" prompts.&lt;/strong&gt; Too vague to enforce; this is the entire reason for Step 4.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory as the system of record.&lt;/strong&gt; Mandatory project rules belong in checked-in instructions, tests, CI, hooks, or skills, not in per-session memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Append-only instruction files.&lt;/strong&gt; Capturing every lesson and keeping files small are only compatible if you actually run Step 7. Adding a rule without budgeting for its retirement is how &lt;code&gt;AGENTS.md&lt;/code&gt; becomes noise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evals from imaginary failures.&lt;/strong&gt; The best eval cases come from real bugs, user corrections, production incidents, CI failures, and reviewer comments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automating too early.&lt;/strong&gt; Understand the failure first. A hook that runs the wrong check is negative value.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Final Idea
&lt;/h2&gt;

&lt;p&gt;A coding agent does not permanently retrain itself after a bad interaction. But the environment around it can be re-engineered after failures, and pruned when the lessons go stale. The repo gains tests; CI gains checks; the agent gains skills and sharper rules; the eval suite gains real failure cases; and the instruction files stay small because what no longer fires gets removed.&lt;/p&gt;

&lt;p&gt;Stark survives because the next suit carries the lesson from the last fight, and because he strips the parts that stopped working. Build the agent's environment the same way.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a id="ref-1"&gt;&lt;/a&gt;&lt;br&gt;
[1] OpenAI Developers, "Prompting - Codex." &lt;a href="https://developers.openai.com/codex/prompting" rel="noopener noreferrer"&gt;https://developers.openai.com/codex/prompting&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-2"&gt;&lt;/a&gt;&lt;br&gt;
[2] Noah Shinn et al., "Reflexion: Language Agents with Verbal Reinforcement Learning." &lt;a href="https://arxiv.org/abs/2303.11366" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2303.11366&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-3"&gt;&lt;/a&gt;&lt;br&gt;
[3] Aman Madaan et al., "Self-Refine: Iterative Refinement with Self-Feedback." &lt;a href="https://arxiv.org/abs/2303.17651" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2303.17651&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-4"&gt;&lt;/a&gt;&lt;br&gt;
[4] Jie Huang et al., "Large Language Models Cannot Self-Correct Reasoning Yet." &lt;a href="https://arxiv.org/abs/2310.01798" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2310.01798&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-5"&gt;&lt;/a&gt;&lt;br&gt;
[5] Ryo Kamoi et al., "When Can LLMs Actually Correct Their Own Mistakes? A Critical Survey of Self-Correction of LLMs." &lt;a href="https://arxiv.org/abs/2406.01297" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2406.01297&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-6"&gt;&lt;/a&gt;&lt;br&gt;
[6] Shunyu Yao et al., "ReAct: Synergizing Reasoning and Acting in Language Models." &lt;a href="https://arxiv.org/abs/2210.03629" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2210.03629&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-7"&gt;&lt;/a&gt;&lt;br&gt;
[7] Shunyu Yao et al., "Tree of Thoughts: Deliberate Problem Solving with Large Language Models." &lt;a href="https://arxiv.org/abs/2305.10601" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2305.10601&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-8"&gt;&lt;/a&gt;&lt;br&gt;
[8] Guanzhi Wang et al., "Voyager: An Open-Ended Embodied Agent with Large Language Models." &lt;a href="https://arxiv.org/abs/2305.16291" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2305.16291&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-9"&gt;&lt;/a&gt;&lt;br&gt;
[9] Carlos E. Jimenez et al., "SWE-bench: Can Language Models Resolve Real-World GitHub Issues?" &lt;a href="https://arxiv.org/abs/2310.06770" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2310.06770&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-10"&gt;&lt;/a&gt;&lt;br&gt;
[10] John Yang et al., "SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering." &lt;a href="https://arxiv.org/abs/2405.15793" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2405.15793&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-11"&gt;&lt;/a&gt;&lt;br&gt;
[11] Chunqiu Steven Xia et al., "Agentless: Demystifying LLM-based Software Engineering Agents." &lt;a href="https://arxiv.org/abs/2407.01489" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2407.01489&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-12"&gt;&lt;/a&gt;&lt;br&gt;
[12] OpenAI Developers, "Custom instructions with AGENTS.md - Codex." &lt;a href="https://developers.openai.com/codex/guides/agents-md" rel="noopener noreferrer"&gt;https://developers.openai.com/codex/guides/agents-md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-13"&gt;&lt;/a&gt;&lt;br&gt;
[13] OpenAI Developers, "Memories - Codex." &lt;a href="https://developers.openai.com/codex/memories" rel="noopener noreferrer"&gt;https://developers.openai.com/codex/memories&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-14"&gt;&lt;/a&gt;&lt;br&gt;
[14] OpenAI Developers, "Agent Skills - Codex." &lt;a href="https://developers.openai.com/codex/skills" rel="noopener noreferrer"&gt;https://developers.openai.com/codex/skills&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-15"&gt;&lt;/a&gt;&lt;br&gt;
[15] OpenAI Developers, "Hooks - Codex." &lt;a href="https://developers.openai.com/codex/hooks" rel="noopener noreferrer"&gt;https://developers.openai.com/codex/hooks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-16"&gt;&lt;/a&gt;&lt;br&gt;
[16] OpenAI Developers, "Working with evals." &lt;a href="https://developers.openai.com/api/docs/guides/evals" rel="noopener noreferrer"&gt;https://developers.openai.com/api/docs/guides/evals&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-17"&gt;&lt;/a&gt;&lt;br&gt;
[17] OpenAI Cookbook, "Build an Agent Improvement Loop with Traces, Evals, and Codex." &lt;a href="https://developers.openai.com/cookbook/examples/agents_sdk/agent_improvement_loop" rel="noopener noreferrer"&gt;https://developers.openai.com/cookbook/examples/agents_sdk/agent_improvement_loop&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-18"&gt;&lt;/a&gt;&lt;br&gt;
[18] Hunter Lightman et al., "Let's Verify Step by Step." &lt;a href="https://arxiv.org/abs/2305.20050" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2305.20050&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-19"&gt;&lt;/a&gt;&lt;br&gt;
[19] Eric Zelikman et al., "STaR: Bootstrapping Reasoning With Reasoning." &lt;a href="https://arxiv.org/abs/2203.14465" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2203.14465&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id="ref-20"&gt;&lt;/a&gt;&lt;br&gt;
[20] Aviral Kumar et al., "Training Language Models to Self-Correct via Reinforcement Learning (SCoRE)." &lt;a href="https://arxiv.org/abs/2409.12917" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2409.12917&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>agents</category>
      <category>openai</category>
    </item>
    <item>
      <title>AGI, Are We There Yet? A Follow-Up</title>
      <dc:creator>Ernesto Herrera Salinas</dc:creator>
      <pubDate>Thu, 25 Jun 2026 03:38:00 +0000</pubDate>
      <link>https://dev.to/ernestohs/agi-are-we-there-yet-a-follow-up-1471</link>
      <guid>https://dev.to/ernestohs/agi-are-we-there-yet-a-follow-up-1471</guid>
      <description>&lt;p&gt;In my previous article, &lt;a href="https://dev.to/ernestohs/agi-are-we-there-yet-n5p"&gt;AGI, Are We There Yet?&lt;/a&gt;, I asked a simple question with a complicated answer:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are we at AGI yet?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At the time, OpenAI’s o3 had just made headlines for its performance on ARC-AGI-1. Depending on the compute budget, o3 reached &lt;strong&gt;75.7%&lt;/strong&gt; on the semi-private evaluation set and &lt;strong&gt;87.5%&lt;/strong&gt; in a much higher-compute configuration, according to &lt;a href="https://arcprize.org/blog/oai-o3-pub-breakthrough" rel="noopener noreferrer"&gt;ARC Prize’s analysis of the o3 result&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That was a serious milestone. It was not just another benchmark bump. ARC was designed to test something closer to fluid intelligence: the ability to solve novel problems, not just repeat patterns from training data.&lt;/p&gt;

&lt;p&gt;But my conclusion then was cautious:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This was a pit stop on the road to AGI, not the destination.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A year and a half later, that still looks like the right call.&lt;/p&gt;

&lt;p&gt;The story since then has not been “AGI arrived.” The story is more interesting than that. Frontier models have become much better at reasoning, coding, tool use, multimodal understanding, long-context processing, and agent-like workflows. They are more useful, more capable, and more economically relevant than the systems we were discussing even a short time ago.&lt;/p&gt;

&lt;p&gt;But they are still not robustly general in the human sense.&lt;/p&gt;

&lt;p&gt;So where are we today?&lt;/p&gt;

&lt;p&gt;We are not at AGI.&lt;/p&gt;

&lt;p&gt;But we are no longer talking about simple chatbots either.&lt;/p&gt;

&lt;p&gt;We are now in the era of &lt;strong&gt;frontier reasoning-and-agent systems&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Current answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Did o3’s ARC-AGI-1 result matter?&lt;/td&gt;
&lt;td&gt;Yes. It was a real milestone.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Did it prove AGI had arrived?&lt;/td&gt;
&lt;td&gt;No. ARC Prize itself warned against that interpretation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Have frontier models improved since then?&lt;/td&gt;
&lt;td&gt;Yes, significantly. Especially in reasoning, coding, multimodality, long context, and tool use.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Are old benchmarks still enough?&lt;/td&gt;
&lt;td&gt;No. Many are saturated or noisy.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Are newer benchmarks still difficult?&lt;/td&gt;
&lt;td&gt;Yes. ARC-AGI-2, ARC-AGI-3, HLE, and long-horizon task evaluations still expose major gaps.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Are we at AGI?&lt;/td&gt;
&lt;td&gt;No. We are at increasingly general-purpose, increasingly agentic systems, but not robust human-like general intelligence.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What the previous article claimed and how it reads today
&lt;/h2&gt;

&lt;p&gt;The previous article defined AGI as &lt;strong&gt;the broad adaptability of a human mind&lt;/strong&gt;, contrasted it with narrow AI, and argued that o3’s ARC result was important but not conclusive.&lt;/p&gt;

&lt;p&gt;That framing still holds.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Claim from the original article&lt;/th&gt;
&lt;th&gt;Current evidence&lt;/th&gt;
&lt;th&gt;Updated reading&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AGI should imply broad adaptability, not just task-specific skill.&lt;/td&gt;
&lt;td&gt;François Chollet’s &lt;a href="https://arxiv.org/abs/1911.01547" rel="noopener noreferrer"&gt;On the Measure of Intelligence&lt;/a&gt; frames intelligence around skill-acquisition efficiency and fluid generalization, not static benchmark skill.&lt;/td&gt;
&lt;td&gt;Still correct. Benchmarks are useful, but not equivalent to AGI.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;o3’s ARC-AGI-1 result was a milestone.&lt;/td&gt;
&lt;td&gt;ARC Prize reported o3 at 75.7% under the public compute budget and 87.5% in a high-compute configuration.&lt;/td&gt;
&lt;td&gt;Still correct. It was a major jump.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Passing ARC-AGI-1 should not be treated as AGI.&lt;/td&gt;
&lt;td&gt;ARC Prize explicitly said the result did not mean AGI had arrived and later introduced harder ARC-AGI benchmarks.&lt;/td&gt;
&lt;td&gt;Still correct, and even more strongly supported now.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chain-of-thought is not necessarily a faithful window into reasoning.&lt;/td&gt;
&lt;td&gt;Research like &lt;a href="https://arxiv.org/abs/2411.15862" rel="noopener noreferrer"&gt;LLMs Do Not Think Step-by-step In Implicit Reasoning&lt;/a&gt; and later chain-of-thought monitorability work suggests caution.&lt;/td&gt;
&lt;td&gt;Still correct. Reasoning traces are useful, but not proof of internal cognition.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling laws matter, but do not guarantee AGI.&lt;/td&gt;
&lt;td&gt;OpenAI’s &lt;a href="https://openai.com/index/learning-to-reason-with-llms/" rel="noopener noreferrer"&gt;Learning to reason with LLMs&lt;/a&gt; and Google’s &lt;a href="https://storage.googleapis.com/deepmind-media/gemini/gemini_v2_5_report.pdf" rel="noopener noreferrer"&gt;Gemini 2.5 report&lt;/a&gt; show gains from both training-time and inference-time compute.&lt;/td&gt;
&lt;td&gt;Correct, with an update: the frontier now also scales through test-time reasoning and tool use.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The o3 ARC result aged well, but not as proof of AGI
&lt;/h2&gt;

&lt;p&gt;The o3 result on ARC-AGI-1 was real and important. It showed that test-time compute, better reasoning methods, and stronger model scaffolding could dramatically improve performance on tasks that had resisted previous systems.&lt;/p&gt;

&lt;p&gt;That matters.&lt;/p&gt;

&lt;p&gt;But the caveats also mattered.&lt;/p&gt;

&lt;p&gt;ARC Prize itself warned that passing ARC-AGI-1 should not be treated as “AGI achieved.” They noted that o3 still failed some tasks humans would find easy, that the result depended heavily on compute, and that the tested system had been trained using part of the public ARC training set.&lt;/p&gt;

&lt;p&gt;That distinction is critical.&lt;/p&gt;

&lt;p&gt;A model can perform extremely well on a benchmark without possessing the full flexible intelligence that the benchmark was trying to approximate.&lt;/p&gt;

&lt;p&gt;And that is exactly what became clearer afterward.&lt;/p&gt;

&lt;p&gt;ARC-AGI-1 started to saturate, so &lt;a href="https://arxiv.org/html/2505.11831v1" rel="noopener noreferrer"&gt;ARC-AGI-2&lt;/a&gt; was introduced. This newer benchmark kept the original spirit of ARC but increased the difficulty around compositional reasoning, contextual rule application, and novelty.&lt;/p&gt;

&lt;p&gt;The result?&lt;/p&gt;

&lt;p&gt;As of the ARC-AGI-2 paper, frontier models were still below meaningful performance. OpenAI o3 scored around &lt;strong&gt;3%&lt;/strong&gt;, and other leading systems were similarly weak. The benchmark authors considered scores under &lt;strong&gt;5%&lt;/strong&gt; not meaningful.&lt;/p&gt;

&lt;p&gt;Then &lt;a href="https://arxiv.org/html/2603.24621v1" rel="noopener noreferrer"&gt;ARC-AGI-3&lt;/a&gt; went further. Instead of static puzzles, it introduced interactive environments where agents must infer goals, explore, learn rules, and adapt through interaction.&lt;/p&gt;

&lt;p&gt;Again, frontier systems struggled. As of the ARC-AGI-3 paper, leading AI systems were below &lt;strong&gt;1%&lt;/strong&gt;, while humans could solve the environments reliably.&lt;/p&gt;

&lt;p&gt;That is the cleanest update to my previous article:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;o3 broke through ARC-AGI-1, but the broader ARC program did not confirm AGI. It confirmed that evaluation had to move.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is progress, but it is not arrival.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timeline: AGI-relevant milestones since the previous article
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Milestone&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dec 2024&lt;/td&gt;
&lt;td&gt;ARC Prize reports o3 at 75.7% high-efficiency and 87.5% high-compute on ARC-AGI-1.&lt;/td&gt;
&lt;td&gt;A major reasoning benchmark breakthrough, but not proof of AGI.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jan 2025&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://arxiv.org/abs/2501.14249" rel="noopener noreferrer"&gt;Humanity’s Last Exam&lt;/a&gt; is introduced.&lt;/td&gt;
&lt;td&gt;A harder, broad academic benchmark designed after older benchmarks became easier for frontier models.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mar 2025&lt;/td&gt;
&lt;td&gt;METR publishes work on &lt;a href="https://arxiv.org/abs/2503.14499" rel="noopener noreferrer"&gt;measuring AI ability to complete long tasks&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;Moves evaluation from static questions toward task duration and real-world work horizons.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apr 2025&lt;/td&gt;
&lt;td&gt;OpenAI releases &lt;a href="https://openai.com/index/introducing-o3-and-o4-mini/" rel="noopener noreferrer"&gt;o3 and o4-mini&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;Reasoning models become more explicitly tool-using and agentic.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 2025&lt;/td&gt;
&lt;td&gt;Anthropic releases &lt;a href="https://www.anthropic.com/news/claude-4" rel="noopener noreferrer"&gt;Claude 4&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;Stronger agentic coding and long-running software workflows become a major frontier battleground.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 2025&lt;/td&gt;
&lt;td&gt;ARC-AGI-2 paper shows frontier systems still below meaningful performance.&lt;/td&gt;
&lt;td&gt;Strong evidence that novelty and compositional generalization remain hard.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jun 2025&lt;/td&gt;
&lt;td&gt;Google publishes the &lt;a href="https://storage.googleapis.com/deepmind-media/gemini/gemini_v2_5_report.pdf" rel="noopener noreferrer"&gt;Gemini 2.5 technical report&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;Shows broad gains in coding, reasoning, multimodality, long context, and thinking-budget performance.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mar 2026&lt;/td&gt;
&lt;td&gt;ARC-AGI-3 is introduced for agentic intelligence.&lt;/td&gt;
&lt;td&gt;Moves evaluation from static reasoning puzzles to interactive environments.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 2026&lt;/td&gt;
&lt;td&gt;METR publishes updated &lt;a href="https://metr.org/time-horizons/" rel="noopener noreferrer"&gt;task-completion time horizon measurements&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;Tracks how long frontier models can work reliably on realistic tasks.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The important shift is not just that model scores went up. The field also changed what it measures.&lt;/p&gt;

&lt;p&gt;By early 2025, older tests were already too easy or too noisy. By mid-2025, the most capable models were being compared on coding agents, difficult science questions, long-context retrieval, multimodal reasoning, and expert-level exams. By 2026, benchmark designers were moving from static test items to interactive environments.&lt;/p&gt;

&lt;p&gt;That evolution itself is strong evidence that “AGI” cannot be reduced to one benchmark win.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmarks improved, but benchmarks also got weirder
&lt;/h2&gt;

&lt;p&gt;Since the previous article, model scores have improved across a lot of hard benchmarks.&lt;/p&gt;

&lt;p&gt;Frontier systems now perform strongly on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GPQA&lt;/li&gt;
&lt;li&gt;MMMU&lt;/li&gt;
&lt;li&gt;AIME&lt;/li&gt;
&lt;li&gt;SWE-bench&lt;/li&gt;
&lt;li&gt;LiveCodeBench&lt;/li&gt;
&lt;li&gt;Humanity’s Last Exam&lt;/li&gt;
&lt;li&gt;long-context retrieval tasks&lt;/li&gt;
&lt;li&gt;tool-use evaluations&lt;/li&gt;
&lt;li&gt;multimodal reasoning evaluations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not trivial. These are not toy tasks. Some of these benchmarks test graduate-level science, difficult math, software engineering, visual reasoning, and multi-step problem solving.&lt;/p&gt;

&lt;p&gt;But there is a problem.&lt;/p&gt;

&lt;p&gt;The better models become, the less stable old benchmarks become as evidence.&lt;/p&gt;

&lt;p&gt;MMLU used to be a big deal. Now it is mostly saturated. HumanEval used to be a strong coding signal. Now it is too easy for frontier models. GSM8K used to be a standard math benchmark. Now it does not tell us much about the frontier.&lt;/p&gt;

&lt;p&gt;Even worse, some benchmarks contain errors. The paper &lt;a href="https://arxiv.org/abs/2406.04127" rel="noopener noreferrer"&gt;Are We Done with MMLU?&lt;/a&gt; found that a non-trivial percentage of MMLU questions contain mistakes, with some subsets much worse than others.&lt;/p&gt;

&lt;p&gt;Stanford HAI’s &lt;a href="https://hai.stanford.edu/ai-index/2025-ai-index-report/technical-performance" rel="noopener noreferrer"&gt;2025 AI Index technical performance chapter&lt;/a&gt; also notes that traditional benchmarks like MMLU, GSM8K, and HumanEval have been saturating, while newer benchmarks like MMMU, GPQA, and SWE-bench became more important.&lt;/p&gt;

&lt;p&gt;So the benchmark story today is mixed.&lt;/p&gt;

&lt;p&gt;Yes, models are getting much better.&lt;/p&gt;

&lt;p&gt;But also, the measurement problem is getting harder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mid-2024 generation snapshot
&lt;/h2&gt;

&lt;p&gt;The following table shows the mid-2024 generation of strong models. These values are useful for historical context because they show how quickly the conversation moved from “chatbot” to “general-purpose assistant.”&lt;/p&gt;

&lt;p&gt;Important caveat: these numbers are not perfect apples-to-apples comparisons. Different labs use different prompts, scaffolds, evaluation setups, and reporting conventions.&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;MMLU&lt;/th&gt;
&lt;th&gt;MMLU-Pro&lt;/th&gt;
&lt;th&gt;GPQA&lt;/th&gt;
&lt;th&gt;HumanEval&lt;/th&gt;
&lt;th&gt;BFCL tool use&lt;/th&gt;
&lt;th&gt;Long-context example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPT-4&lt;/td&gt;
&lt;td&gt;86.4&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;67.0&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Multimodal text and image input supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-4o&lt;/td&gt;
&lt;td&gt;89.1&lt;/td&gt;
&lt;td&gt;74.0&lt;/td&gt;
&lt;td&gt;53.6&lt;/td&gt;
&lt;td&gt;90.2&lt;/td&gt;
&lt;td&gt;80.5&lt;/td&gt;
&lt;td&gt;NIAH 100.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude 3.5 Sonnet&lt;/td&gt;
&lt;td&gt;89.9&lt;/td&gt;
&lt;td&gt;77.0&lt;/td&gt;
&lt;td&gt;59.4&lt;/td&gt;
&lt;td&gt;92.0&lt;/td&gt;
&lt;td&gt;90.2&lt;/td&gt;
&lt;td&gt;NIAH 90.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Llama 3.1 405B&lt;/td&gt;
&lt;td&gt;87.3&lt;/td&gt;
&lt;td&gt;73.3&lt;/td&gt;
&lt;td&gt;51.1&lt;/td&gt;
&lt;td&gt;89.0&lt;/td&gt;
&lt;td&gt;88.5&lt;/td&gt;
&lt;td&gt;ZeroSCROLLS/QuALITY 95.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-3.5 Turbo&lt;/td&gt;
&lt;td&gt;70.7&lt;/td&gt;
&lt;td&gt;49.2&lt;/td&gt;
&lt;td&gt;30.8&lt;/td&gt;
&lt;td&gt;68.0&lt;/td&gt;
&lt;td&gt;85.9&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Sources: &lt;a href="https://cdn.openai.com/papers/gpt-4.pdf" rel="noopener noreferrer"&gt;GPT-4 Technical Report&lt;/a&gt;, &lt;a href="https://ar5iv.labs.arxiv.org/html/2407.21783" rel="noopener noreferrer"&gt;The Llama 3 Herd of Models&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This table explains why the conversation changed so quickly in 2024. The strongest systems were no longer merely fluent chatbots. By mid-2024, leading models were posting near-saturated MMLU scores, strong code generation, usable tool calling, and credible long-context retrieval.&lt;/p&gt;

&lt;p&gt;But even here, GPQA remained much lower than MMLU, which foreshadowed the field’s shift toward harder reasoning benchmarks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mid-2025 frontier reasoning snapshot
&lt;/h2&gt;

&lt;p&gt;By mid-2025, the frontier had moved from “models that answer” toward “models that reason with tools.”&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;LiveCodeBench&lt;/th&gt;
&lt;th&gt;Aider Polyglot&lt;/th&gt;
&lt;th&gt;SWE-bench Verified&lt;/th&gt;
&lt;th&gt;GPQA&lt;/th&gt;
&lt;th&gt;Humanity’s Last Exam&lt;/th&gt;
&lt;th&gt;AIME 2025&lt;/th&gt;
&lt;th&gt;LOFT &amp;lt;=128K&lt;/th&gt;
&lt;th&gt;MMMU&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 2.5 Pro&lt;/td&gt;
&lt;td&gt;74.2&lt;/td&gt;
&lt;td&gt;82.2&lt;/td&gt;
&lt;td&gt;59.6 single / 67.2 multi&lt;/td&gt;
&lt;td&gt;86.4&lt;/td&gt;
&lt;td&gt;21.6&lt;/td&gt;
&lt;td&gt;88.0&lt;/td&gt;
&lt;td&gt;87.0&lt;/td&gt;
&lt;td&gt;82.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI o3 high&lt;/td&gt;
&lt;td&gt;72.0&lt;/td&gt;
&lt;td&gt;79.6&lt;/td&gt;
&lt;td&gt;69.1 single&lt;/td&gt;
&lt;td&gt;83.3&lt;/td&gt;
&lt;td&gt;20.3&lt;/td&gt;
&lt;td&gt;88.9&lt;/td&gt;
&lt;td&gt;77.0&lt;/td&gt;
&lt;td&gt;82.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI o4-mini high&lt;/td&gt;
&lt;td&gt;75.8&lt;/td&gt;
&lt;td&gt;72.0&lt;/td&gt;
&lt;td&gt;68.1 single&lt;/td&gt;
&lt;td&gt;81.4&lt;/td&gt;
&lt;td&gt;18.1&lt;/td&gt;
&lt;td&gt;92.7&lt;/td&gt;
&lt;td&gt;60.5&lt;/td&gt;
&lt;td&gt;81.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude 4 Sonnet&lt;/td&gt;
&lt;td&gt;48.9&lt;/td&gt;
&lt;td&gt;61.3&lt;/td&gt;
&lt;td&gt;72.7 single / 80.2 high-compute multi&lt;/td&gt;
&lt;td&gt;75.4 with extended thinking / 70.0 without&lt;/td&gt;
&lt;td&gt;7.8&lt;/td&gt;
&lt;td&gt;70.5&lt;/td&gt;
&lt;td&gt;81.6&lt;/td&gt;
&lt;td&gt;74.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude 4 Opus&lt;/td&gt;
&lt;td&gt;51.1&lt;/td&gt;
&lt;td&gt;72.0&lt;/td&gt;
&lt;td&gt;72.5 single / 79.4 high-compute multi&lt;/td&gt;
&lt;td&gt;79.6 with extended thinking / 74.9 without&lt;/td&gt;
&lt;td&gt;10.7&lt;/td&gt;
&lt;td&gt;75.5&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;76.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek R1&lt;/td&gt;
&lt;td&gt;70.5&lt;/td&gt;
&lt;td&gt;71.6&lt;/td&gt;
&lt;td&gt;57.6 multi&lt;/td&gt;
&lt;td&gt;81.0&lt;/td&gt;
&lt;td&gt;14.0&lt;/td&gt;
&lt;td&gt;87.5&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;No native multimodal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Sources: &lt;a href="https://storage.googleapis.com/deepmind-media/gemini/gemini_v2_5_report.pdf" rel="noopener noreferrer"&gt;Gemini 2.5 technical report&lt;/a&gt;, &lt;a href="https://www.anthropic.com/news/claude-4" rel="noopener noreferrer"&gt;Claude 4 announcement and benchmark appendix&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This table captures the current situation better than any single “AGI score.”&lt;/p&gt;

&lt;p&gt;The strongest systems now span a much larger capability bundle than the previous article discussed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;frontier coding&lt;/li&gt;
&lt;li&gt;difficult science QA&lt;/li&gt;
&lt;li&gt;difficult math&lt;/li&gt;
&lt;li&gt;long-context retrieval&lt;/li&gt;
&lt;li&gt;multimodal understanding&lt;/li&gt;
&lt;li&gt;tool use&lt;/li&gt;
&lt;li&gt;agentic workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gemini 2.5 Pro looks especially broad in public vendor reporting. OpenAI’s o3 and o4-mini look especially strong on reasoning-heavy tasks and multimodal perception. Anthropic’s Claude 4 family looks especially strong in coding and tool-using software workflows.&lt;/p&gt;

&lt;p&gt;But the caution is important.&lt;/p&gt;

&lt;p&gt;Benchmark wins are not stable enough to map directly to AGI claims. Different labs use different scaffolds and compute settings. Anthropic explicitly distinguishes no-extended-thinking benchmarks from benchmarks run with extended thinking and tool use. Google also notes that many non-Gemini results are provider self-reports.&lt;/p&gt;

&lt;p&gt;These comparisons are useful, but only as capability indicators. They are not a definitive scoreboard for general intelligence.&lt;/p&gt;

&lt;h2&gt;
  
  
  The biggest shift: models now think with tools
&lt;/h2&gt;

&lt;p&gt;In the previous article, I talked about chain-of-thought and the question of whether models are really reasoning step by step or just producing text that looks like reasoning.&lt;/p&gt;

&lt;p&gt;That question is still open.&lt;/p&gt;

&lt;p&gt;But the field has shifted.&lt;/p&gt;

&lt;p&gt;The most important change is that frontier models are no longer only “answer generators.” They are increasingly systems that can use tools while reasoning.&lt;/p&gt;

&lt;p&gt;Modern frontier models can call Python, browse the web, inspect files, work with images, write and execute code, use external tools, and continue across longer workflows. Some models are explicitly trained to spend more time reasoning before answering. Others allow configurable “thinking budgets,” where more inference-time computation can improve performance.&lt;/p&gt;

&lt;p&gt;This is a major shift.&lt;/p&gt;

&lt;p&gt;The frontier is no longer just about bigger pretraining runs.&lt;/p&gt;

&lt;p&gt;It is now scaling along at least three axes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pretraining scale&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Post-training and reinforcement learning&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inference-time reasoning and tool use&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That third axis is especially important.&lt;/p&gt;

&lt;p&gt;A model that can pause, inspect evidence, run code, test a hypothesis, revise its plan, and continue working is meaningfully different from a model that only predicts the next token in a single pass.&lt;/p&gt;

&lt;p&gt;But this still does not mean AGI.&lt;/p&gt;

&lt;p&gt;It means we are building more capable systems around language models. Some of the intelligence is in the model. Some of it is in the scaffold. Some of it is in the tools. Some of it is in the feedback loop.&lt;/p&gt;

&lt;p&gt;That matters because when people say “the model solved it,” we now need to ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did the model solve it from internal reasoning?&lt;/li&gt;
&lt;li&gt;Did it solve it through tool use?&lt;/li&gt;
&lt;li&gt;Did it solve it through repeated attempts?&lt;/li&gt;
&lt;li&gt;Did it solve it because the benchmark was already familiar?&lt;/li&gt;
&lt;li&gt;Did it solve it because the environment was carefully scaffolded?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are not nitpicks. They are the difference between measuring a model and measuring a whole engineered system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Long-horizon work is improving, but still limited
&lt;/h2&gt;

&lt;p&gt;One of the most useful ways to think about current AI progress comes from METR’s task-completion time horizon work.&lt;/p&gt;

&lt;p&gt;Instead of asking, “What score did the model get on this benchmark?”, METR asks something more intuitive:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How long are the tasks that AI systems can complete reliably?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Their March 2025 paper, &lt;a href="https://arxiv.org/abs/2503.14499" rel="noopener noreferrer"&gt;Measuring AI Ability to Complete Long Tasks&lt;/a&gt;, estimated that frontier models had reached a 50% task-completion horizon of around &lt;strong&gt;50 minutes&lt;/strong&gt; on their task suite. METR also reported that this horizon had been doubling roughly every seven months since 2019.&lt;/p&gt;

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

&lt;p&gt;It means the systems are not just answering trivia. They are becoming capable of completing longer, messier, more realistic tasks.&lt;/p&gt;

&lt;p&gt;But it also shows the limitation.&lt;/p&gt;

&lt;p&gt;A 50-minute task horizon is not the same as a full workday. It is not a week-long project. It is not open-ended research. It is not reliable autonomous operation in the real world.&lt;/p&gt;

&lt;p&gt;METR’s later &lt;a href="https://metr.org/time-horizons/" rel="noopener noreferrer"&gt;time-horizon measurements&lt;/a&gt; continue tracking this trend, but the core conclusion remains: the trend is important, and the current level is still not AGI.&lt;/p&gt;

&lt;p&gt;This matches what many software engineers experience in practice. The models are extremely useful. They can write code, review code, explain systems, generate tests, help debug, and accelerate development. But they still need supervision. They still make confident mistakes. They still lose track of constraints. They still require someone with judgment to decide whether the answer is actually correct.&lt;/p&gt;

&lt;p&gt;That is not a small limitation.&lt;/p&gt;

&lt;p&gt;That is the boundary between assistance and autonomy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chain-of-thought is still not a solved window into reasoning
&lt;/h2&gt;

&lt;p&gt;The previous article mentioned research suggesting that implicit chain-of-thought may not always reflect genuine step-by-step reasoning.&lt;/p&gt;

&lt;p&gt;That concern has not gone away.&lt;/p&gt;

&lt;p&gt;If anything, it has become more important.&lt;/p&gt;

&lt;p&gt;As reasoning models become more capable, their intermediate reasoning becomes more valuable for debugging, safety, and evaluation. If a model explains its reasoning, we might be able to catch mistakes, deception, hidden assumptions, or unsafe intent.&lt;/p&gt;

&lt;p&gt;But that only works if the reasoning we see is faithful.&lt;/p&gt;

&lt;p&gt;The paper &lt;a href="https://arxiv.org/abs/2411.15862" rel="noopener noreferrer"&gt;LLMs Do Not Think Step-by-step In Implicit Reasoning&lt;/a&gt; argues that when models are prompted to use implicit reasoning, they often do not appear to internally compute intermediate steps in a robust way.&lt;/p&gt;

&lt;p&gt;Later safety work, such as &lt;a href="https://arxiv.org/abs/2507.11473" rel="noopener noreferrer"&gt;A New and Fragile Opportunity for AI Safety&lt;/a&gt;, frames chain-of-thought as a useful monitoring surface, but also a fragile one.&lt;/p&gt;

&lt;p&gt;That creates a strange situation.&lt;/p&gt;

&lt;p&gt;The more powerful reasoning models become, the more we want to inspect their reasoning.&lt;/p&gt;

&lt;p&gt;But the more strategically capable they become, the less we can naively assume their visible reasoning is complete, faithful, or safe.&lt;/p&gt;

&lt;p&gt;This does not mean chain-of-thought is useless.&lt;/p&gt;

&lt;p&gt;It means it should be treated as a tool, not as proof.&lt;/p&gt;

&lt;p&gt;A model writing a beautiful explanation is not the same as a model having robust, grounded, human-like understanding.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what is missing?
&lt;/h2&gt;

&lt;p&gt;The missing piece is not raw capability.&lt;/p&gt;

&lt;p&gt;Raw capability is clearly improving.&lt;/p&gt;

&lt;p&gt;The missing piece is &lt;strong&gt;robust generality&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Humans are not impressive because we can memorize internet-scale text. Humans are impressive because we can enter new environments, infer goals, test ideas, learn from sparse examples, adapt under uncertainty, and transfer knowledge across domains.&lt;/p&gt;

&lt;p&gt;That is the kind of ability AGI is supposed to capture.&lt;/p&gt;

&lt;p&gt;Today’s frontier models are broad, but brittle.&lt;/p&gt;

&lt;p&gt;They can be superhuman on some tasks and surprisingly weak on others. They can solve difficult coding problems but fail simple novel puzzles. They can reason through expert-level questions and still hallucinate. They can use tools but also misuse them. They can follow instructions but still lose track of the real goal.&lt;/p&gt;

&lt;p&gt;This unevenness is important.&lt;/p&gt;

&lt;p&gt;A system that is excellent across many benchmarks is not automatically generally intelligent. It may simply be very powerful across many benchmark-like distributions.&lt;/p&gt;

&lt;p&gt;AGI requires more than breadth.&lt;/p&gt;

&lt;p&gt;It requires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;transfer&lt;/li&gt;
&lt;li&gt;reliability&lt;/li&gt;
&lt;li&gt;adaptation&lt;/li&gt;
&lt;li&gt;grounded planning&lt;/li&gt;
&lt;li&gt;calibration&lt;/li&gt;
&lt;li&gt;robustness under unfamiliar conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is where the strongest evidence still says: not yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this still is not AGI
&lt;/h2&gt;

&lt;p&gt;The cleanest reason is that &lt;strong&gt;novelty remains hard&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;ARC-AGI-2 was built specifically to preserve human accessibility while increasing compositional difficulty, contextual rule application, and in-context symbol definition. The benchmark authors report that scores below 5% are generally not considered meaningful. Leading systems remained below that threshold.&lt;/p&gt;

&lt;p&gt;ARC-AGI-3 raises the bar again in interactive environments, and its paper reports frontier systems below 1% as of March 2026.&lt;/p&gt;

&lt;p&gt;If one’s AGI criterion includes fluid intelligence and open-ended adaptation, those numbers matter more than a high score on a saturated benchmark.&lt;/p&gt;

&lt;p&gt;The second reason is that benchmark saturation and benchmark quality problems make many impressive scores less informative than they first appear. Stanford’s 2025 AI Index explicitly says traditional benchmarks are saturating. Separate work on MMLU found errors that can mislead evaluation and model comparison.&lt;/p&gt;

&lt;p&gt;The third reason is that long-horizon reliability is still limited. METR’s time-horizon framing is helpful because it shows real progress, but also shows that current systems are not yet reliable for long, messy, open-ended work.&lt;/p&gt;

&lt;p&gt;The fourth reason is that reasoning transparency remains unsettled. Reasoning models are impressive, but their internal cognition is not understood well enough to use as evidence of full AGI.&lt;/p&gt;

&lt;h2&gt;
  
  
  The best current description: general-purpose, not generally intelligent
&lt;/h2&gt;

&lt;p&gt;Here is where I would place today’s frontier AI systems:&lt;/p&gt;

&lt;p&gt;They are not narrow AI in the old sense.&lt;/p&gt;

&lt;p&gt;They are also not AGI.&lt;/p&gt;

&lt;p&gt;They sit in a middle category that is becoming more important:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;general-purpose AI systems with emerging agentic capabilities.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;They can operate across domains. They can use tools. They can reason more deeply than previous models. They can handle text, images, audio, code, long documents, and structured tasks. They can assist professionals in meaningful ways.&lt;/p&gt;

&lt;p&gt;But they still do not have the kind of robust, open-ended, human-like adaptability that most serious definitions of AGI imply.&lt;/p&gt;

&lt;p&gt;This is why saying “AGI is here” feels premature.&lt;/p&gt;

&lt;p&gt;But saying “it is just autocomplete” is also outdated.&lt;/p&gt;

&lt;p&gt;The honest position is uncomfortable because it does not fit the usual internet debate.&lt;/p&gt;

&lt;p&gt;We are not at AGI.&lt;/p&gt;

&lt;p&gt;But we are much closer to something economically disruptive than many people expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bottom line
&lt;/h2&gt;

&lt;p&gt;In the previous article, I treated o3’s ARC result as a milestone, not a destination.&lt;/p&gt;

&lt;p&gt;That conclusion has aged well.&lt;/p&gt;

&lt;p&gt;The milestone was real. The hype was excessive. The research since then has clarified the picture.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ARC-AGI-1 showed that frontier systems could make surprising jumps.&lt;/li&gt;
&lt;li&gt;ARC-AGI-2 and ARC-AGI-3 showed that novelty, interaction, and compositional generalization are still hard.&lt;/li&gt;
&lt;li&gt;METR’s work showed that long-horizon task completion is improving quickly, but also that current systems are still far from reliable long-term autonomy.&lt;/li&gt;
&lt;li&gt;New reasoning models showed that inference-time computation and tool use matter a lot.&lt;/li&gt;
&lt;li&gt;Safety research showed that more capable systems also require more serious evaluation.&lt;/li&gt;
&lt;li&gt;Benchmark research showed that our measurement tools are struggling to keep up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, are we there yet?&lt;/p&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%2Fnses2rwrziuv4efkwatu.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%2Fnses2rwrziuv4efkwatu.png" alt=" " width="498" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But the road changed.&lt;/p&gt;

&lt;p&gt;The question is no longer whether AI can be useful across many domains. That has already been answered.&lt;/p&gt;

&lt;p&gt;The question is whether these systems can become robustly adaptive, reliable, and autonomous outside the distributions where we train, scaffold, and evaluate them.&lt;/p&gt;

&lt;p&gt;That is the real AGI question now.&lt;/p&gt;

&lt;p&gt;And today, the factual answer is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We are not at AGI yet. We are at increasingly general-purpose reasoning systems that can look shockingly intelligent in many contexts, while still failing in ways that reveal they are not generally intelligent in the human sense.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That may be less dramatic than “AGI is here.”&lt;/p&gt;

&lt;p&gt;But it is much more useful.&lt;/p&gt;

&lt;p&gt;And honestly, much more interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;p&gt;Primary sources and technical reports used for this follow-up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/ernestohs/agi-are-we-there-yet-n5p"&gt;AGI, Are We There Yet?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arcprize.org/blog/oai-o3-pub-breakthrough" rel="noopener noreferrer"&gt;OpenAI o3 Breakthrough High Score on ARC-AGI-Pub, ARC Prize&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2505.11831v1" rel="noopener noreferrer"&gt;ARC-AGI-2: A New Challenge for Frontier AI Reasoning Systems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2603.24621v1" rel="noopener noreferrer"&gt;ARC-AGI-3: A New Challenge for Frontier Agentic Intelligence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/1911.01547" rel="noopener noreferrer"&gt;On the Measure of Intelligence, François Chollet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cdn.openai.com/papers/gpt-4.pdf" rel="noopener noreferrer"&gt;GPT-4 Technical Report&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openai.com/index/learning-to-reason-with-llms/" rel="noopener noreferrer"&gt;Learning to Reason with LLMs, OpenAI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openai.com/index/introducing-o3-and-o4-mini/" rel="noopener noreferrer"&gt;Introducing OpenAI o3 and o4-mini&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openai.com/index/o3-o4-mini-system-card/" rel="noopener noreferrer"&gt;OpenAI o3 and o4-mini System Card&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openai.com/index/gpt-4o-system-card/" rel="noopener noreferrer"&gt;GPT-4o System Card&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ar5iv.labs.arxiv.org/html/2407.21783" rel="noopener noreferrer"&gt;The Llama 3 Herd of Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mistral.ai/news/mistral-large-2407/" rel="noopener noreferrer"&gt;Mistral Large 2, Mistral AI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://storage.googleapis.com/deepmind-media/gemini/gemini_v2_5_report.pdf" rel="noopener noreferrer"&gt;Gemini 2.5 Technical Report&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anthropic.com/news/claude-4" rel="noopener noreferrer"&gt;Claude 4, Anthropic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anthropic.com/claude-4-system-card" rel="noopener noreferrer"&gt;Claude 4 System Card&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hai.stanford.edu/ai-index/2025-ai-index-report/technical-performance" rel="noopener noreferrer"&gt;Stanford AI Index 2025, Technical Performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2503.14499" rel="noopener noreferrer"&gt;Measuring AI Ability to Complete Long Tasks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://metr.org/time-horizons/" rel="noopener noreferrer"&gt;Task-Completion Time Horizons of Frontier AI Models, METR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2501.14249" rel="noopener noreferrer"&gt;Humanity’s Last Exam&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2406.04127" rel="noopener noreferrer"&gt;Are We Done with MMLU?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2411.15862" rel="noopener noreferrer"&gt;LLMs Do Not Think Step-by-step In Implicit Reasoning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2507.11473" rel="noopener noreferrer"&gt;A New and Fragile Opportunity for AI Safety&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2403.13793" rel="noopener noreferrer"&gt;Evaluating Frontier Models for Dangerous Capabilities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2412.04984" rel="noopener noreferrer"&gt;Frontier Models are Capable of In-context Scheming&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>openai</category>
      <category>writing</category>
    </item>
    <item>
      <title>How to Reduce Codex Token Spend Without Reducing Code Quality</title>
      <dc:creator>Ernesto Herrera Salinas</dc:creator>
      <pubDate>Tue, 23 Jun 2026 22:46:00 +0000</pubDate>
      <link>https://dev.to/ernestohs/how-to-reduce-codex-token-spend-without-reducing-code-quality-1bpp</link>
      <guid>https://dev.to/ernestohs/how-to-reduce-codex-token-spend-without-reducing-code-quality-1bpp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Scope: Verified against Codex documentation on June 22, 2026.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The safe way to reduce Codex token spend is to optimize only while fixed quality gates remain unchanged. “Without reducing quality” should not mean trusting that a shorter transcript looks equally good. It means defining requirements, tests, static checks, and review criteria before the run, then rejecting any cheaper setup that performs worse against those gates.&lt;/p&gt;

&lt;p&gt;This principle applies across the Codex CLI, IDE extension, app, and cloud, but the budget appears differently on each surface. ChatGPT users generally consume included usage, rate limits, or credits rather than receiving a direct token invoice. API-key users pay standard, model-specific API rates. Context usage affects how much information fits in a thread, while latency is simply elapsed time. These are related operational constraints, not interchangeable measurements. See the official &lt;a href="https://developers.openai.com/codex/pricing" rel="noopener noreferrer"&gt;Codex pricing&lt;/a&gt;, &lt;a href="https://developers.openai.com/codex/auth" rel="noopener noreferrer"&gt;authentication&lt;/a&gt;, and &lt;a href="https://openai.com/api/pricing/" rel="noopener noreferrer"&gt;API pricing&lt;/a&gt; documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Define and measure the budget
&lt;/h2&gt;

&lt;p&gt;A Codex thread contains more than the prompt and final answer. Codex gathers file contents, tool output, model responses, and the ongoing work record; all of it must fit in the model’s context window. Long logs and broad file reads can therefore consume context even when the final response is short. Codex may compact long threads automatically, but compaction summarizes and discards detail rather than making context free (&lt;a href="https://developers.openai.com/codex/prompting" rel="noopener noreferrer"&gt;Prompting Codex&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Measure four separate outcomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Context:&lt;/strong&gt; input tokens, cached input tokens, and remaining context capacity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generated tokens:&lt;/strong&gt; output tokens and reasoning-output tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Account cost:&lt;/strong&gt; API charges, ChatGPT credits, or rate-limit consumption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operational efficiency:&lt;/strong&gt; elapsed time, turns, failed verification, and corrective attempts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a reproducible comparison, use this proposed method rather than relying on anecdotes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose five representative tasks. Give each task a saved prompt, a fixed starting commit, an exact verification command, and a written review checklist.&lt;/li&gt;
&lt;li&gt;Create a baseline profile and one candidate profile. Change one variable at a time. If testing context discipline, keep the model and reasoning effort fixed; test model changes separately.&lt;/li&gt;
&lt;li&gt;Run each task three times per profile from a clean copy of the same commit. Use a new noninteractive thread for every initial run.&lt;/li&gt;
&lt;li&gt;Capture the event stream:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   codex &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--profile&lt;/span&gt; baseline &lt;span class="nt"&gt;--json&lt;/span&gt; - &lt;span class="se"&gt;\&lt;/span&gt;
     &amp;lt; prompts/task-01.txt &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; results/task-01-baseline-1.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Immediately filter the completion event instead of printing the full machine-readable stream into another model context:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   jq &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'select(.type == "turn.completed") | .usage'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     results/task-01-baseline-1.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run the predefined verification command outside Codex. Record pass or fail. If it fails, take the exact session ID from the &lt;code&gt;thread.started&lt;/code&gt; event, resume that thread with the verification log and the fixed instruction, “Make the smallest correction required to pass the stated gate,” and save each corrective turn to another JSONL file. Stop after three corrective attempts and record failure if the gate still does not pass.&lt;/li&gt;
&lt;li&gt;Store one row per task and repetition with: profile, input tokens, cached input tokens, output tokens, reasoning-output tokens, completed turns across all JSONL files, verification result, and corrective-attempt count. Compare medians only after confirming that requirement, test, and review outcomes are equivalent.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;codex exec --json&lt;/code&gt; emits JSONL events, and its &lt;code&gt;turn.completed&lt;/code&gt; usage object reports &lt;code&gt;input_tokens&lt;/code&gt;, &lt;code&gt;cached_input_tokens&lt;/code&gt;, &lt;code&gt;output_tokens&lt;/code&gt;, and &lt;code&gt;reasoning_output_tokens&lt;/code&gt; (&lt;a href="https://developers.openai.com/codex/noninteractive" rel="noopener noreferrer"&gt;Non-interactive mode&lt;/a&gt;). This article does not claim benchmark results; the procedure is a way to produce evidence for your own workload.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Establish quality gates first
&lt;/h2&gt;

&lt;p&gt;Token reduction often fails because the task was underspecified. A five-word prompt can trigger exploration, assumptions, rework, and repeated checks. OpenAI recommends giving Codex a goal, relevant context, constraints, and a definition of done, and recommends including reproducible validation steps (&lt;a href="https://developers.openai.com/codex/learn/best-practices" rel="noopener noreferrer"&gt;Codex best practices&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Use a prompt shape 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;Goal: Fix duplicate invoice creation in the retry path.
Context: Start with src/billing/retry.ts and tests/billing/retry.test.ts.
Constraints: Preserve the public API and database schema. Do not refactor
unrelated billing code.
Done when: The regression test and billing unit suite pass, and the final
diff contains no unrelated changes.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For higher-risk work, add type checks, linting, security checks, performance thresholds, or a human review rubric. Keep these gates identical across the baseline and candidate runs. A configuration that uses fewer tokens but needs more corrective turns, misses requirements, or produces a riskier diff is not an improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Reduce irrelevant context and tool output
&lt;/h2&gt;

&lt;p&gt;Point Codex toward likely files and explicitly exclude generated code, dependencies, build artifacts, coverage output, and unrelated services. Prefer targeted search and line-range reads over printing whole trees or large files. Run the smallest relevant test first, then expand only when the risk or failure requires it.&lt;/p&gt;

&lt;p&gt;Filter command output before it enters the thread:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rg "InvoiceRetry" src tests
git status --short
git diff --stat
npm test -- retry.test.ts --runInBand
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Machine-readable output is useful only when it is immediately filtered to the fields needed for the decision. Raw JSONL, verbose test reporters, and full CI logs can be larger than concise human-readable output. Preserve the failing assertion, stack trace, and summary; omit repeated successes and unrelated diagnostics. Codex also has a &lt;code&gt;tool_output_token_limit&lt;/code&gt; setting, but a hard cap is a backstop because truncation can hide the actual error (&lt;a href="https://developers.openai.com/codex/config-reference" rel="noopener noreferrer"&gt;Configuration reference&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;AGENTS.md&lt;/code&gt; for durable routing and verification commands, but understand discovery correctly. Codex loads one global instruction file, then walks from the project root down to the directory where the run started, loading at most one instruction file per directory. It does not universally load a nested &lt;code&gt;AGENTS.md&lt;/code&gt; merely because it later edits a file beneath that directory. Start Codex in the relevant subtree when those nested instructions must apply, and keep instruction files concise because they enter context at startup (&lt;a href="https://developers.openai.com/codex/guides/agents-md" rel="noopener noreferrer"&gt;AGENTS.md guide&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The self-published &lt;a href="https://github.com/juliusbrussee/caveman" rel="noopener noreferrer"&gt;Caveman&lt;/a&gt; project is a Claude API output-style benchmark, not evidence about Codex, reasoning tokens, or total task cost. Its useful lesson is limited: removing filler can reduce visible output, but terse prose does not compensate for irrelevant reads, noisy tools, or retries.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Match model and reasoning effort to the task
&lt;/h2&gt;

&lt;p&gt;Use the least expensive setup that still passes the fixed gates. OpenAI currently recommends &lt;code&gt;gpt-5.5&lt;/code&gt; for demanding Codex work and &lt;code&gt;gpt-5.4-mini&lt;/code&gt; as a faster, lower-cost option for lighter coding tasks. Reasoning effort can be low for well-scoped mechanical changes and medium or high for complex debugging; higher effort uses more tokens and can consume limits faster (&lt;a href="https://developers.openai.com/codex/models" rel="noopener noreferrer"&gt;Codex models&lt;/a&gt; and &lt;a href="https://developers.openai.com/codex/ide/features" rel="noopener noreferrer"&gt;IDE features&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Do not reduce model capability, reasoning effort, and context simultaneously in the first experiment. If the candidate fails, you will not know which change caused it. Escalate deliberately when ambiguity, concurrency, security, or repeated failed verification demonstrates the need.&lt;/p&gt;

&lt;p&gt;Fast mode is a latency control, not a savings control. With ChatGPT sign-in it makes supported models faster while consuming credits at a higher rate; API-key users instead remain on standard API pricing. Use &lt;code&gt;/fast off&lt;/code&gt; when the objective is credit efficiency rather than response speed (&lt;a href="https://developers.openai.com/codex/speed" rel="noopener noreferrer"&gt;Codex speed&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Cloud tasks currently do not expose local model selection, so optimize them through task scope, repository instructions, environment setup, and verification rather than a local profile (&lt;a href="https://developers.openai.com/codex/models#choosing-your-model-for-cloud-tasks" rel="noopener noreferrer"&gt;Codex models&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Manage threads, compaction, and subagents
&lt;/h2&gt;

&lt;p&gt;Keep one thread aligned to one objective. In the CLI, &lt;code&gt;/status&lt;/code&gt; reports session configuration, token usage, and remaining context capacity. &lt;code&gt;/compact&lt;/code&gt; summarizes the conversation to free context, while &lt;code&gt;/new&lt;/code&gt; or &lt;code&gt;/clear&lt;/code&gt; starts a fresh conversation when prior investigation is no longer relevant. &lt;code&gt;/usage&lt;/code&gt; is account-level ChatGPT activity or rate-limit monitoring; it is not a per-run benchmark. These controls and their current meanings are documented in the &lt;a href="https://developers.openai.com/codex/cli/slash-commands" rel="noopener noreferrer"&gt;CLI slash-command reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Compact at a phase boundary, such as after diagnosis or implementation, rather than repeatedly. Start a new thread when a task changes materially. Resume only when previous decisions and repository state are still useful.&lt;/p&gt;

&lt;p&gt;Subagents can keep noisy exploration out of the main thread and reduce elapsed time for independent work, but they do not reduce total token consumption. Each subagent performs its own model and tool work, so comparable multi-agent runs consume more tokens. Reserve them for parallel research, test analysis, or independent review dimensions where isolation or speed justifies the extra cost (&lt;a href="https://developers.openai.com/codex/concepts/subagents" rel="noopener noreferrer"&gt;Subagent concepts&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Apply a concise reusable configuration
&lt;/h2&gt;

&lt;p&gt;The CLI supports named profiles stored as separate files under &lt;code&gt;CODEX_HOME&lt;/code&gt;, which defaults to &lt;code&gt;~/.codex&lt;/code&gt;. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# ~/.codex/economy.config.toml&lt;/span&gt;
&lt;span class="py"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"gpt-5.4-mini"&lt;/span&gt;
&lt;span class="py"&gt;model_reasoning_effort&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"low"&lt;/span&gt;
&lt;span class="py"&gt;model_verbosity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"low"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it with &lt;code&gt;codex --profile economy&lt;/code&gt; or &lt;code&gt;codex exec --profile economy "task"&lt;/code&gt;. Profile files use top-level keys; current Codex no longer reads legacy &lt;code&gt;[profiles.name]&lt;/code&gt; tables from &lt;code&gt;config.toml&lt;/code&gt; (&lt;a href="https://developers.openai.com/codex/config-advanced#profiles" rel="noopener noreferrer"&gt;Advanced configuration&lt;/a&gt;). &lt;code&gt;model_verbosity&lt;/code&gt; applies to Responses API providers (&lt;a href="https://developers.openai.com/codex/config-advanced#model-reasoning-verbosity-and-limits" rel="noopener noreferrer"&gt;Advanced configuration&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The CLI, IDE extension, and app share configuration layers (&lt;a href="https://developers.openai.com/codex/learn/best-practices#configure-codex-for-consistency" rel="noopener noreferrer"&gt;Codex best practices&lt;/a&gt;). For this workflow, the CLI provides named profiles, its slash-command interface, and &lt;code&gt;codex exec --json&lt;/code&gt; usage events (&lt;a href="https://developers.openai.com/codex/config-advanced#profiles" rel="noopener noreferrer"&gt;profiles&lt;/a&gt;, &lt;a href="https://developers.openai.com/codex/cli/slash-commands" rel="noopener noreferrer"&gt;slash commands&lt;/a&gt;, and &lt;a href="https://developers.openai.com/codex/noninteractive" rel="noopener noreferrer"&gt;noninteractive mode&lt;/a&gt;). Keep project-specific paths and checks in the repository’s &lt;code&gt;AGENTS.md&lt;/code&gt;, and use the profile only where its model choice passes your gates.&lt;/p&gt;

&lt;p&gt;Every concise final report should still preserve four review outputs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;changed behavior;&lt;/li&gt;
&lt;li&gt;checks run;&lt;/li&gt;
&lt;li&gt;results;&lt;/li&gt;
&lt;li&gt;unresolved risks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the quality boundary: spend fewer tokens only when those outputs and the underlying verification outcomes remain intact.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>chatgpt</category>
      <category>productivity</category>
      <category>promptengineering</category>
    </item>
    <item>
      <title>Dev Log: Shipping the Foundation</title>
      <dc:creator>Ernesto Herrera Salinas</dc:creator>
      <pubDate>Tue, 23 Jun 2026 03:07:00 +0000</pubDate>
      <link>https://dev.to/ernestohs/dev-log-shipping-the-foundation-4nhj</link>
      <guid>https://dev.to/ernestohs/dev-log-shipping-the-foundation-4nhj</guid>
      <description>&lt;p&gt;M8 is the last milestone, and it has the texture of every "last 10%" you've ever done: not one big feature, but a dozen smaller things that together turn "it works" into "it's done." Explain the zero-config path, an allocation budget, benchmarks, public documentation, and final goldens. Closing-time work. I like closing-time work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the magic inspectable
&lt;/h2&gt;

&lt;p&gt;The feature I cared most about here is &lt;code&gt;Explain()&lt;/code&gt;. Munchausen &lt;em&gt;infers&lt;/em&gt; a lot; it quietly decides your &lt;code&gt;Make&lt;/code&gt; is a car make and your &lt;code&gt;Email&lt;/code&gt; is an email, and any inferred behavior you can't inspect is just spooky action. So &lt;code&gt;Explain()&lt;/code&gt; walks the compiled plan and tells you, per member, exactly what it decided and why:&lt;br&gt;
the source, the generator, the confidence, and what rules got overridden. It generates nothing; it just reads the plan. &lt;code&gt;Car.Make -&amp;gt; Vehicle.Make [property name + model] High&lt;/code&gt;. No more guessing why a value looks the way it does.&lt;/p&gt;

&lt;p&gt;A nice cleanup came with it: two enums I'd kept &lt;em&gt;internal&lt;/em&gt; since M4 to avoid committing them publicly before &lt;code&gt;Explain()&lt;/code&gt; needed them finally became public.&lt;br&gt;
The promotion was almost free thanks to a C# namespace-resolution quirk: moving the enums to the root namespace meant that every internal reference compiled, since nested namespaces see their parent namespace. Small, tidy, satisfying.&lt;/p&gt;

&lt;h2&gt;
  
  
  The allocation test that made me earn it
&lt;/h2&gt;

&lt;p&gt;One of my performance goals was "no reflection per object," but implementation inspection did not feel like enough proof. So I wrote an allocation test: generate 50,000 objects, measure the bytes allocated, and divide. The accessors were already&lt;br&gt;
compiled (M2), but construction still used reflection's &lt;code&gt;ConstructorInfo.Invoke&lt;/code&gt;.&lt;br&gt;
I compiled the constructor into a delegate too, an &lt;code&gt;Expression&lt;/code&gt; that creates the object from a boxed args array.&lt;/p&gt;

&lt;p&gt;First run of the test: &lt;strong&gt;408 bytes per object.&lt;/strong&gt; My threshold was 400. Off by a whisker. I stared at it, half-expecting a hidden reflective allocation, then realized: that's just &lt;em&gt;boxing&lt;/em&gt;. The model has five value-type members, and every value source returns a boxed &lt;code&gt;object&lt;/code&gt;. 408 bytes is five boxes plus the object plus&lt;br&gt;
a list slot, entirely accounted for, zero reflection. I shaved the empty-args array allocation, nudged the threshold to a value that comfortably separates "boxing" from "reflection would be here," and documented the reasoning right in the test.&lt;br&gt;
A good reminder that an allocation number you can fully explain is worth more than a green checkmark you can't.&lt;/p&gt;

&lt;h2&gt;
  
  
  A dumb little collision
&lt;/h2&gt;

&lt;p&gt;One of those five-minute facepalms: &lt;code&gt;LieDefinition&amp;lt;T&amp;gt;.Explain()&lt;/code&gt; is a method, and &lt;code&gt;Munchausen.Explain&lt;/code&gt; is a namespace. So when I wrote &lt;code&gt;Explain.InferenceReportBuilder&lt;/code&gt; inside the method, the compiler thought I meant the method and gave me a baffling &lt;code&gt;CS0119&lt;/code&gt;. Fully-qualify it (&lt;code&gt;Munchausen.Explain.InferenceReportBuilder&lt;/code&gt;), and it's&lt;br&gt;
fine. The kind of error that's obvious the instant you see it and inscrutable for the thirty seconds before.&lt;/p&gt;

&lt;h2&gt;
  
  
  The last golden
&lt;/h2&gt;

&lt;p&gt;For the final golden, I generated the canonical &lt;code&gt;Car&lt;/code&gt; through the zero-config &lt;code&gt;Lie&amp;lt;Car&amp;gt;&lt;/code&gt; path, but pinned &lt;em&gt;both&lt;/em&gt; the seed and the reference time, because &lt;code&gt;Vehicle.Year&lt;/code&gt; depends on "current year" and I didn't want a golden that breaks every January 1st. Out came a deterministic Mazda Sorento, model year 2020, $788.99, owned&lt;br&gt;
by Linda King. That one fixture now locks the entire pipeline end to end: inference, datasets, traversal, the lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Done
&lt;/h2&gt;

&lt;p&gt;And that's v1.0. Nine milestones, from an empty scaffold to a library that takes your type and hands you believable data, with a locked public surface, a deterministic core validated against published vectors, an inference engine you can interrogate, and&lt;br&gt;
goldens that pin it all in place. Two hundred-odd tests, green, zero warnings.&lt;/p&gt;

&lt;p&gt;The thing I'll remember about this build is how often implementation improved the design. Working one milestone at a time gave each idea room to fail clearly: the canary tested the public boundary, reference vectors tested determinism, and the inference contradiction forced me to articulate what good fake data should feel like. Treating seeded output and public API changes as deliberate decisions made the final milestone calm instead of a panic. Nothing important remained, only an assumption.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Not M9; there isn't one. v1.1 needs a new design pass: inference providers, attributes, hooks, validation, uniqueness, locales, child definitions. The seams are already sitting in the code, empty and waiting. But that's a new plan for another day.&lt;/p&gt;

&lt;p&gt;For now: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/ernestohs/Munchausen/releases/" rel="noopener noreferrer"&gt;v1.0 Foundation, shipped&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nuget.org/packages/Munchausen" rel="noopener noreferrer"&gt;Nuget Package&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>nuget</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Engineering Post: Making inference inspectable, generating cheaply, and the surface final</title>
      <dc:creator>Ernesto Herrera Salinas</dc:creator>
      <pubDate>Tue, 23 Jun 2026 03:00:00 +0000</pubDate>
      <link>https://dev.to/ernestohs/engineering-post-making-inference-inspectable-generation-cheap-and-the-surface-final-59ip</link>
      <guid>https://dev.to/ernestohs/engineering-post-making-inference-inspectable-generation-cheap-and-the-surface-final-59ip</guid>
      <description>&lt;p&gt;M8 is the finale: the &lt;code&gt;Explain()&lt;/code&gt; report family, the cached &lt;code&gt;Lie&amp;lt;T&amp;gt;&lt;/code&gt; automatic path, reflection-free construction, the benchmark suite, and the final goldens.&lt;br&gt;
It tests whether the ideas developed independently across eight milestones hold together as one library.&lt;/p&gt;
&lt;h2&gt;
  
  
  Explain: a pure walk of the plan
&lt;/h2&gt;

&lt;p&gt;I did not want inferred behavior to remain opaque, so &lt;code&gt;Explain()&lt;/code&gt; materializes an &lt;code&gt;InferenceReport&lt;/code&gt; by walking the frozen plan, generating nothing. Each member maps to a &lt;code&gt;MemberInferenceReport&lt;/code&gt; (source, generator, confidence, derivation order, overridden rules); nested members appear as a single entry, so a recursive&lt;br&gt;
&lt;code&gt;Employee.Manager&lt;/code&gt; is one line, not infinite expansion. &lt;code&gt;ToText()&lt;/code&gt; renders a human form whose exact prose is explicitly &lt;em&gt;not&lt;/em&gt; contractual, the tests assert structure, not wording.&lt;/p&gt;

&lt;p&gt;This is also where &lt;code&gt;InferenceConfidence&lt;/code&gt; and &lt;code&gt;InferenceSource&lt;/code&gt; graduate from the internal mirrors of M4 to public enums in the root namespace. Because a &lt;code&gt;Munchausen.Inference&lt;/code&gt; file resolves an unqualified &lt;code&gt;InferenceConfidence&lt;/code&gt; against the enclosing &lt;code&gt;Munchausen&lt;/code&gt; namespace, the promotion is almost free, move the enums up, delete the internal copies, and every internal reference still compiles.&lt;/p&gt;

&lt;p&gt;A subtle fix rode along: nested/collection members now report &lt;code&gt;ChildDefinition&lt;/code&gt; as their source (they reported &lt;code&gt;Type&lt;/code&gt; before), so the report reads correctly, &lt;code&gt;Car.Owner -&amp;gt; (nested object)&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  The automatic path
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Lie&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Lazy&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GenerationPlan&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;CachedPlan&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;DefinitionCompiler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CompileAutomatic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
            &lt;span class="n"&gt;LazyThreadSafetyMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecutionAndPublication&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A generic static gives a free, thread-safe, per-closed-type cache;&lt;br&gt;
&lt;code&gt;CompileAutomatic&lt;/code&gt; sits over a process-wide plan cache; and &lt;code&gt;Lazy&lt;/code&gt; caches a&lt;br&gt;
&lt;em&gt;compilation failure&lt;/em&gt; too, so a bad type fails consistently instead of racily. The&lt;br&gt;
acceptance test proves the automatic path equals an inferred-only definition for&lt;br&gt;
the same seed, &lt;code&gt;Lie&amp;lt;Car&amp;gt;.Generate&lt;/code&gt; and &lt;code&gt;Lie.Define&amp;lt;Car&amp;gt;().Build().Generate&lt;/code&gt; agree&lt;br&gt;
byte for byte.&lt;/p&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.amazonaws.com%2Fuploads%2Farticles%2Fw3az4fp5gycxk3jyhspy.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.amazonaws.com%2Fuploads%2Farticles%2Fw3az4fp5gycxk3jyhspy.png" alt=" " width="799" height="288"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Zero per-object reflection
&lt;/h2&gt;

&lt;p&gt;One of my performance goals was no reflection at generation time. Rather than trusting inspection alone, I verified it with an allocation test. The last reflective holdout was construction: M5/M6 used &lt;code&gt;ConstructorInfo.Invoke&lt;/code&gt;. M8 compiles the constructor to a delegate at build time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// arguments =&amp;gt; (object)new Ctor((T0)arguments[0], (T1)arguments[1], ...)&lt;/span&gt;
&lt;span class="n"&gt;Expression&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lambda&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;?[],&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Compile&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combined with the M2 compiled accessors and &lt;code&gt;Array.Empty&lt;/code&gt; for parameterless ctors, steady-state generation touches no reflection. The allocation test generates 50,000 objects and asserts per-object allocation stays under a small bound, boxing of value-type members is accepted in v1.0, but per-object &lt;code&gt;Invoke&lt;/code&gt;/&lt;code&gt;GetValue&lt;/code&gt; would&lt;br&gt;
blow past it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardening
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benchmarks:&lt;/strong&gt; a BenchmarkDotNet suite covering warm &lt;code&gt;Build&lt;/code&gt;, per-object and batch generation, a collection model, and PRNG throughput, tracked for trend, not gated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; every public member is documented (&lt;code&gt;CS1591&lt;/code&gt; is an error, so a clean build &lt;em&gt;is&lt;/em&gt; the proof). &lt;code&gt;Ignore&lt;/code&gt;/&lt;code&gt;Preserve&lt;/code&gt; docs open by contrasting each other; builder methods name the LIE codes they can cause.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Surface:&lt;/strong&gt; &lt;code&gt;PublicAPI.Shipped.txt&lt;/code&gt; records the final v1.0 API and the analyzer rejects accidental changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Goldens:&lt;/strong&gt; a final &lt;code&gt;Lie&amp;lt;Car&amp;gt;&lt;/code&gt; golden with a fixed seed &lt;em&gt;and&lt;/em&gt; reference time (so &lt;code&gt;Vehicle.Year&lt;/code&gt; is deterministic) pins the whole inference + dataset + traversal pipeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next: &lt;strong&gt;v1.0 is done&lt;/strong&gt;🎉; v1.1 is a new conversation
&lt;/h2&gt;

&lt;p&gt;That's the v1.0 Foundation, complete: M0 scaffold through M8 hardening. The seams for v1.1 already exist and sit empty by design: provider-stage slots in the pipeline, hook/validator/uniqueness arrays on each &lt;code&gt;TypePlan&lt;/code&gt;, the reachable-plan dictionary that child definitions (&lt;code&gt;Use&lt;/code&gt;) can substitute into, and a &lt;code&gt;SequenceTable&lt;/code&gt; field reserved for the operation. Inference providers, DataAnnotations attributes, hooks, validation, uniqueness, locale packs, and child definitions deserve a new design pass rather than being squeezed into the finished plan.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>nuget</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
