A loop that improves loops: factory, instances, canary
Read20 min · Gate → Lock → Ratchet → Scale · Updated 2026-10-04
You end this lesson with: harness/upgrade-ledger.md + harness/canary-checklist.md — a dated propagation ledger and a canary-before-fan-out checklist for spreading template changes across instances.
Chapters
- What is actually going on01
- The rule and its condition02
- Worked case03
- Faded case04
- Open case05
- Where this breaks06
Lesson 07. A loop that improves loops: factory, instances, canary
A team builds one self-improving loop: a shared template that edits its own prompts, checks its own metric, and keeps the change only if the number moved. It works so well they copy it onto six more projects. Nobody plans who maintains the copies. Each project's loop starts self-editing its own instructions immediately, the way it's supposed to. Four months later someone asks a simple question: did the improvement the loop found in project three ever reach project one? Nobody knows, because nobody wrote down which copy was running which version of anything. The tool that was supposed to answer that question exists, sitting unused, because running it was never anyone's job. Decide now: when you let more than one copy of a loop improve itself, who decides what crosses from one copy to the next, and on what schedule?
This lesson gives you an upgrade ledger and a canary checklist: the two artifacts that turn "copy the loop onto another project" from an unmanaged fork into a propagation system you can audit. It serves the Scale stage of the loop-engineering loop (Gate → Lock → Ratchet → Scale) — the last stage, where a loop that already works on one project has to spread to more than one without the first project's habits contaminating the rest.
What is actually going on
Once you run the same self-improving loop on more than one project, you have three layers, not one, and they move at different speeds on purpose.
L0, the factory layer. This is the canonical template: the orchestrator prompt, the role files, the gate scripts, the scorer. One copy, edited rarely, usually by a human or a slow, separately-scheduled meta-loop. Everything in Lesson 01's locked-scorer design and Lesson 05's four-layer goal applies here, at the template level.
L1, the instance layer. Each project runs its own copy of that template against its own goals and its own evaluation set, and — this is the part people miss — each instance is allowed to self-edit its own copy. A project's loop reads its own run history and rewrites its own "how to work" instructions the way Lesson 03's ratchet already permits: propose a change, run it, keep it only if the project's own metric moved. That is correct and you should not stop it. The scorer stays frozen (Lesson 01); the working instructions do not.
L2, the propagation layer. This is the layer nobody builds by default, because a single-project loop never needs it. It is the thin, mostly-manual bridge that moves template improvements down from L0 into L1 copies, and surfaces instance discoveries up for a human to judge. Down-propagation is a versioned, pull-based diff: each instance pins the commit (or version marker) of the template it was last synced against, a dry-run computes a three-way diff (template at that pin, template at its current head, and the instance's live file), and every file gets classified unchanged / local-only / apply / conflict. Up-propagation is proposal-only by design: an instance's loop may write a note to its own log about something that worked, but it never writes into the shared template directly. A person, or a scheduled read-only pass, decides what becomes a template change.
Read the diagram for the direction of the arrows, not the number of boxes: template improvements flow down through a pinned, versioned pull; instance discoveries flow up only as proposals, never as direct writes. The L2 box is doing less work than it looks like — it is a diff and a read, not a merge.
The rule and its condition
Use a canonical, locked layer for anything that defines what counts as correct; let a per-instance layer diverge immediately, by design, for anything that encodes how one specific project explores. Trying to keep everything canonical turns six projects into one project wearing six hats, and no project's loop can actually adapt. Trying to let everything diverge means you have six unrelated loops that happen to share a filename.
| Canonical (L0) | Per-instance (L1) | |
|---|---|---|
| Examples | scorer, gate scripts, protected-path list, safety rules | orchestrator prompt wording, role habits, backlog, evaluation cases |
| Who edits it | human, or a slow separately-scheduled meta-loop | that instance's own loop, continuously |
| Edit speed | rare, deliberate | every cycle |
| Drifts across instances? | never — if it drifts, that is a bug | yes, immediately, and that is correct |
| What breaks if you get this backwards | an instance quietly loosens a safety rule and nobody else is protected by it anymore | every instance is forced to phrase its own habits identically to five unrelated projects, so none of them actually improve |
The three-way question that sorts any file into one column or the other:
A real audit of a self-improving dev crew's own template pack found this sorts itself almost entirely on contact: every gate script stayed canonical on day one of a sync, while the orchestrator prompt and nearly every role file were already flagged as locally diverged before a single cycle ran. That is not a failure of the design. It is the design working: the layer that defines correctness held still; the layer that defines approach moved immediately.
Worked case
You run a loop-engineering setup across three of your own side projects, all three self-improving against the pattern from Lessons 01-04: locked scorer, loop-worthiness gate already passed, a ratchet, tiered spend. You built the shared template on project one first, then copied it onto projects two and three. Six weeks in, you notice project one's loop found a genuinely good fix: a cheap pre-check that catches an entire class of dead-on-arrival proposals before they burn any budget at all. You want that fix in all three projects. You have three ways to get it there.
Option A: push the file to all three instances right now. Fastest. One copy, three pastes, done in five minutes.
Option B: let each instance pull it whenever its own loop happens to notice the template changed, with no schedule and no record. Zero coordination overhead. Nobody has to remember anything.
Option C: pin a version per instance, canary one, watch a full cycle, then fan out — logging every step. Slowest to start. Decide now: which one, and why?
Take C, and here is the reasoning, step by step. Option A fails the moment the "fix" is wrong in a way that only shows up on one project's shape of work: you just broke three projects in the five minutes it took to paste it, and you have no record of what the previous state even was, so rolling back means reconstructing it from memory. Option B fails more slowly and more expensively: nothing is technically broken, but nobody can answer "which version is project two running" without opening project two and reading it, and the gap between template and instance grows without anyone deciding that it should.
Illustrative composite. From a real audit of a self-improving dev crew, 2026-10-04: three instances pinned to the same sync point drifted to roughly 92 commits and close to two thousand lines of unapplied template improvement before anyone checked, simply because the propagation tool existed but its "apply" step had never once been run on any of them. A companion file the template had started shipping to every role reached two of six instances and zero of the other four — not because of a conflict, but because nobody ran the command.
Option C avoids both failure modes with machinery you already half-have. Pin a marker — call it upstream: — in each instance recording which template state it last synced against. Before touching anything, run a dry-run diff: template-at-that-pin vs. template-at-current-head vs. the instance's own live file, and classify every file unchanged / local-only / apply / conflict. Only files marked "apply" (changed upstream, untouched locally) move automatically; a "conflict" (changed in both places) needs a human to read it once. Pick exactly one instance as the canary — the fix only touches the pre-check gate, so project two, which uses that gate the same way project one does, is the canary. Apply only the "apply" files there, bump its upstream: pin to the new commit, and watch one full cycle against project two's own ratchet. If project two's metric holds or improves, fan the same diff out to project three, one instance at a time, same checklist, never more than one new instance per sitting. If project two's next cycle regresses instead, you roll back through the ledger: the row you just wrote names the prior pin, so git show <that pin>:<file> restores exactly what was there before, and projects one and three were never touched at all.
# Upgrade ledger — one row per propagated file, append-only
| date | instance | file | from_sha | to_sha | applied_by | conflicts | cycle_result |
|------------|----------|---------------------|----------|---------|------------|-----------|-------------------------|
| 2026-10-04 | proj-two | precheck-gate.md | a1b2c3d | f9e8d7c | canary run | 0 | kept (ratchet: +1 pass) |
## Canary checklist
- [ ] Dry-run the three-way diff (upstream pin / template HEAD / instance live file); make no edits yet
- [ ] Classify every file: unchanged / local-only / apply / conflict
- [ ] Read every "conflict" file by hand once; apply "apply" files automatically
- [ ] Pick exactly ONE instance as canary; prefer the one closest to the change's own shape of work
- [ ] Apply, bump that instance's `upstream:` pin, write the ledger row
- [ ] Watch one full cycle against that instance's own ratchet/eval set — not a vibe check
- [ ] Regressed → roll back via the ledger's prior pin. Stop. Do not touch the remaining instances.
- [ ] Held or improved → fan out the same diff to one more instance, repeat this checklist
Faded case
Skip to the open case if this is familiar. A different setup: two instances of the same recurring triage loop, both six weeks behind the shared template, both missing the same two files according to a fresh dry-run diff. One instance (call it the quiet one) has had zero conflicts flagged in three straight dry-runs — its own habits never touch the files the template keeps changing. The other (the busy one) has two files flagged "conflict" every time, because its own loop has heavily customized exactly the area the template just improved. You can only canary one this week. Which one, and why?
Open case
A company has ten teams, each running its own copy of a recurring code-review triage loop, all cloned from one shared template four months ago. No team has pulled a template update since. The factory side has made at least a dozen improvements in that time, including a fix for a bug that lets the loop double-count an already-resolved finding. Nobody has an upgrade ledger. Nobody knows which of the ten teams are still exposed to the double-count bug. You are handed this as-is. The quiz's first item grades what you do before you touch a single team's loop.
Where this breaks
Canary windows don't mean the same thing across wildly different instances. If one instance's cycle takes an hour and another's takes a week, "watch one full cycle" is not a comparable signal — the fast instance gives you a fast, cheap false sense of confidence while the slow one is still mid-cycle when you'd otherwise fan out. Name the cycle length per instance in the ledger, not just the result.
The "≥2 instances agree before harvesting upward" rule is a safety trade against speed, and a genuine emergency should not wait for it. If the shared template has a real security hole — not a quality nit, a hole — gating the fix behind a slow, proposal-only harvest cadence is the wrong call. This lesson's checklist needs a second, explicit fast path for canonical-layer safety patches that skips the "wait for agreement" bar entirely and says so in the ledger, rather than quietly reusing the normal path under pressure and hoping nobody notices the skipped step.
Island discipline is a property of the tool's permissions, not of a policy sentence. Saying "instances never write back to the factory" protects nothing if the propagation tool actually has write access in both directions, or if a human reads an instance's log uncritically and pastes its suggestion straight into the template without the harvest pass. The guarantee has to live in what the tool is physically capable of doing, not in what the documentation asks it to do.
Key Takeaways
- Split every file into canonical (defines correctness, edited rarely) or per-instance (defines approach, self-edits every cycle).
- Pin an upstream reference per instance so drift becomes a counted number, not a guess.
- Canary exactly one instance, watch a full cycle, before touching any other instance.
- Propagate like a release, not like a merge — ramp, watch, then fan out, never push blind.
- Harvest upward only when at least two independent instances show the same thing, and only as a proposal.
- Roll back through the ledger's own prior pin; a change you can't trace, you can't safely undo.
What You Have Now
You now have an upgrade ledger and a canary checklist: a dated, append-only table that records every file moved between your loop template and its copies (with the prior state always named), paired with an ordered checklist that forces a one-instance canary and a real cycle watch before anything fans out further. Save them as harness/upgrade-ledger.md and harness/canary-checklist.md; together they are the record that lets you answer "which version is instance three running, and what would I restore if it regressed" without opening instance three and reading it by hand. This is the Scale stage of the loop-engineering loop — the stage that only exists once "the loop" has stopped being one thing and become a family of things that need to stay honest with each other.
Further Reading
- Darwin Gödel Machine (arXiv:2505.22954) — keeps a growing archive of agent variants instead of overwriting a single current-best, the direct precedent for not letting one instance's local edit eliminate the others.
- AlphaEvolve (arXiv:2506.13131) — its evolutionary database runs island-based populations that evolve in parallel with only occasional, controlled migration between them, the cleanest existing model for canary-then-fan-out instead of one shared pool.
- GEPA (arXiv:2507.19457) — keeps a Pareto frontier across multiple validation subsets instead of collapsing to one global-best prompt, so a change that helps one slice can't be silently adopted everywhere; the same shape as requiring more than one instance to agree before a habit gets harvested upward.
- OPRO (arXiv:2309.03409) — shows a plain history of (attempt, score) pairs is enough for a model to propose a better prompt with no gradient, the mechanism behind an instance's loop safely rewriting its own working instructions without ever touching the scorer.
- MLflow: What Is Canary Deployment? (observed 2026-10-04) — the software-release pattern this lesson borrows directly: ramp exposure in small steps, watch a real signal, roll back automatically on regression.
Exercises
- Write your first ledger row. For a loop you run today — even a single instance counts as "instance count = 1" — write the upgrade ledger's header row and one real entry for the last change you made to it, filling in a real
from_sha/to_shaif you use version control, or a dated snapshot name if you don't. - Classify a real template. Pick two projects, or two configurations of the same project, that share any instructions or rules file. Diff them by hand or with a script and classify every shared file: unchanged, local-only, apply, or conflict. Write down which column surprised you.
- Run one real canary. Apply one safe, small change to exactly one instance, watch one full cycle against that instance's own verification, and write the result into your ledger before you let yourself touch a second instance.
Check your understanding
Reading is free — your progress isn't being saved
Nothing you did on this page is recorded. Paid students get saved progress and verified completions, recorded quiz answers, the spaced-repetition review queue, labs, and a certificate for each course they finish.
30-day money-back guarantee. One-time payment — lifetime access and updates.