A siren sounds higher approaching and lower receding — but does the shift depend only on how fast source and listener close on each other, or does the MEDIUM pick a frame? And when the source outruns its own waves, what angle does the shock make?
Units: f′/f ahead of a source approaching at M = 1/3 (exact 1/(1 − 1/3) = 3/2; Doppler 1842)
▶ Run this simulationRead how it works
Doppler & the sonic boom: validated → validated + honest-module — the derisk EXECUTES the module's own source: 8 slices of DopplerModule.ts sha256-pinned and compiled by mechanical strip only, run 7200 ticks (120 s: Mach 0.6→2.6 and back through the barrier) at the engine's fl(1/120) cadence, the tick schedule bit-exact by fl(1/60) === 2·fl(1/120); the on-screen f′/f obeys the EXACT identity (T_EMIT/Δte)/(1∓M̄) with M̄ = Δxe/(C·Δte) off the two newest wavefronts, so its gap to the side-by-side theory label decomposes with ZERO free parameters (worst residual 1.8e-15 over all 1349 subsonic readings) into a quasi-static ramp lag — Lipschitz-bounded by M_RATE·(t−te_older) at every reading (worst 73.6% of bound), halving to ratio 0.4999999999999 at M_RATE/2 and collapsing ×6.1e11 at M_RATE→0 — plus a ONE-TIME emission-quantization transient: 27·fl(1/60) < 0.45 puts the first real emission on tick 28, so exactly 27 readings carry Q ≈ 27/28; worst on-screen deviation 10.08% (lag + transient, tick 54), worst pure-lag 9.31% (tick 5859), mean 3.78%, all bit-=== pinned; end state and all 7201 HUD strings (1344 distinct) sha256-pinned with live headless-Chrome read-back 6/6 byte-identical across all three regimes; tamper both ways exit 1; 16/16 gates ~5.7 s first attempt. Original validation — the siren, weighed by a wave equation: with NOTHING coded but u_tt = c²u_xx (leapfrog at Courant 1, where 1D propagation is EXACT) and a moving point source, zero-crossing counts at a receiver return f′/f = 1.4999971 ± 3.7e-6 vs the exact 3/2 ahead of a M = 1/3 source (rel 2.0e-6), the law's FORM emerges from a free fit (exponent p = 0.999999 in f′/f = (1−M)^−p, intercept free), the shift ignores the note being played to 1e-14, and the rival 'only relative velocity matters' is falsified at 16,375 SE — a moving OBSERVER at the same M hears 4/3, not 3/2 (Buys Ballot's asymmetry: the medium is a preferred frame); supersonic, the union-of-Huygens-disks envelope hands back sin μ · M = 1 to 5.6e-9 with no arcsin coded
Raw integration of the bare 1D wave equation u_tt = c²u_xx by leapfrog at Courant number exactly 1 — the stencil u⁺ᵢ = uᵢ₊₁ + uᵢ₋₁ − u⁻ᵢ propagates 1D waves EXACTLY and the one-sided end update absorbs perfectly, so the solver has no dispersion error to hide behind. A monochromatic point source moving at v = Mc is injected on the two nearest grid nodes with linear weights; stationary receivers ahead/behind (and a moving observer sampling the field by lerp) record u(t). Frequency estimator: window mean removed first (the 1D Green's function is a step, so the received field is the time-INTEGRAL of the source and carries a DC offset ∝ cos φ — found the hard way when zero crossings vanished), then Schmitt-triggered upward zero crossings refined by a phase-unwrap fit of crossing time vs integer cycle index built incrementally (a spurious crossing rounds to a 0-cycle advance, a missed one to 2 — no cumulative drift over hundreds of cycles). 10 seeds randomize source phase, receiver position and add 5% Gaussian noise. The Mach cone is recovered separately from pure Huygens geometry: numerically maximize the union-of-disks boundary ξ(y) = max_τ[−Mτ + √(τ²−y²)] and fit its slope. 9 gates in scripts/doppler-derisk.mjs (~6 s); known values in scripts/oracles/doppler.reference.json, loaded ONLY to score; tamper ⇒ exit 1. ?world=doppler.
3.7400e-6
1.4200e-5
The classical acoustic Doppler effect (Doppler 1842): f′ = f/(1 ∓ M) for a moving source, f′ = f(1 ± M) for a moving observer, distinct at second order because sound has a medium frame (Buys Ballot 1845), plus the supersonic Mach-cone law sin μ = 1/M (Mach & Salcher 1887). It VALIDATES, not derives: the generator is the bare wave equation + a moving forcing term; 1/(1∓M), 1+M and asin(1/M) appear ONLY in the reference file. Non-circularity is checked four ways in-script: the law's functional form is recovered by a free fit whose exponent and intercept are unconstrained (gate C), the shift is invariant under the source frequency (gate D), the scoring self-test flips the exit code with the recovered value unchanged (gate H), and the decisive control is PHYSICAL — the same solver and estimator, with only 'who moves' changed, returns a second-order-different answer (4/3 vs 3/2) that kills the relative-velocity-only rival at 16,375 SE. This is the lab's first oracle where the falsified rival is itself a symmetry claim about frames — the acoustic ancestor of the aether problem — and it grounds the existing muon/schwarzschild relativity arc from the medium side: sound HAS a preferred frame and the oracle proves it; light does not, and that difference is special relativity.
RESOLVED EXACTLY (rung 6, module untouched — the derisk now executes the module's own source; see module_protocol in the reference). The on-screen f′/f values ARE measured off the live wavefront pattern (axis crossings of the two newest fronts), and their deviation from the side-by-side law-fed 'theory' label is now DERIVED, not estimated: the exact identity fa = (T_EMIT/Δte)/(1−M̄), M̄ = Δxe/(C·Δte), decomposes the gap with zero free parameters (worst residual 1.8e-15 across all 1349 subsonic readings of the 7200-tick horizon) into (a) a quasi-static RAMP LAG Q·(M̄−M_now)/((1−M̄)(1−M_now)) — the M-sweep (M_RATE = 0.04/s) makes M_now run ahead of the emission-window mean M̄ by ≤ M_RATE·(t−te_older), a Lipschitz bound every reading obeys (worst 73.6% of bound); measured worst 9.31% of theory, mean 3.78% (the old '2–6%' estimate was right in mechanism, low in maximum) — witnessed: halving M_RATE halves the mean lag (ratio 0.4999999999999), freezing it collapses the deviation ×6.1e11 to float noise; and (b) a ONE-TIME EMISSION-QUANTIZATION TRANSIENT (Q−1)/(1−M_now): 27·fl(1/60) < 0.45, so the module's first real emission lands on tick 28 (not 27) and exactly the 27 readings whose window spans it carry Q ≈ 27/28 ⇒ a −3.6% dip; combined worst 10.08% at tick 54, bit-pinned. Still-open (unchanged, disclosed): the module's wavefronts are ideal Huygens circles sharing the wave-propagation premise — the oracle closes that with the raw PDE recovery; the 'theory' labels and Mach-cone μ readout are law-fed display, with the non-circular subsonic and cone recoveries being gates A–G's job; ratios are suppressed for 0.7 < M ≤ 1 where 1/(1−M) is ill-conditioned against the two-front estimator.
Zero gate retries: prototyped in the scratchpad first, which caught two estimator traps at design time — (a) zero-crossing counting silently fails on the raw received field because the 1D Green's function is a STEP, so the receiver sees the time-integral of the source with a phase-dependent DC offset (fix: remove the window mean — physics, not a fudge); (b) a phase-unwrap fit that anchors every cycle index to the FIRST crossing accumulates rounding drift over ~250 cycles when the median period is off by 0.05 samples (biases of ~1e-2 in early prototypes); building the index incrementally makes each rounding local and the estimator immune to both spurious (round to 0) and missed (round to 2) crossings. Estimator-checklist compliance: no division near zero (crossing interpolation divides by a full sample step), no peak locator (the observable is a frequency, fitted as a line through crossing times), windows start well clear of the switch-on transient and end before any boundary interaction (ends are exact absorbers at Courant 1 anyway). Tolerances justified from measured systematics: noiseless recovery lands at rel 2e-7 (source-injection discretization only — Courant-1 leapfrog is otherwise exact), 10-seed mean at 2e-6 with SE 3.7e-6, gates set at 5e-5/2e-4 (≈13×SE / 10×worst-seed), five orders of magnitude tighter than the 12.5% rival gap. Runtime ~6 s, 9/9 gates. HONEST-MODULE CLIMB (refiner): gates M1–M7 added, zero science retries — the module is fully deterministic (no RNG, basic-ops-only state arithmetic, so Node and Chrome agree bit-for-bit), and the engine drive is provably bit-exact (accumulator ∈ {0, fl(1/120)} at every step, checked over all 14400 engine steps). The one surprise was the transient: prototyping showed max|Q−1| = 1/28-ish rather than ~1e-12, traced to the emission accumulator starting at 0 with 27·fl(1/60) < 0.45 — the first emission is one tick late, a one-time schedule defect that then never recurs (the banked surplus keeps every later interval at 27 ticks over the whole horizon). Gates classify the two reading populations separately instead of averaging the transient away. Live read-back done from the built worktree (vite preview + playwright headless Chrome): 6 reads, every innerHTML byte-identical to a member of the executed-source string sequence with increasing tick assignments, spanning subsonic → transonic → supersonic. Tamper: known_value ×1.02 ⇒ 4 gates fail; t_end pin +1 ulp ⇒ M2 fails, exit 1, run values unchanged; both restored by hand.
npm run derisk -- doppler (scripts/doppler-derisk.mjs)scripts/oracles/doppler.reference.jsonC. Doppler, 'Über das farbige Licht der Doppelsterne und einiger anderer Gestirne des Himmels', Abh. Königl. Böhm. Ges. Wiss. (5) 2, 465–482 (1842); C. H. D. Buys Ballot, 'Akustische Versuche auf der Niederländischen Eisenbahn', Poggendorffs Annalen der Physik 66, 321–351 (1845); E. Mach & P. Salcher, 'Photographische Fixirung der durch Projectile in der Luft eingeleiteten Vorgänge', Sitzungsber. Kais. Akad. Wiss. Wien 95, 764–780 (1887); L. D. Landau & E. M. Lifshitz, Fluid Mechanics, §68 (Mach angle).