The parent article ends with a sentence I think about often: the AI amplifies your judgment, it does not replace it. You are still the pilot. The mech suit is not the thing doing the work; you are, just with more leverage. That framing only holds up if you can actually see what the amplifier is doing. A system that learns silently, that updates hidden thresholds based on prior runs, that routes differently this week than last week without telling you — that is not an amplifier. That is a substitute. And the moment the amplifier becomes a substitute, you are no longer the pilot, because you cannot see the state of the machine you are flying. This post is about the specific design decision in Precheck that refuses to let the learning system become a substitute. Four states, not two. Visible in prompts, not hidden in routing. Auditable lifecycle transitions, not a black box.
The binary toggle that would have been easier
When I was designing the learning subsystem, the obvious first draft was a binary toggle. Lessons exist in a guardrail_lessons table. Each lesson has an is_active boolean. When a lesson is active, it gets injected into the prompt. When it is inactive, it does not. Operators can flip the toggle if they want to manually enable or disable a lesson. Simple. Testable. Easy to implement.
I built most of that before I threw it away. The reason I threw it away is that a binary toggle cannot tell you about improvement. A lesson is either on or off. If the lesson was triggered by a pattern of failures, and the pattern has since improved, the toggle has no way to express "we fixed this." The lesson either stays on (and keeps warning the model about a problem that is no longer happening) or the lesson goes off (and the operator has no way to see that the fix worked). Both outcomes are bad in different ways. The "stays on" case produces stale warnings that degrade signal over time — users stop trusting the lessons because half of them are about problems that are resolved. The "goes off" case hides the success — the operator never gets to see the system recognize that its own corrective worked.
The insight I eventually arrived at is that learning in progress is itself a piece of signal that the operator needs to see. Not just "is the system learning" (yes/no), but "what is the system currently in the process of learning from" — which problems are new, which ones are confirmed, which ones are improving, which ones are resolved. Those are four different states of knowledge, and collapsing them into "active or not" throws away the information that matters most.
The four states
The decision record that captures this is ADR-009. It is the most substantively designed ADR in the repo — not because the implementation is complex, but because the shape of the lifecycle had to be stated precisely enough that the transition rules could be deterministic.
Four states. Six transition rules. Every threshold is an explicit number. Every transition is a deterministic function of measurable inputs. There is no probabilistic scoring, no hidden machine learning, no opaque decision boundary — if you know the recent fail rate of a lesson, you know what state it is in and what state it will move to next, and you can reproduce that decision on any machine with the same inputs.
Let me walk through what each state means in operator terms.
New means the system has detected a pattern — a guardrail that is failing often enough to suggest a systemic issue — but has not yet confirmed the pattern in the most recent window. The lesson exists in the API (so the operator can see that the system noticed something) but is not yet injected into prompts (because the system is not yet confident enough to act on the suspicion). New is the "we are watching this" state.
Active means the pattern has been confirmed in the recent window. The lesson is injected into prompts. The model is being told "look out for this" in every relevant assess call. Active is the "we are correcting for this" state.
Decaying is the new state that the binary toggle cannot express. Decaying means the system was correcting for a pattern, and the pattern is improving — the recent fail rate has dropped at least 30% from the threshold that caused the lesson to go active. The lesson is still being injected into prompts (because the improvement might be recent enough that it is not yet load-bearing without the reminder) but the operator can see that the lesson is in the "this is working, we are pulling back" state. Decaying is the "we think this is being fixed" state.
Inactive means the pattern has either been sustainably resolved (the recent fail rate is below half the original threshold) or it was never a real pattern in the first place (it looked like a pattern in the historical data but doesn't show up in the current window). The lesson stops being injected into prompts. It is retained in the database for history — you can still see that it once existed — but it is no longer shaping current behavior. Inactive is the "we fixed this, or it was never a problem" state.
Why the fourth state matters most
The decaying state is the one I want you to focus on, because it is the state that would not exist in a simpler design, and it is the state that changes the operator's relationship with the learning system.
Without decaying, the operator sees lessons flip from active to inactive. The operator does not see the improvement happening. They see "the system was warning about X" and then, one day, "the system is no longer warning about X." Did the problem get fixed? Did the system give up? Did something in the planner change so that the threshold logic stopped triggering? The operator cannot tell. They have to trust that the state change was earned.
With decaying, the operator sees the intermediate state. The lesson was active for a while. Then the fail rate started dropping. The lesson moved to decaying, which is visible in the API and in the Projection tab. The operator sees "the system recognized that this is getting better," and then, if the improvement holds, the lesson moves to inactive. The operator saw the arc. They saw the system be wrong, be corrected, recognize the correction, and retire its own warning. That is a completely different experience from "a toggle flipped."
The decaying state exists because the operator needs to see the system succeed, not just see the system change. A learning system that hides its own successes is indistinguishable from a learning system that isn't learning. Making success visible is not decorative — it is the thing that keeps the operator in the loop.
Why the visibility has to go through the prompt
There is a second, subtler design choice that the lifecycle depends on. Lessons have to influence the planner by being visible in the archived prompt, not by secretly modifying decision thresholds or routing logic. If learning were implemented as "hidden adjustments to planner thresholds based on prior runs," the operator could not see what the system had learned — they could only see that the system behaved differently this week than last week, with no artifact to point at. ADR-005 captures this commitment explicitly.
Read the consequences list carefully. "Every learning influence is auditable in the archived provider request." If an operator wants to know what the learning system told the model about a specific run, they open the archive for that run, find the prompt text, and look for the <learning_from_prior_runs> block. The block is right there, in the prompt, verbatim. No reconstruction. No log spelunking. The learning that influenced the run is a fragment of the run's own archive.
This is the six-questions rule from post six, applied to learning specifically. The archive has to be able to answer "which lessons were in play when this decision was made" without recomputation. The only way to guarantee that is to make the lessons part of the prompt, which makes them part of the archive, which makes them part of the replayable state. Any other approach — thresholds, routing adjustments, hidden policy changes — breaks the determinism requirement from post six, which breaks the "repo tells you about itself" property from post one, which breaks the entire claim the series is built on.
Everything in this series is the same decision, repeated at different scales.
What within-run learning is allowed to do
There is one more ADR I want to quote, because it addresses a tempting shortcut that I had to explicitly reject. Within-run adaptation — tracking dead-ends the planner has hit inside the current run so it doesn't keep cycling on them — is allowed. Cross-run persistence of those dead-ends is not. Each run is independently replayable. If a blocker was unresolvable in yesterday's run, the planner will not remember that in today's run. It will discover the blocker fresh and respond to it through visible mechanisms.
Within-run memory is ephemeral and visible-in-prompt. Cross-run memory is persistent, structured, and lifecycle-managed. Those are two different problems and they get two different solutions. The shortcut I was tempted by was "let the planner remember unresolvable blockers across runs to save LLM calls." Rejected, because a blocker that is unresolvable in one run context might be fixable in a different one — the blocker's resolvability depends on the work request and the guardrail set, not on some innate property of the blocker. Persisting "this blocker is unresolvable" across runs would create hidden cross-run coupling that the operator cannot see, which is exactly the property I am trying to prevent.
Every form of memory in a learning system has to be classified: ephemeral or persistent, hidden or visible, per-run or cross-run. Once you have the classification, most design decisions become obvious — persistent memory has to be lifecycle-managed, hidden memory is rejected, per-run memory has to be visible in that run's archive. The hard part is not making the decisions. It is committing to the classification strictly enough to produce it.
What the numbers say
I want to ground this in actual data before closing. The numbers from the learning subsystem retrospective, which shipped this whole subsystem end-to-end:
Eighty-four runs. Six thousand outcomes. One active lesson. The ratio is the thing. A system that generated twenty active lessons from eighty-four runs would be a system producing noise — the threshold for "this is a real pattern" would be too low. A system that generated zero active lessons would be a system whose learning pipeline is not actually learning anything. One active lesson from eighty-four runs, with a specific name and a specific fail rate, is the right ratio — it means the system is being selective about what it promotes to active, which is what an operator wants. The operator sees one lesson and knows: the system found one real pattern, here it is, here is why it thinks it is real, and I can see exactly what it is telling the model about it.
The one active lesson, by the way, is "Error Paths Are Explicit," and it fires on features that were bounced by a structural guardrail requiring error-path documentation. It has a 57% historical fail rate, which is well above the 50% threshold for activation. When it moves to decaying — which I expect to happen over the next few weeks as the model learns to anticipate the pattern — I will be able to watch the transition. That will be the first time I have seen the full lifecycle happen in production data. I am honestly looking forward to it.
The closing line
The parent article's closing point is that the AI amplifies your judgment, it does not replace it. You are still the pilot. Everything in this series has been a specific receipt for one aspect of that principle, and this post is the sharpest one. A learning system that shows you what it has learned — new, active, decaying, inactive — lets you stay in the loop. A learning system that hides its state behind a toggle or a routing change pushes you out. The four states are not a nice-to-have. They are the mechanism that keeps the operator in the pilot seat when the system starts learning.
Everything else in Precheck is a consequence of the same commitment. The ADRs exist because decisions have to be visible to the next session. The retrospectives exist because the work has to be auditable while the context is hot. The determinism requirement exists because the archive has to answer questions without recomputation. The runbook exists because the operator has to stay in the loop when switching between projects. The learning lifecycle exists because the operator has to stay in the loop when the system starts correcting its own behavior. Every layer serves the same purpose: keep the human in the seat, with enough visibility to actually fly the thing.
If you take one thing from this series, take that. The receipts — the ADRs, the plans, the retrospectives, the runbook, the lifecycle states — are not documentation overhead. They are the mechanism by which the amplifier stays an amplifier instead of becoming a substitute. You will build better systems by designing the artifact trail first and letting the features fall out downstream. I say this not as theory but as someone who built the wrong way first and had to rebuild from the artifact layer up. The rebuild is in the repo. Every file I quoted in these eight posts is part of it.
That is the whole series. Thanks for reading.
Derek Ciula, Steppe Integrations