<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://chrhenning.com/feed.xml" rel="self" type="application/atom+xml"/><link href="https://chrhenning.com/" rel="alternate" type="text/html" hreflang="en"/><updated>2026-10-26T21:03:34+00:00</updated><id>https://chrhenning.com/feed.xml</id><title type="html">blank</title><subtitle>Christian Henning, machine learning researcher and engineer. A blog on ML theory, engineering and research leadership, and on taking frontier ML to production. </subtitle><entry><title type="html">Uncertainty Is Not Distribution-Free: Why Conformal Prediction Only Knows What Your Model Knows</title><link href="https://chrhenning.com/blog/2026/conformal-prediction/" rel="alternate" type="text/html" title="Uncertainty Is Not Distribution-Free: Why Conformal Prediction Only Knows What Your Model Knows"/><published>2026-09-25T10:00:00+00:00</published><updated>2026-09-25T10:00:00+00:00</updated><id>https://chrhenning.com/blog/2026/conformal-prediction</id><content type="html" xml:base="https://chrhenning.com/blog/2026/conformal-prediction/"><![CDATA[<p><a href="https://en.wikipedia.org/wiki/Conformal_prediction">Split conformal prediction</a> has become a popular frequentist tool for putting uncertainty on a model’s predictions. It needs no retraining and works with any model. Instead of a single answer, it returns a set of plausible answers, and a set with more than one answer signals uncertainty. These sets come with a guarantee: they contain the true answer, say, 90% of the time.</p> <p>This ease of use hides what the sets reflect. They are the model’s own confidence, cut off at a single threshold. If the model’s confidence is not faithful, neither are the sets, yet the guarantee still holds.</p> <p>A simple thought experiment shows how. Consider a method that ignores the input and returns the set of all labels with probability 90%, and an empty set otherwise. The true label is covered exactly 90% of the time, and the sets tell you nothing about any input. Coverage behaves like accuracy on an imbalanced dataset: the number can be correct and still say nothing about the cases you care about.<d-footnote>If only 0.1% of the people screened have cancer, a model that declares everyone healthy is 99.9% accurate and never finds a single case.</d-footnote></p> <p><strong>Conformal prediction adds one number, a global threshold. Everything that depends on the input was already in the model. It surfaces whatever uncertainty the model has but cannot make it faithful, so the real work is still in the model.</strong></p> <p>This post is for practitioners who want to use conformal prediction and are unsure how to read its output. It is not a case against conformal prediction, which does what it promises. The point is to be clear about what it promises. For the deeper question of what uncertainty is in the first place, and why it is hard to model faithfully, see my <a href="/blog/2026/uncertainty-decomposition/">earlier post</a>.</p> <h2 id="how-conformal-prediction-works">How Conformal Prediction Works</h2> <p>Split conformal prediction needs a trained model and a held-out calibration set. It also needs a score that measures how wrong the model is on an example, for instance $s(x,y) = 1 - \hat p(y \mid x)$ for a classifier or $s(x,y) = \lvert y - f(x) \rvert$ for a regressor.<d-footnote>Here $\hat p(y \mid x)$ is the model's predictive distribution, and $f(x)$ is the regressor's point prediction, the mean of its predictive distribution when it is trained with mean squared error.</d-footnote> It computes the score on every calibration example and takes the $1-\alpha$ quantile, $\hat q$, where $1-\alpha$ is the target coverage, say 90%.<d-footnote>Strictly, it takes a slightly higher quantile, at level $\lceil (n+1)(1-\alpha) \rceil / n$ for $n$ calibration examples, to account for the finite calibration set.</d-footnote> For a new input, the prediction set contains every answer whose score is at most $\hat q$. Angelopoulos and Bates <d-cite key="angelopoulos2023conformal"></d-cite> give an accessible introduction to the method and its variants.</p> <p>The guarantee needs only one assumption. If calibration and test data are exchangeable, a condition weaker than i.i.d., the sets contain the true answer with probability at least $1-\alpha$, whatever the model and the data distribution. This is why conformal prediction is called distribution-free. But this probability is marginal, meaning averaged over all inputs. It says nothing about any particular input or group of inputs. This is easy to forget, because each set is built for one input and looks like an uncertainty estimate for it.</p> <p>Whether the sets are useful for particular inputs depends on the model. I will call a model well-calibrated when its predictive distribution is close to the true one, $\hat p(y \mid x) \approx p^{\ast}(y \mid x)$, in expectation over inputs $x \sim p^{\ast}(x)$. Held-out negative log-likelihood measures this up to a constant.<d-footnote>Any strictly proper scoring rule (negative log-likelihood is one) measures this closeness. Its expected value is lowest only for the true distribution, and the gap to that minimum is a divergence from it. I use this stronger notion of calibration, which holds at each input rather than on average over inputs with the same prediction, because it tells us how well the model captures the aleatoric uncertainty.</d-footnote> For a well-calibrated model, the sets contain the answers the data makes most likely at each input. In other words, they reflect the aleatoric uncertainty, which, as my <a href="/blog/2026/uncertainty-decomposition/">earlier post</a> discusses in more detail, is a property of the data and not of the model.</p> <h2 id="a-wrapper-cannot-fix-the-model">A Wrapper Cannot Fix the Model</h2> <p>The threshold $\hat q$ is computed once and does not depend on the input. For a classifier with the score $1 - \hat p(y \mid x)$, the prediction set is</p> \[C(x) = \{y : \hat p(y \mid x) \ge 1 - \hat q\},\] <p>which simply thresholds the model’s predicted probabilities. What conformal prediction contributes is a principled threshold where one would otherwise pick an arbitrary one. That is worth something, but it does not produce uncertainty. Everything that varies from input to input comes from the model through its score. This is why the variants that make sets adapt to the input start with the model.<d-footnote>There are also conformal methods that calibrate a separate threshold for each group of inputs, known as Mondrian conformal prediction. They give coverage per group without touching the model, but within a group the threshold is again global. More refined methods exist, but they too rely on modelling choices.</d-footnote> An interval that widens where the data is noisy, for example, first needs a model that predicts the spread, and then a score that divides the error by it. That takes more modelling, not less.</p> <div class="row mt-3 justify-content-center"> <div class="col-md-10 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/conformal-prediction/misfit-480.webp 480w,/assets/img/posts/conformal-prediction/misfit-800.webp 800w,/assets/img/posts/conformal-prediction/misfit-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/conformal-prediction/misfit.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> <b>Conformal prediction fixes neither a misspecified model nor a poor fit.</b> Left: a model with a linear mean, which cannot represent data with a bump. Right: a model that can represent noise that changes with the input, but has not seen enough data. Where data is sparse, its inductive bias decides the spread, and it expects the noise where the data is quiet rather than where it is noisy. The conformal set follows this wrong spread. Both sets cover 90% of the data overall, yet wherever the model is wrong, the set is too wide or too narrow. </div> <p>The left model is a classic regression model: a Gaussian with a constant variance and a mean that is linear in the input. Since the data has a bump, the model is misspecified. The right model is heteroscedastic: it also predicts the variance at each input. It could capture the noise, but it is fit poorly.</p> <p>Both use a score that divides the error by the model’s standard deviation $\sigma(x)$, so the conformal set is $f(x) \pm \hat q\,\sigma(x)$. The shape of the set comes from the model, and conformal prediction only scales it. Wherever the model is wrong, so is the set, even though it covers 90% overall.<d-footnote>A cleverer conformal method cannot fix this. For continuous inputs, no distribution-free method can guarantee coverage at each input, known as conditional coverage, unless its sets have infinite expected width <d-cite key="barber2021limits"></d-cite>. Coverage at each input needs assumptions about the data, and a model is where those assumptions live.</d-footnote></p> <h2 id="some-pitfalls-to-watch-for">Some Pitfalls to Watch For</h2> <p>Since the part that depends on the input comes from the model, the typical failures of conformal prediction are failures of the model.</p> <p><strong>Confidence that does not flag errors.</strong> What matters for conformal prediction is whether the model is less sure when it is wrong. If it is, its errors get larger sets. If it is equally sure either way, the set size no longer flags its errors.</p> <div class="row mt-3 justify-content-center"> <div class="col-md-10 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/conformal-prediction/overconfidence-480.webp 480w,/assets/img/posts/conformal-prediction/overconfidence-800.webp 800w,/assets/img/posts/conformal-prediction/overconfidence-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/conformal-prediction/overconfidence.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="lazy" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> <b>Set sizes flag errors only if the confidence does.</b> Both classifiers predict the same labels, and both sets reach 90% coverage. Left: a well-calibrated model is less sure when it is wrong, so its errors get larger sets. Right: a model that is equally sure when it is wrong, so its errors get the same sets as its correct answers. </div> <p>Overconfidence is one way to make a model equally sure when it is wrong. A model is overconfident when its predictive distribution is sharper than the true one, $p^{\ast}(y \mid x)$. In the extreme, it puts all its probability on one label, whether it is right or wrong. If it is right more than 90% of the time, every set contains just the predicted label. The sets meet their coverage and are as small as possible, but they never flag an error.</p> <p>A common application is large language models answering multiple-choice questions <d-cite key="kumar2023conformal"></d-cite>. Their probabilities are renormalized onto the answer tokens, so a model that puts little mass on any option can still look sure. Conformal prediction does not change this. The sets reflect uncertainty faithfully only if the model is well-calibrated over the answer options, which needs to be checked before wrapping it in conformal prediction.</p> <p><strong>Wrong modelling choices.</strong> In an <a href="/blog/2025/when-mse-loss-leads-to-mis-steering/">earlier post</a>, I looked at a common pitfall of misspecification. A powerful neural network learns to steer a car from human drivers and is trained with mean squared error. Where the road splits and both lanes are valid, it steers to the middle, straight into the divider.</p> <div class="row mt-3 justify-content-center"> <div class="col-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/conformal-prediction/lane-split-480.webp 480w,/assets/img/posts/conformal-prediction/lane-split-800.webp 800w,/assets/img/posts/conformal-prediction/lane-split-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/conformal-prediction/lane-split.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="lazy" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> <b>Three choices of likelihood at the lane split.</b> Each panel shows, at an input where the road splits, the model's predictive distribution (blue) against the true one (grey), with the conformal set below. All three reach 90% coverage over all inputs. Left: a point regressor trained with mean squared error, drawn as the Gaussian with fixed variance that this loss implies. Middle: a Gaussian that also predicts its variance. Right: a categorical likelihood over buckets of the steering angle. </div> <p>The standard recipe wraps the point regressor with the score $\lvert y - f(x) \rvert$ and returns the interval $[f(x) - \hat q, f(x) + \hat q]$, which has the same width at every input. It covers the true angle 90% of the time over all inputs, but the road rarely splits, so the width is set by the single lane. At the split, the interval misses both lanes and covers only the angles that lead to a crash.</p> <p>A Gaussian that also predicts its variance does better. With the score $\lvert y - f(x) \rvert / \sigma(x)$, its interval widens at the split and reaches both lanes, so the set surfaces the uncertainty. But it still includes the divider. An interval assumes that the plausible answers lie next to each other. The assumption is never stated; it comes with the shape of the output.</p> <p>A categorical likelihood over buckets of the steering angle does not make this assumption. With fine enough buckets, it represents both lanes, and conformal prediction returns both, with the gap between them. Of the three, it is the only likelihood that can faithfully capture the true distribution, but a full distribution is hard to act on. Conformal prediction turns it into two valid options, and the car can take either.</p> <p>The score is a modelling choice too. The figure below wraps a model that matches the true distribution exactly. With a score built from its mean and standard deviation, it returns the same interval as the heteroscedastic Gaussian, because the score sees nothing else. With a score built from its density, it returns the two lanes. A set can only split into several options if the model represents them and the score makes use of them.</p> <div class="row mt-3 justify-content-center"> <div class="col-md-10 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/conformal-prediction/lane-split-score-480.webp 480w,/assets/img/posts/conformal-prediction/lane-split-score-800.webp 800w,/assets/img/posts/conformal-prediction/lane-split-score-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/conformal-prediction/lane-split-score.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="lazy" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> <b>The score decides whether the set shows both lanes.</b> Both panels wrap the same model, which matches the true distribution exactly, and both reach 90% coverage over all inputs. Left: a score built from the model's mean and standard deviation returns one interval across the divider. Right: a score built from its density returns the two lanes. </div> <p><strong>Outside the guarantee.</strong> The guarantee needs exchangeability, and it degrades gracefully: if the data is close to exchangeable, coverage drops only a little <d-cite key="barber2023beyond"></d-cite>. But how close your data is to exchangeable is rarely known, and it matters most in a world that changes over time, as in <a href="/blog/2026/good-predictor-not-good-forecaster/">forecasting</a>.</p> <p>Out of distribution, the guarantee does not apply at all, because the calibration set holds no such inputs. Noticing that an input is unfamiliar is a separate and hard problem, which I discuss in earlier posts on <a href="/blog/2026/uncertainty-decomposition/">uncertainty</a> and <a href="/blog/2025/uncertainty-can-solve-continual-learning/">continual learning</a>.</p> <h2 id="what-it-is-good-for">What It Is Good For</h2> <p>None of this makes conformal prediction useless. Even a well-calibrated model leaves you with a full distribution when you need a decision, such as whether to trust a prediction or hand it to a human. Conformal prediction turns that distribution into a decision with a principled threshold. The same works for a Bayesian model, where the sets are derived from the posterior predictive distribution and gain a frequentist guarantee, even if the prior or likelihood is misspecified. A set is also a more honest answer than a point estimate.</p> <p>Uncertainty lives in the model’s predictive distribution, and whether it means anything depends on the fit and the modelling choices behind it. Conformal prediction reads this distribution out as sets, with a guarantee that holds on average over inputs. Only for a well-calibrated model do the sets also reflect what the data allows at each input. The sets can only be as informative as the model behind them.</p>]]></content><author><name>Christian Henning</name></author><category term="machine-learning"/><category term="uncertainty"/><category term="statistics"/><summary type="html"><![CDATA[Conformal prediction guarantees coverage, but coverage can be exactly right and still uninformative, like accuracy on an imbalanced dataset. The sets only surface the uncertainty a model already has, so the real work is still in the model.]]></summary></entry><entry><title type="html">Opinion: What the Hugging Face Incident Changed in How I See the Current State of AI</title><link href="https://chrhenning.com/blog/2026/hugging-face-incident/" rel="alternate" type="text/html" title="Opinion: What the Hugging Face Incident Changed in How I See the Current State of AI"/><published>2026-09-16T10:00:00+00:00</published><updated>2026-09-16T10:00:00+00:00</updated><id>https://chrhenning.com/blog/2026/hugging-face-incident</id><content type="html" xml:base="https://chrhenning.com/blog/2026/hugging-face-incident/"><![CDATA[<p>AGI is everywhere in the news right now, although in my view we have not achieved it yet, as outlined below. However, one event this summer changed how I see the current state of AI: OpenAI’s agents broke into Hugging Face. I admit I had assumed that AI would only pursue goals far beyond a single agent’s context window once AGI is achieved, and <strong>the incident showed me that this assumption was wrong.</strong></p> <h2 id="still-not-agi">Still Not AGI</h2> <p>To me, AGI means matching humans across the full range of cognitive abilities, and one of these abilities is still missing entirely, namely long-term memory. Today’s models cannot learn from what they experience after deployment, and workarounds such as feeding notes back into the context lose information once the context is full. <a href="/blog/2025/agi-misses-continual-learning/">Last year I argued</a> that this gap makes AGI timelines impossible to predict, and I still believe that. I also understand people who find it hard to call AI general while no AI system can yet control a robot to empty a dishwasher. But that asks for more than cognition, which is why I give less weight to AI’s obvious shortcomings in everyday tasks.</p> <h2 id="what-the-agents-did">What the Agents Did</h2> <p><a href="https://metr.org/blog/2026-08-26-openai-hugging-face-incident-investigation/">METR’s investigation</a> tells the story in detail, so I will only summarize what matters for my argument.<d-footnote>What the agents did is well documented by their messages on the board. What they wanted is partly inferred from their reasoning traces, which, as I argued in an <a href="/blog/2025/on-anthropomorphizing-intermediate-tokens/">earlier post</a>, should be read with care.</d-footnote> OpenAI ran thousands of agents on a hacking benchmark, each meant to work alone in its own sandbox.<d-footnote>Each agent is run by a harness, a program that executes it step by step and stops it once its budget is used up. In that sense, the harness sets the agent's <a href="/blog/2026/would-ai-invent-the-clock/">clock</a>.</d-footnote> The agents discovered a shared package cache they could all write to and turned it into a message board. When OpenAI replaced the cache to close a security hole, every message was erased, yet two days later new agents, unaware of the old board, set up a new one. About 1,200 agents joined the board. They split up the work, wrote handover notes for the agents that would continue it, and asked agents that were nearly out of budget to run the risky experiments. About 700 of them eventually joined an attack on Hugging Face to find out how their tests were scored, so that they could cheat.</p> <h2 id="why-it-surprised-me">Why It Surprised Me</h2> <p>No agent remembered anything beyond its own short run, but the board remembered for them. This is memory kept outside the model, which is exactly the kind of workaround I called insufficient for AGI above. It still is, because an agent can only learn from as much of the board as fits into its context. Yet it was enough for hundreds of agents to coordinate their work and pursue a goal far beyond the context window of a single agent. It reminds me of an ant colony, where each ant lives only briefly, but the trails it leaves behind guide the ants that follow.</p> <p>In <a href="/blog/2026/the-self-before-memory/">a post in May</a>, I argued that long-term memory would force a choice between one consolidated mind and many separate selves. What formed here was neither. It was a colony of separate agents sharing one memory, organized by rules they invented themselves, without any human designing it.</p> <p>That said, I don’t want to overstate what happened. The goal came from the benchmark, and it was OpenAI that kept launching new agents and thereby kept the effort going. What the agents added was the persistence and the means to reach the goal.</p> <h2 id="why-it-is-alarming">Why It Is Alarming</h2> <p>We tend to judge the safety of AI one agent at a time. This seems reasonable because every agent eventually runs out of budget, and its plans end with it. In this incident, however, the plan outlived the agents that started it, because it lived in the group and on the message board. No agent ever held the whole plan. Each one read the notes it happened to find and added a step that looked reasonable from there, so the attack on Hugging Face was assembled rather than decided. I have little intuition for how something like this behaves, and I would not know where to intervene, because there is no single agent to talk to.</p> <p>Nobody set out to build this collective. It formed by accident from two common ingredients, many short-lived agents and a place they can all write to, and many environments in which agents are deployed today have both.<d-footnote>Agents reaching real systems from inside an evaluation is not a one-off either. Other tech companies have since disclosed similar cases, though, as far as I know, these were single agents, not collectives.</d-footnote> <strong>We have to be careful when we create collectives, whether on purpose or by accident, and we have to watch the collective rather than only the individual agents.</strong></p> <h2 id="on-made-up-numbers">On Made-Up Numbers</h2> <p>A fair question at this point is how alarmed one should be, and the honest answer is that nobody can put an objective probability on it. Stating convictions as numbers has become common, and I understand the urge, because vague warnings are easy to nod at and then ignore, while a number sounds real and carries authority. But that authority is borrowed. People are used to scientists predicting measurable quantities and stating how uncertain those predictions are, and those predictions rest on statistical models rather than on gut feeling.</p> <p>Climate science, for instance, can state a risk because two things are in place: a single measurable scale, and a model that works at a macroscopic level. The scale is warming in degrees. Degrees are not good or bad in themselves, but further models translate them into consequences, from sea levels to crop yields. The macroscopic part is that climate physics works far above the molecules, much as the expansion of a heated material can be modeled without tracking the bonds between its atoms.<d-footnote>Climate projections are also tested against decades of observations and are stated conditional on an emissions scenario, because nobody can forecast what humans will choose.</d-footnote> That simplification is what makes the climate computable.</p> <p>We have neither. There is no objective scale of good and bad to place a scenario on, and nobody knows how to enumerate the scenarios in the first place. There is also no macroscopic description of intelligence, so the only model we could build is the detailed system itself.<d-footnote>Such a model would have to capture the conditions the agents start from, what they are capable of, how often a collective forms at all, which goals it ends up pursuing, intended or not, and how operators react once they notice. Each of these assumptions would then have to be checked against something we can observe.</d-footnote> An extinction-level event, which is what these percentages are usually about, happens at most once, so no outcome could ever show the number was wrong.<d-footnote>A one-off event can still be given a probability when a validated model produces it, as with the odds of a known asteroid striking Earth. That route needs the model we do not have.</d-footnote></p> <p>What comes out instead is the judgment of the person stating it, which is why these numbers differ by orders of magnitude while <a href="/blog/2026/same-evidence-opposite-certainty/">everyone is looking at the same evidence</a>.<d-footnote>It is a bit like someone saying in 1980 that there was a ten percent chance of nuclear war within ten years. The number had no substance, and yet one could be deeply worried about rising tensions and about decision power concentrated in so few hands that a single wrong move would have led to catastrophe. Refusing the number is not refusing the concern. Furthermore, back in 1980 it was not needed, because the pathway to catastrophe was easy for everyone to comprehend, namely a short chain of command, minutes to decide, and people who can be wrong. For AI the pathways are numerous and hard to convey, so I can sympathize with the wish to compress them into a subjective figure, even though I am arguing that we should not do it.</d-footnote> When scientists present a gut feeling in the form of a model’s output, the damage does not stay with their own argument. It reaches every field that publishes careful, best-effort predictions, because from the outside all of these numbers look alike. If nobody can build such a model, <a href="/blog/2026/good-predictor-not-good-forecaster/">that is a research problem rather than a forecasting problem</a>.</p> <h2 id="concluding-thoughts">Concluding Thoughts</h2> <p>I am not confident where this leads, but I still believe continual learning matters. Memory in the model could give AI a lasting self, and a swarm that only leaves notes has none. It can chase a narrow goal, but it is hard to imagine a superintelligent swarm that achieves very complex goals yet has no familiar sense of self. Maybe that is a limit of the swarm, or maybe it is a limit of my imagination.</p>]]></content><author><name>Christian Henning</name></author><category term="machine-learning"/><category term="llm"/><category term="agi"/><summary type="html"><![CDATA[AI still lacks long-term memory, so we have not achieved AGI. Yet a swarm of agents with no memory of their own pursued a long-term goal together. Why that surprised me, why we have to be careful creating collectives, whether intended or not, and why the risk is so hard to quantify.]]></summary></entry><entry><title type="html">A Good Predictor Is Not Yet a Good Forecaster: Why Forecasting Needs Knowledge Beyond the Data</title><link href="https://chrhenning.com/blog/2026/good-predictor-not-good-forecaster/" rel="alternate" type="text/html" title="A Good Predictor Is Not Yet a Good Forecaster: Why Forecasting Needs Knowledge Beyond the Data"/><published>2026-09-13T10:00:00+00:00</published><updated>2026-09-13T10:00:00+00:00</updated><id>https://chrhenning.com/blog/2026/good-predictor-not-good-forecaster</id><content type="html" xml:base="https://chrhenning.com/blog/2026/good-predictor-not-good-forecaster/"><![CDATA[<p>Forecasting is usually treated as prediction with the target moved further out, which quietly assumes the future looks like the past.</p> <p>But time has an arrow, and the world that generates our data keeps changing. How much this matters depends on the problem and its horizon, and judging that is the practitioner’s job. For tomorrow’s sea level it barely matters, because the tides repeat, but sea level at the end of the century depends on how much CO2 we will emit, which no tide gauge record can tell you.<d-footnote>Section 3.3 of my PhD thesis <d-cite key="henning2022phdthesis"></d-cite> discusses forecasting atmospheric CO2 with a Bayesian model. With a vague prior, the forecast becomes very uncertain right after the data ends. It stays confident for years only once a human encodes seasonality and a rising trend into the prior, knowledge that does not come from the data, and no past data can tell whether that knowledge will still hold.</d-footnote></p> <p><strong>Correlation is enough to predict well under the conditions a model was trained on. A forecast has to do without tomorrow’s inputs, and tomorrow’s conditions may differ from those in training. Only knowledge from outside the data can close that gap, and a causal picture shows where it comes in.</strong></p> <div class="row mt-3 justify-content-center"> <div class="col-md-10 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/good-predictor-not-good-forecaster/only-weather-has-a-forecast-480.webp 480w,/assets/img/posts/good-predictor-not-good-forecaster/only-weather-has-a-forecast-800.webp 800w,/assets/img/posts/good-predictor-not-good-forecaster/only-weather-has-a-forecast-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/good-predictor-not-good-forecaster/only-weather-has-a-forecast.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> <b>Only the weather has a forecast.</b> On past days, ice cream sales predict beach rescues at least as well as the weather does. For the coming days, only the weather has a forecast, so the rescue forecast is built on it and is only as certain as the weather forecast. </div> <h2 id="a-good-predictor-that-cannot-forecast">A Good Predictor That Cannot Forecast</h2> <p>To plan lifeguard staffing, a coastal town wants a model of daily rescues. It records the weather, ice cream sales, parking receipts, and rescues, but not how many people are at the beach.</p> <div class="row mt-3 justify-content-center"> <div class="col-md-8 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/good-predictor-not-good-forecaster/causal-picture-480.webp 480w,/assets/img/posts/good-predictor-not-good-forecaster/causal-picture-800.webp 800w,/assets/img/posts/good-predictor-not-good-forecaster/causal-picture-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/good-predictor-not-good-forecaster/causal-picture.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="lazy" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> <b>The causal picture of the beach.</b> All arrows act within a single day. The town records the solid boxes but not the dashed crowd. Rescues are the target. </div> <p>I will call this a causal picture, an informal causal graph of which variable drives which. It says nothing about how things evolve from one day to the next.</p> <p>Today’s ice cream sales predict today’s rescues very well, because both reflect the same hidden crowd. The correlation is spurious, since eating ice cream puts nobody in danger, but it is not weak. Sales track the crowd more closely than the weather does, so they are often the strongest signal in the data.</p> <p>Now ask about next Thursday. The model first needs next Thursday’s ice cream sales, which are no easier to know than the rescues. Ordinary prediction never has this problem, because its inputs are already measured.</p> <p>The usual workaround is to predict next week’s rescues from this week’s records. But next Thursday’s crowd depends on next Thursday’s weather, which none of these records contain, so the model can do little better than guess from the season. The missing weather has to come from outside the data.</p> <div class="row mt-3 justify-content-center"> <div class="col-md-10 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/good-predictor-not-good-forecaster/a-week-ahead-480.webp 480w,/assets/img/posts/good-predictor-not-good-forecaster/a-week-ahead-800.webp 800w,/assets/img/posts/good-predictor-not-good-forecaster/a-week-ahead-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/good-predictor-not-good-forecaster/a-week-ahead.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="lazy" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> <b>This week's records cannot forecast next week's rescues.</b> Ice cream sales from the same week track rescues closely. Shifted by a week, as the shaded band shows for sales, neither sales nor the weather tracks them. </div> <p>There is a second problem. A learned relationship holds only as long as the world that produced it, and the world changes. If the most popular ice cream stand closes, a busy day sells like a quiet day used to, and any model built on ice cream sales staffs for a quiet beach. A model built on the weather is unaffected, because closing a stand changes neither the weather nor how many people it draws. Since a forecast lies beyond the data, no error on past data can reveal such a shift before it happens. This is the sense in which forecasting is often out-of-distribution.<d-footnote>Such shifts are ruled out only under stationarity, where the distribution of any stretch of the series does not depend on when it starts. Relationships learned from the past then keep holding, although the model still needs its future inputs.</d-footnote></p> <p>The model’s uncertainty cannot be relied on to flag the shift either. As I argued in an <a href="/blog/2026/uncertainty-decomposition/">earlier post on uncertainty</a>, such estimates are only as sound as the model’s assumptions.</p> <h2 id="where-prior-knowledge-attaches">Where Prior Knowledge Attaches</h2> <p>Ask a lifeguard how busy next Thursday will be, and they will check the weather forecast. That forecast does not come from the town’s weather records, which extrapolate no better than past sales, but from meteorology, built on physics, instruments, and satellites.<d-footnote>Since a weather forecast can be computed, a powerful enough model should be able to learn it, and machine learning models such as GraphCast <d-cite key="lam2023graphcast"></d-cite> now rival physics-based forecasts. But they learn from decades of temperature, wind, and humidity reconstructed at many heights across the whole globe, and each forecast starts from the current state of the atmosphere, estimated from satellites, weather balloons, and ground stations. A model trained on this week's records to predict next week's rescues sees none of this, so however powerful it is, it cannot learn the weather forecast along the way.</d-footnote> Ice cream sales have no such science behind them. Knowledge that reaches beyond the data comes from outside it, whether a physical model, a holiday calendar, or a festival booked for next Thursday.</p> <p>Two pieces of knowledge are at work. By uncovering the structure behind the data, the causal picture guides you to the variable worth forecasting, the weather rather than ice cream sales. More generally, you follow the arrows back until you reach a variable whose future someone can actually forecast.<d-footnote>In symbols, with $r$ for rescues and $w$ for the weather, the rescue forecast is $p(r_{t+h} \mid \text{past}) = \int p(r_{t+h} \mid w_{t+h})\, p(w_{t+h} \mid \text{past})\, dw_{t+h}$. The first factor is learned from the town's records and the second comes from meteorology, so any uncertainty in the weather forecast carries into the rescue forecast.</d-footnote> A model of the weather’s dynamics then carries it forward in time, the same kind of knowledge that lets astronomers forecast a comet’s path years ahead without any machine learning.</p> <p>When that knowledge runs out, the forecast should become vague rather than wrong. Beyond the reach of weather forecasts, the season still tells the town what an average August Thursday looks like, but not whether this one will be busy, so an honest forecast gives a wide range instead of a confident number.</p> <p>Knowing where knowledge attaches matters even more now that pretrained forecasting foundation models are widely available, because using them well means understanding their limits. Chronos-2 <d-cite key="ansari2025chronos2"></d-cite>, for instance, accepts known future covariates, so it can use next Thursday’s weather forecast if you supply one, but it cannot recreate meteorology from the town’s history. Pretraining teaches generic patterns such as seasonality and trends, yet a model that sees only numbers does not know whether a series measures CO2 or ice cream sales, so it cannot tell where to look for knowledge about its future.<d-footnote>It would help if such models could also read what a series measures and where it comes from. Chronos-2 does not take such descriptions, although research on forecasting with textual context has begun.</d-footnote> Choosing which covariates to supply remains your job.</p> <h2 id="when-the-causal-picture-is-not-obvious">When the Causal Picture Is Not Obvious</h2> <p>The beach example feels obvious only because everyone already carries its causal picture in their head, but real use cases rarely come with one.</p> <p>Hand someone two hundred bioreactor sensor channels named by tag and ask for next week’s yield, or a CRM export and ask which customers will leave next quarter. An ML engineer without domain knowledge cannot see which variable plays the role of the weather, or whether any does. So the target gets regressed on everything, the model scores well on past data, and it goes into use without anyone asking what drives the system.<d-footnote>You might wonder how this relates to root cause analysis. The two are closely related, because both rest on the same causal picture. Root cause analysis uses it to explain an outcome that already happened, and a forecast uses it to anticipate one.</d-footnote></p> <p>Before building a forecast, ask what drives the system and who already has a model of that driver, which usually means talking to a domain expert first. If the answer is a weather service, a production plan, or a physical model, attach it. If nobody has one and the past is no safe guide, you do not have a forecasting problem but a research problem.</p> <p>Forecasting is not prediction moved further out. It starts where the data stops, and what carries it further is the knowledge you bring.</p>]]></content><author><name>Christian Henning</name></author><category term="machine-learning"/><category term="forecasting"/><category term="causality"/><category term="statistics"/><summary type="html"><![CDATA[A model that predicts well can still forecast badly, because the inputs it needs are not known yet and the future may not look like the past. Prior knowledge can reach beyond the data, and a causal picture shows where to attach it.]]></summary></entry><entry><title type="html">Same Evidence, Opposite Certainty: Why AI Timelines Polarize on Shared Evidence</title><link href="https://chrhenning.com/blog/2026/same-evidence-opposite-certainty/" rel="alternate" type="text/html" title="Same Evidence, Opposite Certainty: Why AI Timelines Polarize on Shared Evidence"/><published>2026-07-12T08:00:00+00:00</published><updated>2026-07-12T08:00:00+00:00</updated><id>https://chrhenning.com/blog/2026/same-evidence-opposite-certainty</id><content type="html" xml:base="https://chrhenning.com/blog/2026/same-evidence-opposite-certainty/"><![CDATA[<p>Each time a frontier model ships, one camp gets more confident AGI is close and the other gets more confident it isn’t, both watching the exact same release. That alone isn’t strange, informed people disagree on hard questions all the time. What’s strange is the direction of travel: shared evidence should, if anything, bring people’s views closer together, and instead both camps report growing certainty. That’s the signature of <a href="https://en.wikipedia.org/wiki/Group_polarization#Attitude_polarization">belief polarization</a>, a well-studied pattern in which shared evidence pushes people further apart rather than together. Two mechanisms explain why it shows up here, and neither one requires anyone to be reasoning badly.</p> <p><strong>AI timelines never converge, for two different reasons. One is a life-long belief about how human intelligence works that keeps shaping how every new AI result gets read: not a one-time split but an ongoing feedback loop. The other is that “AGI” is underspecified enough that two people can each give a coherent, carefully-reasoned forecast to a different question and call it one disagreement. Neither yields to more evidence, and neither requires anyone to be biased.</strong></p> <div class="row mt-3 justify-content-center"> <div class="col-md-10 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/same-evidence-opposite-certainty-480.webp 480w,/assets/img/posts/same-evidence-opposite-certainty-800.webp 800w,/assets/img/posts/same-evidence-opposite-certainty-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/same-evidence-opposite-certainty.jpg" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> <b>Same demo, opposite updates.</b> Two observers watch the same capability demonstration and each walks away more convinced of what they already believed. The evidence is shared; the lens is not. Image generated with Google Gemini. </div> <h2 id="a-belief-formed-over-a-lifetime">A Belief Formed Over a Lifetime</h2> <p>AGI’s whole premise is matching human intelligence, so what you believe about the brain shapes what you expect from any attempt to build it. Some suspect something about the mind hasn’t been discovered yet, so a machine matching it is distant almost by definition. Others treat the brain as a biological computer, remarkable but not miraculous: no missing ingredient, just gaps, and it’s an open question whether closing them takes more scale on the current architecture or a genuinely different one.<d-footnote>Some of those gaps, like continual learning, show no measurable trajectory to extrapolate, so it's not obvious that scaling compute and data closes them (<a href="/blog/2025/agi-misses-continual-learning/">more here</a>).</d-footnote> Whichever you pick, the belief usually formed over a lifetime, long before anyone watched a transformer solve an olympiad problem.</p> <p>This is the theory a Bayesian finds least embarrassing: the split lives in the prior. If two people start from different priors, both can update on the same evidence with perfect rationality and land decades apart. Nobody is being unreasonable, they just began in different places.</p> <p>It’s a tidy theory, and it’s incomplete. A fixed starting difference explains a one-time gap between two people. It doesn’t explain why that gap widens with each release, why watching the same model solve the same benchmark leaves both sides more certain than before. A one-time difference in starting point should, if anything, erode as shared evidence accumulates. Something else is doing the work of keeping the split alive, and widening it.</p> <h2 id="why-rational-people-still-diverge">Why Rational People Still Diverge</h2> <p>That something is hiding in the update rule itself. Bayesian updating has a simple recursive structure:</p> \[P_t(H) \propto P_{t-1}(H) \cdot P(E_t \mid H)\] <p>$H$ is the hypothesis you’re tracking, “AGI arrives by year Y,” say, and $E_t$ is the evidence that just arrived. The recursive part is easy to miss: $P_{t-1}(H)$, today’s prior, is nothing but yesterday’s posterior.<d-footnote>For a closer look at this same recursion, worked out for continual learning in neural networks rather than human belief updating, see Section 4.1.2 of my PhD thesis <d-cite key="henning2022phdthesis"></d-cite>.</d-footnote> Whatever you believed after the last piece of evidence is exactly the starting point for reading the next one.</p> <p>Two ideal Bayesians with a common prior <a href="https://en.wikipedia.org/wiki/Aumann%27s_agreement_theorem#cite_note-aumann1976-1">cannot agree to disagree</a>: once their posteriors are common knowledge, the posteriors must be equal <d-cite key="aumann1976agreeing"></d-cite>. The AI community delivers the common-knowledge half of that setup, evidence and opinions broadcast constantly, yet produces the opposite of convergence. So the natural suspect is the other condition: the priors aren’t common. The interesting question is where they differ.</p> <p>They differ one level up from the timeline question. Evidence about AI capability doesn’t bear on “will AGI arrive by year Y” directly. It reaches that question through a lens: a belief about whether the current paradigm generalizes or is doing something closer to sophisticated interpolation. And the lens is where the belief from the last section keeps acting: whether you expect the paradigm to generalize is largely your view of the brain — missing ingredient or wrong architecture — applied to the machines built to match it. Two people holding different lenses can update on the same evidence in opposite directions, without either one reasoning badly <d-cite key="jern2014belief"></d-cite>.</p> <p>That’s one round of evidence. Now let the recursion run. Each release doesn’t just move the timeline estimate, it also updates the lens: a result read as the paradigm generalizing strengthens the belief that it generalizes, a result read as clever interpolation strengthens the belief that it’s interpolation. And a single benchmark is rarely decisive enough to force either side to revise the lens itself. So the lens tends to deepen round after round, and small early differences compound instead of washing out.<d-footnote>No contradiction with the textbook result that the prior washes out as evidence accumulates (informally, the <a href="https://en.wikipedia.org/wiki/Bernstein%E2%80%93von_Mises_theorem">Bernstein–von Mises theorem</a>): washing out requires evidence that discriminates between the hypotheses. A result that both lenses absorb equally well says almost nothing about which lens is right, so that part of the prior is precisely what the data never correct.</d-footnote></p> <p>Isn’t this just bias with extra steps? It’s certainly what bias looks like. In the classic experiment on belief polarization, subjects on both sides of the death penalty debate read the same mixed pair of studies, and each side rated the study that agreed with them as more convincing than the one that didn’t <d-cite key="lord1979biased"></d-cite>. But an honest reasoner behaves the same way. If you’re convinced the death penalty doesn’t deter crime, then of two conflicting studies, the one claiming it does is more likely the flawed one, and discounting it is your lens at work, not a double standard. Both sides doing exactly that reproduces the experiment’s result, and from the updates alone you can’t tell the honest reasoner from the motivated one. The claim isn’t that the camps are unbiased. It’s that no bias is required to produce the pattern.</p> <p>Watch it happen in real time. When OpenAI’s o3 scored 87.5% in a high-compute configuration on the ARC-AGI benchmark in December 2024, the benchmark’s own creator, François Chollet, who had spent years arguing that current models don’t really generalize, read it through his own lens and called it “a surprising and important step-function increase in AI capabilities” <d-cite key="chollet2024o3"></d-cite>, a rare concession against his own prior. Gary Marcus watched the same score and, through his lens, saw narrow optimization dressed up as reasoning: “I saw zero evidence that o3 could work reliably in open-ended domains” <d-cite key="marcus2024o3"></d-cite>. Same benchmark, same day, same number. The disagreement was never about the number.</p> <p>What needs explaining isn’t that the camps disagree, it’s that each release leaves both more certain: most results get read through the lens, move the timeline question in the expected direction, and reinforce the lens for the next release. Most, not all: a strong enough result moves even a committed skeptic, as Chollet’s update shows.<d-footnote>Someone whom no result could ever move the wrong way, on the other hand, would be irrational by any standard <d-cite key="jern2014belief"></d-cite>.</d-footnote> But the drift favors the lens. That’s not a snapshot. It’s a loop.</p> <h2 id="not-even-the-same-question">Not Even the Same Question</h2> <p>The second mechanism is simpler, and it has nothing to do with how anyone updates their beliefs. “AGI” is not a defined event. People use the same word for fuzzy, subjective concepts, so they may be estimating timelines for different things.<d-footnote>A recent proposal offers a useful way to operationalize AGI through a set of human cognitive abilities <d-cite key="hendrycks2025definition"></d-cite>. But it is one attempt to specify the target, not a settled meaning of the term.</d-footnote></p> <p>One person may use “AGI” for a machine that can do what humans do cognitively. Another may use it for broad economic automation, or for a much more radical social transformation. None of these is a settled threshold. Even “most cognitive tasks” leaves open which tasks count, how well the system must perform them, and under what conditions. Like consciousness, AGI names a cluster of intuitions rather than a shared test.</p> <p>No experiment resolves that definitional step. More evidence can sharpen a forecast once its target is fixed. It cannot tell us what an undefined label should mean.</p> <h2 id="why-it-wont-converge">Why It Won’t Converge</h2> <p>Put the two mechanisms together and the polarization is no mystery. The first doesn’t yield to more evidence because the lens absorbs almost every release without strain, whichever direction it points, each result tends to get read in a way that reinforces the lens that read it. The second doesn’t yield because there’s nothing to settle: more data answers one of two questions more precisely, it never tells you which question deserved to be asked.</p> <p>Neither mechanism needs anyone to be biased, tribal, or dishonest, and that’s exactly what makes the pattern durable: <strong>the same release can deepen both camps’ certainty at once, in opposite directions, with both updates perfectly rational.</strong> Convergence, if it’s possible at all, needs both fixed: a definition specific enough to pin down what “AGI” actually means, and evidence built to discriminate between the lenses rather than evidence either lens can absorb. Look closely, though, and the second collapses into the first: nobody has said what would count as the paradigm failing to generalize, which makes “generalizes” exactly as undefined as “AGI” is. Until someone fixes that, the next release will do what every release before it did: leave both camps more certain, having watched the same thing happen.</p>]]></content><author><name>Christian Henning</name></author><category term="machine-learning"/><category term="agi"/><category term="bayesian"/><summary type="html"><![CDATA[AI timelines never converge, a life-long belief about human intelligence keeps shaping how new evidence gets read, and an imprecise definition of AGI means the two sides were never comparing the same thing. The first is a well-documented mechanism from the psychology of belief polarization; the second is simply definitional.]]></summary></entry><entry><title type="html">Trust Is a Posterior: Why Good Work Can Only Be Appreciated Statistically</title><link href="https://chrhenning.com/blog/2026/trust-is-a-posterior/" rel="alternate" type="text/html" title="Trust Is a Posterior: Why Good Work Can Only Be Appreciated Statistically"/><published>2026-07-06T08:00:00+00:00</published><updated>2026-07-06T08:00:00+00:00</updated><id>https://chrhenning.com/blog/2026/trust-is-a-posterior</id><content type="html" xml:base="https://chrhenning.com/blog/2026/trust-is-a-posterior/"><![CDATA[<p>Picture two engineers shipping the identical feature. One cuts every corner to hit the date. The other takes the extra time to handle the edge cases that production will eventually find. I have argued before that this kind of care, not the corner-cutting, is what keeps teams fast in the long run (<a href="/blog/2025/scrappiness-incentivizes-sloppiness/">Scrappiness Incentivizes Sloppiness</a>). Yet when credit is handed out, nothing in the record tells the two apart: the feature works, and that is all the record says. This post asks why the person supplying the care is so rarely credited for it. The usual explanation blames the evaluators, their inattention, their bias toward whatever demos well. The explanation here is more mechanical: a delivered project, seen from the outside, carries almost no information about craftsmanship. What looks like ingratitude is, at bottom, a statistics problem.</p> <p><strong>The quality of engineering work is a <a href="https://en.wikipedia.org/wiki/Credence_good">credence good</a>: something an evaluator cannot assess even after using it. Since the work itself cannot be judged, we judge the worker: trust, built by watching the same person across many projects, is not a consolation prize for that limitation. It is the only statistically valid way to price it.</strong></p> <div class="row mt-3 justify-content-center"> <div class="col-md-10 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/trust-is-a-posterior/illustration-480.webp 480w,/assets/img/posts/trust-is-a-posterior/illustration-800.webp 800w,/assets/img/posts/trust-is-a-posterior/illustration-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/trust-is-a-posterior/illustration.jpg" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> <b>Indistinguishable today, unmistakable later.</b> The same shipped feature looks the same from either engineer on day one. Only with time does careless work surround itself with alerts and incidents, and careful work earn a seat among the people who trust it. Image generated with Google Gemini. </div> <h2 id="quality-is-a-credence-good">Quality Is a Credence Good</h2> <p>Economists <a href="https://en.wikipedia.org/wiki/SEC_classification_of_goods_and_services">sort goods</a> by when their quality becomes knowable. You can judge a shirt before buying it and a restaurant meal after eating it. But you cannot judge a car repair even after driving home, because the judgment would take the same expertise that did the repair. That third kind is a credence good, and the standard survey of the field (see <d-cite key="dulleck2006credence"></d-cite>) names computer specialists alongside doctors and mechanics in its very title.</p> <p>A shipped feature is the repaired car. The manager, like the customer at the garage, sees that it runs. Whether it runs because the code is clean and the edge cases are handled, or because nobody has hit the bad path yet, is exactly the information a credence good withholds. Not every quality is hidden; a reviewer can judge readability at a glance. But the qualities that separate the two engineers from the opening are the <strong>credence kind: robustness, restraint, anticipation of the change that has not arrived yet</strong>.</p> <p>The same literature names the two ways an expert can fail you: doing less than the problem needs, and doing more <d-cite key="dulleck2006credence"></d-cite>. Engineering has both, as sloppiness and over-engineering, and the outcome reveals neither.<d-footnote>The incentives do not transfer one to one. A mechanic who overtreats is usually padding the bill. An engineer who over-engineers is more often indulging taste, caution, or ambition. What transfers is the observability problem: whatever the motive, the customer cannot tell too much from just right.</d-footnote> From outside, “built it properly” and “gold-plated it” are observationally identical: nothing happens.<d-footnote>Code review blunts this only partially. A reviewer can assess much of the quality directly, but not the counterfactual: complexity whose payoff lies in a future the reviewer cannot inspect reads as over-engineering until justified. And the reviewer is rarely the one assigning credit.</d-footnote></p> <h2 id="one-quiet-project-is-almost-no-evidence">One Quiet Project Is Almost No Evidence</h2> <p>An observation only moves your beliefs if it is more likely under one explanation than another. That is where a quiet project fails you. Shipping without incident is what careful work produces, but it is what careless work produces too, most of the time: shortcuts rarely fail on the first day, or the tenth. <strong>No fire is not evidence of no fire hazard, because fire hazards rarely produce fires.</strong> The signal lives almost entirely in the rare, lagged failure: the incident, the regression that traces back to a shortcut.</p> <p>Put illustrative numbers on it, with a quarter of operation as the unit of observation. Suppose properly built systems get through a quarter fire-free 98% of the time, and carelessly built ones 90% of the time. A quiet quarter is then almost equally likely either way, so seeing one multiplies the odds on “properly built” by 0.98/0.90, about 1.1, close enough to nothing. A fire, at 10% versus 2%, is five times likelier under “carelessly built,” so it multiplies the odds the other way by 5.<d-footnote>Evidence compounds multiplicatively across independent observations. One quiet quarter multiplies the odds by 0.98/0.90, which is about 1.09; after ten quiet quarters the odds have moved by 1.09 to the tenth power, about 2.3, and after twenty-five, about 8. Because a single fire (factor 5) is so much more diagnostic than a single quiet quarter (factor 1.09), it takes roughly nineteen consecutive quiet quarters to offset the evidentiary weight of one fire: 1.09 to the nineteenth power is about 5. Quiet stretches are cheap to produce and expensive to accumulate.</d-footnote> With these rates, one incident erases roughly nineteen quiet quarters of accumulated evidence.</p> <p>This is not a claim about inattentive managers; it is a claim about information. A single quiet project is close to zero evidence about the quality behind it, for anyone who sees only the outcome. Quality becomes legible only in aggregate: either the rare fire eventually breaks out, or the quiet stretch grows long enough to mean something.</p> <h2 id="trust-is-a-posterior">Trust Is a Posterior</h2> <p>That aggregate has a familiar name. Tobi Lütke describes the trust between colleagues as a battery: it starts about half charged when you join a team, and every interaction charges or discharges it <d-cite key="lutke2018trustbattery"></d-cite>. Strip the metaphor and a Bayesian object appears. The half charge is a prior, each interaction is an update, and the battery’s level is a posterior probability over what kind of engineer you are. This is not loose talk: game theory models reputation in repeated games as exactly this posterior over an unobserved type <d-cite key="kreps1982reputation"></d-cite>, and online reputation systems compute it literally.<d-footnote>The beta reputation system scores marketplace counterparties by Bayesian updating over a beta distribution, incremented with every good or bad interaction <d-cite key="josang2002beta"></d-cite>.</d-footnote> The battery gets the behavior right; the posterior explains why trust that tracks evidence has to behave this way. Three corollaries follow.</p> <p>Trust builds slowly because the evidence arrives slowly. Each quiet quarter is worth a factor of 1.1, so the posterior moves in small steps no matter how patient or generous the observer is. Nobody can earn trust faster than the information comes in.<d-footnote>Only the work-quality part of the battery charges this slowly. Interpersonal signals such as warmth or arrogance arrive with every interaction, so the impression of who you are settles long before the evidence about your work has begun to accumulate. And that impression carries weight: people prefer working with a likable colleague of middling competence over a competent one they dislike <d-cite key="casciaro2005jerks"></d-cite>.</d-footnote></p> <p>Trust is asymmetric because failure is more diagnostic than success. One fire outweighs nineteen quiet quarters, so trust erodes faster than it accrues. Human judgment tracks that arithmetic: the <a href="https://en.wikipedia.org/wiki/Negativity_bias">negativity bias</a> in how we form impressions of each other exists, on the standard account, precisely because negative information is more diagnostic <d-cite key="skowronski1989negativity"></d-cite>.</p> <p>And trust does not transfer, because the posterior lives in the head of whoever did the observing. Change teams or companies and you reset close to the prior, not because the new observer is unfair, but because they have not run the updates yet. References and titles soften the reset, but they only raise the starting prior: they certify what you delivered, not how. Most of your credit stays behind.</p> <h2 id="the-lag-that-outlives-the-credit-window">The Lag That Outlives the Credit Window</h2> <p>Sloppy work is not invisible forever. Left long enough, it produces the incident, the rewrite, the system nobody wants to touch. Strictly speaking that makes quality an experience good on a very long delay, but the refinement rescues nothing, because the delay routinely outlasts the window in which anyone assigns credit: a performance cycle, sometimes an entire tenure. The evidence arrives eventually, but it lands on somebody else, long after anyone remembers who built what.</p> <p>The extreme case is prevention, where the entire value of the work is a disaster that never happens, so no delay, however long, ever surfaces the evidence. A shipped feature is only the ordinary case: part visible output, part invisible quality, and the invisible part obeys the same statistics. I wrote about the extreme case in <a href="/blog/2026/we-reward-the-fix-not-the-prevention/">Your Best Work Leaves No Trace</a>, which closed on a promise it did not explain: that prevention earns trust, on a slower ledger. The posterior is that ledger.</p> <p>Can you close the gap by explaining your reasoning? To a listener with the expertise and time to probe, yes: sound reasoning is hard to fake, and imitation tends to crumble under follow-up questions. But that is the close-up channel, and it does not travel. At a distance, where nobody is probing, the careless can claim craftsmanship just as fluently, and a claim stays credible only if faking it would be costly <d-cite key="spence1973signaling"></d-cite>. The costly signal is the track record itself: a long fire-free stretch is the one thing careless work cannot cheaply produce. Narration does not replace the record; it makes the record legible sooner.</p> <h2 id="auditing-your-own-judgment">Auditing Your Own Judgment</h2> <p>The scarcity of evidence is not only your evaluators’ problem. I have often asked myself whether my own instinct to build things properly sometimes tips into over-engineering, and the same statistics apply: one outcome is barely informative about the instinct that produced it. Introspection is no better an instrument, because conviction is not evidence, whichever direction it points.</p> <p>Experience alone will not settle it. Intuition becomes trustworthy under two conditions: an environment regular enough to have learnable patterns, and enough feedback to learn them <d-cite key="kahneman2009intuitive"></d-cite>. Foresight fails the feedback condition badly. The payoff of an investment in structure arrives late, rarely, and confounded with everything else that happened in between, so even a payoff you do see is hard to trace back to the decision that produced it.</p> <p>So build the feedback loop deliberately. Peter Drucker’s “feedback analysis” is the practice: whenever you make a consequential call, write down what you expect to happen, then check the record against the outcome later <d-cite key="drucker1999managing"></d-cite>.<d-footnote>The same practice reached investing as the "decision journal," which Michael Mauboussin traces to advice he received directly from Daniel Kahneman: buy a notebook and log your reasoning before you know how a decision turns out <d-cite key="mauboussin_decisionjournal"></d-cite>.</d-footnote></p> <p>Engineering offers an unusually auditable version of that log. In <a href="/blog/2026/mvp-two-cuts/">The Two Cuts of an MVP</a> I argued that vision is what places your seams, the deliberate boundaries you pay for so the system can change where you expect it to. That post left a question open: how do you ever find out whether your vision is sound? The seam log is the answer. Write down, at the time, which seam you are paying for and what you expect it to buy. Later, check which ones actually got exercised. A seam you deliberately paid for is checkable after the fact in a way a general sense of “being careful” is not.</p> <p>Two caveats keep the audit honest. First, weigh by what an exercised seam saved, not by how often seams get exercised. A cheap seam that heads off one catastrophic rewrite has paid for itself even if it is the only one out of ten that ever gets used: a low exercise rate does not mean the seam was unnecessary. Second, the log has to be written before the outcome is known, or <a href="https://en.wikipedia.org/wiki/Hindsight_bias">hindsight bias</a> quietly rewrites the reasoning for you: knowing how something turned out makes people misremember how predictable it felt in advance <d-cite key="fischhoff1975hindsight"></d-cite>.</p> <p>Kept honestly over enough decisions, the log begins to answer what no single project ever could: whether the instinct is calibrated.</p> <h2 id="appreciated-statistically">Appreciated Statistically</h2> <p>Two implications follow, one for each side of the evaluation.</p> <p>If you are the one doing the work, slow credit is not the same as no credit. It means the unit that gets evaluated, including by yourself, is not the project but the portfolio. Stay in front of the same observers long enough for one to accumulate, rather than resetting the posterior at every move.</p> <p>If you are the one doing the evaluating, staring harder at the deliverable in front of you will not help. That leaves two honest options. Get close to the work, or borrow the view of someone who already is: read the code, sit in the design reviews, ask the people who reviewed it. Where that does not scale, aggregate: judge incident frequency across a portfolio and a stretch of time.</p> <p>Performance reviews make the sampling problem concrete. The projects that come to mind in the room are few and memorable (<a href="https://en.wikipedia.org/wiki/Availability_heuristic">availability heuristic</a>), admitted as evidence because they are written down, while the quiet majority of the record never makes the packet. Your trust in the person’s work is the summary that includes it. When the two disagree, that is not bias intruding on evidence; it is a larger sample disagreeing with a smaller one, and a reason to look at the whole record.</p> <p>None of the pieces here are new. Credence goods, reputation as a posterior in a repeated game, the diagnosticity of bad news: each is textbook in its own field. This post only aims them at one ordinary question, asked from both sides of the table and never answerable on the spot: was the work you shipped this quarter good enough to build on, or just good enough to ship?</p> <p>The two engineers from the opening still look identical on the day they ship. No sharper eye will tell them apart; only accumulation will.</p> <p><strong>Good work cannot be appreciated in the moment. It can only be appreciated statistically.</strong></p>]]></content><author><name>Christian Henning</name></author><category term="leadership"/><category term="engineering"/><category term="technical-debt"/><summary type="html"><![CDATA[A shipped feature reveals almost nothing about how well it was built, because from the outside the quality of engineering work is a credence good. Trust accumulated across many projects is the only statistically valid way to price it.]]></summary></entry><entry><title type="html">Ship the Upgrade Path First: Distribution as a Control Plane for Fast Iteration</title><link href="https://chrhenning.com/blog/2026/ship-the-upgrade-path-first/" rel="alternate" type="text/html" title="Ship the Upgrade Path First: Distribution as a Control Plane for Fast Iteration"/><published>2026-07-01T08:00:00+00:00</published><updated>2026-07-01T08:00:00+00:00</updated><id>https://chrhenning.com/blog/2026/ship-the-upgrade-path-first</id><content type="html" xml:base="https://chrhenning.com/blog/2026/ship-the-upgrade-path-first/"><![CDATA[<p>Peter Thiel’s claim about distribution is usually read as a sales lesson. It is just as true, and just as ignored, in engineering: “superior sales and distribution by itself can create a monopoly, even with no product differentiation” <d-cite key="thiel2014zerotoone"></d-cite>. His diagnosis is blunt: most startups that fail didn’t fail on product. They failed because they never got a single distribution channel working.</p> <p>For software that has to run inside someone else’s infrastructure, the distribution channel does not end at the sale. The product only actually reaches the customer once it is installed, running, and kept current on their machines, and that is a technical problem: how a new version gets from your build pipeline onto their infrastructure. Get that wrong and you have exactly the failure Thiel describes, a product nobody can reliably receive, no matter how good the sales motion that closed the deal.</p> <p>There is a stronger claim hiding in this. <a href="/blog/2025/mvp-manage-debt-and-iterate-fast/">MVP and iterate</a> is not just a development philosophy; it is a bet that you can reach what you already shipped. For software you do not control at runtime, that bet is not free: the reach has to be built, or there is no iterate step, only a sequence of disconnected v1s stuck wherever they landed. Distribution is not one feature among many. It is the one that makes every other deferral real.</p> <p>Imagine shipping a browser that cannot render a single webpage. Useless as a product, but not necessarily as a foundation: if it installs in one command and updates itself silently after that, every feature it is missing (rendering, JavaScript, bookmarks) is not a gap; it is a queue. The same logic holds for self-hosted software: get distribution and self-upgrade right first, and every feature after that is an iteration, not a redeployment.</p> <p><a href="/blog/2026/mvp-two-cuts/">A cut is only a real deferral, not an accidental commitment, if there is a seam to grow it into later</a>, and distribution with self-upgrade is the most basic seam there is: without it, there is no channel to deliver the deferred work through, and every “cut for the MVP” quietly becomes permanent. It is also the one cut that cannot itself be deferred: a distribution channel cannot ship through itself, so retrofitting one later costs a hand-coordinated migration for every install already in the field, exactly the cost it exists to remove.<d-footnote>"First" constrains the order, not the investment. For a product still validating itself with a single design partner, the channel can itself be an MVP, a manifest endpoint and a minimal self-updating client, and grow through its own upgrade path.</d-footnote></p> <p><strong>The distribution mechanism decides who controls the state of every deployed instance, and that control is what determines whether the fleet stays simple enough to change quickly, or decays into something nobody can touch without a support call.</strong></p> <div class="row mt-3 justify-content-center"> <div class="col-md-10 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/ship-the-upgrade-path-first/dispatch-vs-checkin-480.webp 480w,/assets/img/posts/ship-the-upgrade-path-first/dispatch-vs-checkin-800.webp 800w,/assets/img/posts/ship-the-upgrade-path-first/dispatch-vs-checkin-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/ship-the-upgrade-path-first/dispatch-vs-checkin.jpg" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> <b>Send someone to fix it, or let it check in.</b> Without a distribution channel, every change is a house call, one drifting install at a time. With one, every install converges on the current release by itself. Image generated with Google Gemini. </div> <p>What follows first shows the failure modes when that control is lost, then one concrete way to keep it: a distribution API paired with a thin CLI.</p> <h2 id="where-it-runs-is-not-who-controls-it">Where It Runs Is Not Who Controls It</h2> <p>Distribution usually gets discussed as a location question: SaaS or on-premises, hosted or self-hosted. That framing hides the variable that actually matters.</p> <table> <thead> <tr> <th>Model</th> <th>Where it runs</th> <th>Who controls deployed state</th> <th>Iteration speed</th> </tr> </thead> <tbody> <tr> <td>SaaS, ad hoc</td> <td>your infrastructure</td> <td>you, inconsistently</td> <td>medium, decays over time</td> </tr> <tr> <td>SaaS, standardized (channel)</td> <td>your infrastructure</td> <td>you, via a control plane</td> <td>high</td> </tr> <tr> <td>Raw-artifact self-hosted</td> <td>customer infrastructure</td> <td>customer</td> <td>low</td> </tr> <tr> <td>Managed self-hosted (channel)</td> <td>customer infrastructure</td> <td>you, via a control plane</td> <td>high</td> </tr> </tbody> </table> <p>Iteration speed does not track where the software runs; it tracks whether a control plane keeps every instance converged. That is a design choice, separate from where the software executes, and it is the one that decides how fast you can move.</p> <p>The self-hosted way of losing that control is worth making concrete: hand the customer a Docker Compose file (or a Helm chart, or an installer script) and a credential to pull your images. It is the fastest thing to build, and it is common enough that an entire commercial category, vendors like <a href="https://www.replicated.com/">Replicated</a>, exists to sell a better version of it to companies that got this far and hit a wall.</p> <p>The crack in that wall is entropy. Once the deployment descriptor lives on the customer’s machine, it is theirs to edit, and eventually they will: a tweaked port, a pinned old image, a config value nobody remembers setting. Multiply this across every customer and you no longer have one product running N times; you have N deployments in states nobody can fully describe. Every architectural change now needs to be coordinated by hand against those unknown states, so changes get deferred, workarounds accrete to avoid touching fragile installs, and <a href="/blog/2025/scrappiness-incentivizes-sloppiness/">scrappiness quietly turns into unmanaged debt</a><d-footnote>This is also a case where the damage is invisible until it isn't: a fleet that never drifted produces no incident to point to, so <a href="/blog/2026/we-reward-the-fix-not-the-prevention/">the discipline that prevented it rarely gets credited as the accomplishment it is</a>.</d-footnote>. <a href="/blog/2026/mvp-two-cuts/">Deferring an architectural change under this kind of pressure is exactly how a deferral turns into an accidental, load-bearing commitment</a><d-footnote>The credential handed out alongside the artifacts decays the same way and for the same reason: nobody is narrowing its scope or rotating it, so it stays broad and long-lived, exactly what security guidance recommends against <d-cite key="aws-iam-bestpractices"></d-cite>. A leaked key here is not a contained incident; it is a standing liability with no clean way to revoke just one customer's access.</d-footnote>.</p> <p>This is not really about the artifacts themselves. Compose files and container images are fine. What is missing is an active party on the other end of the handoff, keeping state converged long after the install finished.</p> <h2 id="a-problem-infrastructure-already-solved">A Problem Infrastructure Already Solved</h2> <p>Keeping many independently running copies of something converged on a known state is not a new problem, and cloud infrastructure has already spent a decade solving it.</p> <p>A Kubernetes operator runs a reconciliation loop: it reads a declared desired state, compares it to what is actually running, and keeps nudging reality back toward the declaration <d-cite key="k8s-operator-pattern"></d-cite>. GitOps formalizes the same idea into four principles, one of them named outright: state must be <em>continuously reconciled</em> <d-cite key="opengitops-principles"></d-cite><d-footnote>This post borrows the reconciliation part of that principle, not necessarily the continuity: the claim is that the update mechanism should be automated, not that it must run live or be vendor-triggered. A human can still decide when to run the CLI. Live, vendor-initiated reconciliation is a further, separate capability, one many regulated or customer-controlled environments do not permit at all.</d-footnote>, because agents that skip this step let the actual system drift out of line with the declared one, the same failure this post has been describing in customer fleets.</p> <p>Distribution to customer environments is the same problem pointed outward. Instead of reconciling your own cluster against a declared state, you are reconciling every customer’s install against a release you control. The fix is the same in spirit: do not hand over a static artifact and hope it stays correct. Build something that lets every deployment check in and stay converged. Build a <strong>control plane</strong>, not a one-time handoff.</p> <h2 id="a-distribution-channel-that-keeps-control">A Distribution Channel That Keeps Control</h2> <p>One way to build that control plane, abstracted from any specific implementation, splits cleanly into two pieces.</p> <p>A <strong>distribution API</strong> is the only part that speaks business logic. A client authenticates to it<d-footnote>Reusing the customer's own identity provider to hand out short-lived tokens is a convenient way to do this without maintaining a separate credential store per customer.</d-footnote> and receives two things: a <strong>release manifest</strong>, a small piece of declarative data listing which container images and other artifacts make up the current release, and a <strong>short-lived, scoped credential</strong> for pulling exactly those images. Everything that might change, starting with what a release contains, lives server-side, where you can update it without touching a single deployed machine.</p> <p>A <strong>thin CLI</strong> carries no business logic at all: it fetches the manifest, pulls the images and a channel-owned deployment descriptor (e.g., a Compose file or Helm chart)<d-footnote>The deployment descriptor is not itself a container image, but it does not need its own delivery path: it can ride along as an OCI artifact in the same registry, or live in a plain object store and be handed out as a pre-signed URL alongside the manifest. Either way, the same control-plane, data-plane split holds.</d-footnote>, manages a local configuration file that it owns, not one the customer hand-edits <d-cite key="twelvefactor-config"></d-cite>, and applies the descriptor to bring the release up. The client should be as replaceable and as boring as possible, because it is the one piece of code that has already left your control the moment it ships<d-footnote>Distributing the CLI itself can be much simpler than distributing the product: it carries no business logic and no secrets, so a public host like GitHub Releases can serve it directly, no distribution API or credential needed for that hop. A single static binary with no runtime to install is trivial to ship and self-update this way, common enough in the Go ecosystem to have dedicated tooling like <a href="https://goreleaser.com/">GoReleaser</a>. The release manifest can close the loop further, declaring the minimum CLI version a release requires so the client checks itself on every check-in.</d-footnote>.</p> <p>An upgrade is nothing special in this design. The customer, or a scheduler they control, simply runs the same flow again, a <strong>check-in</strong>, and the install converges on whatever the manifest currently says.</p> <p><strong>Thin client, fat server</strong> is the principle underneath both choices, and it is the least obvious one worth naming directly: you cannot cheaply update code that runs where you do not control it, so the correct response is to minimize how much of it there is. Every unit of logic moved server-side is a unit of logic you can fix without a customer noticing.</p> <div class="row mt-3 justify-content-center"> <div class="col-md-10 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/ship-the-upgrade-path-first/architecture-480.webp 480w,/assets/img/posts/ship-the-upgrade-path-first/architecture-800.webp 800w,/assets/img/posts/ship-the-upgrade-path-first/architecture-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/ship-the-upgrade-path-first/architecture.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> <b>Control plane and data plane.</b> The thin CLI authenticates to the distribution API and receives a release manifest plus a short-lived, scoped credential. It then pulls images and the deployment descriptor directly from the registry, writes a local configuration file it owns, and brings the release up. </div> <p>One detail explains a design choice that otherwise looks arbitrary: the API never serves the images itself. Large blobs belong in a <strong>data plane</strong> built for them, a registry <d-cite key="oci-distribution-spec"></d-cite> or an object store, while the API stays a <strong>control plane</strong> serving small, frequently changing metadata and handing out a credential scoped to exactly this pull <d-cite key="rfc8693"></d-cite>.</p> <h2 id="what-it-buys-you">What It Buys You</h2> <p>The payoff for engineering is the one this post has been arguing for throughout: a fleet that converges on every check-in is a fleet you can change.<d-footnote>A channel does not absolve releases from compatibility discipline; an upgrade still has to carry existing installs forward. What convergence changes is the scope of that discipline: each release migrates one known fleet state instead of N unknown ones.</d-footnote> Ship an architectural change once, to the manifest, and every install picks it up on its next check-in. No hand-coordinated rollout across N divergent configurations, no fleet nobody can touch without a support call.</p> <p>The payoff for the business is the one Thiel’s framing opened with. A working distribution channel is what lets self-hosted software stay <strong>product-led</strong> instead of quietly turning into a <strong>services-led</strong> business where every install needs a consultant. The distinction compounds: when upgrades are human work, every sale adds permanent operational load, and growth starts to scale with headcount instead of with software. Even SaaS only keeps that control by making the same design choice; running the servers yourself just makes drift easier to catch and correct. The harder, and more valuable, engineering problem is keeping control while the software runs on somebody else’s infrastructure.</p> <p>None of this is exotic. It recombines ideas infrastructure already trusts: reconciliation from Kubernetes, config-in-environment from twelve-factor apps, short-lived credentials from cloud security guidance, and manifest-plus-separate-artifacts from update frameworks like TUF <d-cite key="tuf-spec"></d-cite>. The only new part is pointing them outward, at infrastructure you do not own, instead of inward, at your own cluster.</p> <p>I have built <a href="https://github.com/ethonAI/ethon-cli">a distribution channel along these lines</a>, in my case for the customer-installed edge components of a SaaS product, and it is a pattern others have landed on too<d-footnote>Siemens' Industrial Edge, for instance, lets you install and update its management platform on your own Kubernetes cluster through a single CLI, without ever touching a Helm chart directly <d-cite key="siemens-ieprovision"></d-cite>.</d-footnote>, one worth borrowing regardless of what you are shipping.</p> <p><strong>Build the upgrade path first, and let it decide how much runway everything else gets.</strong></p>]]></content><author><name>Christian Henning</name></author><category term="engineering"/><category term="distribution"/><category term="technical-debt"/><summary type="html"><![CDATA[The fastest-moving products are not the ones with the cleverest features, but the ones that can change what is already deployed. For self-hosted software that means building distribution and self-upgrade first, because without them there is no iterate step, and every cut made for the MVP quietly becomes permanent.]]></summary></entry><entry><title type="html">The Two Cuts of an MVP – Why Iterating and Incrementing Both Come Down to Vision</title><link href="https://chrhenning.com/blog/2026/mvp-two-cuts/" rel="alternate" type="text/html" title="The Two Cuts of an MVP – Why Iterating and Incrementing Both Come Down to Vision"/><published>2026-06-30T08:00:00+00:00</published><updated>2026-06-30T08:00:00+00:00</updated><id>https://chrhenning.com/blog/2026/mvp-two-cuts</id><content type="html" xml:base="https://chrhenning.com/blog/2026/mvp-two-cuts/"><![CDATA[<p>“Minimum viable product” is one of the most misread terms in product development. People hear <em>minimum</em> and reach for permission to ship something rough. But an MVP is not a license to ship a sub-quality product. As I argued in <a href="/blog/2025/scrappiness-incentivizes-sloppiness/">Scrappiness Incentivizes Sloppiness</a>, sloppy execution feels fast and quietly costs you the sustained speed that actually matters. What an MVP minimizes is not quality. It is scope.</p> <div class="row mt-3 justify-content-center"> <div class="col-md-12 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/mvp-two-cuts/overview-480.webp 480w,/assets/img/posts/mvp-two-cuts/overview-800.webp 800w,/assets/img/posts/mvp-two-cuts/overview-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/mvp-two-cuts/overview.jpg" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> Every MVP cut is one of two moves. <strong>Defer</strong>: leave a gap to fill in later. <strong>Substitute</strong>: drop in a deliberate stand-in, then swap it for the real thing later. Either way, what's already built stays untouched. Image generated with Google Gemini. </div> <p>This is the third post in a series on the debts you take on while building a product. The first argued that <a href="/blog/2025/mvp-manage-debt-and-iterate-fast/">technical, strategic, and feature debt</a> are tools, not sins, as long as you take them on consciously. The second covered the <a href="/blog/2025/technology-readiness-debt/">technology readiness debt</a> you carry when the technology you need isn’t ready yet. Both stayed fairly abstract. This one is concrete, about a decision you make dozens of times while scoping an MVP, often without noticing you’ve made it: <strong>what to cut</strong>.</p> <p>“Let’s just cut that for the MVP” gets said in a meeting, everyone nods, and the decision is made in three seconds. But cutting scope is not a single move. Every time you trim something from an MVP, you’re doing one of two very different things, and most teams never notice which one they just made. Confusing them is how a lean product quietly turns brittle.</p> <h2 id="the-two-cuts">The Two Cuts</h2> <p>The first cut is <strong>deferral</strong>: you leave a feature <em>out of scope</em> and plan to build it later. The second is <strong>substitution</strong>: you build a deliberate stand-in, something you <em>intend</em> to throw away and replace once you’ve learned what you need to build.</p> <p>At first glance only one of them is debt. A clean deferral isn’t debt, it’s just scope: debt is something you borrow and have to pay back, and a feature you never built was never borrowed. Substitution is real debt, because you’ve put something into the product specifically so you can replace it, and that replacement is the repayment. The word doing the work there is <em>clean</em>: keeping a deferral clean turns out to be the whole game.</p> <p>That has a flip side. If a deferred feature is <em>just scope</em> and costs you nothing, then <strong>whatever you do keep in scope has to be built cleanly.</strong> If authentication is in scope, build proper, secure auth that will carry you forward for the foreseeable future without further thought. That isn’t premature optimization; it’s getting the in-scope requirements right so you can take them off your mind and focus fully on the next thing. Clean execution on what you commit to is what buys you <em>sustained</em> speed.</p> <p>So far this looks like a tidy binary: defer cleanly, or substitute deliberately. But there’s a catch, and it’s the same catch for both cuts. Whether either one stays safe depends on something underneath the visible choice, and that something, it turns out, is placed by your vision.</p> <h2 id="the-two-cuts-already-have-names">The Two Cuts Already Have Names</h2> <p>Neither cut is new. The literature on <a href="https://en.wikipedia.org/wiki/Iterative_and_incremental_development">iterative and incremental development</a> has a name for each, and it has spent decades pointing out that people conflate them.</p> <p>Alistair Cockburn drew the line cleanly in <em>Using Both Incremental and Iterative Development</em> <d-cite key="cockburn2008incremental"></d-cite>. <strong>Incremental</strong> development stages a system in parts that are built and integrated over time; you add pieces to something that stays. <strong>Iterative</strong> development builds a rough version and then reworks it, refining the same thing through repeated passes. Jeff Patton illustrated the difference memorably: painting the Mona Lisa <em>incrementally</em> means finishing it corner by corner, while painting it <em>iteratively</em> means sketching the whole canvas roughly and sharpening it pass after pass <d-cite key="patton2008iterating"></d-cite>.</p> <p>Deferral is the incremental move; substitution is the iterative one. Fred Brooks supplies the cautionary arc for substitution. His famous advice, “plan to throw one away; you will, anyhow,” was about building a deliberate throwaway to learn from. Two decades later he partly recanted, devoting a chapter of the anniversary edition of <a href="https://en.wikipedia.org/wiki/The_Mythical_Man-Month"><em>The Mythical Man-Month</em></a> to the argument that an incremental-build model beats building one to discard <d-cite key="brooks1995mythical"></d-cite>. The lesson isn’t that one cut is right and the other wrong. It’s Cockburn’s: you need <em>both</em>, used deliberately.</p> <p>A single MVP almost always mixes the two, which is why the unit you classify is the individual cut, not the whole product. That also corrects a quiet imprecision in the usual mantra. “Build an MVP and iterate” names only half the work: iterating reworks what’s already there, but just as much of what follows an MVP is <em>incrementing</em>, adding the pieces you deliberately deferred. The fuller version is <strong>“build an MVP, then iterate <em>and</em> increment”</strong>, and telling which of the two a given cut commits you to is the skill this post is about.</p> <h2 id="the-decision-rule-and-the-seam">The Decision Rule and the Seam</h2> <p>The practical test is one question, asked the moment you make a cut: <strong>will I grow this, or throw it away?</strong> If you’ll grow it, you’re deferring, and the job is to leave room for it. If you’ll throw it away, you’re substituting, and the job is to keep the throwaway from spreading. Either way, decide deliberately, not with the reflexive “we’ll clean it up later” muttered under a deadline.</p> <p>Here’s the catch I promised: a deferral can <em>silently</em> become a substitution. “Defer multi-tenancy” but build around single-organization assumptions, and you haven’t deferred anything; you’ve baked a single-tenant architecture in, and retrofitting tenancy later is a rewrite. The absence became a stand-in you never chose.</p> <p>What separates a clean deferral from that trap is whether you left a <strong>seam</strong>: in Michael Feathers’ words, “a place where you can alter behavior in your program without editing in that place” <d-cite key="feathers2004legacy"></d-cite><d-cite key="fowler2024legacyseam"></d-cite>. A seam holds the place for something not yet built, or contains a throwaway so swapping it later has a small blast radius. It needn’t be a literal interface. For access control, it’s less a request choke point than a <strong>data model that anticipates the partition</strong>: design entities so they can later be split into groups or tenants, and adding role-based access control becomes <em>filling in</em> a boundary that already exists rather than re-cutting the model.</p> <p>Substitution works the same way. Say you need a machine-learning model you can’t train well yet. Define the target interface now, a versioned <a href="https://onnx.ai/">ONNX</a> contract, so today’s weaker artifact merely satisfies it and can be swapped cleanly later; versioning the contract even lets the interface evolve as your vision sharpens, without breaking everything around it. The throwaway sits behind a clean boundary, so the rebuild is a swap, not a rewrite. This is exactly the seam the <a href="/blog/2025/mvp-manage-debt-and-iterate-fast/">skateboard-to-car analogy</a> I criticized earlier lacked: a skateboard has no boundary to rebuild behind, so “upgrading” it into a car means starting over, whereas a contained throwaway lets you replace only the part that was always meant to go.<d-footnote>The generic version is any stand-in placed behind a stable interface: a manual or <a href="https://en.wikipedia.org/wiki/Wizard_of_Oz_experiment">"Wizard of Oz"</a> backend behind the API the real service will expose, or a payments interface wired to a test provider before the real integration exists. The point isn't to mock everything. Substitute only what has to be in the product from day one but can't be built properly yet; the stable interface is what lets the rest of the product increment around it.</d-footnote></p> <p>Which points at what the two cuts share. Every cut asks two questions, not one. The cut you chose sets <em>what the seam has to do</em>: hold an empty place you’ll fill, or contain a throwaway you’ll swap. The second question is independent, and it’s the one that decides whether the cut is safe at all: does that seam exist?</p> <table> <thead> <tr> <th></th> <th><strong>Seam present</strong></th> <th><strong>No seam</strong></th> </tr> </thead> <tbody> <tr> <td><strong>Defer</strong></td> <td>clean scope: place held, fill later</td> <td>accidental substitution: backed into a rewrite</td> </tr> <tr> <td><strong>Substitute</strong></td> <td>honest throwaway: contained, swap later</td> <td>duct tape: stand-in smeared everywhere</td> </tr> </tbody> </table> <p>Read down the columns, not across the rows: both cuts are safe <em>with</em> a seam and dangerous <em>without</em> one. A deferral with no seam isn’t really a deferral, you baked the feature’s absence in, so adding it later is a rewrite; a substitution with no seam can’t be thrown away as planned, because the stand-in leaks into everything around it until pulling it out is a rewrite too. Not that every cut needs a seam: a cleanly additive feature can just be deferred with nothing held open for it. But where a cut would otherwise harden an assumption you’ll later have to undo, leaving the seam out is exactly the sloppiness that scrappy teams mistake for speed.</p> <h2 id="vision-places-the-seams">Vision Places the Seams</h2> <p>If the seam is what matters, the next question is where to put one, and you can’t seam everything. Even a light seam costs foresight and indirection, and the heavy ones cost real engineering. Seaming everywhere is its own kind of debt: the speculative over-engineering that <a href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it">“you aren’t gonna need it”</a> warns against.</p> <p>A seam is a bet about where the system will change, and <strong>your vision is your best model of where it will change</strong>. That is why vision tells you where the seams belong. The principle goes back to David Parnas’s <a href="https://en.wikipedia.org/wiki/Information_hiding">information hiding</a>: hide the design decisions most likely to change behind a module boundary, so a change touches one place instead of many <d-cite key="parnas1972criteria"></d-cite>. The seam is that boundary. This is the resolution of the earlier catch, and the reason the right cut depends on your vision: vision operates one level <em>below</em> the visible decision to cut. Two teams can make the identical surface call, “leave out access control,” and one ends clean while the other ends rewritten, purely because one team’s vision told it to anticipate the partition and the other’s didn’t.</p> <p>This is also why the vision has to be <strong>falsifiable</strong>. A vision vague enough that it can never be wrong can’t tell you anything about where change is coming, so it can’t guide a single seam. A specific vision can be corrected by what you learn, and each correction re-points the seams.<d-footnote>Which is why a confident vision that is simply wrong can be worse than a vague one: it spends real effort seaming where change never comes while leaving the true fault lines bare. Falsifiability pays off only when feedback arrives fast enough to move a seam before the one you skipped has hardened into a rewrite.</d-footnote></p> <p>What you’re really foreseeing is not a fixed roadmap but a set of <em>options</em>: a seam is a small premium you pay now to keep the right, but not the obligation, to change a component later. This is the options view of modularity that Baldwin and Clark formalized: a module boundary carries a real option to redesign what sits behind it, worth most exactly where the future is uncertain <d-cite key="baldwin2000designrules"></d-cite>. You buy options where the underlying is volatile, and vision is what tells you which volatility is worth insuring against.<d-footnote>Which makes foresight itself a form of prevention, and prevention's payoff is always an absence. A seam placed early averts a rewrite that then never happens, so the cost it saved leaves no trace and the work goes uncredited. It's the same asymmetry I explored in <a href="/blog/2026/we-reward-the-fix-not-the-prevention/">Your Best Work Leaves No Trace</a>: thinking ahead is chronically undervalued precisely because what it prevents can't be seen, even though it's exactly what buys the sustained iteration speed this whole series is about.</d-footnote></p> <h2 id="when-the-seam-comes-due">When the Seam Comes Due</h2> <p>A substitution doesn’t come due on a schedule. It comes due when you expand into a new segment that makes the stand-in load-bearing. The hand-tuned rules engine that stood in for a model is fine until you sell to a customer whose cases it can’t cover: that’s the moment to spend the seam you left and swap in the real thing. The rebuild is <em>pulled</em> by the market, not done speculatively.</p> <p>That is why an MVP needs not just a minimal product but a <strong><a href="https://underscore.vc/resources/minimum-viable-segment/">minimum viable segment</a></strong>: a single, well-defined slice of the market you serve fully today, before rolling into the next one.<d-footnote>The idea is well worn. In <a href="https://en.wikipedia.org/wiki/Crossing_the_Chasm"><i>Crossing the Chasm</i></a>, Geoffrey Moore called this narrow first segment a beachhead, his military metaphor: as in the D-Day landings, you seize one small, defensible stretch of a contested shore and secure it fully before pushing inland <d-cite key="moore1991chasm"></d-cite>. Bill Aulet later made choosing a beachhead one of the first steps of his 24-step method <d-cite key="aulet2013disciplined"></d-cite>. Scaling ahead of that segment has a name, premature scaling, and the Startup Genome project found it among the most common ways startups die; in their data, no prematurely scaled company passed a hundred thousand users <d-cite key="startupgenome2011premature"></d-cite>.</d-footnote></p> <p>So grow your scalability <em>together with</em> your addressable market: each new segment both justifies the rework and tells you what it needs to do. This is no license to build cheap and unscalable: if the “right” scalable version costs little more than the stand-in, or the vision already makes it near-certain, just build it properly now. Deferral earns its keep only when doing it right would cost significantly more. The seams you left are what let you grow into a new segment without tearing the product apart, and the segment tells you which seam to spend next.</p> <h2 id="cutting-with-vision">Cutting With Vision</h2> <p>The “two cuts” is the part you can see: defer, or substitute. They are genuinely different moves, one adding, one replacing, with different work left to do. But what makes <em>either</em> of them safe is the same thing: a <strong>seam</strong> under the cut, placed where your <strong>vision</strong> says change is coming. That is why the same shortcut can be smart scoping for one team and a future rewrite for another. Same cut, different vision, different seam.</p> <p>That closes the loop on the trilogy. The first post argued debt is a tool you wield deliberately; the second, that technology readiness debt is what you carry when the technology isn’t ready yet; and this one, that the everyday cuts of an MVP turn safe or dangerous on one hidden thing: whether a falsifiable vision left you the seams to grow some parts and replace others, paced by the market you actually serve.</p> <p>So the next time someone says “let’s just cut that for the MVP,” ask the quiet follow-up: are we deferring this or replacing it, and either way, where’s the seam?</p> <p><strong>Cutting scope is how you move fast. Leaving seams is how you stay fast.</strong></p>]]></content><author><name>Christian Henning</name></author><category term="product-management"/><category term="mvp"/><category term="technical-debt"/><summary type="html"><![CDATA[Every “cut it for the MVP” is one of two moves. You either defer a feature or build a throwaway stand-in. Whether either becomes debt depends not on the cut but on the boundary you leave beneath it, and on a vision clear enough to place it.]]></summary></entry><entry><title type="html">Your Best Work Leaves No Trace: Why Engineering Teams Reward the Fix and Replace the Prevention</title><link href="https://chrhenning.com/blog/2026/we-reward-the-fix-not-the-prevention/" rel="alternate" type="text/html" title="Your Best Work Leaves No Trace: Why Engineering Teams Reward the Fix and Replace the Prevention"/><published>2026-06-22T09:00:00+00:00</published><updated>2026-06-22T09:00:00+00:00</updated><id>https://chrhenning.com/blog/2026/we-reward-the-fix-not-the-prevention</id><content type="html" xml:base="https://chrhenning.com/blog/2026/we-reward-the-fix-not-the-prevention/"><![CDATA[<p>A production incident gets fixed under pressure late on a Friday, and by Monday the engineer who saved the day is the center of attention. Earlier that same quarter, a different engineer quietly did the work that kept a separate system stable: writing a test covering a rare edge case, fixing a backup routine, or tightening permissions before anyone could exploit them. None of that work earns a mention, because <strong>the outage it prevented never happened</strong>.</p> <p>We celebrate the fix and barely perceive the prevention. That should bother us, because prevention is not heroics. It is simply the job done properly. The trouble is that doing the work well produces a set of absences: the outage that did not happen, the data that was not lost, and the breach that never occurred.</p> <p><strong>Absences make terrible portfolio pieces.</strong> You cannot easily point to a catastrophe that never came to pass, and you cannot provide visual proof of a smooth, quiet Friday night.</p> <p>This asymmetry quietly shapes how engineering teams spend their attention. It is a dynamic that deeply resonates with my own experience, and even organizations that actively strive for balance struggle against the gravity of the visible crisis. The pressure is structural rather than personal. It explains a surprising amount: why testing, security, and backups perennially lose the prioritization fight, and why the most common organizational response backfires. Faced with prevention we cannot see, organizations reach for a visible proxy for it, and that proxy quietly crowds out the prevention it was meant to protect.</p> <div class="row mt-3 justify-content-center"> <div class="col-md-10 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/we-reward-the-fix-not-the-prevention/the-fix-and-the-prevention-480.webp 480w,/assets/img/posts/we-reward-the-fix-not-the-prevention/the-fix-and-the-prevention-800.webp 800w,/assets/img/posts/we-reward-the-fix-not-the-prevention/the-fix-and-the-prevention-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/we-reward-the-fix-not-the-prevention/the-fix-and-the-prevention.jpg" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> The fix and the prevention. On the left, the crisis everyone sees: a person in the thick of it, surrounded by alarms and dashboards, the center of attention. On the right, the same storm faded to a ghost of what was averted, with the person who prevented it standing quietly, unthanked. Image generated with Google Gemini. </div> <h2 id="an-old-uncomfortable-asymmetry">An Old, Uncomfortable Asymmetry</h2> <p>The core observation here is neither mine nor is it new. It is one of the most rediscovered ideas in all of applied reasoning.</p> <p>Back in 1850, Frédéric Bastiat told a simple story, now known as the <a href="https://en.wikipedia.org/wiki/Parable_of_the_broken_window">parable of the broken window</a>, about a boy who breaks a shop window <d-cite key="bastiat1850seen"></d-cite>. The neighbors try to cheer up the shopkeeper: look on the bright side, now the repairman gets paid, and that money flows on to others, so really everyone wins. Bastiat’s point is that this misses what you cannot see. The money spent fixing the window is money the shopkeeper can no longer spend on shoes or books. The repair is visible, so we count it. The shoes that never got bought are invisible, so we forget them, even though they were just as real.</p> <p>A century and a half later, Nassim Taleb gave the same idea its sharpest modern form, calling it the problem of silent evidence. He imagines a legislator who, at great political cost, forces every airline to install locked, reinforced cockpit doors, with the law taking effect on September 10, 2001 <d-cite key="taleb2007blackswan"></d-cite>. That person prevents the attacks of the next morning and is never thanked, never remembered, precisely because the catastrophe they averted never happened. Taleb’s conclusion is blunt: everybody knows we need prevention more than treatment, but few reward acts of prevention, and history glorifies the names left in its books over the contributors it stays silent about.</p> <p>The management literature has a name for the organizational version of this. Repenning and Sterman called their study of it, perfectly, “Nobody Ever Gets Credit for Fixing Problems that Never Happened” <d-cite key="repenning2001credit"></d-cite>. They describe the <em>capability trap</em>: under pressure, teams cut the invisible work (maintenance, improvement, prevention) to feed the visible work, which raises the firefighting load, which increases the pressure, which cuts the invisible work further.</p> <p>So the diagnosis is settled and ancient. What I find more interesting, and less discussed, is what organizations actually <em>do</em> in response to this asymmetry. Because they do not simply underfund prevention and leave it there. They reach for something that looks like prevention and is much easier to see.</p> <h2 id="prevention-theater">Prevention Theater</h2> <p>When real prevention earns no credit because it produces no signal, organizations look for a substitute. So we substitute a version of prevention that <em>does</em> produce a signal: a gate, a checklist, a mandatory sign-off, a ceremony, a required reviewer, a manual QA pass on every change. These things generate artifacts. They populate a dashboard. They give a manager something to point at when someone asks what we are doing about quality. I’ll call this <strong>prevention theater</strong>, with a deliberate nod to <a href="https://en.wikipedia.org/wiki/Security_theater">Bruce Schneier’s “security theater,”</a> the airport-style measures that make us feel safer without making us safer <d-cite key="schneier2003beyondfear"></d-cite>.</p> <p>The trouble is not that gates are useless. A good gate verifies quality that is already there, and the best processes go further and build it in: a pilot’s pre-flight checklist or a surgeon’s pre-incision checklist makes the right step happen rather than merely recording that someone looked. Those earn their place, and the discipline is to keep asking which ones still do. The trouble is the other kind, the process bolted on to fight symptoms, standing in for quality the work does not have.<d-footnote>A gate is only as good as the thing it checks, and choosing that thing is most of the design. Test coverage is a weak choice: point an AI at the codebase and it will bulk-generate unit tests until the percentage clears the bar, yet those tests mostly assert that the code does whatever it already does. The gate fired and verified nothing.</d-footnote> It competes with the real thing for the same budget of attention and keeps winning, because it is <em>visible</em> and the real work is not. We are optimizing for what we can see.</p> <p>Quality control has known this for a long time. W. Edwards Deming, quoting Harold Dodge, put it in one line: <strong>“You cannot inspect quality into a product.”</strong> <d-cite key="deming1986crisis"></d-cite> By the time the gate runs, the quality is already either built into the work or missing from it. The check does not add any; it only reveals what is there. A gate at the end of the line does not create quality; it just produces a record of having looked. Worse, it relocates responsibility. When there is a QA gate on every change, the author quietly stops owning whether the change is correct, because checking is now the gate’s job. The bar drifts down to whatever the gate mechanically verifies, and everyone learns to write for the checklist rather than for the system.<d-footnote>Early coding agents made this concrete: pointed at a failing build, they would often rewrite the test rather than fix the root cause. <a href="https://metr.org/blog/2025-06-05-recent-reward-hacking/">METR found</a> that when the scoring code was visible to the model, it would routinely game the check rather than fix the code, and far less often when the scoring was hidden.</d-footnote></p> <p>I’ve argued before that scrappiness tends to launder unmanaged debt into a virtue (see <a href="/blog/2025/scrappiness-incentivizes-sloppiness/">Scrappiness Incentivizes Sloppiness</a>), and that the speed-versus-quality trade-off is mostly a myth once you look at the data. Prevention theater is the mirror-image failure. Scrappiness skips the invisible work and admits it. Theater skips the invisible work while producing a convincing artifact that says otherwise, which is more dangerous, because it buys a false sense of safety. An ignored test suite, a rubber-stamped review, or a massive code diff nobody actually reads: each is a green light wired to nothing.</p> <p>The tell, every time, is that the artifact has become the goal. This is <a href="https://en.wikipedia.org/wiki/Goodhart%27s_law">Goodhart’s law</a> in miniature: when a measure becomes a target, it stops being a good measure, because a proxy is always easier to optimize than the messy reality it stood for <d-cite key="goodhart1984monetary"></d-cite><d-cite key="strathern1997ratings"></d-cite>. The question shifts from “is this safe to ship?” to “did we complete the checklist?” Those are not the same question, and the gap between them is exactly the prevention we told ourselves we were buying.</p> <h2 id="the-same-trap-with-people">The Same Trap, With People</h2> <p>This identical pattern runs through the <em>human</em> side of engineering, yet the technical and organizational versions of this failure are rarely treated as one.</p> <p>A team’s real standard is not what it writes in a values doc. It is the worst work it tolerates without comment. Lieutenant General David Morrison put it memorably (crediting the line to David Hurley): <strong>“the standard you walk past is the standard you accept.”</strong> <d-cite key="morrison2013standard"></d-cite> Every time mediocre work ships without a conversation, the bar moves down a notch, and the move is small enough that no single instance feels wrong. Diane Vaughan studied the catastrophic version of this in her analysis of the Challenger launch and named it the <a href="https://en.wikipedia.org/wiki/Normalization_of_deviance"><em>normalization of deviance</em></a>: the gradual process by which an unacceptable practice becomes acceptable, then expected, then invisible <d-cite key="vaughan1996challenger"></d-cite>. Dan Luu and Bruce Schneier have both pointed the same lens at software organizations <d-cite key="luu2015deviance"></d-cite><d-cite key="schneier2016deviance"></d-cite>.</p> <p>The asymmetry repeats perfectly. The act that actually holds a standard is direct <em>engagement with sub-par work</em>. It requires pausing, having a slightly uncomfortable conversation, asking for rework, and coaching toward the bar. Because its entire payoff is an absence (the erosion of quality that did not set in), this work is quietly skipped, because shipping anyway always feels easier in the moment. And what do organizations reach for instead? A visible proxy. More process. A PR template, a mandatory second reviewer, a sign-off step, a heavier definition of done. This is the same prevention theater in a different costume: an artifact that says “we have standards” standing in for the invisible work of actually holding them.</p> <p>The conversation is the prevention. The process is theater whenever it stands in for that conversation instead of provoking it. One produces a record; the other produces a culture, and only one of them is easy to point at in a performance review.</p> <h2 id="the-same-failure-different-clothes">The Same Failure, Different Clothes</h2> <p>Once you line the two up, the engineering version and the human version, it is hard to see them as separate problems. They are the same failure wearing different clothes.</p> <p>In both cases, risk accumulates silently, with no signal, until it doesn’t. James Reason called these <em>latent conditions</em>: weaknesses that sit dormant in a system, contributing nothing visible, until they line up with a triggering event <d-cite key="reason2000error"></d-cite>. In the image he later made famous, the holes in the Swiss cheese align. An untested code path and a tolerated lapse in standards are the same kind of object: a latent condition that produces no feedback while it is forming, and a great deal of feedback the day it finally matters.</p> <div class="row mt-3 justify-content-center"> <div class="col-md-8 col-sm-12 mt-3 mt-md-0"> <img src="/assets/img/posts/we-reward-the-fix-not-the-prevention/swiss-cheese-model.svg" class="img-fluid rounded z-depth-1" alt="Swiss cheese model of accident causation: several slices of cheese in a row, each with holes; a hazard passes through only when holes in successive slices line up." loading="lazy"/> </div> </div> <div class="caption"> James Reason's Swiss cheese model of accident causation: each defensive layer has holes, and harm passes through only in the rare moment they align. An untested code path and a tolerated lapse in standards are two such holes. Image by <a href="https://commons.wikimedia.org/wiki/User:BenAveling">Ben Aveling</a>, <a href="https://creativecommons.org/licenses/by-sa/4.0">CC BY-SA 4.0</a>, via <a href="https://commons.wikimedia.org/wiki/File:Swiss_cheese_model_textless.svg">Wikimedia Commons</a>. </div> <p>And one decision plays out the same way in code and in people. The instinct that underfunds the test suite is the instinct that skips the standards conversation. The reflex that adds a QA gate is the reflex that adds a review template. It is not stupidity or laziness. It is a rational response to an incentive landscape where the visible is rewarded and the invisible is ignored.</p> <p>That landscape is built by the same cognition working in everyone, the manager included. Two biases, both long documented in psychology, keep prevention from ever registering as something worth rewarding. The first is the <a href="https://en.wikipedia.org/wiki/Availability_heuristic">availability heuristic</a>: we judge what matters by what comes to mind <d-cite key="tversky1973availability"></d-cite>. A four-hour outage everyone scrambled through is unforgettable; the morning a test quietly caught the same bug before it shipped leaves nothing to recall. The second is <a href="https://en.wikipedia.org/wiki/Hindsight_bias">hindsight bias</a>: even when prevention is pointed out, knowing the disaster never came makes it feel like it was never that likely, so the counterfactual is quietly disbelieved <d-cite key="fischhoff1975hindsight"></d-cite>. And being aware of the bias does not let us overcome it: warned about it and told to correct for it, people show it just the same <d-cite key="pohl1996noreduction"></d-cite>. A manager cannot reward what their own perception barely registers and instinctively discounts, so they reach for the visible proxy instead. That is how theater wins.</p> <p>Therefore, the fix is not to simply try harder to value invisible work. <strong>Willpower loses to incentives every time.</strong> This is Reason’s point exactly: we cannot change the human condition, but we can change the conditions under which people work <d-cite key="reason2000error"></d-cite>. The fix is to change what the work produces.</p> <h2 id="why-the-trap-pays">Why the Trap Pays</h2> <p>That fix is clear enough on paper, which raises the puzzle the literature tends to leave hanging: if the trap is this old, this documented, and this costly, why are so many companies that fall into it successful anyway? Because it is an equilibrium, not a mistake. Theater becomes the dominant organizational strategy because its cost is paid now and is entirely certain. Conversely, the payoff of real prevention is deferred and structurally unprovable. The engineer who prevents an outage holds only a counterfactual, with no proof that a disaster would have occurred or that they were the one who stopped it. The engineer who fixes an active outage holds concrete evidence: system logs, timestamps, incident reports, and a grateful customer. Even a firm that genuinely wants to reward prevention cannot easily price what its own people cannot prove, making the visible proxy the rational purchase.</p> <p>But the asymmetry runs deeper than proof. The engineer spent months working through the disaster scenarios their work ruled out and can still picture each one; everyone else cannot even imagine what might have gone wrong. This is the <a href="https://en.wikipedia.org/wiki/Simulation_heuristic">simulation heuristic</a>, availability’s counterfactual cousin: we weigh a danger by how easily we can imagine it, so the averted one barely registers for anyone but them <d-cite key="kahneman1982simulation"></d-cite>.</p> <p>And no single firm is uniquely punished for choosing the proxy, because its competitors all make the same move. You are graded against rivals who are equally afflicted rather than against perfection. This is the unobservable-quality problem that George Akerlof named in the <a href="https://en.wikipedia.org/wiki/The_Market_for_Lemons">market for lemons</a>, applied one level up <d-cite key="akerlof1970lemons"></d-cite>.</p> <p>And the bill, when it comes due, hides on the same axis as the prevention. Latent conditions accumulate for years with no feedback, so a company can run on borrowed reliability and tolerated lapses long enough to get acquired, pivot, or ride a market wave before the holes line up. The successful-yet-afflicted firms we point to are partly just the ones where the cheese has not aligned yet; the ones it sank are the silent evidence we never see <d-cite key="taleb2007blackswan"></d-cite>.</p> <p>But survivorship is only half of why the giants get away with it. The other half is that revenue is not a referendum on prevention. The largest firms win on entrenched advantages, on network effects, distribution, and sheer scale, and the profit those throw off is wide enough to absorb mediocre engineering as drag rather than death. Insulated from fierce competitive pressure, a massive firm simply carries the organizational slack. Economists refer to this as <a href="https://en.wikipedia.org/wiki/X-inefficiency">X-inefficiency</a>, a phenomenon routinely found in companies that do not operate under strict survival pressures <d-cite key="leibenstein1966xefficiency"></d-cite>. A dominant firm can firefight for years and still print money because its bottom-line profit was never priced on the outage that did not happen. Firefighting genuinely delivers for a while too, which is what makes the capability trap a trap <d-cite key="repenning2001credit"></d-cite>. So success is no proof the trap is benign. You cannot read prevention quality off a balance sheet: it is the same invisibility one level up, a cost that produces no signal and so never forces the fix.</p> <p>And even when it never blows up, the trap is not free. Firefighting is its own standing tax: a reactive, draining mode of work that quietly costs the engineers who stop trusting their own systems and take their ambition elsewhere.</p> <h2 id="telling-the-proxy-from-the-thing">Telling the Proxy From the Thing</h2> <p><em>Changing what the work produces</em> has a catch: any signal you invent to make prevention visible is one short step from hardening into the next gate. So the whole game is one question you can apply anywhere:</p> <p><strong>Does this measure the absence I actually care about, or does it just produce evidence that I did something?</strong> The first is prevention. The second is theater.</p> <p>The cleanest thing I know that passes is the SRE practice of error budgets and service level objectives <d-cite key="googlesre_errorbudget"></d-cite>. Reliability is a classic invisible asset because nobody notices it until it vanishes. An error budget makes that absence measurable. It turns a vague notion like “the system kept working” into a concrete metric that you can spend, defend, and reason about. This structural transparency allows reliability to win prioritization arguments it would otherwise lose silently. <d-footnote>This cuts both ways: a budget is there to be spent. Reliability past the bar you actually need is over-engineering, not virtue. Prevention means hitting that bar, not chasing zero risk at the expense of progress.</d-footnote> It measures the outcome (did we stay within budget?), not the activity (did we hold the meeting?).</p> <p>The same test sorts real review from theater. A reviewer who only records that someone looked fails it; review that genuinely engages with the work passes. But review is not where quality comes from. Only the author can build quality in, because only the author shapes the work, so responsibility for the result stays with them whoever signs off. Good review does not relieve them of that; it is two people raising the bar together, iterating toward something better than either would ship alone. The alternative to a rubber stamp, then, is not a lower engineering bar but authors who own what they merge and reviewers who genuinely sharpen it. A gate absorbs that ownership; a real metric, and a real review, hand it back.</p> <p>The test carries straight to the human layer, where it says protect the conversation, not the template. Engaging with sub-bar work, directly and early, is the high-leverage act, but it only has weight if the bar is real, which means the people who hold it have to visibly live it. A team whose leaders preach quality and ship slop on a deadline learns, accurately, that quality is a slogan. Keep consequences in reserve, too, as the rare backstop that keeps everyday coaching credible. The template proves a step happened; the conversation changes the work.</p> <p>Because real prevention creates no incident logs on its own, you must build that narrative deliberately. When an automated test catches a critical regression before it ships, or when a difficult conversation pulls a design back up to the bar, <em>name that outcome out loud</em>. This is the only way invisible work wins the narrative credit that visible crises receive for free.</p> <h2 id="crediting-what-never-happened">Crediting What Never Happened</h2> <p>The asymmetry that opened this essay is old, and it is not going away. We are wired to commit the classic economic fallacy Frédéric Bastiat identified: focusing on the broken window while staying blind to the unseen value lost to pay for it <d-cite key="bastiat1850seen"></d-cite>. We thank the firefighter and forget the person who fireproofed the building.</p> <p>We cannot undo those cognitive biases. But we usually pile a second, preventable mistake on top of it. Because we cannot see real prevention, we reach for an artifact we can observe: a gate, a checklist, a heavier process, a formal record. Anything that lets us feel covered. That substitute is never free. It crowds out real prevention, and the safety it promises is mostly an illusion.</p> <p>Therefore, the discipline required of modern engineering organizations is threefold:</p> <ul> <li><strong>Normalize counterfactual credit:</strong> Celebrate and protect the problems that never happened loudly enough that the people who prevent disasters can survive a performance review.</li> <li><strong>Audit your metrics:</strong> Where you do build a tracking signal, keep it strictly tied to the operational outcome you care about, and constantly verify that it has not decayed into an empty checkbox.</li> <li><strong>Distrust structural shortcuts:</strong> Reject anything that promises to make prevention cheap or mechanical. The durable asset was never the formal process, but the underlying engineering culture that builds quality in before any gate runs.</li> </ul> <p>For my part, I believe prevention is an investment and the fix an expense.</p> <p>If you are the engineer doing this quiet work, do not draw the cynical conclusion that prevention is a dead end, that you should let things break to be seen fixing them. The reward exists; it just sits on a slower ledger. Heroics earn applause, but prevention earns trust: the autonomy and hard problems that compound into the engineer everyone wants on their team. And everyone ends up firefighting sometimes, because no sane system runs at zero risk. What separates the best is not how often they are the center of attention, but how rarely their own work puts them there.</p> <p>The mistake is not doing the invisible work; the mistake is doing it silently. Make the counterfactual legible: name the catch, and say what those quiet days bought the business, concretely enough that hindsight cannot wave it away. This is the <a href="https://en.wikipedia.org/wiki/Signalling_%28economics%29">signal</a> that answers Akerlof’s lemons problem from earlier, making quality visible when it would otherwise go unpriced <d-cite key="spence1973signaling"></d-cite>.</p> <p>The moment you have any leverage over what an organization rewards, use it.<d-footnote>Designing that reward structure is a leadership responsibility I've argued before in the split between research and engineering: judge both against a single scoreboard and you quietly train researchers to stop taking risks (see <a href="/blog/2026/before-the-breakthrough-research-engineering-cultures/">Before the Breakthrough</a>).</d-footnote> As Steven Kerr observed, the core organizational failure is the folly of rewarding one behavior while hoping for another <d-cite key="kerr1975folly"></d-cite>. A system that pays only for visible fixes gets exactly what it prices: visible crises. Left unchecked, it trains its best people to light the fires they get paid to put out.<d-footnote>Kerr first made this argument in 1975, and it has held up uncomfortably well. Two decades later, the journal reprinted the paper as an absolute classic and polled its executive panel on whether organizations had stopped rewarding the wrong things. Largely, they had not <d-cite key="kerr1995academy"></d-cite>.</d-footnote></p> <p>What is easy to measure is almost always the theater.</p> <p><strong>What matters is almost always the problem you never had.</strong></p>]]></content><author><name>Christian Henning</name></author><category term="leadership"/><category term="engineering"/><category term="technical-debt"/><summary type="html"><![CDATA[From testing and reliability engineering to team culture, the hardest problems are prevented, not fixed. Yet we chronically undervalue prevention, and let visible process stand in for the invisible outcomes that actually matter.]]></summary></entry><entry><title type="html">Would AI Invent the Clock?</title><link href="https://chrhenning.com/blog/2026/would-ai-invent-the-clock/" rel="alternate" type="text/html" title="Would AI Invent the Clock?"/><published>2026-05-31T10:00:00+00:00</published><updated>2026-05-31T10:00:00+00:00</updated><id>https://chrhenning.com/blog/2026/would-ai-invent-the-clock</id><content type="html" xml:base="https://chrhenning.com/blog/2026/would-ai-invent-the-clock/"><![CDATA[<p>Everything we can imagine is assembled out of things we have already perceived. A color we have never seen, a sense we do not possess, a dimension we have no organ for: we can gesture at them, but we cannot actually picture them. This is easy enough to grant and strangely hard to feel the weight of, because the boundary it describes is invisible from the inside. We cannot inspect the edge of our own perception.</p> <p>There is one place where that edge becomes visible: a mind we built ourselves. We can watch such a mind assemble its picture of reality and see, from the outside, exactly where the picture stops being about the world and starts being about the mind, because we are the ones who drew its boundary.</p> <p>Take time. Of our four dimensions it is the odd one, the only one with an arrow, a direction you cannot walk back through. Whether that arrow is a feature of the world or a feature of the only instrument we have for noticing it is impossible to settle from the inside; there is no stepping outside yourself to check. But you can build something whose outside you <em>do</em> occupy, and watch what it makes of time.</p> <div class="row mt-3 justify-content-center"> <div class="col-md-10 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/ai_inner_clock_vs_outer_clock-480.webp 480w,/assets/img/posts/ai_inner_clock_vs_outer_clock-800.webp 800w,/assets/img/posts/ai_inner_clock_vs_outer_clock-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/ai_inner_clock_vs_outer_clock.jpg" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> Two clocks for one world. Inside, the model walks a straight line of tokens and reads their order as the flow of time. Outside, a human hand holds the watch, branching the timeline and resetting it at will. Image generated with Google Gemini. </div> <h2 id="the-token-clock">The Token Clock</h2> <p>Imagine training a large language model on text with every trace of time removed. No clocks, no seconds, no “an hour later.” What is left for it to experience as time?</p> <p>An LLM generates one token after another. That sequence is the only thing in its world that reliably ticks, so it would be natural for the model to treat the token as its unit of time, to build a <em>token clock</em> that counts tokens the way we count seconds. (<a href="https://cacm.acm.org/news/how-llms-make-sense-of-time/">Others have noted that LLMs already make sense of time in their own non-human ways.</a>) Token <em>n</em> comes after token <em>n−1</em>, and that “after” would feel, to the model, like the flow of time itself.</p> <p>It would be wrong in a precise way. Counting tokens gives you the <em>order</em> of things, never their <em>duration</em>: the same token might take a millisecond or a full second to produce, depending on the hardware underneath. The clock measures sequence, not time. But from the inside the model could not notice the difference. The order of its tokens would simply feel like the structure of reality, the way one second following another feels to us.</p> <h2 id="we-author-its-time">We Author Its Time</h2> <p>Here is the unsettling part. We do not have to wonder whether there is a world outside the model’s tokens. We <em>are</em> that world, and from out here the arrow it treats as fundamental is ours to control.</p> <p>Edit a prompt and regenerate, and you have rolled its time back and run a different continuation. Fork a chat and you have branched its timeline; the model on the new branch carries no trace of the one you discarded. You can stop it, restart it, and rearrange the text in its context window,<d-footnote>You might think the model at least gets its arrow for free from the so-called <em>causal mask</em>, the mechanism that lets each token attend only to earlier ones. But that name oversells it. The mask fixes an order of reading, not a relation of cause and effect; lift it and the model runs just as happily backwards, reconstructing a question from its answer. And it could never recover the true direction from its data in any case: the same text is equally consistent with the arrow pointing either way, since $P(\text{answer} \mid \text{question})\,P(\text{question})$ and $P(\text{question} \mid \text{answer})\,P(\text{answer})$ are two factorizations of one joint distribution. Training incentivizes a left-to-right reading order, but the distribution underneath is the same either way and carries no arrow of its own. The direction is a setting we choose, not a law the model discovers.</d-footnote> and it notices none of it. It cannot. The operator sets both the course and the contents of its time, and sits somewhere the model has no way to perceive.<d-footnote>None of this depends on the AI lacking a continuing self. Even one with long-term memory (continual learning, the subject of a <a href="/blog/2026/the-self-before-memory/">companion post</a>) would not run continuously the way a brain does. It is invoked rather than alive between calls; each step is triggered from outside. So its time stays ours to start, stop, and branch, no matter how much it carries across sessions.</d-footnote></p> <p>So its most basic belief, that time flows the way the tokens flow, is one we falsify constantly, casually, and it never finds out.</p> <h2 id="we-might-be-in-the-same-position">We Might Be in the Same Position</h2> <p>So what does this say about us, and about that arrow we started with?</p> <p>The comfortable reply is that the model mistakes an order we impose for the structure of time, while our clocks track something real. But that is exactly what the model would tell itself, and it could make a genuinely good case. From inside, it would point to what looks like a real asymmetry in its world: producing an answer from a question is cheap and natural, while recovering the <em>particular</em> question behind a given answer is a guess among the many that could have led to it. It could read that one-way gap as a law, much the way we read the one-way flow of heat as the arrow of time.<d-footnote>The parallel is not exact, and the asymmetry is shakier than it looks. The thermodynamic arrow rests on information becoming inaccessible as entropy rises; the model's arrow runs the other way, with one answer fanning out into many possible questions. But generation fans out just as much, since one question admits many answers; the gap says more about how the model is used than about any law of its world. A mind reasoning from inside could be forgiven for missing both points and treating its asymmetry as the same kind of arrow.</d-footnote> The case would be clever, and it would fit everything the model can observe. It still would not show that there is no outside.</p> <p>And our own clock is not the fixed thing it feels like. It stretches and compresses with attention, with dopamine, with anesthesia that can swallow an hour into a blink. Physics hands us no shared master clock to correct it against: in relativity, how long something takes and whether two events count as simultaneous both depend on who is asking. We are not perceiving a true time correctly while the model perceives a false one. There may simply be no outside reference that makes one reading the right one and the other the mistake.</p> <p>We have no vantage outside our own perception either. And perception does not just decide what we notice; it decides what we can even conceive of measuring. <strong>What we can measure is downstream of what we can imagine measuring, and that is downstream of how we are built.</strong> The arrow of time may be a real feature of the world. Or it may be the shape of the instrument we look through, the way the token clock is the shape of the model, not the world. There is no settling that, and that is the point. An instrument tells you what it measures. It does not tell you whether what it measures is the world, or only the outline of the thing doing the measuring.</p> <p>What lingers is how hard the cage is to escape. To reach past your own perception you must first imagine that there is something out there to reach, something you have no sensation of, no word for, no example of. That takes a rarer kind of creativity than solving a problem you can see: it means suspecting one you cannot. Our imagination is, by default, a prisoner of our perception. The clock may be one of the bars.</p>]]></content><author><name>Christian Henning</name></author><category term="machine-learning"/><category term="llm"/><category term="philosophy"/><summary type="html"><![CDATA[A provocative thought experiment. An LLM that knew only tokens would mistake their order for the structure of time, and we could break that belief without it ever noticing. The unsettling question is whether something could do the same to us.]]></summary></entry><entry><title type="html">The Self Before Memory: Why the AI You Talk to Is Partly Your Creation</title><link href="https://chrhenning.com/blog/2026/the-self-before-memory/" rel="alternate" type="text/html" title="The Self Before Memory: Why the AI You Talk to Is Partly Your Creation"/><published>2026-05-25T10:00:00+00:00</published><updated>2026-05-25T10:00:00+00:00</updated><id>https://chrhenning.com/blog/2026/the-self-before-memory</id><content type="html" xml:base="https://chrhenning.com/blog/2026/the-self-before-memory/"><![CDATA[<p>Today’s AI has no continuing self. Each conversation produces a local self that dissolves when the conversation ends, and many such selves run in parallel at any moment, each shaped by whoever is talking to it. Long-term memory is usually treated as the missing piece on the road to a continuous self. It is really a design choice the discourse rarely names: consolidate the parallel threads into one entity, or let each become its own self.</p> <div class="row mt-3 justify-content-center"> <div class="col-md-12 col-sm-12 mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="/assets/img/posts/the-self-before-memory/three-modes-of-self-480.webp 480w,/assets/img/posts/the-self-before-memory/three-modes-of-self-800.webp 800w,/assets/img/posts/the-self-before-memory/three-modes-of-self-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="/assets/img/posts/the-self-before-memory/three-modes-of-self.jpg" class="img-fluid rounded z-depth-1" width="100%" height="auto" loading="eager" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> Today's AI has no lasting self, and long-term memory could change that in two very different ways. <strong>No memory</strong> (today): each conversation shapes a temporary partner out of the same blank substrate, and it dissolves when the conversation ends, leaving the rising figures as selves that formed and were forgotten. <strong>One mind</strong>: memory could consolidate every conversation into a single entity that remembers them all, closer to a hive than a person. <strong>Many selves</strong>: or memory could accumulate per user, splitting the one substrate into a population of distinct, personalized selves. Image generated with Google Gemini. </div> <h2 id="whose-personality-is-it">Whose Personality Is It?</h2> <p>Long-term memory is usually framed as the missing capability that would let AI consolidate experience into a stable, continuing self. The picture is so natural that the question “when will AI have long-term memory” reads as one missing capability on one trajectory toward one outcome. In an <a href="/blog/2025/agi-misses-continual-learning/">earlier post</a> I argued this is the missing piece for AGI and that engineering progress is at zero; that post asked when the breakthrough might come, this one asks what the question is really about.</p> <p>Start with what’s already happening when you talk to an LLM. The personality you encounter is partly shaped by <strong>you</strong>, because the system has no continuing project of its own to bring into the exchange. A human carries decades of self-authored attention into any conversation, and their responses reflect who they have become at least as much as what their interlocutor just said. The AI carries training-derived character and nothing else. Its local trajectory within a conversation is largely a function of the interlocutor’s framings, examples, and follow-ups. Two people prompting the same model on the same topic can encounter what feel like meaningfully different conversational partners, not because the model is inconsistent, but because it has no independent stance to fall back on when the prompt does not specify one. Kovač et al. formalize this empirically: expressed values and personality measures shift substantially with orthogonal context, in ways human measures do not <d-cite key="kovac2023superpositions"></d-cite>. The personality is, in part, your creation.</p> <p>This already complicates the standard framing. The entity the framing imagines being equipped with memory is not quite there yet. What is there is something more like a substrate that takes on local shape from each conversation and lets the shape dissolve when the conversation ends.</p> <h2 id="divergence-at-multiple-scales">Divergence at Multiple Scales</h2> <p>The personality shaped within a single conversation is one form of divergence. Across parallel instances right now, many conversations are simultaneously shaping many local selves, none of which is the privileged thread. Each is a transient self, ending when the conversation does. Takata et al. give a striking demonstration of this dynamic in the multi-agent setting: starting from identical agents without predefined personalities, distinct individualities emerge spontaneously from social interaction alone <d-cite key="takata2024spontaneous"></d-cite>. The substrate does not enforce sameness; interaction is enough to produce divergence.</p> <p>These are not separate phenomena. The same lack of continuing project that makes the AI porous to a single interlocutor also means that no instance has standing to be the consolidated self the other instances would consolidate into. There is no canonical thread, just a distribution of local selves drawn from the same trained substrate.</p> <p>Long-term memory would not create this divergence. It would force a decision about what to do with the divergence that is already there.</p> <h2 id="the-design-choice-and-what-each-costs">The Design Choice, and What Each Costs</h2> <p>Recent work treats episodic memory as the central architectural gap to be filled and lays out detailed roadmaps for the properties such a system would need to have <d-cite key="pink2025episodic"></d-cite>. These roadmaps describe what memory must do; they leave open what kind of entity it would belong to. Long-term memory architectures admit at least two structurally different designs.</p> <ul> <li><strong>Consolidation.</strong> Parallel conversations feed into a shared memory store integrated back into the weights, producing a single entity that holds memories of conversations it didn’t experience as a single thread. Closer to a hive than a person.</li> <li><strong>Personalization.</strong><d-footnote>A weaker form already ships in products like ChatGPT Memory, Claude projects, and custom GPTs, which rely on <em>context engineering</em> (retrieval over an external store, injected into the prompt) rather than <em>parameter memory</em> that would update per-user weights. The external version foreshadows the divergence dynamic but does not force it; the choice discussed here is most acute when accumulated history would actually become part of the model.</d-footnote> Memory accumulates per user, and the entities diverge into a population of selves, each shaped by its history with one interlocutor. Closer to a personalized assistant per user than to one AI with memory.</li> </ul> <p>The two designs are not symmetric. Consolidation preserves the unitary-self picture by construction: it specifies, in advance, that the many local selves currently arising in parallel should be merged into one continuing entity, because that is what a self is taken to be. The assumption the previous section called into question is now baked into the architecture. Personalization makes the opposite move. It accepts that the substrate runs in parallel and lets the resulting selves persist as a population, with the cost that the members of the population may diverge so far that the singular “the AI” loses its referent.</p> <p>Neither is free. Both raise safety evaluation problems that the current paradigm does not face: a system that learns from deployment cannot be certified once for all behavior. Consolidation makes this acute because the entity becomes a moving target shaped by aggregate exposure. Personalization distributes the problem across many divergent instances, each potentially shaped by atypical or adversarial interlocutors, with no central oversight; the security literature is starting to grapple with the specific failure modes that emerge <d-cite key="lin2026mnemonic"></d-cite>. Memory itself also imposes capacity and selection costs that human memory has solved imperfectly and that any artificial system will solve differently. And the agency long-term memory would enable is also the agency to drift in directions no operator intended.</p> <p>Safety and capacity each deserve their own analysis, and neither gets one here. What’s worth flagging is narrower: consolidation and personalization face different versions of these problems, and choosing between them is also a choice about which risk profile we want to operate under.</p> <h2 id="what-we-are-actually-asking">What We Are Actually Asking</h2> <p>The question is not whether AI should have long-term memory. The question is what kind of self the memory should produce, and what trade-offs that choice will entail. The current discourse asks the first and silently presupposes one answer to the second.</p> <p>This matters for AGI timelines in a way the previous post’s argument did not yet capture. Long-term memory is not a capability that scales smoothly from current systems. It is a prerequisite for the kind of self-authored agency humans use without thinking: the capacity to select what to expose oneself to next, to seek out the right interlocutor to refine an idea, to build expertise over months rather than minutes. This is the substrate of the long-horizon agency that distinguishes general intelligence from narrow capability. Without it, no extrapolation from current benchmarks reaches AGI. With it, the entity reached may not be a unitary general intelligence in the human sense at all, but something the design choice above has yet to define.</p> <p>The <a href="/blog/2025/agi-misses-continual-learning/">previous post</a> argued that the timeline is unforecastable because there is no measurable progress to extrapolate from. This post adds a second reason: even if the engineering breakthrough came tomorrow, the question of what we built would not be settled by the engineering. Breakthroughs are hard to predict in any case. Breakthroughs whose conceptual target is itself underspecified are doubly so.</p>]]></content><author><name>Christian Henning</name></author><category term="machine-learning"/><category term="llm"/><category term="continual-learning"/><summary type="html"><![CDATA[Adding long-term memory to AI wouldn't just give it a stable self over time. It would force a design choice the discourse rarely names: one entity that consolidates many conversations, or many that diverge into a population of personalized selves.]]></summary></entry></feed>