Skip to the content.

M0 — pattern validation protocol

Status: complete (2026-07-13 → 2026-07-22; results below and in demo.md). Goal per ROADMAP.md: prove the shelve→recall loop on real work with zero new code — docshelf as-is + the prompt-only kit in adapters/claude-code/.

Kit

Piece File
/shelve skill (live + import modes) adapters/claude-code/skills/shelve/SKILL.md
Recall rule for CLAUDE.md / project prompt adapters/claude-code/CLAUDE-md-snippet.md
This protocol docs/M0.md

Setup

  1. Shelf repo. Design default is git-local (no remote), but M0 runs in cloud sessions where containers are ephemeral — so the M0 shelf uses a private remote (the git-remote mode): a dedicated private GitHub repo, added to the session. Because the container is ephemeral the push is not optional: every shelve pushes right after its commit (a /shelve step), or the committed episode dies with the container — the loss mode recorded below. The M1 SessionEnd hook (#11) will automate it; until then it is manual per shelve.
  2. Init via docshelf: init_shelf(name=…, default_categories=["topics", "research", "sessions"]), provider: none (relative links; recall goes over MCP/file reads, not raw URLs).
  3. Policy file. Drop a POLICY.md in the shelf root stating the PII rules for this shelf’s domain. For sqst material: no student names, nicks, emails, or identifiers — roles and codes only («студент», C1..C7 / S1..S15), consistent with the course PII policy.
  4. Copy the recall-rule snippet into the consuming project’s CLAUDE.md and the skill into .claude/skills/shelve/.

Case A — retro-import: the sqst homework-review dialog

Candidate: the author’s long homework-review chat (Opus 4.7 era, sqst course). This is the import mode of the skill:

  1. The raw transcript is provided into the session only (file upload or pasted path). It is never committed to any repo, shelf included.
  2. The agent proposes a segmentation (episodes per review batch / recurring problem theme / methodology decision, plus one kind: session digest for the whole dialog), with rough token weights. Author confirms.
  3. Episodes are composed depersonalized-by-construction (POLICY.md), written via add_document, ledgered as mode: import, committed.
  4. Output: INDEX.md whose digests summarize months of review practice in a few KB.

Why this is a good M0 case: it’s real, it’s long (way past any context window), it has known-answer questions, and it stress-tests the PII posture — the exact thing black-box memory stores can’t demonstrate.

Case B — live shelving

In a working session on a real project: apply the recall rule + /shelve at natural topic closures for ~a week of normal work. This exercises the cut proposals, digest quality under time pressure, and the “replace in context” convention.

Measurement — the token ledger

Every shelve appends to <shelf>/ledger.tsv:

date	episode_id	mode	approx_tokens_in	digest_tokens	notes

Derived numbers (computed with the same tokenizer methodology as docshelf’s benchmarks/token_savings.py):

The recall test

After Case A import, ask (in a fresh session with only INDEX + recall rule) five known-answer questions of the form “what did we decide about X and why” / “which recurring mistake did students make in HW-N” / “what was rejected and for what reason”. Score: correct & complete answers, sections fetched, tokens spent per answer.

Exit criteria (from ROADMAP)

Results so far (2026-07-13, Case A round 1)

Imported: two chat-export fragments (sqst homework-review tail ~15 KB; personal hardware thread ~28 KB) → 8 episodes (5 topics, 1 research, 2 sessions), ~11K source tokens shelved, INDEX = 3.6 KB (~0.9K tokens). PII gate passed review (sqst-memshelf#1, merged).

Recall test: 5/5 correct and complete. Fresh-context agent, given only the INDEX path + recall rule, answered five known-answer questions (docx root cause + generator fix; student-B’s three config decisions; both students’ open minors; laptop verdict + customs math; Mac Studio imbalance + replaced plan). Navigation was exact: 6 files read (INDEX + 5 episodes), zero misses, zero over-fetch, ~21 KB total. Two questions were answerable from INDEX alone but the agent fetched for the requested specifics — correct behavior.

Cost sketch (chars/4 estimates, proper tokenizer pass pending): per question ≈ INDEX (0.9K) + one episode (~1–1.5K) ≈ ~2–2.5K tokens vs ~11K+ for carrying both fragments in-context — ~5× per question already on a tiny 8-episode shelf. The ratio grows with the archive: INDEX stays ~1K tokens regardless, and the real source chat (full export: 87 MB) does not fit any context window at all — same shape as docshelf’s RouterOS result.

Results — Case A rounds 2–3 (2026-07-13) and Case A close

Round 2 (full-export extraction batch): a fresh-context reviewer agent triaged six by-catch conversations (WORTH/MARGINAL/THROWAWAY) → 3 episodes shelved (IPv6 homelab plan; docshelf origin story — two same-day chats merged into one arc; mentee GitOps review with a live must-fix list), 2 skipped by verdict, ~40K source tokens (sqst-memshelf#2, merged).

Round 3 (Cowork session JSONLs, 1.5 MB + 201 KB): the subagent-deposit pattern validated in production — fresh-context agents read the raw transcripts, returned depersonalized structured digests, episodes composed from those; my context never touched the raw dumps. 6 episodes: four runbook blocks (artifact regen / snap rehash / blob recreation with the divergent-history catch / filter-repo PII purge), a session digest, and the vectors-drawing+lull bootstrap. ~24.8K conversational source tokens (raw JSONL ~375K with tool outputs) (sqst-memshelf#3).

Shelf after round 3: 17 episodes. Benchmark (benchmarks/token_savings.py, chars/4 — tiktoken vocab blocked by the environment proxy; ratios are estimator-independent): INDEX = 1,370 tokens, whole shelf 7,995, query (INDEX + 1 episode) = 1,765 tokens — 77.9% cheaper than dumping the shelf, and ~97% cheaper than the ~76K conversational source tokens the shelf now represents (which themselves are a fraction of the raw sessions).

The strongest M0 finding was accidental. The actual homework-review season transcript (April–June) no longer exists anywhere: not in the claude.ai export (it was a Cowork session), not in ~/.claude/projects (rotated away). The only surviving trace is what the author happened to copy by hand — the exact loss mode memshelf exists to prevent. “Memory that isn’t shelved while the context exists is memory lost” stopped being a design slogan and became an observed fact within the first day of M0.

Case A: CLOSED (source material exhausted). Remaining for M0 exit: Case B — a week of live shelving in working sessions.

Results — Case B (2026-07-13 → 2026-07-22) and M0 close

Case B ran the planned week of live shelve-at-close on real work. Ledger at close: 33 episodes (16 live + 17 import backfill), 1.91M source tokens → 5.7K digest tokens (334:1 overall, 565:1 live-only), with individual live sessions of 160–220K tokens each — and zero episodes lost. The founding invariants held (shelve-at-close, push-in-ephemeral-session, INDEX-first recall, PII gate); the one-shelf-vs-multi question resolved de facto toward per-domain shelves. The full verdict is a research episode on the shelf (2026-07-22-case-b-verdict); the measured write-up is demo.md. M0: CLOSED — exit criteria met. The annoyance log below became the M1 backlog, and the M1 tool surface now enforces what this protocol did by hand.

Annoyance log

# What hurt M1 implication
1 .meta.json hand-patched to get Russian display titles over latin date-slugs — add_document couples title→slug memshelf_shelve takes slug and display_title separately (or upstream a docshelf slug= param)
2 Ledger rows appended by hand, token math by hand memshelf_stats + shelve writes the ledger row itself
3 Digest/schema contract validated “by agent honor” — nothing enforced length/sections tool-side validation as designed
4 Domain mixing: sqst + personal episodes in one shelf (INDEX interleaves them) confirm one-shelf-per-domain; memshelf init cheap enough to make second shelves frictionless; federation stays open question
5 docshelf default INDEX preamble talks raw-GitHub-URLs — had to replace with the recall rule manually memshelf init sets the memory preamble
6 87 MB conversations.json can’t pass through MCP context transfer memshelf_import must take a file path / URL, never content-in-context; chunked local processing
7 Clone-of-empty-repo left git without a fetch refspec — bit twice (memshelf-mcp, sqst-memshelf) environment quirk; document in shelf bootstrap notes
8 Name-based extraction from the export missed the target chat entirely (it matched by title, not content) memshelf_import discovery must search content markers, not conversation titles
9 Session transcripts rot: the review-season Cowork session was already rotated out of ~/.claude/projects — unrecoverable shelve-at-close (SessionEnd hook) is not optional; retro-import cannot be the primary path
10 Raw session JSONL is ~94% tool-output noise (375K raw vs 22.5K conversational) import pipeline must strip tool blocks before any LLM reads the transcript