cc-os/openspec/changes/archive/2026-06-08-memory-project-g.../design.md

8.2 KiB

Last updated: 2026-06-08

Context

The memory plugin ships at ~/.claude/plugins/memory/ with three skills: memory-query, memory-write, memory-reorganize. memory-query covers vault retrieval; the other two are write-path skills. No project-graph skill exists.

Two problems compound:

  1. memory-query has a god-node dependency: it instructs Claude to start from a hub note surfaced in the session's additionalContext. That requires session-context.sh to emit a vault graph report on every session start — cost paid regardless of whether vault knowledge is needed.
  2. There is no routing rule. Claude has to infer when to query the vault versus a project graph, with no explicit guidance. The two question types are structurally distinct and need different tools.

Constraints (unchanged):

  • Ollama model: qwen2.5-coder:7b — established by local-model-selection, used for all graphify extraction.
  • graphify-out/ must never be committed — local, disposable, rebuildable.
  • Skills are mirrored identically across ~/.claude/, .codex/, .pi/.

Goals / Non-Goals

Goals:

  • Two focused skills that align with the two query types.
  • Routing rule that Claude can apply without ambiguity, persisted in a file that's globally visible.
  • Lean session injection — emit only what is used on every session start.
  • Remove the god-node injection dependency without breaking vault retrieval quality.

Non-Goals:

  • Memsearch / episodic layer (Step 4 of build plan — not in scope here).
  • Vault migration scaffolding (Step 1 — separate concern).
  • Automated graph freshness (no daemon; updates remain on-demand).
  • Bulk project onboarding.

Decisions

Decision: Two skills, not one with internal routing

memory-vault and memory-project are separate skills, not branches of a single skill.

The question types are structurally different: vault queries need no project context; project queries need a graph path and a codebase in scope. Skills have asymmetric capabilities — vault writes are meaningful; "project writes" are not a concept. A model routing naturally between two named skills is more reliable than a model routing internally within one skill with conditional logic.

Alternative considered: single memory skill with a routing section at the top. Rejected — the conditional logic would need to cover both lifecycle operations (onboard/update/remove) and query routing, making the skill unwieldy and ambiguous.

Decision: Drop god-node injection dependency from memory-vault

The current memory-query skill instructs Claude to start at a hub note surfaced in additionalContext. Graphify's traversal already handles graph navigation internally — the --budget flag bounds token cost, and graphify query returns relevant subgraph regardless of entry node. The god-node instruction was a guard against unconstrained traversal, not a technical requirement.

Removing it means session-context.sh no longer needs to emit a vault graph report. The skill retains all query/path/explain patterns and the --budget flag, which together bound traversal cost.

Alternative considered: keep god-node but make injection opt-in. Rejected — optional injection is harder to reason about than no injection. The skill works without it.

Decision: Routing rule lives in ~/.claude/CLAUDE.md

The routing heuristic ("vault vs project graph") must be globally visible — it applies in every project session, not just sessions in this repo. ~/.claude/CLAUDE.md is the global user instructions file loaded automatically in every project. It is a single file to update, and changes take effect everywhere immediately.

Alternative considered: per-project CLAUDE.md. Rejected — would require maintaining the rule in every project.

Alternative considered: inside the skills themselves. Rejected — a model reading memory-vault might not read memory-project first, and vice versa. The routing rule needs a neutral home both skills can point to.

Decision: session-context.sh emits only project graph pointer

Current session-context.sh emits: vault graph report, live convention query, journal pointer, project graph path. The vault graph report and convention query are the ones that motivated the god-node dependency — they pre-populate a hub node for the skill to start from. With god-node removed, they are overhead.

The project graph path pointer is the only injection that pays per-session: it tells Claude whether a project graph exists for the current repo without requiring Claude to probe the filesystem. This one conditional line remains.

Alternative considered: emit nothing; let skills query on demand. Rejected — the graph path check is cheap and eliminates a filesystem probe in every session that uses memory-project.

Decision: memory-project delegates query mechanics to memory-vault

memory-project's query section states the --graph ./graphify-out/graph.json routing rule and then explicitly says "see memory-vault for query mechanics (graphify query, graphify path, graphify explain, --budget, --dfs)." This avoids duplication and ensures the two skills stay consistent as graphify evolves.

Decision: AST-only extraction for code repos; --backend ollama specified uniformly

Code repos use the free tree-sitter AST pass — no LLM cost. The --backend ollama --model qwen2.5-coder:7b flags are always specified on the onboard command because the single invocation handles both pure-code and mixed (code + docs) repos without requiring Claude to detect repo type first.

Decision: cluster-only as a separate onboarding step

graphify cluster-only . runs after initial extraction to build the community structure required for graphify query. No combined command exists in the Graphify CLI at v0.8.30, so the two-step sequence is the correct protocol.

memory-vault Skill

Scope: vault at ~/Documents/SecondBrain. Evergreen, cross-project knowledge: conventions, tool behavior, client facts, patterns that generalize beyond one repo.

Query patterns (unchanged from memory-query):

  • graphify query "<topic>" --budget 2000 — explore
  • graphify path "<a>" "<b>" — trace relationships
  • graphify explain "<node>" — deep-dive
  • graphify query "<topic>" --dfs --budget 2000 — bounded depth-first

No --graph flag = vault default. No god-node injection needed.

Tag-scoped caution note retained: facet-tag graph edges not yet verified (ADR-014 open).

Write guidance: use memory-write when knowledge generalizes beyond the current repo. If in doubt: "Would this be useful outside this repo, next year?" If yes → vault.

memory-project Skill

Scope: per-project graph at ./graphify-out/graph.json. Codebase structure and module relationships for the current repo only.

Lifecycle operations:

Operation Command
Onboard (extract) graphify extract . --backend ollama --model qwen2.5-coder:7b
Onboard (cluster) graphify cluster-only .
Onboard (gitignore) ensure graphify-out/ in .gitignore
Incremental update graphify update .
Structural update graphify update . --force (renames, deletions, moves)
Remove delete graphify-out/; leave gitignore entry

Query: graphify query "<question>" --graph ./graphify-out/graph.json — then see memory-vault for traversal mechanics.

Graph path discovery: session-context.sh injects the path if the graph exists. If no path is injected, suggest onboarding before knowledge queries.

Hard constraints: never commit graphify-out/; gitignore entry survives even if graph is deleted; model is qwen2.5-coder:7b.

Risks / Trade-offs

  • [Risk] god-node removal degrades vault retrieval quality → --budget 2000 still bounds token cost; graphify's internal traversal handles routing from any entry. Risk is low; can be revisited if retrieval quality drops.
  • [Risk] routing rule in ~/.claude/CLAUDE.md is invisible to models that don't read it → mitigated by both skills referencing the routing rule location.
  • [Risk] graphify-out/ accidentally committed → .gitignore entry is step 3 of onboard; skill states "never commit" explicitly.
  • [Trade-off] No automatic freshness — graphs stale after significant refactors → accepted (ADR-013 laziness principle); graphify update . is cheap and Claude can suggest it.