Memory System

This page is in two sections. Read the one you need.


Understanding the Memory System

This section is an Explanation. It answers "why does VECTOR's memory work this way?" If you need the exact schema or file format, scroll to the Reference section.


Why Four Layers?

The four-layer memory architecture is not an engineering preference โ€” it is an answer to a specific problem: how do you give an AI system persistent, reliable memory while keeping the concerns of different actors isolated from each other?

A flat memory model โ€” one shared store for everything โ€” fails in a multi-agent system. FORGE's engineering lessons would be visible to SAGE, SAGE's content patterns would be visible to GHOST, and VECTOR's long-term strategic context would be visible to ephemeral workers. The result is context pollution: agents receiving irrelevant information that degrades rather than improves their decisions.

The four layers partition memory by ownership and time horizon.

graph TB subgraph L4["L4 โ€” Chief Context (permanent, VECTOR-reads-only)"] S["SOUL.md โ€” VECTOR identity"] U["USER.md โ€” Chief profile"] M["MEMORY.md โ€” Long-term episodic memory"] end subgraph L3["L3 โ€” VECTOR Operational Memory (persistent)"] DB["state/vector.db โ€” SQLite backbone"] LOG["memory/YYYY-MM-DD.md โ€” Daily logs"] CMP["MEMORY_COMPACT.md โ€” Searchable archive"] SPR["state/active-sprint.json โ€” Compaction anchor"] end subgraph L2["L2 โ€” PM Memory (persistent, isolated per PM)"] BR["BRAIN.md โ€” PM identity"] LE["lessons.md โ€” Task history"] BL["beliefs.json โ€” BEE belief store"] end subgraph L1["L1 โ€” Worker Context (ephemeral)"] TS["Task spec โ€” injected at spawn"] IC["PM-selected context โ€” relevant lessons + beliefs"] end L4 -.->|VECTOR reads at session boot| L3 L3 -.->|injected at PM spawn| L2 L2 -.->|selectively injected at worker spawn| L1

L4 is the identity and mission layer. It changes rarely โ€” when Chief updates direction, when a new project becomes primary, when an operating principle is established. VECTOR reads it at session boot. No PM writes to it. No worker sees it. It is the source of context that persists longer than any task.

L3 is the operational layer. It records what happened, what's in flight, and what VECTOR has learned. The SQLite database (state/vector.db) is the authoritative source for all ticket state, audit history, and cost tracking. The daily logs provide a human-readable operational record. The compaction archive makes past experience searchable.

L2 is the PM expertise layer. Each PM has its own isolated memory partition. FORGE's engineering lessons live in memory/pm-forge/. SAGE's content patterns live in memory/pm-sage/. When a PM boots, it reads its own memory โ€” not another PM's. VECTOR can read all PM memory; PMs cannot read each other's.

L1 is ephemeral by design. A worker session ends and its context disappears. This is intentional. The value of the work should flow up through verified git diffs and belief extraction โ€” not through the worker retaining context across tasks. Ephemeral workers have clear scope and clear limits.


How Memory Survives Compaction

This is the part that most multi-agent systems get wrong.

When a very long VECTOR session runs โ€” hundreds of tasks, thousands of tool calls โ€” the context window fills. The AI infrastructure must summarize the old context to make room for new work. This is called compaction. It is inevitable and happens without warning.

A system without a compaction strategy loses track of in-flight work. Sprints that were active become invisible. Task IDs are forgotten. The next VECTOR boot starts cold, as if nothing had been done before.

VECTOR's answer is state/active-sprint.json โ€” the compaction anchor.

The sprint file is a structured JSON document containing everything VECTOR needs to resume from a compaction event:

{
  "sprint_id": "SPRINT-003",
  "status": "active",
  "tracks": [
    {
      "id": "TRACK-A",
      "pm": "FORGE",
      "task_id": "TASK-20260226-010",
      "status": "in_progress",
      "last_gate": "GATE-A-20260226-001",
      "worker_session": "sess_xyz"
    }
  ],
  "updated_at": "2026-02-27T00:10:00Z"
}

When VECTOR boots, it reads this file first. If status is active, VECTOR does not start fresh โ€” it reads the track statuses, polls any background workers, and continues from where the compaction interrupted. From Chief's perspective, the compaction is invisible.

This is why the sprint file is updated continuously during sprint execution, not just at the start and end. If the update happened only at boundaries, a compaction event at the wrong moment would still lose state.


Why SQLite as the Backbone?

The operational backbone (state/vector.db) is SQLite rather than a cloud database, a distributed store, or flat files. This choice has reasoning behind it.

VECTOR is designed to run on a single machine first, with multi-machine expansion as an upgrade โ€” not a requirement. SQLite is file-based, zero-infrastructure, and ACID-compliant. A VECTOR deployment on a Mac mini has the same query capabilities as one on a server cluster.

The database is the single source of truth for operational state. Markdown files are human-readable caches โ€” useful for reading, but never authoritative when they conflict with the database. If tasks/BOARD.md says a ticket is open and state/vector.db says it is closed, the database is correct.


How BEE Extends Memory Across Sessions

Individual session memory (L1 worker context) and daily logs (L3) capture what happened. BEE captures what was learned.

The distinction matters. "We tried to build auth and hit a conflict with CUSTOM_PATCHES.md line 47 on TASK-20260226-010" is an event. "Auth patches consistently conflict with CUSTOM_PATCHES.md โ€” review before any auth work" is a belief. The event is useful for audit. The belief is useful for prevention.

BEE extracts the belief layer from the event layer and makes it injectable into future PM contexts. This is explained in full in Understanding BEE.


Why PM Memory Is Isolated

PM memory isolation is an architectural choice with both correctness and security implications.

On the correctness side: FORGE's engineering lessons about worktree isolation have no value in SAGE's content work. If all PM memory were shared, every PM would receive a large context of irrelevant information on every spawn โ€” degrading quality and increasing cost.

On the security side: memory isolation prevents a malfunctioning PM from writing beliefs or lessons into another PM's memory space. FORGE cannot inject misleading content patterns into SAGE's memory. The write boundary for L2 memory is enforced at the PM level โ€” each PM writes only to its own directory.

VECTOR, as the Tier 0 conductor, can read all L2 memory. This is intentional: VECTOR synthesizes across all PMs for standup reports, belief promotion, and cross-PM coordination. But VECTOR reads; it does not write to PM memory. PMs write their own memory at session close.



Memory Reference

This section is a Reference. It describes the memory system machinery โ€” file locations, database schema, belief formats, and search API.


File Location Map

Path Layer Type Owner
SOUL.md L4 Markdown Chief / VECTOR
USER.md L4 Markdown VECTOR
MEMORY.md L4 Markdown VECTOR
state/vector.db L3 SQLite VECTOR
memory/YYYY-MM-DD.md L3 Markdown VECTOR
MEMORY_COMPACT.md L3 Markdown VECTOR
state/active-sprint.json L3 JSON VECTOR
memory/pm-{name}/BRAIN.md L2 Markdown Owning PM
memory/pm-{name}/lessons.md L2 Markdown Owning PM
memory/pm-{name}/beliefs.json L2 JSON VECTOR (via BEE)
memory/pm-ai-intel.md L2 Markdown ORACLE
memory/pm-sentinel.md L2 Markdown SENTINEL

SQLite Database Schema (state/vector.db)

Table: tickets

CREATE TABLE tickets (
  id           TEXT    PRIMARY KEY,
  title        TEXT    NOT NULL,
  pm           TEXT    NOT NULL,
  status       TEXT    NOT NULL DEFAULT 'todo',
  priority     INTEGER NOT NULL DEFAULT 2,
  created_at   TEXT    NOT NULL DEFAULT (datetime('now')),
  updated_at   TEXT    NOT NULL DEFAULT (datetime('now')),
  closed_at    TEXT,
  gate_a_id    TEXT,
  gate_b_id    TEXT,
  gate_c_id    TEXT,
  worker_branch TEXT,
  detail       TEXT
);
Column Type Values / Notes
id text PK Format: TASK-YYYYMMDD-NNN
status text todo | in_progress | blocked | done | failed | cancelled
priority integer 0=P0 (critical) ยท 1=P1 ยท 2=P2 ยท 3=P3
pm text FORGE | GHOST | ORACLE | SENTINEL | COMPASS | SAGE | VECTOR

Table: beliefs (written by BEE plugin)

CREATE TABLE beliefs (
  id           INTEGER PRIMARY KEY AUTOINCREMENT,
  content      TEXT    NOT NULL,
  scope        TEXT    NOT NULL,
  type         TEXT    NOT NULL,
  confidence   REAL    NOT NULL,
  source       TEXT    NOT NULL,
  status       TEXT    NOT NULL DEFAULT 'provisional',
  created_at   TEXT    NOT NULL DEFAULT (datetime('now')),
  updated_at   TEXT    NOT NULL DEFAULT (datetime('now')),
  promoted_at  TEXT,
  deprecated_at TEXT,
  evidence     TEXT,
  pm_owner     TEXT
);
Column Type Values / Notes
scope text private | shared | global
status text provisional | active | rejected | deprecated
confidence real 0.0โ€“1.0
source text Must reference existing tickets.id

Table: cost_tracking

CREATE TABLE cost_tracking (
  id           INTEGER PRIMARY KEY AUTOINCREMENT,
  timestamp    TEXT    NOT NULL DEFAULT (datetime('now')),
  actor        TEXT    NOT NULL,
  model        TEXT    NOT NULL,
  input_tokens INTEGER NOT NULL,
  output_tokens INTEGER NOT NULL,
  cost_usd     REAL    NOT NULL,
  task_id      TEXT
);

Table: content_calendar

CREATE TABLE content_calendar (
  id             INTEGER PRIMARY KEY AUTOINCREMENT,
  platform       TEXT    NOT NULL,
  content_type   TEXT    NOT NULL,
  scheduled_date TEXT    NOT NULL,
  status         TEXT    NOT NULL DEFAULT 'pending',
  content_hash   TEXT,
  published_at   TEXT,
  content        TEXT
);
Column Values
platform linkedin_personal | linkedin_company | twitter | blog
status pending | draft | reviewed | published | failed

active-sprint.json Schema

{
  "sprint_id": "string",
  "status": "active | completed | paused",
  "goal": "string",
  "tracks": [
    {
      "id": "string",
      "pm": "FORGE | GHOST | ORACLE | SENTINEL | COMPASS | SAGE",
      "task_id": "string",
      "status": "not_started | in_progress | blocked | done | failed",
      "last_gate": "string | null",
      "worker_session": "string | null",
      "notes": "string | null"
    }
  ],
  "started_at": "ISO 8601",
  "updated_at": "ISO 8601",
  "completed_at": "ISO 8601 | null"
}

Compaction recovery: On session boot, VECTOR reads active-sprint.json. If status = "active", VECTOR resumes the sprint by checking each track's status and polling any worker_session IDs that are non-null.


Semantic Search API

# Search VECTOR's memory archive
node scripts/memory-search.js "<query>"

# Search with scope filter
node scripts/memory-search.js "<query>" --scope pm-forge

# Search beliefs only
node scripts/memory-search.js "<query>" --type beliefs

# Search lessons only  
node scripts/memory-search.js "<query>" --type lessons

Output format:

Results for "worktree isolation":
  [0.94] memory/pm-forge/lessons.md:47 โ€” "node_modules must be explicitly installed..."
  [0.89] memory/pm-forge/lessons.md:112 โ€” "tsc silent failure on missing deps..."
  [0.71] MEMORY_COMPACT.md:234 โ€” "Sprint 2 engineering learnings..."

Scores are cosine similarity. Results above 0.7 are considered relevant.


Memory Integrity Check

VECTOR runs a memory integrity check at every session boot. Manual trigger:

node scripts/memory-integrity.js

# Auto-repair mode (safe โ€” only adds missing tables, never deletes data)
node scripts/memory-integrity.js --repair

Checks performed:

Pass output:

โœ“ Memory integrity check passed (1.8s)
  PM BRAIN.md files: 6/6 present
  SQLite: ok
  Sprint state: active (SPRINT-003)
  Mode: autonomous