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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! **A database that compiles questions instead of guessing answers.**
//!
//! Most systems answer a question about documents by *similarity*: find the nearest text and return it. That
//! works until the question involves a combination (`A but not B`), a complete count, or something the
//! documents simply do not contain — where a similarity search still returns its closest guess, and a guess is
//! indistinguishable from an answer.
//!
//! SteelDB learns which categories your documents actually support, type-checks a question against them before
//! anything runs, and executes the survivors as bitwise set algebra over compressed bitmaps. A question the
//! data cannot answer is **refused**, with the alternatives that do exist.
//!
//! # Start here
//!
//! ```no_run
//! use steeldb::SteelDb;
//!
//! # let documents: Vec<String> = Vec::new();
//! // No model files needed: the vocabulary is discovered from the text.
//! let db = SteelDb::ingest(documents)?;
//!
//! // Category names come from the words the documents use, so read them before writing a query.
//! for c in db.categories() {
//! println!("can ask about {}", c.wildcard());
//! }
//!
//! match db.query("(and elevation/* (not state/negated))") {
//! Ok(answer) => println!("{} situations", answer.len()),
//! Err(refused) => println!("{refused}"), // says what the data does contain
//! }
//! # Ok::<(), steeldb::Error>(())
//! ```
//!
//! # Three verbs
//!
//! | verb | what it needs | what it costs |
//! |---|---|---|
//! | [`SteelDb::ingest`] | nothing — no models, no network | deterministic and free |
//! | [`SteelDb::query`] | nothing | microseconds |
//! | [`learn`] | credentials and a network | a model call, and a bill |
//!
//! The asymmetry is deliberate. `ingest` and `query` are pure; `learn` calls a language model, so it lives in
//! its own module, is `async`, is feature-gated, and returns a *proposal* rather than changing your vocabulary.
//! You review it and [`SteelDb::adopt`] it, at which point the same gate that governs local discovery decides
//! what survives — a model cannot add a category a deterministic test would have rejected.
//!
//! [`SteelDb`] is the whole API for most uses. [`Answer`] is a *complete* set rather than a ranked sample, so
//! counting it means something. [`Refused`] is an error rather than an empty result because those are different
//! facts, and conflating them is how a confident wrong answer gets produced.
//!
//! # The query language
//!
//! Queries are s-expressions — operation first, nested lists, as in Lisp. The whole grammar:
//!
//! | form | meaning |
//! |---|---|
//! | `category/value` | situations carrying that exact tag |
//! | `category/*` | any value in that category |
//! | `(and A B)` | intersection |
//! | `(or A B)` | union |
//! | `(not A)` | difference |
//! | `(num field op value)` | numeric comparison; `op` is `ge gt le lt eq ne` |
//! | `(evidence A :min-bel f)` | only where belief in `A` reaches `f` |
//! | `(s-path :s n (source A) (target B))` | situations on a chain sharing ≥ `n` tags per step |
//! | `(combine-ds :max-conflict f …)` | fuse independent evidence, or refuse |
//!
//! There is deliberately almost no syntax to get wrong, which matters when the author is a language model.
//!
//! # Beyond the basics
//!
//! - [`evidence`] — Dempster–Shafer belief intervals, and the conflict metric that refuses to fuse
//! contradictory sources rather than averaging them into a consensus nobody holds.
//! - [`programs`] — higher-order structure: s-paths, and the primal/dual s-filtration.
//! - [`emergent`] — how the vocabulary is discovered from prose, with no model.
//! - [`models`] — where trained weights come from. Nothing downloads without being asked.
//! - [`linter`] — the type-checker, if you want to validate without executing.
//!
//! # Installing
//!
//! The crate is published as **`hypersteeldb`** and imported as `steeldb`:
//!
//! ```toml
//! [dependencies]
//! hypersteeldb = "0.3"
//! ```
//!
//! (The bare name `steeldb` was taken on crates.io in 2023 by an unrelated project, so the package carries the
//! longer name while the import stays short.)
//!
//! # Features
//!
//! The default build is pure Rust with no model dependencies and compiles to `wasm32`.
//!
//! | feature | adds |
//! |---|---|
//! | `embed` | static embeddings + optimal-transport discovery (links a C regex library) |
//! | `onnx` | the trained span tagger |
//! | `native` | candle: HRM training and inference |
//! | `needle` | the Cactus needle3 query planner |
//! | `agent`, `bedrock`, `paddock` | LLM-driven query planning |
//! | `wasm` | browser bindings |
pub use ;
pub use ;
pub use ;
pub use InfonIndex;
pub use ;
pub use ;