Skip to main content

kglite/
lib.rs

1//! kglite — pure-Rust knowledge graph engine.
2//!
3//! Cypher pipeline, snapshot/working CoW transactions, columnar /
4//! mmap / disk storage backends, optional dataset loaders
5//! (SEC EDGAR, Sodir, Wikidata). The Python wheel
6//! (`pip install kglite`) is built by the sibling `kglite-py`
7//! crate; the Bolt and MCP protocol servers are separate
8//! workspace binaries.
9//!
10//! ## Public API
11//!
12//! Downstream Rust consumers (the Python wheel, the bolt and
13//! mcp server binaries, future Go/TypeScript/JVM bindings)
14//! should depend on the curated [`api`] module — those items
15//! get semver guarantees. Anything else is an implementation
16//! detail.
17//!
18//! See `docs/rust/embedding.md` for the embedder guide.
19
20// Phase A.2 / C2 — crate-wide allow for clippy::result_large_err.
21// `KgError` is intentionally rich (16 variants spanning Cypher /
22// schema / IO / argument validation) so its size pushes past clippy's
23// default 128-byte threshold. Boxing the error variant in every
24// `Result<T, KgError>` would add an allocation per error path for no
25// real benefit — error paths aren't hot. Standard pattern for crates
26// with a unified typed error.
27#![allow(clippy::result_large_err)]
28// Phase G.3a — when the engine moved from a cdylib (root crate) into
29// an rlib (this crate), clippy's lint set widened because more items
30// became reachable across crate boundaries. The noisy lints below
31// were tolerated in the root crate's pub(crate) surface; they're
32// follow-up cleanup tasks but not blockers. Two of them
33// (hidden_glob_reexports, private_interfaces) directly reflect the
34// rushed wide-public visibility bumps in G.3a — proper accessor
35// methods would resolve them.
36#![allow(clippy::new_without_default)]
37#![allow(clippy::len_without_is_empty)]
38#![allow(private_interfaces)]
39#![allow(hidden_glob_reexports)]
40#![allow(clippy::too_many_arguments)]
41#![allow(clippy::should_implement_trait)]
42#![allow(clippy::result_unit_err)]
43
44pub mod code_tree;
45// Dataset loaders — sealed behind the curated `api::datasets` facade (the
46// same chokepoint treatment as `graph`). `pub(crate)` so no wrapper can reach
47// `kglite::datasets::*` directly; the `api::datasets` re-exports still resolve
48// (re-exporting a `pub` item out of a `pub(crate)` module is legal). The CI
49// grep (`scripts/check_api_chokepoint.sh`) keeps wrappers honest.
50pub(crate) mod datasets;
51pub mod datatypes;
52pub mod error;
53// Engine internals — sealed behind the curated `api` facade (roadmap Piece 4).
54// `pub(crate)` so no downstream crate can reach `kglite::graph::*` directly;
55// the `api` re-exports below still resolve (re-exporting a `pub` item out of a
56// `pub(crate)` module is legal). A CI grep (`scripts/check_api_chokepoint.sh`)
57// keeps the wrapper crates honest.
58pub(crate) mod graph;
59pub mod graphgen;
60#[cfg(feature = "okf")]
61pub mod okf;
62pub mod param;
63
64/// Curated stable Rust API. Downstream consumers should depend on
65/// items here, not on the underlying module structure (which may
66/// move between minor releases).
67pub mod api {
68    // ── Root prelude ──────────────────────────────────────────────────────
69    // The root holds only the cross-cutting *data model* (the types every
70    // binding speaks) + a couple of standalone top-level capabilities
71    // (`graphgen`, `explore_markdown`). Everything else is clustered into a
72    // submodule by concern: `param`, `mutation`, `fluent`, `algorithms`,
73    // `timeseries`, `introspection`, `io`, `code_tree`, `blueprint`,
74    // `cypher`, `session`, `datasets`. Per-cluster items live in exactly one
75    // place (no root↔submodule duplication).
76    pub use crate::datatypes::values::{NodeValue, PathValue, RelValue};
77    pub use crate::datatypes::Value;
78    pub use crate::error::{KgError, KgErrorCode};
79    pub use crate::graph::dir_graph::DirGraph;
80    #[cfg(feature = "fastembed")]
81    pub use crate::graph::embedder::fastembed::FastEmbedAdapter;
82    pub use crate::graph::embedder::Embedder;
83    pub use crate::graph::explore::{explore_markdown, ExploreOptions};
84    /// Streaming synthetic-graph generator — `generate_to_dir(&config, dir)`
85    /// streams the benchmark/demo graph as CSVs + a manifest in bounded memory.
86    /// Surfaced through the wheel as `kglite.graphgen(...)`.
87    pub use crate::graphgen::{generate_to_dir as graphgen, GraphGenConfig, GraphGenStats};
88    // Thin pure-Rust graph handle for embedders + the free function
89    // backing it. The wheel crate (`kglite-py`) defines its own,
90    // Python-flavored `KnowledgeGraph` separately — same name,
91    // different audience (`pip install kglite` users), polars-style.
92    //
93    // `infer_selection_node_type` infers the node type of a selection's
94    // current level; it takes `&CowSelection`, so it landed here in
95    // Piece 3b alongside the Selection api-type lift (Piece 3a).
96    //
97    // (The code-tree handle helpers `resolve_code_entity` / `CODE_TYPES` /
98    // `source_location` live in `api::code_tree`.)
99    pub use crate::graph::handle::{
100        discover_property_keys_from_data, infer_selection_node_type, KnowledgeGraph,
101    };
102    /// Core schema data types — the node record (`NodeData`), the projected
103    /// `NodeInfo`, geo/temporal validity configs (`SpatialConfig` /
104    /// `TemporalConfig`), and the declarative schema-definition +
105    /// validation types. Generic across bindings; lifted in roadmap
106    /// Piece 3 cleanup.
107    pub use crate::graph::schema::{
108        parse_spatial_column_types_from_pairs, parse_temporal_column_types_from_pairs,
109        ConnectionSchemaDefinition, NodeData, NodeInfo, NodeSchemaDefinition, SchemaDefinition,
110        SpatialConfig, TemporalConfig, ValidationError,
111    };
112    /// The fluent **selection** data model — the cursor state threaded
113    /// through the fluent query chain (and through Selection-scoped
114    /// capabilities like `algorithms::vector_search`, `mutation`
115    /// set-ops/subgraph, and the spatial predicates). `CowSelection` is
116    /// the Arc copy-on-write wrapper a binding holds as its cursor;
117    /// `CurrentSelection` is the underlying level/plan state; `PlanStep`
118    /// is an `explain()` plan entry. Pure core types (petgraph node
119    /// indices and hash maps), no binding coupling. Lifted in roadmap
120    /// Piece 3a as the foundation for the fluent api surface. The
121    /// high-level fluent chain operations are consolidated into core and
122    /// exposed in Piece 3c; the fine-grained `core::*` primitives stay
123    /// internal.
124    pub use crate::graph::schema::{
125        CowSelection, CurrentSelection, PlanStep, SelectionLevel, SelectionOperation,
126    };
127    /// Interned property-/type-key handle (`InternedKey`, a transparent
128    /// `u64` newtype) + the `StringInterner` that mints them. Bindings
129    /// doing low-level direct graph access bridge string keys ↔ interned
130    /// ids via `InternedKey::from_str(..)` / `.as_u64()`. Lifted in roadmap
131    /// Piece 2 / Piece 3 cleanup.
132    pub use crate::graph::storage::interner::{InternedKey, InternerCollision, StringInterner};
133    /// The canonical graph read trait — node/edge/property accessors
134    /// shared by every storage backend. Non-object-safe (GATs on the
135    /// iterator-returning methods), so consumers take `&impl GraphRead`,
136    /// never `&dyn`. Lifted for cross-binding read access (roadmap Piece 1).
137    pub use crate::graph::storage::GraphRead;
138    /// The temporal query context (`At` / `During` / `Today` / `All`) — the
139    /// as-of filter a binding's cursor carries for temporal-validity
140    /// auto-filtering. Lifted in roadmap Piece 4.
141    pub use crate::graph::TemporalContext;
142    // `Arc<DirGraph>` → `&mut DirGraph` + version bump (lifted in 0.10.1).
143    pub use crate::graph::handle::make_dir_graph_mut;
144    // (Mutation reports → `api::mutation`; schema introspection /
145    // `SchemaOverview` / detail enums → `api::introspection`; `.kgl`
146    // load/save → `api::io`; `SourceLocation`/`SourceLookup` →
147    // `api::code_tree`.)
148
149    /// Parameter-shape helpers for bindings — wire-shaped values
150    /// (JSON / protobuf-map / etc.) ↔ `kglite::api::Value`. Future
151    /// REST / gRPC bindings shouldn't re-implement the JSON dispatch
152    /// each time; these re-exports hand them the canonical converters
153    /// for both directions: `json_value_to_kglite_value` (inbound
154    /// params) and `kglite_value_to_json` (outbound result cells, in
155    /// natural untagged JSON).
156    pub mod param {
157        pub use crate::param::{
158            json_object_to_value_map, json_value_to_kglite_value, kglite_value_to_json,
159        };
160    }
161
162    /// Bulk graph construction + maintenance. `add_edges_from_specs` is
163    /// the DataFrame-free edge-ingest path that non-Python bindings use
164    /// (the C ABI's `create_edges_batch` wraps it); the DataFrame-based
165    /// `add_nodes` / `add_connections` / `replace_connections` are the
166    /// Rust-side bulk-ingest path (polars `DataFrame` in, operation report
167    /// out). `update_node_properties`, `purge_provisional_nodes`, and
168    /// `extend_graph` (merge one graph into another) round out the
169    /// generic, non-Selection mutation surface. Lifted in roadmap Piece 2.
170    /// `create_connections` (edge-create between the two ends of a
171    /// selection) lifted in Piece 3b once `CurrentSelection` reached api.
172    pub mod mutation {
173        /// Structured mutation reports — what a write touched (nodes/edges
174        /// created/updated/deleted, per operation). Returned by the mutation
175        /// functions above; every binding surfaces them after a mutating call.
176        pub use crate::graph::introspection::reporting::{
177            ConnectionOperationReport, NodeOperationReport, OperationReport, OperationReports,
178        };
179        pub use crate::graph::mutation::extend::{extend_graph, ExtendReport};
180        pub use crate::graph::mutation::maintain::{
181            add_connections, add_edges_from_specs, add_nodes, add_properties, create_connections,
182            purge_provisional_nodes, replace_connections, update_node_properties, EdgeSpec,
183            EdgeSpecReport, PropertySpec,
184        };
185        /// Validate a graph against a `SchemaDefinition` (Piece 3 cleanup).
186        pub use crate::graph::mutation::validation::validate_graph;
187    }
188
189    /// Selection-scoped operations — selection set algebra
190    /// (`union`/`intersection`/`difference`/`symmetric_difference`) and
191    /// subgraph extract / expand / stats. These take `&CurrentSelection`
192    /// (now an api type, roadmap Piece 3a) and are the building blocks the
193    /// fluent chain composes.
194    ///
195    /// The bulk of this module (Piece 3c) is the **shared selection-based
196    /// query-primitive layer** — `core::graph::core::*`, which CLAUDE.md
197    /// describes as "pattern matching, filtering, traversal … used by both
198    /// Cypher and the fluent API." Each op takes `(&DirGraph, &mut
199    /// CurrentSelection, …already-marshalled params)` and mutates the
200    /// selection in place; a binding building a fluent surface composes
201    /// these directly (the wheel's `kg_fluent` / `kg_introspection` PyO3
202    /// methods marshal Python args, then call straight into here). The
203    /// primitives stay *defined* in `core::graph::core`; this is their
204    /// curated, stable re-export surface. (A future refinement could hoist
205    /// the small amount of per-method branching — `select`'s
206    /// include-secondary / temporal logic, `traverse`'s temporal precedence
207    /// — into higher-level ops, but the primitives below are already the
208    /// correctly-grained shared operations, not glue to hide.)
209    pub mod fluent {
210        // Selection set algebra + subgraph (Piece 3b).
211        pub use crate::graph::mutation::set_ops::{
212            difference_selections, intersection_selections, symmetric_difference_selections,
213            union_selections,
214        };
215        pub use crate::graph::mutation::subgraph::{
216            expand_selection, extract_subgraph, get_subgraph_stats, SubgraphStats,
217        };
218        // Filtering / sorting / pagination over a selection.
219        pub use crate::graph::core::filtering::{
220            filter_by_connection, filter_nodes, filter_nodes_any, filter_nodes_by_label,
221            filter_orphan_nodes, limit_nodes_per_group, offset_nodes, sort_nodes,
222        };
223        // Traversal (parent→child level expansion) + its config/filter types.
224        pub use crate::graph::core::traversal::{
225            format_for_dictionary, format_for_storage, get_children_properties,
226            make_comparison_traversal, make_traversal, MethodConfig, TemporalEdgeFilter,
227        };
228        // Per-level calculations / equation evaluation / counts.
229        pub use crate::graph::core::calculations::{
230            count_nodes_by_parent, count_nodes_in_level, process_equation, store_count_results,
231            EvaluationResult, StatResult,
232        };
233        // Node/connection/property retrieval from a selection + result types.
234        pub use crate::graph::core::data_retrieval::{
235            format_unique_values_for_storage, get_connections, get_nodes, get_property_values,
236            get_unique_values, LevelConnections, LevelNodes, LevelValues, UniqueValues,
237        };
238        // Aggregate statistics over selected nodes.
239        pub use crate::graph::core::statistics::{
240            calculate_grouped_property_stats, calculate_property_stats, collect_selected_nodes,
241            get_parent_child_pairs, GroupedPropertyStats, PropertyStats,
242        };
243        // Pattern-match execution (shared with Cypher MATCH).
244        pub use crate::graph::core::pattern_matching::{
245            parse_pattern, MatchBinding, PatternExecutor, PatternMatch,
246        };
247        // Compact value formatting for fluent result shaping.
248        pub use crate::graph::core::value_operations::format_value_compact;
249        // Spatial predicates over a selection (geo filters / centroids /
250        // bounds). Selection-scoped — lifted in Piece 3 cleanup now that
251        // CurrentSelection is an api type.
252        pub use crate::graph::features::spatial::{
253            calculate_centroid, contains_point, get_bounds, intersects_geometry, near_point,
254            near_point_m, within_bounds, wkt_centroid,
255        };
256        // Temporal validity predicates (per NodeData + TemporalConfig).
257        pub use crate::graph::features::temporal::{
258            node_is_temporally_valid, node_overlaps_range, node_passes_context,
259        };
260    }
261
262    /// Graph algorithms — pathfinding, components, centrality, community
263    /// detection (the typed, direct-call surface). Every binding that
264    /// exposes a typed `shortest_path()` / `pagerank()` / `louvain()`
265    /// method reaches these; they all take `&DirGraph` + plain params and
266    /// return the result structs below. (Per-query algorithm access is
267    /// also available through Cypher procedures; this is the typed-result
268    /// path for bindings that want structs, not result rows.) Lifted in
269    /// api-sealing roadmap Piece 2 (`vector_search` + `VectorSearchResult`
270    /// added in Piece 3b once `CurrentSelection` was lifted to api — vector
271    /// search is scoped to a selection).
272    pub mod algorithms {
273        pub use crate::graph::algorithms::graph_algorithms::{
274            all_paths, are_connected, betweenness_centrality, closeness_centrality,
275            connected_components, degree_centrality, get_node_info, get_path_connections,
276            label_propagation, louvain_communities, node_degree, pagerank, shortest_path,
277            shortest_path_cost, shortest_path_cost_batch, shortest_path_cost_weighted,
278            shortest_path_weighted, weakly_connected_components, CentralityResult, CommunityResult,
279            PathNodeInfo, PathResult,
280        };
281        pub use crate::graph::algorithms::hnsw::HnswParams;
282        pub use crate::graph::algorithms::vector::{
283            vector_search, DistanceMetric, VectorSearchResult,
284        };
285        pub use crate::graph::algorithms::Interrupt;
286    }
287
288    /// Timeseries date/query helpers — the pure date-parsing and
289    /// range-finding utilities behind inline timeseries support.
290    /// `parse_date_query` ("2013" / "2010..2015" → `NaiveDate` +
291    /// `DatePrecision`), `expand_end`, `date_from_ymd`, `find_range`, and
292    /// the validators are plain functions every binding's date handling
293    /// reaches; `TimeseriesConfig` / `NodeTimeseries` are the config/data
294    /// types. Lifted in roadmap Piece 2. (The KG-construction-level
295    /// `InlineTimeseriesConfig` / `TimeSpec` live in the api root.)
296    pub mod timeseries {
297        pub use crate::graph::features::timeseries::{
298            date_from_ymd, expand_end, find_range, parse_date_query, validate_channel_length,
299            validate_keys_sorted, validate_resolution, DatePrecision, InlineTimeseriesConfig,
300            NodeTimeseries, TimeSpec, TimeseriesConfig,
301        };
302    }
303
304    /// Schema/graph introspection — the compute primitives behind
305    /// `describe()` / schema overview (connectivity, per-type stats,
306    /// neighbor schema) + the detail-level enums + a bug-report writer.
307    /// The typed schema-discovery surface every binding builds its
308    /// agent-facing schema from. Lifted in roadmap Piece 3 cleanup.
309    pub mod introspection {
310        pub use crate::graph::introspection::bug_report::write_bug_report;
311        /// Debug-string helpers (schema / selection dumps) for diagnostics.
312        pub use crate::graph::introspection::debugging;
313        pub use crate::graph::introspection::describe::{compute_description, mcp_quickstart};
314        pub use crate::graph::introspection::schema_overview::{
315            compute_connection_type_stats, compute_neighbors_schema, compute_property_stats,
316            compute_schema,
317        };
318        pub use crate::graph::introspection::{
319            compute_type_connectivity, derive_edge_counts_from_triples, schema_overview_to_json,
320            ConnectionDetail, ConnectionTypeStats, CypherDetail, FluentDetail, SchemaOverview,
321            EXACT_PROPERTY_STATS_MAX_NODES,
322        };
323    }
324
325    /// Graph I/O: `.kgl` load/save, format exporters (GraphML / GEXF /
326    /// D3-JSON / CSV), the N-Triples (RDF) streaming loader + progress
327    /// callbacks, embedding-vector file export/import, and streaming
328    /// disk subset export.
329    pub mod io {
330        pub use crate::graph::io::export::{
331            to_csv, to_csv_dir, to_d3_json, to_gexf, to_graphml, to_text,
332        };
333        /// Embedding-vector file export / import.
334        pub use crate::graph::io::file::{
335            export_embeddings_to_file, import_embeddings_from_file, EmbeddingExportFilter,
336            ImportStats,
337        };
338        /// `.kgl` load / save (the canonical persistence format).
339        pub use crate::graph::io::file::{
340            load_file, load_kgl_bytes, prepare_save, save_graph, save_graph_with, write_kgl,
341            write_kgl_to, write_kgl_with,
342        };
343        pub use crate::graph::io::ntriples::{
344            load_ntriples, Cancelled, NTriplesConfig, ProgressEvent, ProgressSink, ProgressValue,
345        };
346        pub use crate::graph::io::open::{
347            open_or_create_graph, GraphFileIdentity, GraphWriterLease, OpenDisposition,
348            OpenGraphResult,
349        };
350        /// General-purpose RDF loader (Turtle / N-Triples / N-Quads /
351        /// TriG). Gated behind the `rdf` Cargo feature.
352        #[cfg(feature = "rdf")]
353        pub use crate::graph::io::rdf::{load_rdf, RdfConfig, RdfStats};
354        /// Streaming disk subset export (bounded-memory subgraph save).
355        pub use crate::graph::mutation::subgraph_streaming::{
356            pass_a_scan, pass_a_scan_to_file, save_subset, save_subset_streaming_disk, RankIndex,
357            SubsetSpec,
358        };
359    }
360
361    /// Storage backend configuration — the in-memory / mmap / disk backends
362    /// (`GraphBackend` + `DiskGraph` / `MappedGraph` constructors), the
363    /// per-type lookup, and the embedding store. CLAUDE.md designates
364    /// storage-backend configuration a direct-api concern; these let a
365    /// binding open / inspect a graph in a specific storage mode and manage
366    /// embeddings. Lifted in roadmap Piece 4 (the hard-seal gateway).
367    pub mod storage {
368        pub use crate::graph::schema::EmbeddingStore;
369        pub use crate::graph::storage::backend::GraphBackend;
370        pub use crate::graph::storage::disk::graph::DiskGraph;
371        pub use crate::graph::storage::lookups::TypeLookup;
372        /// The cross-binding create-in-mode builder: resolve a mode string to
373        /// a [`StorageMode`] and build a fresh graph in that backend. Shared by
374        /// the wheel (`storage='mapped'/'disk'`), the bolt/mcp servers
375        /// (`--storage`), and the C ABI (`kglite_graph_new_in_mode`).
376        pub use crate::graph::storage::mode::{new_dir_graph_in_mode, StorageMode};
377        pub use crate::graph::storage::MappedGraph;
378    }
379
380    /// Durable transactions — the write-ahead log (append / recover / replay)
381    /// and the write-capture recording layer behind a binding's `durable()`
382    /// feature. The in-process WAL mechanism (distinct from the checkpoint
383    /// save in `io`). Lifted in roadmap Piece 4.
384    pub mod durable {
385        pub use crate::graph::mutation::wal_replay::apply_frames;
386        pub use crate::graph::storage::recording::{resolve_ops, RecordingGraph};
387        pub use crate::graph::wal::{recover, wal_path, Wal, WalFrame};
388    }
389
390    /// Code-tree — build a queryable graph from source files, map a path to
391    /// its language, and resolve / locate code entities. The code-graph
392    /// surface (parser + the `Type::method` entity helpers + source-location
393    /// types). Consolidated in the api-organization pass.
394    pub mod code_tree {
395        pub use crate::code_tree::builder::run_with_options as build_code_tree;
396        pub use crate::code_tree::parsers::language_for_path;
397        /// Multi-rev merge — one graph spanning N git revisions via shared
398        /// identity + `revs` / `rev_fp` list props (B.2b). The wheel's
399        /// `code_tree.build(revs=[...])` and the MCP server's rev-aware
400        /// activation hook are its two bindings.
401        pub use crate::code_tree::rev::{build_code_tree_revs, dedup_revs};
402        pub use crate::graph::handle::{
403            code_entity_context, find_code_entities, resolve_code_entity, source_location,
404            CodeContextLookup, CodeEntityContext, CodeEntityMatch, CODE_TYPES,
405        };
406        pub use crate::graph::{SourceLocation, SourceLookup};
407    }
408
409    /// Blueprint loader + builder — declarative graph construction
410    /// from a YAML/JSON spec + a directory of CSVs. The wheel's
411    /// `from_blueprint` is a thin ergonomics wrapper around
412    /// [`load_blueprint_file`] + [`build`]; future bindings (Go,
413    /// JS, JVM, …) call these directly.
414    pub mod blueprint {
415        pub use crate::graph::blueprint::build::{build, BuildReport, FlatSpec};
416        pub use crate::graph::blueprint::json_records::{from_records, RecordsReport};
417        pub use crate::graph::blueprint::schema::{
418            load_blueprint_file, AggregateEdge, Blueprint, CalendarLink, ComputeOp, Connections,
419            FkEdge, JunctionEdge, NodeSpec, Settings, TimeKey, TimeseriesSpec,
420        };
421    }
422
423    /// Cypher parser + planner + executor primitives. Downstream
424    /// consumers can build their own custom Cypher pipelines using
425    /// these items; for the canonical pipeline see [`session`].
426    pub mod cypher {
427        pub use crate::graph::languages::cypher::ast::{
428            CypherQuery, Expression, OutputFormat, ReturnItem,
429        };
430        pub use crate::graph::languages::cypher::executor::write::execute_mutable;
431        pub use crate::graph::languages::cypher::executor::CypherExecutor;
432        pub use crate::graph::languages::cypher::generate_explain_result;
433        pub use crate::graph::languages::cypher::is_mutation_query;
434        pub use crate::graph::languages::cypher::parse_with_mutation_check;
435        pub use crate::graph::languages::cypher::parser::parse_cypher;
436        pub use crate::graph::languages::cypher::planner;
437        pub use crate::graph::languages::cypher::planner::mark_lazy_eligibility;
438        pub use crate::graph::languages::cypher::planner::schema_check::validate_schema;
439        pub use crate::graph::languages::cypher::planner::simplification::rewrite_text_score;
440        pub use crate::graph::languages::cypher::result::{
441            materialise_lazy, materialise_lazy_range, materialise_lazy_row, CypherResult,
442            LazyResultDescriptor,
443        };
444        /// Operator-declared value codecs — position-scoped, bidirectional
445        /// literal conversions (`'Q42'` ↔ `42`) bound to a property. Bindings
446        /// build a `Vec<ValueCodec>` (e.g. from a YAML manifest) and pass it via
447        /// `session::ExecuteOptions::value_codecs`. See `value_codec` module
448        /// docs for the safety model.
449        pub use crate::graph::languages::cypher::value_codec::{CodecKind, StoredType, ValueCodec};
450        // Specific Cypher-pipeline items a binding implementing a native
451        // `cypher()` method (the wheel) reaches. Exposed INDIVIDUALLY — not as
452        // whole `ast`/`executor`/`parser`/`result` submodules — so the rest of
453        // the executor/parser internals stay un-exported and the optimizer can
454        // keep inlining the per-query hot path. (Re-exporting the whole
455        // executor module measurably regressed cypher micro-query latency by
456        // ~60% on tiny graphs — roadmap Piece 4 perf follow-up.)
457        pub use crate::graph::languages::cypher::executor::helpers::{
458            resolve_edge_property, resolve_node_property,
459        };
460        pub use crate::graph::languages::cypher::optimize;
461        pub use crate::graph::languages::cypher::planner::schema_check::collect_unknown_pattern_warnings;
462        pub use crate::graph::languages::cypher::result::{
463            ClauseStats, EdgeBinding, MutationStats, QueryDiagnostics, ResultRow,
464        };
465    }
466
467    /// Canonical query + transaction surface — single source of
468    /// truth for the Cypher pipeline + snapshot/working CoW
469    /// transaction model. See `docs/rust/session.md`.
470    pub mod session {
471        pub use crate::graph::session::{
472            execute_mut, execute_read, resolve_noderefs, CommitOutcome, ExecuteOptions,
473            ExecuteOutcome, Session, Transaction,
474        };
475    }
476
477    /// Dataset fetch + extract building blocks for bindings that
478    /// want to wrap SEC EDGAR, Sodir (Norwegian Continental Shelf),
479    /// or Wikidata. Each submodule re-exports the same surface the
480    /// Python wheel uses today via `_sec_internal` / `_sodir_internal`
481    /// / `_wikidata_internal`; future Go / JS / JVM bindings consume
482    /// the same items here through the stable api namespace.
483    ///
484    /// **Lifecycle orchestration is NOT in core.** The "fetch what's
485    /// missing, build if cache is stale, return a ready-to-query
486    /// graph" loop lives in each binding's wrapper (the Python
487    /// wheel's wrappers at `kglite/datasets/*/wrapper.py` are the
488    /// reference implementation). The engine ships the building
489    /// blocks; bindings compose them in their own language idiom.
490    /// See `docs/rust/implementing-a-binding.md` → "Wrapping a
491    /// dataset for your binding" for the pattern.
492    ///
493    /// **All `fetch_*` entry points are synchronous.** They run to
494    /// completion on the calling thread, backed by the shared
495    /// `datasets::http` client (ureq + rate gate + retry). No async
496    /// runtime is needed — bindings call them directly and release the
497    /// GIL / manage threads in their own idiom.
498    pub mod datasets {
499        /// SEC EDGAR — quarterly filings index, bulk submissions
500        /// archive, per-form fetchers (Form 3/4/5, 13F, 8-K, SC 13D/G,
501        /// DEF 14A, Form 144, Exhibit 21, XBRL company facts).
502        #[cfg(feature = "sec")]
503        pub mod sec {
504            // Workdir layout, storage-mode sizing, slicing + the error type.
505            pub use crate::datasets::sec::{
506                pick_storage_mode, predict_graph_size_gb, SecError, SliceSpec, StorageMode,
507                Workdir, YearRange,
508            };
509            // HTTP client + per-form fetch entry points. Synchronous —
510            // call directly (no runtime needed); backed by the shared
511            // `DatasetClient` (ureq + rate gate + retry).
512            pub use crate::datasets::sec::{
513                fetch_13f_info_table, fetch_company_facts, fetch_company_submission,
514                fetch_company_tickers, fetch_exhibit21_attachment, fetch_filing_primary_doc,
515                fetch_form4_filing, fetch_quarterly_master_idx, fetch_submissions_bulk, FetchMode,
516                SecClient,
517            };
518            // Form-type → fetch-bucket resolution + per-filing dispatch
519            // planning (reads filing_index.csv, applies CIK/year/form filters).
520            pub use crate::datasets::sec::{
521                all_buckets, prepare_dispatch_plan, resolve_fetch_buckets, DispatchScope,
522                SecFormBucket,
523            };
524            // company_tickers.json parser + the raw→processed extract pipeline.
525            pub use crate::datasets::sec::{parse_tickers_json, run_all, ExtractReport};
526        }
527
528        /// Sodir — Norwegian Continental Shelf petroleum data
529        /// (fields, wells, prospects, licences, …) via the
530        /// ArcGIS FactMaps REST API.
531        #[cfg(feature = "sodir")]
532        pub mod sodir {
533            pub use crate::datasets::sodir::{SodirError, Workdir};
534            // Single synchronous fetch entry — pulls all referenced
535            // datasets into csv/, applies preprocessing, returns the
536            // report. Call directly (no runtime needed); backed by the
537            // shared `DatasetClient` (ureq + rate gate + retry).
538            pub use crate::datasets::sodir::{fetch_all, FetchAllReport};
539            // Blueprint utilities the wheel composes with from_blueprint.
540            pub use crate::datasets::sodir::{datasets_used_by_blueprint, merge_blueprint_json};
541        }
542
543        /// Wikidata — resumable download of the
544        /// `latest-truthy.nt.bz2` RDF dump. Building the graph from
545        /// the dump is a separate concern (the wheel uses
546        /// `KnowledgeGraph::load_ntriples`); this surface is the
547        /// dump-management half only.
548        #[cfg(feature = "wikidata")]
549        pub mod wikidata {
550            pub use crate::datasets::wikidata::{
551                ensure_dump, remote_last_modified, WikidataError, Workdir,
552            };
553            // Cache-freshness decision — every binding's `open()` flow asks
554            // the same question; the decision lives in core, each binding
555            // handles the outcome (verbose prints, process-local cache) in its
556            // own idiom. Lifted from `kglite/datasets/wikidata.py`.
557            pub use crate::datasets::wikidata::{decide, CacheDecision, FreshnessInputs};
558        }
559    }
560}