Graph Engineering

Graph engineering stops the agent from guessing. Before it edits, every requirement gets a stable id, every code symbol the change might touch becomes a link with its evidence, and the list of those symbols is the only scope the agent may touch. After the merge the links that a test proves become VALIDATED and the ones whose symbol moved become STALE, so the next feature starts from what this one left behind. The method comes from the article Graph Engineering #1 by Pierry Borges, written after a knowledge graph with 19,262 nodes answered every question with nothing because its writer and its reader never agreed on a contract.

Three modes

You pick one per project with /hk:graph, and the installer asks once. off is the default and leaves the pipeline exactly as it is. manifest turns on traceability with no infrastructure and no key. full adds a graph database on top, embedded in the project, with no Docker and no server.

Mode What you get What it needs
off the plain pipeline nothing
manifest requirement ids, trace/{feature}.yml, scope gate, link status python3, git
full manifest plus a FalkorDB graph fed by Graphiti and the Joern CPG Python 3.12, a free NVIDIA build key for Graphiti, joern for the code layer

The manifest

trace/{feature_id}.yml sits at the repo root and ships with the PR. It lists the requirements, the scope, and the links. Only .claude/scripts/trace.py writes it, so every write goes through the ontology and the commit check. The file is the truth. In full mode the graph is a projection of it, and if the graph is lost, graph.py sync and graph.py index-code rebuild it from git.

- from: REQ-001
  to: "src/ship.py::validate_weight"
  type: AFFECTS
  status: VALIDATED
  confidence: 0.8
  methods: [semble, cpg_callers]
  evidence:
    semble: intent match on weight validation
  commit: c6e4aa80711b
  recorded: 2026-10-05

A commit hash is resolved against git when the link is written, and a hash git cannot find is refused. That is the check that sixteen invented commit hashes in an ownership map never had to pass, which is why the source post made it mandatory.

Link status

PROPOSED means the plan thinks the requirement touches the symbol. VALIDATED means the change merged and a test linked with VERIFIED_BY proves it. STALE means the symbol is gone or moved, so the link cannot be trusted. trace.py settle --all runs at the start of every plan, so the status moves with the next branch and the harness never commits to main on its own.

The ontology

.claude/graph/ontology.yml says which node types exist and which edges are legal: AFFECTS from a requirement to a method, IMPLEMENTS from a method to a requirement, VERIFIED_BY from a requirement to a test, each with its required fields. It is a file so that changes arrive as pull requests. Copy it to your repo to extend it, and add a type only when a real document or real code asks for it.

Through the pipeline

The PRP writes each success criterion as - [ ] REQ-001: ..., with atomize ids when that skill is installed, and trace.py init creates the manifest. The plan settles older manifests, asks the graph interface for related knowledge and symbols per requirement, records each pick with trace.py propose, and uses trace.py scope as its list of files to touch. Dev records IMPLEMENTS after each commit and runs trace.py gate, which fails the stage when any file changed outside scope; widening scope takes trace.py scope --add with a reason that shows up in the dev summary. Test records VERIFIED_BY for each test that proves a requirement. The PR runs trace.py validate, commits the manifest, and pastes trace.py summary into the description.

One interface

The agent asks four questions and never learns what answers them.

python3 .claude/scripts/graph.py knowledge "<text>"
python3 .claude/scripts/graph.py symbols "<intent>"
python3 .claude/scripts/graph.py tests <file[::symbol]>
python3 .claude/scripts/graph.py history <file>

In manifest mode the answers come from earlier manifests, git, semble, and repowise. In full mode the same calls also read the graph: Graphiti facts for knowledge, CPG callers for symbols and tests. Nothing in the stages changes between the two.

Full mode

The graph is FalkorDB embedded through falkordblite, stored in .claude/runtime/graph/kg.db and git-ignored. One writer owns each layer: Graphiti writes knowledge from unstructured documents passed to graph.py ingest, graph.py index-code writes the code layer from a Joern CPG, and graph.py sync projects the manifests. Manifests and the CPG load through parsers, never a model, because a parser already knows the answer and a model would invent some.

Graphiti runs on NVIDIA build models through the OpenAI-compatible endpoint, on the free tier. The defaults are nvidia/nemotron-3-super-120b-a12b for extraction, which returned valid JSON 4 times out of 4 in 2.5 to 4.6 seconds when measured on 2026-10-05, and nvidia/nemotron-3-embed-1b for embeddings. NVIDIA retires models without notice, so graph.py status checks both against the live catalog. Override them with HK_GRAPH_LLM_MODEL and HK_GRAPH_EMBED_MODEL.

python3 .claude/scripts/graph.py setup
python3 .claude/scripts/graph.py index-code
python3 .claude/scripts/graph.py sync
python3 .claude/scripts/graph.py ingest docs/decisions/weight-limit.md
python3 .claude/scripts/graph.py status

For Java with Lombok, index-code passes --fetch-dependencies --delombok-mode no-delombok to the Joern frontend. Without them the source project saw 4,351 of 4,890 files skipped and a 188 KB graph that looked plausible. Count what the CPG holds; do not trust its size.

Cost

Manifest mode costs milliseconds per call and nothing else. In full mode the CPG is built once per repo and rebuilt when it falls behind the last merge, and Graphiti only runs on new documents. The graph narrows what goes to the model; it never fills the context.

References

Graphiti, FalkorDB, falkordblite, Joern, semble, NVIDIA build. Gotel and Finkelstein, An Analysis of the Requirements Traceability Problem, RE 1994. Yamaguchi et al., Modeling and Discovering Vulnerabilities with Code Property Graphs, IEEE S&P 2014. Rasmussen et al., Zep: A Temporal Knowledge Graph Architecture for Agent Memory, 2025. ISO/IEC/IEEE 29148:2018 for the singular requirement.

This page mirrors Graph Engineering in the wiki. Edit it there.