Fable OSI — Speedgoat Runtime Parameter Reference

A complete, plain-language field guide to every argument and tunable parameter of the real-time Online Stability Indicator (fable_osi_runtime.m) and its authority law, as deployed on the Speedgoat target.

Source of truth: control_and_HS/OSI/fable_osi_runtime.m (estimator + authority law, flattened), control_and_HS/OSI/prepare_fable_runtime.m (builds the parameter arrays), OSI_tests/fable/fable_osi.m and OSI_tests/fable/fable_auth.m (the desktop originals the runtime is bit-for-bit equivalent to). All notation on this page is copied verbatim from those files.

Contents
  1. What the OSI is and what it produces
  2. The runtime interface — every input and output argument
  3. Architecture — two time scales, five branches
  4. The core quantities and equations
  5. Branch 1 — Slow ST (the accurate margin level)
  6. Branch 2 — Residual (quiet-band growth watcher)
  7. Branch 3 — Fast path / “quick dip” guards
  8. Branch 4 — Regime & calibration
  9. Branch 5 — The authority law (fable_auth)
  10. Master table — categorized tunable parameters

1 · What the OSI is and what it produces

The OSI (Online Stability Indicator) watches the servo-hydraulic control loop in real time and answers one question every 0.125 s: how close is the loop to going unstable right now? It answers with a single number, the margin b — large means safe, small means near the edge.

It does not just observe. It also acts: an authority law turns the margin into a gain factor auth (called a internally, range a_min…a_max) that multiplies the command going to the actuator. When the loop is healthy the OSI runs the loop at full authority (auth = 1); when the margin drops toward the target it sheds authority to pull the loop back from the edge, then recovers it once the margin returns.

The one setpoint that governs everything: target (default 0.55). The law regulates the margin b onto this value. A healthy loop sits above it and runs at full authority; a degrading loop is held right at it. target is also reused as the detection threshold. Change this one number and the whole system's conservatism moves with it.

2 · The runtime interface — every input and output argument

The Simulink / Speedgoat block calls one function once per base-rate sample (the base rate is fs = 2048 Hz, so every dt = 1/2048 s):

[auth, b_osi, b_st, b_res, b_fast, trip_reason, valid, decision] = ... fable_osi_runtime(dd, dm, en, fbls, fblw, fblbins, fblfw, fblfbins, fblag, fbla)

Inputs

dd — scalar, one sample

The loop command (drive) signal, in mm. This is the input u of the plant. In the spectral estimates it produces the auto-spectrum Suu.

dm — scalar, one sample

The measured displacement (response) signal, in mm. This is the output y of the plant. It produces Syy and, together with dd, the cross-spectrum Suy.

en — scalar enable code

The mode switch. It combines a base mode with an optional +2 pause bit:

The remaining six inputs are compile-time constant arrays built once by prepare_fable_runtime.m. They carry all configuration — the block never takes a live parameter. They are the subject of most of this document.

ArgumentShapeWhat it carries
fbls57×1Scalar OSI config vector (segment sizes, gates, calibration, fast-path knobs). Index map in §5–§8 and the master table.
fblwsegment_n×1The slow-path Hann window (2048 points) applied to each 1 s segment before its FFT.
fblbinsnf×5Per-slow-bin table: [freq_hz, fft_bin, keep, res_keep, nominal_curve] — which FFT bins are analysed, which survive line-rejection, which are in the residual hazard band, and the prior-model margin curve.
fblfwfast_segment_n×1The fast-path Hann window (512 points) for the 0.25 s fast segments.
fblfbinsnf_fast×6Per-fast-bin table: [freq_hz, fft_bin, keep, cell_lo, cell_hi, band_id] — the fast grid plus the map that projects slow bins onto fast bins and the burst sub-band id of each bin.
fblagn_alpha×1The authority-prediction gain grid alpha_grid (25 log-spaced loop-gain multipliers, 0.05–20). Used to predict the margin at other authority levels.
fbla31×1The authority-law parameter vector (target, rates, gates, trip response). Index map in §8 and the master table.

Outputs

All outputs are held constant between the internal 0.125 s steps (they refresh once per step, published on tick T0+56).

OutputMeaning
authThe authority factor a for the “Apply OSI gain” product. In shadow mode (en_act=0) it is pinned to a_init.
b_osiThe selected margin (the headline number). NaN = no evidence yet / warm-up (never a fabricated value).
b_stThe slow coherent-branch margin (NaN when the band is unobservable).
b_resThe residual-branch margin (equals the cap 1/√2 when the branch is not engaged).
b_fastThe fast short-memory margin (NaN when unavailable).
trip_reason0 none, 1 quiet-band burst trip, 2 fast FRF-collapse trip.
valid1 when b_osi is real evidence (post warm-up, non-NaN).
decisionAuthority-law action this step: 0 hold, 1 down, 2 severe down, 3 up, 4 fast trip.

3 · Architecture — two time scales, five branches

The indicator runs on two clocks so it can be both accurate and fast:

ScaleCadenceSegmentMemoryPurpose
SLOW pathhop_s = 0.25 s1 s Hann (segment_s)5 s ring, 17 segments (window_s)Accurate margin level and the recovery authority. It can only be trusted slowly because good spectra need averaging.
FAST path (“quick dip”)step_s = 0.125 s0.25 s Hann (fast_segment_s)~0.6 s ring, 3 segments (fast_ring_n)Catches a sudden collapse in ≤ 0.5 s. Fast trips may only ever reduce authority; increases always require the slow, accurate margin.

Five detection/decision branches run on top of those two clocks. They are the organizing principle for every parameter in this document:

Slow ST — the accurate margin level (slow) Residual — quiet-band growth watcher (slow) Fast guards — quick-dip ST + burst trips (fast) Regime / calibration — baseline management (both) Authority law — margin → gain decision

The signal chain (one slow hop)

dd, dm rings→ detrend + Hann + FFT→ Suu, Syy, Suy (median over ring)→ FRF M, coherence g2, residual res→ excited / quiet gates→ ST + residual margins→ combine → b→ authority law → auth

The runtime time-slices this pipeline across 56 base-rate ticks (one bounded phase per tick) so the Speedgoat never does the whole burst in a single 488 µs slot — but the arithmetic is bit-identical to doing it all at once. That scheduling is an implementation detail; it does not change any parameter's meaning.

4 · The core quantities and equations

These are the quantities the branches are built from. Understanding them makes the parameters obvious.

Spectra and the frequency response

From the windowed FFTs U (of dd) and Y (of dm), aggregated by median across the ring of segments:

auto- and cross-spectra Suu = median|U|²    Syy = median|Y|²    Suy = median( Y·conj(U) )

The empirical frequency response (FRF, the transfer from command to response at each bin):

FRF estimate M M = SuySuu

Coherence — how much to trust each bin

The raw magnitude-squared coherence measures how linearly related dm is to dd at a bin (1 = perfectly driven, 0 = noise). It is bias-corrected using the effective number of independent averages k_eff:

raw and debiased coherence g2raw = min( |Suy|²Suu·Syy , 1)     g2 = max(0, k_eff·g2raw − 1k_eff − 1 )

k_eff and the coherence gate gamma_gate are derived from the window overlap, not tuned directly:

effective averages & null-calibrated gate k_eff = K1 + 2Σm(1−m/K)ρm²     gamma_gate = 1 − gamma_alpha 1/(k_eff−1)

Here K = n_segment (17), ρm is the window's overlap correlation at lag m·hop. The gate formula comes from the null hypothesis “no true relation”, under which P(γ² > z) = (1−z)k−1. So gamma_alpha (§7) is a false-pass probability, not a raw coherence value.

The margin itself — the number the whole system defends

The project’s stability margin is the chordal / NCF-style distance of the Nyquist locus from the critical point. With the sensitivity S and complementary sensitivity T:

margin definition b(ω) = |1 + L(ω)|√( 2(1 + |L(ω)|²) )  =  1√2 · √( |S|² + |T|² )

In the estimator, L is not known directly; instead the chordal margin is computed from the FRF M via the intermediate st, and capped at the mathematical ceiling cap = 1/√2 ≈ 0.7071:

chordal margin from the FRF st = √( |1 − M|² + |M|² )     chord = 1√2 · st     b_st = min( cap, minexcited bins chord )

The min is taken over the excited bins only (bins the command actually drives), after a frequency-median smoothing of width freq_medfilt_n. The reported b is the temporal median of the two slow branches, min(b_st, b_res), over margin_filter_n hops.

The residual — energy the model does not explain

unexplained (residual) power res = Syy · max( 1 − g2, residual_floor )

A bin with high coherence (g2→1) has almost no residual; a bin whose energy is not explained by the command (an emerging self-excitation) keeps a large residual. The residual branch (§6) watches this in the undriven “quiet” bins.

Two gates that decide which bins count

input-power gate (is this bin actually driven?) has_input = Suu > peak(Suu) · 10−input_power_range_db/10
sidelobe gate (is this bin just window leakage?) not_leak = Suu > movmax(Suu, 7) · 10−sidelobe_db/10

A bin is excited (used by the ST branch) if it passes line-rejection (keep), the coherence gate (g2raw > gamma_gate), the input-power gate and the sidelobe gate. A bin is quiet (used by the residual branch) if it is in the residual band, has no input, and has low coherence (g2raw < gamma_quiet).

CUSUM — the quickest-change detector behind the fast trips

The fast guards do not threshold a single reading; they accumulate evidence with a one-sided CUSUM (cumulative sum) so that sustained moderate shifts trip within a few steps while isolated spikes decay:

CUSUM recursion & trip test Scus ← max( 0, Scus + z − ν )     trip when Scus > h

where z is a calibrated log z-score, ν (nu) is the drift the accumulator ignores, and h is the trip level. Each branch has its own nu/h pair (§7).

The authority prediction — “what would the margin be at a different gain?”

To size sheds and cap recovery, the OSI predicts the margin at other loop-gain multipliers alpha (the alpha_grid). Freezing the plant FRF and scaling the open loop by alpha:

predicted margin vs loop-gain multiplier Lb = M1 − M    Lα = α · Lb    c(α) = |1 + Lα|√( 2(1 + |Lα|²) )    pred_margin(α) = minexcited c(α)

The loop running at multiplier alpha has authority alpha·a. The authority law walks the contiguous safe interval of this curve around alpha = 1 to floor a shed and cap a recovery.

5 · Branch 1 — Slow ST slow

This is the branch that produces the accurate margin level b_st and the recovery authority. It runs every hop_s = 0.25 s on the 5 s ring. Its parameters trade smoothness/lag against reactivity.

segment_s fbls—(via segment_n) 1.0 s

Length of one analysis segment (the FFT window). Sets frequency resolution: 1 s → 1 Hz bins. Derived count segment_n = round(segment_s·fs) = 2048. do not go below 1 s shorter kills the 1 Hz resolution the margins need.

window_s fbls (via n_segment) 5.0 s

Total span averaged. Longer ↑ = smoother, laggier margin; shorter = jumpier, faster to move. Derived: n_segment = round((window_s−segment_s)/hop_s)+1 = 17 (the ring depth).

hop_s fbls[52] 0.25 s

The slow refresh cadence — one new segment FFT per hop. Must be an integer multiple of step_s (steps_per_hop = 2). It is the time unit for every “per hop” counter below.

margin_filter_n fbls[14] 3

Temporal median over this many distinct slow updates before b is reported. Bigger ↑ = smoother, more constant selected OSI, but adds (n−1)·hop_s/2 of lag.

freq_medfilt_n fbls[13] 3

Median smoothing across neighboring frequency bins before the min is taken. Bigger ↑ = fewer single-bin dips counted as the margin. must be odd the runtime's hand-coded median filters assume odd, centered windows.

slow_filt_alpha fbls[15] 0.2

EMA weight of the slow-margin tracker b_slow_filt that the fast path uses as its direction reference. Lower ↓ = steadier reference, slower to follow a real level change. b_slow_filt ← (1−α)·b_slow_filt + α·b_slow.

gamma_alpha fbls (folds into gamma_gate) 0.01

False-pass probability of the coherence gate (see §4). Smaller ↓ = stricter gate, fewer bins accepted, less noise in the margin but more “no evidence”. Enters the runtime already baked into gamma_gate (fbls[8]).

gamma_quiet fbls[9] 0.15

Coherence ceiling for a bin to count as “quiet” (undriven). Bins above this are related to the command and are excluded from the residual branch.

input_power_range_db fbls[10] 35 dB

Bins more than this far below the in-band input peak are treated as unexcited. Smaller (e.g. 30) ↓ = stricter, margin computed on fewer, stronger bins. Feeds the has_input gate (§4).

sidelobe_db fbls[11] 25 dB

Bins more than this far below a ±3 Hz neighbor are window leakage, not real excitation, and are excluded. The Hann first sidelobe is −31 dB and leaks coherently, so without this gate a low-band margin can read 0.45 instead of the true 0.7.

min_bins fbls[12] 5

Minimum number of excited bins for the slow ST margin to be considered observable. Below it, b_st = NaN (reported as no evidence rather than a guess).

cap fbls[16] 1/√2 ≈ 0.7071

The mathematical ceiling of the margin. Every branch caps its output here; it is a constant, not really a tuning knob.

threshold fbls[17] = target (0.55)

Detection / fast-trip margin level. fable_osi.m's own default is 0.30, but prepare_fable_runtime overrides it to target_outer_ncf (0.55) so detection and regulation share one level. Used by the fast-ST trip (b_fast < threshold + fast_babs_offset).

warm_updates fbls[35] 4

Slow updates that must pass before any margin is reported (fills the ring first). During warm-up b_osi = NaN.

6 · Branch 2 — Residual slow

The ST branch only sees frequencies the command drives. A loop can go unstable at a frequency the command is not exciting — a growing self-oscillation. The residual branch watches the undriven (quiet) bins inside a hazard band for energy growth that the model cannot explain (§4, res). It engages with hysteresis and persistence so it does not false-alarm on harmonic distortion.

The detection statistic is a per-bin log z-score of the self-normalized residual ratio against its calibrated baseline:

residual z-score z = log( res/baseline / q_med ) − μ0σ0    growth = exp( max(z,0)·σ0 )    b_res = anchor√( max(growth,1) )
residual_band_hz fblbins (res_keep) [28 100] Hz

The hazard band the branch guards. Keep it where the loop can actually go unstable; widening it down into harmonic-distortion territory (2–28 Hz distortion of a strong 2–7 Hz command) causes false engagement. Enters as the res_keep column of fblbins.

z_on fbls[25] 4.0

The z threshold to engage the branch. Raise ↑ to make engagement rarer (fewer false alarms, later detection).

z_off fbls[26] 2.0

The z threshold to disengage. The gap z_on − z_off is the hysteresis band that stops the branch chattering on/off.

res_on_n fbls[27] 4

Consecutive slow hops above z_on (at the same frequency) required to engage. More ↑ = needs more sustained evidence, smoother but slower.

res_hold_s fbls[28] (res_hold_hops) 5 s

How long an unconfirmed engagement may persist inside the hysteresis zone before it expires. Prevents a stale engagement from depressing the margin forever. Stored as res_hold_hops = round(res_hold_s/hop_s) = 20.

res_min_growth_db fbls[29] 3 dB

Minimum absolute growth (on top of the z threshold) needed to engage. Raise ↑ to ignore small quiet-band changes entirely. This is what makes the defendable quiet-band level absolute (~0.40), not target-relative.

res_match_hz fbls[30] 3 Hz

Same-frequency persistence tolerance: successive exceedances must be within this many Hz to count as the same event.

sigma0_floor fbls[31] 0.15

Floor of the calibrated ln-ratio spread σ0. Raise ↑ to desensitize the z-score globally (a large σ0 shrinks every z).

residual_floor fbls[18] 0.03

Lower clamp on 1 − g2 when forming res, so a perfectly-coherent bin still carries a tiny, well-defined residual instead of exactly zero.

7 · Branch 3 — Fast path / “quick dip” guards fast

The fast path runs every step (0.125 s) on a short ~0.6 s ring of 0.25 s segments. It exists to catch a sudden dip in the margin within 0.25–0.5 s — far faster than the 5 s slow ring could react. It contains two CUSUM detectors (§4) that can only ever reduce authority:

Fast grid & memory

fast_segment_s fbls[36] (fast_segment_n) 0.25 s

Fast segment length → 4 Hz bins (fast_segment_n = 512). Short so it reacts quickly; too short to resolve fine structure, which is why it only trips, never sets the level.

fast_ring_n fbls[37] 3

Number of fast segments aggregated (~0.5 s memory). The fast margin uses the median over this ring.

fast_min_bins fbls[38] 3

Minimum excited fast bins for a fast statistic to be computed at all.

Fast ST guard (FRF-change CUSUM)

fast_st_nu fbls[39] 1.25

CUSUM drift ν for the FRF-change z. Higher ↑ = calmer (more evidence ignored per step).

fast_st_h fbls[40] 4.5

CUSUM trip level h. The main speed-vs-false-alarm knob: each unit of h adds roughly one extra 0.125 s step of sustained evidence before a trip. Lower ↓ = faster, riskier trips.

fast_babs_offset fbls[43] 0.10

A fast-ST trip also requires b_fast < threshold + fast_babs_offset. Raise ↑ to allow trips further above target (more protective); toward 0 = trip only once the fast margin is already at target.

fast_amove_frac fbls[56] (with amove_hold[57]) 0.02

The FRF-change statistic watches the total loop, which includes the authority factor. If the committed authority moves more than this (relative) the statistic is disarmed for one full analysis window (amove_hold = round(window_s/step_s) = 40 steps) so the law's own moves never read as a plant change. In replays where authority does not act on the plant, a_cmd = NaN leaves the detector always armed.

fast_d_sig_floor fbls[48] 0.30

Floor of the calibrated ln FRF-change spread σ_d. Raise to desensitize the fast-ST z-score. With too few calibration samples σ_d is set to 1e6 — the guard disarms itself rather than false-trip.

Fast burst guard (quiet-band divergence CUSUM)

fast_burst_nu fbls[41] 1.0

CUSUM drift for the burst z. Same trade as fast_st_nu.

fast_burst_h fbls[42] 6.0

Burst CUSUM trip level. Can sit high because a diverging loop produces a huge z: a 1–2 segment ring-down after a command step gains ~4, but sustained growth still crosses in 3–6 steps.

fast_burst_bands fblfbins (band_id) → n_burst_bands[49] [28 44; 44 60; 62 78; 78 94; 94 100]

The guarded quiet sub-bands (rows of [lo hi] Hz), 5 bands by default. Each is a separate CUSUM. Fewer rows = cheaper and less sensitive. Enters as per-bin band_id in fblfbins.

fast_sig_floor fbls[47] 0.20

Floor of the calibrated ln burst-power spread. Raise to desensitize all burst bands. Bands with <8 calibration samples get σ = 1e6 and are disarmed.

Fast input-power sanity gate (shared)

fast_pin_lo / fast_pin_hi fbls[44] / fbls[45] 0.25 / 4.0

The newest fast segment's input power must stay within [lo, hi]× its ~3 s EMA for the FRF-change statistic to be trusted. A fading or bursting command mimics a plant change; this window rejects that artifact.

fast_pin_alpha fbls[46] 0.04

EMA update rate (per 0.125 s step) of that input-power reference p_in_ema.

8 · Branch 4 — Regime & calibration both

Every statistic above is measured against a calibrated healthy baseline. This branch builds that baseline at startup and rebuilds it whenever the excitation regime changes (a new test phase drives a different set of frequencies) — because baselines do not transfer across excitation regimes, and the excited-set change is the one exogenous signal that an instability cannot fake. These rarely need touching.

regime_hops fbls[34] 8

Sustained hops of excited-set change before a rebaseline is triggered. Larger ↑ = more tolerant of slowly wandering excitation, slower to re-adapt. A change is declared when ndiff > max(6, 0.5·nref) bins differ.

cal_skip_s fbls[19] 10 s

Startup blackout — ignore this much data before collecting calibration windows (lets transients settle).

cal_windows fbls[20] 80

Number of accepted calibration windows (slow hops) that define a full baseline.

cal_min_windows fbls[24] 24

Minimum acceptable calibration length if the timeout is hit before cal_windows accumulate.

cal_timeout_hops fbls[23] 600

Give up waiting for a full calibration after this many hops and finalize with what is accepted (≥ cal_min_windows).

cal_reject_factor fbls[21] 4

Reject a candidate window if its broadband residual differs from the running reference by more than this factor (guards against calibrating on a transient).

cal_restart_rejects fbls[22] 12

This many consecutive rejects means the reference itself was bad — discard and restart calibration collection.

bl_adapt_tau_s fbls (folds into bl_alpha[32]) 100 s

Time constant of the gated, ultra-slow baseline drift tracking (only while healthy). Enters the runtime as bl_alpha = hop_s/bl_adapt_tau_s = 0.0025.

bl_adapt_max_db fbls[33] 3 dB

Hard cap on how far baseline drift may move from the original calibration. never raise this far a large cap lets real, slow degradation be absorbed into the baseline and go undetected.

Also in fbls and derived, not user-tuned: k_eff [7] (≈9.1), gamma_gate [8], n_alpha [50] (=25), pred_denom_floor [51] (1e-3, numerical guard on 1−M), nf [53], nf_fast [54], pred_enable [55] (see §9), and the sizes dt [1], fs [2], step_n [3], steps_per_hop [4], segment_n [5], n_segment [6].

9 · Branch 5 — The authority law fable_auth decision

This is the actuator. Every 0.125 s it turns the margin b (and the fast trips) into the published authority auth. Its parameters live in fbla (index in brackets). The contract:

Regulation setpoint & smoothness

target fbla[1] 0.55

The OSI level to defend/track. Raising ↑ makes the system more conservative (sheds earlier). must stay below the healthy-loop margin at full authority or the law permanently detunes chasing an unreachable margin. Shared with the detection threshold.

b_filt_tau_s fbla[6] (as filt_alpha) 0.4 s

EMA time constant applied to b before it sizes sheds and gates recovery. Larger ↑ = smoother, more constant authority; 0 disables it. Severe-drop detection always also watches raw b, so smoothing never delays catching a genuine collapse by more than down_confirm_n updates. Stored as filt_alpha = 1 − exp(−dt_update/b_filt_tau_s).

Drop / shed behavior

down_deadband fbla[7] 0.01

Margin must fall below target − down_deadband to count as a deficit. Widen to ignore tiny grazes (less flicker).

down_confirm_n fbla[8] 2

Consecutive low updates before a (non-severe) shed starts. More ↑ = fewer false sheds on noise, but adds n·dt_update of reaction delay.

down_power fbla[9] 1.5

Exponent of the multiplicative shed a·(b/target)down_power. Higher ↑ = deeper correction per update; 1 = proportional.

down_rate fbla[10] 2.0 /s

Max shed speed (authority units/s) for a confirmed deficit. The main “catch drops fast” knob.

down_settle_s fbla[28] 1.25 s

The key anti-compounding knob. The margin estimate lags the loop by its analysis-window flush, so each shed is sized once and then held for down_settle_s before being re-sized. Without this, re-deriving a multiplicative shed from the same stale reading every step compounds one dip into a slam to the floor. Higher (toward the OSI window length) = gentler, staircase-like sheds.

re_shed_delta fbla[29] 0.02

A margin reading this much below the one that sized the active shed re-sizes it immediately (fresh evidence of continued decline bypasses the settle hold). Lower ↓ = more reactive to genuine decline.

sev_frac fbla[11] 0.60

Raw b < sev_frac·target is treated as severe: immediate shed, bypassing confirmation, the commit gate, and the ordinary rate limit.

sev_down_rate fbla[12] 8.0 /s

Shed speed for severe deficits (units/s). The emergency path — keep high.

Recovery behavior

up_deadband fbla[13] 0.02

Margin must exceed target + up_deadband before recovery is considered (hysteresis). Widen to kill target-hugging oscillation; narrow for faster reclaim.

up_hold_s fbla[14] 1.5 s

The margin must hold above the recovery threshold this long before authority moves up. Longer ↑ = more constant authority, later recovery.

up_rate fbla[15] 0.08 /s

Base recovery speed (units/s) when the margin is model-verified (coherent input present, valid_up true).

up_rate_blind fbla[16] 0.02 /s

Recovery speed with no coherent input (“probe and verify”): the loop feels its way up while the burst guard and residual branch stand watch. Kept several times slower than up_rate.

up_prop fbla[17] 3.0

Surplus-proportional recovery boost: effective rate = up_rate·(1 + up_prop·(b_filt − target − up_deadband)/target). 0 = constant rate; higher = sprint back when the margin is comfortably high, creep when barely above target.

Anti-flicker commit gate

min_step fbla[18] 0.02

The committed authority (what the loop sees) only moves when the internally-regulated value has drifted at least this far. Bigger ↑ = steppier, more constant authority (fewer, larger moves); 0 = continuous. Severe sheds and fast trips bypass it. The internal value keeps integrating, so the gate never deadlocks recovery — it just quantizes it into min_step-sized steps.

Model-predicted safe authority

use_pred fbla[19] 1

1 = use the prediction curve (§4) to floor sheds and cap recovery; 0 = pure power-law regulation (cheaper, more shed overshoot). Tie to pred_enable (below).

pred_guard fbla[20] 0.03

Predicted margin must clear target + pred_guard to count as safe. This is also the recovery standoff: authority may climb up to (not past) the interpolated boundary where the predicted margin crosses that level. Widen if the prediction proves optimistic on your rig.

pred_floor_frac fbla[21] 0.90

Shed floor as a fraction of the predicted-safe authority (0.90 = a confirmed shed stops 10% below the predicted-safe point instead of slamming to the power-law floor). DOWN path only.

pred_enable fbls[55] (OSI side) 1

OSI-side switch that actually computes the prediction grid. Set to 0 (via hs.fable_pred_enable) to drop that pipeline phase for CPU relief; the law then regulates by power law alone. Should be turned off together with use_pred.

Fast-trip response

trip_drop fbla[22] 0.60

Multiplicative drop on a trip (0.60 = shed 40% instantly). Burst trips (trip_reason = 1) compound this every step while the divergence evidence persists.

trip_power fbla[23] 1.5

A fast-ST trip (trip_reason = 2) is sized a·(b_fast/target)trip_power, never milder than trip_drop allows. Higher ↑ = deeper drop for a given fast-margin reading.

trip_cool_s fbla[24] 5.0 s

Cooldown after a trip during which recovery is blocked and the trip re-arms.

trip_undo_s fbla[25] 2.5 s

A trip followed within this window by a confirmed excitation-regime recalibration is undone — the “trip” was the test phase changing, not the plant.

self_move_gate_s / self_move_frac fbla[30] / fbla[31] 1.5 s / 0.02

A fast-ST trip is honored only when the committed authority has been steady — moved less than self_move_frac (relative) per update — for the last self_move_gate_s. The estimator watches the total loop including the authority, so the law's own moves would otherwise self-trip. Real damage arrives while a is static, so the gate costs nothing there; burst trips are never gated.

Post-event caution (latched ceiling)

latch_relax fbla[26] 1.15

After a trip or a residual-driven (invisible-band) shed, recovery is capped at latch_relax× the post-shed authority: hard evidence of a plant change is not re-probed immediately.

latch_decay_tau_s fbla[27] 1 s

How slowly that latched ceiling is forgotten (seconds). Raise ↑ for more caution after events; lower to let a healed plant recover sooner. (Was 200 s in an earlier draft; the current tracking law uses 1 s.)

Bounds & cadence

a_min fbla[2] 0.08

Authority floor. The most detuned the loop can get.

a_max fbla[3] 1.00

Authority ceiling — also the value held whenever b ≥ target and nothing is latched.

a_init fbla[4] 1.00

Startup authority and the shadow-mode pin. Recommended 1.0: the law defends the margin, so starting detuned is not needed.

dt_update fbla[5] = step_s (0.125 s)

Seconds between law calls (the OSI step cadence). Every “/s” rate and “_s” time above is converted to update counts with this.

10 · Master table — categorized tunable parameters

The knobs that control OSI behavior, grouped by the branch they belong to. Derived / structural constants (sizes, k_eff, gamma_gate, indices) are omitted — they are computed, not chosen. Columns: the exact code name, where it lands in the runtime arrays, its default, and which way to turn it.

Slow ST Residual Fast / quick-dip Regime / calibration Authority law

Category A  Slow ST branch — the accurate margin level

ParameterArray idxDefaultEffect — turn up (↑)
window_sfbls→n_segment5.0 sSmoother, laggier margin; more averaging.
hop_sfbls[52]0.25 sSlower slow-refresh; coarser cadence for all “per hop” counters.
segment_sfbls→segment_n1.0 sFiner frequency resolution (do not drop below 1 s).
margin_filter_nfbls[14]3Smoother selected OSI, adds lag.
freq_medfilt_nfbls[13]3 (odd)Fewer single-bin dips counted; smoother across frequency.
slow_filt_alphafbls[15]0.2(↓) steadier fast-path reference, slower to follow level change.
gamma_alphafbls→gamma_gate[8]0.01(↓) stricter coherence gate, fewer bins, more “no evidence”.
gamma_quietfbls[9]0.15More bins allowed into “quiet” set for the residual branch.
input_power_range_dbfbls[10]35 dB(↓) stricter; margin on fewer, stronger bins.
sidelobe_dbfbls[11]25 dBStricter leakage rejection.
min_binsfbls[12]5Needs more excited bins before reporting a margin.
thresholdfbls[17]=target 0.55Higher detection/fast-trip level (more protective).
warm_updatesfbls[35]4Longer warm-up before any margin is published.
residual_floorfbls[18]0.03Higher floor on 1−g2 in the residual.

Category B  Residual branch — quiet-band growth watcher

ParameterArray idxDefaultEffect — turn up (↑)
residual_band_hzfblbins(res_keep)[28 100] HzWider hazard band watched (risk of harmonic-distortion false alarms if widened down).
z_onfbls[25]4.0Rarer engagement (fewer false alarms, later detection).
z_offfbls[26]2.0Narrower hysteresis (disengages sooner).
res_on_nfbls[27]4More sustained evidence to engage; smoother, slower.
res_hold_sfbls[28]5 sUnconfirmed engagement persists longer before expiring.
res_min_growth_dbfbls[29]3 dBIgnores larger quiet-band changes (higher absolute defend level).
res_match_hzfbls[30]3 HzLooser same-frequency persistence tolerance.
sigma0_floorfbls[31]0.15Globally desensitizes the residual z-score.

Category C  Fast path / “quick dip” guards

ParameterArray idxDefaultEffect — turn up (↑)
fast_segment_sfbls→fast_segment_n[36]0.25 sCoarser fast bins; slightly slower reaction.
fast_ring_nfbls[37]3Longer fast memory (~more smoothing, more lag).
fast_min_binsfbls[38]3Needs more excited fast bins to compute a statistic.
fast_st_nufbls[39]1.25Calmer FRF-change CUSUM (ignores more per step).
fast_st_hfbls[40]4.5Later FRF-change trip (~+1 step/unit); fewer false trips.
fast_babs_offsetfbls[43]0.10Allows fast-ST trips further above target (more protective).
fast_amove_fracfbls[56]0.02Tolerates larger authority moves before disarming the FRF-change stat.
fast_d_sig_floorfbls[48]0.30Desensitizes the fast-ST z-score.
fast_burst_nufbls[41]1.0Calmer burst CUSUM.
fast_burst_hfbls[42]6.0Later burst trip; fewer false trips.
fast_burst_bandsfblfbins(band_id)5 bandsMore/other guarded sub-bands (cost & sensitivity).
fast_sig_floorfbls[47]0.20Desensitizes all burst bands.
fast_pin_lo / _hifbls[44]/[45]0.25 / 4.0Widen the accepted input-power window (fewer artifacts rejected).
fast_pin_alphafbls[46]0.04Faster input-power reference tracking.

Category D  Regime & calibration

ParameterArray idxDefaultEffect — turn up (↑)
regime_hopsfbls[34]8More tolerant of wandering excitation; slower rebaseline.
cal_skip_sfbls[19]10 sLonger startup blackout before calibrating.
cal_windowsfbls[20]80Longer, more robust baseline; slower first-ready.
cal_min_windowsfbls[24]24Requires more windows on the timeout path.
cal_timeout_hopsfbls[23]600Waits longer for a full calibration.
cal_reject_factorfbls[21]4More permissive window acceptance.
cal_restart_rejectsfbls[22]12Slower to abandon a bad reference.
bl_adapt_tau_sfbls→bl_alpha[32]100 sSlower healthy-baseline drift tracking.
bl_adapt_max_dbfbls[33]3 dBLarger drift cap (danger: can absorb real degradation).

Category E  Authority law (fable_auth → fbla)

Sub-grouped by role. This is the branch that turns the margin into the published gain auth.

RoleParameterfbla idxDefaultEffect — turn up (↑)
Setpoint / smoothingtarget[1]0.55More conservative (sheds earlier). Must stay below healthy margin.
b_filt_tau_s[6]0.4 sSmoother, more constant authority.
Drop / sheddown_deadband[7]0.01Ignores tinier target grazes (less flicker).
down_confirm_n[8]2Fewer false sheds; more reaction delay.
down_power[9]1.5Deeper shed per update.
down_rate[10]2.0 /sSheds faster (main “catch drops” knob).
down_settle_s[28]1.25 sGentler, staircase sheds (anti-compounding).
re_shed_delta[29]0.02Less reactive to continued decline (↓ for more reactive).
sev_frac[11]0.60Severe path triggers at a higher margin (more emergencies).
Severesev_down_rate[12]8.0 /sFaster emergency shed.
Recoveryup_deadband[13]0.02More cautious recovery; kills target-hugging oscillation.
up_hold_s[14]1.5 sLater recovery; more constant authority.
up_rate[15]0.08 /sFaster model-verified recovery.
up_rate_blind[16]0.02 /sFaster blind (probe) recovery (keep < up_rate).
up_prop[17]3.0Sprints back harder when margin is comfortably high.
Anti-flickermin_step[18]0.02Steppier, more constant authority (fewer, larger moves).
Predictionuse_pred[19]1On = floor sheds / cap recovery with the model (with pred_enable).
pred_guard[20]0.03Larger safety standoff on the predicted-safe boundary.
pred_floor_frac[21]0.90Shed stops closer to predicted-safe (less overshoot).
Fast-trip responsetrip_drop[22]0.60Milder instant drop on a trip (↓ for deeper).
trip_power[23]1.5Deeper fast-ST drop for a given b_fast.
trip_cool_s[24]5.0 sLonger post-trip recovery lockout.
trip_undo_s[25]2.5 sWider window to undo a trip on a regime recal.
self_move_gate_s / _frac[30]/[31]1.5 s / 0.02Requires authority steadier/longer before honoring a fast-ST trip.
Post-event latchlatch_relax[26]1.15Higher recovery ceiling right after an event (less caution).
latch_decay_tau_s[27]1 sSlower forgetting of the latched ceiling (more caution).
Bounds / cadencea_min[2]0.08Higher authority floor (less detuning allowed).
a_max[3]1.00Higher ceiling (rarely changed).
a_init[4]1.00Higher startup / shadow-pin authority.
dt_update[5]0.125 sSlower law cadence (tied to step_s).

How to change these in practice. You do not edit fbls/fbla by hand. You pass an override struct through the hs config that prepare_fable_runtime reads: hs.fable_osi_override for Categories A–D (fields = the fable_osi config names above) and hs.fable_auth_override for Category E (fields = the fable_auth param names). Top-level shortcuts hs.target_outer_ncf, hs.osi_gain_min, hs.osi_gain_initial and hs.fable_pred_enable set target/threshold, a_min, a_init and pred_enable directly. After any change, re-run OSI_tests/fable/test_fable_runtime_equivalence.m to confirm the runtime still matches the desktop model.

Generated from a read of the runtime source on the current branch. Notation matches the code exactly; defaults are the validated RTHS-column values from makeConfig / makeParams.