<?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: Richard Emate</title>
    <description>The latest articles on DEV Community by Richard Emate (@rouche01).</description>
    <link>https://dev.to/rouche01</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%2F4026507%2F76ff9ba0-cb7c-4a02-9a09-9c84983d24e3.jpeg</url>
      <title>DEV Community: Richard Emate</title>
      <link>https://dev.to/rouche01</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rouche01"/>
    <language>en</language>
    <item>
      <title>A library is a basis. App code is coefficients. Refactoring is a change of basis. I use compression and sparse coding to pin down what actually counts as a "new idea" — and why frequency, not drama, earns one.</title>
      <dc:creator>Richard Emate</dc:creator>
      <pubDate>Wed, 23 Sep 2026 10:21:31 +0000</pubDate>
      <link>https://dev.to/rouche01/a-library-is-a-basis-app-code-is-coefficients-refactoring-is-a-change-of-basis-i-use-compression-ihm</link>
      <guid>https://dev.to/rouche01/a-library-is-a-basis-app-code-is-coefficients-refactoring-is-a-change-of-basis-i-use-compression-ihm</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/rouche01/a-psychological-state-is-a-coefficient-vector-2jm0" class="crayons-story__hidden-navigation-link"&gt;A Psychological State is a Coefficient Vector&lt;/a&gt;


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

          &lt;a href="/rouche01" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4026507%2F76ff9ba0-cb7c-4a02-9a09-9c84983d24e3.jpeg" alt="rouche01 profile" class="crayons-avatar__image" width="800" height="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/rouche01" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Richard Emate
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Richard Emate
                
                
              
              &lt;div id="story-author-preview-content-4721668" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/rouche01" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4026507%2F76ff9ba0-cb7c-4a02-9a09-9c84983d24e3.jpeg" class="crayons-avatar__image" alt="" width="800" height="800"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Richard Emate&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/rouche01/a-psychological-state-is-a-coefficient-vector-2jm0" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 23&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/rouche01/a-psychological-state-is-a-coefficient-vector-2jm0" id="article-link-4721668"&gt;
          A Psychological State is a Coefficient Vector
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/computerscience"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;computerscience&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/machinelearning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;machinelearning&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/rouche01/a-psychological-state-is-a-coefficient-vector-2jm0#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

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

&lt;/div&gt;


</description>
      <category>architecture</category>
      <category>refactoring</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>A Psychological State is a Coefficient Vector</title>
      <dc:creator>Richard Emate</dc:creator>
      <pubDate>Wed, 23 Sep 2026 10:16:16 +0000</pubDate>
      <link>https://dev.to/rouche01/a-psychological-state-is-a-coefficient-vector-2jm0</link>
      <guid>https://dev.to/rouche01/a-psychological-state-is-a-coefficient-vector-2jm0</guid>
      <description>&lt;p&gt;Hamming's two kinds of novelty are not two kinds of stuff. They are two things you can do with one set of building blocks: mix them differently, or add a new one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hamming's leftover question
&lt;/h2&gt;

&lt;p&gt;I got stuck on two words in Richard Hamming's &lt;em&gt;The Art of Doing Science and Engineering&lt;/em&gt;: logical novelty and psychological novelty.&lt;/p&gt;

&lt;p&gt;He mentions them in passing, in a chapter on machines and originality. A program working properly never produces logical novelty, because everything it does was already implied by what you wrote. It produces psychological novelty constantly. You are surprised by your own code. Then he turns the question on us. Much of human discovery looks the same: past experience led you there, the circumstances set it up. And once you fix the postulates, the definitions and the logic, he says, "all the rest of mathematics is merely psychologically novel." He even asks whether logical novelty is possible at all.&lt;/p&gt;

&lt;p&gt;We use the two words as if they were one. Psychological novelty is new &lt;strong&gt;to you&lt;/strong&gt;: a thought you had never had, but one always within reach, because someone else already had it or you could have worked it out from what you knew. Logical novelty is new &lt;strong&gt;to the space itself&lt;/strong&gt;. One visits a point in a space that already existed. The other makes the space bigger. Hamming's question, put that way, is whether the second kind ever happens.&lt;/p&gt;

&lt;h2&gt;
  
  
  New weights versus new directions
&lt;/h2&gt;

&lt;p&gt;I started asking what it would take to make that difference precise, and it turned into a picture.&lt;/p&gt;

&lt;p&gt;If "new to you" means a new mix of things you already have, then the things you already have sit there like a set of fixed directions. Call that set a basis. Every ordinary new thought is a new &lt;strong&gt;coefficient vector&lt;/strong&gt;: a different mix of the same directions, a combination you had not worked out yet but that was always available. Logical novelty is not a new mix. It is a new &lt;strong&gt;basis vector&lt;/strong&gt;, a direction that was not in the set, which makes more things reachable instead of visiting somewhere new inside what was already reachable.&lt;/p&gt;

&lt;p&gt;There is a third thing you can do, too — keep the same directions but choose better coordinates to describe them in — and I will come back to it, because it is the one that makes Hamming's split hardest to hold.&lt;/p&gt;

&lt;p&gt;That does not answer Hamming. It says what logical novelty would have to be: not a surprising combination, but the set of directions itself getting bigger.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storage, and time
&lt;/h2&gt;

&lt;p&gt;The two layers store differently. A basis vector is cheap to keep, because you do not store what it produces. You store the rule and produce them again on demand. A coefficient is the reverse: cheap to make, expensive to keep, tied to a moment, gone unless something writes it down. Logical and psychological are not two kinds of content. They are two tiers of one storage system.&lt;/p&gt;

&lt;p&gt;None of which is mine. The difference between keeping a lookup table and keeping a short program that regenerates it is the founding move of algorithmic information theory, and Kolmogorov complexity is the formal version of storing the generator rather than its consequences. Minimum description length is its practical descendant, and it makes the cost of missing structure concrete: you pay for the model plus whatever the model fails to explain, which in the usual examples is the difference between a description that grows like N and one that grows like log N.&lt;/p&gt;

&lt;p&gt;The human version of this is time. A logical thing does not happen on a Tuesday. Whatever gets you 2+2=4 (the axioms, not the answer) is the same tomorrow. That is all I mean by timeless: not a separate world of non-physical objects, and not "maths never changes," just that you do not have to work the rule out again when the clock moves.&lt;/p&gt;

&lt;p&gt;A psychological state has a date on it. You live inside the mix: what is recent, what stands out, what happened just before, and the fact that it will fade. Grief has a date. The attachment and the loss it draws on are closer to generators, because they keep producing effects without being the feeling itself. You live through the weather. Generators are why you do not have to store every cloud.&lt;/p&gt;

&lt;p&gt;This is also why hard science and social science can feel like different worlds without being made of different stuff. Physics spends most of its effort on rules that survive time, so the details can be thrown away. Much of social science has to keep the diary, because what it studies is tied to context and changes while you watch. That gap is about storage, not about reality, and it closes whenever someone finds structure that regenerates the pattern.&lt;/p&gt;

&lt;p&gt;One warning, because it protects the distinction. A generator is timeless &lt;em&gt;once you have it&lt;/em&gt;, but the set can still grow. If logical meant "never changes," growth would be impossible, and we would be back to eternal rules sitting above mere feelings.&lt;/p&gt;

&lt;h2&gt;
  
  
  The state is the recipe
&lt;/h2&gt;

&lt;p&gt;Drawing it helps. A few fixed arrows from one origin, and any psychological state is a single arrow built by weighting them. The state &lt;strong&gt;is&lt;/strong&gt; the recipe, and the dashed lines are the coefficients: how much of each generator is in play right now.&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%2Ff4uwx88djgoitxj1ztza.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%2Ff4uwx88djgoitxj1ztza.png" alt="Psychological states as combinations of a logical basis. Two teal axes labeled stable rule A and stable rule B; a coral arrow is their weighted combination." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The teal axes do not move. They are the logical layer, timeless once found. The coral arrow has a date, and tomorrow it can point somewhere else while the generators stay put. The same shape turns up elsewhere under other names: a transformer's attention weights against its fixed matrices, or sparse coding's activations against its dictionary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two exits
&lt;/h2&gt;

&lt;p&gt;A basis does not arrive from nowhere, and neither does a new basis vector.&lt;/p&gt;

&lt;p&gt;Take noisy experience and look for the cheapest structure that still explains it. Most of the time the search just adjusts weights on the basis you have. That is psychological novelty: cheap, constant, the ordinary churn of new mixes. Now and then no mix is good enough, and nothing you have explains the new data however you weight it. Then the system cannot adjust its way out. It has to add a direction.&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%2Fyoewtxyqs7evz5gm1noo.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%2Fyoewtxyqs7evz5gm1noo.png" alt="Two exits of the same minimization. Left: reweighting on the same basis, a new coral state inside the existing space. Right: a faint new teal axis C, and the coral state using it." width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the left is a thought you could always have had: same A, same B, different recipe. On the right is the rarer move. A third generator appears because no mix of A and B lands where the state needs to be, and the coral arrow leaves the old plane only because the basis grew. So this is not a hierarchy with rule on top and feeling underneath. It is one loop with two exits, and whichever it takes, the result changes how the next round of experience gets read.&lt;/p&gt;

&lt;p&gt;Which exit cannot be settled by how surprised you feel. It needs a cost: fit what you are seeing, but keep the structure small. With no penalty for growing, "add a direction" is always available and the distinction turns into taste. With a penalty, you grow only when squeezing the old directions harder would cost more than admitting a new one.&lt;/p&gt;

&lt;p&gt;That cost is also what stops the picture from being a definition in disguise. Arrows and weighted sums are tidier than the real thing, and a few grammar rules will produce sentences nobody has ever said, which can look like the space growing when it has not. So "it was already reachable" cannot be the test on its own. The cost comparison can be.&lt;/p&gt;

&lt;h2&gt;
  
  
  When an atom pays for itself
&lt;/h2&gt;

&lt;p&gt;Sparse coding is the clearest place I know to watch it, because there the basis is a real object you can point at.&lt;/p&gt;

&lt;p&gt;Say you are compressing small patches of photographs. You learn a dictionary: a few hundred atoms, mostly little edges and blobs, and any patch is written as a weighted sum of a handful of them. The dictionary is the basis, the weights are the coefficients, and in this one case the framing of this essay is not a metaphor. It is the data structure.&lt;/p&gt;

&lt;p&gt;Now a new kind of patch starts turning up: a repeating texture, a weave, a patch of fur. Your edge atoms can still represent it, but it takes a lot of them with large weights, and it takes them every single time that texture appears. You have two options, and they are the two exits.&lt;/p&gt;

&lt;p&gt;Keep the dictionary and pay in coefficients. Every patch of that texture is expensive to describe, and you pay again on the next one.&lt;/p&gt;

&lt;p&gt;Or add an atom shaped like the texture. That costs a fixed amount once, since you have to store the atom and a bigger dictionary is a more complex model. After that each patch costs almost nothing: one atom, one weight.&lt;/p&gt;

&lt;p&gt;The arithmetic decides. Total cost is the dictionary plus all the codes. Adding an atom raises the first part once and lowers the second part a little on every patch that uses it. So the decision does not turn on how strange the texture is. It turns on &lt;strong&gt;how often it comes back&lt;/strong&gt;. Seen once, it stays a coefficient no matter how odd it looked. Seen ten thousand times, the atom pays for itself.&lt;/p&gt;

&lt;p&gt;That is the most useful thing this framing buys, and it is not obvious. A one-off shock, however violent, is psychological. You absorb it as an expensive mix and move on. A modest pattern that keeps recurring is what earns a new generator. Frequency, not drama.&lt;/p&gt;

&lt;p&gt;It also says when growing is wrong. Add an atom for every unusual patch and the dictionary swells into a list of everything you have seen, which is just storing the data again.&lt;/p&gt;

&lt;h2&gt;
  
  
  The third move
&lt;/h2&gt;

&lt;p&gt;There is the operation I promised, and it is the one that makes Hamming's split hardest to hold.&lt;/p&gt;

&lt;p&gt;Go back to the dictionary. Keep it exactly the same size, but swap the atoms for better ones. Nothing was added and the space it covers need not change, yet every patch now needs three atoms instead of eleven and the total cost drops sharply. Nothing grew and something real happened.&lt;/p&gt;

&lt;p&gt;That is a change of basis, and it is neither exit. Not reweighting, because the generators themselves moved. Not growth, because nothing became reachable that was not reachable before. It is the same space, described better.&lt;/p&gt;

&lt;p&gt;The everyday case is the numerals you are reading this in. Multiply MDXLVIII by XXIII, then multiply 1548 by 23. The same numbers were expressible both ways and nothing about arithmetic changed, but positional notation &lt;em&gt;is&lt;/em&gt; a coefficient vector: 1548 is the weights 1, 5, 4, 8 against the generators 1000, 100, 10 and 1. Roman numerals are not, which is why IV and VI mean different things from the same two symbols. One honest complication. Positional notation needs a zero to hold an empty place and Roman numerals have none, so the historical shift was a bundle: one new generator, then a rebase the new generator made possible.&lt;/p&gt;

&lt;p&gt;I think this is what most people mean by insight. A reframing feels like logical novelty, because the landscape looks different afterwards and you cannot unsee it. But no direction was added, so by the definition I have been using it is psychological. The honest reading is that Hamming's two categories are not quite enough, and rebasing is what they leave out. It is still not a third exit, though. Rebasing sits on another axis: not what to do with the basis you have, but which coordinates you keep everything in.&lt;/p&gt;

&lt;p&gt;It does share the economics of the second exit. Europe had Hindu-Arabic numerals from Fibonacci in 1202, kept its accounts in Roman for centuries, and in 1299 Florence's money-changers banned the new ones outright. Changing basis costs relearning, retooling, and translating everything already written, so like a new atom it pays only if you will spend long enough in the new coordinates. A reframing you reach for once is not worth the move.&lt;/p&gt;

&lt;h2&gt;
  
  
  Whose basis, and Hamming's regress
&lt;/h2&gt;

&lt;p&gt;Now the objection I owe Hamming.&lt;/p&gt;

&lt;p&gt;Dictionary learning has "add an atom" built into it. The procedure was written in advance, and so was the range of atoms it can reach. So was the new atom ever really outside the space? Compared with Tuesday's dictionary, yes, since no reweighting produced it. Compared with the range of all dictionaries the algorithm can reach, no. Read that way, growth is only reweighting one level up, and logical novelty disappears. Push it and it never stops: whatever produced your new generator was some capacity you already had, sitting inside some larger space you can name afterwards.&lt;/p&gt;

&lt;p&gt;This is Hamming's suspicion at full strength, and the vector picture does not refute it. I do not think anything does. You can always propose a bigger space in hindsight, which makes the absolute question, &lt;em&gt;is logical novelty possible at all, for anyone&lt;/em&gt;, probably unanswerable rather than merely unanswered.&lt;/p&gt;

&lt;p&gt;What the picture does is make the question answerable by making it relative. Novelty is logical or psychological &lt;strong&gt;relative to a named basis&lt;/strong&gt;. That sounds like a retreat and I think it is the opposite, because what a system actually holds decides what things cost it. A texture that needs a new atom is, for that system with that dictionary, in a different class from one it can already code cheaply, and the difference shows up in bits rather than in intuition.&lt;/p&gt;

&lt;p&gt;The relative move rescues the machine and the dictionary cleanly, because there the basis is a named object and the cost comparison is arithmetic you can actually run. For a person it is not. My own point about the asymmetry — that nobody can write down what our basis covers — is exactly what makes the cost comparison uncomputable for us. If I cannot enumerate my generators, I cannot price the choice between squeezing them and adding one; I only ever feel the result. So the relative question does not fully dissolve for people. It splits: answerable in principle, because the accounting is well defined, and intractable in practice, because the ledger is hidden from the thing keeping it. The systems where "look for the two exits" is advice you can follow are the ones that hold their basis as an object — dictionaries, models, codebases. For minds it stays a description of what is happening, not a test you can apply from the inside.&lt;/p&gt;

&lt;p&gt;Computation is the one place I know where this bottoms out in something firmer. The computable functions are closed under composition, so you cannot combine computable things and end up outside the set. Whatever a program does, however much it surprises the person who wrote it, was already reachable from the pieces it was built from. That puts a theorem under Hamming's claim about machines rather than a hunch. (The closure is the theorem. Church–Turing, the claim that this covers everything we could mean by computable, is a thesis, because one side of it is an informal idea.)&lt;/p&gt;

&lt;p&gt;It also sharpens the asymmetry he was circling. For machines the question is settled his way. For us it stays open, so nobody can show we cannot leave it. That is not evidence that we can.&lt;/p&gt;

&lt;p&gt;Last, whose basis I mean, because it changes the mechanism. A person's grows by learning. A field's grows by argument, and by somebody refusing to accept the current framing. A formal system's grows by stipulation. A trained model's grows by optimization, or by an engineer. These are not the same process. What they share is the accounting: a small structure that regenerates, a state that weights it, and a decision about when squeezing the structure costs more than growing it. That is weaker than "it is all one mechanism," and it is the claim I can defend.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it borrows, and one instance
&lt;/h2&gt;

&lt;p&gt;The storage argument was borrowed, and so is this one. Model-based reinforcement learning is what you get once you have a basis you can plan with. Model-free learning still learns, it just grinds through experience, because it never builds the thing that would let it generalize. None of that follows from basis and coefficient. The picture does not prove it, it borrows it, and what it buys is bookkeeping: a question about two kinds of novelty and a question about compression turn out to be the same account, so results on one side are allowed to constrain talk on the other.&lt;/p&gt;

&lt;p&gt;I did not start from the rule and hunt for examples. I got here by studying active inference, and once the two exits were visible the Free Energy Principle looked less like the source of the picture than a clear instance of it: the generative model is the basis, current beliefs are the coefficients, parameter learning is the first exit, structure learning is the second, and variational free energy is the cost — accuracy against complexity, the same trade the dictionary was making. I should name the obvious risk, since a framework you have just learned is the kind of thing you start seeing everywhere, which is dictionary bloat by this essay's own accounting. The test I would want applied to me is the sparse coding one: does it make the description cheaper? I half trust that it does, and the reason is the order I found things in — the two exits were visible in the dictionary before I mapped them onto structure learning.&lt;/p&gt;

&lt;p&gt;That is enough to give the distinction a stake. If a system only ever reweights and never grows, everything expensive stays expensive. Every situation the basis cannot cover is solved from scratch, at full price, again and again, each problem arriving disguised as new.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it matters
&lt;/h2&gt;

&lt;p&gt;Find a new generator and you have not finished discovering. You have opened a room.&lt;/p&gt;

&lt;p&gt;Learn to drive and you have not made one new journey, you have a way of moving. The shop, a friend's house, a road you have never taken: all psychological, new combinations of a skill you are no longer inventing. Hamming's line about mathematics, read the other way round, says the same thing. Given the postulates, everything after is psychologically novel, and that is a large and useful space rather than a consolation prize.&lt;/p&gt;

&lt;p&gt;The dictionary sharpens it. A generator is worth its cost in proportion to how often it gets reused, so the rooms worth opening are the ones you will spend a long time inside. That is a warning for anyone who likes the dramatic exit: a framework you invoke once is a bloated dictionary, not a discovery.&lt;/p&gt;

&lt;p&gt;Anyone who has looked after a codebase has felt all three moves. A library is a basis and application code is coefficients. Refactoring is the change of basis: nothing new, everything cheaper afterwards. Adding a primitive is growth, and it pays only if it recurs, which is the whole argument against the helper you pulled out for a single call site.&lt;/p&gt;

&lt;p&gt;It is also why a small model beats a long list of rules. Expert systems stored answers as rules, and when a case did not match, somebody wrote another rule. That is the expensive path, where every new instance becomes a generator and the dictionary swells exactly as predicted. Modelled inference does the opposite. Keep a small model, treat the situation in front of you as a weighting, and add structure only when no weighting of the old pieces will do. You do not have to stop using rules. You have to stop treating every solution as one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's mine, and what isn't
&lt;/h2&gt;

&lt;p&gt;Nothing here is new on its own. The novelty split is Hamming's, algorithmic information theory got to the storage argument first, model-based reinforcement learning's advantage is documented, sparse coding has been adding atoms for decades, and active inference already has names for both exits. What is mine is noticing they are the same account, with Hamming's two kinds of novelty as the thread.&lt;/p&gt;

&lt;p&gt;I still cannot tell him whether logical novelty is possible in the absolute sense. I have come to think that question has no answer, and that the relative one is the useful thing he left behind: not "is this new to the universe," but "is this new to the basis you are holding, and what does it cost you to find out."&lt;/p&gt;

&lt;p&gt;If you are modelling something that has to live in noisy experience and still keep a cheap set of generators, look for the two exits. Reweighting is the common move. Growth is the rare one. The interesting systems are the ones that can tell the difference.&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>machinelearning</category>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>Your AI agent shouldn’t flinch at every tiny change, but it also shouldn’t treat a career switch like background noise. This post asks what happens when you treat “experience” as leftover surprise: the part of reality your model did not already see coming.</title>
      <dc:creator>Richard Emate</dc:creator>
      <pubDate>Tue, 18 Aug 2026 15:54:50 +0000</pubDate>
      <link>https://dev.to/rouche01/your-ai-agent-shouldnt-flinch-at-every-tiny-change-but-it-also-shouldnt-treat-a-career-switch-5ao</link>
      <guid>https://dev.to/rouche01/your-ai-agent-shouldnt-flinch-at-every-tiny-change-but-it-also-shouldnt-treat-a-career-switch-5ao</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/rouche01/how-a-theory-of-leftover-surprise-changed-a-memory-layer-of3" class="crayons-story__hidden-navigation-link"&gt;How a theory of leftover surprise changed a memory layer&lt;/a&gt;


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

          &lt;a href="/rouche01" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4026507%2F76ff9ba0-cb7c-4a02-9a09-9c84983d24e3.jpeg" alt="rouche01 profile" class="crayons-avatar__image" width="800" height="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/rouche01" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Richard Emate
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Richard Emate
                
                
              
              &lt;div id="story-author-preview-content-4408113" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/rouche01" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4026507%2F76ff9ba0-cb7c-4a02-9a09-9c84983d24e3.jpeg" class="crayons-avatar__image" alt="" width="800" height="800"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Richard Emate&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/rouche01/how-a-theory-of-leftover-surprise-changed-a-memory-layer-of3" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 18&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/rouche01/how-a-theory-of-leftover-surprise-changed-a-memory-layer-of3" id="article-link-4408113"&gt;
          How a theory of leftover surprise changed a memory layer
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/llm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;llm&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/rouche01/how-a-theory-of-leftover-surprise-changed-a-memory-layer-of3#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

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

&lt;/div&gt;


</description>
      <category>agents</category>
      <category>ai</category>
      <category>llm</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>How a theory of leftover surprise changed a memory layer</title>
      <dc:creator>Richard Emate</dc:creator>
      <pubDate>Tue, 18 Aug 2026 12:30:00 +0000</pubDate>
      <link>https://dev.to/rouche01/how-a-theory-of-leftover-surprise-changed-a-memory-layer-of3</link>
      <guid>https://dev.to/rouche01/how-a-theory-of-leftover-surprise-changed-a-memory-layer-of3</guid>
      <description>&lt;h2&gt;
  
  
  Consciousness Might Not Look Like Anything
&lt;/h2&gt;

&lt;p&gt;If you are looking for consciousness in behavior, you may be looking at the wrong thing.&lt;/p&gt;

&lt;p&gt;The system most in contact with the world need not flinch, chatter, or otherwise announce that something happened. It may look, from the outside, as if nothing did.&lt;/p&gt;

&lt;p&gt;The obvious claim is the opposite: the most conscious being is the one whose internals get shoved around the hardest. Raw sensitivity. Volatility as contact. A thermostat kills that story. Turn the heat on and its state flips. Nobody thinks it is more conscious than a rock. Disturbability is cheap.&lt;/p&gt;

&lt;p&gt;What matters is the structure of the response — a large repertoire of distinguishable states, produced by one system you cannot carve into independent parts without losing something. A bundle of switches is many parts and no unity. A single wire is total unity and two possible states. Neither is interesting.&lt;/p&gt;

&lt;p&gt;Even that is not quite the target. The interesting system is not the one that gets pushed around a lot. It is the one that can absorb a wide range of perturbations while remaining itself — and, more than that, can see them coming so the jolt never fully arrives. Internal change is a side effect of regulation, not the point. Paradoxically, a more competent system may look calmer, not more volatile. It is absorbing disturbance predictively. From the outside there may be nothing to watch.&lt;/p&gt;

&lt;p&gt;That is the sense in which consciousness might not look like anything.&lt;/p&gt;

&lt;p&gt;I did not set out to settle that question. I set out to stop an agent from treating a career change like noise and a passing mood like a personality transplant. The philosophy showed up anyway. Then it earned its keep.&lt;/p&gt;




&lt;h2&gt;
  
  
  Two kinds of regulation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Homeostasis&lt;/strong&gt; waits. Deviation is detected, then corrected toward a fixed setpoint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Allostasis&lt;/strong&gt; moves the setpoint first. The target is anticipated, context-dependent, allowed to shift. Blood pressure before you stand up. The coat before the cold. Peter Sterling’s version is blunt: waiting for error and then fixing it is inefficient.&lt;/p&gt;

&lt;p&gt;The interesting quantity is not how much allostasis a system has as a fixed amount. It is the &lt;em&gt;range&lt;/em&gt; it can cover: how far ahead it can act, how many setpoints can move independently, how much of the space of possible contexts actually drives those moves. Each of those is near-useless without the others. Horizon without retargetability is a longer reflex. Retargetability without context is a clock.&lt;/p&gt;

&lt;p&gt;Experience, on the strongest reading of the same literature, is not the regulation itself. It is the leftover: the part of the world the model failed to anticipate. Prediction error after the coat was already on. The same stimulus should feel vivid at first and thin out as the prediction improves. Habituation is the residual shrinking.&lt;/p&gt;

&lt;p&gt;That is a trigger condition, not a solution to the hard problem. I am not claiming a Python library is conscious. I am claiming the split is load-bearing for any memory that has to stay current without coming apart.&lt;/p&gt;




&lt;h2&gt;
  
  
  One number was doing two jobs
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Rouche01/voltmem" rel="noopener noreferrer"&gt;VoltMem&lt;/a&gt; already had a prior about how stubborn each &lt;em&gt;kind&lt;/em&gt; of fact should be. Personality locks down. Mood is cheap. A job sits in between. That prior is a slow allostatic signal: &lt;em&gt;this channel is usually like that.&lt;/em&gt; It is not a reading of what is happening now.&lt;/p&gt;

&lt;p&gt;A live residual would ask a different question. Given what we already expected — including that this channel is usually noisy, or usually quiet — did &lt;em&gt;this&lt;/em&gt; observation arrive in a way we had not already priced in?&lt;/p&gt;

&lt;p&gt;A domain can be historically messy and currently well-predicted. Under one scalar those cases are the same. They should not be.&lt;/p&gt;

&lt;p&gt;The old overwrite rule charged that stubbornness twice. Being a “rarely changes” kind of fact both shrank the evidence &lt;em&gt;and&lt;/em&gt; raised the bar. For a job, a clear “I retrained as a nurse” could fail to overwrite “I was a data analyst.” It was not being careful. It was double-counting the same caution.&lt;/p&gt;

&lt;p&gt;So we built an allostatic mode: drop volatility from the evidence score, and let recent leftover surprise temporarily lower the bar for memories that are going through something.&lt;/p&gt;

&lt;p&gt;The first ablation was rude. The entire career-change win was taking volatility out of the score. It was a cliff, not a blend. A little volatility left in the formula lost the case entirely.&lt;/p&gt;

&lt;p&gt;That looked like a free improvement until we measured the cost.&lt;/p&gt;




&lt;h2&gt;
  
  
  The defect was insurance
&lt;/h2&gt;

&lt;p&gt;The classifier that guesses “what kind of fact is this?” is about 84% accurate. When it files a personality trait as something more changeable, and a weak comment arrives, allostatic mode overwrites. The double charge we had just called a bug still discounts the evidence, and the trait survives.&lt;/p&gt;

&lt;p&gt;At the real error rate, allostatic lost 1.1 points of accuracy and produced 20% more false updates. Every extra overwrite had the same shape: a very-stable fact, mislabeled, contradicted by weak evidence.&lt;/p&gt;

&lt;p&gt;Removing the double charge fixes career changes and breaks mislabeled traits. It is a genuine trade. You cannot slide volatility halfway back in; we already measured that cliff. The remaining honest move is a &lt;em&gt;switch&lt;/em&gt;, not a mix.&lt;/p&gt;

&lt;p&gt;Most of the time the system stays homeostatic: this is the kind of fact it is; I need a lot of proof. It goes allostatic when the world is actually telling it the setpoint moved — a clear correction, or a leftover it did not already expect.&lt;/p&gt;

&lt;p&gt;That switch is now the default in VoltMem 0.4.0. It is called &lt;code&gt;composite&lt;/code&gt;. It matches the cautious law’s false-update rate and still catches the explicit career change. Allostatic stays available if you pass a trusted domain label and want the residual path all the time. Homeostatic stays available if you want the insurance always on.&lt;/p&gt;

&lt;p&gt;A theory of range, not amount, said a channel should be able to move between modes rather than carry one weight for its lifetime. The gate is that claim, implemented as a predicate instead of a personality.&lt;/p&gt;




&lt;h2&gt;
  
  
  We were measuring the thermostat
&lt;/h2&gt;

&lt;p&gt;The live shakiness meter was an average of raw contradiction — how different the new sentence was from the stored one. Every method in the notes treats surprise as leftover mismatch &lt;em&gt;after anticipation&lt;/em&gt;. We were scoring the flinch.&lt;/p&gt;

&lt;p&gt;If someone has been casually mentioning a new job for two weeks, another casual mention is not surprising. If they have been quiet for months and then say the same words, that &lt;em&gt;is&lt;/em&gt; surprising. Same sentence. Different leftover.&lt;/p&gt;

&lt;p&gt;We shipped that definition. Each memory keeps a running “what mismatch size is normal,” widened by how noisy the domain usually is. Surprise is distance from that prediction, not from the stored sentence. Evidence still uses how contradictory the sentence is. Surprise uses how unexpected that contradiction was.&lt;/p&gt;

&lt;p&gt;The career change said clearly still works. It never needed the surprise term. It wins by dropping the double charge.&lt;/p&gt;

&lt;p&gt;The sixteen weak asides stopped catching live. After a few similar mentions the system &lt;em&gt;expects&lt;/em&gt; them. Leftover goes to zero. The bar stays shut. That is the definition working, which is why it could not be the slow-burn fix. People do not rewrite “my job” on every aside. They notice the pattern later.&lt;/p&gt;

&lt;p&gt;We had been celebrating a hairline. An average of raw contradiction had been sitting 0.0002 from the trigger; stretching the half-life from two weeks to a month shoved it over. That is not surprise. That is a constant wearing a costume.&lt;/p&gt;

&lt;p&gt;The pile belongs overnight. Sixteen daily weak mentions stay quiet on the write path, then consolidation actually supersedes the stored job. The same sixteen spread monthly do not. A core preference does not yield. Same evidence, same count, only the pace differs. That is horizon: identical evidence at different spacing must not count the same. An earlier version keyed shakiness to a lifetime counter that could only ratchet open. A long-lived memory would have grown permanently easier to overwrite with age. Time decay was the route back to settled. Range requires a way home.&lt;/p&gt;

&lt;p&gt;So 0.4.0 has three timescales, not one knob:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live leftover&lt;/strong&gt; — was &lt;em&gt;this step&lt;/em&gt; unexpected? Quiet is correct.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The gate&lt;/strong&gt; — explicit correction, or a leftover we did not already expect, opens the easy-update path. Otherwise keep the insurance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sleeptime&lt;/strong&gt; — has the &lt;em&gt;belief&lt;/em&gt; that the old fact still holds actually moved, over a window? Daily weather can shift a job overnight. A monthly drip cannot. A deep preference does not erode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the sleeptime compute idea from a &lt;a href="https://dev.to/rouche01/the-maintenance-window-i-didnt-know-i-was-running-51kk"&gt;previous post&lt;/a&gt;, now with a detector that sees spacing instead of a counter that never forgets.&lt;/p&gt;




&lt;h2&gt;
  
  
  Then we found the thing sitting in front of all of it
&lt;/h2&gt;

&lt;p&gt;None of the overwrite work runs if the new sentence never finds the memory it contradicts.&lt;/p&gt;

&lt;p&gt;The matcher and the overwrite rule are sequential, not alternatives. Homeostatic vs allostatic only starts after a match. A miss inserts a duplicate. A false pair &lt;em&gt;does&lt;/em&gt; consult the overwrite law — on the wrong memory.&lt;/p&gt;

&lt;p&gt;Through the default &lt;code&gt;remember()&lt;/code&gt; path, keyword similarity routed 22% of update cases. A real embedder routed 78% with perfect labels, 56% with the shipped classifier. Decision error &lt;em&gt;once routed&lt;/em&gt; was about six points. We had been arguing about the six-point layer. Two of the cases that never linked even with embeddings were the exact career-change and goal-change probes allostatic was built to recover.&lt;/p&gt;

&lt;p&gt;The obvious repair is to lower the link bar. That repair is forbidden.&lt;/p&gt;

&lt;p&gt;“User is proficient in Python” versus “User is proficient in Japanese” scores as a &lt;em&gt;stronger&lt;/em&gt; match than “I was a data analyst” versus “I retrained as a nurse.” The false merges outrank the true links. No cutoff can work. Bag-of-words and sentence embeddings both encode topic, not entity identity. They cannot tell two facts about family members from one fact restated.&lt;/p&gt;

&lt;p&gt;A duplicate is recoverable. Both facts stay retrievable; a later pass can reconcile them. A false merge treats two different facts as one and loses a true memory. Lowering a bar converts the cheaper error into the expensive one.&lt;/p&gt;

&lt;p&gt;Worse: under a threshold ladder, &lt;em&gt;improving the classifier makes data loss worse&lt;/em&gt;. Correct labels put two distinct facts in the same slot, where the ladder can merge them. Misclassification was accidentally protecting memories by scattering them.&lt;/p&gt;

&lt;p&gt;The architecture that survived is recall wide, decide narrow. Similarity is allowed to fetch candidates. It is not allowed to decide “same fact.” A conservative local model looking at the pair — same subject? same &lt;em&gt;question&lt;/em&gt;, never the same answer? — scored 49/56 on held-out pairs with &lt;strong&gt;zero&lt;/strong&gt; false merges. A hosted model scored three pairs higher and paid for it with two irreversible losses. Under the weighting we used everywhere else, that is a bad trade. We kept the conservatism.&lt;/p&gt;

&lt;p&gt;A 14B call is about five seconds. Fine overnight. Too slow inside an interactive &lt;code&gt;remember()&lt;/code&gt;. The worst case of deferring it is a temporary duplicate. That is what makes deferral acceptable rather than a compromise.&lt;/p&gt;

&lt;p&gt;So the shipped write path is millisecond and conservative. Heuristic subject/attribute frames we trust may join. Grey frames insert as twins. Overnight, the local verifier reconciles them. Live &lt;code&gt;remember()&lt;/code&gt; does not wait for the 14B unless you ask it to.&lt;/p&gt;

&lt;p&gt;The philosophy said leftover only appears at the edges where the model is under-fit. In the library, leftover only appears at all if the observation finds the slot. The matcher is not a theory of consciousness. It is the condition under which the control law, and therefore any residual, is even computed.&lt;/p&gt;




&lt;h2&gt;
  
  
  What 0.4.0 actually is
&lt;/h2&gt;

&lt;p&gt;The consciousness writeup was a searchlight, not a control law. It made us split expected noise from unexpected leftover, refuse raw dynamism, refuse a lifetime weight, refuse a blend, and notice that a miss never consults the overwrite rule. The range formula did not have to be true for those moves to pay. Neither did “this is what experience is.”&lt;/p&gt;

&lt;p&gt;What shipped:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Surprise means unexpected leftover&lt;/strong&gt;, not how different the sentence is. A predicted weak stream no longer impersonates a regime change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Composite overwrite&lt;/strong&gt; — cautious by default; allostatic only on an explicit correction or a learned unexpected residual. Career changes said clearly get through. Mislabeled traits keep the insurance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sleeptime for the pile&lt;/strong&gt; — daily weak evidence can move a belief overnight; the same evidence dripped monthly does not. Very-stable domains do not erode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Search widely, decide narrowly&lt;/strong&gt; — embeddings for recall, a conservative local verifier for precision, deferred to sleeptime. Duplicates are okay. Silent overwrites are not.&lt;/p&gt;




&lt;h2&gt;
  
  
  If you're building persistent agent memory
&lt;/h2&gt;

&lt;p&gt;Three distinctions paid rent. I would steal those and leave the rest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contradiction is not surprise.&lt;/strong&gt; Distance from the stored fact is an observation. Surprise is distance from what you had already predicted, scaled by how noisy that channel usually is. If you average raw mismatch until it crosses a bar, you will eventually "catch" a slow change by sitting on a hairline. That is not a capability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A switch, not a blend.&lt;/strong&gt; If two control laws win on different failure modes, mixing their formulas can lose both. Gate on the kind of evidence. Keep the insurance for weak noise on a guessed label. Spend the plasticity on a clear correction or a leftover you did not expect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The matcher is in front of the overwrite rule.&lt;/strong&gt; Improving when to update a fact does nothing for a sentence that never found it — and does the wrong thing for a sentence that found the wrong one. Rank topic similarity and entity identity separately. Weight errors by whether they can be undone. If your "better embedder" starts deleting stored facts, you did not improve matching. You changed which mistake you make.&lt;/p&gt;

&lt;p&gt;A thermostat looks alive. A system that saw the perturbation coming may look like nothing happened. VoltMem’s write path is now allowed to look like that on purpose: millisecond, quiet, twins instead of guesses. The work happens at the edges, and overnight.&lt;/p&gt;

&lt;p&gt;I still do not think that makes it conscious. I think it makes it less of a thermostat.&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The Maintenance Window I Didn't Know I Was Running</title>
      <dc:creator>Richard Emate</dc:creator>
      <pubDate>Fri, 07 Aug 2026 07:26:58 +0000</pubDate>
      <link>https://dev.to/rouche01/the-maintenance-window-i-didnt-know-i-was-running-51kk</link>
      <guid>https://dev.to/rouche01/the-maintenance-window-i-didnt-know-i-was-running-51kk</guid>
      <description>&lt;h2&gt;
  
  
  How Letta's sleep-time compute reframed VoltMem's open problems
&lt;/h2&gt;

&lt;p&gt;I didn't set out to build a memory layer for LLM agents.&lt;/p&gt;

&lt;p&gt;What I set out to build was a way to stop being frustrated by agents that forget the right things and remember the wrong ones. The Berlin → Paris problem: your agent knows you live in Berlin. You move to Paris. Three months later it's still asking about Berlin weather. Meanwhile, your stable preference for concise answers — something you've held for years — gets overwritten by a single offhand comment because the system treats all facts as equally volatile.&lt;/p&gt;

&lt;p&gt;That frustration became &lt;a href="https://github.com/Rouche01/voltmem" rel="noopener noreferrer"&gt;VoltMem&lt;/a&gt;, a memory layer that assigns domain-specific volatility priors: personality traits get locked down, locations update freely, current tasks evaporate quickly. The math works. The benchmarks validate it. VoltMem is a &lt;a href="https://dev.to/rouche01/i-built-a-memory-layer-for-llm-agents-that-knows-which-facts-go-stale-1mg5"&gt;control knob on the stability-plasticity tradeoff&lt;/a&gt;, not a free-lunch accuracy booster — and that's exactly what it was supposed to be.&lt;/p&gt;

&lt;p&gt;But building it surfaced problems I hadn't prepared to answer. Four of them, tracked in &lt;a href="https://github.com/Rouche01/voltmem/blob/main/docs/OPEN_PROBLEMS.md" rel="noopener noreferrer"&gt;docs/OPEN_PROBLEMS.md&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Classification brittleness&lt;/strong&gt; — write-time labeling of facts is its own judgment call, and if the label is wrong, everything downstream is wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stable facts that genuinely change&lt;/strong&gt; — protection against noise also blocks legitimate updates that build slowly across multiple observations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Under-specified retrieval&lt;/strong&gt; — when queries are vague, similarity scores flatten and volatility re-ranking can pick the wrong winner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-facet events&lt;/strong&gt; — real observations carry multiple signals at once (location, task, emotional state), but VoltMem assumes one fact, one domain.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These aren't edge cases. They're the gap between a memory layer that works in demos and one that survives contact with reality.&lt;/p&gt;




&lt;h2&gt;
  
  
  The rabbit hole
&lt;/h2&gt;

&lt;p&gt;Sometime around when Problem 2 was driving me quietly insane — watching the escalation math correctly reject a noisy blip but also miss a legitimate career change that emerged across four casual mentions over two weeks — I found myself reading everything Letta had published on agent architecture and continual learning.&lt;/p&gt;

&lt;p&gt;That path led to their post on &lt;a href="https://www.letta.com/blog/sleep-time-compute/" rel="noopener noreferrer"&gt;sleep-time compute&lt;/a&gt;: a dual-agent design where a primary agent stays responsive in conversation while a separate sleep-time agent runs asynchronously to consolidate, reorganize, and rewrite shared memory blocks. The point isn't to invent new facts during idle time. It's to offload memory management from the hot path so formation can be proactive instead of incremental and messy.&lt;/p&gt;

&lt;p&gt;I wasn't looking for a VoltMem roadmap. I was looking for language for a gap I already had.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sleep-time compute, simply
&lt;/h2&gt;

&lt;p&gt;Most agents have excellent working memory and no long-term maintenance loop. Between sessions they are simply off. Sleep-time compute uses those gaps — or dedicated background cycles — to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Process and distill what happened during active sessions&lt;/li&gt;
&lt;li&gt;Integrate new memories with old ones&lt;/li&gt;
&lt;li&gt;Notice contradictions that weren't visible in real time because real-time cognition is too narrow&lt;/li&gt;
&lt;li&gt;Build associative structure that only emerges from distance and pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's not about adding new information. It's about reorganizing what you already have.&lt;/p&gt;

&lt;p&gt;The analogy that made this click for me is ordinary human downtime: shower thoughts, late-night drift, the moments where you're not deciding anything and somehow end up filing yesterday's half-finished thoughts against older patterns. That isn't rest in the useful sense. It's maintenance on the index. Agents mostly skip that phase.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mapping sleep-time to VoltMem's open problems
&lt;/h2&gt;

&lt;p&gt;Sleep-time compute isn't a silver bullet. But it directly addresses the hardest of VoltMem's four open problems — and incidentally helps with two others.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 2: Stable facts that genuinely change ← The primary match
&lt;/h3&gt;

&lt;p&gt;This is where the idea shines brightest.&lt;/p&gt;

&lt;p&gt;The core tension in VoltMem's escalation math is: &lt;em&gt;don't corrupt on noise&lt;/em&gt; vs &lt;em&gt;don't miss a real change.&lt;/em&gt; The current system handles this at write-time: when new evidence arrives, check if &lt;code&gt;E_t &amp;gt; θ_t&lt;/code&gt;, and if so, escalate to audit + update. Explicit statements with high mismatch magnitude can override stable-domain protection.&lt;/p&gt;

&lt;p&gt;But some changes don't arrive as dramatic contradictions. They emerge as patterns across multiple weak observations. Like: the user mentions "my new job" casually in 4 conversations over 2 weeks. Each individual mention is weak evidence. None cross the threshold alone. The escalation math, correctly calibrated to reject noise, also misses the signal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A maintenance window catches this.&lt;/strong&gt; During idle cycles, the system can review the full &lt;code&gt;logged_mismatch&lt;/code&gt; history. Those 4 weak "new job" mentions, none strong enough to trigger a real-time audit, combine into a clear pattern during offline analysis. The system can then proactively escalate the career-change audit — possibly even flagging it for user confirmation before the next active session begins.&lt;/p&gt;

&lt;p&gt;This is exactly the gap: the escalation math is &lt;em&gt;reactive&lt;/em&gt; (new evidence arrives → check threshold), while some changes are &lt;em&gt;emergent&lt;/em&gt; (pattern builds over time → need retrospective review).&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 1: Classification brittleness ← Partial, but real
&lt;/h3&gt;

&lt;p&gt;At write-time, VoltMem assigns a domain via keyword heuristics or a local LLM. If "I feel great today" gets labeled &lt;code&gt;emotional_context&lt;/code&gt; (correct) or &lt;code&gt;core_preference&lt;/code&gt; (wrong), the volatility prior is wrong and everything downstream is wrong.&lt;/p&gt;

&lt;p&gt;A maintenance loop adds a &lt;em&gt;correction pass.&lt;/em&gt; During idle cycles, the system can re-classify ambiguous facts using richer context — the full conversation history, not just the turn where the fact was extracted. A label assigned based on fragmentary evidence at write-time might look obviously wrong when reviewed alongside three months of consistent contradictory observations.&lt;/p&gt;

&lt;p&gt;This doesn't fix the initial brittleness. But it adds a nightly audit: "these 47 facts got labeled &lt;code&gt;core_preference&lt;/code&gt; but only 3 have ever been audited, while 12 have been contradicted multiple times. Are some of them actually &lt;code&gt;emotional_context&lt;/code&gt; or &lt;code&gt;current_task&lt;/code&gt;?"&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 4: Multi-facet events ← Architectural enabler
&lt;/h3&gt;

&lt;p&gt;Real utterances carry multiple signals. "I'm exhausted but heading to the gym in my new apartment" contains emotional state, current task, and location — plus an implicit causal link between them.&lt;/p&gt;

&lt;p&gt;At write-time, processing this into multiple facets is expensive and error-prone. Most systems (including VoltMem today) pick one domain and move on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A maintenance window separates the tradeoff.&lt;/strong&gt; During idle cycles, the system can re-parse rich utterances into multiple linked facets, assign per-facet volatility, and link them under a shared &lt;code&gt;event_id&lt;/code&gt; — all without blocking the write path. The user gets fast, simple storage. The agent gets rich, linked structure after hours. This is essentially the multi-facet &lt;code&gt;add_event()&lt;/code&gt; API proposed in OPEN_PROBLEMS.md, but implemented asynchronously rather than synchronously.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 3: Under-specified retrieval ← Weaker connection
&lt;/h3&gt;

&lt;p&gt;When queries are vague ("what was I working on?"), similarity scores flatten and VoltMem's volatility re-ranking can invert ranks incorrectly. Background integration helps indirectly here: by building associative structures during idle hours — noticing that "database migration" co-occurs with "current_project" 80% of the time, or that certain task memories cluster around specific project phases — the retrieval system gets richer linkage to fall back on when raw similarity is uninformative.&lt;/p&gt;

&lt;p&gt;But this is the weakest connection. The core issue in Problem 3 is query specificity, and sleep-time doesn't make queries more specific. It just gives the retrieval system more paths to follow when the direct path is muddy.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this changes for VoltMem
&lt;/h2&gt;

&lt;p&gt;Reading Letta's work reframed my open issues.&lt;/p&gt;

&lt;p&gt;The product claim isn't "agents should sleep like brains." It's narrower and more useful:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Memory layers need an explicit &lt;strong&gt;maintenance surface&lt;/strong&gt; for operations that are too expensive, too speculative, or too context-heavy for the write path.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Async support for VoltMem isn't just about not blocking the event loop — it's about whether the memory layer can survive being left alone for hours and come back &lt;em&gt;integrated.&lt;/em&gt; Smarter domain classification isn't just about better heuristics — it's about whether the classification itself gets refined during the gaps.&lt;/p&gt;

&lt;p&gt;That principle is what the next VoltMem cycle operationalizes: ship the enabling API (&lt;code&gt;event_id&lt;/code&gt;, multi-facet events, optional TTL), then populate a maintenance runner task by task — pattern audits on logged mismatches, ambiguous reclassification, expire cleanup — without pretending VoltMem is a full sleep-time agent architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  A note on scope
&lt;/h2&gt;

&lt;p&gt;I don't think VoltMem's next version will literally implement Letta's sleep-time agents — that's a full system architecture, not a memory layer feature. But the principle is seeping into the roadmap.&lt;/p&gt;

&lt;p&gt;The question isn't "should VoltMem run background threads?" The question is: what maintenance operations does a memory layer need that are too expensive, too speculative, or too context-dependent to run at write-time?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrospective pattern detection on logged mismatches? Maintenance.&lt;/li&gt;
&lt;li&gt;Domain relabeling with full historical context? Maintenance.&lt;/li&gt;
&lt;li&gt;Multi-facet re-parsing of rich utterances? Maintenance.&lt;/li&gt;
&lt;li&gt;Building cross-referential links that only emerge from co-occurrence over weeks? Maintenance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the gaps VoltMem has. Sleep-time compute is one architecture for filling them. VoltMem's next step is the smaller, portable version: a maintenance window the memory layer can own.&lt;/p&gt;




&lt;h2&gt;
  
  
  If you're building persistent agent memory
&lt;/h2&gt;

&lt;p&gt;The sleep-time compute idea is worth your attention. Not because it's a quick win — it's harder than it sounds to do well — but because it names a real gap: most of our agents have excellent working memory and no long-term maintenance loop.&lt;/p&gt;

&lt;p&gt;An agent that only learns when the user is present is like a person who only thinks when someone else is talking. The quiet hours matter. The maintenance window is where integration happens. Without it, you get either brittleness (too rigid) or corruption (too plastic) — and the escalation math alone can't solve both.&lt;/p&gt;

&lt;p&gt;And if you too spend a suspicious amount of time reorganizing thoughts you didn't finish yesterday — you're not broken. You're running the index.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/Rouche01/voltmem" rel="noopener noreferrer"&gt;VoltMem on GitHub&lt;/a&gt; · &lt;a href="https://dev.to/rouche01/i-built-a-memory-layer-for-llm-agents-that-knows-which-facts-go-stale-1mg5"&gt;Original VoltMem writeup&lt;/a&gt; · &lt;a href="https://www.letta.com/blog/sleep-time-compute/" rel="noopener noreferrer"&gt;Letta: Sleep-time Compute&lt;/a&gt; · Built by &lt;a href="https://github.com/Rouche01" rel="noopener noreferrer"&gt;Richard Emate&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>architecture</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I Built a Memory Layer for LLM Agents That Knows Which Facts Go Stale</title>
      <dc:creator>Richard Emate</dc:creator>
      <pubDate>Mon, 13 Jul 2026 01:42:18 +0000</pubDate>
      <link>https://dev.to/rouche01/i-built-a-memory-layer-for-llm-agents-that-knows-which-facts-go-stale-1mg5</link>
      <guid>https://dev.to/rouche01/i-built-a-memory-layer-for-llm-agents-that-knows-which-facts-go-stale-1mg5</guid>
      <description>&lt;p&gt;VoltMem didn't start because I kept hitting bugs in production agents.&lt;/p&gt;

&lt;p&gt;It started with a conversation about how memory actually works — why some beliefs stick for decades while others evaporate in hours, and what triggers the audit when an old calibration stops matching present reality. That led to continual-learning research on the stability–plasticity tradeoff, and then to a structural parallel in agent memory: most layers treat every fact the same at write and search time.&lt;/p&gt;


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

  &lt;br&gt;
&lt;strong&gt;The Berlin → Paris Problem&lt;/strong&gt;&lt;br&gt;
Most memory systems treat "I live in Berlin" (volatile) with the same protection as "I prefer concise answers" (stable). VoltMem differentiates them by domain.&lt;br&gt;

&lt;/div&gt;


&lt;p&gt;Your AI assistant knows you live in Berlin. You moved to Paris three months ago. It still thinks you live in Berlin. Meanwhile, the fact that you prefer concise answers — stable for years — gets the same grip as "currently working on a database migration," which you finished last week.&lt;/p&gt;

&lt;p&gt;Everything is stored the same way. Everything decays (or doesn't) at the same rate. There's no concept of &lt;em&gt;how volatile&lt;/em&gt; a piece of knowledge actually is.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mem0 remembers relevant facts. VoltMem remembers &lt;strong&gt;current truth&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Core Insight&lt;/li&gt;
&lt;li&gt;The Math&lt;/li&gt;
&lt;li&gt;What it Looks Like in Practice&lt;/li&gt;
&lt;li&gt;Using it&lt;/li&gt;
&lt;li&gt;Built-in Domain Volatility Priors&lt;/li&gt;
&lt;li&gt;LangChain Integration&lt;/li&gt;
&lt;li&gt;Where This Came From&lt;/li&gt;
&lt;li&gt;What's Next&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The core insight
&lt;/h2&gt;

&lt;p&gt;Think about how different types of facts actually behave over time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your personality traits&lt;/strong&gt; — barely change over decades&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core preferences&lt;/strong&gt; (communication style, aesthetic sensibilities) — stable for years&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your job&lt;/strong&gt; — changes every few years&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What you're currently working on&lt;/strong&gt; — changes weekly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your mood right now&lt;/strong&gt; — changes hourly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An LLM memory system that treats all of these with the same protection strength makes systematic errors in a predictable direction: it holds volatile facts too long (stale knowledge), or overwrites stable facts on thin evidence (corrupted knowledge). You can't fix both with one dial.&lt;/p&gt;

&lt;p&gt;What you need is &lt;em&gt;domain-aware protection&lt;/em&gt; — and, at search time, down-ranking of stale volatile memories even when they're semantically close.&lt;/p&gt;




&lt;h2&gt;
  
  
  The math (stay with me, it's not that bad)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Protection weight&lt;/strong&gt; (per domain):&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;w&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;V&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;γ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Write / audit decision&lt;/strong&gt; — escalate (audit + update) when 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;E&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-r"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;E&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="col-align-l"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size3"&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size3"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;V&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;G&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-r"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;V&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;L&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 — how strongly the new observation contradicts what's stored (0 to 1)&lt;/li&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 — how reliable the source is (explicit user statement vs. weak inference)&lt;/li&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 — how many times this memory has been confirmed (repetition count)&lt;/li&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;α&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 — entrenchment exponent (how hard history fights back)&lt;/li&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;V&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 — domain volatility prior (how fast does this &lt;em&gt;type&lt;/em&gt; of fact change?)&lt;/li&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;G&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 — goal-attainment delta (is updating this memory actually useful?)&lt;/li&gt;
&lt;li&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;L&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 — cognitive load&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;High-volatility domain → low threshold → easy to update.&lt;br&gt;
Low-volatility domain → high threshold → hard to update.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retrieval&lt;/strong&gt; — down-rank stale volatile memories:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;score&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;similarity&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;V&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;staleness&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;The practical effect: a confident blip like "the user seemed extroverted today" won't overwrite a deeply confirmed "user is introverted" — but "user moved to Paris" will cleanly supersede "user lives in Berlin" because location is a volatile domain where a single explicit statement clears the update bar easily.&lt;/p&gt;

&lt;p&gt;On Split-MNIST, this isn't a free-lunch accuracy booster. It's a validated &lt;strong&gt;control knob&lt;/strong&gt;: run the same pipeline with volatility priors shuffled or inverted, and the ordering breaks (REAL &amp;gt; SHUFFLE &amp;gt; SWAP). Pre-arXiv draft: &lt;a href="https://github.com/Rouche01/voltmem/blob/main/paper/volatility_ewc_portfolio.pdf" rel="noopener noreferrer"&gt;volatility_ewc_portfolio.pdf&lt;/a&gt;. Full reproduction: &lt;a href="https://github.com/Rouche01/voltmem/blob/main/docs/RESEARCH.md" rel="noopener noreferrer"&gt;docs/RESEARCH.md&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it looks like in practice
&lt;/h2&gt;

&lt;p&gt;I compared VoltMem against Mem0 (open-source LLM memory) on three concrete scenarios — a &lt;strong&gt;case study&lt;/strong&gt;, not a leaderboard claim:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 1: Location update&lt;/strong&gt;&lt;br&gt;
User says they moved from Berlin to Paris.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Mem0&lt;/th&gt;
&lt;th&gt;VoltMem&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Result&lt;/td&gt;
&lt;td&gt;Stale "Berlin" stored, 2 conflicting facts&lt;/td&gt;
&lt;td&gt;Updated to "Paris", 1 clean fact&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Scenario 2: Stable preference blip&lt;/strong&gt;&lt;br&gt;
User says they "really like short replies" in one session, contradicting an established preference for thorough explanations.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Mem0&lt;/th&gt;
&lt;th&gt;VoltMem&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Result&lt;/td&gt;
&lt;td&gt;Adopts the blip&lt;/td&gt;
&lt;td&gt;Keeps original (resists weak contradicting evidence)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Scenario 3: Volatile mood&lt;/strong&gt;&lt;br&gt;
User's mood shifts from "great" to "stressed".&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Mem0&lt;/th&gt;
&lt;th&gt;VoltMem&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Result&lt;/td&gt;
&lt;td&gt;Stale "great" persists&lt;/td&gt;
&lt;td&gt;Updates to "stressed"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;VoltMem: 3/3&lt;/strong&gt; current top answer on these scripted scenarios. Challenge the scripts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python experiments/mem0_side_by_side.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Retrieval haystack&lt;/strong&gt; (same chunks, different ranker): cosine-only returns the stale fact first &lt;strong&gt;20%&lt;/strong&gt; of the time; VoltMem &lt;strong&gt;0%&lt;/strong&gt; &lt;a href="mailto:stale@1"&gt;stale@1&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python experiments/retrieval_haystack_bench.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;LongMemEval-S (n=60):&lt;/strong&gt; &lt;strong&gt;70% answer@5&lt;/strong&gt; — &lt;strong&gt;ties cosine, does not beat it.&lt;/strong&gt; If your only metric is public benchmark SOTA, this isn't the pitch. The pitch is update policy + retrieval freshness on mixed-volatility personal memory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python experiments/longmemeval.py &lt;span class="nt"&gt;--split&lt;/span&gt; s &lt;span class="nt"&gt;--per-type&lt;/span&gt; 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Using it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;voltmem[embeddings]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Core library: &lt;strong&gt;zero required dependencies&lt;/strong&gt;. Embeddings optional (&lt;code&gt;sentence-transformers&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;voltmem&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_memory&lt;/span&gt;

&lt;span class="n"&gt;mem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_memory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app.db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I live in Berlin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I prefer concise, direct answers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Actually I moved to Paris last month&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# updates location, not prefs
&lt;/span&gt;
&lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mem&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;where does the user live?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hits&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;   &lt;span class="c1"&gt;# "Actually I moved to Paris last month"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inject into any LLM system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;memories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mem&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="n"&gt;user_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;memory&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;memories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What you know about this user:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Built-in domain volatility priors
&lt;/h2&gt;

&lt;p&gt;VoltMem ships with sensible defaults you can override:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Domain&lt;/th&gt;
&lt;th&gt;Volatility&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;personality_trait&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;Strongly protected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;core_preference&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.08&lt;/td&gt;
&lt;td&gt;Strongly protected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;biographical&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.10&lt;/td&gt;
&lt;td&gt;High protection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;professional_context&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.30&lt;/td&gt;
&lt;td&gt;Medium — changes every few years&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;current_project&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.55&lt;/td&gt;
&lt;td&gt;Updates readily&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;emotional_context&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.80&lt;/td&gt;
&lt;td&gt;Fast-moving&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;current_task&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.90&lt;/td&gt;
&lt;td&gt;Minimal protection&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Custom domains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;voltmem&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DomainRegistry&lt;/span&gt;

&lt;span class="n"&gt;domains&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DomainRegistry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;client_relationship&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.35&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;active_deal_stage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.70&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;mem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_memory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;crm.db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rep_01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The priors are hand-tuned today — that's an open gap, and one of the places I'd most like real-world feedback.&lt;/p&gt;




&lt;h2&gt;
  
  
  LangChain integration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;voltmem[langchain]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;voltmem.integrations.langchain&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;VoltMemMemory&lt;/span&gt;

&lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;VoltMemMemory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user-42&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app.db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_memory_variables&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&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;Where do I live?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save_context&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&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;I moved to Paris&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;output&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;Noted.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Where this came from
&lt;/h2&gt;

&lt;p&gt;This grew out of a philosophical conversation about how human minds handle stale beliefs — when to trust an old habit and when to question it.&lt;/p&gt;

&lt;p&gt;The observation: animals mostly rely on impulses and simple reinforcement to build routines. Human minds add a monitoring layer on top — but that layer can go wrong when calibrated by social contexts that no longer apply. An old rule, reinforced enough times in a specific environment, can feel like an unquestionable fact even when the environment has fundamentally changed.&lt;/p&gt;

&lt;p&gt;That maps almost exactly onto the LLM memory problem. A memory system calibrated by early conversation data can become rigid in the same way — protecting old "truths" that are now stale because they were confirmed enough times in the past.&lt;/p&gt;

&lt;p&gt;The escalation equations above formalize the same idea: use historical reinforcement as &lt;em&gt;one&lt;/em&gt; input, but also factor in domain volatility, source reliability, and actual mismatch — rather than letting any one factor dominate. The continual-learning experiments validated that as a causal control knob; VoltMem is the engineering artifact applied to agent context memory.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;More benchmark scenarios&lt;/strong&gt; — expanding beyond the 3-scenario Mem0 comparison, including cases where VoltMem loses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smarter domain classification&lt;/strong&gt; — heuristics and optional Ollama LLM work today, but priors are hand-tuned and new domains still need manual registration; next up is better defaults, cloud LLM support, and inferring domain + volatility from context&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Async support&lt;/strong&gt; — sync store today; most production LLM apps are async&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;arXiv preprint&lt;/strong&gt; — theoretical foundations written up; submission in progress&lt;/li&gt;
&lt;/ul&gt;




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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;voltmem[embeddings]
python examples/contradiction_demo.py
python &lt;span class="nt"&gt;-m&lt;/span&gt; examples.chat_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/Rouche01/voltmem" rel="noopener noreferrer"&gt;https://github.com/Rouche01/voltmem&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PyPI: &lt;a href="https://pypi.org/project/voltmem/" rel="noopener noreferrer"&gt;https://pypi.org/project/voltmem/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Research &amp;amp; repro: &lt;a href="https://github.com/Rouche01/voltmem/blob/main/docs/RESEARCH.md" rel="noopener noreferrer"&gt;https://github.com/Rouche01/voltmem/blob/main/docs/RESEARCH.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building anything with persistent LLM memory, I'd genuinely like to hear how the stale-knowledge problem shows up in practice — the use cases I haven't thought of are usually the most interesting ones.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Rouche01/voltmem" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Check out VoltMem on GitHub and leave a Star!&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>opensource</category>
      <category>machinelearning</category>
    </item>
  </channel>
</rss>
