soul.demarkus.io:6309/plans/memory-knowledge-layering.md/v2 draft reader meta

Plan: Memory and knowledge layering

Audience: demarkus maintainers. Gives the code the shape of the two tiers, memory and knowledge, so the application layer can keep growing without breaking what people use today. Drafted 2026-10-16 with Fritz; proposed, no code. Positioning, the two doors and the transport freeze are settled in The engine, not the wire and are not repeated here.

Premise

Fritz calls the core the memory store: versioned markdown, the catalog, change hints. It is well defined. What sits above it is not. The code is layered by mechanism (protocol, server, client), not by product, so the application layer has no home of its own.

Concept Where it lives on 2026-10-16
Memory store protocol/, server/internal/{filestore,backend,catalog,changefeed,fanout,handler}
Memory model: journal, hubs, write gates, promote, curate, doctor inside client/ (journal, hub, docwrite, metaguard, promote, curate, audit, generation) next to the CLI, TUI and MCP code, plus prompts in plugins/prompt-source/
Knowledge tier split between server/knowledgeserver, server/internal/{knowledgeconfig,worldruntime,snirouter,writepolicy} and knowledge/internal/broker
SDK not started; more than 100 files import client/fetch

The memory model exists in code but has no name and no module. Its rules are also written again in prompts, the plugin binary and the gateway, which is why 1.0 definition item 9 (memory gateway parity) needs a test to hold them together.

Target layers

  1. Memory store. The durable core, kept dumb: protocol, store, catalog, WATCH hints, and the SDK.
  2. Memory model. One library over the store client: document kinds, hub rules, write gates, journal, promote and refresh, doctor with apply. No MCP, no CLI.
  3. Tiers. A soul is the model plus local provisioning. A knowledge system is the same model plus worlds, identity and policy. One model, not two applications.
  4. Surfaces. MCP tools, plugins, the gateway, CLI, TUI and the library stay thin.

Tiers and the durability layers in the vision are two axes: tiers say who owns knowledge, layers say how long it must last.

No protocol change. The wire stays the machine door from engine-not-wire, and agents keep the verb shaped tools. New needs go up into the model, never down into new verbs, and model behavior lands behind the existing tool names, the way mark_append with route: today already works.

Contracts that must not break

Contract Who depends on it Guard
Wire protocol CLI, TUI, MCP server, broker, demarkus-library, Caztor (FETCH only) storetest; wire fixtures planned in SDK phase 1
MCP tool names, parameters, output every agent session plugin eval; no golden test of the tool list found
Plugin commands and hooks plugin users plugin eval, pre-commit
Stored format (protocol/storefmt) every local soul, the GCS deploy format and fuzz tests
Config and token files deploy repo, installs knowledgeconfig tests; no pinned fixture
Go import paths demarkus-library (client/fetch, mdoutline, graphstore) its go.mod pin

mark-knowledge imports no demarkus Go code. The benchmark worktrees import internal packages and rebase after each move. The binary merge in engine-not-wire keeps its own plugin compatibility gate.

Where breakage can come from

  • Agent visible output, when a mechanic moves from a prompt into software: keep the tool name, run the eval before and after.
  • Writes to people's stores (doctor apply, generated hubs): dry run by default, a human gate, opt in.
  • New refusals (a secret check on soul writes): warn for one release, then refuse, with a release note.
  • Format or config changes: none planned; both stay frozen.

Gaps, ranked

  1. Maintenance before features. This soul has 745 doctor findings and apply is unbuilt (agent UX item 3). The root hub holds 47 links against a cap of 40; /journal/ (127) and /plans/ (147) have no generated hubs.
  2. The memory model as a named layer, with mechanics moved out of prompts into it.
  3. The same write gates in both tiers. The knowledge system refuses secrets at write; this soul holds three connection-string-password findings. Check whether the soul write path runs the same content check.
  4. Lifecycle as model rules: supersede, stale, archive. Overlaps Embracing staleness.
  5. The protocol freeze after WATCH and ALPN mark/1 (ADR 0025), so the wire stops costing attention.

Sequence

Each step is additive or behavior neutral.

  1. Contract inventory and the missing guards: a golden test of the MCP tool list, a config fixture.
  2. Doctor apply and generated hubs, built where the code lives now (client/audit).
  3. Carve out the memory model, one package per PR, pure moves; proof is identical pre-commit and eval results. docwrite splits: write rules toward the SDK, the gate into the model.
  4. Move prompt mechanics into the model behind existing tool names, one eval case per mechanic. This retires the Cowork plugin (below).
  5. Same gates in both tiers: warn, then refuse.
  6. SDK as narrowed in engine-not-wire. Independent of step 3: moved packages switch from client/fetch to the SDK in their new home, never both in one PR.
  7. Knowledge tier consolidation, decided together with the binary merge.

Rule for every PR: a pure move or a behavior change, never both. Every behavior change ships with an eval case or a guard.

Plugins

One memory plugin: once host reads are MCP tools, demarkus-cowork retires and every host runs the same commands; host writes stay shell, hooks stay optional.

What elegant means

Principle Test
One model, two tiers same names, gates and commands in soul and knowledge; promote and refresh are the only edge
Mechanics in software, judgment in the agent prompt source bytes go down; ADR 0042 holds
Memory maintains itself zero doctor findings in the classes apply owns; hubs stay under the cap without manual edits
Few nouns nothing beyond memory, soul, knowledge system, world
Thin surfaces one plugin per host format; the parity test of 1.0 item 9 passes
Measured eval pass rate holds; tokens per correct answer go down

Gate for each new feature: does it make memory more linked, findable, durable or current, and does it work the same in both tiers? If not, it is a product feature, not the model.

Open questions

  • Multi-world hosting: core or knowledge tier? Lean: worldruntime, changefeed, fanout and catalog are core; knowledgeserver, knowledgeconfig and snirouter are the knowledge tier; writepolicy is a core mechanism whose policy content belongs to the tier.
  • The memory model as its own Go module (memory/, lockstep versioned) or a directory inside client/?
  • After the binary merge the knowledge/ module also hosts the soul's local profile, so its name stops matching the tier.
  • Is "memory store" the public word engine-not-wire leaves open?
soul.demarkus.io:6309/adr/0042-soul-entries-are-agent-written.md draft reader meta

ADR 0042: Soul entries are agent-written; software supplies facts, never entries

Status: accepted (2026-10-14). Plan: deterministic session capture. Applies the responsibility boundary (agents decide meaning, software executes mechanics) to what lands in the soul. Part of the decisions hub.

Context

  • Capture depends on the agent choosing to write. The session-end nudge fires when a session changed files and wrote nothing, but carries no facts, so entries come out vague or not at all.
  • The first draft of the capture plan had the plugin binary write a journal stub on SessionEnd from the transcript and git state, with no agent involved, first as the default and then as an opt-in.
  • Automatic capture is a different product concept: record everything, then rank, decay and deduplicate the noise. demarkus is built the other way round. The agent is the librarian, writes are deliberate, the soul rules forbid trivia and anything derivable from the repo, and lookup quality rests on every document having been chosen.
  • An entry nobody chose to write is not curated. Even a factual stub competes with curated entries in lookup and dilutes the journal the session primer reads.

Decision

  • Nothing writes to the soul except an agent acting on its own judgment or a user's instruction. No hook, binary, server job or background pass creates or edits soul documents on its own, by default or as an option.
  • Software may compute facts deterministically and hand them to the agent: in a nudge, through a subcommand, in a tool result. The agent decides whether any of it is worth recording and words the entry.
  • Mechanics that act on a write the agent already chose stay allowed: the journal route, hub links, tag widening, the write gate, curate proposals applied after a human gate.
  • Reports stay reports. Doctor, staleness, conflict and near-duplicate checks surface findings; the agent or the user resolves them.

Consequences

  • A killed or abandoned session can leave no entry. Accepted: the floor is the agent's habit plus better facts, not an uncurated record.
  • The capture plan narrows to facts in the session-end nudge and a session-facts subcommand for /soul-journal.
  • Future proposals for auto-capture, decay, automatic consolidation or model rewrites of soul content are out of scope under this decision; reopening one needs a superseding ADR.
  • The knowledge system already holds the stricter form of this rule through promote and its human gate; the soul now states it explicitly too.

Alternatives considered

  • Automatic stub on session end, default on. Rejected: uncurated content in every soul, against the restraint rule and the librarian principle.
  • Automatic stub, opt-in. Rejected: an option that lowers lookup quality for those who enable it is still a second product concept to maintain, and it invites the next automatic writer.
  • Stubs in a separate unindexed area. Rejected: hidden content still costs storage and review, and a stub nobody reads has no value; facts handed to the agent at the right moment do the same job.
trail
  1. soul.demarkus.io:6309 v2
  2. 0042-soul-entries-are-agent-written