halaprix

bd-graph

Community halaprix
Updated

Temporal knowledge graph over a beads (bd) issue tracker — built by your coding agents, queried over MCP, no LLM API keys

bd-graph

A temporal knowledge graph over your beadsissue tracker — built by coding agents, queried over MCP, no LLM API keys required.

Your bd store accumulates decisions, invariants, supersessions, and provenance —but keyword search can't answer shape questions: which rules currently governthis component, and since when? Was that memory superseded? Which lastingdecisions came out of that epic? bd-graph derives a Neo4j graph from your bdcorpus (issues, memories, ADRs) that answers exactly those, and exposes it tocoding agents through a read-only MCP server.

The temporal layer is the point: edges carry valid_from / invalid_at, andSUPERSEDES / INVALIDATES edges record when guidance flipped — so agentsretrieve the current rule instead of a stale one.

The graph is a derived, disposable index. bd stays the source of truth.Rebuild it any time with one command; never write project state to it.

How it works

bd store ──export──▶ corpus/ ──┬─▶ load_p1.py  (deterministic: structure + regex)
docs/adr ──copy───▶            └─▶ load_p2.py  (semantic: agent-extracted JSON)
                                        │
                     Neo4j  ◀───────────┘
                       ▲
        mcp-neo4j-cypher (read-only MCP) ◀── your coding agents

Phase 1 — deterministic (no LLM). Issue dependency trees (CHILD_OF,DEPENDS_ON, DISCOVERED_FROM), ADR→issue tracking links, ADR supersessionstatus lines, and regex cross-mentions between issues/ADRs/memories/PRs. Thisalone is ~90% of the edges.

Phase 2 — semantic (agents, not APIs). Your coding agents (Claude Codesubagents, Codex, whatever you run) extract Component and Rule entities andGOVERNS / ESTABLISHES / SUPERSEDES / INVALIDATES edges with dates, usingthe prompt template in prompts/extraction.md. Because the extractor is youragent harness, this costs subscription tokens — no OPENAI_API_KEY, noembeddings provider, nothing.

Precision pass. A second wave of agents adversarially verifies everyextracted edge against its source (prompts/verification.md); apply_verdicts.pydeletes refuted edges and tags unverifiable ones confidence: "unsupported".In practice verifiers kill 5–15% of edges — mostly fabricated dates andmisattributed components.

Data model

Node Key From
Issue id every bd issue incl. closed (title, status, dates, close_reason, summary)
Memory key bd memories --json
ADR id NNNN-slug.md files (title, status, date)
PR number regex over all text
Component, Rule name Phase-2 extraction
Meta freshness stamp: generated_at, corpus counts

Phase-1 edges: CHILD_OF, DEPENDS_ON, DISCOVERED_FROM, TRACKED_IN,SUPERSEDES (ADR status lines), MENTIONS, REFERENCES_PR.Phase-2 edges: ABOUT, ESTABLISHES, GOVERNS, CONSTRAINS, SUPERSEDES,INVALIDATES, PART_OF — each with fact, valid_from, invalid_at,confidence, source.

Quickstart

Requirements: Python ≥3.11, Docker, a beads store (tested against bd 1.1.0);pipx install mcp-neo4j-cypher for the MCP server (no pipx? python3 -m pip install --user pipx first).

git clone <this repo> && cd bd-graph
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt

docker run -d --name bd-graph-neo4j --restart unless-stopped \
  -p 127.0.0.1:7474:7474 -p 127.0.0.1:7687:7687 \
  -v bd-graph-data:/data -e NEO4J_AUTH=neo4j/<pick-a-password> neo4j:5-community

cp config.example.toml config.toml   # edit: id_prefix, password, repo_root, vocab
                                     # repo_root IS REQUIRED for the first run —
                                     # it's what lets regenerate.sh export your corpus
mkdir -p corpus extracted
./regenerate.sh                       # exports corpus, builds Phase 1
.venv/bin/python test_graph.py        # structural + recall assertions

Then wire the MCP server into your agent tool (Claude Code shown):

claude mcp add bd-graph --scope local -- mcp-neo4j-cypher \
  --db-url bolt://localhost:7687 --username neo4j --password <password> \
  --database neo4j --transport stdio --read-only

For Phase 2, dispatch extraction agents with prompts/extraction.md, verifywith prompts/verification.md, then:

.venv/bin/python apply_verdicts.py && ./regenerate.sh

Try it without a bd store

demo/ contains a synthetic corpus (5 issues, 3 memories, 2 ADRs, a sampleextraction) — setup commands in demo/config.demo.toml. The demo exercisesevery edge type including a supersession chain.

Example queries

// pre-flight: what binds this component, and since when
MATCH (r:Rule)-[g:GOVERNS|CONSTRAINS]->(c:Component {name:'Api'})
OPTIONAL MATCH (src)-[e:ESTABLISHES]->(r)
RETURN r.name, g.fact, e.valid_from, coalesce(src.id, src.key);

// staleness chain: what superseded what, in date order
MATCH (a)-[s:SUPERSEDES|INVALIDATES]->(b)
RETURN coalesce(a.id,a.key,a.name), type(s), s.valid_from,
       coalesce(b.id,b.key,b.name) ORDER BY s.valid_from;

// epic rollup: lasting decisions that came out of an epic
MATCH (adr:ADR)-[:TRACKED_IN]->(:Issue)-[:CHILD_OF*1..2]->(:Issue {id:'demo-ep1'})
MATCH (adr)-[:ESTABLISHES]->(r:Rule) RETURN adr.id, r.name;

// issue provenance: where it came from, what it left behind
MATCH (i:Issue {id:'demo-bug7'})
OPTIONAL MATCH (i)-[:DISCOVERED_FROM]->(p)
OPTIONAL MATCH (i)-[:REFERENCES_PR]->(pr)
RETURN p.id, collect(pr.number);

Keeping it honest

  • Freshness is queryable in-band: MATCH (m:Meta) RETURN m.generated_at, m.issues. Tell your agents to check it at first use per session.

  • ./doctor.sh names the failing layer (container / bolt / data /staleness) with the exact fix command; exit 0/2/1 = healthy/stale/broken.--full chains both test suites.

  • test_graph.py asserts corpus↔graph parity, dependency-edge parity,no dupes/self-loops, ISO dates, all corpus supersession lines present — plusany project-specific [[probes]] you define in config.

  • test_mcp.py drives the MCP server over raw stdio JSON-RPC and provesthe write path is closed.

  • Suggested agent-instruction snippet (CLAUDE.md / AGENTS.md):

    Use the bd-graph MCP for shape questions over the tracker (what governs acomponent, supersession chains, epic rollups, provenance). It is a derivedindex — on any mismatch trust bd. Check Meta.generated_at at first use;on any problem run doctor.sh and say explicitly that you're falling backto the bd CLI. Never fail silently.

Design notes & limitations

  • Recall is deliberately partial (~8 edges/doc): the graph is a map, not asubstitute for reading the document it points to.
  • ADR parsing assumes the common # ADR-NNNN: title + - **Status:** / - **Date:** / - **Tracked in:** header block; adjust ADR_META in load_p1.py forother formats. Duplicate ADR numbers merge into one node — treat that as alint error in your repo.
  • Extraction quality depends on your [vocab] component list; keep it shortand canonical.
  • Inspired by the Graphiti/Neo4j temporal-graph approach(getzep/graphiti); this project tradesGraphiti's embedding-based hybrid search for zero API keys andagent-native extraction. If you have API keys and want semantic search,Graphiti is the heavier-duty option.

Security

Everything is local-only by design: Neo4j binds to 127.0.0.1, the MCP serveris registered --read-only, and config.toml (credentials, project vocab) isgitignored. Your corpus (corpus/, extracted/) contains your project'sinternal knowledge — both are gitignored; never commit or publish them.Note that mcp-neo4j-cypher takes the password as a CLI argument (visible inps on the local machine) — one more reason the password must be alocal-only throwaway, never a reused credential.

License

MIT

MCP Server · Populars

MCP Server · New

    gura105

    Operational Ontology

    A minimal, readable reference implementation of the Operational Ontology pattern. Palantir Foundry is one implementation; this is the concept, minimized.

    Community gura105
    EllisMorrow

    Caelune

    Caelune (星野) — Local-first retrieval for private Markdown, PDF, and Tika documents, with a Windows desktop app and read-only MCP server.|本地优先的私人知识检索工具。

    Community EllisMorrow
    vmware-skills

    VMware AIops

    VMware vCenter/ESXi AI-powered monitoring and operations. Two skills: vmware-monitor (read-only, safe) and vmware-aiops (full operations) | Claude Code Skill

    Community vmware-skills
    asdecided

    AsDecided

    Native deterministic requirements-as-code engine and read-only MCP server.

    Community asdecided
    Mapika

    portview

    See what's on your ports, then act on it. Diagnostic-first port viewer for Linux, MacOS and Windows.

    Community Mapika