anapao/lib.rs
1// SPDX-FileCopyrightText: 2026 Bruno Meilick
2// SPDX-License-Identifier: LicenseRef-Anapao-FreeUse-NoCopy-NoDerivatives
3//
4// All rights reserved.
5//
6// This file is part of Anapao and is proprietary software.
7// Unauthorized copying, modification, or distribution is prohibited.
8
9//! Anapao — deterministic simulation testing utility.
10//!
11//! ## Concepts
12//! - `ScenarioSpec`: declarative simulation graph (nodes, edges, end conditions, metrics).
13//! - `RunConfig`: deterministic single-run controls (`seed`, `max_steps`, capture options).
14//! - `BatchConfig`: deterministic Monte Carlo controls (`runs`, `base_seed`, execution mode).
15//! - `BatchRunTemplate`: seed-agnostic per-run defaults used by `BatchConfig`.
16//! - `Expectation`: typed assertions evaluated against run or batch reports.
17//! - Artifacts: manifested CI-friendly outputs (`events.jsonl`, `series.csv`, `summary.csv`, ...).
18//!
19//! ## Deterministic Single Run
20//! ```rust
21//! use anapao::{Simulator, testkit};
22//! use anapao::types::MetricKey;
23//!
24//! let compiled = Simulator::compile(testkit::fixture_scenario()).unwrap();
25//! let report = Simulator::run(&compiled, &testkit::deterministic_run_config()).unwrap();
26//!
27//! assert!(report.completed);
28//! assert_eq!(report.steps_executed, 3);
29//! assert_eq!(report.final_metrics.get(&MetricKey::fixture("sink")), Some(&3.0));
30//! ```
31//!
32//! ## Deterministic Batch (Monte Carlo)
33//! ```rust
34//! use anapao::{Simulator, testkit};
35//! use anapao::types::MetricKey;
36//!
37//! let compiled = Simulator::compile(testkit::fixture_scenario()).unwrap();
38//! let batch = Simulator::run_batch(&compiled, &testkit::deterministic_batch_config()).unwrap();
39//!
40//! assert_eq!(batch.completed_runs, batch.requested_runs);
41//! assert!(batch.runs.windows(2).all(|window| window[0].run_index < window[1].run_index));
42//! assert!(batch.aggregate_series.contains_key(&MetricKey::fixture("sink")));
43//! ```
44//!
45//! ## Assertions Plus Event Stream
46//! ```rust
47//! use anapao::{Simulator, testkit};
48//! use anapao::assertions::{Expectation, MetricSelector};
49//! use anapao::events::VecEventSink;
50//! use anapao::types::MetricKey;
51//!
52//! let compiled = Simulator::compile(testkit::fixture_scenario()).unwrap();
53//! let expectations = vec![Expectation::Equals {
54//! metric: MetricKey::fixture("sink"),
55//! selector: MetricSelector::Final,
56//! expected: 3.0,
57//! }];
58//!
59//! let mut sink = VecEventSink::new();
60//! let (_report, assertion_report) = Simulator::run_with_assertions_and_sink(
61//! &compiled,
62//! &testkit::deterministic_run_config(),
63//! &expectations,
64//! &mut sink,
65//! )
66//! .unwrap();
67//!
68//! assert!(assertion_report.is_success());
69//! assert!(sink
70//! .events()
71//! .iter()
72//! .any(|event| event.event_name() == "assertion_checkpoint"));
73//! ```
74//!
75//! ## Full Playbook (Setup -> Run -> Assert -> Artifacts)
76//! ```no_run
77//! use anapao::{Simulator, testkit};
78//! use anapao::artifact::write_run_artifacts_with_assertions;
79//! use anapao::assertions::{Expectation, MetricSelector};
80//! use anapao::events::VecEventSink;
81//! use anapao::types::MetricKey;
82//!
83//! // 1) Setup scenario + compile.
84//! let scenario = testkit::fixture_scenario();
85//! let compiled = Simulator::compile(scenario).unwrap();
86//!
87//! // 2) Setup run config + expectations.
88//! let run_config = testkit::deterministic_run_config();
89//! let expectations = vec![Expectation::Equals {
90//! metric: MetricKey::fixture("sink"),
91//! selector: MetricSelector::Final,
92//! expected: 3.0,
93//! }];
94//!
95//! // 3) Run simulation and evaluate assertions.
96//! let mut sink = VecEventSink::new();
97//! let (run_report, assertion_report) = Simulator::run_with_assertions_and_sink(
98//! &compiled,
99//! &run_config,
100//! &expectations,
101//! &mut sink,
102//! )
103//! .unwrap();
104//! assert!(assertion_report.is_success());
105//!
106//! // 4) Persist artifact pack for CI/debugging.
107//! let output_dir = std::env::temp_dir().join("anapao-doc-playbook");
108//! let manifest = write_run_artifacts_with_assertions(
109//! &output_dir,
110//! &run_report,
111//! sink.events(),
112//! Some(&assertion_report),
113//! )
114//! .unwrap();
115//! assert!(manifest.artifacts.contains_key("manifest"));
116//! ```
117
118#![forbid(unsafe_code)]
119
120pub mod artifact;
121pub mod assertions;
122pub mod batch;
123pub mod engine;
124pub mod error;
125pub mod events;
126pub mod expr;
127pub mod prelude;
128pub mod rng;
129pub mod simulator;
130pub mod stats;
131pub mod stochastic;
132pub mod testkit;
133pub mod types;
134pub mod validation;
135
136#[cfg(feature = "analysis-polars")]
137pub mod analysis;
138
139pub use assertions::{AssertionReport, Expectation, MetricSelector};
140pub use events::{EventSink, VecEventSink};
141pub use simulator::Simulator;
142pub use types::{
143 BatchConfig, BatchReport, BatchRunTemplate, CaptureConfig, EndConditionSpec, ExecutionMode,
144 MetricKey, RunConfig, RunReport, ScenarioSpec, TransferSpec,
145};
146
147#[cfg(doctest)]
148#[doc = include_str!("../README.md")]
149mod readme_doctest {}