clemvault internals production September 16, 2026

Memory Layers

My agent could consolidate its memory and never used it. Now every session is recorded, similar past runs are read before work starts, and nothing is deleted.

Node.jsClaude CodeJSONLMarkdownYAML

An agent vault that wrote memory down for months and never read it back before starting work. This is the loop that closed: remember → retrieve before acting → forget on purpose.

The Problem

The vault had good raw material: 31 archived handoff files, a decisions log, a small knowledge graph, and a consolidation pass that tidied all of it on command. None of it was ever read at the moment it would have helped, which is the first minute of a task.

So the same ground got re-walked. A polish pass shipped in August, and the verdict on it was that it did not look like an upgrade. Nothing in the system would surface that verdict to the next session about to do a polish pass. Facts had no way to be superseded, only rewritten. Skills carried no record of whether they were approved or abandoned. And nothing was ever forgotten, so the memory that existed kept growing until the index outgrew its own load limit and started dropping its last forty lines silently.

The Three-Layer Architecture

The architecture spans three distinct layers, implemented entirely as plain files: Markdown, YAML frontmatter, and JSONL. No vector databases, no remote embeddings, and no third-party memory services.

LayerStoreContract & ScopeAnswers
Episodicmemory/episodes.jsonl
memory/episodes.archive.jsonl
Append-only experience log validated against schema; archived after 90 days unless pinned.”Have we tried something like this before, and how did it go?”
Semanticbrain/nodes/*.md
brain/schema.yaml
Entity-relation-value triples on Facts & Decisions; lifecycle states (active, superseded, stale).”What is true, and is it still true?”
Procedural.claude/skills/*/SKILL.mdLifecycle frontmatter mirroring security rules; usage telemetry and candidate tracking.”Which way of working is approved, used, or retired?“

1. Episodic Schema

Every session and queue run emits a single line of structured JSON validated on write by scripts/memory/memory.mjs. Malformed or duplicate entries are rejected immediately.

id: ep-YYYYMMDD-HHMM-<slug>
ts: ISO-8601
task: string                  # One line: what was requested
scope: string                 # Target project slug or 'vault'
approach: string              # One line: how it was attempted
outcome: success | failure | partial
key_decisions: string[]       # Max 5 decisions, one line each
errors: string[]              # Max 5 error strings
resolution: string            # One line fix or empty
evidence_refs: string[]       # Links to queue results, handoff anchors, or commit SHAs
tags: string[]                # Searchable keyword facets
pinned: boolean               # If true, exempted from 90-day archive pass
status: active | archived
agent_id: string              # Optional; writer identity for memory-aware routing

The system launched with 63 historical episodes backfilled from handoffs, each explicitly tagged backfill to preserve audit integrity.

2. Semantic Node Lifecycle & Minimal Ontology

Facts and decisions are recorded as Markdown nodes under brain/nodes/ validated against brain/schema.yaml. The schema introduces formal lifecycle tracking and disambiguation fields:

status: active | superseded | stale | flagged
confirmed_at: YYYY-MM-DD
superseded_by: string         # Target node ID if superseded
entity: string                # Target entity (e.g., 'wanessalabs-com')
relation: string              # Predicate: prefers | uses | bans | owns | depends_on | located_at | decided
value: string                 # The statement or rule value

This triple structure allows newer facts to automatically supersede older contradictory entries without human intervention.

3. Procedural Skill Lifecycle

Every tool and workflow under .claude/skills/*/SKILL.md carries version and vetting metadata:

version: 1
status: pending | approved | deprecated | superseded
last_used: YYYY-MM-DD
uses: number
superseded_by: string

Status strictly mirrors .claude/rules/security.md. Skills are never promoted automatically: when /dream observes three or more successful episodes sharing a tag pattern over 90 days, it outputs a proposal to memory/review/skill-candidates.md for human approval.

Retrieval Before Acting (recall-before-task)

Before any work begins, the orchestrator queries past experience. The answer is injected as a concise, high-density context block ($\le 400$ tokens) formatted as [outcome] task → approach → resolution (id).

[RECALL] 2 relevant episodes:
• [success] polish wanessalabs-games hub -> replaced box-shadow with transform/opacity -> 60fps achieved (ep-20260923-1430-games-cwv)
• [partial] add audio to kalimba -> web audio api blocked on mobile gesture -> unlock on first tap (ep-20260921-1100-kalimba-audio)

Retrieval Mechanics

  1. Pipeline Hooks: Wired as step zero in three critical entrypoints:
    • Session startup (/resume step 5.5).
    • Project initialization (/project <path>).
    • Task execution (/queue-run before orchestrator-runner).
  2. Scoring Formula: $$\text{Score} = (1 \times \text{text token overlap}) + (2 \times \text{tag overlap}) + (3 \times \text{scope match})$$
  3. The Two-Token Precision Floor: Early prototypes produced noisy matches where a single generic word like "session" returned five confident hallucinations. Requiring a minimum of two overlapping tokens cut noise to zero. A compact or empty block is the correct response to a vague query.
  4. Latency: Linear scans across active JSONL records complete in $< 15\text{ms}$ in Node.js, making external vector stores or indexing daemons unnecessary.

Forgetting, Which Is Not Deleting

The forgetting engine runs inside /dream (and in preview mode via /dream-dry-run), enforcing strict retention rules:

EntityTrigger ConditionAction
Episodesstatus: active, pinned: false, age $> 90$ daysSet status: archived, move to memory/episodes.archive.jsonl. Reversible.
Brain Nodesconfirmed_at $> 90$ days oldSet status: stale. Never deleted or archived.
Stale NodesNode reaffirmed by claude-mem in a sessionconfirmed_at refreshed; next pass restores status: active.
Facts & DecisionsTwo active nodes with identical entity + relationOlder node receives status: superseded, superseded_by: <newer id>.
ContradictionsColliding Pillars, Playbooks, design rules, or negationsFlagged to memory/review/contradictions.md as - [ ] <A> vs <B>: <why>.

The Contradiction Detector

The detector scans active nodes, skills, and design documents for hard rule conflicts. It successfully isolates:

Single-Writer Ownership Matrix

To prevent file contention, data corruption, and multi-agent race conditions, every memory artifact has a declared single writer:

ArtifactSingle WriterPermitted Readers & Proposers
HANDOFF.md/session-end (auto-primer)dream proposes via memory/proposals/handoff.md
~/.claude/.../MEMORY.mdclaude-memdream proposes via memory/proposals/memory.md
brain/nodes/* (status)dream-keeperRead-only to all
brain/nodes/* (confirmed_at)claude-mem (reaffirmation only)Read-only to all
brain/schema.yamlHumandream proposes in digest
memory/episodes.jsonl (Append)orchestrator-runner / /session-endSubagents forbidden
memory/episodes.jsonl (Archive)dream-keeper (forgetting pass)Exclusive pass
review/contradictions.mddream-keeper (append) / Human (tick)Machine never auto-resolves
tasks/todo.md/session-enddream-keeper forbidden

Memory agents (auto-primer, dream-keeper, claude-mem) operate in an exclusive memory lane and never run concurrently.

Proof & Verification

The test harness (scripts/memory-tests/) runs 15 automated test suites against isolated fixtures, never touching live production records:

The entire memory loop—remembering experiences, recalling past solutions, and pruning stale information—operates deterministically as plain text in git.

Development timeline

5 logged updates over 125 days, 15 May 2026 to 16 Sept 2026.

  1. Recall moves to session start, and gains a floorfeature

    Reverses a v1 decision. Q5 kept session start out of retrieval, on the grounds that session start is auto-primer's job.

  2. Memory layers v1, remember, retrieve before acting, forget on purposefeature

    The vault could consolidate memory but not use it: no task read past experience before starting, no fact could be superseded, no skill carried a lifecycle, and nothing was ever forgotten on purpose. v1 builds one end-to-end slice of each,…

  3. A staging surface for signal picked up between sessionsfeature

    A read-only discovery heartbeat was added that scans local sources and stages what it finds, proposing only and never editing the vault. It is not a memory write, and it was not built for this project.

  4. The memory surfaces landed firstfeature

    Two skills arrived on the same day and they are what memory is actually made of today. One owns the topic files and the index that lists them, creating, updating and removing entries, and reads the handoff without writing it.

  5. Scoped: memory should be written by events, not by one commandfeature

    The complaint behind this project was that a whole session's learning depended on remembering to run one command at the end of it. If that command was skipped, or the session ended badly, the memory of it was gone.

Written from this project's decision log as work happened, not afterwards. See every project →