decode_envelope_strict chose the capabilities its early replicate refusal reads by what the sink's registry holds alone. A candidate, companion-only capability, record or derivation held at the sink could then decide that refusal, though dispatch never takes one. The gate now reads only capabilities codecs::is_dispatchable accepts and the sink advertises, so a held candidate gives the reason an empty registry gives (strict_gate_ignores_a_held_capability_it_cannot_dispatch). A pinned decode builds its ONNX session from the verified bytes, but an ONNX tensor can name another file for its data. Run locally against the linked ONNX Runtime, a model loaded from memory read such a file from the process's working directory, outside every pin. neural::onnx_external now reads the model's protobuf for a tensor stored as external data (graph initializers, attribute tensors and subgraphs, training graphs, local functions) and the pinned decode refuses such a model with set_incomplete, naming the file, before the runtime sees it. Bytes that do not parse are refused too. wai-neural-gates.yml adds the new tests to its exact lists and counts. determinism-tiers.md scopes its forge-run statement to the job as it was before the pin-aware tests were added; those have no recorded forge run. Co-Authored-By: Claude Opus 5.5 <[email protected]>
44 lines
2.1 KiB
Rust
44 lines
2.1 KiB
Rust
//! Shared deterministic `ort::Session` loader, used by both the neural
|
|
//! decode path and the semantic (perceptual) path.
|
|
//!
|
|
//! Single intra-op + inter-op thread and a fixed graph-optimization level so
|
|
//! float ONNX inference is reproducible run-to-run and machine-to-machine —
|
|
//! determinism is load-bearing for any conformance claim (see
|
|
//! `neural/runtime.rs`). Throughput is traded for reproducibility on purpose.
|
|
|
|
use std::path::Path;
|
|
use ort::session::{builder::GraphOptimizationLevel, Session};
|
|
|
|
/// Load an ONNX model into a deterministic CPU session. Returns the raw ort
|
|
/// error as a `String`; callers wrap it into their own error type.
|
|
pub(crate) fn load_deterministic(path: &Path) -> Result<Session, String> {
|
|
Session::builder()
|
|
.map_err(|e| format!("session builder: {e}"))?
|
|
.with_intra_threads(1)
|
|
.map_err(|e| format!("intra-threads: {e}"))?
|
|
.with_inter_threads(1)
|
|
.map_err(|e| format!("inter-threads: {e}"))?
|
|
.with_optimization_level(GraphOptimizationLevel::Level3)
|
|
.map_err(|e| format!("optimization level: {e}"))?
|
|
.commit_from_file(path)
|
|
.map_err(|e| format!("load {} failed: {e}", path.display()))
|
|
}
|
|
|
|
/// [`load_deterministic`] over model bytes already in memory — the bytes a pin
|
|
/// verified, so the session runs exactly what was hashed. A model that keeps
|
|
/// tensors in external files would have the runtime read them from outside those
|
|
/// bytes; the pinned decode refuses such a model before calling this
|
|
/// (`neural::params`).
|
|
#[cfg(feature = "neural")]
|
|
pub(crate) fn load_deterministic_from_memory(bytes: &[u8]) -> Result<Session, String> {
|
|
Session::builder()
|
|
.map_err(|e| format!("session builder: {e}"))?
|
|
.with_intra_threads(1)
|
|
.map_err(|e| format!("intra-threads: {e}"))?
|
|
.with_inter_threads(1)
|
|
.map_err(|e| format!("inter-threads: {e}"))?
|
|
.with_optimization_level(GraphOptimizationLevel::Level3)
|
|
.map_err(|e| format!("optimization level: {e}"))?
|
|
.commit_from_memory(bytes)
|
|
.map_err(|e| format!("load from verified bytes failed: {e}"))
|
|
}
|