| name | membrane |
| description | Tend the membrane memory corpus — an OKF concept store whose fragment evolution lives in the git log as lineage trailers. Fire when creating, evolving, merging, splitting, or CORRECTING durable memory/knowledge that lives as OKF files under git; when recording how a belief changed or was repudiated; or when tracing a concept's history through time. YOU are the evolver — there is no evolution engine and no LLM sidecar. NOT for transient notes, scratch, or code comments. |
membrane — memory as a disciplined git log over OKF
The membrane is a memory corpus with one move: the agent updates the knowledge,
and in the same act records how it evolved — into the git log. There is no
fragment-evolution engine, no proprietary store, no required embedding model. The
intelligence (which concept is this? evolve or correct? what's the lineage?) is a
judgment you make as you write, not a technology. git is the temporal ledger;
OKF is the on-disk shape; you are the evolver.
The ambition — read this first, it decides everything
We are not encoding truth. We are encoding an iteratively improving
approximation of truth. A wrong belief was a legitimate prior state of the
approximation; the correction is itself fallible. Three consequences, load-bearing:
- Nothing is deleted. Ever.
- History is never rewritten. No rebase, no force-push, no amend of landed
commits. (The value-tickets, replay, and content-addressing all depend on
immutability — and the record of having been wrong is part of the honest
approximation.)
- Correction is always a forward commit that marks the past, never erases
it. The corpus improves by accumulating forward corrections.
The store
- One concept = one OKF markdown file, keyed by a stable opaque id, not by its
text:
concepts/frag-<id>.md. The id never changes as the belief evolves —
identity is the filename; the belief is the body.
- Frontmatter:
type, id, provenance, ts (+ optional tags, resource).
Body = the current belief, in prose.
- The working tree is the live corpus (current beliefs). git history is
everything that's been occluded or repudiated — reachable, never gone.
The five-verb lineage discipline
Every commit to the corpus carries a trailer block. The verb is the judgment.
<verb>(<id>): <one-line summary>
Action: create | evolve | merge | split | correct
Concept: frag-<id> # the resulting/affected concept
Occludes: <blob-sha> # evolve ONLY — the prior belief's blob (reachable)
Parents: frag-<id>[, frag-<id>...] # merge/split ONLY — the lineage DAG edge
Severs: frag-<id>@<blob-sha> # correct ONLY — the repudiated lineage point
Reason: <why the prior line was wrong> # correct ONLY
Provenance: <session / conversation / source of this update>
Signal: <type> [value=<n>] [<note>] # zero or more — the WMFX faucet (see below)
Signals: none # REQUIRED if there are no Signal: lines
Choosing the verb:
- create — a new belief that doesn't belong to any existing concept.
- evolve — an existing concept, superseded but was-valid: the world moved,
the belief refined.
Occludes: the prior blob. ("Walls were sage; I repainted
them white.")
- merge — two concepts are actually one. One commit deletes both source files,
writes the unified one;
Parents: lists both (both occluded by this commit).
- split — one concept is actually two distinct beliefs.
Parents: the original.
- correct — an existing concept was wrong — a smear, a mis-extraction, a bad
merge. Not superseded — repudiated.
Severs: the bad lineage point +
Reason:. Stays on the same file/id: a discontinuity within an identity,
not a new identity.
The one hard discernment is evolve vs. correct. Evolve = "this was true, now
it's different." Correct = "this was never right." Mislabel a correction as an
evolve and you bury an error as honest history; mislabel an evolve as a correction
and you slander a valid past. When genuinely unsure, it's evolve — reserve
correct for real defects.
Occlusion and severance are the two ways the past stops being current, and the
trailer is the only thing that distinguishes them. Both are forward; both keep the
full history.
Faucet signals — the carrier; the meaning lives in world-modeling
The membrane commit is also WMFX's universal envelope: source (= membrane),
ts (= commit time), and claim_id (= the commit SHA — the content-addressed
value ticket) all come from the commit, so a Signal: trailer derefs back to the
exact memory change that triggered it, for free. This skill owns the carrier
and its enforcement only.
What counts as a signal, and the bar, are NOT defined here — they are
world-modeling doctrine, in the arbiters-worldmodel skill (the
"discipline-declared signal" path). Read it for the meaning; what follows is
just how membrane carries and enforces it:
- Format:
Signal: <type> [value=<n>] [<note>] — one per attention-worthy signal;
source/ts/claim_id come from the commit.
- Every commit must declare: a
Signal: line, or an explicit Signals: none
(a conscious "I considered it; nothing here"). The hook rejects silence.
- Interlock: a
correct is intrinsically attention-worthy, so it may not
declare Signals: none — it must carry at least one Signal:. The hook enforces it.
Write-time loop (this replaces the evolution engine)
- Survey — what concept(s) does this update touch? Read/grep the store. (Later,
optionally, embedding-match to find candidates.)
- Decide the verb — create / evolve / merge / split / correct.
- Edit the file(s) — opaque-id filename, belief in the body.
- Commit with the trailer. The hook rejects a malformed one.
Spend the time this needs. You are the intelligence; there is nothing behind you.
Querying through time
- Current belief — read the working-tree file.
- A concept's whole trajectory —
git log --grep="Concept: frag-<id>" --format="%h %ad %s%n%b" --date=short.
- Belief at time T —
git show <commit>:concepts/frag-<id>.md (read-only;
never checkout — it mutates the tree and can clobber untracked sidecar state).
- Lineage / parents / occlusions — parse the
Parents: / Occludes: / Severs:
trailers from the log.
- Suspect descendants of a defect — from a
Severs:, trace Parents: edges
forward to find every concept that merged from the repudiated point. They are
not auto-corrected (that's a later judgment) — but they are now visible as
suspect. This is the discipline-side answer to smear.
The typed log is the visualization bridge
The commit log is not just storage — it is a strictly-typed IR, and the
visualization surface is a pluggable renderer over it (WMFX's "emit, not render"
doctrine: a first-class graph IR with pluggable emitters). The bridge contract is
the trailer grammar; the surface consumes it, never the reverse.
The principle: strict typing in the log funds visual richness. Every typed
field is an affordance the renderer can spend. Loose prose renders as a flat list;
a tight schema renders as a living graph. So tightening the trailers is not
bureaucracy — it is buying visual expressiveness, and that is the forward
flywheel: each new typed field unlocks a new visual dimension, which is the reason
to keep the discipline sharp. The walk feeds it for free — every membrane commit a
/arbiters session makes is one more typed event the surface renders, live.
Starter field → affordance map (the renderer's vocabulary):
| Trailer field | Visual affordance |
|---|
Action: create | a new node appears |
Action: evolve + Occludes: | node updates; prior state a faded ghost behind it |
Action: merge + Parents: | two nodes converge into one |
Action: split + Parents: | one node forks into two |
Action: correct + Severs: | a visible cut in the lineage — a scar, not a smooth step |
Signal: <type> | colour / glyph by type (surprise, smear, regime-change, correction) |
Signal: … value=<n> | intensity / size / glow by strength |
claim_id (commit SHA) | the node's stable handle; click-through to the exact change |
ts (commit time) | position on the time axis |
The surface can be as flamboyant as the schema is strict. Surface binding: the
renderer is 6digit-cordial — the Hollywood-OS development HUD (the Iron Man
transparency plane, literalized). Cordial renders two feeds from the same substrate:
membrane lineage/signal walks (this log) and WMFX world-model state (the wm
tool, which stores state). Everything above is surface-agnostic and holds for any
renderer; Cordial is the target.
The enforcement hook (the one piece of required tech)
A commit-msg hook validates the trailer so the discipline can't silently drift —
encode the discipline into something that fires on its own. It must:
- require an
Action: from the five verbs and a Concept:;
- require
Occludes: on evolve; Parents: on merge/split; Severs: AND
Reason: on correct;
- require a faucet-signal declaration on every membrane commit — a
Signal: line
or an explicit Signals: none; and forbid Signals: none on a correct;
- reject the commit (non-zero exit) on any violation, printing what's missing.
Reference logic (Node; install at <store>/.git/hooks/commit-msg):
const msg = require("fs").readFileSync(process.argv[2], "utf8");
const f = (k) => (msg.match(new RegExp("^" + k + ":\\s*(.+)$", "m")) || [])[1];
const action = f("Action");
const need = { create:[], evolve:["Occludes"], merge:["Parents"], split:["Parents"], correct:["Severs","Reason"] };
const fail = (m) => { console.error("membrane: rejected — " + m); process.exit(1); };
if (!action) process.exit(0);
if (!need[action]) fail(`unknown Action '${action}'`);
if (!f("Concept")) fail("missing Concept:");
for (const k of need[action]) if (!f(k)) fail(`Action ${action} requires ${k}:`);
const none = /^Signals:\s*none\b/im.test(msg), nSig = (msg.match(/^Signal:\s*\S+/gim) || []).length;
if (!none && !nSig) fail("declare a 'Signal:' line or 'Signals: none'");
if (action === "correct" && !nSig) fail("correct is intrinsically a signal — not 'none'");
Embeddings — deferred, back-fillable (do NOT build until needed)
git + OKF is the complete source of truth. A JINA index over (concept, commit)
is a derived cache you can rebuild from history in one pass at any time — so
nothing is lost by shipping without it. It buys exactly one thing: cold semantic
retrieval (a query whose words don't match the stored text). Measured on
LongMemEval s-10q, plain keyword search already hits ~90% recall, so embeddings are
a ~10% tail optimization, not a load-bearing part. Reach for them only when that
tail becomes the bottleneck — and back-fill the whole index then.
Optional tooling (benefits split by who it serves)
- Traversal helper (
membrane trace/at/suspect) — encodes the query commands
above once. A convenience for the agent (consistency, fewer tokens). Not required.
- Lineage visualizer — reads
git log, renders evolutions as continuous lines
and correct/Severs as explicit cuts. This is the human's transparency plane:
how the corpus's history and health are seen without poking. High value for the
human, marginal for the agent — build it for that purpose.
Never
- Rewrite history (rebase/amend/force) — corrections are forward commits.
- Delete a concept to "remove" a wrong belief —
correct + Severs it forward.
- Skip the trailer, or hand-wave the verb — the hook will reject it, and a silent
evolve-vs-correct mislabel corrupts the time-travel.
- Reach for an LLM or embedding "evolver" — you are the evolver; that's the point.