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 warnings

2 · 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.

Convention

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 in

A 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-replay by git tag and route all time reads through Arc<dyn Clock>.
  • Copy clippy.toml; run cargo clippy -- -D warnings in CI.
  • Copy scripts/check-wallclock.sh; empty the ALLOWED list; wire it as a CI job.
  • Disable chrono's clock feature.
  • Select the current-thread runtime wherever the replay producer is configured.