Skip to content

Propagation

Rendered from knowledge/exobrain/propagation.md — the text an agent reads.

How exobrains share improvements without a fork-and-merge relationship.

Four words, kept distinct: propagation is the whole exchange between seed and instances; adoption (verb adopt) is the seed→instance direction — an instance taking in the seed’s changes, run via the exobrain-evolve skill; publishing is the reverse, instance-initiated — contributing a pattern back as a feed card; since cards live only on the seed, an instance publishes by adding one in the seed repo, not in its own tree; harvesting is that same reverse direction seed-initiated — the seed reading its instances and pulling their universal improvements up into the framework, run via the seed-local seed-harvest skill. The wiring-refresh op (connect-agent.sh --relink) is a separate concern and is deliberately not called “update”, so the two never collide.

The template era assumed a human running git merge upstream against a fork. That breaks the moment two exobrains diverge — with/without groups, restructured scripts, locally rewritten skills. The agentic era assumes something the template era couldn’t: a competent adapter sits at every node. So an exobrain has no upstream remote and never merges. Instead, an agent reads the seed’s feed, copies the files an instance hasn’t diverged, and re-synthesizes the rest into local names and structure.

The canonical exobrain (github.com/bo2/exobrain) is a read target + a generator, not a fork parent. It is itself an exobrain — its knowledge/exobrain/ meta-domain is the concept. Downstream exobrains:

  • Are independent. Each owns its own tree. No upstream remote, no merge, no conflicts — exobrain-evolve caches the seed in a gitignored src/exobrain-seed/ (pull if present, else clone) and reads it from there. A local cache, not a tracked remote: nothing to merge, nothing that pulls framework code in automatically.
  • May diverge freely. Different names, layout, scripts. Where an instance diverged, changes re-synthesize; where it didn’t, they copy cleanly.
  • Take improvements, adapting as needed. Framework files an instance never touched can be copied directly; anything it changed locally is reconciled from the pattern.

This is a deliberate hybrid: copy is exact and cheap for the framework code (which arrived as a copy in the first place); re-synthesis crosses structural divergence that a line-level merge can’t.

Every change worth propagating is published by the seed as a dated pattern-card under seed/feed/ — a problem, a pattern, optionally the files it touches, and adapt notes. The feed is the changelog an instance reads to adopt, from the seed cache — it keeps no copy of its own. Format: the seed’s seed/feed/README.md. Each card carries a stable ID so provenance survives even across divergence.

The exobrain-evolve skill is the single way an instance moves forward — there is no git pull of framework code:

  1. Fetch the seed into src/exobrain-seed/ (pull if the cache exists, else clone) from the seed URL recorded in the adoption-ledger header — not a tracked remote.
  2. Diff the feed’s card IDs against this instance’s adoption ledger; the unadopted cards are the changes since last adoption.
  3. Triage — the agent sorts the new cards by category (mandatory, recommended, optional, probably not needed) and the human decides once per category: apply, confirm card by card, or skip (exobrain-evolve step 3).
  4. Apply each card — copy the seed’s files where this instance is undiverged; re-synthesize where it diverged or where structure differs. Preserve invariants exactly.
  5. Validate and re-link.
  6. Record every decided card in the ledger — adopted or declined.

Instances are where the framework meets real use, so they’re where its gaps get solved first. Harvesting is how a solution stops being one instance’s local fix and becomes everyone’s — the seed reads its instances, keeps what is universal, and publishes it as a card the others adopt normally.

It runs on the seed only (an instance has no downstream) and is read-only toward the instances: nothing is committed or pushed into a downstream checkout. Two filters do the work. Universality — a candidate must help an exobrain sharing none of that instance’s content, so instance domains, workspaces, person scopes, tool docs, and one-machine workarounds never qualify. Genericization — instances are private and the seed is public, so a harvested change is re-synthesized in the seed’s own names and voice rather than pasted, stripped of the source’s identity per Provenance hygiene below. A change that can’t be described without naming its origin was never harvestable.

Presented candidates are recorded either way in a harvest ledger, kept in the seed’s gitignored local scope; the declines are what keeps a later run from re-proposing settled divergence.

Invariants — adapt around, never reinterpret

Section titled “Invariants — adapt around, never reinterpret”

A few things tolerate no drift. These are invariants: preserved semantically exactly, even while names and structure change around them.

  • Security — the credential-handling rules in AGENTS.md § Security. Never weakened by an adaptation.
  • Scope-resolution semantics — the chain resolves shallow→deep with the deepest scope winning. Names and shape may change; the resolution contract may not.
  • The validation contract — what validate-exobrain.sh guarantees about naming, JSON integrity, and registry consistency. An adaptation may extend it; it must not silently drop a check.

A card that touches an invariant flags it (touches_invariant: true). If applying it would alter an invariant’s meaning, stop and surface it to the human rather than reinterpreting.

Provenance hygiene — keep shared scopes generic

Section titled “Provenance hygiene — keep shared scopes generic”

The seed and its feed are public; downstream instances are mostly private. When a change is backported up into the seed, the feed, or any shared scope, re-synthesize it free of the source instance’s identity — strip org or company names, internal hostnames, ticket prefixes, usernames, and private repo or tool names. A card describes the pattern, never where it came from. This is a hard publishing rule: a card or shared-scope file that names a downstream’s specifics has leaked private provenance, and must be genericized before it lands.

When an agent builds a fresh exobrain by reading this concept (create-instance):

  1. Read this meta-domain. It describes principles, not a rigid layout.
  2. Choose the structure that fits the principal — whether groups exist, which scopes are populated. Divergence is expected.
  3. Preserve the invariants above. Carry the framework scripts, adapting them to your structure.
  4. Seed the minimum: AGENTS.md, a knowledge/exobrain/ meta-domain, one person scope, an empty workspaces/, and the exobrain-evolve skill.
  5. Seed the adoption ledger (adopted-feed.md at the instance root) with the cards the seed currently publishes — you built from them — so exobrain-evolve carries you forward from there.

The proof of the model is that the exobrain you’re reading this in was built exactly this way.