Memory Architecture: QMD Migration + Artifact Simplification

implementation plan 2026-03-24 6 min read 1184 words
Artifact Preview

Memory Architecture: QMD Migration + Artifact Simplification

Executive Summary

Migrate from the builtin Gemini-only memory search to QMD hybrid search (BM25 + vector + reranking), and simultaneously simplify the artifact system from a 5-file packaging pipeline to plain markdown files that QMD auto-discovers. Two phases, done in reverse order: simplify artifacts first (less risk, unblocks Phase 2), then swap the search backend.

Current State

What exists today

Memory recall path (what agents can search):
  MEMORY.md ─────────────────── always loaded in context
  memory/*.md (43 files, 404K) ─ indexed by builtin Gemini embeddings
  memory/YYYY-MM-DD.md ──────── today + yesterday auto-loaded

Artifact storage (NOT searchable):
  mission-control/artifacts/by-id/
    art_*/
      source.md          ← the actual content
      meta.json           ← packaging metadata
      preview.html        ← rendered HTML
      preview-card.svg    ← summary card image
      preview.pdf         ← PDF export

Workspace files (always loaded, not searched):
  AGENTS.md, SOUL.md, USER.md, TOOLS.md, IDENTITY.md, HEARTBEAT.md

Problems

  1. Artifacts are invisible to recall. 8 artifact source files with real research and decisions. Agents can't find them via memory_search.
  2. Artifact creation is fragile. Agents must run create-artifact.mjs to register. Raw writes produce orphaned files (happened today with the LinkedIn artifact).
  3. 5 files per artifact is over-engineered. meta.json, preview.html, preview-card.svg, preview.pdf exist for a presentation layer that could render on-the-fly from source markdown.
  4. Builtin search is vector-only. No keyword matching, so exact terms (project names, issue numbers) can miss. QMD adds BM25 for lexical precision.

Target State

Memory + Knowledge recall path (all searchable via QMD):
  MEMORY.md ─────────────────── always loaded in context
  memory/*.md ───────────────── daily notes, session logs
  artifacts/*.md ────────────── research, plans, specs, analysis
  (optional) references/*.md ── ingested external docs

MC presentation layer (renders from source):
  MC reads artifacts/*.md directly
  Extracts title from H1, summary from first paragraph
  Renders via shared markdown renderer
  No meta.json, no preview files, no registration step

Search backend:
  QMD (BM25 + vector + reranking, fully local)
  Auto-indexes all paths on 5-minute interval
  Zero API cost for search operations

Phase 1: Simplify Artifacts (do this first)

Why first: This is lower risk and produces the directory structure QMD will index. No point indexing the current mess of meta.json and preview files.

1.1 New artifact directory

Move artifact source files to a flat, simple location:

workspace/artifacts/
  voice-solutions-analysis.md
  agent-operating-protocol-v1.md
  linkedin-post-analysis-2026.md
  mc2-architecture.md
  ...

Rules:

1.2 MC auto-discovery

Rewrite the MC artifact list API to scan workspace/artifacts/*.md instead of reading data-v2/artifacts.json:

1.3 Migration

1.4 Agent workflow change

Before:

Agent writes source.md → runs create-artifact.mjs → MC sees it

After:

Agent writes workspace/artifacts/my-research.md → MC sees it

Definition of done (Phase 1)

Phase 2: QMD Search Backend

Why second: Now that artifacts are clean .md files in a known location, QMD can index them alongside memory files.

2.1 Fix QMD installation

Current state: QMD binary exists at /Users/vinny/.bun/bin/qmd but module is missing. Fix:

bash
bun install -g @tobilu/qmd    # reinstall cleanly
qmd --version                  # verify

Prerequisites already met:

2.2 Configure QMD as memory backend

json5
{
  "memory": {
    "backend": "qmd",
    "citations": "auto",
    "qmd": {
      "includeDefaultMemory": true,
      "paths": [
        {
          "name": "artifacts",
          "path": "artifacts",
          "pattern": "**/*.md"
        }
      ],
      "update": {
        "interval": "5m",
        "debounceMs": 15000,
        "onBoot": true,
        "waitForBootSync": false
      },
      "limits": {
        "maxResults": 8,
        "maxSnippetChars": 700,
        "timeoutMs": 4000
      },
      "scope": {
        "default": "deny",
        "rules": [
          { "action": "allow", "match": { "chatType": "direct" } },
          { "action": "allow", "match": { "keyPrefix": "discord:channel:" } }
        ]
      }
    }
  }
}

This indexes:

2.3 Verify search quality

Test queries that should surface artifacts:

Test queries that should still find memory:

2.4 Remove builtin search config

Once QMD is verified:

Definition of done (Phase 2)

What changes for agents

ActionBeforeAfter
Create artifactRun create-artifact.mjs with 8 flagsWrite a .md file to workspace/artifacts/
Find past researchManually read file if you know pathmemory_search finds it automatically
Reference a decisionHope it's in MEMORY.mdQMD searches artifacts + memory together
Artifact shows in MCOnly if registered in artifacts.jsonAuto-discovered from directory

Risks

RiskMitigation
QMD install fails againKeep builtin Gemini search as fallback; OpenClaw auto-falls-back if QMD errors
MC auto-discovery slower than JSON lookupCache the glob results; 8 files is trivial
Frontmatter parsing edge casesKeep frontmatter optional; H1 + first paragraph is the minimum
Losing artifact metadata (owner, type, tags)Migrate to frontmatter in each .md file before deleting meta.json

Timeline estimate