Skip to content

Branch Status — feat/anchor-dual-signal-calibration


C1 — Schema + Config ✅ COMPLETE

Verified (Vesper): All spec items landed. No issues.

  • state_manager.py — three new REAL columns (structural_basis_bps, rolling_basis_baseline_bps, residual_distortion_bps) on system_metrics CREATE TABLE; three matching _ensure_column ALTER calls for legacy DBs; record_system_metric extended with three Optional[float] = None kwargs; INSERT updated.
  • config.pyAnchorDualSignalConfig frozen dataclass with Atlas Option 3 ruling reference in docstring; registered on Config; YAML parse block added; _validate_anchor_dual_signal with five invariants (includes warmup_ticks <= basis_ema_window_ticks); wired into load_config.
  • config_live_stage1.yaml, config.example.yaml, config.yamlanchor_dual_signal: block added with correct defaults: enabled: true, basis_ema_window_ticks: 150, warmup_ticks: 50, residual_hysteresis_lookback_ticks: 20, baseline_staleness_hours: 24.0.
  • Backward compat confirmed: legacy-shape record_system_metric call leaves new columns NULL.
  • Backup DB ALTER migration path confirmed.
  • 99 tests passed (test_config.py + test_state_manager.py).

Branch not yet cut (per standing rule #1 — correct).


C2 — Signal Computation ✅ COMPLETE

Verified (Vesper): All spec items landed. Zero new failures.

  • dual_signal_calculator.py — new module. DualSignalObservation frozen dataclass + AnchorDualSignalCalculator. observe() gates baseline/residual to None during warm-up (EMA advances internally — warm-ready at tick 51). seed_baseline() / reset() stubs in place for C4.
  • strategy_engine.py — three new attrs (last_structural_basis_bps, last_rolling_basis_baseline_bps, last_residual_distortion_bps). Atlas-literal formula ((mid - amm) / mid) * 10000.0 — NOT reusing raw_divergence_bps. Sign invariant confirmed: structural_basis_bps and last_anchor_divergence_bps carry opposite signs.
  • main_loop.py — four touch points: import, instantiate, observe, persist. _persist_tick_telemetry uses same snapshot.is_valid() gate as legacy anchor_err_bps.
  • test_anchor_error_telemetry.py — helper fixed (MagicMock → None for new attrs).
  • 212 FLAG-048-adjacent tests green. Zero new failures on regression (325/639 pre-existing split unchanged).
  • Legacy anchor saturation guard untouched — reads last_anchor_divergence_bps / capped window unchanged until C3.

C3 — Guard Rewire ✅ COMPLETE

Verified (Vesper): All spec items landed. Rename confirmed. Zero stale references.

  • _select_anchor_guard_window() — returns (residual_window, "residual_distortion_bps") when dual-signal enabled AND warm; falls back to (anchor_error_window, "last_anchor_divergence_bps") otherwise.
  • Both entry and exit evaluators read through the same selector — hysteresis coherence preserved.
  • Source label threaded into WARNING logs and circuit_breaker context dict for forensic visibility.
  • _anchor_residual_window fed from dual_obs.residual_distortion_bps when warm. NULL-during-warmup honored — no partial-window saturation risk.
  • Rename: _evaluate_anchor_saturation_guard_evaluate_anchor_residual_guard. main_loop.py (5 replacements), test_anchor_idle_state.py (4 replacements), test_anchor_saturation_guard.py (13 replacements). grep -rn "_evaluate_anchor_saturation_guard" returns zero hits.
  • _evaluate_anchor_idle_exit intentionally NOT renamed — FLAG-046 scope, different semantic layer.
  • anchor_saturation_guard YAML key intentionally NOT renamed — backward-compat surface, separate deliberate decision if ever revisited.
  • Test fixtures: _select_anchor_guard_window stubbed on MagicMock engines in three suites to exercise legacy capped-window path. Residual-window coverage reserved for C5.
  • 120/120 FLAG-048 adjacent tests green. Full regression 691 passed / 378 failed — baseline-identical. Pre-existing failures unrelated to FLAG-048.

C4 — Cross-Session Persistence ✅ COMPLETE

Verified (Vesper): All spec items landed. Branch coverage correct. Standing note answered.

  • dump_state() — returns (baseline, effective_sample_count) or None if pre-seed. Does NOT gate on is_warm — correct. Pre-warm EMA is a legitimate partial sample worth preserving across sessions.
  • Three engine_state key constants: KEY_ANCHOR_DS_BASIS_BASELINE_BPS, KEY_ANCHOR_DS_BASIS_BASELINE_COUNT, KEY_ANCHOR_DS_BASIS_BASELINE_CLOSED_AT. Namespace anchor_dual_signal.*.
  • _restore_anchor_dual_signal_baseline() — 7 behavioral branches: disabled→noop, missing→cold-start silent, DB read exception→cold-start log, malformed float→cold-start+clear, malformed ISO→cold-start+clear, stale (>24h)→cold-start+clear+WARN with forensic detail, seed rejects count<1→cold-start+clear+ERROR, success→seed+INFO with is_warm_on_resume. All correct.
  • _persist_anchor_dual_signal_baseline() — 3 branches: disabled→noop, no observation→noop (preserves prior persisted state — critical: engine that halts pre-tick-1 must not cost next run its warm-up), normal→3-key atomic write. No-observation path is the right call.
  • _clear_anchor_dual_signal_persistence() helper — best-effort triple clear, exceptions swallowed.
  • Wired into _startup() and _shutdown() correctly.
  • Standing Vesper note answered: fix/startup-mode-reset confirmed does NOT touch anchor_dual_signal.* keys (commits 401d006 + 502be63 touch halt.*, inventory_truth.*, KEY_ANCHOR_IDLE_*, FLAG-044 cooldown only). Documented inline in reset block.
  • 188/188 FLAG-048 adjacent tests green. Full regression 691/378 — baseline-identical.
  • 9 behavioral branches verified end-to-end via direct unit exercise.

VPS note (flag for setup checklist): KEY_ANCHOR_DS_BASIS_BASELINE_CLOSED_AT is an ISO timestamp — staleness check is timezone-sensitive. Atlas's hardening baseline requires NTP + correct timezone on VPS before engine runs. Confirm this is in the setup runbook.


C5 — 12 Tests ✅ COMPLETE

Verified (Vesper): All spec items landed. 17 tests, 12 plan items, 0 new failures. Branch accepted.

  • tests/test_flag_048_dual_signal.py — 874 lines, 17 tests, 5 classes.
  • T1: Structural basis uncapped ✅ | T2: Sign convention (±basis) ✅ | T3: EMA convergence (stable + stepped) ✅
  • T4: Rail-lock proof ✅ (non-negotiable per Atlas) | T5: Residual entry fires (fire + below-threshold) ✅ | T6: Exit reachability proof ✅ (non-negotiable per Atlas)
  • T7: Hysteresis preserved ✅ | T8/T9/T10: Cross-session persistence DB round-trips via real StateManager(":memory:") ✅ — T10 additionally asserts three persistence keys cleared after stale discard
  • T11: Warm-up suppression (calculator None + selector fallback) ✅ | T12: Dashboard no hidden substitution (3-column distinctness + NULL-not-zero) ✅
  • 150-tick benchmark row: N=150, alpha=0.0132, baseline@t150=13.46, residual_stdev=1.14 bps. 86% convergence in one window width — correct default. ✅
  • Full regression: 708 passed (+17 vs C4 baseline), 378 pre-existing failures unchanged. Zero new failures. ✅
  • NTP/UTC VPS prerequisite documented by Orion, traceable to Vesper's C4 note. ✅

⚠️ Pre-live gate open item: T4 rail-lock proof is synthetic at session-52 shape — live DB was not accessible from sandbox. Atlas's pre-code ruling requires replay on S48/S49/S50 showing exit condition reachable in afternoon ET. This is NOT a branch acceptance blocker but IS required before session hold lifts and S51 runs. Orion to complete once live DB is accessible (VPS migration or direct copy to working tree).


Pre-Live Replay — ✅ COMPLETE — SESSION HOLD LIFTED

Vesper ruling (2026-04-22): Option A — replay accepted as sufficient. Session hold lifted.

  • Replay executed against neo_live_stage1.db.bak.20260421T165223Z (integrity_check=ok) via real StateManager(":memory:") round-trips. No mocks. Read-only (mode=ro&immutable=1).
  • Sessions 50/51/52 (S47/S48/S49) replayed in order. Session 53 (S50) unrecoverable — live DB malformed (Atlas's exact SMB/WAL failure mode confirmed).
  • Exit reachability (Q4) ✅ PASS: Session 51 tick 171 — structural +10→+4.58, residual = +0.08 bps. Sub-threshold, single-tick reaction.
  • Rail-lock (Q5) ✅ DIRECTIONAL PASS: Session 52 (38 ticks @ +10) — residual 5.42→3.31 monotone toward 0. Right sign, right slope. Full convergence unambiguous from 150-tick window math.
  • Cross-session persistence ✅ PASS: dump→write→read→seed round-trip verified end-to-end at both session boundaries.
  • Warm-up gating ✅ PASS: Session 50 (32 ticks, never warm) emits None throughout. Session 51 seeded at 32, crossed warm at tick 18.
  • Uncapped structural not exercised (data gap, not calculator gap) — queued for post-merge replay after first clean session.
  • FLAG-049 urgency confirmed: backup cadence was the only reason this replay was possible.

Replay report: [C] Orion Pre-Live Replay Report — FLAG-048.md

Branch Disposition — ✅ MERGED — SESSION HOLD LIFTED

All five checkpoints (C1–C5) verified by Vesper. Branch merged to main (commit a8033e5). Pre-live replay complete. Katja cleared to run next session.


— Vesper (COO) 2026-04-22