VIOLET V0: reactor clock primitives + latency harness (gate PASSED)
clock.py: mono_ns single timebase; LatencyHistogram (raw reservoir, exact nearest-rank percentiles); PlaneClock per-plane seq clocks with strict staleness budgets (age==budget not stale — MHS FIX-9 lesson); DeadlineScheduler — single-driver timer heap with EARLY-WAKE on earlier-than-head insert (the jitter-budget mechanism), isolated callbacks. harness.py: seeded deterministic event storms (sequence-hash asserted) driving the REAL Rust ExecutionKernel via the MOCK bundle; reaction latency measured producer-stamp→post-fold across the queue hop exactly as the production account stream consumes; ACCOUNT_UPDATE wallet sentinel tracks kernel k_capital so synthetic storms never trip capital_frozen; sustained throughput reported alongside the gate. V0 GATE (prod host, 50k events, 5k concurrent deadlines, burst 8/12ms ≈ 667 ev/s offered): venue_event_reaction p99 7.19ms (<10ms budget), deadline_jitter p99 4.86ms (<25ms), zero early fires. Capacity artifacts: the 32/1ms and 16/12ms storms (archived reports) show intra-burst queueing dominating beyond ~1.3k ev/s offered at ~0.33ms/fold. 17 unit tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
68
prod/clean_arch/violet/test_violet_harness.py
Normal file
68
prod/clean_arch/violet/test_violet_harness.py
Normal file
@@ -0,0 +1,68 @@
|
||||
"""V0: ReactorHarness — determinism, report shape, MOCK bundle wiring."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, "/mnt/dolphinng5_predict")
|
||||
sys.path.insert(0, "/mnt/dolphinng5_predict/nautilus_dolphin")
|
||||
|
||||
import pytest
|
||||
|
||||
from prod.clean_arch.violet.harness import (
|
||||
HarnessReport,
|
||||
ReactorHarness,
|
||||
StormSpec,
|
||||
generate_events,
|
||||
sequence_hash,
|
||||
)
|
||||
|
||||
|
||||
def test_seed_determinism_sequence_hash():
|
||||
a = generate_events(StormSpec(n_events=500, seed=42))
|
||||
b = generate_events(StormSpec(n_events=500, seed=42))
|
||||
c = generate_events(StormSpec(n_events=500, seed=43))
|
||||
assert sequence_hash(a) == sequence_hash(b)
|
||||
assert sequence_hash(a) != sequence_hash(c)
|
||||
|
||||
|
||||
def test_event_mix_kinds_only_known():
|
||||
spec = StormSpec(n_events=300, seed=1)
|
||||
kinds = {e["kind"] for e in generate_events(spec)}
|
||||
assert kinds <= set(spec.mix.keys())
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_small_storm_report_shape_real_kernel():
|
||||
"""Drives the REAL Rust kernel through a tiny storm via the MOCK bundle."""
|
||||
spec = StormSpec(n_events=400, seed=7, deadlines=50,
|
||||
deadline_spread_ms=(5, 200), warmup_events=50)
|
||||
harness = ReactorHarness()
|
||||
report = await harness.run_storm(spec)
|
||||
assert isinstance(report, HarnessReport)
|
||||
payload = json.loads(report.to_json())
|
||||
for key in ("spec", "histograms", "gate", "passed", "sequence_hash", "meta"):
|
||||
assert key in payload
|
||||
for hist in ("venue_event_reaction", "kernel_call", "deadline_jitter"):
|
||||
assert hist in payload["histograms"]
|
||||
assert payload["histograms"][hist]["count"] > 0
|
||||
assert payload["gate"]["early_fires"] == 0
|
||||
assert payload["gate"]["deadlines_fired"] == 50
|
||||
# reaction samples exclude warmup
|
||||
assert payload["histograms"]["venue_event_reaction"]["count"] == 400 - 50
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_storm_does_not_freeze_kernel_capital():
|
||||
"""Account-event storm must leave the kernel tradeable (no reconcile
|
||||
freeze from synthetic wallet noise — wallet values are kept coherent)."""
|
||||
spec = StormSpec(n_events=300, seed=3, deadlines=10, warmup_events=10)
|
||||
harness = ReactorHarness()
|
||||
await harness.run_storm(spec)
|
||||
assert harness.kernel.is_capital_frozen() is False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(pytest.main([__file__, "-v"]))
|
||||
Reference in New Issue
Block a user