Closing the numerical loop does not change the PID + Hdc,dm loop —
the intuition is right. What it changes is the command signal the OSI listens to: the 3-DOF FEM has a
direct feedthrough term dd = C·x + interface_from_force·fm, so every sample of the measured
force — noise included — reappears in dd within the same tick, amplified ×8 by the
fem3_ncf3 phase lead. Above the FEM's top mode (18.5 Hz) that echo is almost all of
dd. The estimator then measures the inverse of the outer feedback path instead of the
inner-loop FRF, the chordal margin at those bins reads 0.1–0.3, and the authority law
dutifully sheds to the floor. One subtraction at the OSI's command tap — estimator untouched — restores the margin to where the
open-loop tests always had it.
The RTHS signal path, with the part nobody drew on the whiteboard in red. The FEM's output equation has a
D-term: interface_from_force = −5.22·10⁻⁸ m/N. Multiply by the interface
stiffness (≈6·10⁶ N/m) and the phase lead's high-frequency gain (×8) and the loop hands the OSI a
zero-lag copy of roughly −0.23·dm at every frequency, buried inside dd:
The proof is one filter and one regression away. Take the >25 Hz part of dd during the
earthquake and overlay the reconstructed echo G_lead(iff·fm): they are the same waveform
(r = 0.94), and the cross-correlation peaks at 0.0 ms — the FEM's algebraic D-term, not the
actuator's forward path, which would show up 15–25 ms later:

The OSI's ST branch estimates the inner-loop FRF as M = S_uy/S_uu from
(dd, dm) and takes the worst chordal margin over bins that pass three gates —
coherence, input power, sidelobe. This is textbook-correct when the command is exogenous. The echo
breaks the assumption, and it breaks it in a way every gate approves of:
dm — γ² sits at 0.8–1.0 across 20–100 Hz. Passes.

This also explains why the BLWN / band-noise tests were always fine. An injected broadband command puts real exogenous power in every bin; the echo (a fraction of dm's noise floor) is negligible next to it, the same estimator reads 0.6–0.7, and everything looks healthy. The echo only owns the band when the exogenous content is narrowband and low — exactly an earthquake at intensity 0.06. And it explains the characteristic time signature you saw: at EQ onset the estimator's first windows are nearly pure echo (fast drop to ≈0.1), then the strong motion adds genuine low-frequency bins that pull the min-scan up to the least-bad echo bin (recovery to only ≈0.3).
The FEM computes dd = C·x + iff·fm. Both iff (a FEM constant) and
fm (the measured force the FEM already consumes) are sitting in the model, so the echo term is
known exactly, sample by sample. Give the OSI's command input the strictly-proper part only; the
actuator keeps receiving the full dd — RTHS physics is untouched, and the estimator, runtime,
and authority law stay byte-for-byte as they are.
Tap the FEM output before the phase lead, subtract iff·fm (one Gain + one Sum), pass
that through a copy of the phase-lead block, feed the OSI's dd port. Zero approximation:
it reconstructs the FEM's strictly-proper output.
Equivalent post-lead form: u_osi = dd_lead − G_T(iff·fm).
Records only store the post-lead dd, so the echo is reconstructed from fm and the
saved fem3_ncf3 lead, with one scalar s fitted on the >25 Hz band (the record does not resolve
an extra rig-side scaling on fm; on-target the structural wiring needs no fit). 10.8 dB echo suppression —
enough to push every echo bin under the estimator's own gates.

The same pipeline ran on every new test record plus two historical open-loop controls. The echo detector
(zero-lag regression of >25 Hz dd against G_T(iff·fm)) doubles as a
classifier — it flags exactly the runs where the numerical loop actually carried the feedthrough, and its
lag separates echo (0 ms) from ordinary forward-path correlation (−25 ms at the actuator delay).
Metrics below are over the engaged span (skipping the estimator warm-up), target 0.55.
| record | echo verdict | corr @ lag | b median | < target | full authority | note |
|---|---|---|---|---|---|---|
| 20260625_1740_RTHS_02 | closed · echo dominant | 0.96 @ 0 | 0.29 → 0.66 | 98% → 6% | 0% → 76% | the user's stable run; fully recovered by the fix |
| RTHS_instability_during_eq | closed · echo dominant | 0.91 @ 0 | 0.20 → 0.33 | 100% → 93% | 0% → 0% | genuine instability: still reads b < 0.1 at the event — detection preserved |
| RHTS_no_inst_butindicators_jump | closed · echo dominant | 0.97 @ 0 | 0.71 → 0.71 | 47% → 43% | 0% → 0% | loop closed with ~zero excitation and no tracking (LP corr −0.27): a no-information regime — see LIMITS |
| RTHS_osi_rising_emergency | closed · echo dominant | 0.95 @ 0 | 0.11 → 0.19 | 88% → 83% | 0% → 0% | ran with authority collapsed live (tracking corr 0.33) — the run itself was broken by the bug; not repairable offline |
| RTHS_instability_at_the_end | closed · echo minor | 0.51 @ 0 | 0.71 | 42% | 33% | strong broadband excitation swamps the echo; baseline healthy through the test, collapses correctly at the real instability (~93 s). No subtraction applied |
| RTHS_5k | no zero-lag echo | 0.35 @ −52 | 0.51 | 72% | 0% | forward-path lag only. Its low margin is a different topic: the 5k plant's healthy margin (≈0.35 by model) sits below the 0.55 target |
| 20260704_1129_testing_OSI | no zero-lag echo | 0.31 @ 0 | 0.71 | 24% | 79% | strong injected signal — healthy |
| osi_highband | no zero-lag echo | 0.39 @ −52 | 0.52 | 70% | 0% | open-loop control group |
| osi_lowband | no zero-lag echo | 0.00 @ +2 | 0.67 | 8% | 62% | open-loop control group — healthy |
| 20260630_1930_testing_OSI | no zero-lag echo | 0.27 @ 0 | 0.71 | 3% | 86% | historical open-loop reference — matches its known-good replay |
Three cross-checks worth calling out:
dm) is untouched, so the residual and
burst branches see the same growth they always did, and genuinely excited bins still carry the ST evidence.
Even with the cleaned tap, the first seconds after the numerical loop engages read low
(b ≈ 0.2 for ~5 s on RTHS_02): the 5 s analysis window still straddles the switch-on, and during the EQ
ramp-in the FEM's modal response to force noise outweighs the tiny exogenous content. That reading is
not evidence — and the authority law already has the right reflex for "no evidence": when the margin is
NaN, it holds (fable_auth.m, "no evidence: hold"). So the remaining piece is a small
evidence-arming gate (fable_evidence_gate.m) that decides, from the OSI's own input
signal, when the slow margin deserves to be believed:
theta = 0.05 mm
(ramp-in/idle sit at 0.002–0.04 mm, strong motion at 0.26–0.79 mm);arm_s = 6 s, one full analysis window plus the
margin median span, so everything the estimator remembers was produced under real excitation;fable_auth processes them before the NaN hold, so the burst/FRF guards keep
watching — including a divergence that starts from an idle loop, which raises the excitation measure and
arms the gate by itself.

The price, measured. Genuine events during armed operation shed on time (instability_at_the_end, event at 87 s: −0.5 s vs ungated). A genuine event inside the very first arming window (instability_during_eq: event 3 s after engagement) sheds ~11 s later — during the first seconds of excitation, "healthy loop under new input" and "diverging loop" are statistically the same from (u, y), so this delay is an information limit, not a tuning miss; the rig's displacement/force interlocks remain the backstop for that window. The theta/arm sweep (0.03–0.08 mm × 5–8 s) confirms the onset protection is robust: every combination except the loosest (0.03 mm / 5 s) keeps start-up authority at 1.00.
run_evidence_gate_validation.m.model_ColumnSetup_00: u_osi = G_T(dd_fem − iff·fm)
(Gain + Sum + one copy of the phase-lead block). The OSI/authority runtime is untouched.
research/osi_parameter_tuning/fable/rths_echo_diagnosis.m % 10-record detector + replays + figures + metrics
research/osi_parameter_tuning/fable/rths_echo_mechanism_figs.m % Figs 1–3 (RTHS_02 autopsy)
research/osi_parameter_tuning/fable/fable_evidence_gate.m % the arming gate (params/state/step)
research/osi_parameter_tuning/fable/run_evidence_gate_validation.m % Figs 6–7 + theta/arm sweep
results: results/rths_echo_diagnosis.mat · results/echo_metrics.json · results/evidence_gate_validation.mat · figures/*.png