pub struct Engine { /* private fields */ }Implementations§
Source§impl Engine
impl Engine
pub fn open(path: impl Into<PathBuf>) -> Result<OpenedEngine, EngineOpenError>
Sourcepub fn open_with_choice(
path: impl Into<PathBuf>,
choice: EmbedderChoice,
) -> Result<OpenedEngine, EngineOpenError>
pub fn open_with_choice( path: impl Into<PathBuf>, choice: EmbedderChoice, ) -> Result<OpenedEngine, EngineOpenError>
Open an engine with an explicit EmbedderChoice.
Per dev/design/embedder.md §0 + the 0.7.1 EU-5 campaign, this is
the canonical entry point for selecting how the workspace’s
default embedder is supplied. See EmbedderChoice for the
semantics of each variant; in particular Default materializes
the pinned BGE embedder via the loader when the default-embedder
feature is enabled.
pub fn open_with_migration_event_sink( path: impl Into<PathBuf>, emit_migration_event: impl FnMut(&MigrationStepReport), ) -> Result<OpenedEngine, EngineOpenError>
pub fn path(&self) -> &Path
pub fn write( &self, batch: &[PreparedWrite], ) -> Result<WriteReceipt, EngineError>
Sourcepub fn ingest_with_extractor(
&self,
cmd: &[&str],
documents: &[ExtractDocument],
) -> Result<IngestWithExtractorReceipt, EngineError>
pub fn ingest_with_extractor( &self, cmd: &[&str], documents: &[ExtractDocument], ) -> Result<IngestWithExtractorReceipt, EngineError>
G11 (Slice 15) — BYO-LLM ingest: spawn an external extraction harness
speaking the fathomdb.extract.v1 NDJSON-over-stdio protocol, send
documents for extraction, and write the resulting entities
(→ canonical_nodes) and fact-edges (→ canonical_edges with G11
enrichment columns) to the store.
cmd is argv (first element = program, rest = args). Documents are
batched per the harness’s max_docs_per_request. Entity logical_id
is derived as sha256("<type>:<name>") (lowercase, hex-encoded) for
stable cross-re-ingestion identity. Edge logical_id is derived as
sha256("<from_lid>:<to_lid>:<relation>"). Both are consistent with
G0 supersession: re-ingesting the same document yields the same ids,
triggering tombstone-then-insert rather than accumulation.
Returns EngineError::Extractor on protocol errors (bad handshake,
subprocess spawn failure, JSON decode error). no_facts warnings from
the harness are not errors and do not affect the receipt counts.
pub fn search(&self, query: &str) -> Result<SearchResult, EngineError>
Sourcepub fn search_filtered(
&self,
query: &str,
filter: Option<SearchFilter>,
) -> Result<SearchResult, EngineError>
pub fn search_filtered( &self, query: &str, filter: Option<SearchFilter>, ) -> Result<SearchResult, EngineError>
G10 — hybrid search with an optional closed SearchFilter. None
(or an all-None filter) is the unfiltered path whose phase-1 SQL is
byte-identical to 0.7.2. The filter prunes the vector branch in the
single phase-1 candidates statement and constrains the text branch by the
same metadata. Ranking is the unconditional G9 RRF fusion.
Sourcepub fn search_reranked(
&self,
query: &str,
filter: Option<SearchFilter>,
rerank_depth: usize,
use_graph_arm: bool,
alpha: f64,
pool_n: usize,
) -> Result<SearchResult, EngineError>
pub fn search_reranked( &self, query: &str, filter: Option<SearchFilter>, rerank_depth: usize, use_graph_arm: bool, alpha: f64, pool_n: usize, ) -> Result<SearchResult, EngineError>
0.8.1 Slice 10 (R1) / Slice 30 (R3) — search_reranked: hybrid search
with optional CE reranking and optional graph-BFS third arm. rerank_depth = 0 is the identity (soft-fallback) path, byte-identical to
search_filtered. rerank_depth = N > 0
applies the cross-encoder over the top-N fused hits (when the
default-reranker feature is enabled and the model is loaded); without the
model, the call falls back to the fused order.
use_graph_arm = false (the default) produces byte-identical results to
the pre-Slice-30 two-arm pipeline. use_graph_arm = true seeds a BFS over
temporal fact-edges from the top-10 fused hits and fuses the reachable
nodes as a third RRF arm.
Governed surface: re-exported from fathomdb facade.
Sourcepub fn search_explained(
&self,
query: &str,
filter: Option<SearchFilter>,
rerank_depth: usize,
use_graph_arm: bool,
alpha: f64,
pool_n: usize,
) -> Result<SearchResult, EngineError>
pub fn search_explained( &self, query: &str, filter: Option<SearchFilter>, rerank_depth: usize, use_graph_arm: bool, alpha: f64, pool_n: usize, ) -> Result<SearchResult, EngineError>
0.8.8 EXP-OBS (Slice 5) — search_explained: the opt-in explain=true
surface. Identical retrieval to search_reranked
(same fused/CE ranking, same results), additionally returning a
Explanation sidecar on SearchResult.explanation with per-hit arm
provenance + score breakdown + a query-level QueryTrace. The default
search/search_filtered/search_reranked paths are unaffected and stay
byte-identical (R-OBS-2).
Governed surface: re-exported from fathomdb facade.
Sourcepub fn enable_telemetry(&self, sink_path: &str) -> Result<(), EngineError>
pub fn enable_telemetry(&self, sink_path: &str) -> Result<(), EngineError>
0.8.8 Slice 15 (OPP-9) — enable opt-in telemetry capture to a local JSONL
sink_path (append-only). Off by default; once enabled, each search
records a query→result event and record_feedback appends agent labels.
Local file only — no network/egress. query_id + ts_monotonic_ms are
reset deterministically on enable. Idempotent re-enable resets the seq.
Sourcepub fn last_telemetry_query_id(&self) -> Option<String>
pub fn last_telemetry_query_id(&self) -> Option<String>
0.8.8 Slice 15 — the most-recent captured query_id (for record_feedback).
None when telemetry is off or no query has been captured yet.
Sourcepub fn record_feedback(
&self,
query_id: &str,
relevant_ids: &[u64],
irrelevant_ids: &[u64],
label_source: &str,
) -> Result<(), EngineError>
pub fn record_feedback( &self, query_id: &str, relevant_ids: &[u64], irrelevant_ids: &[u64], label_source: &str, ) -> Result<(), EngineError>
0.8.8 Slice 15 — append an agent-supplied relevance-label record for a
previously-captured query_id. label_source is the only exogenous string
(caller-declared, e.g. "agent:hermes"). Ids are the stable logical_id.
Errors if telemetry is off.
Sourcepub fn _graph_frontier_stats_for_test(
&self,
query: &str,
) -> Result<GraphFrontierStats, EngineError>
pub fn _graph_frontier_stats_for_test( &self, query: &str, ) -> Result<GraphFrontierStats, EngineError>
G0 Phase-2 (BLOCK-1) test seam — runs the graph-arm retrieval path and
returns the frontier meter (GraphFrontierStats) for query. Mirrors the
sanctioned set_vector_stage_only_for_test / _configure_vector_kind_for_test
pattern: kept OFF the governed surface (test/eval-only), so the meter never
appears on SearchResult. Used by the recall harness to prove the
doc-seeded frontier is empty (resolved_seed_rate == 0.0) and, post-C1, the
0→>0 flip.
Sourcepub fn read_get(
&self,
logical_id: &str,
) -> Result<Option<NodeRecord>, EngineError>
pub fn read_get( &self, logical_id: &str, ) -> Result<Option<NodeRecord>, EngineError>
Slice 30 (G2) — read.get: active-only point lookup by logical_id.
Delegates to Engine::read_get_many; returns the single slot. A
missing/superseded id is None (a normal absence, not an error). Reads
ride the ReaderWorkerPool DEFERRED-tx path (never the writer lock).
Sourcepub fn read_get_many(
&self,
logical_ids: &[String],
) -> Result<Vec<Option<NodeRecord>>, EngineError>
pub fn read_get_many( &self, logical_ids: &[String], ) -> Result<Vec<Option<NodeRecord>>, EngineError>
Slice 30 (G2) — read.get_many: active-only point lookup over many
logical_ids. Returns one slot per requested id in REQUEST ORDER, None
where no active row carries that id (partial, never all-or-nothing).
Sourcepub fn graph_neighbors(
&self,
root_logical_id: &str,
depth: u32,
direction: TraversalDirection,
) -> Result<Vec<NodeRecord>, EngineError>
pub fn graph_neighbors( &self, root_logical_id: &str, depth: u32, direction: TraversalDirection, ) -> Result<Vec<NodeRecord>, EngineError>
Slice 20 (G5) — read.neighbors: bounded BFS from root_logical_id
over canonical_edges. Returns nodes reachable within depth hops
(1..=3) in the given direction, excluding the root itself.
Hard cap: 50 results (engine-enforced LIMIT 50).
Traversal filter: superseded_at IS NULL AND (t_invalid IS NULL OR t_invalid > now).
Returns Err(EngineError::InvalidArgument) for depth > 3.
Returns Ok(vec![]) for an unknown/superseded root.
Reads ride the ReaderWorkerPool DEFERRED-tx path.
Sourcepub fn search_expand(
&self,
query: &str,
filter: Option<SearchFilter>,
depth: u32,
) -> Result<SearchExpandResult, EngineError>
pub fn search_expand( &self, query: &str, filter: Option<SearchFilter>, depth: u32, ) -> Result<SearchExpandResult, EngineError>
Slice 20 (G6) — search_expand: hybrid search (G1+G9) followed by
bounded BFS expansion (G5) of each search hit. Returns the original
search hits (with RRF scores) plus nodes reachable from any hit via
up to depth hops that are NOT already in the search hit set.
Returns Err(EngineError::InvalidArgument) for depth > 3.
A depth = 0 call returns search hits with their logical_ids resolved
but no BFS expansion. Reads ride the ReaderWorkerPool DEFERRED-tx path.
Snapshot note: the search phase (search_inner) and the expansion
phase (SearchExpand reader request) run in separate DEFERRED reader
transactions; a write that lands between them is visible to expansion
but not search (or vice-versa). In practice the window is negligible for
single-process embedded use. The expansion phase mitigates drift by
filtering search_hits to only include hits whose write_cursor is
still active in the expansion snapshot (superseded hits are dropped from
the result rather than surfaced with stale data).
Sourcepub fn read_collection(
&self,
collection: &str,
after_id: Option<i64>,
limit: usize,
) -> Result<Vec<OpStoreRow>, EngineError>
pub fn read_collection( &self, collection: &str, after_id: Option<i64>, limit: usize, ) -> Result<Vec<OpStoreRow>, EngineError>
Slice 30 (G3) — read.collection: paginated op-store read-back over
operational_mutations for collection, ORDER BY id. limit is
MANDATORY (clamped to the ~1M cap); after_id is the exclusive cursor.
Reads ride the ReaderWorkerPool DEFERRED-tx path.
Sourcepub fn read_mutations(
&self,
collection: &str,
after_id: Option<i64>,
limit: usize,
) -> Result<Vec<OpStoreRow>, EngineError>
pub fn read_mutations( &self, collection: &str, after_id: Option<i64>, limit: usize, ) -> Result<Vec<OpStoreRow>, EngineError>
Slice 30 (G3) — read.mutations: the mutation-log-oriented alias surface
over the SAME op-store read-back as Engine::read_collection.
Sourcepub fn read_list(
&self,
kind: &str,
predicates: &[Predicate],
limit: usize,
) -> Result<Vec<NodeRecord>, EngineError>
pub fn read_list( &self, kind: &str, predicates: &[Predicate], limit: usize, ) -> Result<Vec<NodeRecord>, EngineError>
Slice 35 (G4) — read.list: list active canonical_nodes of a given
kind, optionally filtered by a closed Predicate set, up to limit
rows. Returns Vec<NodeRecord> (active only; superseded_at IS NULL).
Multiple predicates are combined as AND (D-F5). An empty predicate slice
returns all active nodes of the given kind up to limit (unfiltered path).
Compilation target: json_extract(body, '$.field') <op> ? with bound
parameters (injection-safe per D-F4). See dev/adr/ADR-0.8.0-filter-grammar.md.
Path validation happens at Predicate construction time; read_list
revalidates as defense-in-depth (enum variants are pub, so direct
struct-literal construction could bypass the constructors).
pub fn close(&self) -> Result<(), EngineError>
Sourcepub fn drain(&self, timeout_ms: u64) -> Result<(), EngineError>
pub fn drain(&self, timeout_ms: u64) -> Result<(), EngineError>
Block until in-flight writes drain or timeout_ms elapses.
Surface owned by dev/interfaces/rust.md § Engine-attached
instrumentation; semantics are owned by dev/design/lifecycle.md.
Sourcepub fn counters(&self) -> CounterSnapshot
pub fn counters(&self) -> CounterSnapshot
Snapshot of engine-internal counters.
Field set owned by dev/design/lifecycle.md.
Sourcepub fn set_profiling(&self, enabled: bool) -> Result<(), EngineError>
pub fn set_profiling(&self, enabled: bool) -> Result<(), EngineError>
Toggle response-cycle profiling.
Per dev/design/lifecycle.md § Per-statement profiling, profiling
is an opt-in surface that is independently toggleable on a running
engine without restart. AC-005a locks runtime toggleability.
Sourcepub fn set_slow_threshold_ms(&self, value: u64) -> Result<(), EngineError>
pub fn set_slow_threshold_ms(&self, value: u64) -> Result<(), EngineError>
Set the threshold above which an operation is reported as slow.
Per dev/design/lifecycle.md § Slow and heartbeat policy, the
threshold is runtime-configurable; mutating it changes detection
behavior on subsequent statements without restart (AC-007b).
Sourcepub fn subscribe(&self, subscriber: Arc<dyn Subscriber>) -> Subscription
pub fn subscribe(&self, subscriber: Arc<dyn Subscriber>) -> Subscription
Attach a host subscriber to engine events.
Dropping the returned Subscription detaches the subscriber.
Payload shape owned by dev/design/lifecycle.md and
dev/design/migrations.md.
Sourcepub fn embed_text(&self, text: &str) -> Result<Vec<f32>, EngineError>
pub fn embed_text(&self, text: &str) -> Result<Vec<f32>, EngineError>
Embed arbitrary text with the engine’s configured runtime embedder, returning the raw (un-centered) vector.
This is the read-path embed primitive: it mirrors the search
query-embedding path — a single, direct Embedder::embed call. The
per-embed() watchdog/circuit-breaker guards only the bulk
projection/write path (many embeds, fault isolation), not single
read-side embeds, so a direct call is consistent with how a query is
embedded. Callers get vectors under the engine’s pinned embedder
identity (fathomdb-bge-small-en-v1.5 by default) rather than a
parallel, possibly-divergent embedder.
Returns EngineError::EmbedderNotConfigured if the engine was opened
without an embedder (use_default_embedder = false).
Sourcepub fn drain_embedder_events(&self) -> Result<Vec<EmbedderEvent>, EngineError>
pub fn drain_embedder_events(&self) -> Result<Vec<EmbedderEvent>, EngineError>
0.7.2 PR-2b — NON-test observation seam. Drains and returns every
EmbedderEvent queued since the last drain (mean pin, manual mean
recompute). Production callers use
this to observe the synchronous recompute work; events are queued
only AFTER the recompute transaction is durable, so a rolled-back
recompute never surfaces. Mirrors the at-open
OpenReport.embedder_events channel for the steady-state path.