The goal loop, charted
How a goal map gets acted on, measured, and redrawn — one pass at a time, then as a tree of versions, then zoomed out.
The equations
Each pass is numbered i. Everything with a subscript i belongs to that pass; i+1 is the next one.
The chart
Tap any symbol to jump to its definition. Circles are functions that transform things, tags are data passed between them, and filled blocks are stores that persist between passes.
The grey dashed path is single-loop learning. The red path back to the top is double-loop learning.
The dictionary
- i
- Pass index Which trip around the loop this is. Gi is the map during pass i; Gi+1 is the map after it's been redrawn.Attempt four is one pass; attempt five is the next.
- Gi
- Goal graphstore
Your map of what matters and how you'd know: fundamental goals, objective goals, strategies connecting them, supports and hurts links, and known obstacles. It changes only when U redraws it."The fly runs a farm" connected by a strategy to "24 wheat in the chest." - π
- Policyfunction
The rule that picks the next command. It reads the goal graph (what's worth doing, what's prioritized) and the world model (what's true right now), and outputs a command plus what that command should achieve. It's the conventional symbol in control theory and reinforcement learning, and has nothing to do with 3.14. Your prioritization step lives here."Nothing is ripe and my pockets are empty, so: wait." - ci
- Commanddata
An action described as data, like a Dizzy command. It says what to do, not how.StoreWheat(chest). - ŷi
- Expectationdata
What the command predicts the queries will return afterward. The hat means "estimated." This is the piece that turns every command into a round-trip test: it states the answer before the world gives one."After this, chest wheat goes up." - D
- Procedurefunction
The thing that actually does the work when handed a command, and reports what happened as events. Side effects it doesn't report are invisible to everything downstream.The walking-and-clicking script, plus the game itself. - Ei
- Eventsdata
Facts about what happened during the pass. Rejections are events too, and usually the most informative ones.CommandRejected(StoreWheat, "no wheat in inventory"). - J
- Projectionfunction
Folds events into the world model. Its schema decides which facts exist at all. If J never records a fact, no query can ever ask about it.Adds one to the rejection count; keeps inventory wheat at 0. - Mi+1
- World modelstore
The current state of the world as far as you've recorded it. It's i+1 because it already includes this pass's events.Plots: 24. Ripe: 0. Inventory wheat: 0. Rejections: 12. - Q
- Querierfunction
Answers a question against the world model.Reads the chest's contents out of the model. - q
- Querydata
The question, as an input/output pair. Each objective goal owns one or more of these; that's what makes it measurable.(chest_wheat, ?) — the ? is filled in by Q. - yi
- Observationdata
What the queries actually returned this pass. The same letter as ŷ, minus the hat, because it's the real value of the thing you estimated.chest_wheat = 0. - ⊖
- Comparefunction
Lines up what you observed against what you expected. For numbers it's subtraction; for other types it's whatever "how far off" means for them. - ri
- Residualdata
The gap left over after the comparison — the error signal. Zero means the world did what you predicted.Expected more wheat, got none, plus a rejection. - U
- Updatefunction
Redraws the goal graph from the residuals. It works at two levels. Continuous: nudge confidence in strategies and evidence status on goals. Structural: add an obstacle, add an objective goal, split or drop a strategy — or change J and Q so a missing fact becomes visible. Structural edits fire when a residual is both persistent and concentrated in one kind of situation.Twelve identical rejections, all when the field is young: add an obstacle and a new goal. - k
- Map version The slow clock. Many passes i run under one map Gk; the version number only goes up at a checkpoint.Each full farm attempt ran under one version of the map.
- Rk
- Issue listdata
All the residuals collected since the last checkpoint, reviewed together. Wintergatan's test-fit list is exactly this."Walked to store wheat with empty pockets, twelve times, field all young." - T
- Search treestore
Every version of the map, linked to the version it grew from. The spine is the path that worked; branches are dead ends.Five attempts at the full farm: four branches, one spine. - σ
- Selectionfunction
The second policy. Where π picks the next command inside one map, σ picks which map in the tree to work from next — keep going, or back up and branch.Reload the saved brain from the end of lesson four and start again. - Bk
- Branch predictiondata
ŷ for a whole branch: which objective goals should move, how far, within what budget. It lets a branch fail its own forecast, which turns "give up?" into a measurement."Within three attempts, the full run should finish."
Symbols inside the goal graph
These are the glyphs that live inside Gi. The strategy parallelogram follows GSN; the red obstacle follows KAOS.
A story: the empty chest
This follows the fly's fourth and fifth attempts at the full farm run, from the video. Everything the fly had learned was in place; it failed at the very end.
The map before anything happens
G0 holds one fundamental goal, a strategy, and the objective goals it relies on.
F: the fly runs a farm on its ownS: if each stage's objective passes in order, the farm runsO1…4: logs ≥ 4, seeds ≥ 24, plots = 24, chest wheat ≥ 24Choose
Twenty-four plots are planted. π reads Gi — the next unmet objective is "chest wheat ≥ 24" — and Mi. It outputs a command and an expectation.
ci = StoreWheat(chest)ŷi: chest_wheat increasesAct, record, fold
D tries it. The game refuses.
Ei = [ CommandRejected(StoreWheat, "no wheat in inventory") ]Mi+1: plots 24, ripe 0, inventory wheat 0, rejections 1Ask and compare
q = (chest_wheat, ?) → yi = 0ri: expected an increase, got 0 and a rejectionNothing in the world changed, so the next pass sees the same M, π picks the same command, and the same residual comes back. Twelve times. That's the single loop spinning without learning anything.
Redraw the map
The residual is persistent (twelve in a row) and concentrated (every one happened when the field was all young wheat). That's the signal for a structural edit rather than a confidence nudge. U produces:
X: no rule for idling when nothing is ripeO5: maintain — wait while ripe = 0O6: avoid — store attempts with empty pocketsS weakened: stage objectives in order don't cover the gaps between stagesIn the video, the concrete fix was practice material for exactly these situations. In map terms, that's a new strategy aimed at the obstacle.
The next pass
π reads Gi+1, which now contains O5.
ci+1 = Waitŷi+1: nothing changes until something ripensyi+1 matches, so ri+1 ≈ 0With a near-zero residual, U only makes a small continuous update: a bit more confidence in the revised strategy. Twenty seconds later the first plot ripens, and the loop carries on to 24 wheat in the chest.
A second, shorter story: when indicators disagree
Fundamental goal: fluent in Chinese. Two objective goals feed it through two strategies: daily flashcards at 95% or better, and holding a ten-minute conversation.
After a month, y says flashcards pass and the conversation fails. You can never query fluency directly, but you can see the two indicators contradict each other. U lowers confidence in the flashcard strategy, since it's the one that claims fluency while the more direct measure disagrees. No structural edit is needed; this is the continuous half of U doing its job.
Two clocks
The chart above shows U running every pass. In practice it shouldn't. The inner loop — command, events, query — runs many times under one fixed map. Residuals pile up. Then, at a deliberate checkpoint, you review them all at once and redraw the map once.
This is Wintergatan's method: build, test fit, write down every issue, then redesign. Batching keeps the map from thrashing in response to every noisy result, and writing the list is where obstacles get their names.
The tree of maps
Each checkpoint produces a new version of the map, linked to the one it came from. Keep all of them and you get a tree, T. U adds a child; σ decides which leaf to work from next. Here are the fly's five full-farm attempts drawn that way.
Dashed red: each named obstacle is what U uses to grow the next version. This tree is narrow — every dead end is one attempt long. Real research trees are wide, with long dead ends.
Why the video reads so well
It shows the spine, and every dead end hangs off it as one short, named failure. Most research write-ups keep only the spine and delete the branches. A write-up in the video's style keeps them: what was tried, what the residual looked like, what obstacle it named, and why it was abandoned.
Search, step by step
Working the tree follows the same four steps as Monte Carlo tree search:
- Select a map to work from (σ).
- Expand it into a new version (U).
- Roll out: run commands and queries under it.
- Backpropagate: carry what the rollout found back up the tree.
Step four is the one most processes skip. When a dead-end branch names an obstacle, that obstacle should move up to the shared ancestor so every sibling branch inherits it. That's what turns a dead end into knowledge. The empty chest in attempt four came back because the lesson from lesson eight never travelled that far.
A rule for persistence
Humans give up when a branch feels hopeless — a real signal, but noisy. AI mostly lacks it, which helps on the problems that need stubbornness and hurts on the ones that don't. The rule below replaces the feeling with a measurement.
When a branch opens, it states Bk: which objective goals should move, by how much, within what budget.
At each checkpoint, compare what happened to Bk. If it's on track, continue. If it missed, there are exactly two legal moves:
Backtrack, or continue with a new prediction that risks more than the last one.
A branch can never continue by explaining its miss — only by predicting something new. Determination is allowed as long as it keeps producing testable claims.
Signals worth tracking at each checkpoint:
- Residual trend. Is the issue list getting shorter, or just changing shape?
- Repeat obstacles. The same obstacle under a new name means the branch is spinning.
- Progressive ratio. Of the edits on this branch, how many predicted a later success that happened, versus how many only explained the last failure?
- Cost per unit of progress, compared against what other branches bought for the same spend.
Log every Bk with its outcome, and you get calibration data: how often "a few more passes" actually paid off, for a person, an agent, or a kind of problem. Agent time estimates are branch predictions too; scored this way, they'd stop being guesses nobody checks.
Zooming out
The same structure shows up at every scale. There are four directions to move in.
Up: recursion
Zoom out far enough and a whole research tree looks like a single procedure D one level up: a command goes in ("investigate X") and events come out (papers, results, a working farm). That level has its own goal graph, policy, and U. This is Stafford Beer's recursion in the Viable System Model. It also explains fundamental goals: each level's hard core can't be revised by its own U, only by the level above. A paradigm shift is the level above redrawing what the level below treated as fixed.
Sideways: a forest
Different research efforts share obstacles, strategies, and even objective goals, so the forest is really a lattice with shared nodes. Science's shared record publishes spines and drops branches, so groups keep rediscovering the same dead ends. A shared catalog of named obstacles, with the situations that trigger them, would be backpropagation for a whole field.
Forward: evolution
Over longer time, trees compete. Strategies that keep producing progressive branches get copied into other trees; degenerating ones fade. This is where Lakatos's research programmes live. What persists is the set of fundamental goals that many trees keep reaching back to.
Down: every command hides a tree
The fly's walking-and-clicking script was built through its own small tree of attempts that never appeared on screen. Any D, opened up, is a loop with its own map. The only thing that changes between scales is which level gets to call its goals fundamental.
Where Argyris and Lakatos sit
Argyris. Single-loop learning is the grey path: the world changes, π picks again, the map stays fixed. Double-loop learning is the red path: U changes the map itself. An organization that never takes the red path keeps trying harder at the same plan.
Lakatos. Fundamental goals are the hard core that U never deletes. Strategies and objective goals are the protective belt that absorbs failures. His health check applies to U's edits: a progressive edit makes new predictions that come true on later passes; a degenerating one only explains away the last failure.
Open questions
- Does π belong inside the goal system, or is it a separate navigator that only reads the map?
- Should every command carry ŷ? Without it, there's no residual to feed U.
- Do rejected commands emit events in your system, or fail silently?
- If G is itself a projection over its own event stream, what are the event types for "the map changed"?
- Who sets the checkpoints, and what triggers one — a fixed cadence, a budget, or a residual threshold?
- How do you interview someone to build G0 in the first place? Goal extraction is its own problem.