Current-graph ontology adapters
The explicit adapter gestaltdb.reasoning.adapters.graph projects one
verifiable mutable-state read snapshot. It never reads temporal claims and
does not alter Cypher planning, stored labels/edges, typed adjacency or sampler
arrays. The Datalog engine imports none of these integrations.
from tempfile import TemporaryDirectory
from gestaltdb.graphdb import GraphDB, Node, Edge
from gestaltdb.ontology import Ontology, SubPropertyOf, compile_ontology
from gestaltdb.reasoning import ReasoningLimits
from gestaltdb.reasoning.adapters.graph import GraphMapping, PinnedGraphSource
plan = compile_ontology(Ontology("relations", [SubPropertyOf("knows", "related")]))
with TemporaryDirectory() as directory:
graph = GraphDB.create(directory, backend="lmdb", serializer="json")
try:
graph.put_nodes([Node("a"), Node("b")])
graph.put_edge(Edge("ab", "a", "b", {"type": "KNOWS"}))
with graph.current_read_view(require_verifiable=True) as view:
with PinnedGraphSource(view, mapping=GraphMapping(
edge_types=[("KNOWS", "knows")],
)) as source:
scoped = source.evaluate(plan, limits=ReasoningLimits())
assert scoped.sample_neighbors("a", predicate="related", direction="out",
fanout=10, seed=1) == ("b",)
finally:
graph.close()
Mapping and query semantics
GraphMapping(labels=[(label, class_iri)], edge_types=[(type, predicate)],
node_properties=[(property_key, predicate)]) is an allowlist. Unmapped fields
are ignored. Property values must be single nonempty entity-ID strings; literal
coercion, list expansion and edge-attribute statements are not implicit. Node and
endpoint IDs remain unchanged. Named labels become RDF type facts. Dangling
endpoint IDs are logical constants, not automatically created graph nodes.
scoped.match(...) filters complete logical triples, not graph entities or
Cypher rows. scoped.result.explain(fact) works if proofs were collected.
The immutable result can outlive its read view; extraction cannot. Keep the
view open through evaluation and close sources explicitly. Unsupported backend
snapshot identities fail closed. GraphSourceLimits.max_records bounds source
records; kernel bounds independently constrain projected facts/closure. Neither
bounds the full-state snapshot authentication cost.
Expanded-relation fanout
sample_neighbors requires an explicit derived predicate and direction.
It first selects distinct logical endpoints from the completed closure, then
samples uniformly without replacement with a local seeded RNG. Parallel edges,
multiple inheritance routes and independent proofs do not multiply weights.
Fanout zero returns no endpoints; fanout above population returns all endpoints.
Self loops can appear if logically entailed. Results are sorted external IDs,
not compact sampler IDs, physical edge IDs or paths. A caller can use selected
IDs as seeds for a separate asserted-graph sampler, but that sampler’s next hop
does not automatically use inferred relations. There is no implicit multi-hop,
weighted sampling or Cypher clause rewrite. This explicit semantic boundary is
the integration point for the broader hierarchical-sampling work in issue #127.