Add Miri test runner and sandbox-aware timestamp stubs#370
Merged
Conversation
Channel was bumped to 1.95.0 in PR #367 but the explanatory comment above it still said "Pinned to 1.94.1 ... 1.95 turned several previously-safe patterns into denied lints ... without sufficient value to justify the churn." Pure documentation drift — the bump already happened, the lint debt was closed by #367 + #368, and the comment now describes a state that has not been true for ~a day. Update the comment to reflect the actual 1.95.0 pin, cross-ref PR #367, name the clippy lints that came with 1.95, and keep the "never auto-track stable" rule.
…ked calls
Same ephemeral-nightly discipline as ndarray/scripts/miri-tests.sh:
default toolchain stays stable 1.95.0; `cargo +nightly miri` is the
only nightly invocation, scoped to this one script.
Scope: lance-graph-contract (zero-dep), lance-graph-rbac, neural-debug,
and lance-graph-ontology without the lance-cache feature. FFI-heavy
crates (lance, datafusion, arrow, BLAS) cannot run under Miri.
Bypasses for things Miri's default sandbox blocks (none of which
indicate UB — all are Miri sandboxing artifacts):
* `registry::now_micros` + `lance_cache::chrono_micros`: cfg(miri)
returns 0. Miri blocks `clock_gettime(REALTIME)`; timestamps are
meaningless inside the sandbox anyway. Production builds and
stable CI run the real `SystemTime::now()` path.
* `literal_graph::tests::test_real_aiwar_graph`: cfg_attr(miri, ignore).
Reads `/root/data/aiwar_graph.json` — Miri's isolation blocks
`std::fs::*`.
* `manifest_codegen::test_idempotency`: cfg_attr(miri, ignore). Reads
the on-disk canonical manifests + codegen output. The other 7 tests
in the file use in-memory YAML strings and run clean.
* `bridge_scope_lock.rs` + `round_trip_ttl.rs` + `hydrate_real_ogit.rs`:
`#![cfg(not(miri))]` at file head. Every test in these three files
uses `tempfile::tempdir()` + `std::fs::*` to stage TTL fixtures.
Stable / nightly without Miri runs them normally.
* `dcterms_source_attribute_test::dcterms_source_attribute_pairs_surface_for_customer`:
cfg_attr(miri, ignore). Reads /home/user/OGIT.
* MIRIFLAGS=-Zmiri-ignore-leaks in the script: lance-graph-ontology
test helpers do `Box::leak(name.into_boxed_str())` to fabricate
`&'static str` for `Schema::builder` (which intentionally takes
`&'static str`). 11 leaks across the registry test suite, all
test-helper-only — production code does not use Box::leak.
Verification (clippy-first then targeted miri runs):
lance-graph-contract: 401 passed / 0 failed / 4 ignored (~240s)
lance-graph-rbac: 14 passed / 0 failed (~1.6s)
neural-debug: 10 passed / 0 failed (~321s)
lance-graph-ontology (--no-default-features):
34 passed / 0 failed / 1 ignored (~46s + setup)
Total: 459 tests Miri-clean across 4 crates. The miri job in
.github/workflows/ci.yaml (if added) can promote to required for
these crates.
The architectural finding for ndarray side — `crate::simd::*` directly
re-exports intrinsics-based types; the polyfill at `crate::simd_nightly`
covers 5/30 types and is not wired into `crate::simd::*` under cfg(miri)
— is documented in ndarray's miri-tests.sh and is the next miri-coverage
follow-up there.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Miri (Rust's interpreter-based UB detector) support to lance-graph by:
Key Changes
scripts/miri-tests.sh (new): Ephemeral nightly-only test runner following ndarray's pattern
lance-graph-contract,lance-graph-rbac,neural-debug, andlance-graph-ontology(withoutlance-cachefeature)lance,arrow,datafusion, BLAS) that Miri cannot enter-Zrandomize-layout) to catch missing#[repr(transparent)]-Zmiri-ignore-leakscrates/lance-graph-ontology/src/registry.rs: Stub
now_micros()to return 0 under Miriclock_gettime(REALTIME), making timestamp-dependent append paths abortcrates/lance-graph-ontology/src/lance_cache.rs: Stub
chrono_micros()similarlyTest file isolation (6 files): Skip or ignore tests that require filesystem access
bridge_scope_lock.rs,hydrate_real_ogit.rs,round_trip_ttl.rs:#literal_graph.rs::test_real_aiwar_graph,manifest_codegen.rs::test_idempotency,dcterms_source_attribute_test.rs::dcterms_source_attribute_pairs_surface_for_customer:#[cfg_attr(miri, ignore)](skip individual test)rust-toolchain.toml: Bump from 1.94.1 to 1.95.0
Implementation Details
The script follows ndarray's proven pattern: ephemeral per-invocation nightly switch (
cargo +nightly miri) without changing the default stable toolchain. This keeps Miri optional for local development while enabling CI to validate memory safety on the contract layer and pure-Rust planner paths.Timestamp stubs use
#[cfg(miri)]guards rather than conditional compilation of entire functions, preserving code clarity while allowing Miri to exercise the surrounding logic (registry state machines, TTL parsing) with deterministic time values.https://claude.ai/code/session_01UwJuKqP828qyX1VkLgGJFS