Part III Scale It From Loop to System

Chapter 8 – Keep the Map Fresh (Map-Updaters)

Drift is the default state. Docs fall behind code. Specs lag behind services. Inventories and indexes rot. Policies miss new surfaces.

In SDaC, you do not fight drift with reminders. You fight it with a loop that turns “this Map surface is wrong” into a bounded, reviewable patch.

Enter the Map-Updater. A Map-Updater is a specialized loop designed to keep a specific Map surface synchronized with its corresponding Terrain. It does this by observing reality, comparing it to expectations, and proposing concrete, reviewable patches to reconcile any differences.

The Map-Updater Loop: Sense → Normalize → Compare → Propose

A Map-Updater follows a consistent four-step process:

  1. Sense: Observe the current state of the Terrain. This means reading directly from the source of truth—a running service, a code repository, a cloud configuration, a schema file. The output is raw reality.

  2. Normalize: Transform the sensed data into a structured, canonical form that is easy to compare. This might involve parsing, sorting, standardizing field names, or omitting irrelevant transient data.

  3. Compare: Fetch the current state of the Map and normalize it. Then, deterministically compare the normalized Map with the normalized Terrain. The output is a clear difference.

  4. Propose: Generate a patch—concrete changes that bring Map and Terrain back into alignment (in the direction your authority model permits). The patch must be reviewable.

Meta-Pattern: Skeleton-First Rule (Maps get skeletons from Sensors)

Map-Updaters are where teams get hurt by fabricated structure.

Rule: build the Map on a deterministically extracted skeleton, then (optionally) let the model add “flesh” such as explanations or formatting. The model must never invent the skeleton.

Concrete examples of skeletons you can (and should) extract deterministically:

Failure mode: if the model generates the skeleton, it can invent routes, symbols, or fields. Those invented facts enter the Map, get treated as “context” in later runs, and the updater starts converging on a self-consistent story instead of reality. This is Map Contamination in SDaC: generation contaminates what later steps treat as extracted fact.

Mechanism: treat skeleton mismatch as a hard failure.

A self-referential Map-Updater: keep agent instructions aligned

This repository has a second class of Map surface: directory-level agent instructions. They are the local laws of motion—how to work in a directory safely, what commands to run, and what boundaries to respect.

After a file changes, we run a Map-Updater that proposes minimal updates to the instruction file in the same directory. The tool is tools/update_agents.py.

It implements the loop in a pragmatic form:

  1. Sense: read the changed file and the existing instruction file (if any).
  2. Normalize: trim large inputs and resolve which project profile applies to that path.
  3. Propose: generate patch-style suggestions for the instruction file.
  4. Emit: write suggestions under build/update_agents/ for review.

Example invocations (from repo root):

python -m tools.update_agents --path core/scope.py
python -m tools.update_agents --path tools/dream.py

The important point is not the particular file name. The point is the direction: your terrain changed, so you update the Map that tells future operators how to move through that terrain.

Authority Models: Terrain-first vs. Map-first Surfaces

The direction of the patch is determined by the authority model:

Trying to make one surface both Terrain-first and Map-first produces an unstable equilibrium where automated systems fight over what “truth” is.

CI Gate: Drift Becomes a Build Failure

A Map-Updater becomes powerful when drift becomes non-ignorable:

  1. Run the Map-Updater in CI for every relevant change.
  2. If drift exists, fail the build (or block merge) with the proposed patch attached as evidence.
  3. Require the Map surface to be updated in the same pull request, or require an explicit waiver.

This turns drift from a quiet, compounding problem into an immediate, bounded, reviewable change.

Not every updater is a pure Physics gate. Some Map-Updaters are advisory (they generate suggested prose patches). That’s still valuable: the output becomes part of the Decision Trace, and humans can review and accept or reject the update.

North Star: Map-Updaters are a plank of the Hofstadter Bridge

At first, a Map-Updater feels like housekeeping: “keep docs fresh.”

The higher-leverage view is that you’re turning documentation from an output into an input: Map/Terrain sync today is the prerequisite for Maps that can become executable constraints tomorrow. Chapter 13 explores that limit case (the Hofstadter Bridge): the Map stops being advisory and starts acting as an enforcer.

If you want that future safely, you start here: deterministic skeletons, bounded diffs, and hard gates.

Actionable: What you can do this week

Choose one Map surface in your current project that drifts often.

  1. Identify Terrain and Map: pinpoint the source of truth and the Map file(s) that should track it.
  2. Choose an authority model: Terrain-first or Map-first. Write it down.
  3. Sketch the updater loop: Sense -> Normalize -> Compare -> Propose.
  4. Pick a skeleton you can extract deterministically: signatures, routes, schemas, inventories. Treat it as truth.
  5. Make the output reviewable: emit a unified diff or a patch file, not a paragraph of advice.
  6. Wire it into your loop: run it on every relevant change, and decide whether it should fail the build or simply attach evidence to review.