FABLE-native diagnosis · GDB replay + ten-case audit

The FABLE target does not need to be reachable for diagnostic recovery

The delay is not caused by PID or phase lead. It comes from the FABLE authority law waiting for slow, gated b_osi evidence to satisfy an impossible upward threshold after the game returns to nominal.

Direct answer: no. A known diagnostic gain return must be able to restore committed authority a even when target_outer_ncf is above the attainable FABLE margin. Keep b_st, b_res, b_fast, and measured b_osi unchanged; add a narrowly armed restore_pending path to the authority supervisor.
Exact gain restore75.469238 s
Saved committed a0.20 → never
Measured b_osi reaches cap77.776855 s
Candidate a = 176.276855 s
Correction to the first report: 1/√2 is the configured software cap of the selected FABLE margin, not the mathematical maximum of the underlying chordal expression. Also, the exact gain-return time is 75.469238 s, so the measured slow-margin delay is 2.307617 s—not 2.78 s.

Exact reason in FABLE terminology

b_st is stale, then unavailable

After the gain returns 2→1, the coherent/excited-bin branch b_st still contains the damaged slow window. Through 77.277 s it is approximately 0.272 while b_res = 0.707107, so b_slow = min(b_st,b_res) remains low. The three-slow-hop median b_osi therefore cannot change immediately.

The evidence gate then blocks valid_up

At 77.776855 s, b_st = NaN and b_res = 0.707107, allowing b_osi to reach the configured cap. From 78.401855 s, the evidence gate makes b_osi = NaN and valid_up = false while not g_armed. The saved no-evidence branch holds a rather than recovering it.

saved downward test: min(b_osi,b_filt) < 0.80 − 0.01
saved upward test: b_filt ≥ 0.80 + 0.10 = 0.90
FABLE cap: cfg.cap = 1/√2 = 0.707107
Two independent blockers: the upward threshold 0.90 is above cfg.cap, and healthy evidence disappears before b_filt/above_n can complete. The only fast event in this record is trip_reason = 1 at 64.402 s; b_fast is not used by the ordinary upward path. regime_recal is also not a plant-repair signal—it only handles changed input support and can undo a recent fast trip inside trip_undo_s.

What each FABLE branch must continue to do

SignalExisting FABLE rolePolicy in the fix
b_stST margin on coherent/excited bins; valid only when st_valid.Unchanged. Preserve its calibration, rings, and measurement-only recovery role.
b_resResidual/quiet-bin margin: cap while disengaged, residual-growth margin while res_on.Unchanged. It remains essential where coherent-bin evidence is weak.
b_slowmin(b_st,b_res), including the existing all-NaN handling.Unchanged.
b_osiMedian of slow_hist across three distinct slow updates, capped by cfg.cap.Never synthesize a healthy value. Show NaN / WARMING while evidence refreshes.
b_fastShort-memory ST margin; selected into b_osi only for trip_reason = 2.Keep the fast CUSUM/trip path alive. After a diagnostic return, use publications only as permissive “no fast fault” checks.
a_cont, aContinuous and committed authority governed by trip, cooldown, evidence, filtering, deadband, and commit states.Only this supervisor receives the additive diagnostic-return state.

Exact record timeline and winning replay

gainb_osi rawsaved authreplay auth40 s60 s80 s100 s120 s 75.469: known gain 2 → 177.777: raw b_osi reaches cap78.402: raw b_osi → NaN76.277: 3 checks + ramp reaches 1
logged diagnostic gainraw measured b_osisaved authority0.5 s supervised replay

The diagnostic gain is result.Results signal 21: 1 → 1.5 at 50.224121 s, 1.5 → 2 at 56.520508 s, then 2 → 1 at 75.469238 s.

Offline replay comparison

The replay reads the actual v7.3 MAT streams and changes only recovery logic. It is a fixed-record counterfactual, not a closed-loop plant simulation. Full metrics are in offline_replay_subagent_metrics.json.

CandidateAuthority ≥ 0.90 after restoreFull authorityFalse pre-restore triggersVerdict
Saved target-tracking lawNeverNever; final 0.200Deadlocked
Target clamp onlyDoes not complete before gate blanksNever in saved no-evidence branch0Insufficient
Cap-relative measured recovery, b ≥ 0.6871Would start before actual repairUnsafe2 windows: 64.400–64.776 and 70.777–72.526 sReject
Aggressive NaN/blind recovery3.933 s3.933 s1: no-evidence interval 65.527–69.526 s while gain is abnormalReject
Production blind fallback, 5 s + 0.06/s19.683 s21.308 s0 in this replaySafe fallback, too slow
Supervised 1.0 s ramp0.875 s1.000 s0Acceptable
Gain edge + 3 clean fast checks + 0.5 s ramp0.807617 s0.807617 s0Recommended
Supervised 0.5 s ramp without confirmation0.500 s0.500 s0Fastest bumpless option
Immediate supervised step0.125 s0.125 s0Reject: 5× authority jump
Why the winner is defensible: the gain-return edge is external ground truth supplied by the diagnostic test. It arms three clean fast publications at 75.526855, 75.651855 and 75.776855 s; only then does the 0.5 s ramp begin. Emergency trips remain higher priority.

Only changes needed

Gain return 2→1
When diagnostic mode is enabled, arm restore_pending. This is not regime_recal.
→
3 clean b_fast publications
No trip_reason; then begin a bounded ramp of a_cont/a.
→
a = 1
Existing trip and downward authority paths remain higher priority.
Keep the requested target, add a feasible decision reference.
target_outer_ncf = 0.8 remains the requested/reported target. For authority decisions use b_ref = min(target_outer_ncf, cfg.cap - up_deadband - 0.02). With current up_deadband = 0.04, b_ref = 0.647107. This prevents an immediate re-shed after supervised restoration. The saved record used up_deadband = 0.10; that is why its upward test was 0.90.
Detect the configured nominal return.
Add diagnostic_restore_enable, diagnostic_gain and diagnostic_gain_nominal. Do not hardcode 1; the saved run used 1, while other model configurations may use another nominal value.
Confirm three clean fast publications.
After—and only after—the known gain-return edge, require three consecutive fast updates with no trip. Treat b_fast as a permissive no-fast-fault check, not proof of healing: the replay found 12 pre-edge intervals that would satisfy the same fast-only condition.
Do not reset the measurement branches.
Preserve b_st/b_res calibration, baselines, spectral rings, and the b_fast CUSUM. Clear only stale selected aggregation and authority transient memory needed for a clean commit—such as slow_hist, b_filt, below_n, above_n, cooldown/latch counters, and the old shed target. Keep raw b_osi = NaN/WARMING until fresh evidence exists.
Ramp authority bumplessly.
At the 0.125 s update cadence, use a = min(a_init, a + 1.6·0.125). Starting from 0.2 gives four updates: 0.2 → 0.4 → 0.6 → 0.8 → 1.0. Confirmation plus ramp takes 0.807617 s in this record.
trip_reason always wins.
A quiet-band burst (trip_reason = 1), fast FRF collapse (trip_reason = 2), or newly valid degradation cancels restore_pending within one update and executes the existing downward path.
Default the feature off.
When diagnostic_restore_enable = 0, the new branch is unreachable. Existing synthetic and physical-test behavior is therefore unchanged by construction.
if trip_reason ~= 0 || fresh_degradation
    restore_pending = false;
    run_existing_drop_path();
elseif diagnostic_restore_enable && gain_returned_to_nominal
    restore_pending = true;
    clean_fast_count = 0;
elseif restore_pending && clean_fast_count < 3 && b_fast_published
    clean_fast_count = clean_fast_count + 1;
elseif restore_pending && clean_fast_count >= 3
    clear_stale_aggregation_and_authority_memory();
    a_cont = min(a_init, a_cont + 1.6*dt_update);
    a = commit_existing_way(a_cont);
    restore_pending = a < a_init;
end

Why the diagnostic edge is additive, not a replacement

Autonomous cases still recover from measurements

Cases 7 and 8 have no diagnostic gain event. Their recovery must remain entirely b_st/prediction based; the new branch is unreachable and their traces remain unchanged.

A scalar cap is not proof of repair

b_osi reaches the cap in two pre-return windows, and the same three-clean-b_fast condition occurs 12 times before the gain edge. The known edge is what makes the confirmation safe in this diagnostic test.

Autonomous future extension: the fast path already computes newest-versus-slow FRF deviation and currently discards changes in the improving direction. Expose a symmetric heal_reason, confirm it for 2–3 steps, and abort on any existing trip. That design needs a new closed-loop replay because the required directional statistic was not logged in GDBqFpKb.

Old implementation versus candidate: ten FABLE cases

The archived suite_runtime_sliced.mat baseline was replayed with an isolated wrapper. Because none of the ten cases contains the diagnostic gain-return event, restore_pending activates zero times. Authority, b_osi, and trip outputs are therefore sample-for-sample identical. Full machine-readable results: diagnostic_restore_validation.json.

#Canonical caseFABLE behavior being exercisedOldCandidate difference
1healthy broadbandb_st selected; b_res at cap; no fast tripPass0; pass
2intensity stepb_st normalization; residual branch disengagedPass0; pass
3broadband damageb_fast type-2 trip, then b_st/st_bindingPass0; pass
4low-band damageIntended b_res defense; archived run actually uses one type-2 fast tripPre-existing fail0; same fail
5silentEvidence gate: b_osi = NaN, authority holdPass0; pass
6gradual softeningSlow b_st tracking without false fast tripPass0; pass
7damage then repairType-2 shed followed by measurement-only b_st/prediction recoveryPre-existing fail: 0.625 s versus 0.5 s limit0; same fail
8starts damaged, improvesPure b_st/prediction recovery; no diagnostic eventPass0; pass
9healthy regime changeregime_recal/gate prevents stale residual or fast effectsPass0; pass
10transient pulseBounded fast trip, residual release, b_st recoveryPass0; pass
No-regression result: old = 8/10 and candidate = 8/10; maximum |Δa| = 0 in every case, authority total variation is identical, and b_osi/trip streams are identical. The two failures already exist in the archived implementation and were not created or hidden by this change.
The ten-case harness needs revision before final production acceptance. Its built-in adapters currently return only four outputs, leaving stored b_st, b_res, and b_fast traces as NaN. Add these branch traces plus decision and g_armed; add a residual-only case that truly forces res_on; and run both canonical and production-configured suites. The archive predates current HEAD, so a fresh MATLAB-MCP baseline/candidate run remains mandatory.

PID and phase-lead conclusion

The model does not retune PID or phase lead during authority adaptation. auth from Fable OSI + Auth multiplies the displacement command in Apply OSI gain before saturation/MTS. PID and pl_5k remain static.

Keep them unchanged for this fix

Changing P, I, D or phase lead cannot change the state-machine conditions that hold on NaN or require b_filt ≥ target + deadband. It would change tracking and estimator excitation in every case.

Robust redesign remains separate

Existing studies show phase-lead changes are not monotonic across damage cases. The saved-lead/full-authority envelope includes very poor worst-case margins, while the robust candidate required authority attenuation and a significant tracking tradeoff. That is not a recovery-logic patch.

Implementation validation gates

GateRequired result
GDB fixed-record replayGain return to full authority in ≤0.81 s with three fast checks; zero activation before 75.469238 s; no re-shed for 10 s unless a real trip/degradation is injected.
Trip during restoreRamp cancels and downward action begins within one 0.125 s update.
Legacy ten-case replayVerified: zero diagnostic activations; a, total variation, b_osi, and trip outputs unchanged in all cases.
Fresh current-HEAD suitesStill required through MATLAB MCP: canonical plus production configuration, with explicit b_st/b_res/b_fast/decision/g_armed outputs.
Runtime equivalenceDesktop and real-time implementations retain maximum absolute difference 0.
Bumpless commandAdjacent dc change remains inside the configured command slew/saturation limit and does not create a new dm transient.
Raw indicator semanticsAfter restoration, display WARMING/known nominal restored; never fabricate a measured 0.7071 value.