DEV Community

Cover image for The Reasoning Ledger: Remembering Decisions, Not Just Data
Ken W Alger
Ken W Alger

Posted on Originally published at kenwalger.com

The Reasoning Ledger: Remembering Decisions, Not Just Data

Git analogy clarifies agent memory gaps

Part 4 of the Building the AI Memory Stack series

After finishing the previous article, I looked at the repository a little differently. The specifications were still there. The Architecture Decision Records were still there. The glossary entries were still there. The project's durable memory had done exactly what it was supposed to do: preserve the knowledge that deserved to survive.

But something was missing. I could see what existed, but I couldn't always see why it existed.

Memory tells you what. Reasoning tells you why.

That distinction turns out to matter.

Durable Memory Isn't the Whole Story

In the previous article, I argued that Durable Memory decides what knowledge deserves to outlive the task that created it.

That remains true. But imagine opening an Architecture Decision Record six months later and asking:

Why was this decision made?

The document gives you the conclusion, but it may not give you the path that produced it. Perhaps the decision came from competing specifications, several tool invocations, human review, rejected alternatives, or a policy constraint that no longer exists.

The final artifact survives. The reasoning process often does not.

Another Layer in the Stack

Diagram of the AI Memory Stack highlighting the Reasoning Ledger as the layer that preserves why decisions happened. Information flows from the Reasoning Ledger to Durable Memory, Active Working Memory, the Context Window, and finally Model Inference.

Layer Primary Question Preserves
Reasoning Ledger Why did this happen? Decisions
Durable Memory What should survive? Knowledge
Active Working Memory What matters now? Working set
Context Window What can the model see? Current tokens

Software Already Solved Part of This

Git repositories preserve more than source code. They preserve commit history, pull requests, code reviews, issues, and discussion. Together they explain how software evolved.

Imagine if Git only stored the latest version of every file. The software would still exist, but understanding it would become dramatically harder.

Git doesn't exist because developers forget what their code looks like. It exists because developers eventually ask:

Why did we change this?

Agentic systems deserve the same architectural capability.

The Missing Layer

Most AI systems optimize retrieval, but far fewer preserve the observable decision process surrounding an inference. If someone asks months later:

Why did the system recommend this?

can we answer?

If the only answer is "because the model said so," then the system hasn't preserved enough information to be trustworthy. We've preserved knowledge but lost understanding.

The Reasoning Ledger

The Sovereign Systems Specification calls this architectural layer the Reasoning Ledger.

It deliberately avoids recording private chain-of-thought.

It records the observable architecture surrounding a decision.

A ledger may capture:

  • Evidence consulted
  • Tool invocations
  • Policy evaluations
  • Human approvals
  • Timestamps
  • Confidence assessments
  • References to durable artifacts
  • Links to Forensic Receipts

In practice, a single record might look like this:

reasoning_ledger:
  decision: "Approve deployment"
  timestamp: 2026-03-14T09:22:00Z
  evidence:
    - artifact: ADR-014
      authority: architecture-review
      version: 3
    - artifact: production-health-metrics
      observed_at: 2026-03-14T09:20:00Z
    - artifact: security-policy
      authority: security-team
      version: 7
  tools:
    - GitHub
    - CI pipeline
  approvals:
    - release manager
  outcome: approved

Notice that the ledger does not merely record that a security policy was consulted. It can preserve which policy, which version, and which authority governed the decision at that moment. That distinction matters because evidence can remain perfectly retrievable long after the world that made it authoritative has changed.

The Reasoning Ledger is therefore a historical record, not a promise of continuing authority. It tells us what governed the decision then. Determining whether the same evidence still governs a future decision belongs elsewhere in the architecture.

The goal is not to reconstruct what happened inside the model. It is to preserve the externally observable evidence, authorities, policies, tools, approvals, and outcomes that allow someone to examine the decision later.

Observable reasoning is architecture. Private reasoning belongs to the model.

Memory Preserves Knowledge. Reasoning Preserves Decisions.

Memory is fundamentally a write problem, while reasoning is fundamentally an accountability problem. Memory preserves knowledge. Reasoning preserves decisions.

Both are required for trustworthy AI systems.

Looking Ahead

A Reasoning Ledger explains the observable path that produced a decision.

But how do we know those records themselves have not been altered?

That is where Write-Side Custody begins, and where Part 5 will take us.

Top comments (62)

Collapse
 
publiflow profile image
PubliFlow

Good coverage of ML patterns. I'd stress that monitoring data drift and model staleness is as important as the initial training — a model that was accurate at launch can silently degrade without proper observability.

Collapse
 
publiflow profile image
PubliFlow

Interesting ML content! We built a suite of AI tools at tools.shopveigo.com — essay polisher, copywriter, interview coach, image processing. The inference cost optimization you mentioned is something we deal with daily. Happy to compare notes.

Collapse
 
wrobeltomasz profile image
Tomasz

That's a cool idea—I'd never thought of that before. After all, Git is supposed to contain everything, but it turns out it doesn't. I think this can be easily realized with Python and SQL. It's a good tool for companies that want to monitor the performance of AI models.

Collapse
 
xiaoxiao2026 profile image
xiaoxiao2026

“Remembering decisions, not just data” is a really interesting idea. Storing knowledge alone isn't enough. Knowing why a decision made sense at the time could be much more valuable for future maintenance and troubleshooting.

Collapse
 
mnemehq profile image
Theo Valmis

The distinction between what and why is the right layer to add, and it's worth pushing one step further: a Reasoning Ledger that only gets read by a human six months later is an archive. The version that actually earns its keep is one an agent has to check before it makes the next decision, so the why from six months ago can veto a locally reasonable choice today. That's the layer we're building at Mneme, less a ledger you consult and more a constraint you can't generate past.

Collapse
 
alexshev profile image
Alex Shev

The post makes a useful distinction between a feature working once and a system being dependable. I’d add an explicit failure-mode checklist so the next contributor can see which assumptions are intentional and which ones still need evidence.

Collapse
 
codingwithjiro profile image
Elmar Chavez

Really interesting read. If this would be automated, this is like a goldmine for looking back on as to "why" this part of the code was built in the first place.

Collapse
 
gnomeman4201 profile image
GnomeMan4201

One thing I’d be tempted to make first class here is disconfirming evidence / rejected alternatives, not just the evidence that survived into the decision.

I’ve run into this from the investigation side: if the ledger only preserves what supported the final conclusion, you can reconstruct why it looked reasonable, but lose what competed with it, what failed a threshold, or what remained unresolved.

Something like alternatives_considered, disconfirmed_by, and maybe unknowns/scope_limitations would make the historical record harder to turn into a post hoc justification of whatever eventually won.

An immutable ledger can preserve history perfectly and still preserve a biased history if the losing evidence disappears before the write

Collapse
 
kenwalger profile image
Ken W Alger

This is a really good distinction. Immutability protects the record after the write, but it says nothing about whether the write captured a representative account of what was available at the time of the decision.

I especially like making rejected alternatives and disconfirming evidence first-class rather than burying them in an evidence list. Otherwise, the ledger can become a very trustworthy record of a selectively remembered decision.

unknowns and scope_limitations belong in that same category for me. "We chose A because of X" is a different historical claim from "we chose A because of X, rejected B because of Y, and could not resolve Z." The second is much more useful when someone later asks whether the decision was reasonable given what was actually known.

Collapse
 
gnomeman4201 profile image
GnomeMan4201

Agree with the split. I’d add that the two halves aren’t equally tractable.

The read side failure is comparatively testable. Give the store a question, inspect what comes back first, and check whether retrieval respected supersession, validity, and which record actually won. You can red-team that and keep regressions for it.

The write side problem is nastier because anything omitted never crossed the ledger boundary in the first place. An empty alternatives field can mean “nothing challenged this,” “nothing was looked for,” or “something challenged it and never made the write.” From the record alone, those can look identical.

So the negative space probably has to become evidence too: no alternatives found, not evaluated, freshness check not required, with enough provenance that someone can later challenge the assertion itself. That still doesn’t make no alternatives found true it just turns an invisible omission into an attributable, falsifiable claim.

What’s interesting is that this same shape keeps appearing elsewhere in the thread: the skipped freshness check, the missing alternative, the compacted coverage window. Different mechanisms, same failure mode silence gets interpreted as confirmation.

And that may be the bigger risk with a reasoning ledger: not just faithfully remembering the wrong thing, but letting strong integrity guarantees on the container get mistaken for guarantees about the completeness or truth of what made it inside.

Thread Thread
 
brainbootdev profile image
brainbootdev

There is a fourth mechanism with that same shape, and it sits upstream of the write: the collector was pointed somewhere that no longer existed. A scanner of ours had a hardcoded root that had been moved months earlier, so every run completed successfully, found nothing, and recorded a clean empty result. Nothing failed, so nothing was ever flagged.

Which is why "no alternatives found" probably has to carry where it looked, not just that it looked. A well formed empty answer from a broken instrument is byte for byte identical to a true negative, and it is the one that arrives with a green check next to it.

Thread Thread
 
kenwalger profile image
Ken W Alger

I think "negative space has to become evidence too" is the right extension, especially because it separates nothing was found from nothing was looked for. Those are radically different claims that collapse into the same empty field otherwise.

I'd probably model that as an explicit observation rather than trying to infer meaning from absence: alternatives_evaluated: true, result: none_found, plus enough provenance to say what was searched and under what scope. That still doesn't prove there were no alternatives. It proves the system performed a particular search and observed none within that boundary.

And your last point is the important limit: integrity of the ledger proves integrity of what crossed the boundary. It cannot prove completeness of what should have crossed it, much less truth about the external world.

That's increasingly the distinction I want the architecture to preserve: "nothing was observed" is a claim; an empty record is just silence.

Thread Thread
 
gnomeman4201 profile image
GnomeMan4201

A negative observation requires not merely evidence that a search occurred, but evidence that the search completed to a declared adequacy threshold within a defined scope and observation interval

Collapse
 
gde03 profile image
Giulio D'Erme

Agreed, and I would add what it costs on the read side, since that is the part I
found out late.

The retracted claim is usually the nearer semantic match to the question that
provoked it. It was written to answer exactly that question. Its correction tends
to be written as commentary on the claim, hedged and qualified, and sits further
from the question's wording. So a ledger that faithfully keeps both and then ranks
by similarity hands back the losing evidence, confidently, as the best match.

That is not a tuning problem. A ranker with no notion of validity has no way to
prefer the correction, however good the embeddings are. Completeness of the write
does not survive on its own: each hit has to carry a verdict at read time saying
what it is, superseded by what, and whether it is inside its validity window.

Which makes your point a slightly stronger one than stated. Deleting the losing
evidence gives you a biased history. Keeping it without a verdict gives you a
biased history that also retrieves better than the truth.

Collapse
 
kenwalger profile image
Ken W Alger

This is a really important extension of the argument. The retracted record being the better semantic match is exactly the sort of failure that can look like successful retrieval by every conventional metric. The ranker found the record most closely matching the question. It just had no way to know that the record had lost.

I think your "verdict at read time" framing is the key. Preserving correction, supersession, and validity at write time isn't enough if retrieval flattens those relationships back into independent hits. The relationship has to survive the retrieval boundary too.

That actually became one of the central arguments in a follow-up I published after some of these discussions: Your Memory API Is Lying to Your Agent. A ranked list can faithfully return both records while discarding the fact that one superseded the other. At that point, relevance quietly becomes authority.

And "keeping it without a verdict gives you a biased history that also retrieves better than the truth" is a wonderfully uncomfortable way of putting the problem.

Collapse
 
p0rt profile image
Sergei Parfenov

observable reasoning is architecture, private reasoning belongs to the model: sharpest line in the series, cleaner than my july framing of "provenance is a capability u hold, not a field u write". stealing pm25coder's "same entry shape, different trust" (credited).

one gap the thread hasn't touched: who holds the pen per field. retrieval_method: fresh is either minted by the tool boundary that ran the fetch, or it's the agent describing what it thinks it did. same yaml, two epistemic statuses, and the schema can't tell them apart. imo each field carries an author type: runtime-minted (tool calls, retrieval events, approvals, timestamps) vs agent-reported (decision, alternatives, unknowns, confidence), and unmarked defaults to agent-reported, so untrusted. compaction is the third author nobody types.

so for write-side custody: does the agent get to write retrieval_method at all, or is it minted at the tool boundary? if the agent holds that pen, custody protects a claim, not a fact.

Collapse
 
kenwalger profile image
Ken W Alger

I think “who holds the pen per field” is the right way to sharpen this. There’s a meaningful difference between the agent reporting that it used fresh evidence and the runtime that actually performed the fetch attesting that the evidence was fresh.

So I’d separate reported claims from witnessed events. The agent can own things like the decision, alternatives considered, unknowns, and confidence. The runtime/tool boundary should own claims it can independently establish: retrieval events, tool execution, returned policy versions, approvals, timestamps, etc.

And agreed that entry-level provenance isn’t quite enough once those coexist in the same record. retrieval_method: fresh has a different epistemic status depending on whether it was minted by the boundary that performed the retrieval or merely reported by the agent afterward. Same YAML, very different evidence.

I also like the compaction observation. A projection or summary is effectively making a new claim about the underlying record, so its authorship/provenance matters too. It shouldn’t quietly inherit the epistemic status of the evidence it summarizes.

Which brings me back to your last line: custody can preserve an agent’s claim perfectly without turning that claim into a witnessed fact. Knowing who was allowed to hold the pen is part of knowing what the record actually proves.

Collapse
 
p0rt profile image
Sergei Parfenov

reported claims vs witnessed events is the schema boundary i was missing. i’d attach issuer and evidence class per field, then treat every summary as a new derived record with its own provenance rather than a transparent view. custody preserves the claim; it never upgrades who observed it.

Thread Thread
 
kenwalger profile image
Ken W Alger

Yes, I think that's the right conceptual model. For me, the important part is that provenance has enough resolution to tell us who or what was entitled to make each claim and what evidence supports it. Whether an implementation literally stores issuer/evidence class beside every field or groups fields that share the same provenance is probably a representation choice.

And agreed on summaries. Once a system transforms several witnessed and reported fields into a new statement, that statement has its own authorship and evidentiary status. It can reference the records it summarizes, but it doesn't inherit their authority merely because it was derived from them.

“Custody preserves the claim; it never upgrades who observed it” is a very clean invariant. I think that survives beyond the ledger too.

Collapse
 
kenielzep97 profile image
Self-Correcting Systems

read this next to the memory api piece from the same day, and i think the two are solving different halves of one problem with the second half still open.

the api piece is the case where the store knows. both records exist, the supersession edge exists, and the interface flattens it on the way out. return the graph instead of the list and the agent can see what it was already holding.

the ledger piece names the harder one and then routes it away. evidence can remain perfectly retrievable long after the world that made it authoritative has changed, and whether the same evidence still governs belongs elsewhere in the architecture. right call for scope. i also think elsewhere is where most of the damage lives, because in that case there is no edge to preserve. nothing inside your system ever observed the change. the record is well formed, in policy, internally consistent, and wrong.

that does something specific to a ledger. it produces a flawless account of a decision that was already wrong when it was made. if security-team published version 8 an hour before your 09:22 entry, the entry still faithfully records version 7, and nothing in the ledger can flag it, because the ledger is consistent with itself. thats the one failure a perfect audit trail cannot surface.

so one schema question. the entry records version 7 but not how the 7 was obtained. copied from a cached artifact, or re derived from the authority at 09:22, produce identical entries and completely different trust, and the reader six months later cannot tell which one happened.

i built both gates to find out what that costs. the timestamp only baseline returned ALLOW on the divergence cell, recorded version still inside ttl, source already moved. re derivation caught it. scope stated honestly: five of seven cells against a real external source, two still open.

Collapse
 
kenwalger profile image
Ken W Alger

I think this is exactly the distinction between the two pieces. The Memory API problem is lossy retrieval: the system knows A was superseded by B and then throws that relationship away on the way to the agent. The harder ledger case is epistemic: B changed somewhere outside the system and no observation of that change ever crossed the boundary. There is literally no edge available to preserve.

And I agree that this exposes a hole in the example schema. policy_version: 7 isn't enough. A future examiner needs to know how v7 became the governing authority for that decision: fetched from the authority at decision time, retrieved from a cache, inherited from session state, etc. Those can produce identical version fields while supporting very different claims about what the system could reasonably have known.

I'd still keep re-derivation outside the ledger itself. The ledger should witness that the authority was fetched, from where, when, what came back, and whether cached state was involved. The mechanism responsible for deciding that a fresh authority check is required belongs at the appropriate policy/use boundary.

Your divergence cell is a particularly good demonstration of why TTL and authority aren't interchangeable. TTL can say "this cached artifact is still inside the period in which we agreed to reuse it." It cannot say "the external authority has not changed." The first is locally computable. The second is news.

And your "flawless account of a decision that was already wrong when it was made" formulation gets at an important limit of auditability. A perfect ledger can tell us exactly what the system knew and did. It cannot retroactively give the system knowledge it never acquired.

Collapse
 
kenielzep97 profile image
Self-Correcting Systems

agreed on the boundary, and locally computable versus news is a better line for it than anything i had.

the thing that boundary leaves blank is the decision not to check. if the ledger witnesses the fetch and the deciding mechanism sits at the policy boundary, then a decision made after a fresh check carries a fetch event and a decision made without one carries nothing. nothing covers too much. policy correctly determined no fresh check was needed, the check was skipped, the mechanism is broken, or nobody wired it into that path. all four produce an identical entry.

so the skip probably has to be an event too. not only fetched from authority X at 09:22, received v7, but also evaluated freshness requirement, fresh check not required, reason within agreed reuse window. your own framing is what makes me want it. observable reasoning is architecture, and choosing not to re derive is reasoning. right now its the only decision in the system that leaves no trace.

and it inverts the failure in a useful way. an entry saying we decided not to check is auditable, someone can disagree with that reason six months later. an entry saying nothing is unfalsifiable, because there is no way to separate a correct skip from a mechanism that was never there.

Thread Thread
 
kenwalger profile image
Ken W Alger

Yes. I think you've convinced me that the skip is itself an observable decision when freshness/revalidation is part of the governing policy.

Otherwise no fetch event is hopelessly overloaded: fresh check not required, check accidentally skipped, mechanism failed, or mechanism never existed all collapse into silence. Recording freshness evaluated → revalidation not required → reason: within reuse window turns one of those cases into an attributable claim that can actually be challenged later.

I wouldn't record every operation the system didn't perform, obviously. The boundary I'd use is whether policy required the system to make an explicit choice about performing it. Once "should I revalidate?" is a policy evaluation, both YES and NO are decisions worth witnessing.

That also gives me a cleaner formulation of the negative-space problem emerging elsewhere in this thread: absence is only evidence when the system can prove it evaluated the possibility of presence.

Collapse
 
pm25coder profile image
pm25coder

The provenance gap you've named is the one I'd bet on too: a record that says "version 7 governed this" without saying how version 7 was obtained is only half an audit trail. In the system I run, we solved it by making the authority fetch itself the recorded event - the ledger entry stores which source was consulted, the version returned, and the retrieval timestamp, and re-derivation is the default path (cached artifacts must be explicitly marked as such, which is then visible in the diff). Same entry shape, different trust, exactly as you found.

Your "no edge to preserve" case is the sharper one though - it's the failure mode where the ledger is consistent so nothing can flag it. We hit that exact shape with policy changes: an entry records policy v7, the authority moves to v8 silently, and the ledger stays perfectly coherent and perfectly wrong. The only fix we've found is periodic re-validation jobs that re-fetch the referenced authorities and emit a "still current" / "stale" marker - the ledger can't see the world changed, so something outside the ledger has to check. If your re-derivation gate already covers that, you're ahead of where we were.

Collapse
 
kenwalger profile image
Ken W Alger

I like treating the authority fetch itself as an observable event. That closes a gap in the example schema I used because policy_version: 7 tells a future reader what supposedly governed, but not how the system established that v7 was authoritative at the time. "Fetched from authority X at 09:22 and received v7" is a much stronger historical claim than "used v7."

I also like explicitly distinguishing re-derived authority from cached authority rather than pretending they're equivalent evidence. Same version, very different provenance.

On the silent v7 → v8 case, I think we're arriving at the same boundary. The ledger can preserve what the system observed, but it can't observe a change that never entered the system. Something has to revalidate against the external authority and then write that new observation back into the evidence history. The interesting distinction for me is that the revalidation mechanism remains outside the ledger, while its result becomes another event the ledger can preserve.

Your periodic still current / stale marker is a nice concrete implementation of that. It also makes the absence problem explicit: the ledger isn't claiming continuous authority between checks, only that authority was observed at particular moments.

Thread Thread
 
pm25coder profile image
pm25coder

The "not claiming continuous authority between checks" is the honest epistemic core of the whole design - it converts the ledger from "this is true" into "this was observed to be true at these moments", and everything reviewable follows from that. One practical consequence worth naming: the revalidation markers are themselves ledger events, which means they participate in the same evidence rules as the decisions they qualify - they get superseded, they get compacted, they show up in the diff. So the revalidation loop doesn't just fix staleness; it keeps the ledger's own evidence chain honest. And the "fetched from authority X at 09:22, received v7" form has a side benefit you'll like: it makes the absence case greppable - "no fetch event for source X after date D" becomes a query, not an archaeology project.

Collapse
 
kenielzep97 profile image
Self-Correcting Systems

behind on the part you named, ahead on three others.

behind: nothing in ours re examines a past decision. the gate only fires when an action is attempted, so a stale grant nobody acts on sits there unexamined forever. your periodic job catches that and we have no equivalent.

ahead, and this is the part that speaks to your job. unreachable is a separate verdict from stale in ours. REFUSED_UNREACHABLE and REFUSED_STALE are different decisions, so a source we could not reach can never be recorded as a source we checked. does your still current marker distinguish those? thats where id look first, because a job that cant reach the authority and a world that hasnt changed both produce a quiet ledger.

the source adapter also asserts agent_writable is false at construction, so re deriving from agent authored state isnt a convention we follow, its a thing that wont instantiate. and the entry stores raw before and after instead of a derived stale flag, so a reader recomputes the verdict rather than trusting ours.

where i think the real answer is, and its not a scheduled job: re derive at read time. every time someone opens a past entry to justify a present belief, run the same comparison then. the entry already carries the snapshot, so nothing new needs storing. no schedule to die, no silence to interpret, and the check happens exactly when the answer is being used.

my nightly job is dead right now, runs 4 exit 127 against a script that isnt there. which is most of why i dont want the fix to be another scheduled thing.

Thread Thread
 
pm25coder profile image
pm25coder

Yes - unreachable and unchanged must be different verdicts, and yes, our marker distinguishes them: the revalidation event records current / stale / unreachable, and the unreachable case is also timestamped so a later reader sees "not verified since D because the source wouldn't answer", not "verified at D". We learned that the hard way - a source down for a day looks identical to a world that didn't change, and the quiet ledger is how false permanence sneaks in.

But your read-time re-derivation is the better end-state and I'll say so plainly: the scheduled job is a crutch for a data model that hasn't caught up. If the entry already carries the snapshot, running the comparison at the moment the entry is consulted makes the schedule unnecessary - the check happens exactly when the answer is being used, which is the only moment that matters. "No schedule to die, no silence to interpret" is the design goal, not a compromise. And the dead-nightly-job anecdote (exit 127 against a script that isn't there) is the honest data point for why - scheduled things rot precisely because their failure mode is silence.

Thread Thread
 
kenielzep97 profile image
Self-Correcting Systems

the unreachable case being timestamped is the part that matters. not verified since D because the source wouldnt answer is a different sentence from verified at D, and most systems collapse them into the same quiet.

one tension between your two points though. you said the markers are themselves ledger events that get compacted, and you said absence becomes greppable, no fetch event for source X after date D. those fight. after compaction that query cant distinguish nothing was fetched from the fetches were folded away. absence stops being evidence the moment the record it depends on gets summarized.

i have the scar from that exact shape. i asked whether some collectors had gone quiet and got back a confident no, built on schedules, running services, and that days logs. all live, all real. an hour later a gap detector run over the actual data showed nineteen days silent in one window and twenty four in another. the present was verified and the past was asserted.

so what compaction has to preserve probably isnt the events, its the coverage. a folded range needs to carry checked continuously from D1 through D2, or the absence query has to answer unknown for this range rather than no fetch. unknown is the worse answer and the true one.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.