Replace Ruby tag-index CLI with Graphify knowledge graph

Graphify eliminates the need for the Ruby/SQLite tag index (Step 2 on
the critical path). It provides entity extraction and relationship
inference over vault docs via a local SLM, and deterministic code
graphs for projects via AST — both at significantly lower complexity.
This commit records the architecture decision and evaluation that
justifies the pivot.

Vault graphs still require author-maintained summaries (human router
hint), but tagging discipline is now optional. Project code graphs are
free (no LLM cost). Stale-node drift requires periodic `--force`
rebuilds; strategy documented for SessionStart hooks.

The three-layer memory system remains unchanged: episodic (memsearch),
knowledge (Graphify + vault), integration (custom glue). See
06-graphify-evaluation.md for the open questions and limitations.
This commit is contained in:
jared 2026-06-03 17:36:12 -04:00
parent 54b00364cd
commit 2bc95ed30e
2 changed files with 318 additions and 83 deletions

View File

@ -8,66 +8,149 @@ skills.
> This is a build outline, not the implementation plan. The next session should turn this into
> a proper implementation plan (writing-plans skill) and execute it.
**Architecture decision (2026-06-03):** Graphify replaces the Ruby/SQLite tag index.
The Ruby CLI (old Step 2) is skipped. Graphify handles both knowledge-graph queries over the
vault and free AST-based code graphs per project. The deferred QMD semantic layer (old Step 7)
is also skipped — Graphify covers it without vectors. See `06-graphify-evaluation.md` for
the full rationale.
---
## Part A — Build order (human builder's path)
Build bottom-up: the vault and CLI first (usable standalone), then the hooks, then the plugin
that packages it.
Build bottom-up: the vault and Graphify first (usable standalone), then the hooks, then the
plugin that packages it.
### Step 1 — Vault skeleton & conventions
- Decide the vault location (default: a synced home dir, e.g. `~/brain`; symlink into
`~/.claude/memory` only if a tool insists). **Vault is the single source of truth.**
- Write `CONVENTIONS.md` in the vault: the frontmatter contract and the tag namespaces
(`tool/`, `client/`, `domain/`, `convention/`, `scope/`). This doubles as the spec the
skills teach the AI.
- Seed a few real notes (e.g. `tool/semrush` global + a `client/<x>` project note) to test
against.
- Write `CONVENTIONS.md` in the vault: the frontmatter contract. The required fields are
`summary` (one-line, author-written — this is the human-readable router hint Graphify
does not generate) and `scope` (`scope/global` or `scope/project`). Tags are now
supplementary, not the primary query mechanism.
- Seed a few real notes (e.g. `tool/semrush`, `client/<x>`) to use as extraction test cases
in Step 2.
### Step 2 — The Ruby tag-index CLI (the core build)
- Ruby project, `sequel` + `sqlite3` gems. SQLite file in a cache dir (e.g.
`~/.cache/memory-index/index.sqlite`) — disposable, never synced.
- **Schema / migrations**: `files(id, path, mtime, summary, scope)`, `tags(id, name)`,
`files_tags(file_id, tag_id)`; `many_to_many` between files and tags.
- **Frontmatter parser**: read YAML frontmatter from a `.md` file → `{summary, scope, tags[]}`.
Fail loudly (or quarantine) notes missing the required `summary`/tags so the contract is
enforced.
- **Commands** (a thin CLI dispatch — `thor`/`optparse` or plain):
- `index update --since <iso8601|auto>` — find `.md` with `mtime >` last-cache-time, upsert
them; **reconcile**: delete rows for paths no longer on disk.
- `index update --file <path>` — upsert a single file (used by the write hook); prune if the
path is gone.
- `index update --rebuild` (default off) — drop & rebuild from a full vault scan.
- `index query --client X --tool Y [--domain Z] [--scope global]` — AND the filters; output
JSON lines of `{path, summary, tags[]}` (option C).
- `index tags [--namespace tool/]` — enumerate the vocabulary (virtual index).
- Store `last_cache_time` (a tiny meta table or a stamp file) so `--since auto` works.
- **Tests**: create/edit/delete/rename a note, assert the index reflects it; rebuild equals
incremental.
### Step 2 — Graphify + Ollama setup (the knowledge graph layer)
This replaces the Ruby tag-index CLI. Graphify builds a knowledge graph over vault docs via a
local SLM, and a free code graph over project files via AST.
#### 2a — Install Graphify
```
pip install graphify # or follow current install docs
```
Verify: `graphify --version`
#### 2b — Configure Ollama for extraction
The 2024 approach (Modelfile with `PARAMETER num_ctx`) still works but the preferred
programmatic method is now per-request via the API (Graphify supports this via
`GRAPHIFY_OLLAMA_NUM_CTX`):
```bash
# Set in your shell profile or service env:
OLLAMA_FLASH_ATTENTION=1 # 30-50% VRAM savings on KV cache — always set this
GRAPHIFY_OLLAMA_NUM_CTX=8192 # 8K is sufficient for vault notes (200-2000 words)
# and leaves comfortable headroom for prompt overhead
```
To verify context is being used: `ollama ps` shows allocated context after first call.
Available models (as of 2026-06-03, in order of interest):
- `gemma4:e2b` — 7.2 GB, ~2B effective params, 128K native window, fast; **start here**
- `qwen3.5:2b` — 2.7 GB, smallest, good fallback if VRAM is constrained
- `gemma4:e4b` — 9.6 GB, more capable, slower
#### 2c — Model benchmarking (before committing to a model)
Run a small extraction test across all local models plus the three Claude API models. The goal
is to find the best speed/accuracy tradeoff for entity+relationship extraction from vault notes.
**Test set:** 510 representative vault notes spanning different note types (tool note, client
note, convention note, domain note). Include one note that is dense with relationships.
**What to measure per model:**
1. Extraction speed (tokens/sec or wall-clock time per note)
2. Entity quality: are the right concepts extracted? Any hallucinated entities?
3. Relationship quality: are edges plausible and correctly typed? Missing relationships?
4. Confidence tag accuracy: are `INFERRED` vs `AMBIGUOUS` edges appropriately flagged?
**Models to test:**
| Model | Backend | Notes |
|---|---|---|
| `gemma4:e2b` | Ollama local | Primary candidate — fast, 7.2 GB |
| `qwen3.5:2b` | Ollama local | Smallest, fastest |
| `gemma4:e4b` | Ollama local | Highest local quality |
| `claude-haiku-4-5` | Claude API | Baseline API option |
| `claude-sonnet-4-6` | Claude API | Mid-tier reference |
| `claude-opus-4-8` | Claude API | **Gold standard** — judge quality against this |
Run using subagents in Claude Code: dispatch one agent per model, each extracting the same
test set, return structured JSON of entities+relationships. Review god-node quality in
`GRAPH_REPORT.md` after each run. Use Opus output as the scoring rubric for the local models.
**Decision rule:** Choose the fastest local model whose entity/relationship quality is
"close enough" to Opus (subjective; likely Gemma4:e2b or Gemma4:e4b based on the description).
API models are a fallback option for high-stakes notes, not the default.
#### 2d — Initial vault graph build
```bash
graphify extract --path ~/brain --backend ollama --model gemma4:e2b \
--token-budget 512 --max-concurrency 2
```
Tune `--token-budget` (semantic chunk size) and `--max-concurrency` based on VRAM headroom.
Review `GRAPH_REPORT.md` — check god nodes make sense (they should be your most-connected
tools, clients, and domain concepts).
#### 2e — Per-project code graphs (free, no model needed)
For each client project:
```bash
graphify extract --path ~/projects/<client>/<project> --no-docs
```
`--no-docs` skips LLM extraction; only AST is run. Zero token cost. Add `--update` on
subsequent runs; use `--force` when you've deleted files (to clear stale nodes).
Store each project's `graphify-out/` alongside the project, or in a configurable cache dir.
Keep per-project graphs separate — do not merge client projects into one graph.
### Step 3 — Hooks (maintenance + retrieval)
See Part C for exact mapping. Implement as small shell wrappers that call the Ruby CLI:
- `pre-tool-memory` style **PostToolUse** updater (write path → `index update --file`).
- **SessionStart** reconcile + inject (index overview + resolved `convention/*` files + journal
pointer).
- **SessionEnd** journal appender (daily note with pointers).
Hooks now call Graphify instead of the Ruby CLI.
- **PostToolUse** (on Write/Edit of vault `.md`): `graphify update --file <path>` to merge
the changed note into the vault graph. Note: Graphify's `--update` does not prune deleted
nodes — a periodic `--force` rebuild (e.g. weekly, or triggered by SessionStart stale
check) is needed to clear ghost nodes.
- **SessionStart**: reconcile (check vault graph mtime vs last rebuild; trigger `--force` if
stale threshold exceeded) + inject context (query MCP server for god nodes + inject
`convention/*` note summaries + journal pointer).
- **SessionEnd**: append daily journal note with pointers to vault notes touched.
**Stale-node mitigation strategy:** track last `--force` rebuild time in a stamp file
(e.g. `~/.cache/graphify/vault-rebuild.stamp`). SessionStart hook triggers `--force` if
older than N days (7 is a reasonable starting point).
### Step 4 — Episodic layer (memsearch)
- Install memsearch (`/plugin marketplace add zilliztech/memsearch`, then `plugin install
memsearch`), local to start. Verify daily memory files appear after a few conversations.
- Decide whether memsearch indexes our session-end journal notes or its own capture (likely its
own; our journal can point into the knowledge vault).
- Graphify does **not** replace memsearch here. Time-anchored semantic queries ("what was I
working on last Tuesday?") are better served by vector similarity over session logs.
### Step 5 — Sync
- Pick **git** (versioned, hourly push/pull) or **Syncthing** (continuous, zero-thought) for the
vault → VPS. Configure on each machine. **Do not sync the SQLite/Milvus caches.**
- Pick **git** (versioned, hourly push/pull) or **Syncthing** (continuous, zero-thought) for
the vault → VPS. Configure on each machine.
- **Do not sync** the Graphify `graphify-out/` directories, Milvus caches, or the Ollama
models. Graphs are rebuilt per machine from the vault (the single source of truth).
### Step 6 — Package as a global plugin (Part D)
- Wrap Steps 23 into a Claude Code plugin with skills; install at user level.
### Step 7 (deferred) — QMD semantic layer
- Only when structured-only retrieval misses notes you know exist: `qmd` over the vault,
optionally as an MCP server the AI can query.
### Step 7 — (SKIPPED) QMD semantic layer
Covered by Graphify. The knowledge-graph approach provides structured semantic retrieval
without vectors. Only revisit if Graphify's graph queries prove insufficient for a use case
where embedding similarity would outperform graph traversal.
---
@ -82,74 +165,109 @@ project-ephemeral state (that's the episodic layer / project files). Concretely:
**What conventions to follow when writing** (enforced by the frontmatter contract):
- One concept per note; keep notes small (the L1 "under ~200 lines / one topic" discipline).
- **Required frontmatter**: a one-line `summary` (written now, not deferred), `scope/global`
or `scope/project`, and namespaced tags (`tool/…`, `client/…`, `domain/…`, optionally
`convention/…`).
- **Scope rule**: default new tool/domain knowledge to `scope/global`; mark `scope/project` +
a `client/<name>` tag when it's specific to how a client uses something.
- **Required frontmatter**: a one-line `summary` (written now, not deferred — this is the
human-authored router hint; Graphify extracts entities but does not write summaries),
and `scope/global` or `scope/project`.
- **Scope rule**: default new tool/domain knowledge to `scope/global`; mark `scope/project`
when it's specific to how a client uses something.
- **Write only to the vault**, never silently into a project repo.
- **Promotion to global** (project → global) and **consolidation** are *not* done inline —
they happen in the reorganize step (Part C), in plan mode, for human review.
- **Promotion to global** and **consolidation** happen in the reorganize step (Part C), in
plan mode, for human review.
### When & how the AI QUERIES
- **At session start**: the injected index overview + resolved `convention/*` files tell it
what's available without reading everything.
- **On demand, during a task**: when the task touches a tool/client/domain, run
`index query --tool semrush --client sesame3g` → get `{path, summary, tags}` → open only the
files whose summary matches. This is the progressive-disclosure loop that keeps tokens low.
- **Cross-client lookups**: query by `--tool` alone (omit client) to surface what was learned
with *any* client; tags in the output show provenance.
- **"What happened" questions** go to the **episodic layer (memsearch)** in natural language,
not the tag index.
**Knowledge queries (vault graph)** via Graphify CLI (Bash tool):
- `graphify query "how do we authenticate with SEMrush?"` — semantic graph search
- `graphify path "client/sesame3g" "tool/semrush"` — how these two concepts connect
- `graphify explain "convention/seo-workflow"` — node deep-dive with neighbors
- Add `--budget N` to cap answer size (default ~2000 tokens); `--dfs --budget N` for bounded traversal
- Add `--graph <path>` to query a specific project's `graph.json` instead of the vault graph
**At session start**: god-node summary (injected by hook from `GRAPH_REPORT.md`) gives the
architecture spine — what are the highest-connectivity concepts in the vault. The AI then
queries specific nodes on demand rather than reading everything.
**On demand, during a task**: run `graphify query` when the task touches a tool/client/domain.
The graph returns relevant node clusters; the AI opens only the vault notes whose `summary`
matches the task. The `summary` frontmatter field remains the human-written progressive-disclosure hint.
**Cross-client lookups**: `graphify query "tool semrush"` returns all nodes connected to the
SEMrush concept, regardless of which client project they came from. Graph edges show provenance.
**"What happened" questions** go to **memsearch** in natural language — not the graph.
---
## Part C — Hooks & CRUD mapping
CRUD over the knowledge vault, and which hook/command services each operation:
| Operation | Trigger | Mechanism |
|-----------|---------|-----------|
| **Create** | AI writes a new note | AI writes `.md` (Write tool) → **PostToolUse** hook → `index update --file` |
| **Read / query** | AI needs knowledge | AI calls `index query …` (no hook; on-demand CLI) |
| **Update** | AI/user edits a note | AI edit → **PostToolUse** hook → `index update --file`; user edit → **SessionStart** reconcile |
| **Delete / rename** | note removed/renamed | covered by `--file` (prune) on AI ops; by **SessionStart** reconcile (prune vanished paths) on manual ops |
| **Inject** | new session/sub-agent starts | **SessionStart** hook injects index overview + resolved `convention/*` + journal pointer |
| **Create** | AI writes a new vault note | AI writes `.md` (Write tool) → **PostToolUse** hook → `graphify update --file` |
| **Read / query** | AI needs knowledge | AI runs `graphify query` / `graphify explain` via Bash (no hook; on-demand) |
| **Update** | AI/user edits a note | AI edit → **PostToolUse** `graphify update --file`; user edit → **SessionStart** reconcile |
| **Delete / rename** | note removed/renamed | `graphify update --file` prunes AI-deleted paths; **SessionStart** triggers `--force` rebuild if stale (catches manual deletes) |
| **Inject** | new session starts | **SessionStart** hook: god-node summary + `convention/*` summaries + journal pointer |
| **Journal** | session ends | **SessionEnd** hook appends a dated journal note with pointers |
| **Reorganize** | periodic, user-invoked | `reorganize memory` run in **plan mode**: dedupe, merge, split, re-tag, promote `scope/global`, rebuild index — human approves |
| **Reorganize** | periodic, user-invoked | `reorganize memory` in **plan mode**: dedupe, merge, split, re-scope, then `graphify --force` to rebuild clean graph — human approves |
| **Stale graph rebuild** | SessionStart stale check | If rebuild stamp > N days old: `graphify --force` on vault; resets stamp |
Hooks are thin shell wrappers over the Ruby CLI so the logic lives in one place.
Hooks are thin shell wrappers; the logic lives in Graphify.
**Hooks summary:**
- **SessionStart**reconcile (`index update --since auto`) + inject context.
- **PostToolUse** (on `Write`/`Edit` of vault `.md`) — `index update --file`.
- **SessionStart**stale check + `--force` if needed, then inject (god nodes + conventions + journal pointer).
- **PostToolUse** (on `Write`/`Edit` of vault `.md`) — `graphify update --file`.
- **SessionEnd** — append daily journal note.
- (memsearch brings its own `UserPromptSubmit` + capture hooks for the episodic layer.)
- (memsearch brings its own hooks for the episodic layer.)
---
## Part D — Claude Code plugin with skills (global install)
Goal: one global install so every project/machine knows the vault, conventions, hooks, and CLI.
Goal: one global install so every project/machine knows the vault, conventions, hooks, and
Graphify config.
**Plugin contents:**
- **Hooks** registered in settings: SessionStart, PostToolUse, SessionEnd (the shell wrappers
from Part C), pointed at a configurable vault path + cache dir.
- **The Ruby CLI** (the tag index) bundled or installed as a dependency, on `PATH`.
- **Hooks** registered in settings: SessionStart, PostToolUse, SessionEnd (shell wrappers
from Part C), pointed at a configurable vault path + Graphify output dir.
- **Graphify CLI** on `PATH` — the AI uses the Bash tool to run `graphify query`,
`graphify path`, `graphify explain` directly. No server process. Project-specific graphs
are queried with `--graph <path>` pointing at the project's `graphify-out/graph.json`.
- **Skills** (these carry the *know-how* to the model):
- `memory-write` — when to record evergreen knowledge, the frontmatter contract, scope rules,
"vault not repo." (Part B write section.)
- `memory-query` — how/when to query the tag index vs the episodic layer; the progressive-
disclosure loop; cross-client lookups. (Part B query section.)
- `memory-reorganize` — the plan-mode consolidation/promotion procedure + guardrails.
- **Config**: vault path, cache path, sync method — set once at user level.
- `memory-write` — when to record evergreen knowledge, the frontmatter contract (summary
required, scope rule), "vault not repo."
- `memory-query` — how/when to use `graphify query` vs memsearch; god-node discipline;
`--budget`/`--dfs` usage; cross-client lookups via `--graph`; progressive-disclosure
via summary field.
- `memory-reorganize` — the plan-mode consolidation/promotion procedure + guardrails;
when to trigger `graphify --force` rebuild.
- **Config**: vault path, Graphify output dir, Ollama model name, `num_ctx`, rebuild-stale
threshold in days — set once at user level.
- **Env vars** set by plugin: `OLLAMA_FLASH_ATTENTION=1`, `GRAPHIFY_OLLAMA_NUM_CTX=8192`,
`GRAPHIFY_OLLAMA_KEEP_ALIVE=5`.
**Why a plugin + skills (not just CLAUDE.md):** hooks must be registered by the harness (the
plugin does that), and the conventions are taught as skills so they load on demand without
bloating every project's context. A single global install keeps the conventions themselves a
single source of truth — edit the skill once, every project follows.
**Why a plugin + skills (not just CLAUDE.md):** hooks must be registered by the harness;
conventions taught as skills load on demand without bloating every project's context. A single
global install keeps conventions a single source of truth.
**Open question for build time**: do the coding-`convention/*` notes live *in the vault* (data,
edited freely, resolved by the SessionStart hook) while the *memory-system skills* live *in the
plugin* (behavior, versioned)? Recommended: yes — conventions are data in the vault; the skills
are the mechanism.
**Convention notes placement:** coding `convention/*` notes live as **data in the vault**
(edited freely, resolved by SessionStart hook); memory-system **skills live in the plugin**
(behavior, versioned).
---
## Open questions (carried from 05-handoff.md + updated)
1. **Vault location**`~/brain` (synced home dir)? Symlink into `~/.claude/memory`?
2. **Sync mechanism** — git (versioned, hourly) vs Syncthing (continuous)?
3. **Stale rebuild threshold** — how many days before SessionStart triggers `--force`?
7 days is the starting guess; tune after observing drift in practice.
4. **Per-project graph path** — how does the AI know which `graph.json` to pass to
`--graph` for the current project? Convention: `<project-root>/graphify-out/graph.json`,
injected by SessionStart hook if a project graph exists at that path.
5. **Summary field ownership** — Graphify extracts entities but does NOT write summaries.
The human (or AI, on vault note creation) must write the `summary` frontmatter. Confirm
this discipline holds in practice.
6. **Model benchmark results** — defer all model decisions until Step 2c benchmark is done.
Don't hardcode `gemma4:e2b` until testing confirms it's the right pick.
7. **memsearch + journal** — does memsearch index our SessionEnd journal notes, or only
its own auto-capture? See `05-handoff.md:55-56`.

View File

@ -0,0 +1,117 @@
# Graphify Evaluation: Fit for the Three-Source Memory System
> Evaluated: 2026-06-03. Source docs: `/docs/graphify/` (0009 + external-tips).
---
## Summary Verdict
**Graphify is a strong fit for Layer 2 (knowledge) and a natural fit for project-file code analysis. It is NOT the right tool for Layer 1 (episodic/session logs), and it does not "connect" the three sources on its own — that bridge still needs custom glue.**
---
## What Graphify Actually Is
Graphify builds a knowledge graph from code and documents:
- **Nodes**: entities (functions, classes, concepts, topics)
- **Edges**: typed relationships with confidence tags (`EXTRACTED` = deterministic AST, `INFERRED` = LLM, `AMBIGUOUS` = flagged)
- **Storage**: `graph.json` + optional exports (Obsidian sidecar, GraphML, Cypher)
- **Query**: semantic graph traversal (`query`, `path`, `explain`) — not vector/embedding search
- **MCP server**: `graphify.serve` exposes `query_graph`, `get_node`, `shortest_path` as Claude tools
The core cost split:
- **Code** → tree-sitter AST, 33 languages, deterministic, **zero LLM cost**
- **Docs** → LLM entity extraction, can use local SLMs via Ollama (`--backend ollama`)
---
## Fit by Layer
### Layer 1: Episodic ("what happened") — memsearch / Milvus Lite
**Graphify is not the right tool here.**
Episodic queries are time-anchored semantic lookups: "what was I working on last Tuesday?", "what client did we discuss the Stripe integration for?" Vector similarity over session logs is well-matched to this. A knowledge graph of session entities would add build overhead without improving recall for timeline queries. **Keep memsearch.**
### Layer 2: Knowledge ("how do we…") — Obsidian vault + tag index
**Graphify is a strong candidate to replace or complement the tag index.**
**What it replaces:** The tagging-discipline requirement. Instead of manually adding `#tool/semrush #client/sesame3g` to every note, a local SLM (Ollama + Qwen2.5 7B or Phi-4 14B) extracts entities automatically. You get entity nodes and relationship edges from the vault without frontmatter authoring.
**What it adds that tags cannot:** Inferred cross-note relationships. Tags only filter ("give me notes tagged tool/semrush"). A graph can say "tool/semrush is connected to client/sesame3g via 3 project notes, and both reference convention/seo-workflow." That's a graph query, not a tag query.
**What it does NOT replace:** The `summary` column in the tag index schema, which is a human-written first-class router hint. Graphify extracts entities, not prose summaries. If summaries are the primary token-efficiency mechanism (see `02-system-design.md:98-102`), they need to remain author-controlled.
**Critical limitation:** Stale node drift. Graphify's `--update` does not prune deleted symbols/notes — you must `--force` rebuild to clear ghost nodes. The current design's SQLite is explicitly disposable-and-rebuildable from frontmatter; a Graphify graph is a snapshot with known drift. This is a real tradeoff.
**Recommendation:** Use Graphify's Obsidian sidecar export (`--obsidian`) to augment vault notes with auto-extracted entity metadata, and the MCP server for graph queries. Keep the summary frontmatter field as author-controlled. Consider Graphify as the **semantic enrichment step** that the deferred QMD layer was meant to fill — but without vectors.
### Project Files (code) — currently unindexed
**Graphify is a no-brainer add here.**
Project-file code analysis via AST is free (no LLM, no API key needed at runtime), deterministic, and produces exactly the call-graph / symbol map that "what does this codebase do?" queries need. Every client project gets a `graph.json` at zero ongoing cost. Query via the MCP server.
**Limitation from issue #1122:** `graphify extract` demands a backend credential even for pure-code extraction. Workaround: set a dummy key or use `--backend ollama` with a running (or not) Ollama instance — confirm at build time.
---
## The "Three Sources Connected" Question
Graphify does **not** natively connect three separate graphs. It builds one graph per ingestion run. To connect project files, vault, and session logs in one queryable surface, you'd need:
1. **A combined ingestion run** that points at all three source trees, OR
2. **Three separate graphs** queried via three MCP tool instances and synthesized at the Claude layer
Option 1 risks cross-contamination of unrelated client projects. Option 2 is the safer model: each source has its own graph, and Claude stitches results from three MCP calls.
The more honest framing: Graphify replaces tags as the **vault entity index**, adds a **free code graph per project**, and leaves episodic (memsearch) alone. That's a meaningful simplification — you no longer need the Ruby/SQLite tag index CLI — but it's a layer replacement, not a unified connector.
---
## What Changes in the Current Design
| Current design | With Graphify |
|---|---|
| Ruby/Sequel/SQLite tag index CLI | Replaced by `graphify query` + MCP server |
| Manual `#tool/ #client/ #domain/` tagging discipline | Auto-extracted by local SLM on vault ingestion |
| `summary` frontmatter (author-written, router hint) | Unchanged — Graphify doesn't generate these |
| QMD semantic layer (deferred) | Graphify fills this role without vectors |
| memsearch (episodic) | Unchanged |
| Project files (unindexed) | Free code graph via AST |
**What's saved:** The entire Ruby CLI build (Step 2 on the critical path in `04-build-plan.md`) could be skipped. That's significant scope reduction.
**What's added:** A local Ollama SLM running on this machine for vault doc extraction. This is a new infrastructure dependency. On low-RAM machines, a 7B model at 4-bit takes ~5 GB VRAM/RAM.
---
## Open Questions This Creates
1. **Rebuild strategy**: How often do you rebuild the vault graph? On every SessionStart (expensive), on vault git commit (right cadence), or manually? The `--update` flag helps but stale-node drift means periodic `--force` rebuilds are needed.
2. **Model choice for vault extraction**: No official recommendation. Test Qwen2.5 7B and Phi-4 14B against a sample of your vault notes and review god-node quality before committing.
3. **Summary field fate**: If Graphify extracts entities but doesn't write summaries, does the human still maintain summary frontmatter? Or does a local SLM generate those too?
4. **Cross-client isolation**: Project code graphs should be per-client-project, not merged. How do you namespace them? Separate `graphify-out/` per project? Or a single graph with source labels as node properties?
5. **MCP server management**: Running `graphify.serve` for vault + N project graphs means N+1 MCP server instances. Is that manageable, or do you build a single meta-server?
---
## References
| Topic | Source |
|---|---|
| Code AST extraction (free, deterministic) | `docs/graphify/03-ingesting-code-ast.md:9100` |
| Local SLM (Ollama) setup | `docs/graphify/05-local-models-and-backends.md:63156` |
| Query verbs + bounded traversal | `docs/graphify/06-querying-and-god-nodes.md:5193` |
| Stale node drift limitation | `docs/graphify/07-token-economics-and-updates.md:136148` |
| Token savings by repo size | `docs/graphify/external-tips.md:3145` |
| Tag index schema and role | `docs/memory-system/02-system-design.md:95113` |
| Graph rejection decisions (LightRAG) | `docs/memory-system/03-architecture-decisions.md:83, 145` |
| Critical path (Ruby CLI = Step 2) | `docs/memory-system/04-build-plan.md` |
| Open handoff questions | `docs/memory-system/05-handoff.md:4760` |