6.7 KiB
| id | date | status | supersedes | superseded-by | affected-paths | affected-components | migration_confidence | migration_source |
|---|---|---|---|---|---|---|---|---|
| 0015 | 2026-06-09 | Accepted | medium | docs/memory-system/03-architecture-decisions.md### ADR-015 — memsearch episodic memory version-controlled in a dedicated private repo, auto-synced via cc-os SessionEnd hook |
0015 — memsearch episodic memory version-controlled in a dedicated private repo, auto-synced via cc-os SessionEnd hook
Context
memsearch's memory store at ~/.memsearch accumulates daily session-summary
files (memory/YYYY-MM-DD.md) that are the only irreplaceable data in the episodic layer —
the Milvus Lite index (milvus.db) and the bge-m3 ONNX embeddings model are derived/
disposable and can be rebuilt at any time via memsearch index. With Step 4 (episodic layer)
now live, preserving episodic memory across machines and protecting against local disk loss
required a sync strategy. The question was: what venue, what scope, and who owns the sync?
memsearch's own stated design philosophy is "markdown files are the canonical data store; the
vector database is a derived index" and notes that markdown is "git-friendly" and the index
rebuildable from markdown — making git a natural fit for the markdown layer.
Decision
~/.memsearch is a dedicated git repo on branch main with remote origin
pointing to a private self-hosted Forgejo repo
(ssh://git@forgejo.swansoncloud.com:2222/jared/memsearch.git;
web: https://forgejo.swansoncloud.com/jared/memsearch). A whitelist .gitignore tracks
only memory/*.md (the daily session files) and .gitignore itself. Excluded as
derived/disposable: milvus.db (Milvus Lite index — rebuildable any time via
memsearch index), config.toml, and the bge-m3 ONNX embeddings model (lives in
~/.cache/huggingface, not in the store). Auto-commit and push are wired into the cc-os
memory plugin's own session-end.sh hook, not the marketplace plugin. The appended block
guards on ~/.memsearch/.git existing, runs git add -A (whitelist makes it safe), commits
only when something is staged (message: memsearch: session memory <date>), and pushes with
timeout 30 ... || true. The entire block is wrapped in a subshell with a trailing || true
so it can never fail session shutdown.
- Rationale:
- Dedicated repo (not folded into the vault or a project repo): ADR-001 established
episodic and semantic/knowledge as separate systems by design, and
~/.memsearchis a global, cross-project store with no natural home in any single project repo. Committing episodic session logs into the Obsidian vault repo would conflate the two systems and violate the separation of concerns that ADR-001 is built on. - Whitelist — commit markdown, exclude rebuildable index/model/config: consistent with memsearch's own design philosophy ("markdown is canonical; index is derived") and with the cc-os principle from ADR-008 ("sync the vault, not the indexes"). The 544 MB bge-m3 ONNX model is not even in the store; the Milvus Lite DB rebuilds in one command. Committing them would bloat the repo for zero durability gain.
- Sync lives in cc-os hook, not the marketplace plugin: the marketplace plugin's hook
scripts (
stop.sh,session-start.sh,user-prompt-submit.sh,session-end.sh) perform no git operations — only a read-onlygit rev-parse --show-toplevelfor scoping. Adding sync to a marketplace plugin that can be clobbered by an upstream update is fragile; owning it in the cc-ossession-end.shkeeps the sync logic under our control and version-tracked in this repo. - Fail-safe contract: the
|| truewrap andtimeout 30on push ensure that a network outage, an unreachable Forgejo instance, or any git error cannot prevent a session from closing cleanly. The SessionEnd hook's harness timeout is ~10 s, so push is effectively capped; commits land locally first, and any unpushed commit is carried forward by the next session's push (daily files are append-only, so no conflict risk).
- Dedicated repo (not folded into the vault or a project repo): ADR-001 established
episodic and semantic/knowledge as separate systems by design, and
- Commingling — resolved 2026-06-09:
~/.memsearchaggregates session summaries across all clients into one global store. This is an explicit design choice, not a tolerated risk: the user deliberately accepts a single commingled global store across all clients. Private self-hosted Forgejo (user-owned infrastructure) is the chosen sync venue; client- agreement compliance is the user's knowing responsibility. The concern was previously recorded as user-owned and unresolved; that is now closed: single global store is the intended design. This also aligns with a forward direction of minimizing dedicated per-client working directories — since memsearch captures memory globally regardless of cwd, a singleclients/area for non-project client work becomes viable (direction stated; not yet designed).
Consequences
~/.memsearch becomes its own git repo synced to a private self-hosted Forgejo remote, tracking only the daily markdown session files (via a whitelist .gitignore) while excluding the derived/disposable Milvus index, config, and embeddings model; sync is wired into cc-os's own SessionEnd hook rather than the marketplace plugin, wrapped in a fail-safe subshell so it can never block session shutdown. The design explicitly accepts a single global store commingling all clients' episodic memory as an intentional choice, with client-agreement compliance left as the user's responsibility.
Alternatives rejected
- Fold into the Obsidian vault repo: violates ADR-001's episodic/semantic separation.
Episodic logs have different lifecycle (accrete and decay), different write patterns
(auto-captured every session), and would clutter a vault intended for curated durable
knowledge.
- Auto-commit in the marketplace plugin: the marketplace plugin can be overwritten on update, losing the sync logic silently. Out-of-band ownership in cc-os is safer.
- Commit the Milvus Lite index or the embeddings model: both are large binaries, derived from the markdown source, and rebuildable. Committing them wastes space and provides no additional durability. The markdown files are the canonical source; the index follows from them.
- Syncthing or rsync instead of git: git provides both version history and conflict-free daily-append semantics; Syncthing is continuous-async (suitable for the vault where changes are sparse); git's push-on-session-end cadence matches how memsearch produces data (one daily file per day, append-only). Git was already chosen for ADR-008's vault sync rationale; applying the same mechanism to the episodic store is consistent.