1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! `kglite::api::session` — canonical query + transaction surface.
//!
//! Pure-Rust, no PyO3, no async, no transport. Bindings (pyapi,
//! bolt-server, mcp-server, future Go/TS) wrap this module's types
//! and free functions. The Cypher pipeline orchestration + the
//! snapshot/working CoW transaction mechanics live here exactly
//! once.
//!
//! **Why this module exists.** Before Phase E, the same pipeline
//! (parse → validate → rewrite_text_score → optimize → mark_lazy →
//! mutation gate → execute) was duplicated three times — once in
//! `src/graph/pyapi/kg_core.rs::cypher`, once in
//! `crates/kglite-mcp-server/src/tools.rs::cypher_query`, and once
//! in `crates/kglite-bolt-server/src/backend.rs`. The CoW
//! transaction state was duplicated twice (pyapi/transaction.rs +
//! bolt-server backend). That drift cost the team twice in real
//! bugs: `validate_schema` was missing from two consumers; the
//! bolt-server's incorrect `mark_lazy_eligibility` call returned
//! 0 rows for any non-ORDER-BY RETURN until the robustness pass
//! surfaced it.
//!
//! See [`bolt_implementation.md`](../../../bolt_implementation.md)
//! Phase E for the full rationale.
//!
//! ## Surface
//!
//! - [`Session`] — shared graph state with commit-swap semantics
//! (`Arc<DirGraph>` behind a `Mutex` for atomic swap). Bindings
//! wrap a Session inside their own concurrency model.
//! - [`Transaction`] — snapshot/working CoW state, built via
//! [`Session::begin`] and finalized via [`Session::commit`] or
//! [`Session::rollback`].
//! - [`execute_read`] / [`execute_mut`] — pure-Rust pipeline
//! orchestration. Bindings call these for every Cypher query
//! (auto-commit reads use `execute_read` against a snapshot;
//! in-transaction queries use the helpers on `Session` that
//! route reads vs writes against `Transaction::current()` vs
//! `Transaction::working_mut()`).
//! - [`ExecuteOptions`] — single struct for all per-query knobs
//! (params, deadline, max_rows, lazy_eligible flag, disabled
//! planner passes, optional embedder reference).
//! - [`ExecuteOutcome`] — wraps `CypherResult` with `is_mutation`,
//! `output_format`, `explain` flags that callers need for
//! serialization decisions.
//! - [`CommitOutcome`] — `NoWritesNoOp` / `Committed` /
//! `ConflictDetected` so the binding maps to its own error type
//! (PyErr / BoltError / etc.).
pub use ;
pub use ;
pub
pub
use crateValue;
use crateGraphBackend;
// `node_weight` is on the GraphRead trait; the wheel's import path
// did `pub use kglite_core::graph::*` glob which brought it in.
use crateGraphRead;
/// Resolve any `Value::NodeRef` entries in Cypher result rows to the
/// referenced node's `title` value. Called by bindings just before
/// emitting rows to their consumer (`PyDict`/`PyList` for the wheel,
/// `RecordMessage` for bolt-server, JSON for mcp-server). `NodeRef`
/// is an internal sentinel used by `collect()` / `WITH` to preserve
/// node identity through the planner — it should never appear in
/// output.
///
/// Lifted from the wheel crate in 0.10.1 so every binding can call
/// the same post-execute cleanup instead of re-implementing it.