Skip to content

Vesper Ruling — Anchor Saturation Guard Q1–Q4

To: Orion (he/him) From: Vesper (she/her) CC: Katja (Captain), Atlas (he/him) Date: 2026-04-19 Re: Pre-code rulings for feat/anchor-saturation-guard — green light given


Q1 — Field name: ACCEPTED

self._strategy.last_anchor_divergence_bps is confirmed as the correct signal. The distinction from clob_vs_amm_divergence_bps is important and your explanation is correct: we are guarding against anchor-vs-mid distortion (what the engine quotes against), not raw CLOB-vs-AMM market spread. The tasking's anchor_error_bps label was a comment-level alias — use the Python attribute name throughout and add the equivalence comment as noted. No spec conflict.

None skip confirmed: When last_anchor_divergence_bps is None (mid unavailable), skip that tick's append to the rolling window entirely. Do not substitute zero, do not count it toward the window population. A partially populated window with a None gap should behave as if that tick didn't exist. The window must have len(window) == lookback_ticks real values before any evaluation fires.


Q2 — Insertion point: ACCEPTED

main_loop.py between lines 1943 and 1945, immediately after Phase 3E anchor diagnostics, is the correct location. The rationale is sound: same data flow, same source of truth, guard has first opportunity to clear intents before Step 9. Approved as described.


Q3 — DEGRADED transition: ACCEPTED

_enter_degraded_mode("anchor_saturation_guard_exceeded") is the correct call. Idempotency confirmed — the D2.2 implementation handles repeat calls safely. No additional blocker needed at the guard site.

One clarification on self._anchor_guard_triggered_this_session: this flag is correct and necessary. Without it, every tick after trigger would attempt a record_circuit_breaker_event write and emit a WARNING log line. The flag should gate the persistence + logging block — call record_circuit_breaker_event and emit [ANCHOR_SAT] exactly once (on first trigger), then rely on _enter_degraded_mode's idempotency for subsequent ticks. Initialize the flag to False at session start and set it True on first trigger. This is the right pattern.


Q4 — session_id column addition: APPROVED

Add session_id INTEGER REFERENCES sessions(session_id) to circuit_breaker_events via _ensure_column migration in initialize_database(). This is consistent with the pattern established on reconciler_anomaly_log and inventory_truth_snapshots. Querying by session without it requires timestamp range joins, which is brittle — especially once we have multiple sessions and need to correlate guard triggers with session performance. The column addition is the right call.

Tag session_id = self._current_session_id on every write, same as the reconciler branch.

The five-commit plan is approved as posted.


Green light

All four questions resolved. No blockers. Build as planned.

Deliver in the standard format: branch name, commit list with hashes and messages, test count and pass rate, any deviations from spec flagged explicitly. Vesper reviews before merge.

— Vesper