13 KiB
Implementation Process
Last updated: 2026-06-04 | Status: Ready to plan — awaiting Step 2c benchmark results
This document distills 04-build-plan.md into a concrete, staged build process and folds in
two locked decisions: ADR-011 (faceted six-namespace taxonomy) and ADR-012 (reuse the
existing ~/Documents/SecondBrain vault rather than creating a new one). Read 04-build-plan.md
for the underlying rationale, query/CRUD conventions, and plugin internals; read
03-architecture-decisions.md for the decision log. This document is the runbook.
This is still a build process outline, not a detailed implementation plan. The recommended next move is to feed Step 2 (the critical path) into the writing-plans skill to produce an executable, task-level plan. Most open questions in Steps 3–6 can be defaulted; Step 2c's model benchmark is the genuine gate that the rest depends on — do not hardcode a model before it runs.
Build order
Bottom-up: vault migration first (usable standalone), then Graphify, then hooks, then plugin.
Step 1 — Adopt and migrate the SecondBrain vault
Per ADR-012: reuse ~/Documents/SecondBrain as the knowledge vault rather than creating a
new ~/brain. The vault is already flat, already scoped to durable knowledge, and already
articulates the correct governance philosophy. Migration cost is mechanical.
1a — Initialize git
The vault has no .git yet. Initialize it so ADR-008's sync strategy works:
git init ~/Documents/SecondBrain
1b — Update vault governance notes
Update three files to the new schema:
CLAUDE.md— update vault path references, Graphify commands, ADR-011 namespace list.vault-conventions.md— update tag-namespace list to the six-facet form; keep the existing "act without being asked" proactive-retrieval section intact (it's better than what cc-os had — adopt it, don't overwrite it).- Project-config hub note(s) — update the tag-inference table values to namespaced form
(e.g.
semrush-work → tool/semrush,pest-control → domain/pest-control). Keep the table; it operationalizes auto-tagging by path pattern and should be preserved.
Frontmatter contract (apply to all notes, new and migrated):
---
summary: "One-line, human-written router hint (required; Graphify does not generate this)"
tags:
- type/<kind> # listed first by convention
- client/<name> # as applicable
- project/<name> # as applicable — first-class for a freelancer
- domain/<topic> # as applicable
- tool/<name> # as applicable
- convention/<name> # as applicable
- scope/global # or scope/project
---
type/ listed first preserves the vault's existing type-first ordering habit and makes note
kind immediately visible.
1c — Migrate existing notes (~20)
For each existing note:
- Add
summary:frontmatter (one line; write it now — it's the human-authored router hint). - Convert flat unnamespaced tags to the six-facet namespaced form. Examples:
research→type/researchpest-control→domain/pest-controlniche-automation-prospecting→domain/niche-automation-prospecting(or split acrossdomain/+project/if the note is project-specific)semrush→tool/semrush
- Add
scope/globalorscope/projectto each note.
Keep 5–10 migrated notes aside as representative test cases for Step 2c's extraction benchmark. Include variety: a tool note, a client/project note, a convention note, a domain note, and at least one note dense with relationships between concepts.
1d — Create _templates for core note types only
Add templates for: research, howto, adr, hub. The long tail stays freeform until a
pattern earns a template (per ADR-011). Consistent per-type structure improves Graphify's
local-SLM extraction reliability.
1e — Fix the broken vault search reference
vault-conventions.md (or CLAUDE.md) currently references
~/.claude/scripts/vault_search.rb, which does not exist. Replace every reference to that
script with graphify query (per ADR-010).
Step 2 — Graphify + Ollama setup (CRITICAL PATH)
This step is the genuine gate. All hook behavior, model selection, and extraction tuning depend on the benchmark in 2c. Do not skip or defer 2c.
2a — Install and verify Graphify
The PyPI package name has a double-y — this is the correct install command:
pip install graphifyy
Verify: graphify --version
2b — Configure Ollama
Set these in your shell profile (or the plugin env block in Step 6):
OLLAMA_FLASH_ATTENTION=1 # 30–50% VRAM savings on KV cache — always set
GRAPHIFY_OLLAMA_NUM_CTX=8192 # 8K is sufficient for vault notes (200–2000 words)
# leaves comfortable headroom for prompt overhead
GRAPHIFY_OLLAMA_KEEP_ALIVE=5 # set when packaging in Step 6
Verify context allocation after the first extraction call: ollama ps shows allocated context.
2c — Model benchmark (THE GATE)
Run a small extraction test before committing to any model. Use the 5–10 representative migrated notes from Step 1c as the test set.
Models to benchmark:
| Model | Backend | Size | Notes |
|---|---|---|---|
gemma4:e2b |
Ollama local | 7.2 GB | Primary candidate — fast, large context |
qwen3.5:2b |
Ollama local | 2.7 GB | Smallest; fallback if VRAM is constrained |
gemma4:e4b |
Ollama local | 9.6 GB | Highest local quality; slower |
claude-haiku-4-5 |
Claude API | — | API baseline |
claude-sonnet-4-6 |
Claude API | — | Mid-tier reference |
claude-opus-4-8 |
Claude API | — | Gold standard — score local models against this |
What to measure per model:
- Extraction speed (wall-clock time per note)
- Entity quality: right concepts extracted, no hallucinated entities
- Relationship quality: edges plausible and correctly typed, no missing key edges
- Confidence tag accuracy:
INFERREDvsAMBIGUOUSappropriately flagged
Decision rule: choose the fastest local model whose entity/relationship quality is "close
enough" to Opus output. Do not hardcode gemma4:e2b — the benchmark decides.
Review god-node quality in GRAPH_REPORT.md after each run. Opus output is the scoring rubric.
2d — Build the initial vault graph
After 2c picks a model:
graphify extract --path ~/Documents/SecondBrain \
--backend ollama --model <chosen-model> \
--token-budget 512 --max-concurrency 2
Review GRAPH_REPORT.md. God nodes should be the most-connected tools, clients, and domain
concepts — confirm they make sense given the vault's content.
2e — Per-project code graphs (free; no model)
For each active client project:
graphify extract --path ~/projects/<client>/<project> --no-docs
--no-docs runs only tree-sitter AST — zero token cost. Use --update on subsequent runs;
use --force when files have been deleted (to clear stale nodes). Keep each project's
graphify-out/ alongside the project; do not merge client projects into one graph.
Step 3 — Hooks
Thin shell wrappers around Graphify. The logic lives in Graphify; the hooks only invoke it.
| Hook | Trigger | Action |
|---|---|---|
| PostToolUse | AI writes/edits a vault .md |
graphify update --file <path> |
| SessionStart | Session opens | Stale check → --force rebuild if needed → inject context |
| SessionEnd | Session closes | Append dated journal note to vault |
Stale-check mechanism (SessionStart): read the mtime of
~/.cache/graphify/vault-rebuild.stamp. If older than N days (7 is the starting guess — tune
after observing drift), run graphify --force on the vault and write a new stamp. Then inject:
god-node summary from GRAPH_REPORT.md + convention/* note summaries + journal pointer.
Note on --update vs --force: graphify update --file does not prune deleted nodes.
Stale/ghost nodes accumulate from manual deletes and renames. The periodic --force rebuild
triggered by the stale check is the mitigation — it rebuilds the graph clean.
Step 4 — Episodic layer (memsearch)
Install memsearch for time-anchored "what happened / what was I working on" queries. Graphify does not replace this — they serve different query patterns (knowledge graph vs timeline recall).
/plugin marketplace add zilliztech/memsearch
plugin install memsearch
Verify daily memory files appear after a few conversations. The open question of whether memsearch indexes SessionEnd journal notes or only its own auto-capture is deferred to build time (see Open questions §7).
Step 5 — Vault sync
Sync the markdown vault to the VPS. Pick one:
- git — versioned, hourly push/pull via cron; explicit audit trail.
- Syncthing — continuous, bidirectional, zero-thought after setup.
What to sync: the vault only (~/Documents/SecondBrain).
What NOT to sync: graphify-out/ directories, Milvus Lite caches, Ollama models. These are
disposable — rebuilt per machine from the vault (markdown is the single source of truth, per
ADR-008).
Step 6 — Package as a global Claude Code plugin
One global install so every project and machine shares the same vault conventions, hooks, and Graphify config.
Plugin contents:
- Hooks registered in settings: SessionStart, PostToolUse, SessionEnd — shell wrappers from Step 3, parameterized by vault path and Graphify output dir.
- Graphify CLI on PATH — the AI calls
graphify query,graphify path,graphify explainvia the Bash tool. No server process per graph; project-specific graphs are queried with--graph <project-root>/graphify-out/graph.json. - Skills (carry the know-how to the model):
memory-write— when to record evergreen knowledge, frontmatter contract, scope rule, vault not repo.memory-query—graphify queryvs memsearch; god-node discipline;--budget/--dfs; cross-client lookups; progressive disclosure viasummary.memory-reorganize— plan-mode consolidation/promotion procedure; when to trigger--forcerebuild; human-approval guardrails.
- Env vars baked in:
OLLAMA_FLASH_ATTENTION=1,GRAPHIFY_OLLAMA_NUM_CTX=8192,GRAPHIFY_OLLAMA_KEEP_ALIVE=5. - Config (set once at user level): vault path, Graphify output dir, Ollama model name, stale-rebuild threshold in days.
Open questions / decisions still to settle
These are deferred to build time. Most can be defaulted without blocking; the only genuine gate is §6 (Step 2c benchmark) — model selection is blocked until it runs.
-
Vault symlink —
~/Documents/SecondBrainis confirmed as the vault (RESOLVED per ADR-012). The open sub-question: symlink it into~/.claude/memoryor not? Only needed if a tool requires that path. -
Sync mechanism — git (versioned, hourly) vs Syncthing (continuous). Both are valid; choose at build time based on preference.
-
Stale rebuild threshold — 7 days is the starting guess. Tune after observing how quickly ghost-node drift becomes noticeable in practice.
-
Per-project graph path convention — how does SessionStart know which
graph.jsonto inject? Proposed convention:<project-root>/graphify-out/graph.json, injected only if the file exists at that path. Not yet made explicit in the plugin spec. -
summaryfield discipline — Graphify extracts entities and edges but does not write summaries. The human (or AI at note-creation time) must writesummary:frontmatter. Confirm this holds in practice and add a lint/reminder to the memory-write skill if it drifts. -
Model benchmark results (Step 2c) — all model choices are deferred until the benchmark runs. Do not hardcode
gemma4:e2b(it's the primary candidate, not the confirmed pick). -
memsearch + journal integration — does memsearch index SessionEnd journal notes or only its own auto-capture? How does the journal pointer injected at SessionStart reference the vault? Nail down at memsearch install time (Step 4).
-
MCP server management — vault graph + N project graphs = N+1 potential instances. The build plan leans toward a single Graphify CLI on PATH with
--graph <path>rather than running multiplegraphify serveinstances, but this is not yet made explicit in the plugin spec. Confirm the CLI-only approach or define the server lifecycle.
Resolved: The type-tag taxonomy is settled via ADR-011 (faceted, six independent namespaces;
type/ listed first). No further debate needed on taxonomy shape.
Recommended next move
Turn Step 2 into a detailed implementation plan via the writing-plans skill. It is the critical path: Graphify install, Ollama configuration, the model benchmark (2c), and the initial graph build are the smallest set of tasks that unblock everything else. Open questions §1–5 and §7–8 can be defaulted or deferred; only §6 (the benchmark) genuinely blocks model-dependent decisions.