White Paper · Recursive Imitation Learning

Beyond
the Release Cycle

I corrected my assistant once. This is what had to exist for that correction to change what it did the next morning.

Every agent I have ever deployed had the same hole in it: it could be corrected, and the correction went nowhere.

So I built the missing piece and named it RL — a standalone substrate that catches a verdict where it is known, folds it into a score, and reads it back at the moment of the next decision. This paper follows one real correction through it, function by function, in plain language. Where I got it wrong on the way, I say so.

The short version

My assistant believes a supplier’s lead time is three weeks. It is six. I tell it so, once, in passing. What happens to that sentence is the whole subject of this paper.

In most stacks, this: the fact is updated, my correction is written to a log, and nothing is different tomorrow. The system has recorded that it was wrong without becoming less likely to be wrong the same way again. I call the missing step the Read-Back Gap — the distance between a system that records what it learned and a system that consults what it learned. It is silent, because every test anyone writes tests the write.

RL is the piece that closes it. Three tiers — Athena for memory, Aristotle for reasoning, and a reward-and-policy layer — behind one tool surface an agent calls. Sixteen tools sit on that surface. Fourteen are memory and runtime operations. Exactly two belong to the loop: one to report an outcome, one to ask what to do before acting. The second one is the entire point, and it is the one nearly everybody leaves out.

A system that writes down what it learned and never reads it back is not learning. It is keeping a diary.

00 / The use case

One correction, followed all the way down

Here is the scenario I will use for the rest of the paper, because it is small enough to follow completely and real enough to be worth following.

My household assistant keeps a memory card that says a particular supplier delivers in three weeks. That was true last year. It is now six, and the card is being used to plan around a date that will not happen. I tell the assistant it is wrong.

The assistant now has a decision to make, and it is not the obvious one. It could correct the card — write the new lead time over the old. It could quarantine it — mark it untrustworthy and stop using it while a human checks. It could forget it entirely. Or it could do nothing and flag the conflict to me. All four are reasonable. Which is best depends on something no prompt can encode: how those four choices have been working out lately, for this assistant, on this kind of card.

That is the question RL exists to answer, and everything below is the machinery that answers it.

One correction, end to end The agent consults the learned state before acting, passes an intent gate and a deliberation gate, performs the memory mutation, reports the verdict to the outcome ledger, which feeds both an overnight round and a fast path that changes the next morning's ranking. “The lead time is six weeks, not three.” Six steps. Only one of them is the thing people usually build. 1 · ASK FIRST rank the four options reads what was learned 2 · TWO GATES allowed? agreed? both state their answer 3 · THE CHANGE the card is corrected 4 · THE VERDICT one row on disk + who marked it, + real or rehearsal 5 · OVERNIGHT reward → pairs → gate changes the model, needs a gate 6 · NEXT MORNING the ranking differs THE FAST PATH — THIS ONE DOES NOT WAIT FOR A TRAINING ROUND
Visual 1: Step 5 is the one the industry builds. Step 1 and the dashed return are the ones that decide whether any of it matters, and they are cheap by comparison.
01 / Step one

It asks before it acts

Before the assistant touches the card, it calls one tool and hands it the four options it is weighing: correct, quarantine, forget, escalate.

That tool is the only thing on the entire surface that reads what the system has learned. It keeps a small number for every pairing of who is acting and what kind of action — a confidence adjustment, moved a little every time a verdict comes back about that pairing. It returns the four options ranked, with those adjustments applied, and a recommendation.

It also returns something the assistant cannot argue with: a hold. If this actor has failed repeatedly at this class of action recently, the tool says so, and the hold expires on its own rather than requiring anyone to remember to lift it.

Two design decisions inside that call are worth more than the rest of the tier.

The first is that no option is ever scored to zero. Whatever the learned adjustment says, every option keeps a floor, which leaves it a small but real chance of being chosen. That is not a gesture toward open-mindedness. When an option fails, its score drops, and the penalty is supposed to fade over time — but the fading only runs when a new result about that option arrives. An option pushed down and then never chosen again produces no new results, so the penalty never fades. It would sit there for the life of the file, on evidence from one bad week. The floor is the only thing that generates the evidence that can clear it.

The second is that this is not a bandit, and I am not going to borrow the word. There is no exploration bonus and no sampling policy. There is a ranking, a floor, and a caller that is free to take the top answer. That is a weaker guarantee than a proper bandit gives, and stating it plainly is worth more than the vocabulary would be.

02 / Step two

Two gates, and both of them speak

The assistant takes the recommendation — correct the card — and calls the correction tool. Before anything is written, the request passes two gates in order, and this order matters.

The first gate asks whether this actor is allowed to do this at all. It reads a file of learned blockers, refreshed nightly, which records actors that have earned a temporary hold by failing repeatedly. If the assistant is held, the correction is refused, and the refusal names the blocker rather than returning a generic denial.

That gate reads its file in a way that is deliberately unfriendly: if the file is present but unreadable, it does not shrug and continue. It fails closed and says the blockers are unreadable. The version before it did the opposite — a corrupt file was swallowed silently and everything was permitted, which is the worst possible behaviour, because a governance control that disappears when its input is damaged is not a control.

The second gate asks whether anything independent agrees. Destructive memory changes — correct, forget, quarantine — can consult a deliberation source, and here is where I will be precise rather than impressive: in a standalone install there is no such source configured. The gate does not invent an approval. It returns a distinct answer meaning no source, the mutation proceeds on the caller’s authentication alone, and a warning is emitted once at startup naming exactly which surfaces are unmoderated.

Both gates stamp their answer onto the receipt the mutation leaves behind, including when the mutation was blocked. So the record does not merely say what happened; it says what was consulted, what each said, and on what basis the thing was allowed.

A gate that disappears when its input is damaged is not a gate.

03 / Steps three and four

The change, and the verdict that outlives it

The correction itself is the least interesting part: the card is updated in the memory store, the old value is retained, and a receipt is written.

What matters is the next call, and it is the one almost nobody makes. The assistant reports how it went — through a single tool, as a direct call at the decision point rather than an event thrown at a queue. That produces one row, appended to a ledger on disk, carrying what was done, which class of action it was, who marked it, and the verdict.

I chose the direct call over the message bus for a reason I can now prove. The component in this system that captures outcomes from our internal bus subscribes to ten topics, and nothing anywhere in the codebase publishes a single one of them. It had been waiting, correctly and silently, for events that were never going to arrive. The code now says so on its own startup log line.

One field on that row matters more than it looks: where the outcome came from. A system like this generates synthetic activity constantly — replays of old failures, canaries proving a path still works — and in the record it is indistinguishable from real work. So every outcome carries a provenance label, and an unrecognised label raises an error rather than quietly defaulting to “real”. A misspelling that silently defaults is exactly how test traffic ends up inside the headline number.

04 / Step five

What happens overnight

One command runs the nightly round, and it runs eight named stages in a fixed order. Described plainly, they are:

  • Flush the outcomes. Anything captured during the day is settled onto disk.
  • Fold them into reward. Each verdict becomes a score. The formula has two terms — the verdict itself, and a rubric grade — weighted.
  • Build preference pairs. Two attempts at the same task, one better than the other, with the full text of both. This is the raw material a trainer can actually use.
  • Train. Gated on a minimum number of pairs; below the threshold the stage declines and says how short it was.
  • Graduate. The candidate is compared against what is already serving, and adopted only on a measured win.
  • Refresh the learned blockers. Actors with a recent run of failures earn a time-limited hold — the file the first gate reads tomorrow.
  • Maintain memory. Stale claims are re-verified or decayed rather than silently trusted.
  • Drain the replay queue. Cases that failed before are re-run to see whether they now pass.

On the reward formula, I want to be exact, because it is smaller than the usual diagram implies. It has two terms. It had four. A memory-improvement term and a cost term were removed rather than left summing to a structural zero, because neither could be produced: the memory term needs a link from an action to the card it created, and card receipts carry no originating action identifier; the cost term needs a per-action spend row, and the function that would write one has no callers. The code now names what each would need in order to come back, which is more useful than the term was.

On the graduation bar: it used to be any win above zero. That would have promoted a candidate an independent judge scored 28 to 52 against the model already serving. It is now 0.5 — beat what you are replacing, or do not replace it — and the gate fails closed, so a comparison that cannot be run is a refusal rather than a pass.

05 / Step six

The next morning

This is the step that decides whether any of the previous five were worth building.

The assistant faces a similar situation: another card looks wrong. It calls the same tool with the same four options. The ranking it gets back is not the same ranking it got yesterday, because the verdict from my correction moved the confidence adjustment for that pairing of actor and action class. If corrections have been going well, correcting is recommended more readily. If they have been going badly, it is pushed down — but never below the floor, so it retains a route back.

And if the assistant has had a genuinely bad run, the first gate now holds it: the blocker refreshed overnight is read at the top of the mutation path, and the correction is refused until the hold expires.

Note what did not have to happen for any of that. No model was retrained. No deployment occurred. The fast half of this loop — verdict in, ranking out — runs entirely on a file that a decision reads before acting. The slow half changes the model and needs a gate; the fast half changes the next answer and needs a floor. Confusing the two is how people end up overestimating systems like this.

There is a test in my build that does nothing but prove this step is real. It writes a confidence value, calls the tool, hand-edits the value, calls the same tool with the same arguments in the same process, and fails the build if the recommendation does not change. You can run the same check on whatever you already have, in about ten minutes, without a vendor in the room: open the file where your system keeps what it has learned, change one value, ask again. If the answer does not move, the thing is logging, not learning.

06 / The audit

Four things I had to fix before any of this was true

I am describing the system as it now behaves. It did not behave this way when I started auditing it, and the failures are worth publishing because they were all the same species: no crash, no alert, and an artefact that looked like evidence of work.

A ledger that had never written a row

The function that records every learning event returned skipped on every call, for the life of the fork. It was written to tolerate a missing upstream module — a reasonable choice — and that module is not present here, so the tolerance was permanent. The file was never created, so there was nothing to notice the absence of.

A gate that failed in both directions at once

The deliberation gate returned a hardcoded “proceed” to callers that only ever blocked on the word “hold”, so by design it was a rubber stamp. Meanwhile the calling code referenced a name that did not exist, crashed, and landed in the fail-closed branch, so in practice it refused everything. Both were true simultaneously. No memory correction ran, and the gate had never once made a decision.

A false inventory

The sensor registry listed 122 entries against three files on disk. 119 of them raised an import error, which was swallowed, logged at debug level, and bound to nothing. The registry advertised 122 sensors and could run one. Nothing was actually reporting coverage off that number — but it was sitting there ready to be counted, which is why the entries were deleted rather than stubbed, and why a scan now fires a high-severity finding on any entry without a file behind it.

A gate reading a folder nothing had ever written to

A policy gate read each memory card’s contradiction status from a folder of per-thread JSON files. That layout belongs to the upstream product; here, memory lives in a database, and nothing has ever written those files. The gate projected, scored, ranked and issued a receipt for a memory context that could not structurally contain a single card.

A fifth defect belongs to the upstream platform rather than to this substrate, and I include it because the guard against it was carried here and hardened. An independence check compares the grader’s identity against the student’s. Production had recorded the student as its base model family while the thing actually serving carried a different checkpoint name; the comparison found no match and declared the grader independent. The check is now deliberately broad and fails closed: a reference nobody can resolve counts as the student. A grader that cannot prove independence is treated as compromised.

None of these raised an error. Most of them produced a receipt.

07 / The build

What my own build refuses to let me do

Every one of those survived because a person would have had to go looking for it. So the checks that catch them are things the build refuses, not things a reviewer is asked to remember.

No file may be written that nothing reads. A check walks the code for paths written under the data root and fails if no other part of the tree opens them. It found twenty such files on its first run against my own tree. They are listed explicitly rather than suppressed, so every run reprints them.

No dependency on the upstream platform. Seven package names are forbidden, and a clean-room check imports the whole tree with the parent absent to prove none of them load. For a while this rule was upheld by a list of eight exemptions that let real violations through; the fix was to sever all eight and then delete the exemption mechanism itself, because a list you can append to is precisely how those eight became invisible. A test now fails if anything resembling a baseline or allowlist reappears.

No outcome of unknown origin. An unrecognised provenance label raises rather than defaulting to real work.

The pattern is the same in all three. The check does not ask whether something looks right. It asks whether the thing that was supposed to happen can be shown to have happened, and refuses when it cannot.

08 / The limit

What is not true of this yet

A paper about systems that overstate their own learning should be exact about its own state, so here is the boundary.

This substrate does not train anything today. The shipped training connector is a no-operation adapter: it records the request and hands back the model it was given. The optional local one runs no gradient step. The trainer is a seam with a defined contract, and it binds to a rig that lives outside this repository. Until that is connected, the training stage is gated on a pair count it will not reach, and the graduation gate does what it should in the absence of evidence — it refuses, and says why.

So the honest description is five of six steps. Ask, gate, change, record, and read back are wired to each other, each with a test that fails if the wiring is cut. Overnight training is real machinery around an unbound seam. I am not going to call that fifty rounds of compounding improvement, because it is not.

What I will claim is narrower and, I think, more useful to anyone evaluating this class of system: the fast loop closes, it is provable in ten minutes, and it was not closed six weeks ago in a system that looked entirely healthy.

09 / The shape

Why it is a separate thing, and where it sits

RL is about 167 source files and 68,000 lines, carved out of our larger platform at a pinned commit with no merge path back.

What was severed: the cognition gateway, the identity system, the workflow engine, the platform bus, the notifications engine, and an API monolith of some 64,000 lines. What was kept is the part that already produced the raw material of a learning loop. The carried subset is around forty core modules, chosen against an import closure that would otherwise have run past a million lines.

The price is real and I will state it rather than bury it: upstream fixes do not flow here. A security patch in the parent platform has to be noticed and reapplied deliberately. I accept that because a substrate that cannot be deployed without the platform it came from is not a substrate — and the whole value of this one is that agents which are not mine can use it.

It runs on very little. Every ledger is append-only text under one data root, coordinated with file locks. The core loop needs a POSIX filesystem and nothing else: no Postgres, no Redis, no workflow engine, no vector database. Those can be pointed at if you have them. For a system whose entire claim is auditability, a loop you can read with cat is not a limitation.

Alongside the rest of the series: Metis is the vertical model, narrow and private to the firm. Scouts are the operators that return something checkable rather than something plausible. RL is the connective tissue over time — the part that turns what the Scouts learned this week into what Metis knows next month, under a gate that refuses the rounds that did not earn it. Without it the other two are static, and a vertical model that never learns from the work it does is a snapshot of the firm as it was the day its corpus was assembled.

10 / Conclusion

Why this compounds, and renting does not

A frontier model’s improvements arrive for everybody at once. That is valuable and it is not an advantage: your competitor gets the same upgrade on the same morning, and neither of you earned it.

What does not arrive for everybody is a record of qualified people marking work in your domain over time. The algorithm is public and the hardware is rentable; that record is neither, because acquiring it would mean having done your business for as long as you have.

Which is why the release cycle is the wrong clock. Not because the releases do not matter, but because they are the part everybody gets on the same day. The part that is only yours improves on a schedule you set, or it does not improve at all.

And it begins with something as small as telling an assistant that a lead time is six weeks, not three — and having built the thing that makes the correction count.

Where to start

Ten minutes, on the system you already have

Open the file where your system keeps what it has learned. Change one value by hand. Ask it the same question again. If the answer does not move, you now know something about your own stack that most teams running agents have never checked on theirs.

What an engagement settles is the part that cannot be done from outside: which repeated judgments are worth learning from, who in your organisation is qualified to mark them, what “better” means on the work your teams do every day, and how much of that judgment left the building unrecorded last week.

An agent repeats what it was taught.
A system that learns repeats what worked.

Ownership and licensing. Foundation-AI and Foundation-LifeStyle, together with all intellectual property rights subsisting in them, are the sole and exclusive property of MediaGlyphics GK. Ibex is an authorized licensor of these technologies for forward deployed engineering (FDE) engagements. © 2026 MediaGlyphics GK. All rights reserved.