semantic_graph package

Reviewed against commit 8a2cb42ad on 2026-10-23.

Reference: generated package page orchestrata_ultimate.semantic_graph (20 modules including the 3-module adapters subpackage, 5,437 lines of code); key modules interfaces, repository, ingestion, architecture_twin, ha_controller. The overview explains the two graphs and why they must not be confused: orchestrata overview.

The story

Orchestrata's volks need more than raw text search when they reason about a codebase: they need retrieval that understands both meaning (vector similarity over embedded chunks) and structure (entities and relationships in a graph). orchestrata_ultimate.semantic_graph exists to provide exactly that — a repository abstraction for RAG / GraphRAG. Rather than binding the rest of the system to a particular database, the package defines small typing.Protocol contracts in interfaces.py — VectorStore for embedding search, GraphStore for entity/relationship traversal, and SemanticGraph, which inherits both — together with the shared dataclasses in models.py (Entity, Relationship, Chunk, and the GraphRAGContext bundle returned by retrieve). Everything upstream depends only on these contracts, so the concrete backend can change without touching a caller.

Two swappable backends satisfy the contract. adapters/memgraph.py's MemgraphSemanticGraph is the production adapter, speaking Cypher over Bolt to a Memgraph instance, driving a native vector index for search_similar, and fusing that with a keyword scan (search_keyword) and module/entity-prominence boosts for hybrid retrieval; adapters/memory.py's InMemorySemanticGraph is a pure-Python adapter whose vector search is a local cosine similarity, making it the default for unit tests and local development. Callers never choose an adapter directly: repository.py exposes create_semantic_graph(), a factory that reads a SemanticGraphConfig (config.py, resolved from environment variables with no hard-coded IPs) and returns whichever backend the configuration names, raising the package's own exception hierarchy (exceptions.py) on an unknown backend or connection trouble.

Data flows into the graph along two pipelines. The first is code ingestion: ingestion.py's CodeChunker splits source files into overlapping line-window chunks, and SemanticGraphIngester embeds them through a pluggable Embedder backend (embedders.py offers OpenRouterEmbedder, cloud embeddings via OpenRouter/Codestral, and SentenceTransformerEmbedder, local GPU embeddings via sentence-transformers) before upserting chunks, entities, and their relationships into a SemanticGraph (which embedder is used is now decided once, from the environment, by embedder_factory.py; ArchitectureTwin in architecture_twin.py reuses it to index ADRs and design documents). On the way back out, SemanticGraphIngester.search runs hybrid vector+keyword retrieval and can hand its candidates to rerankers.py's OpenRouterReranker for a final relevance re-scoring. The second pipeline is spec/trace enrichment: spec_trace_parser.py parses Orchestrata's SPEC markdown and the @traces annotations scattered through the code (leaning on core.traceability) into SpecInfo / StoryInfo / RequirementInfo structures, and spec_trace_enricher.py's SpecTraceEnricher writes the resulting spec, story, requirement, and code-element entities — plus the trace edges between them — into the graph, returning an EnrichmentSummary of what it wrote.

The package collaborates with its neighbors at arm's length: scripts/ingest_orchestrata_ultimate.py and scripts/enrich_semantic_graph_specs.py drive the two write pipelines from the repo, and core.traceability supplies the @traces machinery the enrichment path reads. Because production Memgraph runs as Community edition without built-in HA, the package also ships its own operational layer: ha_controller.py's MemgraphHAController manages main/replica replication, per-node health state, and failover across a cluster (modeled by NodeConfig, NodeState, and the ClusterStatus snapshot it serves over a small FastAPI surface), ha_controller_cli.py wraps it in an async argparse CLI whose node list can come from the command line or the environment, and main_discovery.py's resolve_main() lets clients discover the current write leader — via the HA controller or by probing the Raft coordinators directly — so writes always land on the live MAIN.

Key responsibilities

Class diagram

Contracts and data models

The Protocol contracts live in interfaces.py; SemanticGraph composes the VectorStore and GraphStore capabilities into the single interface every adapter implements. retrieve returns a GraphRAGContext — the bundle of entities, relationships, and chunks assembled for an LLM prompt.

Diagram projects-orchestrata-ultimate-modules-semantic_graph-1

Backends and the factory

create_semantic_graph() reads a SemanticGraphConfig and returns one of the two adapters. Both realize the SemanticGraph Protocol; the Memgraph adapter adds hybrid-retrieval helpers (search_keyword, link_chunks_to_modules) on top of the base contract.

Diagram projects-orchestrata-ultimate-modules-semantic_graph-2

Embedding, reranking, and ingestion pipeline

SemanticGraphIngester orchestrates the write path: it chunks with CodeChunker, embeds through an Embedder (one of two concrete backends), writes to a SemanticGraph, and optionally reranks retrieval candidates with OpenRouterReranker.

Diagram projects-orchestrata-ultimate-modules-semantic_graph-3

Spec / trace enrichment

The parser (spec_trace_parser.py) turns SPEC markdown into a SpecInfo tree of stories and requirements; SpecTraceEnricher reads those, joins them with collected @traces, writes the resulting entities and edges into a SemanticGraph, and reports an EnrichmentSummary.

Diagram projects-orchestrata-ultimate-modules-semantic_graph-4

Memgraph HA control plane

Because Community-edition Memgraph has no built-in HA, MemgraphHAController runs the replication/failover loop over a fleet of data instances. It holds one NodeState per instance (each wrapping a NodeConfig) and exposes a ClusterStatus snapshot through its FastAPI surface.

Diagram projects-orchestrata-ultimate-modules-semantic_graph-5

Module dependency diagram

Internal module imports within orchestrata_ultimate.semantic_graph (render-verified).

Diagram projects-orchestrata-ultimate-modules-semantic_graph-6

Module inventory

Module Purpose
__init__.py Package facade: re-exports adapters, models, interfaces, factory, and the spec/trace API.
interfaces.py Repository Protocols: VectorStore, GraphStore, and the combined SemanticGraph.
models.py Data models: Entity, Relationship, Chunk, GraphRAGContext.
config.py SemanticGraphConfig — env-resolved connection + hybrid-retrieval config; from_env().
exceptions.py Exception hierarchy: SemanticGraphError, ConnectionError, QueryError, EntityNotFoundError, VectorSearchError.
repository.py Repository factory — create_semantic_graph() selects a backend from config.
adapters/__init__.py Adapter subpackage exports.
adapters/memgraph.py MemgraphSemanticGraph — Bolt/Cypher adapter with native vector index, hybrid keyword search, and module linking.
adapters/memory.py InMemorySemanticGraph — in-memory adapter (cosine-similarity vector search) for unit tests and local dev.
embedders.py Embedding backends: Embedder Protocol, OpenRouterEmbedder, SentenceTransformerEmbedder.
embedder_factory.py Chooses the embedding backend once, from the environment, instead of three scripts each hard-coding a model: embed_backend, embed_model, embed_dimension, requires_api_key, create_embedder, chunk_label and vector_index_name. SEMANTIC_EMBED_BACKEND=local selects the on-machine Qwen3-Embedding-0.6B (no API key, no network, no cost) used by the dev and test profiles; the other choice is the cloud OpenRouter embedder. Added after the first version of this page.
architecture_twin.py ArchitectureTwin — the semantic twin of the architecture ontology: reads the ADR and design-doc corpus from the operational KG (orchkg), chunks it (build_adr_chunk, chunk_design_doc), embeds it with the same embedder as code ingestion and MERGEs it into a dedicated chunk label in the memgraph database, so decisions can be found with GraphRAG. Its sync() returns counts. Added after the first version of this page.
rerankers.py OpenRouterReranker — reranking backend for retrieval results.
ingestion.py Source-code ingestion: CodeChunker + SemanticGraphIngester (hybrid search).
spec_trace_parser.py Parses specs and @traces into SpecInfo/StoryInfo/RequirementInfo (+ trace index / test-module map).
spec_trace_enricher.py SpecTraceEnricher + EnrichmentSummary — writes spec/story/requirement/trace entities into the graph.
main_discovery.py resolve_main() — discover the current Memgraph write leader via the HA controller or Raft coordinators.
ha_controller.py MemgraphHAController + NodeConfig/NodeState/ClusterStatus — replication and failover control plane.
ha_controller_cli.py Async argparse CLI wrapping MemgraphHAController.
_freshness.py Internal freshness helpers for the retrieval/ingestion path.

Class map (generated)

Generated from the live source AST by scripts/gen-module-class-diagrams.py — do not hand-edit. Abstract classes have a green border; members listed are those defined on the class itself (inherited members excluded). Solid empty-triangle arrows = in-package inheritance; dashed arrows into dashed boxes = external/stdlib/cross-package bases; filled diamond = composition (constructed in __init__); open diamond = aggregation (annotated/injected reference); diamond edge labels name the owning attribute.

semantic_graph class map