Skip to content

11. Determinism and guarantees

  • Read-only. A user query never writes the graph. Nothing it materializes outlives the run, projected nodes and relationships it creates included (§2, §7.9); the sole persisted side effect is a write-through identity bridge (a cache of who an external identity is, not what data they hold). The single, explicitly opted-in exception is the dedicated annotation-write surface (§12) — ordinary queries remain read-only and continue to reject mutating clauses on stored or fetched data.
  • Scoped, fail-closed. Every keyed probe goes through the world/context scope rewriter; vector searches are filtered by world, context, and access-policy revision at the source. A query can never read another context without an explicit authorized bridge, and never another PRINCIPAL’s data; between two worlds of one principal the boundary is focus rather than confidentiality (§15). Deployment-approved, revisioned Public/reference datasets are the explicit exception. An unparseable or unscopable query is rejected, not run — and what the ENGINE writes is never the reason it is: a probe binds only positions it can scope, and drops the rest (§2). Which positions a statement must label for it to be scopable is §15.5, the same in either spelling of a subquery.
  • Bounded. Every fetch is bounded by a bound anchor, maxAnchors/maxFanoutTotal, paging caps, k, and rate budgets. Truncation is reported.
  • One answer whichever engine holds the graph. A deployment may keep the graph in Neo4j or in the appliance’s own in-process engine, and a query answers the same on both: the same values, nulls and conversions, the same column names, the same refusals by type. A statement that fails changes nothing on either. A difference between the two is a defect in the engine that differs, not a dialect for queries to allow for.
  • Idempotent re-runs. A re-run re-fetches; caching (ttl/immutable) makes repeated runs of the same query agree, including on any LLM-derived value — repeatability is a correctness property, not just a speed one. Without a cache, an LLM-derived value may differ between runs.
  • A refusal is stable, and it is actionable. A refused statement, re-issued unchanged, is refused again with the same text; every refusal names what was counted, the size and the limit it passed, and a lever that changes the outcome; and a figure that is only a floor says so. §9 states the contract in full, because a caller rewriting a query has nothing else to go on.