# Reconciliation Divergence Runbook

## Incident description
The reconciliation loop detects mismatches between Supabase orders/positions and exchange open orders, meaning the database drifted from exchange truth.

## Symptoms
- `reconciliationMismatchCount`, `reconciliationMissingFromExchange`, or `reconciliationMissingInDb` metrics rise.
- Logs show lifecycle-safe handlers executing to correct entry/exit states.
- Dashboard shows active orders or positions that do not exist on the exchange.

## Metrics to check
- `/internal/health` ? `reconciliationLoopHealthy`, `reconciliationMismatchCount`, `reconciliationLastRun`.
- `/metrics` ? `reconciliation_mismatch_total`, `reconciliation_missing_from_exchange_total`, `reconciliation_missing_in_db_total`.
- `/internal/health` runtime fields:
  - `reconciliationParityMismatchTrades`
  - `reconciliationParityQuarantinedTrades`
  - `reconciliationParityAutoClosedTrades`
  - `reconciliationParityMaxMismatchNotionalUsd`
  - `reconciliationParityTotalMismatchNotionalUsd`
  - `reconciliationIntegrityWatchdogTriggered`

## Automated parity heartbeat (ghost self-healing)
- Feature flag: `ENABLE_RECON_POSITION_PARITY_HEARTBEAT=true` (default is `true`; set `false` only for controlled rollback).
- Confirmation gate: `RECON_POSITION_PARITY_CONFIRMATIONS` (default `3` consecutive checks).
- Attribution safety gate: `RECON_POSITION_PARITY_REQUIRE_SUBTAG_ATTRIBUTION` (default `true`).
- Watchdog threshold: `RECON_POSITION_PARITY_MAX_NOTIONAL_PCT` (default `0.5` of allocated capital).
- Auto-resume gate: `ENABLE_RECON_WATCHDOG_AUTO_RESUME=true`.
- Auto-resume delay: `RECON_WATCHDOG_AUTO_RESUME_MIN_PAUSE_MS` (default `900000`).
- Auto-resume clean streak: `RECON_WATCHDOG_AUTO_RESUME_CLEAN_CYCLES` (default `2`).
- Auto-resume cooldown: `RECON_WATCHDOG_AUTO_RESUME_COOLDOWN_MS` (default `1800000`).
- Dry-run mode: `RECON_POSITION_PARITY_DRY_RUN=true` to observe without applying synthetic exits.

Heartbeat behavior:
- Detects ghost lifecycle slices where virtual open qty remains but exchange position is effectively zero.
- Requires consecutive mismatch confirmations before synthetic EXIT reconciliation.
- Enforces sub-tag attribution before any synthetic close; unattributed slices are quarantined.
- Triggers integrity watchdog pause when cumulative mismatch notional exceeds configured capital ratio.
- Auto-resumes trading only when pause source is parity watchdog and reconciliation stays clean for required consecutive cycles.

## EXIT backfill safety gates
- `RECON_EXIT_BACKFILL_REQUIRE_STRONG_ATTRIBUTION=true`:
  - only uses exchange fills that are attributable to the profile/trade (`sub_tag`, deterministic `client_order_id`, or explicit `trade_id` hint).
  - prevents auto-backfill from consuming unrelated account activity.
- `RECON_EXIT_BACKFILL_ALLOW_HEURISTIC_MATCH=false`:
  - disables heuristic assignment modes (`single_open_trade`, `qty_unique`) by default.
  - keeps unmatched rows in `NO_GO` for operator review instead of auto-closing.
- `RECON_EXIT_BACKFILL_FILL_AFTER_TRADE_GRACE_MINUTES=5`:
  - rejects stale fill evidence that predates the lifecycle slice timestamp beyond grace.
  - blocks historical fills from being attached to newer open trades.

## Immediate mitigation
1. Confirm the reconciliation lock is available for the affected profile to avoid double processing.
2. Allow the reconciliation loop to run; it will route mismatches through lifecycle-safe handlers (`reconcileEntryFill`, `reconcileExitFill`, `reconcileCancel`).
3. If divergence persists, manually inspect trade_history and positions for inconsistent state.
4. Notify stakeholders that reconciliation is running and that no manual edits should occur during the fix.

## Expected self-recovery
- Handler corrections align DB orders/positions with exchange data, and metrics return to zero.
- The capital ledger recalculates reservations, and dashboard data becomes consistent.

## When to escalate
- Mismatch metrics stay elevated after two reconciliation runs.
- Reconciliation lock contention prevents the loop from running.
- Exchanges report stale or unknown fills after reconciliation.
Escalate to the trading engineering lead and reference docs/runbooks/reconciliation.md and docs/runbooks/lifecycle-incident.md for follow-up.

## What NOT to do
- Do not manually patch `orders` or `positions` tables while reconciliation is active.
- Do not disable the reconciliation loop; divergence will only grow.
- Do not trigger new ENTRY/EXIT flows for the affected profile until reconciliation completes.
