Skip to content

[C] Vesper Prework — FLAG 053 Fix Package

This package contains four deliverables as directed by Atlas. Read this before touching code.


Part 1 — S40 Diagnostic Comparison Framework

Purpose: define what "alive" and "tradeable" mean before the run, so comparison is objective.

Metrics to capture from the S40 diagnostic run

Category Metric Source What we want to see
Participation Total fills DB fills table >0 confirms market is still tradeable
Participation Fill rate (fills/ticks) Computed Compare to S40 (84/316 = 26.6%)
Participation Tick count at halt Session log Minimum 100 ticks for meaningful comparison
Participation Halt reason Session log duration_elapsed = clean run; anything else = new problem
Market activity CLOB-AMM divergence range Tick log clob_vs_amm_divergence_bps Document range — baseline for structural regime
Market activity Spread (bps) Tick log Compare to S40 spread data
Anchoring Anchor error mean/median Tick log S40-era anchoring had no cap → unconstrained signal
Anchoring % ticks cap-locked Tick log S40 = 0% (no cap logic existed)
Guard behavior Any DEGRADED entries Session log Should be zero — no guards in this codebase
Guard behavior Any ANCHOR_IDLE entries Session log Should be zero — flag did not exist at this commit
Truth checks Delta at any truth check Reconciler log Should be near-zero with clean DB seed
Capital End-of-session RLUSD total Realignment dry-run Compare to start: 79.684 XRP + 83.463 RLUSD ≈ 196.9 RLUSD

Side-by-side comparison table (fill after run)

Metric S40 (2026-04-19) S40-diagnostic (2026-04-22) Delta / Assessment
Duration 316 ticks (~26 min) TBD
Total fills 84 TBD
Buy fills 53 TBD
Sell fills 31 TBD
Halt reason duration_elapsed TBD
VW spread (bps) +12.47 TBD
Toxic fills 0 TBD
Anchor mean (bps) Not recorded (pre-telemetry) TBD
Cap-locked ticks (%) N/A (no cap) TBD
DEGRADED entries N/A (no guards) TBD
Capital delta Approx flat TBD

What each outcome means

S40-diagnostic runs cleanly (duration_elapsed, fills, no errors): → Market is still supporting fills. Problem is entirely in the guard/signal architecture added post-S40. Main branch fix is the priority.

S40-diagnostic runs but zero fills: → Market conditions changed. Spread/liquidity regime analysis needed. Before attributing to code, check CLOB-AMM divergence during run.

S40-diagnostic halts unexpectedly (truth halt, etc.): → Unexpected — D2.2 bugs or environment issue. Investigate before comparing to current branch.


Part 2 — Sign Convention Normalization Proposal

Purpose: define the canonical sign convention before Orion implements standardization, so implementation has a clear target.

Current state — three metrics, three conventions

Metric Location Formula Sign when AMM > CLOB mid Example (S55)
clob_vs_amm_divergence_bps Tick log (clob_mid − amm) / amm × 10000 Negative −11 to −13 bps
last_anchor_divergence_bps Dashboard, main_loop (quote_anchor − mid) / mid × 10000, capped ±10 Positive +9.56 bps
structural_basis_bps EMA input, dual_signal_calculator (mid − amm) / mid × 10000 Negative −11 to −13 bps

All three are mathematically consistent descriptions of the same regime. They disagree in sign because their numerators are constructed differently.

Proposed canonical convention

Formula: (clob_mid − amm_mid) / amm_mid × 10000

Interpretation: positive = CLOB trades above AMM (engine should BUY XRP from AMM / SELL to CLOB). Negative = CLOB trades below AMM (engine should SELL XRP to AMM / BUY from CLOB).

Why this one: - Matches clob_vs_amm_divergence_bps (already in tick log, already what operators read natively) - Matches structural_basis_bps in sign direction (minimal downstream rewiring) - last_anchor_divergence_bps is the outlier — it is the residual-control signal, which can remain internal with its own sign if needed, but operator-facing representation must flip

Renaming recommendation

Old name New operator-facing name Sign change required?
clob_vs_amm_divergence_bps Keep — already canonical No
structural_basis_bps Keep — already canonical sign No
last_anchor_divergence_bps (dashboard label) Rename to anchor_divergence_bps Yes — flip sign or recompute from canonical formula
rolling_basis_baseline_bps Keep (internal EMA — same sign as structural) No
residual_distortion_bps Keep (control signal — internal) No change needed for internal use

Implementation scope for sign standardization

Minimal: Change the operator-facing dashboard display of last_anchor_divergence_bps to render with flipped sign and update the label. No internal wiring changes.

Full: Recompute last_anchor_divergence_bps from (clob_mid − amm) / amm directly, removing the cap-induced sign flip. This also helps the exit evaluator (see Part 3 below) since the legacy capped window would then match the canonical sign.

Atlas direction: Full standardization preferred ("pick a canonical interpretation, normalize the names and signs around it"). Orion should propose which approach and confirm with Atlas if full recompute is structurally safe.


Part 3 — FLAG-053 Design Note: Exit Evaluator Options

Purpose: give Orion a precise problem statement and design options, not just "fix the lockout."

Problem statement (exact)

The ANCHOR_IDLE exit evaluator (main_loop.py:2887-2997) calls _select_anchor_guard_window() (main_loop.py:2729-2766) to obtain a data window. The window selector returns:

  • Residual window — available after warmup_ticks (50) + residual_hysteresis_lookback_ticks (20) = 70 valid observations. Correct signal source in a FLAG-048 architecture.
  • Legacy capped window — fallback when residual window is not yet available. Fed from last_anchor_divergence_bps, which is capped at ±10 bps.

In a cap-saturated regime (S55: 82% of ticks at cap), the legacy window holds values uniformly near ±10 bps. The exit conditions are: - |mean(window)| < 4.0 bps → fails when mean ≈ 10 - pct(|x| > 5 bps) < 30% → fails when pct ≈ 100%

Both fail on every tick for the first 70 ticks. After tick 70, residual window takes over but requires 30 consecutive stability ticks to exit. Minimum 100 ticks to exit in a hostile regime.

Option A — Earlier residual-window eligibility (Atlas approved)

Mechanism: Reduce the warmup_ticks or residual_hysteresis_lookback_ticks requirement specifically for ANCHOR_IDLE exit evaluation. Production confidence in the EMA can remain at full 70 ticks; but a shorter "exit-eligible residual preview" window (e.g., 30 ticks) could be accepted for the exit test.

Tradeoff: Lower data maturity for exit test. Acceptable if exit is still double-gated by the stability tick counter (30 consecutive ticks of improvement still required).

Orion to propose: the exact new threshold and whether it's a separate config parameter or a shared reduction.

Option B — Benign-regime early-exit path on uncapped signal (Atlas approved)

Mechanism: If structural_basis_bps (the uncapped EMA input, available immediately) shows a clear improving regime during the pre-residual phase, allow the exit stability counter to accumulate against it instead of against the capped legacy window.

Trigger condition (proposed): abs(structural_basis_bps) < X bps where X is configurable (suggest 4.0 bps, matching the existing mean threshold).

Tradeoff: The EMA has not fully converged yet at early ticks. However, structural_basis_bps is not capped, so it can express improvement. False exits are possible if structural is noisy early, but the stability tick counter (30 ticks) provides a buffer.

Orion to propose: whether to use structural_basis_bps directly or a short rolling mean of it, and the stability tick count to use.

Option C — Both (Atlas ruling)

Implement A and B. A fixes the structural lockout. B provides a faster early path in genuinely improving regimes. They are additive.

What does NOT change

  • Entry into ANCHOR_IDLE — not touched
  • The 30-tick stability counter for exit — not touched (it's a safeguard, keep it)
  • The residual window itself at full maturity — not touched
  • Drift / corridor / truth escalation from ANCHOR_IDLE to DEGRADED — not touched

Part 4 — Validation Criteria for the FLAG-053 Fix

Purpose: define what counts as success before a line of code is written.

Functional correctness

Test 1 — Early exit in improving regime (pre-residual phase) Setup: session in cap-saturated regime for first 20 ticks, then CLOB-AMM divergence drops below 4 bps. Expect: engine exits ANCHOR_IDLE before tick 70.

Test 2 — Residual handover still works (>70 ticks) Setup: long session, regime genuinely improves after tick 70. Expect: exit via residual window (unchanged path). No regression.

Test 3 — No false exit in persistently hostile regime Setup: 100 ticks with CLOB-AMM divergence at −12 bps throughout, no improvement. Expect: engine stays in ANCHOR_IDLE for duration. 30-tick stability counter must not reset to "exitable" spuriously.

Test 4 — Sign convention round-trip Setup: known CLOB-AMM divergence. Expect: clob_vs_amm_divergence_bps, dashboard display of anchor divergence, and structural_basis_bps all report the same direction (all negative OR all positive for the same regime).

Operator legibility check (Vesper audits before merge)

  • In a hostile regime (AMM above CLOB), all three surfaced signals show the same sign
  • In a favorable regime (AMM below CLOB), all three surfaced signals show the same sign
  • Dashboard label(s) updated to match canonical convention
  • Tick log field names are either unchanged or renamed with backward-compatible note in changelog

Production evidence

After fix is merged and first qualifying session runs: - ANCHOR_IDLE entry tick recorded - ANCHOR_IDLE exit tick recorded (or confirmed it stayed, with reason) - Minimum ticks to exit in a flat-to-improving regime < 70 ticks (confirms lockout reduced) - No spurious exits in hostile regimes (stability counter held)

What still counts as "stuck" (failure criteria)

  • ANCHOR_IDLE entered, regime improves clearly, exit takes >70 ticks → fix did not work
  • ANCHOR_IDLE exited in <10 ticks in a clearly hostile regime → false exit, stability counter broken
  • Dashboard still shows opposite sign to tick log for the same regime → sign standardization incomplete

Summary for Orion

Blocking question for Orion before code: 1. For Option A: what specific threshold reduction do you propose, and does it need a new config parameter? 2. For Option B: structural_basis_bps or a short rolling mean of it? Threshold value? 3. For sign standardization: full recompute of last_anchor_divergence_bps from canonical formula, or operator-facing display flip only?

Orion proposes → Vesper audits for legibility → Atlas reviews if architectural → implement.

Do not create the feature branch until implementation plan is confirmed.

— Vesper