klieo-memory-graph-rag 3.3.0

Graph-first RAG composer over KnowledgeGraph + LongTermMemory. Stable at 1.x per ADR-039.
Documentation
# klieo-memory-graph-rag

Graph-first RAG composer over `klieo-memory-graph::KnowledgeGraph` +
`klieo-core::LongTermMemory`.

**Status:** stable at 3.x. Trait freeze contract recorded in [ADR-039](../../docs/adr/adr-039-graphrag-1-0-promotion.md).

## Layers

- `klieo-core` (Layer 0) — frozen at 3.2.0
- `klieo-memory-graph` (Layer 1) — `KnowledgeGraph` trait
- `klieo-memory-graph-neo4j` (Layer 2) — Neo4j backend
- `klieo-memory-qdrant` (Layer 1) — vector store with `FilterableLongTermMemory`
- **`klieo-memory-graph-rag`** (Layer 2) — this crate

## What's in the crate

- `BuiltinExtractor` (regex + caller-hint dedup)
- `FallbackExtractor` (primary → secondary on empty)
- `LlmEntityExtractor` (klieo-core::llm + JSON-array prompt)
- `NullProvenance` stub (M4 replaces with a `klieo-provenance` bridge)
- `GraphAwareLongTerm` — drop-in `LongTermMemory` impl
- `KnowledgeIngestionPipeline` + `ImportSource` extension point

## Quickstart — builder facade

`GraphAwareLongTerm::builder()` defaults the extractor
(`BuiltinExtractor`) and the metrics counter (`RecallMetrics::default()`)
so callers only supply the two mandatory backends — the authoritative
vector store and the graph index:

```rust
use std::sync::Arc;
use klieo_memory_graph::{FilterableLongTermMemory, KnowledgeGraph};
use klieo_memory_graph_rag::GraphAwareLongTerm;

# fn run(vector: Arc<dyn FilterableLongTermMemory>, graph: Arc<dyn KnowledgeGraph>) {
let long_term = GraphAwareLongTerm::builder().build(vector, graph);
# let _ = long_term; }
```

Override defaults via the builder's setters:

```rust
use std::sync::Arc;
use klieo_memory_graph::RecallMetrics;
use klieo_memory_graph_rag::{
    FallbackExtractor, BuiltinExtractor, GraphAwareLongTerm, LlmEntityExtractor,
};

# fn run<V, G>(vector: Arc<V>, graph: Arc<G>, llm: Arc<dyn klieo_core::llm::LlmClient>)
# where
#     V: klieo_memory_graph::FilterableLongTermMemory + 'static,
#     G: klieo_memory_graph::KnowledgeGraph + 'static,
# {
let metrics = Arc::new(RecallMetrics::default());
let extractor = Arc::new(FallbackExtractor::new(
    BuiltinExtractor::default(),
    LlmEntityExtractor::new(llm),
));
let long_term = GraphAwareLongTerm::builder()
    .extractor(extractor)
    .metrics(Arc::clone(&metrics))
    .min_graph_hits(2)
    .build(vector, graph);
# let _ = long_term; let _ = metrics; }
```

Read `metrics.snapshot()` from an ops/metrics endpoint to see graph
hit-rate vs vector-fallback rate.

## Full M2 wiring

```rust
use std::sync::Arc;
use klieo_memory_graph_rag::GraphAwareLongTerm;
use klieo_memory_graph_neo4j::Neo4jKnowledgeGraph;
use klieo_memory_neo4j::MemoryNeo4j;
use klieo_memory_qdrant::MemoryQdrant;

# async fn run() -> Result<(), Box<dyn std::error::Error>> {
let qdrant = MemoryQdrant::connect("http://localhost:6334").await?;
let neo4j = MemoryNeo4j::connect("bolt://localhost:7687", "neo4j", "pw").await?;
let graph = Arc::new(Neo4jKnowledgeGraph::new(neo4j.neo4j_handle()));
let long_term = GraphAwareLongTerm::builder().build(qdrant.qdrant_long_term, graph);
// `long_term` is a drop-in `Arc<dyn LongTermMemory>`.
# let _ = long_term; Ok(()) }
```

## Advanced wiring — direct constructor

`GraphAwareLongTerm::new(vector, graph, extractor, metrics)` stays
available for callers that want explicit control over every component.

For ingest from external sources (Confluence pages, regulatory texts,
…) implement `ImportSource` in your own crate and pass it to
`KnowledgeIngestionPipeline::new`.

## License

MIT.