Skip to the content.

memshelf — Decision log

Newest last. Earlier entries were made while the design lived as RFC-0001 in docshelf-mcp.

Date Decision By
2026-07-13 RFC draft created. Form = companion project over docshelf (not a docshelf subpackage, not a prompt-only pattern); primary surface v1 = Claude Code / Cowork. draft, author-merged (ignatenkofi/docshelf-mcp#42)
2026-07-13 Portability requirement: core/episode format/on-disk shelf contain nothing host-specific; three-ring model (core → MCP+CLI surfaces → host adapters); triggers are adapter territory; prompts are core assets. author note, merged (ignatenkofi/docshelf-mcp#43)
2026-07-13 Prior-art survey (LANDSCAPE.md): niche confirmed open — no project combines episodes+digests+git+INDEX navigation. Design amendments: mechanical eviction, injection budgets/KV-cache discipline, prompt-injection-on-recall defense, platform-collision defense, subagent-deposit trigger (v2), memory-tool adapter ring. Direction kept, scope sharpened. draft, author-merged (ignatenkofi/docshelf-mcp#44)
2026-07-13 Name + placement resolved: memshelf, repo ignatenkofi/memshelf-mcp (PyPI memshelf / memshelf-mcp checked free). Repo created by author; seeded from the RFC. author
2026-07-13 Storage defaults reworked per author’s git concerns: modes plain / git-local (default — auto-commit, no remote configured) / git-remote (opt-in, private-only, doctor-enforced, autopush: false). Accidental-exfiltration threat handled by absence of a remote, not absence of git. “Store inside Claude” (artifacts/attachments) assessed: unsuitable as canonical store (breaks portability), adopted as optional read-mirror idea (M3 experiment). author + draft
2026-07-13 Positioning: hero scenarios added to MANIFEST — (1) the weeks-long dialog that must not die (primary wedge), (2) context advisor: surface where the window goes, flag shelvable episodes (promoted into M2; also the onboarding moment), (3) archive as raw material: tags/graph/retrospectives/fork-a-thread (M3). Many-repos overload noted as advisor diagnosis territory, not a direct memshelf fix. author + draft
2026-07-13 Import mode adopted (author: “выгрузить весь диалог на полку”): whole-dialog retro-shelving = segmentation into episodes + one session digest, mode: import in the ledger. Distinct from the “transcript archiver” non-goal — segmentation and digests are mandatory, raw excerpts optional, the raw transcript itself is input-only and never committed. M0 does it manually via the skill; memshelf_import is an M1 candidate. author + draft
2026-07-13 Transparent token accounting adopted (author request, mirroring docshelf’s measured-savings ethos): ledger.tsv per shelf, one row per shelve; memshelf_stats in M1; derived metrics (standing cost / shelved mass / compression / recall cost per question) defined in docs/M0.md. author + draft
2026-07-13 M0 launched. Kit: prompt-only /shelve skill (live + import modes) and recall-rule snippet in adapters/claude-code/; protocol in docs/M0.md. Case A material: author’s long sqst homework-review dialog (Opus 4.7 era) as retro-import; episodes depersonalized per sqst PII policy (roles/codes, no student identifiers), raw transcript stays outside all repos. M0 shelf uses a private remote (cloud sessions are ephemeral) — a documented deviation from the git-local default. author + draft
2026-07-22 Claude Code plugin hooks scoped to what shell hooks can actually do (#11): a hook is a shell command, not the LLM, and per the current hook contracts SessionStart can inject context while PreCompact cannot and SessionEnd runs after the agent stops. So the plugin ships SessionStart → inject INDEX.md (recall bootstrap) and SessionEnd/PreCompact → mechanical shelf push (MEMSHELF_AUTOPUSH, off by default). The ROADMAP’s “PreCompact shelve / SessionEnd session digest” is revised: both need the LLM, so they stay agent-driven (the /shelve skill + recall rule), not hooks. author + draft
2026-07-22 Server topology: separate MCP process (closes open question 3 / #28). memshelf-mcp ships its own FastMCP stdio server (server.py, mirroring docshelf’s), not an in-process registration alongside docshelf tools — shipped this way in the M1 slices and confirmed as the decision: the core imports docshelf as a library (one dependency), while the server stays independently versioned, installable, and testable; users who want both attach two config entries. Revisit only if the two-entry config proves a real adoption burden. draft, per shipped M1
2026-07-22 memshelf_stats reports claimed AND realized economy (#6; closes the Case B verdict’s measurement gap). Claimed = ledger-derived (standing cost = tokens(INDEX) + Σ digest tokens; shelved mass = Σ approx_tokens_in; compression = mass / standing). Realized = an opt-in recall log (recall --logrecall-log.tsv), where each fetch’s saving = the episode’s original mass − tokens actually fetched. The true fetch-hit rate (share of past-work questions closed by a shelf fetch vs re-reading the repo / owner re-explaining) needs a denominator that can’t be captured mechanically, so stats reports the measurable side (recall count, episodes recalled, realized tokens saved) and stays honest about the rest. chars/4 estimator, tokenizer-independent. author + draft
2026-07-31 Derived shelf files become bot-rendered; notes moves into the episode (#58; adopts project-atlas ADR 0007). Parallel shelve runs collide in four files at once — INDEX.md, ledger.tsv, docs/*/.meta.json, stats.svg — because every writer regenerates all of them. Target shape (M2): shelve writes only the episode file; ledger.tsv becomes derivable once its one non-derivable column (notes) lives in the episode frontmatter; INDEX/ledger/.meta/stats are rendered by a bot on main behind a PR guard on the derived paths. The conflict class then cannot occur by construction rather than being resolved after the fact. memshelf resolve (shipped, live run 2026-07-30) stays as the fallback for hand-merges and for shelves that keep the current layout. Rejected: .gitattributes merge=union — GitHub’s server-side merge does not run custom drivers, the same reason the atlas turned it down; and push-straight-to-main on shelve, which breaks the draft-PR discipline of night shifts without closing the two-simultaneous-push race. author + draft
2026-08-01 Context advisor: heuristics only; the window breakdown is an input, not something the tool hunts for (#14, closes open question 7). A library cannot see the window it is asked about, and a parser for a host’s /context output would work on exactly one host and rot with its next release. So the advisor reuses the split shelve and rollup already have: the model reports what only the model knows (labels, rough sizes, which topics are closed), and the tool contributes the four things a self-assessment cannot — memshelf’s own standing cost, measured; verification of every “already shelved” claim against the actual episodes (a false claim is refused loudly, since acting on it destroys work); arithmetic net of what shelving adds forever (~200 tokens per episode, so nothing under 2000 is proposed at all); and a deterministic ranking, without which the M2 exit criterion “proposals accepted, not overridden” cannot be measured. Proposals only — the tool writes nothing. Rejected: harness-parsing in core (host-bound, and portability rule 2 puts it in an adapter filling the same input); inferring “already shelved” from a title match (it becomes a hint, never an auto-drop). author-planned, draft