Skip to main content

uor_foundation/
lib.rs

1// @generated by uor-crate from uor-ontology — do not edit manually
2
3//! UOR Foundation — typed Rust traits for the complete ontology.
4//!
5//! Version: 0.4.10
6//!
7//! This crate exports every ontology class as a trait, every property as a
8//! method, and every named individual as a constant. Implementations import
9//! these traits and provide concrete types.
10//!
11//! # Principal data path
12//!
13//! v0.2.2 establishes a single sanctioned API path. Everything else has been
14//! deleted (no proc-macro back-doors, no second constructor for sealed types):
15//!
16//! ```text
17//!  host bytes  ──▶  impl Grounding<Map = …>  ──▶  Datum<L>   [W4: kind-typed]
18//!                                                  │
19//!                                                  ▼
20//!  builder.validate_const() │ .validate()  ──▶  Validated<T, Phase>
21//!                                                  │            [W2 + W13]
22//!                                                  ▼
23//!  pipeline::run::<T, P>(unit)  ──▶  Grounded<T>
24//!                                       │            [W14]
25//!                                       ▼
26//!                            .triad() → Triad<L>     [W8]
27//!                            .certificate()          [W11: Certified<C>]
28//! ```
29//!
30//! Every contract is enforced at the type and visibility level. Sealed traits,
31//! `pub(crate)` constructors, and the v0.2.2 conformance suite (W5 ψ-leakage gate,
32//! W6 public-API snapshot) catch any deviation.
33//!
34//! # Substitution axes (per the UOR-Framework wiki)
35//!
36//! The wiki names three substitution axes the application author selects
37//! against — `HostTypes`, `HostBounds`, `Hasher`. The foundation defines
38//! the trait surface; downstream substrates declare the bound the trait
39//! must satisfy; the application's crate selects the implementation.
40//!
41//! ## `HostTypes` (target §4.1 W10)
42//!
43//! Downstream chooses representations only for the three slots that genuinely
44//! vary across host environments. Witt-level integers, booleans, IRIs, canonical
45//! bytes, and `UorTime` are foundation-owned and derived from `WittLevel`.
46//!
47//! ```no_run
48//! use uor_foundation::{HostTypes, DefaultHostTypes};
49//!
50//! // Use the canonical defaults: f64 / str / [u8].
51//! type H = DefaultHostTypes;
52//!
53//! // Or override one slot:
54//! struct EmbeddedHost;
55//! impl HostTypes for EmbeddedHost {
56//!     type Decimal = f32;          // override: tighter precision budget
57//!     type HostString = str;       // default
58//!     type WitnessBytes = [u8];    // default
59//!     const EMPTY_DECIMAL: f32 = 0.0;
60//!     const EMPTY_HOST_STRING: &'static str = "";
61//!     const EMPTY_WITNESS_BYTES: &'static [u8] = &[];
62//! }
63//! ```
64//!
65//! ## `HostBounds` (wiki ADR-018)
66//!
67//! Carries every capacity bound that varies along the principal data
68//! path: the fingerprint output width range, the trace event-count
69//! ceiling, the algebraic-level bit-width ceiling. Per ADR-018 the
70//! architecture admits no capacity bound outside `HostBounds`.
71//!
72//! ```no_run
73//! use uor_foundation::{HostBounds, DefaultHostBounds};
74//!
75//! type B = DefaultHostBounds;
76//! assert_eq!(<B as HostBounds>::FINGERPRINT_MAX_BYTES, 32);
77//! ```
78//!
79//!
80//! # Module structure
81//!
82//! - [`kernel`] — Immutable foundation: addressing, schema, operations
83//! - [`bridge`] — Kernel-computed, user-consumed: queries, resolution, partitions, proofs
84//! - [`user`] — Runtime declarations: types, morphisms, state
85//! - [`enforcement`] — Sealed types and the principal-path entry surface
86//! - [`pipeline`] — `pipeline::run::<T, P>` and the resolver dispatch
87//!
88//! # Enforcement layer
89//!
90//! [`enforcement`] provides the sealed types that v0.2.2 forbids downstream
91//! from constructing directly:
92//!
93//! **Layer 1 — Opaque witnesses.** [`enforcement::Datum`],
94//! [`enforcement::Validated`], [`enforcement::Derivation`],
95//! [`enforcement::FreeRank`], [`enforcement::Grounded`],
96//! [`enforcement::Certified`], [`enforcement::Triad`]: sealed types with
97//! private fields. Only the foundation's pipeline / resolver paths produce them.
98//!
99//! **Layer 2 — Declarative builders.** [`enforcement::CompileUnitBuilder`]
100//! and 8 others collect declarations and emit `Validated<T, Phase>` on
101//! success or [`enforcement::ShapeViolation`] with a machine-readable IRI.
102//!
103//! **Layer 3 — Term AST.** [`enforcement::Term`] and
104//! [`enforcement::TermArena`]: stack-resident, `#![no_std]`-safe expression
105//! trees. The `Term` enum's struct-variant constructors are the canonical
106//! builder API — there is no DSL macro in v0.2.2.
107//!
108//! # Foundation as a signature category (wiki ADR-019)
109//!
110//! `uor-foundation`'s vocabulary is the **signature category** of Prism's
111//! typed routes. Objects are [`pipeline::ConstrainedTypeShape`] impls under
112//! the substitution-axis selections; morphisms are typed compositions of
113//! [`PrimitiveOp`] discriminants and [`enforcement::Term::Application`]
114//! constructions.
115//!
116//! The category supports a **signature endofunctor** F whose enriched
117//! signature has one branch per [`enforcement::Term`] variant — the four
118//! first-order constructors (`Literal`, `Application`, `Lift`, `Project`),
119//! plus binding (`Variable`), case analysis (`Match`), explicit fixed-point
120//! (`Recurse`), explicit unfold (`Unfold`), and failure-promote (`Try`).
121//!
122//! [`enforcement::Term`] is F's **initial algebra**: any well-typed term
123//! tree is an element of the free term language F generates from its
124//! enriched signature, and any carrier supporting the same enriched
125//! structure admits a *unique* structure-preserving map from `Term`.
126//!
127//! [`pipeline::run`] is the **catamorphism** into the runtime carrier
128//! parameterized by the substitution axes (`HostTypes`, `HostBounds`,
129//! `Hasher`). Its dual, the **anamorphism**, is the trace-replay surface
130//! ([`enforcement::Derivation::replay`] +
131//! [`enforcement::replay::certify_from_trace`]); the trace is the
132//! anamorphism's witness object. The four UOR-domain sealed types
133//! ([`enforcement::Datum`], [`enforcement::Triad`],
134//! [`enforcement::Derivation`], [`enforcement::FreeRank`]) and the three
135//! Prism-mechanism sealed types ([`enforcement::Validated`],
136//! [`enforcement::Grounded`], [`enforcement::Certified`]) are **fixed
137//! points** of the typed pipeline endofunctor (distinct from F; see wiki
138//! section 8, Fixed Points).
139//!
140//! Initiality and uniqueness of the catamorphism hold *within each fixed
141//! choice of the three substitution axes*: for a given
142//! `(HostTypes, HostBounds, Hasher)` selection, there is exactly one
143//! F-algebra homomorphism from `Term` to the corresponding carrier. The
144//! categorical statement of ADR-018's capacity completeness is that the
145//! indexing of carriers is *total* over `HostBounds` — every
146//! capacity-bounded width that varies along the principal data path is
147//! part of the index. The substrate-vs-implementor split (ADR-007's
148//! three-position pattern) extends naturally: foundation defines F and
149//! the initial algebra; the runtime declares the bound any application's
150//! `Route` MUST satisfy and the catamorphism that compiles it; the
151//! application author selects the F-algebra by writing the model.
152//!
153//! # `PrismModel` — the application author's typed iso (wiki ADR-020)
154//!
155//! [`pipeline::PrismModel`] codifies the iso the application author
156//! declares: an `Input` feature type, an `Output` label type, and a
157//! type-level `Route` witness of the term tree mapping one to the other.
158//! The `Route` associated type is bound by [`pipeline::FoundationClosed`]
159//! — closure under foundation vocabulary, enforced at the application's
160//! compile time per UORassembly (TC-04, ADR-006). `forward()` is the
161//! catamorphism into [`pipeline::run`]'s runtime carrier; together with
162//! the `Trace`-witnessed anamorphism through
163//! [`enforcement::replay::certify_from_trace`] it forms the verifiable
164//! round-trip described in the wiki.
165//!
166//! # Witness minting (Phases 10 + 12 + 14 + 15)
167//!
168//! Path-2 ontology classes (theorem-attesting witnesses such as
169//! [`witness_scaffolds::MintBornRuleVerification`],
170//! [`witness_scaffolds::MintCompletenessWitness`], etc.) implement the
171//! sealed [`OntologyVerifiedMint`] trait. Mint a witness by populating
172//! its `Mint{Foo}Inputs<H>` bundle with non-zero handles + true
173//! attestation flags + non-empty strings, then calling
174//! `Mint{Foo}::ontology_mint::<H>(inputs)`. On structural-invariant
175//! failure each `verify_*` primitive in `crate::primitives::{family}`
176//! returns a typed [`enforcement::GenericImpossibilityWitness`] whose
177//! IRI cites the specific failing op-namespace identity (BR_*,
178//! CC_*, IH_*, FX_4, WLS_*, surfaceSymmetry).
179//!
180//! # Per-class observable views (Phase 16)
181//!
182//! [`enforcement::Validated<T, Phase>`] does not directly implement
183//! the kind-specific `Observable<H>` trait — Rust forbids multiple
184//! `Observable<H>` impls per type, and the bare blanket would return
185//! a sentinel for every kind. Consumers select an explicit kind via
186//! the inherent accessors
187//! [`Validated::as_landauer`](enforcement::Validated::as_landauer),
188//! [`Validated::as_jacobian`](enforcement::Validated::as_jacobian),
189//! [`Validated::as_carry_depth`](enforcement::Validated::as_carry_depth),
190//! [`Validated::as_derivation_depth`](enforcement::Validated::as_derivation_depth),
191//! and [`Validated::as_free_rank`](enforcement::Validated::as_free_rank).
192//! Each returns a zero-cost newtype view in [`blanket_impls`] whose
193//! `Observable<H>::value()` body delegates to the relevant primitive
194//! (`primitive_descent_metrics`, `primitive_curvature_jacobian`,
195//! `primitive_dihedral_signature`, etc.).
196//!
197//! Calling `.landauer_nats()` on the view requires the
198//! `bridge::observable::LandauerBudget` *trait* to be in scope —
199//! distinct from the `enforcement::LandauerBudget` *struct*
200//! re-exported at the crate root. Likewise for `as_jacobian` →
201//! `bridge::observable::JacobianObservable`,
202//! `as_carry_depth` → `kernel::carry::CarryDepthObservable`,
203//! `as_derivation_depth` →
204//! `bridge::derivation::DerivationDepthObservable`, and
205//! `as_free_rank` → `bridge::partition::FreeRankObservable`.
206//! `<_ as Observable<H>>::value(&view)` works for every view
207//! once `Observable` itself is in scope.
208//!
209//! # Resolvers (v0.2.2 W12)
210//!
211//! Verdict-producing resolvers are free functions in module-per-resolver
212//! organization. Each function returns a `Result<Certified<Cert>, Witness>`:
213//!
214//! - `enforcement::resolver::inhabitance::certify(input)` — inhabitance verdict
215//! - `enforcement::resolver::tower_completeness::certify(input)` — tower completeness
216//! - `enforcement::resolver::incremental_completeness::certify(input)` — incremental
217//! - `enforcement::resolver::grounding_aware::certify(unit)` — grounding-aware
218//!
219//! # Features
220//!
221//! The crate ships this feature-flag layout. Every capability the `default`
222//! build omits is opt-in; the default is `#![no_std]`-pure and alloc-free.
223//!
224//! | Feature         | Default | Adds | When to enable |
225//! |-----------------|---------|------|----------------|
226//! | `alloc`         | off     | `extern crate alloc`; alloc-backed diagnostic helpers | Heap available but no OS |
227//! | `std`           | off     | `alloc` + std-specific paths | Hosted platforms |
228//! | `libm`          | **on** (unconditional dep) | `libm`-backed `ln`, `exp`, `sqrt` for transcendental observables | Always on — required by `xsd:decimal` observables (see target §1.6) |
229//! | `serde`         | off     | `serde::{Serialize, Deserialize}` on `Trace`, `TraceEvent`, and other carriers | Exporting traces to external verifiers |
230//! | `observability` | off     | `alloc` + a `subscribe(handler: FnMut(&TraceEvent))` surface | Runtime observation of the reduction pipeline |
231//!
232//! The `default = []` posture means bare-metal targets (`thumbv7em-none-eabihf`)
233//! build without any feature flag. CI validates three configurations: the
234//! bare-metal `no_std` cross-build, the `alloc`-additive hosted build, and
235//! the `--all-features` composite. See target §1.6 and §7.5.
236//!
237//! # Scope note
238//!
239//! This crate is conformance-first: every surface the ontology specifies
240//! is present, and every surface it rejects (e.g., the deleted v0.2.1
241//! `Primitives` trait and unit-struct resolver façades) is absent. There
242//! is no migration layer, no deprecation aliases, and no compatibility
243//! shims — the crate is either in conformance with the ontology or it isn't.
244
245#![no_std]
246
247pub mod blanket_impls;
248pub mod bridge;
249pub mod enforcement;
250pub mod enums;
251pub mod kernel;
252pub mod pipeline;
253pub mod primitives;
254pub mod user;
255pub mod witness_scaffolds;
256
257pub use enums::*;
258
259pub use witness_scaffolds::OntologyVerifiedMint;
260
261pub use enforcement::{
262    BindingEntry, BindingsTable, BindingsTableError, BoundConstraint, Calibration,
263    CalibrationError, Certificate, CertificateKind, Certified, CompileUnit, CompileUnitBuilder,
264    ContentAddress, ContentFingerprint, Derivation, Grounded, GroundingCertificate, Hasher,
265    LandauerBudget, MultiplicationCertificate, Nanos, PipelineFailure, ReplayError, ShapeViolation,
266    Term, TermArena, TermList, Trace, TraceEvent, UorTime, Validated, TRACE_REPLAY_FORMAT_VERSION,
267};
268
269pub use enforcement::{
270    CartesianProductEvidence, CartesianProductMintInputs, CartesianProductWitness,
271    GenericImpossibilityWitness, NullPartition, PartitionCoproductEvidence,
272    PartitionCoproductMintInputs, PartitionCoproductWitness, PartitionHandle,
273    PartitionProductEvidence, PartitionProductMintInputs, PartitionProductWitness, PartitionRecord,
274    PartitionResolver, VerifiedMint,
275};
276
277/// Closed arithmetic and transcendental math for the `HostTypes::Decimal`
278/// slot. `f64` and `f32` implement this via `libm`. Downstream `HostTypes`
279/// impls are free to bring their own implementation (interval arithmetic,
280/// arbitrary precision, fixed-point, etc.).
281pub trait DecimalTranscendental:
282    Copy
283    + Default
284    + core::fmt::Debug
285    + PartialEq
286    + PartialOrd
287    + core::ops::Add<Output = Self>
288    + core::ops::Sub<Output = Self>
289    + core::ops::Mul<Output = Self>
290    + core::ops::Div<Output = Self>
291{
292    /// Construct from an unsigned 32-bit integer. f32 / f64 use `as` widening; downstream impls bring their own promotion.
293    fn from_u32(value: u32) -> Self;
294    /// Construct from an unsigned 64-bit integer (rewrite-step counts, etc.).
295    fn from_u64(value: u64) -> Self;
296    /// Saturating projection to `u64`. Used by `UorTime::min_wall_clock` to convert a wall-clock seconds-Decimal into integer nanoseconds.
297    fn as_u64_saturating(self) -> u64;
298    /// Natural logarithm.
299    fn ln(self) -> Self;
300    /// Exponential `e^x`.
301    fn exp(self) -> Self;
302    /// Square root.
303    fn sqrt(self) -> Self;
304    /// Construct from an IEEE-754 bit pattern (default-host f64 round-trip).
305    fn from_bits(bits: u64) -> Self;
306    /// Project to an IEEE-754 bit pattern (default-host f64 round-trip).
307    fn to_bits(self) -> u64;
308    /// Entropy contribution `x * ln(x)`, with the convention `0 * ln(0) = 0`.
309    #[inline]
310    fn entropy_term_nats(self) -> Self {
311        if self == Self::default() {
312            return Self::default();
313        }
314        self * self.ln()
315    }
316}
317
318impl DecimalTranscendental for f64 {
319    #[inline]
320    fn from_u32(value: u32) -> Self {
321        f64::from(value)
322    }
323    #[inline]
324    fn from_u64(value: u64) -> Self {
325        // u64 -> f64 is lossy above 2^53; documented at use sites.
326        value as f64
327    }
328    #[inline]
329    fn as_u64_saturating(self) -> u64 {
330        if self.partial_cmp(&0.0).is_none_or(|o| o.is_lt()) {
331            return 0;
332        }
333        if self >= u64::MAX as f64 {
334            return u64::MAX;
335        }
336        self as u64
337    }
338    #[inline]
339    fn ln(self) -> Self {
340        libm::log(self)
341    }
342    #[inline]
343    fn exp(self) -> Self {
344        libm::exp(self)
345    }
346    #[inline]
347    fn sqrt(self) -> Self {
348        libm::sqrt(self)
349    }
350    #[inline]
351    fn from_bits(bits: u64) -> Self {
352        f64::from_bits(bits)
353    }
354    #[inline]
355    fn to_bits(self) -> u64 {
356        f64::to_bits(self)
357    }
358}
359
360impl DecimalTranscendental for f32 {
361    #[inline]
362    fn from_u32(value: u32) -> Self {
363        // u32 -> f32 is lossy at high values; this is the documented
364        // host-default behavior for arithmetic constants.
365        value as f32
366    }
367    #[inline]
368    fn from_u64(value: u64) -> Self {
369        // u64 -> f32 is lossy above 2^24; documented at use sites.
370        value as f32
371    }
372    #[inline]
373    fn as_u64_saturating(self) -> u64 {
374        if self.partial_cmp(&0.0).is_none_or(|o| o.is_lt()) {
375            return 0;
376        }
377        if self >= u64::MAX as f32 {
378            return u64::MAX;
379        }
380        self as u64
381    }
382    #[inline]
383    fn ln(self) -> Self {
384        libm::logf(self)
385    }
386    #[inline]
387    fn exp(self) -> Self {
388        libm::expf(self)
389    }
390    #[inline]
391    fn sqrt(self) -> Self {
392        libm::sqrtf(self)
393    }
394    #[inline]
395    fn from_bits(bits: u64) -> Self {
396        // f32 has no native u64-bit constructor; widen via f64 then narrow.
397        f64::from_bits(bits) as f32
398    }
399    #[inline]
400    fn to_bits(self) -> u64 {
401        (self as f64).to_bits()
402    }
403}
404
405/// Phase B (target §4.1 W10): narrow host-types trait — the only carrier for
406/// the slots that genuinely vary across host environments. Foundation-owned
407/// types (Witt-level integers, booleans, IRIs, canonicalBytes, `UorTime`) are
408/// derived from the `WittLevel` family and not exposed here.
409/// Three slots: `Decimal` (real-number representation), `HostString` (opaque
410/// host string, NOT a foundation IRI), and `WitnessBytes` (opaque host byte
411/// sequence, NOT a foundation `canonicalBytes` constant). The v0.2.1 `DateTime`
412/// slot is removed; downstream associates timestamps out-of-band.
413/// # Example
414/// ```
415/// use uor_foundation::{HostTypes, DefaultHostTypes};
416/// // Canonical defaults: f64 / str / [u8].
417/// type DefaultH = DefaultHostTypes;
418/// // Override the Decimal slot for embedded targets with tighter precision:
419/// struct EmbeddedHost;
420/// impl HostTypes for EmbeddedHost {
421///     type Decimal = f32;          // override
422///     type HostString = str;       // default
423///     type WitnessBytes = [u8];    // default
424///     const EMPTY_DECIMAL: f32 = 0.0;
425///     const EMPTY_HOST_STRING: &'static str = "";
426///     const EMPTY_WITNESS_BYTES: &'static [u8] = &[];
427/// }
428/// # let _ = (core::marker::PhantomData::<DefaultH>, core::marker::PhantomData::<EmbeddedHost>);
429/// ```
430pub trait HostTypes {
431    /// Real-number representation for kernel observables (entropies, amplitudes, rates).
432    /// `DefaultHostTypes` selects `f64`. Override with higher-precision or interval
433    /// arithmetic as needed.
434    ///
435    /// Phase 9 bound: every `Decimal` must implement [`DecimalTranscendental`] —
436    /// closed arithmetic + ln/exp/sqrt + IEEE-754 bit-pattern round-trip. The
437    /// in-tree `f64` and `f32` impls satisfy this via `libm`.
438    type Decimal: DecimalTranscendental;
439
440    /// Host-supplied opaque string (NOT a foundation IRI).
441    /// `DefaultHostTypes` selects `str`. Override with owned `String`, `Cow<'_, str>`,
442    /// etc. for embedded / host-heap environments.
443    /// The `'static` bound is required by the Product/Coproduct Completion
444    /// Amendment §B1 `EMPTY_HOST_STRING` constant — every conforming `H`
445    /// must be able to expose a `&'static HostString`. All in-tree impls
446    /// (`DefaultHostTypes::HostString = str`) already satisfy this.
447    type HostString: ?Sized + 'static;
448
449    /// Host-supplied opaque byte sequence (NOT a foundation `canonicalBytes` constant).
450    /// `DefaultHostTypes` selects `[u8]`. Override with owned `Vec<u8>`, `Bytes`,
451    /// etc. for host-heap environments.
452    /// The `'static` bound mirrors `HostString` for the same reason — see
453    /// the `EMPTY_WITNESS_BYTES` constant below.
454    type WitnessBytes: ?Sized + 'static;
455
456    /// Empty / zero `Decimal` value for resolver-absent partition accessors.
457    /// `DefaultHostTypes` selects `0.0`. Used by `NullPartition::density()`
458    /// and analogous H-typed defaults.
459    const EMPTY_DECIMAL: Self::Decimal;
460
461    /// Empty `&'static HostString` reference for resolver-absent accessors.
462    /// `DefaultHostTypes` selects `&""` coerced to `&str`. Used by
463    /// `NullPartition::product_category_level()` and the address-typed
464    /// string accessors on `NullElement<H>`.
465    const EMPTY_HOST_STRING: &'static Self::HostString;
466
467    /// Empty `&'static WitnessBytes` reference for resolver-absent accessors.
468    /// `DefaultHostTypes` selects `&[]` coerced to `&[u8]`. Used by
469    /// `NullElement<H>::canonical_bytes()`.
470    const EMPTY_WITNESS_BYTES: &'static Self::WitnessBytes;
471}
472
473/// Phase B: canonical default impl of [`HostTypes`]. Selects `f64`/`str`/`[u8]`.
474/// Use as `type H = uor_foundation::DefaultHostTypes;` to inherit the defaults;
475/// replace with a downstream marker struct if any slot needs an override.
476#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
477pub struct DefaultHostTypes;
478
479/// π · ℏ = `core::f64::consts::PI * 1.054_571_817e-34` J·s, in IEEE-754 bits.
480/// Half of one orthogonal-state-transition Margolus-Levitin bound.
481pub const PI_TIMES_H_BAR_BITS: u64 = f64::to_bits(core::f64::consts::PI * 1.054_571_817e-34_f64);
482
483/// Nanoseconds per second (`1.0e9`) in IEEE-754 bits. Used by `UorTime::min_wall_clock`.
484pub const NANOS_PER_SECOND_BITS: u64 = f64::to_bits(1.0e9_f64);
485
486/// Natural logarithm of 2, in IEEE-754 bits. Drives the Landauer bit-erasure unit.
487pub const LN_2_BITS: u64 = f64::to_bits(core::f64::consts::LN_2);
488
489/// Lower bound for `Calibration::k_b_t` (1e-30 J), in IEEE-754 bits.
490pub const CALIBRATION_KBT_LO_BITS: u64 = f64::to_bits(1.0e-30_f64);
491
492/// Upper bound for `Calibration::k_b_t` (1e-15 J), in IEEE-754 bits.
493pub const CALIBRATION_KBT_HI_BITS: u64 = f64::to_bits(1.0e-15_f64);
494
495/// Upper bound for `Calibration::thermal_power` (1e9 W), in IEEE-754 bits.
496pub const CALIBRATION_THERMAL_POWER_HI_BITS: u64 = f64::to_bits(1.0e9_f64);
497
498/// Upper bound for `Calibration::characteristic_energy` (1e3 J), in IEEE-754 bits.
499pub const CALIBRATION_CHAR_ENERGY_HI_BITS: u64 = f64::to_bits(1.0e3_f64);
500
501impl HostTypes for DefaultHostTypes {
502    type Decimal = f64;
503    type HostString = str;
504    type WitnessBytes = [u8];
505    const EMPTY_DECIMAL: Self::Decimal = 0.0;
506    const EMPTY_HOST_STRING: &'static str = "";
507    const EMPTY_WITNESS_BYTES: &'static [u8] = &[];
508}
509
510/// Substitution axis 2 of 3 (per the UOR-Framework wiki). Carries every
511/// capacity bound that varies along the principal data path: the fingerprint
512/// output width range, the trace event-count ceiling, and the algebraic-level
513/// bit-width ceiling. The application author selects an impl; the foundation
514/// (this trait) declares the contract.
515/// Per the wiki's ADR-018, the architecture admits no capacity bound outside
516/// `HostBounds`. Foundation's `Hasher`, `ContentFingerprint`, and `Trace` are
517/// const-generic over their capacity bounds; applications populate each
518/// type's const-generic with `<MyBounds as HostBounds>::CONST`. There are no
519/// free-standing capacity constants on the public surface — collapsing the
520/// substitution axis is exactly what ADR-018 rejects.
521/// # Example
522/// ```
523/// use uor_foundation::{HostBounds, DefaultHostBounds};
524/// // Inherit the canonical defaults (16 / 32 / 256 / 64).
525/// type B = DefaultHostBounds;
526/// assert_eq!(<B as HostBounds>::FINGERPRINT_MAX_BYTES, 32);
527/// // Or declare an application-specific capacity profile:
528/// struct BitcoinPow;
529/// impl HostBounds for BitcoinPow {
530///     const FINGERPRINT_MIN_BYTES: usize = 32;
531///     const FINGERPRINT_MAX_BYTES: usize = 32;
532///     const TRACE_MAX_EVENTS: usize = 1024;
533///     const WITT_LEVEL_MAX_BITS: u32 = 256;
534///     // ADR-037: 14 data-shape capacity caps. Match the
535///     // DefaultHostBounds defaults unless the application has a
536///     // specific reason to vary them.
537///     const TERM_VALUE_MAX_BYTES: usize = 4096;
538///     const AXIS_OUTPUT_BYTES_MAX: usize = 4096;
539///     const FOLD_UNROLL_THRESHOLD: usize = 8;
540///     const BETTI_DIMENSION_MAX: usize = 8;
541///     const NERVE_CONSTRAINTS_MAX: usize = 8;
542///     const NERVE_SITES_MAX: usize = 8;
543///     const JACOBIAN_SITES_MAX: usize = 8;
544///     const RECURSION_TRACE_DEPTH_MAX: usize = 16;
545///     const OP_CHAIN_DEPTH_MAX: usize = 8;
546///     const AFFINE_COEFFS_MAX: usize = 8;
547///     const CONJUNCTION_TERMS_MAX: usize = 8;
548///     const ROUTE_INPUT_BUFFER_BYTES: usize = 4096;
549///     const ROUTE_OUTPUT_BUFFER_BYTES: usize = 4096;
550///     const UNFOLD_ITERATIONS_MAX: usize = 256;
551///     // ADR-037: 8 ψ-stage resolver output byte-buffer ceilings.
552///     const NERVE_OUTPUT_BYTES_MAX: usize = 4096;
553///     const CHAIN_COMPLEX_OUTPUT_BYTES_MAX: usize = 4096;
554///     const HOMOLOGY_GROUPS_OUTPUT_BYTES_MAX: usize = 4096;
555///     const COCHAIN_COMPLEX_OUTPUT_BYTES_MAX: usize = 4096;
556///     const COHOMOLOGY_GROUPS_OUTPUT_BYTES_MAX: usize = 4096;
557///     const POSTNIKOV_TOWER_OUTPUT_BYTES_MAX: usize = 4096;
558///     const HOMOTOPY_GROUPS_OUTPUT_BYTES_MAX: usize = 4096;
559///     const K_INVARIANTS_OUTPUT_BYTES_MAX: usize = 4096;
560/// }
561/// ```
562pub trait HostBounds {
563    /// Minimum content-fingerprint width in bytes that the application's
564    /// selected `Hasher` impl MUST produce. Derived from the application's
565    /// collision-probability target (16 bytes ≈ 2^-64 under the birthday
566    /// bound; raise to 32 to reach 2^-128).
567    const FINGERPRINT_MIN_BYTES: usize;
568
569    /// Maximum content-fingerprint width in bytes — the inline buffer
570    /// capacity carried by every `ContentFingerprint`. The application's
571    /// selected `Hasher` MUST produce output no wider than this.
572    const FINGERPRINT_MAX_BYTES: usize;
573
574    /// Maximum number of `TraceEvent` values a `Trace` may carry.
575    /// Bounds the inline event buffer and caps verification time.
576    const TRACE_MAX_EVENTS: usize;
577
578    /// Algebraic-level bit-width ceiling. Caps the Witt-level any value
579    /// along the principal data path may compute against. The
580    /// `DefaultHostBounds` value of 64 corresponds to `WittLevel::W64`.
581    const WITT_LEVEL_MAX_BITS: u32;
582
583    /// ADR-037: maximum `TermValue` inline buffer width in bytes.
584    /// Caps the catamorphism's per-fold-rule scratch size and the
585    /// `TermValue::from_slice` capacity.
586    const TERM_VALUE_MAX_BYTES: usize;
587
588    /// ADR-037: maximum axis-kernel output byte-buffer width — the
589    /// upper bound on the substitution-axis `dispatch()` return value's
590    /// `out` slice length. Sized at least as wide as the largest
591    /// axis-kernel output across the application's `AxisTuple`.
592    const AXIS_OUTPUT_BYTES_MAX: usize;
593
594    /// ADR-037: threshold below which `fold_n(n, init, step)` lowers to
595    /// an unrolled `Term::Application` chain (one application per
596    /// iteration). Counts `n >= FOLD_UNROLL_THRESHOLD` lower to
597    /// `Term::Recurse` instead.
598    const FOLD_UNROLL_THRESHOLD: usize;
599
600    /// ADR-037: maximum dimension index for `BettiNumbers` arrays —
601    /// `β_k(K)` is stored for `k` in `0..BETTI_DIMENSION_MAX`.
602    const BETTI_DIMENSION_MAX: usize;
603
604    /// ADR-037: maximum number of constraints in a single constraint
605    /// nerve's array representation.
606    const NERVE_CONSTRAINTS_MAX: usize;
607
608    /// ADR-037: maximum number of sites in a single constraint nerve's
609    /// array representation.
610    const NERVE_SITES_MAX: usize;
611
612    /// ADR-037: maximum number of sites for which a Jacobian matrix
613    /// can be stored inline.
614    const JACOBIAN_SITES_MAX: usize;
615
616    /// ADR-037: maximum recursion depth for the trace-replay stack.
617    const RECURSION_TRACE_DEPTH_MAX: usize;
618
619    /// ADR-037: maximum operator-chain depth in a single operation.
620    const OP_CHAIN_DEPTH_MAX: usize;
621
622    /// ADR-037: maximum number of affine coefficients per
623    /// `ConstraintRef::Affine`.
624    const AFFINE_COEFFS_MAX: usize;
625
626    /// ADR-037: maximum number of conjuncts per
627    /// `ConstraintRef::Conjunction`.
628    const CONJUNCTION_TERMS_MAX: usize;
629
630    /// ADR-037: maximum byte width of the route input buffer per
631    /// ADR-023's `IntoBindingValue` serialization.
632    const ROUTE_INPUT_BUFFER_BYTES: usize;
633
634    /// ADR-037: maximum byte width of the route output buffer per
635    /// ADR-028's `Grounded::output_bytes` payload.
636    const ROUTE_OUTPUT_BUFFER_BYTES: usize;
637
638    /// ADR-037: maximum iteration count for `Term::Unfold` evaluation.
639    const UNFOLD_ITERATIONS_MAX: usize;
640
641    /// ADR-037: maximum byte width of ψ_1 `NerveResolver::resolve`'s
642    /// `out` buffer (the SimplicialComplex serialization).
643    const NERVE_OUTPUT_BYTES_MAX: usize;
644
645    /// ADR-037: maximum byte width of ψ_2 `ChainComplexResolver::resolve`
646    /// output.
647    const CHAIN_COMPLEX_OUTPUT_BYTES_MAX: usize;
648
649    /// ADR-037: maximum byte width of ψ_3
650    /// `HomologyGroupResolver::resolve` output.
651    const HOMOLOGY_GROUPS_OUTPUT_BYTES_MAX: usize;
652
653    /// ADR-037: maximum byte width of ψ_5
654    /// `CochainComplexResolver::resolve` output.
655    const COCHAIN_COMPLEX_OUTPUT_BYTES_MAX: usize;
656
657    /// ADR-037: maximum byte width of ψ_6
658    /// `CohomologyGroupResolver::resolve` output.
659    const COHOMOLOGY_GROUPS_OUTPUT_BYTES_MAX: usize;
660
661    /// ADR-037: maximum byte width of ψ_7 `PostnikovResolver::resolve`
662    /// output (the Postnikov-tower serialization).
663    const POSTNIKOV_TOWER_OUTPUT_BYTES_MAX: usize;
664
665    /// ADR-037: maximum byte width of ψ_8
666    /// `HomotopyGroupResolver::resolve` output.
667    const HOMOTOPY_GROUPS_OUTPUT_BYTES_MAX: usize;
668
669    /// ADR-037: maximum byte width of ψ_9 `KInvariantResolver::resolve`
670    /// output (the κ-label byte serialization at ψ_9).
671    const K_INVARIANTS_OUTPUT_BYTES_MAX: usize;
672}
673
674/// Canonical default impl of [`HostBounds`]. Carries the values the default
675/// const-generic on `Hasher`, `ContentFingerprint`, and `Trace` resolves to.
676/// Use as `type B = uor_foundation::DefaultHostBounds;` to inherit; replace
677/// with a downstream marker struct when an application needs different
678/// capacity bounds (per ADR-018, this is the only sanctioned way to vary).
679#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
680pub struct DefaultHostBounds;
681
682impl HostBounds for DefaultHostBounds {
683    const FINGERPRINT_MIN_BYTES: usize = 16;
684    const FINGERPRINT_MAX_BYTES: usize = 32;
685    const TRACE_MAX_EVENTS: usize = 256;
686    const WITT_LEVEL_MAX_BITS: u32 = 64;
687    const TERM_VALUE_MAX_BYTES: usize = 4096;
688    const AXIS_OUTPUT_BYTES_MAX: usize = 4096;
689    const FOLD_UNROLL_THRESHOLD: usize = 8;
690    const BETTI_DIMENSION_MAX: usize = 8;
691    const NERVE_CONSTRAINTS_MAX: usize = 8;
692    const NERVE_SITES_MAX: usize = 8;
693    const JACOBIAN_SITES_MAX: usize = 8;
694    const RECURSION_TRACE_DEPTH_MAX: usize = 16;
695    const OP_CHAIN_DEPTH_MAX: usize = 8;
696    const AFFINE_COEFFS_MAX: usize = 8;
697    const CONJUNCTION_TERMS_MAX: usize = 8;
698    const ROUTE_INPUT_BUFFER_BYTES: usize = 4096;
699    const ROUTE_OUTPUT_BUFFER_BYTES: usize = 4096;
700    const UNFOLD_ITERATIONS_MAX: usize = 256;
701    const NERVE_OUTPUT_BYTES_MAX: usize = 4096;
702    const CHAIN_COMPLEX_OUTPUT_BYTES_MAX: usize = 4096;
703    const HOMOLOGY_GROUPS_OUTPUT_BYTES_MAX: usize = 4096;
704    const COCHAIN_COMPLEX_OUTPUT_BYTES_MAX: usize = 4096;
705    const COHOMOLOGY_GROUPS_OUTPUT_BYTES_MAX: usize = 4096;
706    const POSTNIKOV_TOWER_OUTPUT_BYTES_MAX: usize = 4096;
707    const HOMOTOPY_GROUPS_OUTPUT_BYTES_MAX: usize = 4096;
708    const K_INVARIANTS_OUTPUT_BYTES_MAX: usize = 4096;
709}