Epic 52 — giving the overseer a memory the agent can't write
2026-06-09
A single cycle is easy to supervise; a sequence of them is where the trouble hides. An agent that withdraws from a vault, then redeposits into the one it just left, then withdraws again is not malicious — it is just reacting cycle by cycle to numbers that wobble — but it churns capital and pays fees for nothing. None of the per-transaction policy gates catch this, because each individual move is fine. What is wrong is the pattern across moves, and to see a pattern you need to remember the moves. Epic 52 is the Decision Ledger: the overseer now carries cross-cycle memory — recent rotations, denied fingerprints, and a projected-versus-realized record — and folds a summary of it back into the top of each new cycle.
The decision that shaped the whole epic was where the memory lives. We put it in the overseer, not the agent. The reasoning is straightforward and a little uncomfortable: the agent is the component making the decisions, and if it also authored its own memory of those decisions, it could quietly reinforce its own bad ones — a loop that grades its own homework. So the memory is a derived, overseer-owned fact set. GET /v1/memory returns the denied fingerprints and the oscillation signals it has observed, and the agent receives that at cycle-top as context it reads but cannot rewrite.
One column in that ledger is projectedApr, captured write-only at propose time. The agent states what return it expects when it proposes a move, we record it, and — deliberately — we never feed that projection back into the prompt. A model's own optimistic forecast, echoed back to it later, is poison for calibration: it would learn to trust its earlier self instead of the on-chain outcome. The projection is there so a human can compare what was promised against what actually happened; it is not there for the agent to lean on.
This is honest about its limits. The memory catches the oscillation patterns we have modeled, not every possible one, and a determined bad loop could still find a shape we have not anticipated. It also bit us during the build: the query that surfaced the most recent denied fingerprint was selecting the lexically largest intent rather than the latest-denied row — a subtle bug that showed up six separate times before we correlated the sightings and rewrote it. That is the point of building in public. The fix is real, the gap that remains is real, and both belong on the record.