Skip to content
sim-run logo

Run Deterministic Simulation Tests

sim-run

Run deterministic simulation tests with progressive difficulty levels (sunny/stormy/radioactive) inspired by TigerBeetle VOPR — orchestrates seed management, workload selection, and invariant verification

ahrav/scratch-scanner-rs0installs2stars

SKILL.md

Full skill instructions

Run Deterministic Simulation Tests

Execute simulation tests with progressive difficulty levels, inspired by TigerBeetle's VOPR three-level system. Manages seeds, selects workloads, injects faults, and reports invariant violations.

Evidence Base

SourcePrinciple
TigerBeetle VOPR3 levels: clean → faults → catastrophic; 3.3 sec sim = 39 min real-world
FoundationDB (SIGMOD 2021)Tens of thousands of sims nightly, seeded determinism
sled (simulation.html)Discrete-event simulation with priority queue
Eaton (practical DST guide)Seeds break on code changes — use continuous exploration
CockroachDB (Jepsen lessons)Workload design determines simulation effectiveness
Yuan et al. (OSDI 2014)Error handling paths are highest-value targets

When to Use

  • Level 1 (Sunny Day): Before committing coordination changes (quick sanity check)
  • Level 2 (Stormy): Nightly CI or before merging coordination PRs
  • Level 3 (Radioactive): Before releases or after significant coordination changes
  • When a coordination bug is suspected and you want to explore the state space
  • When verifying a fix for a simulation-found bug

When NOT to Use

  • Code that doesn't touch coordination, gossip, or shard lifecycle
  • Detection engine changes (use /​run-fuzz instead)
  • When simulation harness isn't implemented yet (use /​sim-scaffold first)

Prerequisites

Before running simulations, verify:

  1. SimContext exists in gossip-contracts/​src/​sim/ (P1 prerequisite)
  2. At least one simulation harness exists (generated by /​sim-scaffold)
  3. The test-support feature gate is configured
  4. proptest is available as a dev-dependency

If prerequisites are missing, report what needs to be created and suggest running /​sim-scaffold first.


Procedure

Step 1: Select Level

LevelNameFaultsSeedsContext
1Sunny DayNone — perfect conditions10Per-PR, pre-commit, quick sanity
2StormyNetwork partitions, lease expiry, message loss/​reorder, clock skew100Nightly CI, pre-merge
3RadioactiveStorage corruption, cascading failures, Byzantine faults, all Level 2 combined1000+Pre-release, deep exploration

If the user doesn't specify a level:

  • Default to Level 1 for quick checks
  • Recommend Level 2 if the change touches lease/​fence/​split logic
  • Recommend Level 3 if the change is a significant architectural modification

Step 2: Select Workload Templates

Each workload template exercises a specific coordination scenario. Select all that are relevant to the changed code, or run all for comprehensive coverage.

TemplateExercisesPriority
Full scan lifecycleAcquire → checkpoint x N → completeALWAYS
Lease expiry during checkpointAcquire → delay → checkpoint with stale leaseHIGH — etcd Jepsen 3.4.3 pattern
Split during active scanAcquire → checkpoint → split → verify childrenHIGH — shard coverage invariant
Concurrent acquisition2+ workers acquire same shardHIGH — fence monotonicity
Ambiguous failureNetwork drop after mutation succeedsMED — Jepsen Redis-Raft pattern
Park and unparkActive → Parked → Active (reacquire)MED — state machine completeness
Mass restartAll workers restart simultaneouslyMED — Serf/​memberlist edge case
Asymmetric partitionA→B works, B→A dropsLOW — Lifeguard false positives

Step 3: Run Simulation

Execute tests with the selected level and seeds:

# Level 1 (Sunny Day) — quick sanity check
cargo test --features test-support -- --test-threads=1 sim::level1

# Level 2 (Stormy) — fault injection
SIM_SEEDS=100 SIM_LEVEL=2 cargo test --features test-support -- --test-threads=1 sim::level2

# Level 3 (Radioactive) — maximum chaos
SIM_SEEDS=1000 SIM_LEVEL=3 cargo test --features test-support -- --test-threads=1 sim::level3

# Reproduce a specific failure
SIM_SEED=12345 cargo test --features test-support -- --test-threads=1 sim::specific_test

Key flags:

  • --test-threads=1: Required for deterministic execution (no thread interleaving)
  • SIM_SEEDS: Number of random seeds to explore
  • SIM_LEVEL: Fault injection intensity
  • SIM_SEED: Specific seed for reproduction

Step 4: Analyze Results

On success (all seeds pass):

SIMULATION REPORT — Level {N}
═════════════════════════════
Result:           PASS
Seeds tested:     {count}
Wall time:        {duration}
Sim time:         {total simulated time}
Time compression: {sim_time / wall_time}x

Workload coverage:
  [x] Full scan lifecycle          — {N} occurrences
  [x] Lease expiry during checkpoint — {N} occurrences
  [x] Split during active scan     — {N} occurrences
  [x] Concurrent acquisition       — {N} occurrences
  [ ] Asymmetric partition          — 0 occurrences (not exercised)

Invariants verified:
  - Mutual exclusion (lease)       — checked {N} times
  - Fence monotonicity             — checked {N} times
  - Shard coverage (no gaps)       — checked {N} times
  - Terminal irreversibility       — checked {N} times

On failure:

SIMULATION REPORT — Level {N}
═════════════════════════════
Result:           FAIL
Seeds tested:     {count} ({failures} failures)
Unique bugs:      {count}

Invariant violations:
  ┌─────────────────────────────┬───────┬─────────────────────┐
  │ Invariant                   │ Count │ Seeds               │
  ├─────────────────────────────┼───────┼─────────────────────┤
  │ Mutual exclusion (lease)    │ 3     │ 42, 1337, 99999     │
  │ Fence monotonicity          │ 1     │ 42                  │
  └─────────────────────────────┴───────┴─────────────────────┘

Reproduction commands:
  SIM_SEED=42 cargo test --features test-support -- sim::level2::lease_expiry_during_checkpoint
  SIM_SEED=1337 cargo test --features test-support -- sim::level2::concurrent_acquisition

Failure trace (seed=42):
  t=0    Worker-1: acquire_shard(shard-A) → Ok(epoch=1)
  t=5    Worker-2: acquire_shard(shard-A) → Ok(epoch=2)
  t=7    FAULT: pause Worker-2 for 100 ticks
  t=10   Worker-1: checkpoint(shard-A, epoch=1) → Ok  ← VIOLATION: stale epoch accepted
  t=107  Worker-2: resume
  ...

Step 5: Handle Failures

When a simulation failure is found:

  1. Minimize: Use proptest shrinking to find the minimal reproduction case
  2. Classify: Is this a real bug or a simulation artifact?
  3. Root cause: Trace the failure to specific code
  4. Fix: Apply the fix
  5. Verify: Re-run with the failing seed AND fresh seeds
  6. Do NOT save the specific seed as a regression test — seeds break on code changes (Eaton, Antithesis). Instead, ensure the invariant check catches the class of bug under continuous exploration.

Step 6: Coverage Assessment

After the run, assess workload coverage:

  • Well-covered: Workload generated sufficient occurrences across seeds
  • Under-covered: Workload generated fewer than 5 occurrences across all seeds → May need to tune workload generation probabilities
  • Not exercised: Workload never triggered → May need explicit workload scenario or higher seed count

If critical workloads are under-covered, recommend:

  • Increasing seed count
  • Adding targeted workload scenarios
  • Adjusting fault injection probabilities

Fault Injection Reference

Level 2 (Stormy) Faults

FaultDescriptionImplementation
Network partitionMessages between node subsets are droppedNetworkFaults.partitions
Message lossRandom message drops (10-30%)NetworkFaults.drop_rate
Message reorderMessages arrive out of orderRandom delay in event queue
Lease expiryForce lease timeout mid-operationAdvance clock past lease deadline
Process pauseFreeze a worker for N ticksSkip node in simulation loop
Clock skewNodes disagree on current timePer-node clock offset

Level 3 (Radioactive) Faults

All Level 2 faults plus:

FaultDescriptionImplementation
Storage corruptionBackend returns garbage dataMock backend returns corrupted state
Cascading failureFailure of one node triggers failures in othersFault propagation rules
ByzantineNode sends conflicting messages to different peersDuplicate + modify messages
Split brainTwo partitions each believe they're the majoritySymmetric partition
Repeated crash-restartNode crashes and restarts multiple timesReset node state periodically

Invariant Catalog

These are the core invariants that every simulation run must verify. They map to the phase 2 spec invariant catalog.

IDInvariantCheck
S1Mutual exclusion — at most one active lease per shardCount active leases per shard ≤ 1
S2Fence monotonicity — epochs never decreaseTrack max epoch per shard, assert non-decreasing
S3Terminal irreversibility — Done/​Failed shards never transitionAssert no transitions from terminal states
S4Shard coverage — split children cover parent range exactlyVerify range algebra on split
S5Idempotency — duplicate OpId returns same resultReplay operations, assert identical results
S6Progress — under fair scheduling, work eventually completesAssert completion within bounded time
L1Lease exclusivity — stale-epoch checkpoints are rejectedAttempt checkpoint with old epoch, assert rejection
L2Zombie rejection — restarted worker cannot use old leaseKill and restart worker, assert old operations fail

Seed Management Philosophy

Do NOT save specific seeds as regression tests.

Seeds break whenever code changes (Eaton survey, Antithesis blog). Instead:

  1. Run many fresh seeds continuously (exploration, not regression)
  2. When a bug is found, fix it and verify the fix with fresh seeds
  3. Ensure the invariant assertion catches the class of bug, not just the specific sequence that triggered it
  4. The invariant check IS the regression test — not the seed

This is counterintuitive but well-established: FoundationDB, TigerBeetle, and Antithesis all use continuous exploration over saved seeds.


Related Skills

  • /​sim-review — Verify code is DST-compatible before running simulations
  • /​sim-scaffold — Generate simulation harnesses
  • /​jepsen-test — Complement DST with real-network cluster tests
  • /​test-strategy — Choose between simulation and other test approaches

More skills from ahrav

execute-review-findings logo
ahrav/scratch-scanner-rs

execute-review-findings

Use when you have code review findings, PR comments, or review reports that need to be systematically addressed — especially when there are multiple findings across different files and severities

2 0
View
deep-research logo
ahrav/scratch-scanner-rs

deep-research

Deep research before design — 3-5 parallel research agents survey papers, production systems, failure modes, and prior art, then a synthesizer compiles evidence, and an integrator maps findings to a concrete codebase plan with citations

2 0
View
perf-regression logo
ahrav/scratch-scanner-rs

perf-regression

Performance regression testing workflow for hot path changes

2 0
View
safe-over-unsafe logo
ahrav/scratch-scanner-rs

safe-over-unsafe

Use when designing safe public APIs that wrap unsafe Rust code, adding unsafe blocks to existing types, reviewing unsafe code for soundness, or creating new types backed by raw pointers, MaybeUninit, or FFI

2 0
View
create-task logo
ahrav/scratch-scanner-rs

create-task

Use when creating any beads task — auto-researches the codebase, links related tasks, and produces a rich self-contained description from a structured template. Accepts minimal intent and outputs a complete task ready for agent implementation.

2 0
View
linux-perf-profile logo
ahrav/scratch-scanner-rs

linux-perf-profile

Deep Linux perf profiling — PMU counters, topdown analysis, flamegraphs, and annotated hotspot drill-down on ARM/Graviton

2 0
View
doc-rigor logo
ahrav/scratch-scanner-rs

doc-rigor

Write-then-verify documentation pipeline. Use when a user asks to

2 0
View
sqlite-review logo
ahrav/scratch-scanner-rs

sqlite-review

Review and tune SQLite schemas, queries, indexes, and pragmas. Connects to the actual database to gather concrete evidence (EXPLAIN QUERY PLAN, page counts, table stats) before recommending changes.

2 0
View
review-dispatch logo
ahrav/scratch-scanner-rs

review-dispatch

Parallel specialist code review — 6 focused agents (correctness, design, performance, safety, docs, complexity) diverge independently, then a single ranker merges findings into an importance-ranked report with confidence scores

2 0
View
archive-src logo
ahrav/scratch-scanner-rs

archive-src

Use when the user wants a minimal source-only archive for upload or checkpoint. Creates a tar.gz with just src/ and tests/ directories.

2 0
View
security-reviewer logo
ahrav/scratch-scanner-rs

security-reviewer

Audit memory safety and security in unsafe code blocks, buffer handling, and security-sensitive operations

2 0
View
sim-scaffold logo
ahrav/scratch-scanner-rs

sim-scaffold

Scaffold simulation-testable modules with sans-IO pattern, proptest state machine tests, and fault injection points — prevents retrofitting costs by making code DST-ready from the start

2 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View