Overview
The wallclock gate
FerroReplay is only as deterministic as its consumers are disciplined. Every adopting repo enforces no direct time APIs outside FerroReplay — through three layers that ship with the crate.
Why a gate
A single stray Instant::now() or Utc::now() in a consumer is enough to make a replay diverge from the run it is meant to reproduce. The gate makes that class of bug a build failure rather than a debugging session. The crate owns the only sanctioned wall-clock site; everywhere else, reading time directly is an error.
1 · clippy disallowed-methods
Copy the crate's clippy.toml(at this repo's root) into yours. It disallows the direct time APIs and CI runs clippy as a hard error:
# clippy.toml — disallowed-methods covers:
# std::time::SystemTime::now
# std::time::Instant::now
# the tokio::time timer set (sleep, sleep_until, interval, ...)
# chrono::Utc::now / chrono::Local::now
# CI:
cargo clippy --all-targets -- -D warnings2 · the textual gate
Copy scripts/check-wallclock.sh and wire it as a CI job. In a consumer repo the ALLOWED list is empty — delete the exemption line: the crate owns the sanctioned sites, so any match in your src/is a bug. The textual gate catches what clippy can't, including macro-built call sites.
Never write the gated tokens literally, even in comments — a comment mentioning Instant::now trips the textual gate, and that is intentional. Refer to them obliquely, the way this page mostly does.
3 · drop chrono's clock feature
Build chrono without the clockfeature so the wall-clock constructors don't even exist to call. The cheapest gate is the one the compiler enforces for free:
[dependencies]
chrono = { version = "0.4", default-features = false, features = ["std"] }
# no "clock" feature -> Utc::now / Local::now are not compiled inA worked reference
gamma-engine is the reference adopter. Its CI runs the wallclock-gate job over a real engine, so you can start from a working configuration rather than assembling one from scratch.
Adoption checklist
- Pin
ferro-replayby git tag and route all time reads throughArc<dyn Clock>. - Copy
clippy.toml; runcargo clippy -- -D warningsin CI. - Copy
scripts/check-wallclock.sh; empty theALLOWEDlist; wire it as a CI job. - Disable chrono's
clockfeature. - Select the current-thread runtime wherever the replay producer is configured.