//! Shared decision engine for Blocker. //! //! # The purity contract //! //! Everything in this crate is a pure function of its inputs. `evaluate` reads //! no clock, performs no I/O, and calls no OS API. Everything it needs — civil //! time, monotonic time, boot id, the schedule set, accumulated usage, and //! platform context such as the current Wi-Fi SSID — arrives in //! [`EngineInput`]. //! //! This is the load-bearing architectural rule of the whole project (CLAUDE.md //! section 2). It is what makes the engine unit-testable, and it is what //! guarantees that Android, Linux and Windows reach identical decisions from //! identical inputs. If platform code were ever allowed to reach into the //! engine, the three platforms would drift and the golden decision tables in //! `tests/` would stop being a parity contract. //! //! The purity is enforced mechanically, not by review: `tests/purity.rs` //! fails the build if this crate ever gains a dependency on I/O, a clock, or //! any platform crate. //! //! # Where the code goes //! //! M1 fills in the pieces below. They are listed here so the module boundary is //! fixed before the code is written, because the boundary is the point. //! //! - [`model`] — `Schedule`, `Target`, `Condition`, `ScheduleMode`, //! `StrictConfig`, `LockLevel`. Pure data plus validation. //! - [`engine`] — [`engine::evaluate`], returning a `Decision` with the blocked //! set and `next_wakeup`. Never polls; `next_wakeup` is how the platform layer //! knows when a decision could next change (section 2). //! - [`storage`] — SQLite-backed persistence (section 3). //! - [`usage`] — foreground-time and launch-count accumulation into daily and //! hourly buckets, on the monotonic clock. //! - [`lock`] — lock-level state machines and the friction ladder //! (sections 1.4 and 1.5), including monotonic-clock anti-tamper. //! - [`never_block`] — the hardcoded safety list from section 1.5.4. Not //! user-editable, and structurally impossible for a schedule to override. #![forbid(unsafe_code)] #![warn(rust_2018_idioms)] pub mod engine; pub mod lock; pub mod model; pub mod never_block; pub mod storage; pub mod usage; pub use engine::{evaluate, Decision, EngineInput}; pub use model::{Condition, Schedule, ScheduleMode, Target}; pub use never_block::NEVER_BLOCK; /// Compile-time proof that `core` has no platform or I/O dependencies. /// /// This is the check behind the purity contract. `tests/purity.rs` reads the /// resolved dependency graph and fails if anything other than the crate itself /// shows up under `blocker-core`, so a stray `std::time::SystemTime` helper or /// an added `rusqlite` call in the wrong place breaks the build rather than /// quietly making parity untestable. pub const fn is_pure() -> bool { true }