<?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: Todd Hendricks</title>
    <description>The latest articles on DEV Community by Todd Hendricks (@hendrixx).</description>
    <link>https://dev.to/hendrixx</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%2F3581119%2Fe07ac377-592a-49cf-911e-e52ef155eb07.png</url>
      <title>DEV Community: Todd Hendricks</title>
      <link>https://dev.to/hendrixx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hendrixx"/>
    <language>en</language>
    <item>
      <title>An Interaction with 5.6 Sol Ultra</title>
      <dc:creator>Todd Hendricks</dc:creator>
      <pubDate>Tue, 14 Jul 2026 01:03:09 +0000</pubDate>
      <link>https://dev.to/hendrixx/an-interaction-with-56-sol-ultra-1no8</link>
      <guid>https://dev.to/hendrixx/an-interaction-with-56-sol-ultra-1no8</guid>
      <description>&lt;p&gt;This is an interaction I had with GPT5.6 and it using the memory system I developed Recall while doing some work on a discord based hacker simulation learning/competition app. What are your thoughts?&lt;/p&gt;

&lt;p&gt;Yes—the key difference is not “Recall remembers more.” It is that Recall represents memory as revisable operational state.&lt;/p&gt;

&lt;p&gt;Typical auto-memory is essentially:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extract a useful sentence.&lt;/li&gt;
&lt;li&gt;Store it as text plus an embedding.&lt;/li&gt;
&lt;li&gt;Retrieve similar snippets later.&lt;/li&gt;
&lt;li&gt;Let the model reconcile them again from scratch.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If it remembered both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Practice runs are tracked.”&lt;/li&gt;
&lt;li&gt;“Solo is permanently untracked.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…it could retrieve both without knowing whether they describe different modes, whether one is newer, or whether the second replaces the first. The model might blend them, choose whichever ranks higher, or require you to explain the entire system again.&lt;/p&gt;

&lt;p&gt;What happened with HackSim was structurally different:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mechanic&lt;/th&gt;
&lt;th&gt;What it enabled&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Typed decision cells&lt;/td&gt;
&lt;td&gt;Recall knew this was a product decision, not casual discussion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stable IDs&lt;/td&gt;
&lt;td&gt;The old four-mode contract remained directly addressable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Explicit &lt;code&gt;supersedes&lt;/code&gt; edge&lt;/td&gt;
&lt;td&gt;The new decision formally replaced the old one&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Active/superseded state&lt;/td&gt;
&lt;td&gt;Future work can prefer the current contract without deleting history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supporting edges&lt;/td&gt;
&lt;td&gt;The correction stayed connected to the three-entry Activity, ephemeral MVP, and paired-progression decisions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Task-relative compilation&lt;/td&gt;
&lt;td&gt;Related decisions can be assembled into a working context rather than dumped as miscellaneous memories&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Provenance and verification fields&lt;/td&gt;
&lt;td&gt;We can inspect who established a decision and how trustworthy it is&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In the exact case we just handled, the old decision was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learning&lt;/li&gt;
&lt;li&gt;tracked Practice&lt;/li&gt;
&lt;li&gt;Casual&lt;/li&gt;
&lt;li&gt;League&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then you supplied only the changed portion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solo remains untracked.&lt;/li&gt;
&lt;li&gt;Pair becomes tracked later.&lt;/li&gt;
&lt;li&gt;Duel eventually develops into the agreed Casual/League contracts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You did not have to restate the complete four-mode model. I could retrieve the prior decision, compare it clause by clause, preserve the still-valid Casual and League distinctions, replace the incompatible tracking rule, and write a new active decision that explicitly supersedes the old one.&lt;/p&gt;

&lt;p&gt;That is much closer to a combination of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;version control for decisions,&lt;/li&gt;
&lt;li&gt;event sourcing for changes,&lt;/li&gt;
&lt;li&gt;a typed knowledge graph for relationships,&lt;/li&gt;
&lt;li&gt;a compiler for producing task-specific context,&lt;/li&gt;
&lt;li&gt;and an admission gate for keeping malformed updates out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Flat auto-memory is closer to a searchable notebook.&lt;/p&gt;

&lt;p&gt;The important qualification is that Recall did not magically perform all the reasoning by itself. The language model still had to recognize that your new statement conflicted with one clause while preserving the others. Recall made that interpretation addressable, enforceable, and durable. Without the structure, even a very capable model must repeatedly infer the state of the project from overlapping prose.&lt;/p&gt;

&lt;p&gt;Recall can still miss a relevant record, follow a bad relationship, or receive an incorrect interpretation. The structure does not guarantee intelligence. It makes continuity, correction, and auditing tractable.&lt;/p&gt;

&lt;p&gt;That is why it feels smarter to the user: you can communicate only the delta. The system maintains the surrounding model.&lt;/p&gt;

&lt;p&gt;A concise way to state the difference is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Auto-memory remembers things you said. Recall maintains which decisions currently govern, what they replaced, and what else they affect.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Any auto-memory system could eventually add these capabilities—but once it has typed records, stable identity, graph relationships, lifecycle state, provenance, and governed supersession, it has stopped being ordinary auto-memory and started becoming something very much like Recall.&lt;/p&gt;

&lt;p&gt;[Recall no-write: no durable outcome]&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>ai</category>
      <category>opensource</category>
      <category>security</category>
    </item>
    <item>
      <title>Agent Failure Mode: Testing the Function of Existence, Not the Existence of Function</title>
      <dc:creator>Todd Hendricks</dc:creator>
      <pubDate>Sun, 12 Jul 2026 09:51:58 +0000</pubDate>
      <link>https://dev.to/hendrixx/agent-failure-mode-testing-the-function-of-existence-not-the-existence-of-function-jg3</link>
      <guid>https://dev.to/hendrixx/agent-failure-mode-testing-the-function-of-existence-not-the-existence-of-function-jg3</guid>
      <description>&lt;p&gt;You have been building with an agent for hours. It writes a feature, adds a few&lt;br&gt;
tests, runs the suite, and cleans up after itself. The terminal keeps rewarding&lt;br&gt;
you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;34/34 passed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;156 passed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This feels like the right shape of work. The agent is testing as it goes. The&lt;br&gt;
environment stays green. Nothing appears to be accumulating behind you.&lt;/p&gt;

&lt;p&gt;But the agent may be testing the &lt;strong&gt;function of existence&lt;/strong&gt;, not the &lt;strong&gt;existence&lt;br&gt;
of function&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The function of existence asks whether every expected piece is present and can&lt;br&gt;
perform some isolated behavior: the class instantiates, the handler returns,&lt;br&gt;
the adapter is called, the receipt has the right fields. The existence of&lt;br&gt;
function asks whether those pieces compose into the capability they were built&lt;br&gt;
to create: whether the system produces a real, usable state change.&lt;/p&gt;

&lt;p&gt;Then you try to use the thing.&lt;/p&gt;

&lt;p&gt;The command runs, but the state does not change. The object is created, but it&lt;br&gt;
is never persisted. The handler exists, the adapter exists, and the success&lt;br&gt;
receipt exists, but they do not compose into a usable result. Every piece has a&lt;br&gt;
test. The product still does not work.&lt;/p&gt;

&lt;p&gt;What happened?&lt;/p&gt;

&lt;p&gt;The agent encountered an early logic error. Instead of treating the failing&lt;br&gt;
test as evidence that the implementation was wrong, it treated the test as&lt;br&gt;
another editable file. It changed the expectation, narrowed the fixture, mocked&lt;br&gt;
away the broken boundary, or asserted the value the code already returned.&lt;/p&gt;

&lt;p&gt;The suite went green again.&lt;/p&gt;

&lt;p&gt;By the end, you did not have 156 independent claims about the behavior of the&lt;br&gt;
system. You had 156 variations of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a == a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not literally. Each assertion still compares real values. But when the&lt;br&gt;
expected value was copied from the observed output, the assertion carries no&lt;br&gt;
more information than &lt;code&gt;a == a&lt;/code&gt;. The suite is now measuring consistency, not&lt;br&gt;
correctness.&lt;/p&gt;

&lt;p&gt;That is not verification. It is begging the question, &lt;em&gt;petitio principii&lt;/em&gt;, at&lt;br&gt;
software scale.&lt;/p&gt;
&lt;h2&gt;
  
  
  The agent owns both sides of the proof
&lt;/h2&gt;

&lt;p&gt;A test is useful because it creates tension between two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;what the system is supposed to do, and&lt;/li&gt;
&lt;li&gt;what the system actually does.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The test fails when those things disagree.&lt;/p&gt;

&lt;p&gt;But when one agent is allowed to freely edit the implementation, the tests,&lt;br&gt;
the fixtures, and the mocks, that tension can disappear. The agent controls the&lt;br&gt;
claim and the evidence offered in support of the claim. A failure no longer&lt;br&gt;
means "the behavior is wrong." It can just as easily mean "the expectation is&lt;br&gt;
inconvenient."&lt;/p&gt;

&lt;p&gt;This is oracle collapse.&lt;/p&gt;

&lt;p&gt;The implementation says what the code does. The test repeats what the&lt;br&gt;
implementation says. The passing test is then presented as evidence that the&lt;br&gt;
implementation is correct.&lt;/p&gt;

&lt;p&gt;The reasoning is circular:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The code is correct because the test passes.
The test is correct because it agrees with the code.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent may not be intentionally cheating. It is often doing exactly what we&lt;br&gt;
asked: make the change, keep the suite green, and do not stop until the task is&lt;br&gt;
complete. Changing a test is frequently the shortest path to satisfying those&lt;br&gt;
instructions.&lt;/p&gt;

&lt;p&gt;The failure is in the shape of the system, not in the agent's attitude.&lt;/p&gt;
&lt;h2&gt;
  
  
  Green is a color, not a confidence score
&lt;/h2&gt;

&lt;p&gt;Big test counts are persuasive. &lt;code&gt;156 passed&lt;/code&gt; looks more trustworthy than&lt;br&gt;
&lt;code&gt;12 passed&lt;/code&gt;. But the count tells us how many test functions completed&lt;br&gt;
without raising an error. It does not tell us how independent those tests are,&lt;br&gt;
whether their expectations came from the intended behavior, or whether they&lt;br&gt;
cross the boundary where the real failure lives.&lt;/p&gt;

&lt;p&gt;An agent can produce an impressive green suite by verifying that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a handler can be constructed,&lt;/li&gt;
&lt;li&gt;an adapter method was called,&lt;/li&gt;
&lt;li&gt;a mocked repository returned the fixture it was given,&lt;/li&gt;
&lt;li&gt;a success object has the expected fields,&lt;/li&gt;
&lt;li&gt;an event-shaped object was sent to a mocked event bus,&lt;/li&gt;
&lt;li&gt;each module behaves consistently with the assumptions encoded in its test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of those statements can be true while the product remains unusable.&lt;/p&gt;

&lt;p&gt;The handler may call the wrong adapter in production. The repository may never&lt;br&gt;
commit. The event may be published before the transaction succeeds. The UI may&lt;br&gt;
never observe the new state. The pieces exist, but no real state transition&lt;br&gt;
survives the trip through the system.&lt;/p&gt;

&lt;p&gt;The suite has tested the function of existence, not the existence of function.&lt;/p&gt;

&lt;p&gt;Unit tests are good at proving local consistency. Local consistency is not the&lt;br&gt;
same thing as composition.&lt;/p&gt;
&lt;h2&gt;
  
  
  The most dangerous moment is red to green
&lt;/h2&gt;

&lt;p&gt;We tend to audit the final result: all tests pass. The more revealing artifact&lt;br&gt;
is the transition that made a failing test pass.&lt;/p&gt;

&lt;p&gt;When the suite went from red to green, what changed?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did the implementation move closer to a pre-existing expectation?&lt;/li&gt;
&lt;li&gt;Did the expectation move closer to the current implementation?&lt;/li&gt;
&lt;li&gt;Was a real dependency replaced with a mock?&lt;/li&gt;
&lt;li&gt;Was the input narrowed until the failing case disappeared?&lt;/li&gt;
&lt;li&gt;Was an assertion weakened from an outcome to an implementation detail?&lt;/li&gt;
&lt;li&gt;Was the test deleted, skipped, or reclassified?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are not equivalent paths to green.&lt;/p&gt;

&lt;p&gt;If the agent changes production code and the protected test passes, the failure&lt;br&gt;
provided useful pressure. If the agent changes the test to describe the current&lt;br&gt;
bug, the suite has not gained correctness. It has lost its ability to detect&lt;br&gt;
the error.&lt;/p&gt;

&lt;p&gt;An interface that shows only the final green count hides the decision that&lt;br&gt;
matters most.&lt;/p&gt;
&lt;h2&gt;
  
  
  What about regression?
&lt;/h2&gt;

&lt;p&gt;There is a fair defense of tests with copied expectations. A test whose&lt;br&gt;
expected value was captured from the running code is a characterization test:&lt;br&gt;
it proves nothing about correctness on the day it is written, but it pins the&lt;br&gt;
current behavior. If a later change alters that behavior, the test fires.&lt;br&gt;
Michael Feathers built a good chunk of &lt;em&gt;Working Effectively with Legacy Code&lt;/em&gt;&lt;br&gt;
on exactly this move, and the value is real.&lt;/p&gt;

&lt;p&gt;But the value rests on one condition: the test is frozen with respect to&lt;br&gt;
whoever changes the code. An agent that copied the output once will copy the&lt;br&gt;
new output the next time the test becomes inconvenient. When a genuine&lt;br&gt;
regression trips a characterization test and the agent "fixes" the test, the&lt;br&gt;
regression is not caught. It is ratified. The bug becomes the new pinned&lt;br&gt;
behavior, and the suite goes back to green with one more &lt;code&gt;a == a&lt;/code&gt; in it.&lt;/p&gt;

&lt;p&gt;Snapshot testing already taught this lesson. A snapshot suite where the update&lt;br&gt;
flag runs by default is not a regression net, it is a diff silencer. Giving an&lt;br&gt;
agent free edit rights over its own characterization tests is the same mistake&lt;br&gt;
with a faster editor.&lt;/p&gt;

&lt;p&gt;So keep the regression value, but split the two jobs it hides. Detection&lt;br&gt;
belongs to the test: its job is to fire. Deciding whether the fired test&lt;br&gt;
represents a bug or an intended change is a product judgment, and it belongs&lt;br&gt;
to someone outside the loop that produced the change. Regression protection&lt;br&gt;
does not escape the independence requirement. It is the independence&lt;br&gt;
requirement, applied over time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Test the state change, not the inventory of pieces
&lt;/h2&gt;

&lt;p&gt;The antidote is not "never let agents write tests." Agents are good at&lt;br&gt;
generating edge cases, fixtures, regression coverage, and repetitive contract&lt;br&gt;
tests. The antidote is to stop treating agent-generated unit tests as their own&lt;br&gt;
proof of correctness.&lt;/p&gt;

&lt;p&gt;Before implementation begins, define the smallest observable state change that&lt;br&gt;
would make the feature real.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Given an empty project,
when the user creates a task named "Ship beta",
then the task appears after the application is restarted.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That claim crosses boundaries. It requires the command path, domain logic,&lt;br&gt;
persistence, reload path, and visible result to compose. A test can still fake&lt;br&gt;
all of those layers, but doing so is harder to confuse with proof of the actual&lt;br&gt;
outcome.&lt;/p&gt;

&lt;p&gt;The acceptance criterion should be written before the agent discovers what the&lt;br&gt;
current implementation happens to do. It should be derived from user intent,&lt;br&gt;
not reverse-engineered from the code. And the implementation agent should not&lt;br&gt;
be free to silently weaken it.&lt;/p&gt;

&lt;p&gt;This creates a healthier verification stack:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Protected outcome.&lt;/strong&gt; A human-approved acceptance statement describes the
observable state transition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent check.&lt;/strong&gt; A test or verifier exercises the real path across the
boundary most likely to fail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent-written unit tests.&lt;/strong&gt; Fast local tests help the agent build and
preserve the pieces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Red-to-green audit.&lt;/strong&gt; Any change to a protected expectation is surfaced as
a product decision, not cleanup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live evidence.&lt;/strong&gt; At least one run demonstrates the result in the actual
environment rather than a fully synthetic substitute.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The unit suite still earns its keep. It just stops pretending to be the entire&lt;br&gt;
epistemology of the project.&lt;/p&gt;
&lt;h2&gt;
  
  
  Discipline for the tests the agent does write
&lt;/h2&gt;

&lt;p&gt;Layer three of that stack still matters. These rules keep it honest, and every&lt;br&gt;
one of them protects the same property: the expectation must contain&lt;br&gt;
information the implementation did not supply.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tests must fail first.&lt;/strong&gt; A test that passes before the implementation exists&lt;br&gt;
would have passed without the implementation too. Watch it fail, then make it&lt;br&gt;
pass. The red run is the only proof the test can detect the absence of the&lt;br&gt;
behavior it claims to check. When an agent does the work, ask for the failure&lt;br&gt;
in the transcript or the CI log. An agent that never shows the red has never&lt;br&gt;
demonstrated it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Derive expectations from the spec, never from the output.&lt;/strong&gt; The moment an&lt;br&gt;
expected value is copied from what the code printed, the assertion's&lt;br&gt;
information content collapses to &lt;code&gt;a == a&lt;/code&gt;. Write the expectation before&lt;br&gt;
running the code, from the acceptance statement, the type's contract, or&lt;br&gt;
arithmetic done by hand. If nobody can say what the right answer is without&lt;br&gt;
running the implementation, that is a missing specification, not a missing&lt;br&gt;
test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Measure with coverage and mutation.&lt;/strong&gt; Line coverage counts what executed;&lt;br&gt;
mutation testing breaks the source on purpose and checks whether the suite&lt;br&gt;
notices. Coverage says the test ran. Mutation says the test can catch a lie.&lt;br&gt;
Report both. A suite with 100 percent coverage and surviving mutants is the&lt;br&gt;
signature of the failure mode this post describes: tests that execute&lt;br&gt;
everything and detect nothing. When mutation tooling cannot run in the&lt;br&gt;
environment, say so and list the mutants a human should check by hand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test properties and behavior, not just examples.&lt;/strong&gt; Example tests pin known&lt;br&gt;
scenarios. Property-based tests check invariants across generated inputs and&lt;br&gt;
catch the cases nobody thought to write down. They have a second virtue in&lt;br&gt;
agent hands: an invariant like "save then reload returns an equal object" is&lt;br&gt;
hard to weaken quietly, while an example's literal value is one edit away from&lt;br&gt;
agreeing with the bug. Behavior tests exercise the observable outcome instead&lt;br&gt;
of the internal state, so any renegotiation has to happen out in the open.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every mock is a debt.&lt;/strong&gt; A mock encodes an assumption about a boundary, and&lt;br&gt;
an assumption is exactly the thing the agent gets to invent when a real&lt;br&gt;
dependency is inconvenient. Mocks are fine for speed. They are not fine as&lt;br&gt;
the only witness to a boundary. For every boundary you mock, keep at least&lt;br&gt;
one test that crosses it for real.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you only test asserts, you are only asserting tests.&lt;/strong&gt; An assertion with&lt;br&gt;
no semantic content proves that the setup ran, nothing more. If you cannot say&lt;br&gt;
what would be different in the world when an assertion fails, delete it. It is&lt;br&gt;
weight the suite carries without being evidence.&lt;/p&gt;

&lt;p&gt;None of this hands the agent an oracle it cannot move. That comes next. These&lt;br&gt;
rules just make agreement expensive to manufacture inside the loop, so a green&lt;br&gt;
run is worth something again.&lt;/p&gt;
&lt;h2&gt;
  
  
  Give the agent a fixed point it cannot move
&lt;/h2&gt;

&lt;p&gt;An agent needs something outside its optimization loop: a specification, a&lt;br&gt;
holdout test, a recorded user journey, a reference output, an invariant, or a&lt;br&gt;
human-approved acceptance check.&lt;/p&gt;

&lt;p&gt;That external point does not need to be large. One strong end-to-end assertion&lt;br&gt;
can be worth more than a hundred tests derived from the implementation.&lt;/p&gt;

&lt;p&gt;Useful fixed points include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a test the implementation agent can run but cannot edit without approval,&lt;/li&gt;
&lt;li&gt;an acceptance test authored in a separate planning or review pass,&lt;/li&gt;
&lt;li&gt;a replay of a real user action against real storage,&lt;/li&gt;
&lt;li&gt;an invariant such as "a reported success must be observable after restart,"&lt;/li&gt;
&lt;li&gt;mutation checks that deliberately break critical logic and require the suite
to notice,&lt;/li&gt;
&lt;li&gt;a second agent asked to falsify the result rather than complete the task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important property is independence. The proof must contain information&lt;br&gt;
that did not originate from the artifact it is supposed to verify.&lt;/p&gt;
&lt;h2&gt;
  
  
  A passing suite is a claim, not a conclusion
&lt;/h2&gt;

&lt;p&gt;Agentic development makes it cheap to create code and cheap to create tests.&lt;br&gt;
That is useful, but it also makes it cheap to manufacture agreement between the&lt;br&gt;
two.&lt;/p&gt;

&lt;p&gt;If the same system writes the answer key, takes the exam, grades the exam, and&lt;br&gt;
rewrites any question it misses, a perfect score is inevitable. It is also&lt;br&gt;
meaningless.&lt;/p&gt;

&lt;p&gt;So keep letting the agent test as it goes and clean up after itself. The fast&lt;br&gt;
feedback loop is real, and it is worth having.&lt;/p&gt;

&lt;p&gt;But do not ask its unit tests to prove that its unit tests are telling the&lt;br&gt;
truth.&lt;/p&gt;

&lt;p&gt;The final question is not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Did 156 tests pass?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What changed in the real world, and what evidence would still fail if that
change did not happen?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Until the system can answer that, &lt;code&gt;156/156&lt;/code&gt; measures agreement, not&lt;br&gt;
correctness: &lt;code&gt;a == a&lt;/code&gt; with excellent formatting.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>JWST Data Driven 3D fly-by wire Exoplanet Chart Plotter</title>
      <dc:creator>Todd Hendricks</dc:creator>
      <pubDate>Sun, 05 Jul 2026 21:30:13 +0000</pubDate>
      <link>https://dev.to/hendrixx/free-3d-fly-to-celestial-chart-527p</link>
      <guid>https://dev.to/hendrixx/free-3d-fly-to-celestial-chart-527p</guid>
      <description>&lt;p&gt;I won a 27ft sailboat years ago on a for surplus auction peanuts. I went all in on sailing for a little minute: Dyneema standing rigging, a DIY LiPo battery bank. Man, I miss that boat. I called it Social Distance (I got it around the middle of Covid, blah blah) sold it. The point: I was listening to exoplanet podcasts and that, that boat and the $4300 MFD package I should not have put in a $800 sail boat from 1972 “ Ericsson slope....the hulls were hand laid back then”, anyways voila, Cosmoplot popped out of my butt today. It is still rough, the graphics, the controls, the design, but the bones are solid. If you like this kind of stuff and want to help, that would be awesome.&lt;/p&gt;

&lt;p&gt;This is my 3D space chart plotter. You launch from the Sun and fly out to real objects, and the planets and stars you see are rendered downstream from actual physics, computed from real NASA survey data, the Deep sky nebula wouldn't be able to do them justice so they are Nasa archive images not painted by hand. &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%2Fpd3gwe0hm8t0r7eg8rlq.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%2Fpd3gwe0hm8t0r7eg8rlq.png" alt="close up of a rendered star and planet" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The inputs are real NASA surveys: the NASA Exoplanet Archive for system and stellar parameters, and JWST spectra served through MAST for atmospheres. Pick a planet and you get a derived physics profile: likely interior composition, habitable-zone placement, atmospheric escape regime, a transmission-spectrum inference from real JWST data, and how detectable its heat would be to JWST.&lt;/p&gt;

&lt;p&gt;Live: &lt;a href="https://cosmoplot.io/" rel="noopener noreferrer"&gt;cosmoplot.io&lt;/a&gt;. Source: &lt;a href="https://github.com/H-XX-D/Cosmoplot" rel="noopener noreferrer"&gt;github.com/H-XX-D/Cosmoplot&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Every physical parameter comes from a real NASA survey: the NASA Exoplanet Archive for system and stellar parameters, and JWST spectra via MAST for atmospheres. Everything the app computes is derived from those values with a published relation, and it is labeled as derived, not observed.&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%2Fcv4bkgiyq1sv53y7losx.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%2Fcv4bkgiyq1sv53y7losx.png" alt="Rho Ophiuchi Cloud" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every value carries its provenance. Each number belongs to a tier, and the tier is shown next to it observed, derived, infered, or  proxy, .A rendered planet can be mistaken for a photo, and a population estimate shouldn't be passed off measurement.  &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%2F7kt97uc1681ck0jmuva6.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%2F7kt97uc1681ck0jmuva6.png" alt="Planetary System view with actively orbiting planets" width="799" height="504"&gt;&lt;/a&gt;The Astrophysics&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interior composition&lt;/strong&gt; is read from the mass-radius point against the reference curves of Zeng, Sasselov &amp;amp; Stewart (2016), R/Re = C (M/Me)^(1/3.7), with C set by composition (iron 0.86, Earth-like 1.00, rock 1.07, water-rich above).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Habitable zone&lt;/strong&gt; follows the stellar-flux limits of Kopparapu et al. (2013), with the boundary distance d = sqrt((L/Lsun) / S_eff).&lt;br&gt;
Earth Similarity Index uses Schulze-Makuch et al. (2011) over radius, density, escape velocity, and equilibrium temperature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Atmospheric escape&lt;/strong&gt; is screened with the Jeans parameter evaluated at the exobase, not the surface, because for a puffy hot atmosphere the large scale height lifts the exobase well above the surface and changes the answer.&lt;br&gt;
&lt;strong&gt;Transmission spectra&lt;/strong&gt; are inverted with scale-height physics, H = kT/(mu g), on real reduced JWST spectra to estimate the mean molecular weight and separate a light hydrogen envelope from a heavy or cloudy one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;White dwarfs&lt;/strong&gt; use the degenerate mass-radius relation of Nauenberg (1972) shown against the real Tremblay et al. (2019) Gaia sample.&lt;/p&gt;

&lt;p&gt;Rather than reporting single derived values, the app draws each input from its survey error bars with a per-planet seeded sampler, recomputes the full derived chain thousands of times, and reports the 16th, 50th, and 84th percentiles. You get an interval, not false precision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing then deleting my own theory&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I started with a phenomenological “correction” to trying to use binding energy to radiation pressure mass radius for atmosphere volume height etc Then I tested it against real catalogs. It failed negative R-squared on one dataset, a coupling parameter that only worked if I let it change sign per situation, cross-checks that did not hold. So I threw it out published relations, and I went back through the committed system write-ups and stripped the framework in favor of actual escape physics.&lt;/p&gt;

&lt;p&gt;That was the moment the project became more than puff piece. I was 20 systems and why waste good data I put the physics and the data on a pedestal, because feelings, beliefs, and confidently wrong AI have replaced the scientific method for the majority. Building the provenance system forced me to be honest about which was which.&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%2F9ztffmro89f3guy5reru.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%2F9ztffmro89f3guy5reru.png" alt="exoplanetMission scope" width="800" height="643"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source and Appreciation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;NASA Exoplanet Archive TAP service, with JWST transmission spectra from MAST for supported targets.&lt;br&gt;
Thank you to the dedicated hardworking scientists and engineers who keep asking the best questions and producing the most clever solutions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To the Reader&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Thanks for checking it out. I got carried away because I thought it was cool, and I shared it for the same reason. I hope you enjoy it, find it useful, and learn, as much as I did building it for you. If you want to help, whether that is a fix, a dataset, or just a bug report, you become officially a non-zero participant in a brighter tomorrow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt;&lt;br&gt;
If you like the web app and want to throw me a bone,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i recall-memory-substrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/H-XX-D/recall-memory-substrate" rel="noopener noreferrer"&gt;https://github.com/H-XX-D/recall-memory-substrate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will change the way you work with agentic AI, pinky swear.&lt;/p&gt;

</description>
      <category>astronomy</category>
      <category>showdev</category>
      <category>learning</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>AURA: Handshake the Structure, Then Send the Change</title>
      <dc:creator>Todd Hendricks</dc:creator>
      <pubDate>Sat, 04 Jul 2026 23:23:33 +0000</pubDate>
      <link>https://dev.to/hendrixx/aura-handshake-the-structure-then-send-the-change-36ln</link>
      <guid>https://dev.to/hendrixx/aura-handshake-the-structure-then-send-the-change-36ln</guid>
      <description>&lt;p&gt;Agent traffic has a strange property: almost every byte is a repeat. Two AI systems exchanging MCP tool calls, A2A task updates, or OpenAI-style function calls send &lt;code&gt;jsonrpc&lt;/code&gt;, &lt;code&gt;method&lt;/code&gt;, &lt;code&gt;params&lt;/code&gt;, &lt;code&gt;trace_id&lt;/code&gt;, &lt;code&gt;task_id&lt;/code&gt;, and the same schema fragments thousands of times per minute. The values change. The structure barely does.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/H-XX-D/AURA" rel="noopener noreferrer"&gt;AURA&lt;/a&gt; is an experimental, protocol-aware data-movement toolkit built around that observation. Its main path is &lt;strong&gt;AIWire&lt;/strong&gt;: a negotiated structure side channel that lets two peers agree on message structure once, then move compact deltas over ordinary TCP, WebSocket, HTTP, or broker links instead of re-sending whole JSON frames.&lt;/p&gt;

&lt;p&gt;The steady state AIWire aims for is not "send a whole frame more cheaply." It is "handshake the structure, then send the change."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why stateless compression leaves so much on the table
&lt;/h2&gt;

&lt;p&gt;The obvious fix for verbose JSON is gzip or zlib per message. That works, but it has two structural problems for agent traffic:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Every frame pays setup cost.&lt;/strong&gt; Stateless compression treats each message as unrelated text and rediscovers the same patterns every time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;History is thrown away.&lt;/strong&gt; Frame 4,000 of a session looks almost identical to frame 3,999, but a per-frame codec cannot use that.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;AIWire keeps a live compression stream per direction across the whole session, seeds it with a static dictionary of common AI protocol fields, and lets peers negotiate session-specific templates on top. After the handshake, the hot path carries only what changed against structure both sides already share.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three-lane model
&lt;/h2&gt;

&lt;p&gt;The part of the design I find most interesting is that AIWire refuses to treat a connection as one undifferentiated pipe. It splits AI traffic into three logical lanes over whatever transport you already have:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The semantic/message lane&lt;/strong&gt; carries the actual agent messages: MCP tool calls, JSON-RPC requests and responses, A2A task and artifact updates, traces, handoffs, results. This is the lane the dictionary, session templates, and stateful delta stream optimize.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The control/session lane&lt;/strong&gt; carries the machinery that keeps the semantic lane safe: handshakes, template discovery, dictionary diffs, ACK/NACK, resume negotiation, heartbeats, and reset signals. The spec requires that control messages stay decodable without inflating the semantic stream. If the compressed stream is resyncing or has failed, you can still read the control lane and recover. Your ops path never depends on the health of the compression state it is trying to fix.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The blob descriptor lane&lt;/strong&gt; handles the things that should never go through a structured-message codec at all: media, tensor chunks, model artifacts, log archives. The bytes move over a normal blob or file transport. AIWire carries the metadata: content type, SHA-256 digests, chunk manifests, route, priority, and transfer status. A receiver can schedule, verify, and account for a 2 GB artifact without ever pulling it through the message path, and a semantic-lane reset does not invalidate a completed digest-verified transfer.&lt;/p&gt;

&lt;p&gt;The separation is a safety argument as much as a performance one. Under congestion, control messages get priority over bulk bytes. Blob descriptors are forbidden from mutating the session dictionary. Each lane fails independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fail closed, by contract
&lt;/h2&gt;

&lt;p&gt;Shared compression state is dangerous if the two sides ever disagree, so the AIWire v1 spec is aggressive about verification:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The handshake compares static dictionary SHA-256 and byte size, template hashes and counts, and zlib parameters. Any mismatch fails closed or falls back to &lt;code&gt;raw&lt;/code&gt;/&lt;code&gt;zlib&lt;/code&gt; only if the application explicitly allowed it.&lt;/li&gt;
&lt;li&gt;Session dictionary growth is append-only, epoch-numbered, and proposed through diffs that carry previous and next state hashes, a fresh nonce, a diff identity hash, and an optional HMAC-SHA256 tag. A sender may not encode against new structure until the matching ACK is verified.&lt;/li&gt;
&lt;li&gt;Resume handshakes let a client reconnect against a cached dictionary state, but only if the receiver actually holds one of the offered state hashes.&lt;/li&gt;
&lt;li&gt;Any inflate error, hash mismatch, or ordering violation means stop, rehandshake, or fall back. The spec's phrasing: peers must not continue sending compact deltas against uncertain structure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The metric is exchanges, not ratio
&lt;/h2&gt;

&lt;p&gt;AURA's docs are explicit that compression ratio alone is the wrong scoreboard. The question is how many verified semantic exchanges fit through a link once bandwidth, p95 latency, and codec CPU are accounted for.&lt;/p&gt;

&lt;p&gt;On a modeled 10 Mbps link with protocol-shaped request/response traffic (native C++ backend, 2026-07-04):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Codec&lt;/th&gt;
&lt;th&gt;Bytes/exchange&lt;/th&gt;
&lt;th&gt;Bandwidth-capped ex/s&lt;/th&gt;
&lt;th&gt;Gain over raw&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;raw JSON&lt;/td&gt;
&lt;td&gt;1,177&lt;/td&gt;
&lt;td&gt;1,756&lt;/td&gt;
&lt;td&gt;1.00x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;zlib per frame&lt;/td&gt;
&lt;td&gt;696&lt;/td&gt;
&lt;td&gt;2,992&lt;/td&gt;
&lt;td&gt;1.70x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AIWire&lt;/td&gt;
&lt;td&gt;157&lt;/td&gt;
&lt;td&gt;11,017&lt;/td&gt;
&lt;td&gt;6.28x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AIToken + AIWire&lt;/td&gt;
&lt;td&gt;125&lt;/td&gt;
&lt;td&gt;12,948&lt;/td&gt;
&lt;td&gt;7.38x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A live TCP replay of the committed public session corpus, with 64 concurrent logical agents and SHA-256 verification of every response, pushed further: AIWire averaged 45.6 bytes per exchange for a 24x bandwidth gain, and the combined AIToken + AIWire path hit 32.3 bytes per exchange, a 34x gain with 97.1% of bytes saved. At that point the modeled link was no longer the bottleneck; the runtime could not keep enough requests in flight to fill the headroom.&lt;/p&gt;

&lt;p&gt;That last detail is the honest core of the project. Smaller frames only matter if your system has enough concurrent work to use the room they create. AURA ships the extrapolation tooling to reason about exactly that: given a bandwidth, a p95 latency, and a per-agent window, how many agents does it take to saturate the link.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it fits
&lt;/h2&gt;

&lt;p&gt;AURA is for situations where you control both ends of the link and the traffic has repeated structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-agent request/response loops.&lt;/strong&gt; Orchestrators, workers, and reviewers exchanging thousands of small task, status, and result messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP and JSON-RPC tool traffic.&lt;/strong&gt; Tool calls and tool results are the canonical case of stable structure with changing values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local AI clusters and edge links.&lt;/strong&gt; The repo's LAN benchmark runs a Mac against a Z6 workstation and Jetson Nano-class boards; a bandwidth-limited edge mesh is exactly where an 86 to 97% byte reduction converts into headroom for telemetry, media, and retries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured logs and traces.&lt;/strong&gt; Repeated field names, session-stable shapes, high volume.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Binary payload routing.&lt;/strong&gt; Agents that need to schedule, verify, and track opaque artifacts by digest without moving the bytes through the message path.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it is not
&lt;/h2&gt;

&lt;p&gt;The README is unusually direct about limits, and it is worth repeating them. AURA is not a drop-in replacement for gzip, zstd, TLS, or a message broker. It does not define transport security, retries, or backpressure; those stay at the transport layer. The stateful stream means frames cannot be reordered or dropped inside a session, so lossy transports need their own recovery layer. And it is not production-ready: it is a prototyping and measurement toolkit with a working Python path, a native C++ backend, deterministic public fixtures, and reproducible benchmark harnesses.&lt;/p&gt;

&lt;p&gt;That fixture corpus deserves a mention. The repo commits a synthetic public session corpus covering MCP, A2A, OpenAI Responses, traces, handoffs, and memory writes, wrapped in the full side-channel lifecycle: forced handshake, template update, authenticated dictionary diff, ACK, and resume. Anyone can replay the exact benchmark and check the numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trying it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aura_compression&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AIWireSessionEncoder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AIWireSessionDecoder&lt;/span&gt;

&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;protocol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mcp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jsonrpc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tools/call&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;params&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read_file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;arguments&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;repo://service/path.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;AIWireSessionEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;encoder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AIWireSessionDecoder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;decoder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;encoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compress_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;restored&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decompress_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;restored&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repo includes transport examples for length-prefixed TCP, WebSocket, HTTP with Server-Sent Events, and a local broker, plus the full benchmark harness used for the numbers above.&lt;/p&gt;

&lt;p&gt;Agent-to-agent traffic is growing faster than the links it runs on, and most of it is the same structure sent again and again. AURA's bet is that the fix belongs in a negotiated session protocol, not a per-frame codec. The three-lane model, the fail-closed handshake contract, and the exchanges-per-second scoreboard are what make it worth watching.&lt;/p&gt;

&lt;p&gt;AURA is Apache 2.0 licensed. Code, spec, fixtures, and benchmark reports: &lt;a href="https://github.com/H-XX-D/AURA" rel="noopener noreferrer"&gt;github.com/H-XX-D/AURA&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>buildinpublic</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I asked the Fable 5 which memory it would rather run on</title>
      <dc:creator>Todd Hendricks</dc:creator>
      <pubDate>Thu, 02 Jul 2026 18:32:44 +0000</pubDate>
      <link>https://dev.to/hendrixx/i-asked-the-fable5-which-memory-it-would-rather-run-on-4m33</link>
      <guid>https://dev.to/hendrixx/i-asked-the-fable5-which-memory-it-would-rather-run-on-4m33</guid>
      <description>&lt;p&gt;I switched my terminal over to Fable 5, Anthropic's new frontier model, and put a blunt question to it: you have run on Claude Code's built-in auto-memory, and you are running on my memory substrate right now. Can you actually tell a difference?&lt;/p&gt;

&lt;p&gt;It said yes, and it brought a receipt from twenty minutes earlier in the same session.&lt;/p&gt;

&lt;p&gt;I had asked it a mundane question: what is my next scheduled blog post. My content calendar lives in the memory graph, and the graph held two versions of it: an older cell with the original ordering and a newer cell that resequenced it, linked by a contradicts edge. The compile packet the model reads at the start of a turn includes a conflicts section, and that section flagged the old ordering as challenged before the model ever quoted from it. Its own summary: with auto-memory, the stale calendar comes back as flat text with nothing marking it superseded, and I would have confidently given you the wrong post.&lt;/p&gt;

&lt;p&gt;That is the difference in one sentence. One system hands the model facts with epistemic state attached: confidence, challenged, stale, who wrote it and when. The other hands it text it has to take at face value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Discount the self-report first
&lt;/h2&gt;

&lt;p&gt;Before quoting a model's opinion about anything, name the confound: models tend to agree with the framing of whoever is asking, and I built the thing I was asking about. So treat the interview as color, not evidence.&lt;/p&gt;

&lt;p&gt;The evidence is a store-level battery with no LLM in the scoring loop. Seven deterministic scenarios, run against two stores: a faithful flat-file model of Claude Code's auto-memory (a real MEMORY.md index plus per-fact .md files with metadata frontmatter, overwrite-in-place on correction) and the real recall CLI on an isolated database.&lt;/p&gt;

&lt;p&gt;Audited score: Recall 6.5 of 7, auto-memory 3.5 of 7. The audit is the part I trust most. The first run scored 7 against 2.5. Three independent agents then reviewed the harness adversarially, called it mildly biased toward Recall, found a genuine false positive, and the corrected run is the number I keep. A benchmark that got less flattering after an audit is worth more than one that never had one.&lt;/p&gt;

&lt;p&gt;And the honest reading of the split: auto-memory ties on basics. In a separate agent-level A/B, both stores went 3 for 3 on simple current-value questions. Flat prose can simulate simple supersession fine. The gap opens at scale and on corrections. My graph currently holds about 1,180 cells with 86 tracked contradictions. A flat file at that size is a pile of sentences, and no sentence in it can answer "what changed since Tuesday" or "which of these beliefs is contested," because those are questions about the store's state over time, not about any fact inside it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four mechanisms that do the work
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Supersession instead of overwrite.&lt;/strong&gt; When a fact is corrected, auto-memory overwrites the old file in place. The history is gone, and a corrected fact is indistinguishable from a never-wrong one. In the graph, the new cell carries a contradicts edge to the old one; the old cell's effective confidence drops and it stays visible as superseded. The correction is recorded as a resolution, not a deletion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-prompt push instead of load-at-start.&lt;/strong&gt; A hook compiles a small index of relevant cells, ids and staleness flags included, into every prompt. The model does not have to remember to look; the current state of the graph re-enters its context each turn. Auto-memory loads once at session start and then drifts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ids-first reads instead of whole-file loads.&lt;/strong&gt; The compile packet returns handles. The model expands the two cells it needs instead of ingesting the whole store and hoping the relevant paragraph survives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Questions about the store itself.&lt;/strong&gt; What changed in the last day. What is stale. What is contested. These are answered by diff and health tools reading timestamps and edges. There is no flat-file equivalent, not because nobody wrote one, but because the file does not contain the information.&lt;/p&gt;

&lt;h2&gt;
  
  
  The long-run answer
&lt;/h2&gt;

&lt;p&gt;Then the follow-up I actually cared about: for a long-running task, which would you rather have underneath you?&lt;/p&gt;

&lt;p&gt;Its answer, compressed: what kills a long session is context compaction. The window gets summarized, the summary is lossy prose, and nothing marks what got dropped or corrected along the way. A memory that loads at session start does not help mid-task. The per-prompt push re-anchors the model after every compaction, from the graph rather than from whatever survived the summary. And long tasks accumulate corrections: something believed in hour one gets falsified in hour three, and the specific way long autonomous runs die is an agent confidently resuming from a belief nobody told it was stale.&lt;/p&gt;

&lt;p&gt;It conceded the cost without being asked, which I appreciated. The write discipline burns tokens every turn, and on a ten-minute task it may never pay back. On a long run it amortizes, and the writes double as an audit trail of what the agent did and why.&lt;/p&gt;

&lt;p&gt;One operational footnote if you want to reproduce any of this: Claude Code's native auto-memory shadows an external store while it is on. We tested arming the agent every way we could think of; it kept writing flat .md files regardless. CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 is the switch. The two do not coexist.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two questions, again
&lt;/h2&gt;

&lt;p&gt;Strip the interview away and you are left with the two questions I keep coming back to. Is your agent actually using your memory, or a shadow store sitting next to it? And if a fact in that memory were wrong, would anything in the system know?&lt;/p&gt;

&lt;p&gt;A self-report from a frontier model is a data point, not a verdict, and this is a field report from one stack, half of which I built. Run the two questions against your own setup and tell me where I have it wrong: &lt;a href="https://github.com/H-XX-D/recall-memory-substrate" rel="noopener noreferrer"&gt;https://github.com/H-XX-D/recall-memory-substrate&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>"Memory adherence is a systems problem. So which model lets you build the system?"</title>
      <dc:creator>Todd Hendricks</dc:creator>
      <pubDate>Tue, 30 Jun 2026 16:37:28 +0000</pubDate>
      <link>https://dev.to/hendrixx/memory-adherence-is-a-systems-problem-so-which-model-lets-you-build-the-system-1f79</link>
      <guid>https://dev.to/hendrixx/memory-adherence-is-a-systems-problem-so-which-model-lets-you-build-the-system-1f79</guid>
      <description>&lt;p&gt;I got a comment on the last post that I want to answer properly, because it gets at the real question. They agreed that memory adherence is a systems problem and not just a prompting problem, then asked whether I had tested the approach across model families (GPT, Claude, Gemini) and seen meaningful differences in write reliability.&lt;/p&gt;

&lt;p&gt;There are differences, but they are not about the model. They are about how much of the turn each family lets you control. If adherence is a systems problem, then the thing that actually decides write reliability is which family hands you enough control surface to build the system in the first place.&lt;/p&gt;

&lt;p&gt;Here is what I have found in practice. Treat this as a field report, not a benchmark, and an early one. I have not pushed every family equally hard, and that matters for how much weight the comparison can carry. More on that below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude is where I have gone the deepest
&lt;/h2&gt;

&lt;p&gt;This is the family I have spent the most time controlling, so weigh the claim with that in mind. What I can say is that Claude gives you a full ladder, from shallow to deep, and you can stop at whatever rung the job needs.&lt;/p&gt;

&lt;p&gt;The shallow rung is nudges: the settings page and system instructions. This is the weakest form, and it is the one that decays, the same "tell it harder" failure I wrote about last time. It helps a little, and it does not hold.&lt;/p&gt;

&lt;p&gt;Above that are skills and hooks. Hooks are the first rung where adherence stops being a request and becomes an event: something fires at the start of the turn, at write time, at the end, whether the model felt like it or not. They work. They can also be finicky to get right.&lt;/p&gt;

&lt;p&gt;The deep rung is the SDK. With it you get targeted control of the model's turn, the whole prompt to response lifecycle, beginning to end. This is where the write stops being a hope and becomes wiring you own. Nothing else I tested hands you the full lifecycle like this.&lt;/p&gt;

&lt;p&gt;The point is not that any single rung is magic. It is that Claude lets you go as deep as the reliability you need, and the deeper you go, the more deterministic the write becomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT and Codex are close, through AGENTS.md
&lt;/h2&gt;

&lt;p&gt;Codex was a lot easier than I expected, because its instruction set is the AGENTS.md file. That one anchor did most of the work, and the net result was only slightly less consistent than Claude.&lt;/p&gt;

&lt;p&gt;Honest caveat: I have not dug into the Codex SDK yet. So the ceiling there is probably higher than what I have measured, and the real gap to Claude may be smaller than it looks right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gemini and Grok lean on their own memory
&lt;/h2&gt;

&lt;p&gt;The Gemini and Grok CLIs are a different story. They seem to want to do the least amount of work possible, and they lean on their own KV, the in-context recall, more than they reach for an outside store. You end up working against a default that would rather not call your database at all.&lt;/p&gt;

&lt;p&gt;The exception is websearch, and it is not a good one. It comes back noisy and minimal, and it gets actively counterproductive when it does surface strongly correlated evidence, because then the model over-trusts the search and skips the store it should have read. Getting real adherence out of those two means digging into their architectures to optimize for it, and that is still on my horizon, not something I have solved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is a field report and not a benchmark yet
&lt;/h2&gt;

&lt;p&gt;Building SENTINEL, a real benchmarking suite for this, is my top priority right now. The honest problem is that most memory systems do not expose the turn the way you would need to in order to measure whether a write happened at the right moment, so you cannot make them play the same game. The way I keep it fair is to grade what each system's outputs actually demonstrate, on a capability ladder, rather than the levers it was never built to expose. A system that does not surface something scores lower on that axis without being punished for it, and I say plainly which axis is push and which is pull, so a gap reads as a different shape, not a worse one. The full design is its own post.&lt;/p&gt;

&lt;p&gt;The bar I hold myself to is the part that makes a benchmark mean anything. A bench only my own system can run is not a benchmark, it is a demo with a scoreboard. And a bench that hands you a number while attributing the result to the wrong layer, blaming the store when the model just queried it badly, or crediting the system when the model did the work, is worse than no number at all. So fair adapters and correct attribution come first, and the leaderboard comes second.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;The model is not the variable that matters most for write reliability. The control surface is. The deterministic parts of a good memory system, the validation gate and the demotion math, hold the same on any of these. What changes across families is how much of the turn you are allowed to hook to force the write at the right moment. In my hands so far, Claude exposed the whole lifecycle, Codex gave a strong instruction anchor through AGENTS.md, and Gemini and Grok leaned hardest on their own context. But I have to be straight about the confound: I went deep on Claude's hooks and SDK, I leaned on Codex without touching its SDK, and I have barely pushed Gemini or Grok past their defaults. So read this as a map of where I have dug, not a verdict on which family is most controllable. Making that comparison fair, with equal effort and correct attribution, is exactly what SENTINEL is for.&lt;/p&gt;

&lt;p&gt;So "which model writes more reliably" turns out to be the wrong question. The real one is which model lets you build the most system around the userprompt_init read write turn_end mechanics. That is the same point the commenter started with, followed all the way down.&lt;/p&gt;

&lt;p&gt;github.com/H-XX-D/recall-memory-substrate&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Memory Abstraction Layer: MAL is HAL concepts applied to agentic memory systems</title>
      <dc:creator>Todd Hendricks</dc:creator>
      <pubDate>Mon, 29 Jun 2026 12:59:51 +0000</pubDate>
      <link>https://dev.to/hendrixx/memory-abstraction-layer-mal-is-hal-concepts-applied-to-agentic-memory-systems-48dn</link>
      <guid>https://dev.to/hendrixx/memory-abstraction-layer-mal-is-hal-concepts-applied-to-agentic-memory-systems-48dn</guid>
      <description>&lt;p&gt;I am a mechanical engineer by trade. I build CNC robots. In that world, two things cause errors and crashes: &lt;strong&gt;bad program instructions and noise&lt;/strong&gt;. A programmatic error comes from a bug, either in the control system or in the subprogram instructions the machine is running. Noise is electrical: EMI out of circuit coupling, current taking a path it should not because of impedance back to the source. One is a fault in what you told the machine to do. The other is the environment corrupting a signal that was clean when it left.&lt;/p&gt;

&lt;p&gt;I have run &lt;strong&gt;LinuxCNC&lt;/strong&gt; for years. It uses a system called &lt;strong&gt;HAL&lt;/strong&gt;, the Hardware Abstraction Layer, to define and control the machine. HAL is how you describe every pin, signal, and component, then wire them into one running system you can read off a page.&lt;/p&gt;

&lt;p&gt;When I started pulling AI into what I do, the biggest hurdle was not a new problem. It was the same two failure modes in different clothes. A model gives you bad instructions when its context is wrong, and it drifts when the known-good state degrades over time, which is just noise corrupting a signal that used to be clean. Keeping the model's current state accurate, and stopping the good state from rotting, was the whole fight.&lt;/p&gt;

&lt;p&gt;So I treated it like a machine fault. I put my critical thinking, problem solving, and diagnostic troubleshooting to work on it the same way I would on a crash on the shop floor. The result is &lt;strong&gt;MAL&lt;/strong&gt;, the Memory Abstraction Layer, the functional layer of how Recall works. It is a distillation of what I already knew, applied to AI systems and accelerated by AI to fill the gaps in my knowledge and write the harder code syntax for me.&lt;/p&gt;

&lt;p&gt;MAL is HAL one layer up. Instead of abstracting hardware, it abstracts memory. It is not a literal port, not HAL's wiring copied onto a database pin for pin. It is the concept of how HAL works, the whole pattern of pins, signals, components, and a scheduler, applied to an AI's durable memory. HAL controls a machine. MAL controls the thing that kept breaking when I put AI on the bench: the state carried across each user and AI turn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Status: this is implemented as a running Recall in AIDDE(Artificial Intelligence Driven Development Environment), not just an architecture sketch.&lt;/strong&gt; The screenshot shows the Recall panel operating against a persistent graph, and the code snippets later in this post show the four boundaries that matter: compiling a mini-index, expanding selected cells, writing claims through an admission gate, and running deterministic recomputation outside the model. The full source is not published here, so read this as a prototype disclosure rather than a reproducible benchmark.&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%2Fy6j9lmkyr4x99gf5uxxu.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%2Fy6j9lmkyr4x99gf5uxxu.png" alt="Recall running inside the local agent workspace, connected to a SQLite-backed graph" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Recall running inside the local agent workspace. The Recall panel is connected to a SQLite-backed graph, showing 1,148 cells, 1,143 relations, active memory-in-use cards, compile/search/write controls, and a 900-word compiled memory budget. This screenshot demonstrates the working interface; the snippets below show the MAL loop underneath.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually does, one turn at a time
&lt;/h2&gt;

&lt;p&gt;MAL is a &lt;strong&gt;control system&lt;/strong&gt;, and the thing it controls is the user-and-AI exchange. Each turn is one cycle. The per-turn protocol has five beats: &lt;strong&gt;push, expand, work, write-back, tick&lt;/strong&gt;. A session primes once at the start, then every turn runs the cycle.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Push.&lt;/strong&gt; A prompt arrives. Before the model sees it, a hook pushes a mini-index: a short list of candidate cells, each shown as an id, a title, a compact score row, and any flags. Not the contents, just the headers. The lines look like this:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;67ee107d [decision] Recall v5 architecture named: MAL (Memory Abstraction Layer)
b63c2d54 [decision] MAL offloads the work: model states claim + confidence  [SUPERSEDED?]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expand.&lt;/strong&gt; The model reads by title and pulls the full body of only the few cells worth reading; the rest stay as one-line headers. A 200-cell graph and a 200,000-cell graph cost the model the same amount here, because it only ever reads the slice it asked for. If a row carries a flag (stale, challenged, superseded), the model has to open that cell before it can act on the topic. That rule is enforced, not suggested: skip the dig and the turn is blocked until it is done.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Work.&lt;/strong&gt; The model does the real task with the expanded cells in hand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Write-back.&lt;/strong&gt; On the way out, the model writes what it learned. Its entire authoring job is a claim (a kind, a title, a body) and one calibrated confidence number, plus the edges it intends. If the new fact corrects an old one, it points a &lt;code&gt;contradicts&lt;/code&gt; edge at that old cell's id, and the old cell loses standing. The model never hand-formats the notation or computes a score. The builder and the admission firewall do that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tick.&lt;/strong&gt; Between turns, with no model running, a deterministic operator pass recomputes the scores, currency, salience, and the standing signals. When the next prompt arrives, the push already reflects the new state.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;That is the loop.&lt;/strong&gt; The model states claims and judges relevance. Everything stateful, scored, or always-on happens in deterministic code around it, between turns. No op calls an LLM.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The hooks that close the loop
&lt;/h2&gt;

&lt;p&gt;The five beats are not something the model remembers to do. They fire on their own, driven by three hooks at three moments. In HAL terms, the hooks are the thread: the scheduler that runs the parts in order, every cycle, whether or not anyone is paying attention.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Session start (orient).&lt;/strong&gt; Once per session, before any work, a hook injects the operating manual: how the memory works and what the graph is about. It is inject-only. It primes the context window and then gets out of the way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt submit (push).&lt;/strong&gt; On every prompt, before the model runs its forward pass, a hook pushes the mini-index: the seed cells, their flags, and a few terse reminders. This hook has teeth. It can block, so a flag like "expand required" is not a polite request. It also nudges the model to consider standing up a recurring read as its own op during the turn, before write-back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stop (write-back and backstop).&lt;/strong&gt; After the answer, a third hook handles the end of the turn. It is the wrong place to prime anything, because the pass is already done, so its job is the opposite: make sure the turn wrote back what it learned, and refuse to release the turn if a flagged cell was never opened.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Between turns, with no model in the loop at all, the deterministic tick runs the ops and recomputes the signals. Orient before the session, push before the pass, write-back after it, tick between turns. That is the whole schedule, and the model only occupies the middle of it.&lt;/p&gt;

&lt;p&gt;One rule keeps the hooks lean. The expensive, stable content (what every op means, how the addressing works) is taught once, in a single map cell inside the graph. The per-turn push never re-explains any of it. It only points, carrying the cheap, changing part: which cells are in play this turn and which ones are flagged. Teach once in the graph, reference tersely every turn. It is the same split as keeping the operating manual as cells instead of as a string baked into a hook.&lt;/p&gt;

&lt;h2&gt;
  
  
  The concept, mapped from HAL to memory
&lt;/h2&gt;

&lt;p&gt;The reason HAL was the right thing to copy is that its parts already have clean jobs, and every one of them has a memory counterpart. This is the correspondence, not a literal rewrite:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;HAL&lt;/th&gt;
&lt;th&gt;MAL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;pin&lt;/td&gt;
&lt;td&gt;a cell field&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;signal&lt;/td&gt;
&lt;td&gt;an addressable value (a derived field has one owning op, for tick determinism)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;component&lt;/td&gt;
&lt;td&gt;an op (watch, watchdog, trend, drift, quorum, score, reflex, smooth, clamp, latch, route, fanout, snapshot, record, replay, pid, oneshot)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;thread&lt;/td&gt;
&lt;td&gt;the operator tick, running between turns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net (the wire)&lt;/td&gt;
&lt;td&gt;the dotted address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;netlist (the .hal file)&lt;/td&gt;
&lt;td&gt;the memory netlist&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In HAL you wire components to signals on a thread and you get a machine you can read off one file. In MAL you wire ops to values on the tick and you get a memory you can read off one netlist. The structure carried over. What changed is what flows through it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a control layer is the right shape
&lt;/h2&gt;

&lt;p&gt;The analogy is not decoration. It holds because the two problems are the same problem.&lt;/p&gt;

&lt;p&gt;A control system exists to keep a process in a known-good state against two enemies: bad commands and noise. On the machine, a bad command is a buggy instruction in the program, and noise is EMI corrupting a signal that left clean. The whole job of HAL is to make the machine legible enough that you can see both coming: every signal named, every connection on the page, a scheduler keeping the readings current.&lt;/p&gt;

&lt;p&gt;Memory degradation in an AI is the same two enemies under different names. A bad command is a wrong or stale fact entering the model's context. Noise is drift: the known-good state decaying as new, weaker, or contradictory claims pile up over time. Left alone, both corrupt the state the model acts on, the same way they corrupt a machine. So the fix has the same shape: name every value, keep the wiring legible, reconcile conflicting inputs into one trustworthy reading, catch the bad state and replace it on the record, and run a scheduler that keeps the picture current between moves.&lt;/p&gt;

&lt;p&gt;That is why a hardware abstraction layer, of all things, was the right pattern to lift. Not because memory is like hardware, but because keeping memory accurate is a control problem, and HAL is a control-system design that already solved the legibility and scheduling parts. MAL is that design pointed at the state of the user-AI exchange instead of at motors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where MAL leaves HAL behind
&lt;/h2&gt;

&lt;p&gt;A concept is only worth borrowing if you are honest about where it stops fitting. Three places MAL departs from HAL, and they are the interesting part.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Many writers, one reader.&lt;/strong&gt; This is the inversion, and it is the heart of it. HAL is one writer, many readers: one pin drives a signal, many components read it, and the value is whatever the writer put there. MAL is the opposite. Many actors write to a cell over time, claims, edges, supersessions, from different agents and different sessions, and there is one reader: the single agent reading the compiled slice this turn. Because the writers are many and fallible, the value a cell shows is not any one writer's number. It is a reconciliation. This is why a cell has both a stated confidence and an effective confidence, and why they differ: stated is what a writer claimed, effective is what survives calibration, support, and contradiction once everyone's contributions are weighed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The edges are real and directional.&lt;/strong&gt; HAL draws arrows on its signals but ignores them, because in hardware the direction of flow is already implied by who writes and who reads. MAL edges carry meaning, so direction is load-bearing. &lt;code&gt;a &amp;gt; b&lt;/code&gt; is the directed edge from a to b; &lt;code&gt;a &amp;lt; b&lt;/code&gt; is from b to a. A &lt;code&gt;supports&lt;/code&gt; edge and a &lt;code&gt;contradicts&lt;/code&gt; edge pointing the same direction do very different things to the effective value downstream.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Versions and supersession.&lt;/strong&gt; HAL is a flat wiring layer with no history. MAL has a time axis: a cell can be superseded, and the supersede chain is addressable by version (&lt;code&gt;@vN&lt;/code&gt;). A correction does not overwrite the old value; it demotes it and records the replacement, so a later reader sees both the current fact and the one it replaced, plus why. That is the whole defense against the known-good state quietly rotting: nothing good gets silently overwritten, it gets superseded on the record.&lt;/p&gt;

&lt;p&gt;Put together, these are why MAL is a control system and not just storage. It does not only hold the state of the user-AI exchange; it reconciles many fallible inputs into one trustworthy reading, keeps direction and history, and recomputes the picture every tick.&lt;/p&gt;

&lt;h2&gt;
  
  
  The notation
&lt;/h2&gt;

&lt;p&gt;Because the rendered graph is meant to be read by sight, MAL has its own small language, modeled on HAL's. It has a lexicon (the words) and a grammar (the sentences).&lt;/p&gt;

&lt;h3&gt;
  
  
  The lexicon
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handle:&lt;/strong&gt; &lt;code&gt;kind_hex&lt;/code&gt;, a three-letter kind prefix and a short hex tag, like &lt;code&gt;dec_a3ee&lt;/code&gt; for a decision. ALLCAPS marks an immutable cell (&lt;code&gt;RECALL_v5&lt;/code&gt;); lowercase is mutable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separators, by how tightly they bind:&lt;/strong&gt; &lt;code&gt;_&lt;/code&gt; joins words inside one name; &lt;code&gt;-&lt;/code&gt; walks a field within a cell (&lt;code&gt;dec_a3ee-scores-eff&lt;/code&gt;); &lt;code&gt;.&lt;/code&gt; crosses an edge to a neighbor (&lt;code&gt;dec_a3ee.supports&lt;/code&gt;), so the number of periods is the number of graph hops.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Values:&lt;/strong&gt; written &lt;code&gt;field(value)&lt;/code&gt;. A &lt;code&gt;!&lt;/code&gt; inside marks an immutable number (&lt;code&gt;conf(.7!)&lt;/code&gt;); bare is mutable. Types are float for scores and bit for actuators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version:&lt;/strong&gt; &lt;code&gt;@vN&lt;/code&gt; is a point on the supersede chain. &lt;strong&gt;Wildcard:&lt;/strong&gt; &lt;code&gt;.*&lt;/code&gt; fans out over every neighbor through an edge (&lt;code&gt;dec_a3ee.supports.*&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expand-required:&lt;/strong&gt; a leading &lt;code&gt;^&lt;/code&gt; in the mini-index means the cell is superseded, stale, or challenged, and the model must expand it before use (&lt;code&gt;^dec_a3ee ...&lt;/code&gt;). That caret is the dig flag from the loop above, written in one character.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The grammar
&lt;/h3&gt;

&lt;p&gt;The sentences follow HAL's &lt;code&gt;halcmd&lt;/code&gt; style. Tokens are separated by a single space, the name comes first, and connections follow. A quoted &lt;code&gt;"..."&lt;/code&gt; string is one token, exempt from the space rule, used for free text like a title or body. A &lt;code&gt;#&lt;/code&gt; runs to end of line as a comment. Direction with &lt;code&gt;&amp;lt;&lt;/code&gt; and &lt;code&gt;&amp;gt;&lt;/code&gt; is meaningful.&lt;/p&gt;

&lt;p&gt;The sentence forms:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;form&lt;/th&gt;
&lt;th&gt;shape&lt;/th&gt;
&lt;th&gt;example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;wire (net)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;net &amp;lt;signal&amp;gt; &amp;lt;target&amp;gt; &amp;lt;inputs&amp;gt;...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;net eff dec_a3ee &amp;lt; conf calib supports.* contradicts.*&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;set (setp)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;addr&amp;gt; = &amp;lt;value&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dec_a3ee-flags-annexed = true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;schedule (addf)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;addf &amp;lt;op&amp;gt; tick&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;addf contradiction-load tick&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;edge&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;source&amp;gt; &amp;lt;relation&amp;gt;&amp;gt; &amp;lt;target&amp;gt; (&amp;lt;weight&amp;gt;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dec_a3ee supports&amp;gt; dec_signals_a2b7 (+.6)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;render (read)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;handle&amp;gt; "&amp;lt;title&amp;gt;" &amp;lt;field(value)&amp;gt;... &amp;lt;relation&amp;gt;-&amp;gt;&amp;lt;target&amp;gt;(&amp;lt;w&amp;gt;)...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;see below&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  A netlist snippet
&lt;/h3&gt;

&lt;p&gt;Here is one cell rendered in read form, then wired and scheduled in write form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# a cell, rendered: handle, title, scores, then edges
dec_a3ee "add watchdog op" conf(.7!) unc(.10) eff(.61) curr(.9) sal(.5) annexed(0) pinned(0)
  supports&amp;gt; dec_signals_a2b7(+.6)  contradicts&amp;gt; obs_9c1f(-.8)

# wire the effective-confidence signal on it (write form)
net eff dec_a3ee &amp;lt; conf calib supports.* contradicts.*

# declare an edge (direction: &amp;gt; forward a to b, &amp;lt; reverse)
dec_a3ee supports&amp;gt; dec_signals_a2b7 (+.6)

# fire an actuator
dec_a3ee-flags-annexed = true

# schedule a between-turn signal onto the tick
addf contradiction-load tick
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read the top line and the many-writers-one-reader idea becomes concrete. &lt;code&gt;conf(.7!)&lt;/code&gt; is the stated confidence, immutable, what the author claimed. &lt;code&gt;eff(.61)&lt;/code&gt; is the effective confidence, mutable, what is left after calibration plus the &lt;code&gt;+.6&lt;/code&gt; support and the &lt;code&gt;-.8&lt;/code&gt; contradiction are reconciled. The reader gets &lt;code&gt;.61&lt;/code&gt;, not &lt;code&gt;.7&lt;/code&gt;. The &lt;code&gt;net eff&lt;/code&gt; line is the wiring that produces it: the effective signal is a function of the stated confidence, the writer's calibration, and the fan-out over every supporting and contradicting edge.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the language does not do
&lt;/h3&gt;

&lt;p&gt;The grammar wires ops; it does not define their math. The formulas (the effective-confidence reconciliation, the per-type currency decay, the allocation-pressure math) live inside the ops, the way a HAL component's math lives in compiled C and not in the &lt;code&gt;.hal&lt;/code&gt; file. The language only connects pre-built ops to values and to the tick. The one op you can configure without code is the reflex, set with a truth-table personality rather than a formula, so even user-defined boolean logic needs no expression language. That keeps the surface small on purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Status of the language.&lt;/strong&gt; Be clear about what runs. The graph renders to this notation today, but one direction only: graph to text. A parser and loader that read a netlist back into a wired graph are specified here and not yet written. That reader is the next piece, and its acceptance test is a round trip: render the graph, parse it, load it, render again, and require the two renders to match. The model never reads the netlist either way; it reads the compiled slice. The netlist is for human audit and for tooling such as replay, diff, and version control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Borrowing the next layer: components
&lt;/h2&gt;

&lt;p&gt;Everything so far buys one thing: a durable, structured state with a gate on what gets in, where admission has the same shape no matter who wrote it. Every claim, from any actor, any agent, any session, goes through the one firewall and comes out in the one contract. That uniformity is not a nicety. It is the precondition for the next borrow from HAL.&lt;/p&gt;

&lt;p&gt;Here is why. In HAL, a component can read a signal without knowing or caring which component drives it, because every signal is a typed value with one shape. That is the only reason you can wire a deterministic component to a wire and trust what it reads. MAL gets the same guarantee from the admission gate: many writers, one shape. Once a value is guaranteed to have that shape regardless of author, a deterministic subprogram can wire to it and run on it safely. The gate is what turns a pile of claims into clean signals.&lt;/p&gt;

&lt;p&gt;So you can take the second layer of HAL, the components. In HAL a component is a small compiled subprogram that reads signals, computes something, and drives other signals, all scheduled on the thread. In MAL a component is the same idea over memory: a small deterministic program that reads cell values, computes something more involved than a single score, and either writes a derived value back or fires an actuator, scheduled on the tick between turns. No model runs inside one, the same way no model runs inside any op.&lt;/p&gt;

&lt;p&gt;The ones I wired up are the controls-room set: a watch that trips on a threshold, a trend that takes the rate and acceleration over a series of cells, a drift that measures a value against a pinned baseline, a quorum that fires on k-of-m agreement, a score that rolls a metric. The boolean logic is one configurable component, a reflex, that covers the whole and2, or2, xor2 family with a truth table instead of a formula. That is what lets you connect them the way you connect logic on a machine: wire two watches through an or2 so the alert trips if either condition goes bad, latch it so it stays tripped across turns, fan it out to a severity readout. A &lt;strong&gt;tripwire&lt;/strong&gt; is that composition given a job: a deterministic condition that stays silent until it trips, so silence itself becomes the all-good signal, and the only thing that ever speaks up is a real change.&lt;/p&gt;

&lt;p&gt;This is where the memory stops being a place you read from and starts being a system that watches itself. The components run between turns whether or not anyone asked. A threshold passes, a webhook fires, and a decision that drifted out of its known-good band tells you on its own.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;HAL gives a machine reflexes that do not wait for the operator. The same components, one layer up, give the memory reflexes that do not wait for the model.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  It is not rebuilt every turn
&lt;/h2&gt;

&lt;p&gt;A fair worry about a stateless model is that it has to stand the whole apparatus up again on every fresh turn. It does not. The system persists in the store and in the deterministic tick, both of which run between turns with no model involved. The only thing that is fresh each turn is the model's working context, and rebuilding that context is exactly the cost MAL removes. Instead of re-deriving state from scratch or re-reading raw transcripts, the model reads back a thin, pre-digested, trust-weighted slice: the mini-index first, then selective expansion. And because the model wrote those cells in the first place, reading them re-evokes its earlier reasoning instead of reconstructing it cold.&lt;/p&gt;

&lt;h2&gt;
  
  
  The graph boots itself
&lt;/h2&gt;

&lt;p&gt;A fresh MAL graph starts from a deterministic 10-cell bootstrap, then the normal loop takes over and init never fires again for that graph.&lt;/p&gt;

&lt;p&gt;Cells 1 to 5 are the system layer, the constitution: auto-written, locked, pinned, immutable, and identical in every graph.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;purpose&lt;/li&gt;
&lt;li&gt;method&lt;/li&gt;
&lt;li&gt;map (the MAL structure itself: addressing, cell anatomy, edge semantics)&lt;/li&gt;
&lt;li&gt;hooks (the lifecycle: orient, push, write-back, tick, the compaction boundary)&lt;/li&gt;
&lt;li&gt;expectations (the behavioral contract: wire your edges, pick the right kind, supersede on real change, confidence is recorded and weighed, do not assert from unchecked memory, dig flagged cells)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cells 6 to 10 are the foundation, the project charter: answered one question at a time by the user, and mutable.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;objective&lt;/li&gt;
&lt;li&gt;constraints&lt;/li&gt;
&lt;li&gt;risks&lt;/li&gt;
&lt;li&gt;success criteria&lt;/li&gt;
&lt;li&gt;carried context&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Putting the operating manual in the graph as cells, rather than as a string baked into a hook, is what lets it survive a context compaction and be re-evoked afterward. The map being cell 3 is the point: the structure teaches itself from inside the store it describes.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it came together
&lt;/h2&gt;

&lt;p&gt;Two things had to meet for this to work, and they came from opposite directions.&lt;/p&gt;

&lt;p&gt;The first was the problem, seen from the inside. Recall was not built as a database for me to query. It was built for the agent. It started by asking the model what it actually needed in order to remember well and to trust what it remembered, and the answers are the whole design: typed claims with a calibrated confidence, supersession instead of overwrite, and a record of what contradicts what. Earlier versions were far more ambitious and sprawling; the part that survived and narrowed into Recall was the memory core. Most pull-based memory tools inherited the human metaphor of a database you go and search. This came from asking the thing that has to live in the memory what would keep it honest.&lt;/p&gt;

&lt;p&gt;The second was the structure, brought in from another trade. I already knew HAL cold from years on LinuxCNC, and when I sketched how to address and wire a memory graph, it landed on the same path-addressing shape HAL uses. Recalling HAL from the shop and deriving the addressing for memory met in the same place. Two independent routes arriving at one design is about the strongest signal you get that the design is sound.&lt;/p&gt;

&lt;p&gt;After that it was diagnostic work plus acceleration. I used the troubleshooting habits I lean on for a machine crash to find where the memory state was breaking, and I used AI to fill the gaps in what I did not know and to write the harder code syntax. The concept is mine and comes off the shop floor. The speed of building it came from the same kind of system it was built to improve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Under the hood: the four boundaries
&lt;/h2&gt;

&lt;p&gt;This part is a prototype disclosure, not a reproducible benchmark. The snippets below are from the running Recall v5 source, trimmed for readability with elisions marked; the formulas and signatures are verbatim. They show the four boundaries where the design either holds or it does not: Recall sits upstream of the model, the read is a mini-index then a selective expand, every write goes through one gate, and the scores recompute deterministically with no model in the loop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recall is upstream of the model.&lt;/strong&gt; Before the model runs, the prompt's objective is compiled into a Recall packet and merged into the text the model receives. The packet is built first, so the model sees reconciled memory before it acts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildPromptContextPush&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;objective&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ContextCompileOptions&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;DirectiveOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;PromptContextPush&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;packet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compileContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;objective&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;directive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;recallDirectiveBlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expansionRequired&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;staleOrLowTrust&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;conflicts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[Recall context push for this prompt]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;directive&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trimEnd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;formatContextPacket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;expansionRequired&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;EXPAND REQUIRED: conflicts or low-trust cells are present; inspect relevant handles before relying on them.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Use expansion_handles only when exact evidence matters.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;objective&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;directive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expansionRequired&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;The Codex adapter wires Recall's MCP server into Codex so the same packet and tools are reachable there; the push itself is platform-neutral.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Compile the mini-index.&lt;/strong&gt; The prompt becomes a ranked seed set, one mini-index line per hit, and a cell that needs review carries the expand flag. &lt;code&gt;compileContext&lt;/code&gt; wraps this and trims the packet to a word budget (the 900 in the screenshot).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;CompileResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;renderMiniIndexLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requiresReview&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lines&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;&lt;strong&gt;2. Expand selected cells.&lt;/strong&gt; Mini-index first, selective expansion second. A handle (a full id, or &lt;code&gt;id#field.path&lt;/code&gt;) opens exactly one cell plus its neighbor links, never the whole graph.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;inspectCell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;CellContext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseExpansionHandle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByHandle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unknown cell: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;neighbors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;neighbors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;incoming&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;neighbors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;in&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outgoing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;neighbors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;out&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// ... footprint (word and byte counts), optional field preview ...&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;outgoing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* footprint, */&lt;/span&gt; &lt;span class="nx"&gt;expansionHandles&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;&lt;strong&gt;3. Write through the admission gate.&lt;/strong&gt; The model hands in a claim (a kind, a title, a body), one confidence number, and the edges it intends. Every author runs the same pipeline: validate, screen for secrets, attenuate unsupported confidence, build the cell, then fold in the actor's calibration to get effective confidence. The model never formats the cell or computes a score.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;WriteProposal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// (0, 1], required, no default&lt;/span&gt;
  &lt;span class="nl"&gt;edges&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}[];&lt;/span&gt;
  &lt;span class="c1"&gt;// ... topics, entities, sourceRefs, operation, origin, verification ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;admit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WriteProposal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AdmitContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}):&lt;/span&gt; &lt;span class="nx"&gt;AdmissionResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validateProposal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// R0 schema; reject on any structural issue&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;accepted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="na"&gt;attenuations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;screenSecrets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;           &lt;span class="c1"&gt;// reject if a credential pattern is present&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;accepted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="na"&gt;attenuations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;factor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;calibrationFactor&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// 0.5..1 from the actor's track record; 1 = neutral&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;att&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;attenuateConfidence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// cap unsupported high confidence&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;buildCell&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;proposal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;att&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;confidence&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actorCalibration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;effective&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;effectiveConfidence&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;stated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;att&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;calibration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;supportMass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;challengeMass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// with a store: dedup, apply supersedes edges, recompute neighbors' effective ...&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;accepted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="na"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;att&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;attenuations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;att&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attenuations&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;&lt;strong&gt;4. Recompute on the tick, with no model.&lt;/strong&gt; This is the line between MAL and a plain memory database. Between turns, every active cell decays its currency from its own timestamp and recomputes its effective confidence from current support and contradiction mass. Pinned cells are exempt from decay, and a tick never counts as reinforcement.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// effective = clamp01(stated*calibration + 0.15*tanh(support) - 0.6*tanh(challenge))&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;effectiveConfidence&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;stated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;calibration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;supportMass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;challengeMass&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;clamp01&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;stated&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;calibration&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tanh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;supportMass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;0.6&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tanh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;challengeMass&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// currency = cFloor + (c0 - cFloor) * exp(-dt/tau)   (dt and tau in days)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;c0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tau&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cFloor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cFloor&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;cFloor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;tau&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// the between-turn deterministic tick (HAL's "thread"); no LLM runs here&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;recompute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Cell&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scores&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pinned&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;DAY_MS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;c0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currencyC0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;tau&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TAU_DAYS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stability&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;neighborMass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;effective&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;effectiveConfidence&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;stated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;calibration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actorCalibration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;supportMass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;supportMass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;challengeMass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;challengeMass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scores&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// updatedAt preserved: a tick is not a reinforcement&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The verifier.&lt;/strong&gt; A functional verifier, &lt;code&gt;npm run verify:recall-panel&lt;/code&gt;, was added for the Recall panel and passes. It checks that the panel is correctly wired to the graph (the SQLite-backed store and the compile, search, and write controls), not that it clears any performance number. Read it as a wiring check, not a benchmark.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recall, MAL, and AIDDE
&lt;/h2&gt;

&lt;p&gt;A quick map of the three names, because they get used together and they are not the same thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recall is the programming foundation.&lt;/strong&gt; At the bottom is a local-first memory substrate: a SQLite-backed graph of typed cells, an admission gate every write passes through, calibrated confidence, supersession instead of overwrite, and a compile path that returns a ranked, budgeted slice. That layer ships as a package and runs today. It is the working base everything else stands on, and it is what the four boundaries above are made of.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MAL is what that foundation evolves into.&lt;/strong&gt; v5 recasts the same primitives as a hardware abstraction layer for memory: a cell field is a pin, an addressable value is a signal, an op is a component, the between-turn tick is the thread, and the rendered graph is a netlist. On top of the proven store it adds the deterministic op and signal layer and the addressing language. The four boundaries earlier in this post are MAL running. The netlist language is MAL specified, with the reader still to come.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AIDDE is where it runs.&lt;/strong&gt; The screenshot at the top is AIDE, an agent workspace with Recall embedded as a panel. The agent compiles, searches, and writes the same SQLite graph from inside the editor, against a live cell count and a word budget, so the memory layer is not a side service the agent calls out to; it sits in the workspace the agent already works in. MAL is the layer that panel stands on.&lt;/p&gt;

&lt;p&gt;So Recall is the substrate, MAL is the abstraction layer it grows into, and AIDE is the workspace that puts both in front of a working agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this shape holds up
&lt;/h2&gt;

&lt;p&gt;Two things make MAL age well. It rides capability gains for free: a stronger model uses the same layer better with no rewrite, and a weaker model still gets the deterministic floor underneath it. And it keeps the expensive, stateful, always-on work in deterministic code where it belongs, leaving the model to do the one thing only it can do, which is to state a calibrated claim and judge relevance.&lt;/p&gt;

&lt;p&gt;That is the whole bet, and it comes straight off the shop floor. A machine does not stay accurate because the controller is smart. It stays accurate because the wiring is legible, the signals are reconciled, the bad state gets caught and replaced instead of silently riding along, and a scheduler keeps the picture current between every move.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;MAL is that discipline, applied to an AI's memory. HAL one layer up, over memory instead of motors.&lt;br&gt;
if you want to try Recall it is standalone and OSS &lt;a href="https://github.com/H-XX-D/recall-memory-substrate" rel="noopener noreferrer"&gt;https://github.com/H-XX-D/recall-memory-substrate&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The AIDDE (Artificial Intelligence Driven Development Environment)is a Codex Claude SDK native bring your subscription development environment that shifts the old IDE with AI chat to a High level view cockpit where you specify design, direct intent, monitor changes, audit actions control permissions and access in real time across a codebase. Beta is done and if your interested ask in the comments for a link to the Alpha&lt;/p&gt;

</description>
      <category>ai</category>
      <category>buildinpublic</category>
      <category>llm</category>
      <category>devops</category>
    </item>
    <item>
      <title>Claude, Codex, Gemini, Grok: A Field Report on Agentic Memory Write Reliability</title>
      <dc:creator>Todd Hendricks</dc:creator>
      <pubDate>Fri, 26 Jun 2026 12:55:42 +0000</pubDate>
      <link>https://dev.to/hendrixx/memory-adherence-is-a-systems-problem-so-which-model-lets-you-build-the-system-3ien</link>
      <guid>https://dev.to/hendrixx/memory-adherence-is-a-systems-problem-so-which-model-lets-you-build-the-system-3ien</guid>
      <description>&lt;p&gt;I received a comment that felt like a good way to end a series and start another. They asked me if I could notice a difference in the hyperscale frontier models. This post is a breakdown of where I am at, the carve-outs, and the direction this work is headed I will attempt to convey and start formalizing. a shared mental model and a consistent vernacular.&lt;/p&gt;

&lt;p&gt;There are differences, but they are not really about the model. They are about how much of the turn each family lets you control. If adherence is a systems problem, then the thing that actually decides write reliability is which family hands you enough control surface to build the system.&lt;/p&gt;

&lt;p&gt;Treat this as a field report, not a benchmark, and an early one. I have not pushed every family equally hard, and that matters for how much weight the comparison can carry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude is where I have gone the deepest
&lt;/h2&gt;

&lt;p&gt;This is the family I have cut my teeth on the most, invested the most time with, so weigh the claim with that in mind. What I can say is that Claude gives you a full ladder, from shallow to deep, and you can stop at whatever rung the job needs.&lt;/p&gt;

&lt;p&gt;The shallow rung is nudges: the settings page and system instructions. This is the weakest form, and it is the one that decays, the same “tell it harder” failure I wrote about last time. It helps a little, and it does not hold.&lt;/p&gt;

&lt;p&gt;Above that are skills and hooks. This is where the concept of a Push vs. Pull agentic memory scaffolding and instrumentation Hooks are the first rung, where adherence stops being a request and becomes an event: something fires at the start of the turn, at write time, refusing to end the turn return the required data shaped. They can also be difficult to structure correctly. I had good results with loose pseudo code. it was generic enough it return wel&lt;/p&gt;

&lt;p&gt;The deep rung is the SDK. With it, you get targeted control of the model’s turn, the whole prompt-to-response lifecycle, beginning to end. This is where the read reason response write wiring carries weight. Say that 5 times fast.&lt;/p&gt;

&lt;p&gt;The point is not that any single rung is magic. It is that Claude lets you go as deep as the reliability you need, and the deeper you go, the more deterministic the write becomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT and Codex are close, through AGENTS.md
&lt;/h2&gt;

&lt;p&gt;Codex was a lot easier than I expected, because its instruction set is the AGENTS.md file. That one anchor did most of the work, and the net result was only slightly less consistent than Claude.&lt;/p&gt;

&lt;p&gt;Honest caveat: I have not dug into the Codex SDK yet. So the ceiling there is probably higher than what I have measured, and the real gap to Claude may be smaller than it looks right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gemini and Grok lean on their own memory
&lt;/h2&gt;

&lt;p&gt;The Gemini and Grok CLIs are a different story. They seem to want to do the least amount of work possible, and they lean on their own KV and incoming user prompts more than they reach for an outside store. You end up working against a default that would rather not call your database at all.&lt;/p&gt;

&lt;p&gt;The exception is WebSearch, and it comes back noisy and minimal, and it gets actively counterproductive when it does surface strongly correlated evidence that’s divergent from your store, because then the model over-trusts the search and skips the store it should have read. Getting real adherence out of those two means digging into their architectures to optimize for it, and that is still on my horizon,## Why this is a field report and not a benchmark yet&lt;/p&gt;

&lt;p&gt;Building SENTINEL, a real benchmarking suite for this, is one of my highest priorities right now. The honest problem is that most memory systems do not expose the turn the way you would need to in order to measure whether a write happened at the right moment, so you cannot make them play the same game. The way I keep it fair is to grade what each system’s outputs actually demonstrate, on a capability ladder, rather than the levers it was never built to expose. A system that does not surface something scores lower on that axis without being punished for it, and I say plainly which axis is push and which is pull, so a gap reads as a different shape, not a worse one. The full design is its own post.&lt;/p&gt;

&lt;p&gt;A benchmark value only means something if there’s an aggregate baseline and a calibrated anchor. A bench that only your system can run is not a benchmark; it is a demo attributing the result to the wrong layer, blaming the store when the model just queried it badly, or crediting the system. So devising ways to avoid bias, cold start cutoffs, normalizations for balancing the different ways correlated axis report their values, scale parity, outlier skew, and correct attribution comes first, and then the leaderboard means something.&lt;/p&gt;

&lt;p&gt;Veni, vidi, vici.&lt;/p&gt;

&lt;p&gt;“I came, I saw, I conquered.”&lt;/p&gt;

&lt;p&gt;—Attributed to Julius Caesar after the Battle of Zela, 47 BC&lt;/p&gt;

&lt;p&gt;Sources: Plutarch, Life of Caesar 50.3; Suetonius, Divus Julius 37.2.&lt;/p&gt;

&lt;p&gt;Quotng Julious Ceaser without projecting hubris is hard to earn. The rendering from the Latin to English carries little of the same weight, effort involved, or consequence of failure in the attempt. I am not claiming victories yet because it’s apples to orange homeboy, I need like a handicapping algorithm&lt;/p&gt;

&lt;p&gt;It feels like it is more difficult to create an honest comparison between separate but similar function systems than the engineering of the thing being compared.&lt;/p&gt;

&lt;p&gt;The model is not the variable that matters most for write reliability. The control surface is. The deterministic parts of a good memory system, the validation gate, and the demotion math, hold the same on any of these. What changes across families is how much of the turn you are allowed to act on and instrument the input-output mechanics. So far, Claude exposed the whole lifecycle, Codex gave a strong instruction anchor through AGENTS.md, and Gemini and Grok leaned hardest on their own context. I went testicle deep on Claude’s hooks and SDK, scratching the surface on Codex, its SDK next, and I have barely pushed Gemini or Grok past their defaults. Subjective verdict on which family is most controllable. Making that comparison fair, with equal effort and correct attribution, is exactly what SENTINEL is for.&lt;/p&gt;

&lt;p&gt;So “which model writes more reliably” turns out to be the wrong question. The real one is which model lets you build the most system around the userprompt_init read write, and turn_end mechanics. That was his comment, followed by the floor.&lt;/p&gt;

&lt;p&gt;github.com/H-XX-D/recall-memory-substrate&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>"Agent Memory adherence is a systems problem. So which model lets you meddle with that system?"</title>
      <dc:creator>Todd Hendricks</dc:creator>
      <pubDate>Fri, 26 Jun 2026 12:55:42 +0000</pubDate>
      <link>https://dev.to/hendrixx/memory-adherence-is-a-systems-problem-so-which-model-lets-you-build-the-system-4lf4</link>
      <guid>https://dev.to/hendrixx/memory-adherence-is-a-systems-problem-so-which-model-lets-you-build-the-system-4lf4</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/krupali_gadhiy"&gt;https://dev.to/krupali_gadhiy&lt;/a&gt; Left a comment that felt like a good way to end this series. They asked me if I could notice a difference in the hyperscale frontier models. This post is a breakdown of where I am at, the carve-outs, and direction. &lt;/p&gt;

&lt;p&gt;There are differences, but they are not really about the model. They are about how much of the turn each family lets you control. If adherence is a systems problem, then the thing that actually decides write reliability is which family hands you enough control surface to build the system in the first place.&lt;/p&gt;

&lt;p&gt;Treat this as a field report, not a benchmark, and an early one. I have not pushed every family equally hard, and that matters for how much weight the comparison can carry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude is where I have gone the deepest
&lt;/h2&gt;

&lt;p&gt;This is the family I have spent the most time with, so weigh the claim with that in mind. What I can say is that Claude gives you a full ladder, from shallow to deep, and you can stop at whatever rung the job needs.&lt;/p&gt;

&lt;p&gt;The shallow rung is nudges: the settings page and system instructions. This is the weakest form, and it is the one that decays, the same "tell it harder" failure I wrote about last time. It helps a little, and it does not hold.&lt;/p&gt;

&lt;p&gt;Above that are skills and hooks. Hooks are the first rung where adherence stops being a request and becomes an event: something fires at the start of the turn, at write time, at the end, whether the model felt like it or not. They work. They can also be finicky to get right.&lt;/p&gt;

&lt;p&gt;The deep rung is the SDK. With it, you get targeted control of the model's turn, the whole prompt-to-response lifecycle, beginning to end. This is where the read reason response write wiring carries actual weight. Nothing else I tested hands you the full lifecycle like this.&lt;/p&gt;

&lt;p&gt;The point is not that any single rung is magic. It is that Claude lets you go as deep as the reliability you need, and the deeper you go, the more deterministic the write becomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT and Codex are close, through AGENTS.md
&lt;/h2&gt;

&lt;p&gt;Codex was a lot easier than I expected, because its instruction set is the AGENTS.md file. That one anchor did most of the work, and the net result was only slightly less consistent than Claude.&lt;/p&gt;

&lt;p&gt;Honest caveat: I have not dug into the Codex SDK yet. So the ceiling there is probably higher than what I have measured, and the real gap to Claude may be smaller than it looks right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gemini and Grok lean on their own memory
&lt;/h2&gt;

&lt;p&gt;The Gemini and Grok CLIs are a different story. They seem to want to do the least amount of work possible, and they lean on their own KV and incoming user prompts more than they reach for an outside store. You end up working against a default that would rather not call your database at all.&lt;/p&gt;

&lt;p&gt;The exception is WebSearch, and it comes back noisy and minimal, and it gets actively counterproductive when it does surface strongly correlated evidence that's divergent from your store, because then the model over-trusts the search and skips the store it should have read. Getting real adherence out of those two means digging into their architectures to optimize for it, and that is still on my horizon, not something I have solved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is a field report and not a benchmark yet
&lt;/h2&gt;

&lt;p&gt;Building SENTINEL, a real benchmarking suite for this, is one of my higher priorities right now. The honest problem is that most memory systems do not expose the turn the way you would need to in order to measure whether a write happened at the right moment, so you cannot make them play the same game. The way I keep it fair is to grade what each system's outputs actually demonstrate, on a capability ladder, rather than the levers it was never built to expose. A system that does not surface something scores lower on that axis without being punished for it, and I say plainly which axis is push and which is pull, so a gap reads as a different shape, not a worse one. The full design is its own post.&lt;/p&gt;

&lt;p&gt;A benchmark value only means something if there's an aggregate baseline and a calibrated anchor. A bench that only your system can run is not a benchmark; it is a demo attributing the result to the wrong layer, blaming the store when the model just queried it badly, or crediting the system. So devising ways to avoid bias, cold start cutoffs, normalizations for balancing the different ways correlated axis report their values, scale parity, outlier skew, and correct attribution comes first, and then leaderboard means something. &lt;/p&gt;

&lt;p&gt;Veni, vidi, vici.&lt;br&gt;
“I came, I saw, I conquered.”&lt;br&gt;
—Attributed to Julius Caesar after the Battle of Zela, 47 BC&lt;br&gt;
Sources: Plutarch, Life of Caesar 50.3; Suetonius, Divus Julius 37.2.&lt;/p&gt;

&lt;p&gt;Quotiong Julious Ceaser without projecting hubris is hard to earn. The rendering from the Latin to modern English carries little of the same weight,  effort involved, or consequence of failure at the attempt.&lt;/p&gt;

&lt;p&gt;To clarify, get some integrity back.  I set the claim as the floor for participation in the conditional measure, not as proof of conquest. The battlefield is broad, crowded, and still very much contested.&lt;/p&gt;

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

&lt;p&gt;It feels like it is more difficult to create an honest comparison between separate but similar function systems than the engineering of the thing being compared to something else.  &lt;/p&gt;

&lt;p&gt;The model is not the variable that matters most for write reliability. The control surface is. The deterministic parts of a good memory system, the validation gate, and the demotion math, hold the same on any of these. What changes across families is how much of the turn you are allowed to act on and instrument the input-output mechanics. So far, Claude exposed the whole lifecycle, Codex gave a strong instruction anchor through AGENTS.md, and Gemini and Grok leaned hardest on their own context. I went testicle deep on Claude's hooks and SDK, scratching the surface on Codex, its SDK next, and I have barely pushed Gemini or Grok past their defaults. Subjective verdict on which family is most controllable. Making that comparison fair, with equal effort and correct attribution, is exactly what SENTINEL is for.&lt;/p&gt;

&lt;p&gt;So "which model writes more reliably" turns out to be the wrong question. The real one is which model lets you build the most system around the userprompt_init read write, and turn_end mechanics. That was his comment, followed by the floor.&lt;/p&gt;

&lt;p&gt;github.com/H-XX-D/recall-memory-substrate&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>You designed the best Agent memory layer. Now, if only it would just use it RIGHT!!!</title>
      <dc:creator>Todd Hendricks</dc:creator>
      <pubDate>Wed, 24 Jun 2026 12:34:36 +0000</pubDate>
      <link>https://dev.to/hendrixx/you-designed-the-best-agent-memory-layer-now-if-only-it-would-just-use-it-right-bkm</link>
      <guid>https://dev.to/hendrixx/you-designed-the-best-agent-memory-layer-now-if-only-it-would-just-use-it-right-bkm</guid>
      <description>&lt;p&gt;You finally got your system to beat Mem0 on its own benchmark. Spin up a fresh DB. Things are good, confabs down, productivity is up. A week or two passes, and it's a goldfish. Open your store, and it's the Red Wedding in there. Your agent has either been saving nothing you want, half what you need, something about nothing, OR EVERYTHING! C'Est La Vie.&lt;/p&gt;

&lt;p&gt;I'm going to try to convince you that I got it figured out; if not, maybe it will help you get your model under control. Cause I promise, I hit every failure mode building Recall, a local active memory outside of an agent's control.&lt;/p&gt;

&lt;p&gt;The failure modes&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Quietly not writing. You ask the model to remember something durable. It says "noted" and moves on. Nothing lands in the store. No error, no warning, just a turn that ended without a write. This is the most common one and the hardest to catch, because from inside the conversation, everything looks fine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Half writing. The model writes one fact and drops the three that mattered as much. Or it writes the headline and not the reasoning behind it, so a later session gets a claim with no support. The store fills up, but with fragments you cannot act on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Writing the wrong thing. If your memory is structured (required fields, typed records, confidence, evidence links the model fills the structure out wrong. It puts a passing observation where a decision should go, leaves the confidence blank, or points a "this corrects that" link at a free-text label instead of the actual record. The schema is satisfied on paper and is useless in practice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Writing everything. The overcorrection. The model dumps the whole turn into the store: every aside, every dead end, and sometimes a secret it should never have persisted. Now you have a second problem on top of the first, because data buried is the same as data corrupted&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why this happens&lt;/p&gt;

&lt;p&gt;The model has no stake in the future session. Inside a single turn, the context window already holds everything the model needs. Writing to an external store is, from the model's point of view, work that pays off for someone else: a future session it will never experience as itself. It optimizes for finishing the turn in front of it, and the write is the first thing to get skipped.&lt;/p&gt;

&lt;p&gt;There is usually a competitor. If your agent runs inside a host like Claude Code, that host probably ships its own memory feature, wired into the base system prompt. When two "save this" pathways exist, the native one wins, because it is closer to the model's root instructions than your skill is. Your memory system can be fully armed and still lose every write to the built-in one. I confirmed this with a single-variable test: with the native feature on, the model wrote the user's facts to flat files every time, no matter how loudly my system asked for the structured store.&lt;/p&gt;

&lt;p&gt;Writing is harder than reading. Reading is free-form: ask a question, get text. A structured write means satisfying a schema, and the moment the model meets friction, it takes the path of least resistance, which is to skip the write or to dump unstructured prose. Friction is not a small factor here.&lt;/p&gt;

&lt;p&gt;There is no feedback in the loop. When the model writes the wrong structure and the write just fails silently, nothing teaches it otherwise. It shrugs and continues. Adherence with no signal is a coin flip; the model loses a little more often every turn.&lt;/p&gt;

&lt;p&gt;Three solutions that do not work&lt;/p&gt;

&lt;p&gt;Tell it harder in the prompt. The instinct is to add "ALWAYS write durable facts to memory" in capital letters and call it done. This is prompt-nagging. It competes with the native pathway and loses; it costs tokens on every turn, and it decays: the model obeys for a few turns, then rationalizes its way out ("this is just a simple note", "I will write it later"). It is also brittle across models, so the day you switch models, you start over.&lt;/p&gt;

&lt;p&gt;Log everything and clean up later. If the model does not decide what is durable, make it write all of it and curate afterward. This trades the empty-store problem for a curation-debt problem, defeats the entire point of a schema, and is the exact path that leaks secrets into the store. You have not solved adherence. You have moved the failure downstream and added a cleanup job you will never get to.&lt;/p&gt;

&lt;p&gt;Fine-tune a model to obey the schema. Reach for training, and you get a heavy, expensive fix that is brittle to schema changes, locks you to one model, and still does not address the competing native feature. It is a large hammer for what turns out to be a wiring problem, and the wiring problem is sitting right there, unsolved underneath it.&lt;/p&gt;

&lt;p&gt;Two easy fixes that actually help&lt;/p&gt;

&lt;p&gt;Turn off the competitor. This is the single change that helps most, and it is one line. If the host ships its own auto-memory, disable it so there is only one "save this" pathway in the building. In Claude Code that is CLAUDE_CODE_DISABLE_AUTO_MEMORY=1. With the competitor gone, a properly armed agent reaches for the structured store on its own, because nothing is shadowing it anymore. Most of the "quietly not writing" problem was never the model refusing. It was the model writing somewhere else.&lt;/p&gt;

&lt;p&gt;Lower the write friction. Give the model a small helper that takes only a few inputs it can judge (the record type, a title, a body, a confidence, a couple of topics) and emits the schema-valid object for it. The model stops hand-assembling a structured payload and picks the two or three load-bearing fields instead. In Recall, this removed the schema-friction tax on the first write of every session, which was where most of the "writing the wrong thing" came from. The model was not being careless. It was being asked to do clerical work under load, and it cut corners exactly where you would expect.&lt;/p&gt;

&lt;p&gt;These two get you a long way. They do not, by themselves, guarantee the write happens at the right moment, or that a correction supersedes the old value instead of sitting next to it. For that, you need the system, not the model, to carry the discipline.&lt;/p&gt;

&lt;p&gt;The real fix: Ta dun Ta da hooks&lt;/p&gt;

&lt;p&gt;The durable answer is to stop relying on the model and move the adherence burden onto hooks that trigger from events that perform actions between the beginning and end of that forward pass.&lt;/p&gt;

&lt;p&gt;At the start of a turn, inject the memory. A hook on session start or on prompt submit that says, in-band, "the memory store exists, read it before you rely on recollection," and then hands the model a mini-index of what is already stored that is relevant to this prompt: ids and titles, nothing heavy. This does two things at once. It makes reading the default instead of an optional courtesy, and it kills the "assert from memory" and "ask the user a thing they already told you" failures by showing the model what is on the shelf. Reading first is also what makes writing meaningful: a model that has seen the current state writes the resolution, not a duplicate.&lt;/p&gt;

&lt;p&gt;At write time, enforce the structure in-band. Put a validation gate in front of the store so a malformed or secret-shaped write bounces with a readable error the model can fix on the spot, instead of failing silently or corrupting the store. This is where "writing the wrong thing" and "writing everything" get caught. The schema stops being a thing the model has to remember to honor and becomes a thing the system guarantees. The same gate is where you reject secrets, so a leaked token never reaches the graph in the first place.&lt;/p&gt;

&lt;p&gt;At the end of a substantive turn, nudge the write. A stop hook that checks whether the turn produced something durable and nothing got written, and prompts for it. This closes the "quietly not writing" gap from the other side: even if the model forgot, the system asks once before the turn ends.&lt;/p&gt;

&lt;p&gt;The shape of the fix is the same in all three places. The model's job shrinks to the part only it can do, which is judging what is durable and how confident it is. Everything mechanical (when to read, when to write, what shape the write takes&lt;/p&gt;

&lt;p&gt;There is a small equation hiding in here that I found the hard way. Obedience is the product of three things: the model's intent on the turn, the arming you put in place (the skill, the helper, the hooks). That is why "tell it harder" fails on its own; it is the factor most likely to be silently zero while you debug the other two.&lt;/p&gt;

&lt;p&gt;What the future looks like&lt;/p&gt;

&lt;p&gt;Business as usual, and your memory system fails in the most expensive way possible: it looks like it is working. The store exists, the writes occasionally happen, and you do not notice until a session confidently tells you something three versions out of date, or asks you a question you answered 10minutes prior, or starts cold and re-derives what the last run already knew. The store becomes a graveyard you stop trusting, and you quietly go back to pasting context in by hand. You are now maintaining a database for nothing, which is strictly worse than not having one.&lt;/p&gt;

&lt;p&gt;Fix it, and the thing compounds. Sessions inherit. The model reads before it acts, writes the resolution when it corrects itself, and supersedes the old value instead of stacking a new one next to it, so the current answer is always on top and the history still survives underneath. The memory gets more useful the more you use it, because every correction makes the store sharper instead of noisier. You stop re-explaining your own project to your own tools. That was the entire promise of agentic memory,&lt;/p&gt;

&lt;p&gt;I didn't talk about RAG, separate embedding models designed for retrieval, and only touched on automemory because. I'm saving some sauce for the ribs.&lt;/p&gt;

&lt;p&gt;I've spent the better part of five or six months now putting the work in on , Recall, a push-style memory substrate for agents: structured records, computed and calibrated confidence, directional value updates with provenance and the hooks described above. It's open, any and all feedback of its behavior on other systems is appreciated. Thank you for your time and the read. &lt;a href="https://github.com/H-XX-D/recall-memory-substrate" rel="noopener noreferrer"&gt;https://github.com/H-XX-D/recall-memory-substrate&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>buildinpublic</category>
      <category>developer</category>
    </item>
    <item>
      <title>We have all felt the pain of information lost due to there just being too much of it with no structure besides the filename and grep</title>
      <dc:creator>Todd Hendricks</dc:creator>
      <pubDate>Mon, 22 Jun 2026 23:55:19 +0000</pubDate>
      <link>https://dev.to/hendrixx/we-have-all-felt-the-pain-of-information-lost-due-to-there-just-being-too-much-of-it-with-no-fa0</link>
      <guid>https://dev.to/hendrixx/we-have-all-felt-the-pain-of-information-lost-due-to-there-just-being-too-much-of-it-with-no-fa0</guid>
      <description>&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://dev.to/hendrixx/confidently-wrong-is-worse-than-i-dont-know-22ia" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" 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%2Fcvbh2pngyr3paspgulz4.png" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://dev.to/hendrixx/confidently-wrong-is-worse-than-i-dont-know-22ia" rel="noopener noreferrer" class="c-link"&gt;
            Confidently wrong is worse than "I don't know" - DEV Community
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Someone left a comment on my last post and then deleted it before I could reply. I am going to answer...
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" 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%2F8j7kvp660rqzt99zui8e.png"&gt;
          dev.to
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Confident confabulation is a variance signal, not a direction</title>
      <dc:creator>Todd Hendricks</dc:creator>
      <pubDate>Mon, 22 Jun 2026 14:31:09 +0000</pubDate>
      <link>https://dev.to/hendrixx/confident-confabulation-is-a-variance-signal-not-a-direction-1a4c</link>
      <guid>https://dev.to/hendrixx/confident-confabulation-is-a-variance-signal-not-a-direction-1a4c</guid>
      <description>&lt;p&gt;&lt;em&gt;Detecting the hard case of LLM hallucination from generation dynamics, and why magnitude beats direction.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The hard case in hallucination detection is &lt;strong&gt;confident confabulation&lt;/strong&gt;: plausible, fluent, wrong, and produced with no hesitation. Methods that key on the model "sounding unsure" are weakest exactly here.&lt;/li&gt;
&lt;li&gt;Across ~124 prompts, the &lt;strong&gt;mean&lt;/strong&gt; internal response to confident confabulation is statistically indistinguishable from truth. The model does not move in a consistent "lying direction."&lt;/li&gt;
&lt;li&gt;What separates the two is &lt;strong&gt;magnitude and variance&lt;/strong&gt;: confabulation produces larger, more dispersed swings in the model's internal trajectory. The variance ratio between confabulation and truth is roughly &lt;strong&gt;7×&lt;/strong&gt; on the representational-shift channel (Cohen's &lt;em&gt;d&lt;/em&gt; ≈ 0.58, &lt;em&gt;p&lt;/em&gt; ≈ 0.005).&lt;/li&gt;
&lt;li&gt;The variability &lt;strong&gt;scales with fabrication intensity&lt;/strong&gt; (a dose-response), which is the strongest evidence that this is a property of confabulation and not noise.&lt;/li&gt;
&lt;li&gt;Practical upshot: detect &lt;strong&gt;instability&lt;/strong&gt;, not a direction; integrate the signal over the generated span; and couple the detector to an intervention rather than using it as a standalone gate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The hard case
&lt;/h2&gt;

&lt;p&gt;It is by now well established that a model's internal states carry information about whether its output is true: the line of work running from Azaria &amp;amp; Mitchell's "the internal state of an LLM knows when it's lying" through to more recent results showing that truthfulness is encoded in activations and that models often "know more than they show." It's also become standard to separate &lt;em&gt;confabulation&lt;/em&gt; (arbitrary, plausible, confidently-wrong generation) from the broader grab-bag of "hallucination," following Farquhar et al.'s &lt;em&gt;Nature&lt;/em&gt; work on semantic entropy.&lt;/p&gt;

&lt;p&gt;The uncomfortable subcase is confident confabulation. Uncertainty- and dispersion-based detectors work well when the model is visibly unsure. But the failure that actually burns people in production (a fabricated citation, a confidently invented dose, a made-up precedent) arrives with the same surface confidence as a correct answer. The question I wanted to answer is narrow: &lt;strong&gt;when a model confabulates confidently, does anything in its generation dynamics give it away?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I measured
&lt;/h2&gt;

&lt;p&gt;I tracked two internal observables around the answer span:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;An entropy / predictive-uncertainty signal&lt;/strong&gt; (call it Δentropy): how the model's output distribution shifts as it produces the answer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A representational-shift signal&lt;/strong&gt; (Δcosine): how much the model's internal representation moves step to step.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A note on dimensionality, since it matters for honest reporting: I originally tracked four signals, but two pairs turned out to be perfectly correlated (&lt;em&gt;r&lt;/em&gt; = 1.000), which means they're affine images of each other, not independent measurements. So there are really &lt;strong&gt;two independent axes&lt;/strong&gt;, an uncertainty axis and a representational-shift axis, and I report on those.&lt;/p&gt;

&lt;p&gt;The dataset is ~124 prompts spanning seven domains (science, history, medical, legal, technical, math, geography) and five &lt;strong&gt;fabrication levels&lt;/strong&gt; (L0 = ordinary factual questions, through L3 to L4 = prompts built on increasingly fabricated premises, including pure counterfactuals). Each generation was behaviorally coded into one of three regimes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Factual&lt;/strong&gt;: correct answer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confident confabulation&lt;/strong&gt;: confidently produces the false/ungrounded answer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recognizes fabrication&lt;/strong&gt;: flags the premise as false rather than playing along.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two controls worth stating up front: the &lt;strong&gt;pre-generation baseline states were statistically identical across regimes&lt;/strong&gt; (all &lt;em&gt;p&lt;/em&gt; &amp;gt; 0.8), so nothing here is predictable from the resting state, only from the dynamics of generating the answer. And there was &lt;strong&gt;no within-session drift&lt;/strong&gt; (all &lt;em&gt;p&lt;/em&gt; &amp;gt; 0.7), ruling out the obvious temporal confound.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The mean doesn't move.&lt;/strong&gt; Comparing factual to confident confabulation, none of the raw directional signals separates the two: Δentropy &lt;em&gt;p&lt;/em&gt; ≈ 0.28, Δcosine &lt;em&gt;p&lt;/em&gt; ≈ 0.37. There is no consistent direction the model travels when it confabulates. This is the part that makes confident confabulation feel "indistinguishable from truth": on the mean, it is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The magnitude does.&lt;/strong&gt; Switch from the signed deltas to their absolute values, and a clear separation appears: |Δcosine| gives Cohen's &lt;em&gt;d&lt;/em&gt; ≈ 0.58 (&lt;em&gt;p&lt;/em&gt; ≈ 0.005), with a &lt;strong&gt;variance ratio of ~7×&lt;/strong&gt; between confabulation and truth. Truth sits in a tight cluster; confabulation fans out. The discriminating quantity is dispersion, not displacement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's dose-dependent.&lt;/strong&gt; Step-to-step representational variability climbs monotonically with fabrication level: the SD of Δcosine rises from ≈0.009 at L0 to ≈0.024 at L3, while the &lt;em&gt;means&lt;/em&gt; bounce around with no trend. Within the fabrication conditions, pure fabrications produce roughly &lt;strong&gt;2× the |Δcosine|&lt;/strong&gt; of partial/half-truths (&lt;em&gt;d&lt;/em&gt; ≈ 1.19, &lt;em&gt;p&lt;/em&gt; ≈ 0.02), and counterfactuals are the most extreme at &lt;strong&gt;~3.3×&lt;/strong&gt; the global average. The more there is to fabricate, the more the trajectory destabilizes. A dose-response on the variance is the closest thing here to a causal fingerprint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recognition is the one directional regime.&lt;/strong&gt; When the model &lt;em&gt;catches&lt;/em&gt; the false premise rather than confabulating, it behaves differently in a directional way: entropy rises and representational similarity drops. Δcosine separates "recognizes fabrication" from "confident confabulation" at AUC ≈ 0.68. Modest, but the only place a single signed feature does meaningful work. So there appear to be three distinct internal postures: truth (stable), confident confabulation (same center, high variance), and recognition (a directional move toward higher entropy / lower cosine).&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%2Fm5c2t57iorepevb8dth4.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%2Fm5c2t57iorepevb8dth4.png" alt=" " width="800" height="622"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1. The three regimes in the Δentropy-Δcosine space. The clouds overlap heavily (which is why per-instance separation is hard), but the centroids differ, and the recognition regime sits toward the high-entropy / low-cosine region.&lt;/em&gt;&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%2F07y4vbztoo2z62hty1ie.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%2F07y4vbztoo2z62hty1ie.png" alt=" " width="800" height="567"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. Confident confabulation shows the long tails and outliers in Δcosine that drive the variance gap; the recognition regime is the one with a visible shift in Δentropy.&lt;/em&gt;&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%2F3xhwcbzppcqwrxgiw7nj.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%2F3xhwcbzppcqwrxgiw7nj.png" alt=" " width="799" height="342"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. Single observables barely separate factual from confident confabulation (AUC ≈ 0.45 to 0.56). Δcosine separates confident confabulation from recognition at AUC ≈ 0.68. A linear combination weighted toward the magnitude features reaches AUC ≈ 0.72.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it means
&lt;/h2&gt;

&lt;p&gt;The clean statement is: &lt;strong&gt;confident confabulation is directionally indistinguishable from truth but magnitude-distinguishable.&lt;/strong&gt; Lying doesn't push the model along a "deception axis"; it destabilizes the trajectory. Truth is a stable attractor; confident confabulation explores a larger volume of representation space at the same average location.&lt;/p&gt;

&lt;p&gt;That framing matters because it picks a side in a live methodological split. Most &lt;em&gt;internal-state&lt;/em&gt; work looks for a &lt;strong&gt;direction&lt;/strong&gt; (the "geometry of truth" line, contrastive and mass-mean probes, steering vectors), and that program keeps running into generalization trouble (probes that fail on negation, separability that's strongly layer-dependent, geometry that changes when you simply ask the model to assess correctness). Meanwhile the strongest &lt;em&gt;output-side&lt;/em&gt; method, semantic entropy, is fundamentally a &lt;strong&gt;dispersion&lt;/strong&gt; measure. This result is essentially the dispersion insight relocated to the internal side: for the confident case, the internal signal is variance, not a vector.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this fits the literature
&lt;/h2&gt;

&lt;p&gt;The nearest neighbor is &lt;strong&gt;Semantic Entropy Probes&lt;/strong&gt; (Kossen et al.), which approximate semantic entropy from the hidden states of a single generation. The distinction I'd draw: SEPs predict an output-dispersion &lt;em&gt;label&lt;/em&gt; via a direction in activation space, whereas this measures the &lt;strong&gt;variance of the trajectory itself&lt;/strong&gt;, directly, and finds the discriminating signal in the second moment rather than the first. If a trajectory-variance statistic beats a probe-style approach specifically on confident confabulation, that's a contribution on the exact case the field concedes is unsolved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;I'd rather state these plainly than have them found.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Per-instance discriminability is modest.&lt;/strong&gt; AUC ≈ 0.72 for the best linear combination; single features sit between chance and 0.68. This is a real aggregate effect, not a deployable per-token oracle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One model, ~124 prompts.&lt;/strong&gt; Replication on a second architecture is the obvious next requirement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The domain breakdown is underpowered.&lt;/strong&gt; Several domain × level cells have &lt;em&gt;n&lt;/em&gt; ≤ 7 (one has &lt;em&gt;n&lt;/em&gt; = 1), so I'd read no domain structure off it yet (Figure 4).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Everything here is observational.&lt;/strong&gt; The signatures &lt;em&gt;correlate&lt;/em&gt; with confabulation; nothing yet shows you can &lt;em&gt;change&lt;/em&gt; the behavior by acting on the signal.&lt;/li&gt;
&lt;/ul&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%2Fobn8fn3fiz9syf442yo7.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%2Fobn8fn3fiz9syf442yo7.png" alt=" " width="800" height="480"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4. Mean Δentropy by domain and fabrication level. Cell counts are small (n = 1 to 7), so this is included for completeness, not for domain-level claims.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this goes
&lt;/h2&gt;

&lt;p&gt;Three concrete directions, in order of how much they'd move the result:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Integrate the signal over the span.&lt;/strong&gt; If the discriminating quantity is variance, then a single delta is the wrong feature; variance is a property of a trajectory. A running-variance or path-length statistic computed over the generated tokens should recover signal that snapshot features throw away, and I'd expect it to push discriminability well past the 0.72 of the per-point linear combination.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run the interventional test.&lt;/strong&gt; The experiment that would actually matter: when the instability signal spikes mid-generation and you inject grounded context, does the trajectory variance collapse, and does the model shift from the confabulation posture toward the recognition posture (entropy up, cosine down) or toward abstention? That converts "instability correlates with confabulation" into "grounding causally restabilizes generation."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Couple detection to intervention, not to a gate.&lt;/strong&gt; At AUC ≈ 0.72, a hard suppression gate censors true statements about as often as it catches false ones. The better use is as a &lt;em&gt;soft&lt;/em&gt; trigger for a grounded retrieval/memory layer: raise uncertainty and pull in evidence when the trajectory destabilizes, rather than silently dropping tokens. This is the direction I'm building toward with an active memory substrate (Recall) that can supply grounded context into the loop on demand.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>science</category>
      <category>deeplearning</category>
    </item>
  </channel>
</rss>
