graphrefly_core/lib.rs
1//! `GraphReFly` handle-protocol core dispatcher.
2//!
3//! This crate is the heart of the protocol: dispatcher, message tiers,
4//! batch coalescing, wave engine, dep tracking, equals-substitution,
5//! first-run gate, PAUSE/RESUME with lockIds, INVALIDATE broadcast,
6//! versioning lifecycle, atomic dep mutation (`set_deps`).
7//!
8//! It operates entirely on opaque [`HandleId`](handle::HandleId) integers —
9//! user values `T` never enter the core. Per-language bindings (napi-rs for
10//! JavaScript, pyo3 for Python, wasm-bindgen for WASM) hold the
11//! value-to-handle registry. Equals-substitution under
12//! `EqualsMode::Identity` is a `u64` compare with zero FFI; user-fn
13//! invocation is the only mandatory boundary crossing per fn fire.
14//!
15//! # Status (2026-05-03)
16//!
17//! M1 first slice — warm-up modules ([`message`], [`handle`], [`clock`],
18//! [`boundary`]). The dispatcher itself, batch engine, PAUSE/RESUME, and
19//! `set_deps` follow incrementally. See
20//! `~/src/graphrefly-ts/docs/implementation-plan.md` Phase 13.7 for the
21//! full slice plan; reference impl at
22//! `~/src/graphrefly-ts/src/__experiments__/handle-core/`.
23//!
24//! # Safety
25//!
26//! No `unsafe` is permitted in this crate or anywhere in the workspace.
27//! Enforced by `#![forbid(unsafe_code)]` at the root. See `CLAUDE.md`
28//! Rust invariant 1.
29
30#![forbid(unsafe_code)]
31#![cfg_attr(not(feature = "std"), no_std)]
32#![warn(rust_2018_idioms, unreachable_pub)]
33#![warn(clippy::pedantic)]
34// `clippy::pedantic` includes a few that are too noisy for this codebase.
35#![allow(
36 clippy::module_name_repetitions,
37 clippy::missing_errors_doc,
38 // Some Core methods take `&self` for architectural consistency (they're
39 // conceptually Core methods even if they don't read self state directly,
40 // since the state lives in CoreState behind self.state.lock()). The lint
41 // would force them into associated fns, breaking the consistent API.
42 clippy::unused_self,
43 // doc_markdown false-positives on protocol identifiers like `T`, `JS`, etc.
44 clippy::doc_markdown,
45)]
46
47mod batch;
48pub mod boundary;
49pub mod clock;
50pub mod handle;
51pub mod hash;
52pub mod message;
53pub mod node;
54pub(crate) mod op_state;
55pub mod subgraph;
56#[cfg(feature = "tokio")]
57pub mod timer;
58pub mod topology;
59
60pub use batch::BatchGuard;
61
62pub use boundary::{BindingBoundary, CleanupTrigger, DepBatch, FnEmission, FnResult};
63pub use clock::{monotonic_ns, wall_clock_ns};
64pub use handle::{FnId, HandleId, LockId, NodeId, NO_HANDLE};
65pub use hash::sha256_hex;
66pub use message::{Message, Messages};
67pub use node::{
68 Core, DeferredProducerOp, EqualsMode, NodeFnOrOp, NodeKind, NodeOpts, NodeRegistration,
69 OperatorOp, OperatorOpts, PartitionOrderViolation, PausableMode, PauseError, RegisterError,
70 ResumeReport, SetDepsError, SetPausableModeError, Sink, SubscribeError, Subscription,
71 TerminalKind, UpError, WeakCore,
72};
73pub use subgraph::SubgraphId;
74pub use topology::{TopologyEvent, TopologySink, TopologySubscription};
75
76/// Phase H+ STRICT (D115): test-only thread-local accessors for
77/// verifying the H+ check's bookkeeping stays clean across panic
78/// unwinds. Re-exported `pub` (gated by
79/// `cfg(any(test, debug_assertions))`) so integration tests under
80/// `tests/` can call them. Not part of the v1 stable API.
81#[cfg(any(test, debug_assertions))]
82pub use node::held_snapshot_for_tests;