omgbase_surface/lib.rs
1//! # omgbase-surface
2//!
3//! The omgbase surface, Rust implementation of `spec/surface`: the OQX
4//! **query binding** over [`omgbase_store::Store`] ([`context`], [`mod@query`],
5//! the tier-3 pushdown [`planner`] and its [`translate`] seam, the
6//! store-backed indexes nested blocks probe — [`store_index`]),
7//! the dates and durations of §1.3 ([`dates`]),
8//! the document and block **reads** ([`read`]), the **history** reads
9//! ([`history`]), link health ([`links`]), the `graph` macro ([`graph`]), and
10//! the **MCP tool catalog** as a library ([`catalog`]): a table of tools with
11//! JSON-schema inputs and handlers dispatching into the store, with the
12//! error envelope of §4. Transport-agnostic — the `omgbase` binary serves
13//! [`catalog::Surface`] over MCP stdio.
14//!
15//! ```
16//! use omgbase_store::Store;
17//! use omgbase_surface::catalog::Surface;
18//! use serde_json::json;
19//!
20//! let mut store = Store::open_in_memory()?;
21//! let repo = store.create_repo("notes")?;
22//! let mut surface = Surface::new(store, &repo, None);
23//! let out = surface.call("observe", json!({ "path": "a.md", "content": "# Title\n\nFirst.\n" }));
24//! assert!(!out.is_error);
25//! let res = surface.call("query", json!({ "query": "select title from docs" }));
26//! assert_eq!(res.body["hits"][0]["title"], "Title");
27//! # Ok::<(), omgbase_store::Error>(())
28//! ```
29
30#![forbid(unsafe_code)]
31// The error envelope carries a code, a message and an optional JSON `data`
32// (~128 bytes); every failure is a cold path at the tool boundary, so the
33// `Result` size is not worth boxing.
34#![allow(clippy::result_large_err)]
35
36pub mod arguments;
37pub mod catalog;
38pub mod context;
39pub mod cursor;
40pub mod dates;
41pub mod descriptions;
42pub mod error;
43pub mod fixes;
44pub mod graph;
45pub mod history;
46pub mod links;
47pub mod names;
48pub mod paths;
49pub mod planner;
50pub mod query;
51pub mod read;
52pub mod reference;
53pub mod select;
54pub mod store_index;
55pub mod translate;
56pub mod version;
57
58pub use catalog::{MINIMAL_TOOLS, Profile, Surface, ToolOutcome, ToolSpec};
59pub use context::{SemanticVec, StoreContext, Target, glob_to_like};
60pub use cursor::{decode_cursor, decode_path_cursor, encode_cursor};
61pub use error::{Result, SurfaceError};
62pub use names::{UnknownNames, VocabularyCache};
63pub use paths::{reference_path, storage_path};
64pub use planner::SqlitePlanner;
65pub use query::{
66 OqxResult, QueryOptions, collect_semantic_phrases, embed_phrases, query, query_ast,
67 rewrite_query,
68};
69pub use version::{BuildInfo, MCP_PROTOCOL_VERSION, version_info};
70
71/// The `spec/surface/VERSION` this crate implements (`major.minor`).
72pub const SPEC_VERSION: &str = "4.8";
73
74/// This crate's own version (`Cargo.toml`), for the surface's `version` tool.
75pub const VERSION: &str = env!("CARGO_PKG_VERSION");
76
77#[cfg(test)]
78mod version_tests {
79 use super::SPEC_VERSION;
80
81 /// The crate line tracks the spec it implements (AGENTS.md "Spec
82 /// tracking"): `major.minor` of `Cargo.toml` equals `SPEC_VERSION`. Every
83 /// other spec crate pins this; the surface had relied on `release plan`
84 /// alone, so a 4.8 spec over a 4.7.x crate went unnoticed by `cargo test`.
85 #[test]
86 fn spec_version_matches_the_crate_line() {
87 let crate_version = env!("CARGO_PKG_VERSION");
88 assert!(
89 crate_version.starts_with(&format!("{SPEC_VERSION}.")),
90 "crate {crate_version} must track spec {SPEC_VERSION}.x"
91 );
92 }
93}