Architecture and Rust API
The dependency direction is intentionally simple:
validated probability types
|
numerical methods and evaluation
|
question / evidence / forecast lifecycle
|
separate JSON + SQLite adapter
|
calling agent application
The core cannot open a database, fetch a source, invoke a model, or start a background task. This keeps numerical behavior testable and lets a caller choose its own runtime and data infrastructure.
Core module map
| Module | Main types and operations |
|---|---|
probability | Probability, Categorical, logit/sigmoid, entropy |
bayes | likelihood update, LR update, sensitivity, BetaPrior |
reference | attributable case counts, empirical rates, quantiles |
aggregate | weighted arithmetic/logit pools, recalibration mapping |
decompose | conditional chains, Frechet bounds, unions, mixtures, indicators, event-window probability |
decision | expected utility, best action, value of information |
score | Brier conventions, log loss, ranked score, CRPS, streaming Brier |
calibration | frozen question records, grouping, diagnostic report |
evaluation | paired cases, holdout validation, time grids, cluster bootstrap, calibration selection |
workflow | questions, evidence, forecasts, adjudications, ledger, updates, challenges and panels |
Probability has a private representation. Construct it with new or TryFrom<f64> so invalid values cannot enter ordinary safe Rust code. Public workflow records use validated probability values but still require lifecycle validation when appended to a ledger.
extern crate supercast;
use supercast::Probability;
assert!(Probability::new(f64::NAN).is_err());
assert!(Probability::new(1.01).is_err());
let p = Probability::try_from(0.25)?;
assert_eq!(p.complement().get(), 0.75);
Ok::<(), supercast::Error>(())
Adapter modules
wire owns Serde/Schemars transport types. Its probability wrapper calls the core constructor during deserialization. protocol defines the request enum, response envelope and dispatch. analysis_tools translates the additional numerical/evaluation operations. store owns a SQLite connection, event replay and transactional writes. main implements bounded line input and flushed output.
The transport and core structs are separate by design. A future input format should convert through the same validated values rather than deserialize directly into private domain state. Ledger itself is not deserializable; persisted events must be replayed.
Error boundaries
The core returns supercast::Result<T> with explicit validation errors. The adapter maps those into structured error codes and messages, distinguishing malformed input, invalid models, storage failures, contention, conflicts and missing keys.
Core functions with mathematically bounded internal results sometimes construct a probability with an internal unwrap. External numbers still pass through fallible constructors. Unsafe Rust is forbidden in both project crates; dependencies such as SQLite have their own implementation contracts.
Generated Rust API pages from cargo doc --workspace --no-deps complement these books with source navigation. The JSON transport types and operation pages describe the cross-language boundary.