# Design Decisions
> The choices that shape CGraph, and the reasoning and tradeoffs behind each.
[Source](https://open.nxtsoft.io/docs/cgraph/design-decisions)

CGraph makes a handful of load-bearing decisions. This page states each one, why
it was made, and what it costs.

## Deterministic extraction

**Decision.** Extraction is deterministic — the same source tree always produces
the same graph.

**Why.** An agent's answers shouldn't drift between runs, and a deterministic
graph can be *diffed*. That diffability is what makes incremental updates and
background persistence correct: the daemon can fold a change into the previous
graph because it knows the previous graph was reproducible.

**Tradeoff.** Determinism means resolution is static. Dynamic dispatch,
reflection, and runtime wiring can't always be resolved from source, so some
edges are approximate. CGraph accepts approximate dynamic edges in exchange for a
reproducible, diffable graph.

## One operation handler

**Decision.** The MCP server's tool calls route through the *same* daemon
operation handler as the thin client.

**Why.** An agent and a shell should get identical semantics. Sharing one code
path means there's a single place to reason about correctness, and no drift
between "what the CLI does" and "what the agent sees".

**Tradeoff.** The handler has to be general enough to serve both a human at a
terminal and an agent over MCP — but that generality is cheaper than maintaining
two parallel implementations.

## A warm daemon

**Decision.** Offer a long-lived daemon (`graphd`) alongside the one-shot CLI.

**Why.** Rebuilding the graph on every query is wasteful for interactive use.
Keeping it warm and folding edits in incrementally turns repeated queries from
"rescan each time" into "answer from memory".

**Tradeoff.** A daemon is a process to manage — start, watch, idle-timeout, shut
down. The one-shot `cgraph` stays available for CI and scripts where a resident
process isn't wanted.

## Adaptive gather

**Decision.** Default agent context to adaptive gather rather than a fixed k-hop.

**Why.** Expanding every third hop is expensive; expanding none loses relevant
context. Adaptive gather keeps the full 2-hop core and expands the third hop only
along query-relevant nodes — most of the recall for a fraction of the tokens (see
[Benchmarks](/docs/cgraph/benchmarks)).

**Tradeoff.** Adaptive gather needs a query to gate on; without one the relevance
gate is a no-op and it falls back to fixed behavior.

## Host-driven semantic enrichment

**Decision.** Semantic enrichment is host-driven: the host writes fragments;
CGraph validates them and manages cache state.

**Why.** It keeps the deterministic core separate from open-ended semantic work.
CGraph owns extraction, validation, and local mutation; the semantic model is
supplied rather than guessed, and content-hash cache records keep it from being
recomputed needlessly.

**Tradeoff.** Enrichment isn't automatic — it's a workflow the host drives. The
base graph is useful on its own; enrichment is an opt-in layer.

## Native C++

**Decision.** Build the engine in native C++20.

**Why.** Extraction and query latency are the product. A native engine keeps both
low and makes the deterministic, incremental design practical at speed.

**Tradeoff.** A C++ build with CMake and vcpkg is heavier to set up than a scripting
runtime (see [Installation](/docs/cgraph/installation)) — the cost paid once for
speed paid back on every query.
