RFDs/0018
Deterministic execution proof of concept
Goal
Establish an architecture for running unmodified Linux software in a controlled environment where a recorded execution can be reproduced exactly. The first implementation should prove the determinism boundary with the least original hypervisor work while preserving a path toward state-space exploration.
Deliver a command-line proof of concept that records and exactly replays a small Linux execution containing a client, a server, a workload, a checker, and one controlled process failure. The result should determine whether this architecture is a viable base for SimFerret before work begins on branching exploration or general application support.
Context
Deterministic simulation testing needs three distinct capabilities:
-
deterministic execution and replay;
-
exploration of alternative inputs, schedules, and faults;
-
properties that identify invalid system states.
FoundationDB obtains determinism by routing production actors through simulated time, network, storage, and process implementations. SimFerret instead aims to run software that was not designed for simulation. Its determinism boundary must therefore sit below the application and guest operating system.
Antithesis demonstrates this model with a deterministic hypervisor, simulated devices, snapshots, guided exploration, and property checking. Reproducing that complete platform is not an appropriate first milestone. SimFerret first needs to establish that it can control and replay one small whole-system execution.
Proposal
SimFerret uses Rust for its control plane and QEMU TCG for its initial execution engine. QEMU runs one x86-64 Linux guest with one virtual CPU. The Rust process starts and controls QEMU through its command-line and QMP interfaces, records the complete execution identity, and stores simulation events and results.
The initial boundary is:
Rust CLI and controller
-> scenario and deterministic choice plan
-> QMP and controlled guest input
-> QEMU TCG record/replay
-> one-vCPU Linux guest
-> application, workload, and checker processes
QEMU’s instruction-counted record/replay mode supplies the first CPU, virtual time, interrupt, and supported-device replay implementation. SimFerret does not fork QEMU until a concrete missing hook is demonstrated. Any necessary QEMU changes remain narrow and are kept separate from the Rust control plane.
The controller may use ordinary asynchronous Rust for process supervision and artifact I/O. Decisions that affect a scenario use an explicit seeded PRNG and stable ordering. They are materialized into a choice plan before or through a controlled input boundary rather than depending on host task wake order or wall clock time.
Replay identity
A replay is identified by all inputs capable of changing guest execution:
-
SimFerret and QEMU executable digests or immutable Nix derivation identities, plus their reported versions;
-
guest kernel, root filesystem, and application artifact digests;
-
QEMU machine, CPU, memory, firmware digest, and device configuration;
-
initial disk or VM snapshot digest;
-
QEMU record/replay log;
-
SimFerret scenario, seed, choice plan, and configuration.
A seed alone is not an exact replay contract. It generates SimFerret’s choices, while QEMU’s replay log fixes the instruction positions and ordering of external events. SimFerret must reject or clearly mark a replay when its recorded identity does not match the available environment.
Ownership boundaries
The Rust control plane owns scenario parsing, seeded choices, VM lifecycle, fault requests, artifacts, event normalization, assertions, and later exploration policy. QEMU owns guest CPU execution, virtual machine state, and record/replay of supported nondeterministic machine events. A small guest agent may translate controlled commands into process lifecycle operations and emit structured events, but it must not become an application-specific simulator.
All host communication that can affect the guest is part of the deterministic input boundary. Uncontrolled external networks, host filesystems, entropy, and wall clocks are excluded from a replayable simulation.
Proof-of-concept scenario
The proof of concept uses a fixed minimal Linux guest with one virtual CPU. The guest contains a small TCP echo server, a workload client, a checker, and a SimFerret guest agent. These fixtures should be simple enough to audit and exist only to exercise orchestration rather than demonstrate a useful distributed system.
For each generated operation, the client sends an opaque request identifier and payload. The server returns both unchanged. The checker asserts that every successful response matches its request and records progress as structured events.
The scenario performs this sequence:
-
boot the guest and establish the controlled agent channel;
-
start the server, client, and checker;
-
execute a seed-derived finite request plan;
-
terminate the server at a recorded choice point;
-
observe bounded failed or unavailable requests;
-
restart the server;
-
observe a subsequent successful matching response;
-
finish the workload and emit assertion results.
The failure validates process control and liveness checking without requiring a custom network or storage model. Network partitions, disk corruption, and durable state are intentionally later scenarios.
Command-line contract
The intended interface is approximately:
simferret image build
simferret run --scenario scenarios/echo-process-restart.toml --seed 42
simferret replay runs/<run-id>
The exact command spelling may change during implementation, but record and replay remain separate operations. A successful run prints its run identifier, assertion summary, artifact location, and replay command.
Determinism contract
The first execution records QEMU’s nondeterministic event log and SimFerret’s choice plan. Replay starts from the same recorded initial state and consumes those artifacts. It is successful only when it reaches normal termination and produces the same normalized guest-event sequence, assertion results, and semantic outcome digest.
The QEMU replay log establishes reproduction of machine execution under the recorded replay identity. Byte-identical normalized event, assertion, and semantic outcome artifacts establish observable equivalence. The PoC does not claim that the semantic outcome digest represents all guest memory or device state.
Timestamps, host process identifiers, temporary paths, and QEMU diagnostic noise are not semantic events and are excluded from comparison. Exclusions must be enumerated; the implementation may not silently discard a field merely because it differs.
The PoC claims exact replay from a recorded run. It does not claim that running the same seed twice without the QEMU replay log produces instruction-identical executions.
Assertions
The scenario defines three initial property forms:
-
safety: every successful response contains the request identifier and payload sent by the client;
-
controlled outage: at least one request attempt occurs while the server is stopped and produces a failed or unavailable result within a scenario-defined virtual-time or event bound;
-
bounded liveness: after the controlled restart, at least one matching request succeeds within a scenario-defined virtual-time or event bound.
Assertion evaluation uses structured events rather than scraping human logs. The run fails when any property fails, a required event is absent, replay diverges, QEMU exits unexpectedly, or the scenario exceeds its bound.
Artifacts
Every run directory contains the run outputs and compatibility identities needed to inspect and request replay of the run:
runs/<run-id>/
manifest.json
scenario.toml
choices.json
replay.bin
events.jsonl
assertions.json
logs/
The manifest records the full replay identity and digests every other run
artifact; manifest.json does not contain its own digest. Replay also requires
matching content-addressed external QEMU, firmware, guest-image, application,
and initial-state artifacts; the PoC does not copy those large dependencies
into every run directory. The semantic outcome digest covers normalized events
and all explicitly serializable SimFerret state.
Acceptance criteria
The proof of concept is complete when:
-
one documented command builds or obtains the fixed guest image;
-
one command records the scenario without interactive steps;
-
at least one request attempt occurs while the server is stopped and reports a bounded failed or unavailable result;
-
replay succeeds at least twice from the produced run directory;
-
each replay produces byte-identical normalized event and assertion artifacts and a matching semantic outcome digest;
-
changing the scenario seed changes the request or fault choice plan;
-
tampering with a replay identity or artifact is detected before or during replay;
-
an intentionally violated fixture property produces a failing assertion and nonzero CLI exit status;
-
the complete demonstration runs in a documented supported environment.
Initial constraints
The first implementation supports one host architecture, one QEMU version, one machine definition, one virtual CPU, and a minimal fixed Linux image. Device passthrough, accelerators, and host-mounted mutable filesystems are forbidden. These constraints reduce the number of execution paths that can escape QEMU’s record/replay model.
Excluded from the proof of concept
The proof of concept does not include:
-
KVM, MSHV, or hardware-accelerated deterministic execution;
-
Cloud Hypervisor or a custom VMM;
-
arbitrary Docker Compose or Kubernetes deployments;
-
multiple VMs or multiple virtual CPUs;
-
custom deterministic network or block devices;
-
uncontrolled external network or service dependencies;
-
disk faults or network partitions;
-
snapshot-tree branching and distributed exploration workers;
-
coverage-guided or reinforcement-learning exploration;
-
time-travel debugging user interfaces;
-
performance, security, or compatibility claims for production use.
It is not a performance benchmark. TCG speed is recorded to establish a baseline but is not an acceptance criterion unless the scenario cannot complete in a practical development loop. The excluded capabilities are possible later RFDs after the proof of concept establishes a measured baseline and identifies which QEMU facilities are sufficient.
Alternatives considered
Cloud Hypervisor provides a smaller Rust VMM and useful snapshot and virtio boundaries, but currently relies on KVM or MSHV and does not provide deterministic CPU execution, instruction-counted virtual time, or whole-system record/replay. Choosing it first would make those mechanisms prerequisite to any simulation.
A new Rust VMM would provide maximum control but requires implementing or integrating CPU execution, interrupt and timer semantics, deterministic devices, snapshots, and replay before validating the product model.
Application-level simulation is much smaller and faster, as FoundationDB shows, but requires applications to adopt SimFerret-specific interfaces. That conflicts with the goal of running unmodified software.
Follow-up decision
Completion produces an evidence record covering replay fidelity, event-log and snapshot sizes, record and replay duration, unsupported QEMU devices or inputs, observed divergence, and operational friction. That evidence informs a new RFD choosing the next increment. Likely candidates are a deterministic network fault model, checkpoint branching, or packaging arbitrary container workloads; none is selected by this RFD.
Implementation
Delivery phases are tracked in RFD 18 implementation checklist, with measured results in the adjacent evidence record.