Vesper Delivery — fix/flag-051-regime-drift¶
What This Fixes¶
S53 entered ANCHOR_IDLE at tick ~5 and never exited. Root cause: the EMA baseline persisted from prior sessions (S49/S50/S52) where structural was +10 bps cap-locked. S53 opened with structural at −5 bps. Residual = −5 − (+10) = −15 bps, which exceeds the 7.0 bps ANCHOR_IDLE entry threshold. The engine correctly fired ANCHOR_IDLE, but had no way to exit because the residual stayed large until the 150-tick EMA caught up — which would take ~10+ minutes in a 30-minute session, and during warmup (first 50 ticks) it was using the legacy window where abs(−5.08) > 4.0 bps exit threshold anyway.
The time-based staleness check (24h) didn't help because S52 ended within minutes of S53 starting.
The Fix¶
One new field in AnchorDualSignalConfig: baseline_regime_drift_threshold_bps (default 10.0 bps).
One new flag in AnchorDualSignalCalculator: _pending_regime_drift_check, set on seed_baseline(), cleared and evaluated on the first call to observe() after a persistence restore.
Logic: On the first structural observation after loading a persisted baseline, if abs(structural − persisted_baseline) > threshold, the baseline is discarded and warm-up restarts from the current structural value. Normal cross-session resume if drift is within threshold.
At 10.0 bps threshold: - S52→S53 scenario (structural −5, persisted baseline ~+10, drift ~15): triggers cold start ✓ - Normal inter-session jitter (structural +4, persisted +2, drift ~2): baseline preserved ✓ - Legitimate regime shift of 10+ bps: cold start (correct — EMA would be wrong) ✓
Effect in S54 (Next Session)¶
Session starts. Persisted EMA from prior sessions ~+8–10 bps. First structural at −5 bps (drift ~13–15 bps > 10.0 threshold).
[ANCHOR_DS] FLAG-051 — regime drift on first post-seed tick; discarding persisted baseline and cold-starting warm-up
Calculator cold-starts at −5 bps. After 50 ticks (~3 min): - EMA baseline ≈ −5 bps (tracking structural) - Residual ≈ 0 bps - Legacy window also shows −5 bps → abs(−5) < 7.0 → anchor entry guard does NOT fire - Engine stays in MODE_OK and quotes normally
If structural is −5 bps, the engine quotes. If structural spikes to −9 bps (abs > 7.0 + 40% prevalence > 5 bps), the anchor guard fires correctly. This is correct behavior.
Files Changed¶
| File | Change |
|---|---|
neo_engine/config.py |
Add baseline_regime_drift_threshold_bps: float = 10.0 to AnchorDualSignalConfig, parse in load_config, validate in _validate_anchor_dual_signal |
neo_engine/dual_signal_calculator.py |
Add _pending_regime_drift_check flag to __init__ and seed_baseline; add drift check to top of observe(); clear flag in reset() |
config/config_live_stage1.yaml |
Add baseline_regime_drift_threshold_bps: 10.0 to anchor_dual_signal block |
tests/test_flag_051_regime_drift.py |
11 new tests (all passing) |
Test Coverage (11 tests, all passing)¶
| Test | Confirms |
|---|---|
test_large_drift_discards_persisted_baseline |
15 bps drift > 10 threshold → cold start |
test_cold_start_after_drift_warms_up_correctly |
Post-cold-start warm-up is normal |
test_drift_check_clears_pending_flag |
Check fires exactly once |
test_no_cold_start_if_no_seed |
No seed = no check (cold start from scratch unaffected) |
test_small_drift_preserves_baseline |
2 bps drift < 10 → baseline preserved |
test_drift_exactly_at_threshold_does_not_trigger |
Strictly-greater-than boundary |
test_drift_one_bps_above_threshold_triggers |
Boundary epsilon |
test_none_threshold_preserves_baseline_regardless_of_drift |
None disables check |
test_reset_after_seed_clears_drift_check |
reset() clears pending flag |
test_zero_threshold_raises_config_error |
Config validation |
test_none_threshold_passes_validation |
Config validation |
S53 scenario regression (T11): Seed at +10 bps (500 samples), first observe at −5 bps → cold start → 3 ticks → warm, residual = 0.0000 bps. ✓
Apply Instructions (PowerShell)¶
Important: the working tree in the Linux sandbox has SMB corruption. Run git status first on your machine to confirm the working tree is clean.
cd "C:\Users\Katja\Documents\NEO GitHub\neo-2026"
# Confirm working tree is clean
git status
# Create branch
git checkout main
git pull
git branch -D fix/flag-051-regime-drift 2>$null
git checkout -b fix/flag-051-regime-drift
# Copy the 3 source files from workspace into repo
Copy-Item "C:\Users\Katja\Documents\Claude Homebase Neo\02 Projects\NEO Trading Engine\03 Branches\fix-flag-051-regime-drift\files\config.py" neo_engine\config.py
Copy-Item "C:\Users\Katja\Documents\Claude Homebase Neo\02 Projects\NEO Trading Engine\03 Branches\fix-flag-051-regime-drift\files\dual_signal_calculator.py" neo_engine\dual_signal_calculator.py
Copy-Item "C:\Users\Katja\Documents\Claude Homebase Neo\02 Projects\NEO Trading Engine\03 Branches\fix-flag-051-regime-drift\files\config_live_stage1.yaml" config\config_live_stage1.yaml
Copy-Item "C:\Users\Katja\Documents\Claude Homebase Neo\02 Projects\NEO Trading Engine\03 Branches\fix-flag-051-regime-drift\files\test_flag_051_regime_drift.py" tests\test_flag_051_regime_drift.py
# Verify, run tests, then commit
git diff --stat
pytest tests/test_flag_051_regime_drift.py -v
Expected: 11 passed.
Then commit:
git add neo_engine/config.py neo_engine/dual_signal_calculator.py config/config_live_stage1.yaml tests/test_flag_051_regime_drift.py
git commit -m "fix(calc,config): FLAG-051 — regime-drift cold-start check for persisted EMA baseline
On the first structural observation after a cross-session EMA restore,
if abs(structural - persisted_baseline) > baseline_regime_drift_threshold_bps
(default 10.0 bps), the persisted baseline is discarded and warm-up
restarts from the current structural value.
Fixes S53 lockout: EMA persisted from +10 bps cap-locked sessions
produced residual of -15 bps on session open with structural at -5 bps,
triggering ANCHOR_IDLE immediately with no viable exit path.
After this fix: S54 opens, drift check fires, cold start from -5 bps,
50-tick warmup completes, residual near 0 bps, engine quotes normally."
git log --oneline main..HEAD
git push origin fix/flag-051-regime-drift
Then merge:
git checkout main
git merge --ff-only fix/flag-051-regime-drift
git push origin main
git branch -d fix/flag-051-regime-drift
Post-Merge: Run Adjacent Suite¶
pytest tests/test_flag_051_regime_drift.py tests/test_anchor_dual_signal.py tests/test_anchor_idle_state.py tests/test_anchor_saturation_guard.py -v
— Vesper 2026-04-22