How the Factory Learns From Its Mistakes

The most expensive failure in an autonomous system is not making a mistake. It is making the same mistake again while believing the system has learned.

That was the uncomfortable shape of the factory for a while. A correction could live in a conversation. A closed defect could have a root cause. A rule could sit in a file. None of those facts meant the next worker would see them at the moment they mattered.

So I rebuilt the learning path: correction or closure becomes a LESSON row; the relevant rows are selected for the new task; the bounded packet is placed at the top of the prompt; and the delivery is recorded. The mechanism is useful only if I can prove each link.

THE LOOPcaptureLESSON rowselectioninjectionchecktitle, body, role, stage, provenancebounded packet at prompt topsource event → persisted row → relevant rows → visible delivery → independent evidence
The important boundary is the row: a source file or a remembered sentence is not the record.
427lesson rows in the read-only factory snapshot
3,170recorded lesson injections
1,705lesson occurrences behind the learning history

The failure A lesson that never reached the worker is not a lesson

Before the rebuild, the system had several plausible memories: markdown, migrated material, issue history, and whatever an agent claimed it had seen. The dangerous part was not that these sources existed. It was treating a source as if it were an authoritative record, or treating a matching phrase as proof of delivery.

The current rule is stricter. The record is a row in factory_rules/factory.db. Files are sources or evidence. Injection reads rows through get_relevant_lessons(). A closed issue must choose exactly one prevention path: an existing lesson, a new lesson, or an explicitly scoped one-off.

That is why a closed defect now has somewhere to go. The closure path makes prevention part of the act of closing, while the prompt path makes retrieval part of the act of starting.

The row What a real lesson looks like

Here is a real CLI read from the evidence snapshot. It is not a summary generated for this article:

$ python3 factory_rules/lesson_cli.py --db factory-evidence.db show L-0003
{
  "id": "L-0003",
  "title": "Two operator pushbacks on one task means stuck: stop and re-plan",
  "body": "Do not retry the same fix a third time. Stop, state what is actually unknown, and change approach.",
  "who": "ORCHESTRATOR",
  "scope": "PROJECT",
  "level": "CHECK",
  "check_hook": "capture_pushback.py",
  "seen_count": 146,
  "occurrence_count": 145,
  "status": "ACTIVE"
}

The row has an owner, scope, level, stage link, and—because it is a CHECK—a named hook. The hook is not the lesson itself; it is the enforcement path associated with the lesson.

The prompt Retrieval is deliberately boring

At task start, the factory classifies the work into a role and stage. The catalog consumer asks for active rows with the matching scope, worker, and stage. It can use technical tags, prefers check lessons where appropriate, caps the result, and trims the rendered packet to a character budget. The result is deterministic and fail-open: a broken lesson query must not silently become a false claim that no lesson exists.

This is the real block emitted in a live session on 2026-09-09, reproduced verbatim:

§7.3 LESSONS · who=ORCHESTRATOR stage=AUDIT · 4 rows
L-0003 [CHECK->capture_pushback.py] Two operator pushbacks on one task means stuck: stop and re-plan [FALLBACK]
L-0007 [CHECK->guard_spawn_ledger.sh] Every spawn is recorded with its parent task_id [FALLBACK]
L-0263 [ADVISE] Multi-phase work uncommitted = 1-crash-away from total loss
L-0409 [ADVISE] A capability can be complete, correct and fully tested while no code path exists to switch it on

That block does not prove the agent obeyed the lessons. It proves a delivery event was rendered. The separate check is whether the relevant hook, gate, test, or reviewer catches the recurrence.

Hero probe: the local ComfyUI endpoint was unavailable on 2026-09-09, so the hero is the hand-authored SVG fallback shown in this post. The FLUX checkpoint was present, but a configured model is not a running engine.

The ledger Delivery has its own evidence

The database now separates lesson rows from the history around them: 511 stage links, 2,436 votes used in sorting, 1,705 occurrences, and 3,170 injection records. Those counts are not a success score. They are the machinery needed to ask narrower questions: which row was selected, for whom, at which stage, and whether the rendered row set was actually recorded.

MEASURED STORE SHAPElesson rowsstage linksoccurrencesvotesinjections4275111,7052,4363,170
Counts re-measured from the factory database on 2026-09-09; the bars are a shape comparison, not a performance claim.

The honesty checks Learning needs skepticism too

There are four ways this system could lie while looking healthy.

First, a file could look like a lesson without being in the store. The single-store guard and the documented source/evidence boundary keep the record in the database.

Second, a duplicate could inflate the catalogue. Exact duplicates are refused; suspected duplicates are recorded for review rather than silently discarded.

Third, a relevance match could be mistaken for delivery. The renderer records the exact rows that fit, and the injection table is the delivery evidence.

Fourth, a clean exit could be mistaken for an executed check. The factory’s INV-9 and INV-9A rules require checking the instrument and its artifact, not just the return code.

The system also promotes cautiously. Repeated active advice across distinct sessions can become a debt assessment; a vote is not a mandate, and a lesson that is not enforceable does not get promoted merely because it is popular.

Still open The loop is real, not finished

The rebuild closes important paths, but it does not prove that every future mistake will be prevented. Relevance is deterministic keyword and task-class matching today. A lesson can be active yet be too general for a particular task. A CHECK row can be delivered while its hook is unavailable or fail-open. And the injection ledger records delivery, not compliance.

Those are not reasons to market the system as solved. They are the next measurements: prove project-specific relevance where history exists, test the write path and the read path together, and keep open defects in the tracker until an independent verifier can reproduce the prevention.

A factory does not learn when it can recite its past. It learns when the past changes what the next worker is asked to check—and when the system can show that it happened.

Meharban Singh
AI systems / delivery architect. I build software with AI agents governed by rules, hooks, gates and independent review.