# VRP Strategy Full Removal — Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development to implement this plan task-by-task. Steps use checkbox tracking; delete leaves before callers so imports never break mid-removal.

**Derived from:** a discovery workflow (24 file classifications + 3 deep-traces) — `wf_ffbdc8b5-c02`. The
tricky shared-vs-VRP calls were resolved by trace: **DVOL pipeline = delete** (only VRP reads it),
**black_scholes.py = delete** (VRP-only), **surfer vendor = untouched** (docstring mention only),
**xsp_option_bars TABLE/MODEL/data = KEEP** (only the VRP-only `XspOptionBarsRepo` *class* is deleted).

## Goal

Fully delete the VRP (variance-risk-premium) strategy — the shelved/FALSIFIED equity-VRP
sleeve and its executed twin `vrp_exec` — from the fxhnt repo, leaving **zero orphaned code,
zero dead registry keys, and zero dangling imports**. The nightly Dagster pipeline, the cockpit
web app, live IBKR/UCITS execution, the Bybit paper book, and all four kept crypto edges must
remain fully functional and the pytest suite must be green at the end.

The removal spans four coupled clusters, all of which are VRP-exclusive per the deep-traces:

1. **VRP application modules**: `vrp_book`, `vrp_eval`, `vrp_defined_risk_eval`,
   `vrp_exec_record`, `vrp_marking`, `vrp_pricing`, `vrp_research`.
2. **VRP option-math + IV plumbing**: `black_scholes.py` (VRP-only), the entire DVOL pipeline
   (`deribit_dvol.py`, `dvol_ingest.py`, the `dvol` feature panel, the unused
   `VolIndexClient.dvol()` port).
3. **VRP persistence/orchestration**: `xsp_option_bars.py` repo class, the `vrp_nav` Dagster
   asset + its ~14 private OPRA-freeze/backfill helpers, the `backfill-xsp-opra` ingest path,
   the `VrpStrategy` builder, and the `vrp`/`vrp_exec` registry entries.
4. **Comment/registry-string scrubs** across shared cockpit infrastructure that merely *names*
   VRP as an illustrative example.

## Architecture

VRP was ARCHIVED 2026-07-15 (fails the LOO marginal-Sharpe gate; see
`pearl_fxhnt_diversifier_hunt_2026_07_15`). The two registry entries already carry
`archived: True`, and `vrp_nav` is already **de-wired** from `definitions.py`'s nightly asset
graph — so no live nightly asset materializes VRP today. What remains is dead weight plus two
active-but-purposeless CLI/CronJob ingest paths (`ingest-dvol`, `backfill-xsp-opra`) and a set
of stale registry keys/comment references.

Dependency direction (leaf → root), which dictates task order so imports never break mid-removal:

```
black_scholes.py ────────────► vrp_defined_risk_eval.py ──┐
deribit_dvol.py ─► dvol_ingest.py ─► (dvol panel) ────────┤
xsp_option_bars.py (repo class) ──► vrp_book.py ──────────┤──► cli.py commands
vrp_pricing.py / vrp_marking.py ──► vrp_book/eval/exec ───┤     migration_builders (_build_vrp)
                                                          └──► assets.py vrp_nav + helpers
                                                               registry.py vrp / vrp_exec
                                                               forward_ingest _REF_ALIAS
                                                               sim_curves / dashboard_service /
                                                               app.py / definitions.py (scrub)
```

Rule: delete leaf modules **and their tests together** first, then the callers that referenced
them (asset graph, registry, CLI, migration builder), then the pure comment-scrub edits last.

## DVOL and black_scholes — resolved decisions (per deep-traces)

- **DVOL pipeline → DELETE (do not keep).** Exhaustive grep confirms the only readers of the
  `dvol` feature panel (`store.read_panel(..., "dvol")`) are `vrp_eval.py` and
  `vrp_defined_risk_eval.py`. `VolIndexClient.dvol()` (`ports/market_data.py:22`) has **zero**
  callers. DVOL is not a Dagster asset. DVOL is the Deribit IV index — a data source entirely
  distinct from the OPRA `xsp_option_bars` data being kept; there is no keep-carve-out for it.
  Delete `deribit_dvol.py`, `dvol_ingest.py`, the `ingest-dvol` CLI command, the
  `VolIndexClient.dvol()` port method, and their tests. The `dvol` warehouse rows in
  `bybit_features` are inert once nothing reads them — no migration needed; they can age out.

- **black_scholes.py → DELETE (VRP-only, not shared math).** The only importers are
  `vrp_defined_risk_eval.py` and its own unit test `tests/unit/test_black_scholes.py`.
  `vrp_pricing.py` defines a *separate* `bs_put` (different signature) and does **not** import
  from `black_scholes.py`, so there is no hidden cross-file sharing. Delete both files.

- **`xsp_option_bars` TABLE + `XspOptionBarRow` model + OPRA `.dbn` → KEEP.** Only the
  `XspOptionBarsRepo` *repo class* (`adapters/persistence/xsp_option_bars.py`) is VRP-only and
  gets deleted. The ORM row model `XspOptionBarRow` in `cockpit_models.py`, the physical table,
  the 13-year OPRA data, and `ForwardNavRepo.xsp_freeze_max_date()` (raw `SELECT max(date)`)
  all stay untouched.

## Global Constraints

1. **KEEP the OPRA data.** Do **not** drop or migrate the `xsp_option_bars` table, do **not**
   remove `XspOptionBarRow` from `cockpit_models.py`, do **not** delete OPRA `.dbn` files, and
   do **not** touch `ForwardNavRepo.xsp_freeze_max_date()`. Only the VRP *ingest/consumer*
   machinery (`XspOptionBarsRepo` class, `_backfill_month`/`_freeze_*` helpers, `backfill-xsp-opra`)
   is removed. The freeze-staleness health axis (`_FREEZE_SOURCES = {"opra-pit"}`) stays generic.
2. **Real-money paths must err false-WAIT, never false-EXECUTE.** VRP execution
   (`execute-vrp`/`vrp_exec_record`) is being deleted, not disabled — but during the removal no
   edit may cause any *surviving* real-money path (multistrat/UCITS IBKR, Bybit paper) to
   silently promote/execute on missing state. After removing the `vrp`/`vrp_exec` registry keys,
   confirm the cockpit gate and `forward_ingest` promotion loop still default to WAIT for every
   surviving strategy and never KeyError into a false-PASS.
3. **Full pytest suite green before finishing.** Run `uv run pytest -n auto` (or
   `python -m pytest -n auto` per `pyproject.toml addopts = "-n auto"`) from the repo root and
   confirm 0 failures / 0 errors before the final commit. Per-task commands below are the fast
   local gate; the full-suite run in the final task is the release gate.
4. **The false VRP STALE health alarm must be gone.** After removal, verify **no `vrp` key
   remains in `STRATEGY_REGISTRY`** (`vrp` and `vrp_exec` both removed) so the forward-health
   freeze/staleness axis and `dashboard_service._active_ibkr_account_sids()` can no longer
   surface a ghost VRP STALE row. Verification command in the final task.

### Pre-flight note (already-broken test)

`tests/unit/test_vrp_rebalancer_yaml.py` asserts the existence of
`infra/k8s/jobs/fxhnt-vrp-rebalancer.yaml`, which **no longer exists** in the tree. This test is
already failing/erroring at HEAD; it is deleted in Task 1 alongside the other VRP tests, which
also removes that pre-existing red.

---

## Task 1 — Delete VRP application modules + their tests (leaves first)

**Files to delete (whole file):**
- `src/fxhnt/application/vrp_book.py`
- `src/fxhnt/application/vrp_eval.py`
- `src/fxhnt/application/vrp_defined_risk_eval.py`
- `src/fxhnt/application/vrp_exec_record.py`
- `src/fxhnt/application/vrp_marking.py`
- `src/fxhnt/application/vrp_pricing.py`
- `src/fxhnt/application/vrp_research.py`
- `src/fxhnt/application/black_scholes.py`
- `tests/unit/test_vrp_book.py`
- `tests/unit/test_vrp_pricing.py`
- `tests/unit/test_vrp_exec_helpers.py`
- `tests/unit/test_vrp_exec_ladder_cap.py`
- `tests/unit/test_vrp_exec_record.py`
- `tests/unit/test_vrp_rebalancer_yaml.py` (also clears the pre-existing red — see pre-flight note)
- `tests/unit/test_registry_vrp.py`
- `tests/unit/test_black_scholes.py`
- `tests/integration/test_vrp_eval.py`
- `tests/integration/test_vrp_defined_risk_eval.py`
- `tests/integration/test_vrp_nav_asset.py`
- `tests/integration/test_cockpit_vrp_render.py`

**Rationale:** every one of these modules is imported only by other `vrp_*` modules or by the
`cli.py`/`assets.py`/`migration_builders.py` callers handled in later tasks. Deleting the tests
in the *same* task prevents collection-time `ImportError` on the deleted modules. Do NOT yet
touch `assets.py`, `cli.py`, `registry.py`, or `migration_builders.py` — those still reference
these modules only via **lazy (in-function) imports**, so the module tree still imports cleanly
after this task (the broken imports are inside function bodies not executed at import time). They
are removed in Tasks 3–5.

**Covering test command** (must import-clean and not collect the deleted files):
```
uv run pytest tests/unit tests/integration -q --co 2>&1 | tail -20
```
Expect: collection succeeds with the deleted VRP tests absent and no `ImportError`.

**Commit:** `refactor(vrp): delete VRP application modules + black_scholes + their tests`

---

## Task 2 — Delete the DVOL pipeline + its tests

**Files to delete (whole file):**
- `src/fxhnt/adapters/data/deribit_dvol.py`
- `src/fxhnt/application/dvol_ingest.py`
- `tests/integration/test_deribit_dvol.py`
- `tests/integration/test_dvol_ingest.py`

**Edit `src/fxhnt/ports/market_data.py`:**
- Remove the `VolIndexClient` Protocol (the `dvol()` method block, ~lines 21–24). Confirmed
  zero implementers and zero callers repo-wide; it is dead scaffolding.

**Do NOT touch:** `deribit_funding.py` and the `ingest-deribit-funding` CronJob/command —
that is the *funding* (cross-venue carry) edge, a separate kept data source that reads the
`funding`/`deribit_funding` features, never `dvol`.

**Rationale:** `ingest_dvol` and `DeribitDVOL` are consumed only by the `ingest-dvol` CLI
command (removed in Task 3) which fed only the two VRP evaluators (deleted in Task 1). The
`dvol` feature panel now has no readers.

**Covering test command:**
```
uv run pytest tests/integration -q --co 2>&1 | tail -20
grep -rn "VolIndexClient\|import.*deribit_dvol\|import.*dvol_ingest" src/ | grep -v "/cli.py"
```
Expect: no collection errors; the grep returns only the (still-present, removed next task)
`cli.py` lazy imports.

**Commit:** `refactor(vrp): delete DVOL pipeline (deribit_dvol, dvol_ingest, VolIndexClient port) + tests`

---

## Task 3 — Delete VRP + DVOL commands from `cli.py`

**File to edit:** `src/fxhnt/cli.py`

**Exact edits (delete each command block in full, including its in-function lazy imports):**
- Delete `@app.command("execute-vrp")` `execute_vrp` (lines ~439–499), including the lazy
  `from fxhnt.application.vrp_exec_record import plan_and_record_vrp`. **Keep** the module-level
  and other commands' use of `ForwardNavRepo` — only remove this command's local import line if
  it has one; the `ForwardNavRepo` module itself is reused by `execute-multistrat` and others.
- Delete `@app.command("ingest-dvol")` `ingest_dvol_cmd` (lines ~1217–1266), including the lazy
  `from fxhnt.adapters.data.deribit_dvol import DeribitDVOL` and
  `from fxhnt.application.dvol_ingest import ingest_dvol`.
- Delete `@app.command("vrp-eval")` `vrp_eval` (lines ~2193–2288), including the lazy
  `from fxhnt.application.vrp_eval import (verify_vrp_edge, vrp_metrics_from_store, walk_forward_vrp)`.
- Delete `@app.command("vrp-defined-risk-eval")` `vrp_defined_risk_eval` (lines ~2291–2403),
  including the lazy `from fxhnt.application.vrp_defined_risk_eval import (...)`.
- Delete the private helpers `_print_vrp_verify` (~2406–2446) and `_print_vrp_walk_forward`
  (~2449–2469) — called only by the two eval commands above.

**Decision — `backfill-xsp-opra` (lines ~578–623): DELETE this command too.** It calls
`_backfill_month` and `XspOptionBarsRepo`, both of which are deleted in Tasks 4/5, and its sole
purpose is freezing OPRA marks into `xsp_option_bars` **for VRP recompute**. Keeping the OPRA
*data* (Constraint 1) does not require keeping the *ingest path* — the data already exists and
the only consumer of freshly-frozen marks was VRP. Delete the `@app.command("backfill-xsp-opra")`
`backfill_xsp_opra` function and its `from fxhnt.adapters.orchestration.assets import _backfill_month`
+ `from fxhnt.adapters.persistence.xsp_option_bars import XspOptionBarsRepo` local imports. (If
the executor finds a documented non-VRP consumer of freshly-frozen OPRA marks, stop and flag —
none was found in the trace.)

**Covering test command:**
```
uv run python -c "import fxhnt.cli"          # module must import clean
uv run fxhnt --help >/dev/null               # Typer app builds with commands gone
grep -n "vrp\|dvol\|backfill-xsp\|VrpStrategy\|black_scholes\|XspOptionBarsRepo" src/fxhnt/cli.py
```
Expect: import + `--help` succeed; grep returns no hits.

**Commit:** `refactor(vrp): remove execute-vrp/ingest-dvol/vrp-eval/vrp-defined-risk-eval/backfill-xsp-opra CLI commands`

---

## Task 4 — Remove the `vrp_nav` asset + OPRA-freeze helpers from `assets.py`

**File to edit:** `src/fxhnt/adapters/orchestration/assets.py`

**Exact edits (delete code):**
- Delete the `@asset`-decorated `vrp_nav` function (lines ~686–718), including its inline
  imports of `DatabentoDataProvider`, `XspOptionBarsRepo`, `VrpStrategy` (~line 694).
- Delete the exclusive private helper chain (lines ~492–683), all VRP-only and now callerless
  after Tasks 1/3: `_iso_date`, `_forward_from_marks` (+ its inline
  `fxhnt.application.vrp_pricing.parity_forward` import ~502), `_band_contracts`,
  `_band_rows_from_marks`, `_day_marks`, `_xsp_forward_estimate`, `_freeze_xsp_slice`,
  `_freeze_day`, `_prev_trading_day`, `_DEGENERATE_FORWARD_MARKERS`,
  `_is_degenerate_forward_error`, `_freeze_latest_session` (+ its inline
  `DatabentoRangeUnavailable` import ~614), `_rough_forward`, `_backfill_month`.
- Delete the trailing `# vrp_nav ARCHIVED 2026-07-15 — de-wired (fn kept below)` comment
  (~line 1131) — the function no longer exists below.
- Reword the module docstring (~line 4): drop the trailing `/vrp` from the forward-track asset
  enumeration.

**Do NOT touch:** `deribit_funding_bars` (~825–856, unrelated Deribit perp *funding*, kept for
cross-venue-carry), and all other assets (`futures_bars`, `bybit_*`, `multistrat_*`,
`sixtyforty_nav`, `positioning_nav`, `xsfunding_nav`, `unlock_nav`, `cockpit_forward`, …). The
RETIRED-track comments at ~721 and ~748 do not mention vrp — leave as-is.

**Covering test command:**
```
uv run python -c "import fxhnt.adapters.orchestration.assets"
uv run python -c "import fxhnt.adapters.orchestration.definitions"   # Dagster code-location loads
grep -n "vrp\|Vrp\|_backfill_month\|_freeze_\|XspOptionBarsRepo\|vrp_pricing" src/fxhnt/adapters/orchestration/assets.py
uv run pytest tests/integration/test_orchestration_definitions.py -q
```
Expect: both modules import clean, grep returns no hits, definitions test passes.

**Commit:** `refactor(vrp): delete vrp_nav Dagster asset + OPRA-freeze/backfill helper chain`

---

## Task 5 — Remove `XspOptionBarsRepo` class + the `_build_vrp` migration builder

**File to delete (whole file):**
- `src/fxhnt/adapters/persistence/xsp_option_bars.py` (the `XspOptionBarsRepo` repo class).
  All callers (`vrp_book.py`, `vrp_exec_record.py`, `vrp_marking.py`, the `vrp_nav` asset, the
  `backfill-xsp-opra` command) are gone after Tasks 1/3/4.
- **VERIFIED 2026-07-20: `tests/integration/test_xsp_option_bars_repo.py` does NOT exist in the tree** —
  do not attempt to delete it. If a repo-class test surfaces under another name during removal, delete it;
  otherwise there is no test file for this class.

**KEEP (Constraint 1):** `cockpit_models.XspOptionBarRow`, the `xsp_option_bars` table, and
`ForwardNavRepo.xsp_freeze_max_date()` — none of these import or depend on the repo class.

**File to edit:** `src/fxhnt/adapters/orchestration/migration_builders.py`
- Delete the `_build_vrp` closure (lines ~71–76) and its `builders["vrp"] = ("vrp_state",
  _build_vrp)` registration (~78), plus the preceding `# ---- vrp_nav: ...` comment banner (~71).

**Covering test command:**
```
uv run python -c "import fxhnt.adapters.orchestration.migration_builders"
grep -rn "XspOptionBarsRepo\|_build_vrp\|builders\[.vrp" src/
uv run pytest tests/ -q -k "migration or migrate" 2>&1 | tail -20
```
Expect: import clean, grep returns no hits (the `XspOptionBarRow` model in `cockpit_models.py`
is a different symbol and must still be present — verify separately:
`grep -n "class XspOptionBarRow" src/fxhnt/adapters/persistence/cockpit_models.py` returns 1 hit).

**Commit:** `refactor(vrp): delete XspOptionBarsRepo class + _build_vrp migration builder (keep table + XspOptionBarRow)`

---

## Task 6 — Remove `vrp`/`vrp_exec` registry keys + `forward_ingest` alias

**File to edit:** `src/fxhnt/registry.py`
- Delete the `"vrp"` `STRATEGY_REGISTRY` entry (lines ~161–172) and its preceding comment
  block (~157).
- Delete the `"vrp_exec"` `STRATEGY_REGISTRY` entry (lines ~177–186) and its preceding comment
  block (~173–176).
- Keep the dict itself and all 9 non-VRP entries and the `FUND_INSTRUMENTS` import/re-export.

**File to edit:** `src/fxhnt/application/forward_ingest.py`
- Remove the `"vrp_exec": "vrp"` pair from `_REF_ALIAS` (line ~45), leaving
  `{"multistrat_exec": "multistrat", "bybit_4edge_exec": "bybit_4edge"}`.

**Rationale + Constraint 4:** removing the `vrp` key is what actually kills the false VRP STALE
health alarm — with no `vrp` in `STRATEGY_REGISTRY`, the forward-health freeze/staleness loop
and `dashboard_service._active_ibkr_account_sids()` can no longer iterate a ghost VRP row.
(Note: `dashboard_service._IBKR_ACCOUNT_SIDS` hard-codes `"vrp"`; that literal is fixed in
Task 7 in the *same PR* so the window where the key is gone but the literal remains never ships.)

**Covering test command:**
```
uv run python -c "from fxhnt.registry import STRATEGY_REGISTRY; assert 'vrp' not in STRATEGY_REGISTRY and 'vrp_exec' not in STRATEGY_REGISTRY, STRATEGY_REGISTRY.keys(); print('registry clean')"
uv run pytest tests/unit/test_forward_definition.py tests/integration/test_forward_health.py tests/integration/test_dashboard_service.py -q 2>&1 | tail -20
```
Expect: assertion passes; forward/dashboard tests green (these confirm surviving strategies
still WAIT-by-default — Constraint 2).

**Commit:** `refactor(vrp): remove vrp/vrp_exec registry entries + forward_ingest _REF_ALIAS`

---

## Task 7 — Fix the one behavioral literal + `sim_curves` book pill (data edits)

These are the two non-comment edits that gate on `vrp` being a *present* registry key and would
misbehave once it is gone (Task 6). They ship together with — or immediately after — Task 6.

**File to edit:** `src/fxhnt/application/dashboard_service.py`
- Line ~30: change `_IBKR_ACCOUNT_SIDS = frozenset({"multistrat", "vrp"})` to
  `frozenset({"multistrat"})`. **Why this is behavioral, not cosmetic:** `_active_ibkr_account_sids()`
  computes `not STRATEGY_REGISTRY.get("vrp", {}).get("archived")`; once the `vrp` key is gone
  this becomes `not None` = `True`, wrongly treating `vrp` as an ACTIVE ibkr-account sid and
  rendering a ghost/broken VRP row on the IBKR account page. Removing the literal eliminates it.

**File to edit:** `src/fxhnt/application/sim_curves.py`
- Line ~15: remove the `"vrp"` string from the `SIM_BOOKS` tuple, leaving
  `("bybit_4edge", "bybit_4edge_levered", "multistrat", "multistrat_levered")`. **Why:** once
  the `vrp` registry entry is gone, a `vrp` Backtest-page pill would `KeyError`/500 at request
  time in `app.py` (`registry_backtest_kind("vrp")`). The dispatch logic in `sim_returns_for`
  is generic and unchanged.

**Covering test command:**
```
uv run pytest tests/unit/test_sim_curves.py tests/integration/test_dashboard_service.py tests/integration/test_ibkr_account_detail_web.py tests/integration/test_dashboard_ibkr_holdings.py tests/integration/test_paper_books_web.py tests/integration/test_ibkr_sim_web.py -q 2>&1 | tail -20
```
Expect: green; no VRP row/pill; surviving books render.

**Commit:** `fix(vrp): drop vrp from _IBKR_ACCOUNT_SIDS and SIM_BOOKS so ghost VRP row/pill can't render`

---

## Task 8 — Delete the now-purposeless VRP/OPRA CronJob manifest

**File to delete:**
- `infra/k8s/jobs/fxhnt-opra-backfill.yaml` — invokes `fxhnt backfill-xsp-opra` (deleted in
  Task 3). With the command gone this CronJob would crash-loop; its only job was freezing OPRA
  marks for VRP recompute. (The `fxhnt-vrp-rebalancer.yaml` manifest is already absent from the
  tree — nothing to delete there; its dangling test is removed in Task 1.)

**Do NOT touch:** `fxhnt-deribit-carry-job.yaml` (funding/carry, not DVOL),
`fxhnt-bybit-*`, `fxhnt-ucits-rebalancer.yaml`, `fxhnt-ibkr-rebalancer.yaml`, and all other
manifests.

**Covering check:**
```
grep -rln "vrp\|ingest-dvol\|execute-vrp\|backfill-xsp-opra" infra/    # expect: no hits
```

**Commit:** `chore(vrp): remove fxhnt-opra-backfill CronJob (backfill-xsp-opra command deleted)`

---

## Task 9 — Comment/docstring scrubs (no logic change) — LAST

Pure prose edits that dangling-reference the deleted `vrp` strategy id. No imports, logic,
registry entries, or types change. Batched last because none affect importability.

**Files + edits (reword to drop the `vrp` example, keep meaning):**
- `src/fxhnt/adapters/orchestration/definitions.py` — lines ~10–12: drop the
  "vrp_nav ARCHIVED … KEPT in assets.py but DE-WIRED" paragraph (the "KEPT" claim is now false);
  replace with a one-line "VRP removed entirely 2026-07-20" note or delete outright.
- `src/fxhnt/adapters/persistence/cockpit_models.py` — line ~46 (drop the `(… that would have
  caught vrp)` parenthetical or generalize to "a dead strategy"); line ~228 (drop `/vrp` from
  `(multistrat/vrp …)`).
- `src/fxhnt/adapters/persistence/forward_nav.py` — lines ~146–147 (generalize "the vrp freeze
  table" / "a vrp recompute is bounded by this max date" to opra-pit-anchored/strategy-generic
  wording; the `xsp_freeze_max_date` query stays); line ~199 (drop the "shelved/FALSIFIED
  vrp/vrp_exec" example from the `archived: True` registry note).
- `src/fxhnt/adapters/persistence/paper_repo.py` — line ~519 (drop `vrp` from the
  `(multistrat/vrp …)` recompute-replay parenthetical).
- `src/fxhnt/adapters/web/app.py` — lines ~449, 453, 473, 482, 551, 567, 728, 752, 810: drop the
  `/vrp` example from each `multistrat/vrp` phrase. No code change (the archived-filter
  comprehension already yields one fewer element once `vrp` left `SIM_BOOKS`/registry).
- `src/fxhnt/adapters/web/templates/_macros.html` — line ~61 ("2-week vrp rot"): generalize.
- `src/fxhnt/adapters/web/templates/cockpit.html` — line ~78: drop `/vrp` from
  "two IBKR real-account books (multistrat/vrp)".
- `src/fxhnt/application/dashboard_service.py` — comment-only lines ~27, 55, 89, 390, 416, 417:
  drop/generalize the `vrp` examples (the code literal was already fixed in Task 7).
- `src/fxhnt/application/sim_curves.py` — lines ~2, 12, 22: drop `vrp` from the
  `multistrat/vrp` recompute-replay examples (the tuple was already fixed in Task 7).
- `src/fxhnt/application/forward_health.py` — docstring lines ~3, 11, 13, 14, 15, 24, 31 and the
  inline comment at ~147 ("for the vrp freeze axis"): generalize away from naming `vrp` as the
  mechanism's reason for existing; the `_FREEZE_SOURCES = {"opra-pit"}` logic and
  `xsp_freeze_max_date()` call are unchanged.
- `src/fxhnt/application/display_names.py` — lines ~2 and ~51: drop the `vrp` example id /
  option-contract example from the illustrative prose.
- `src/fxhnt/application/em_asia_marginal_eval.py` — lines ~6, 19, 71: replace "VRP" in the
  Stage-1 kill-gate precedent comments with a VRP-agnostic phrase ("prior failed diversifier
  candidates"). No logic change.
- `src/fxhnt/config.py` — line ~215: drop `(… that would have caught vrp)` from the
  `stale_after_business_days` comment; keep the setting + default.
- `src/fxhnt/ports/dashboard.py` — lines ~72 and ~190: drop the `vrp` example from the
  `multistrat/vrp` IBKR-real-account docstrings. (Line ~34 is unrelated carry — leave.)
- `src/fxhnt/vendor/surfer/__init__.py` — lines ~11–13: compress the `surfer_poc`/
  `MomentumVrpStrategy` retirement note to a plain historical line without the VRP signpost.

**Do NOT edit** as part of scrubbing (already covered / must not change): the `xsp_option_bars`
query, `_FREEZE_SOURCES`, `XspOptionBarRow`, any settings field, or any Protocol field.

**Covering test command** (broad — scrubs must not have touched logic):
```
uv run python -c "import fxhnt.adapters.web.app, fxhnt.application.dashboard_service, fxhnt.application.forward_health, fxhnt.config, fxhnt.ports.dashboard, fxhnt.application.display_names, fxhnt.application.em_asia_marginal_eval, fxhnt.application.sim_curves"
uv run pytest tests/unit/test_display_names.py tests/integration/test_dashboard_service.py -q 2>&1 | tail -20
```
Expect: all import clean; tests green.

**Commit:** `docs(vrp): scrub stale VRP comment/docstring references across cockpit + shared infra`

---

## Task 10 — Full-suite green gate + removal verification (release gate)

**No file edits.** Final verification against all Global Constraints.

**Commands (all must pass):**
```
# (3) full suite green
uv run pytest -n auto 2>&1 | tail -30        # 0 failed, 0 errors

# (4) no vrp in registry — false STALE alarm gone
uv run python -c "from fxhnt.registry import STRATEGY_REGISTRY; assert not any(k.startswith('vrp') for k in STRATEGY_REGISTRY), list(STRATEGY_REGISTRY); print('no vrp in registry')"

# no orphaned VRP code / imports anywhere in src
grep -rn "import.*vrp_\|VrpStrategy\|deribit_dvol\|dvol_ingest\|black_scholes\|XspOptionBarsRepo\|VolIndexClient\|_backfill_month\|plan_and_record_vrp" src/     # expect: no hits
ls src/fxhnt/application/vrp_*.py 2>&1                 # expect: No such file
ls src/fxhnt/application/black_scholes.py src/fxhnt/application/dvol_ingest.py src/fxhnt/adapters/data/deribit_dvol.py src/fxhnt/adapters/persistence/xsp_option_bars.py 2>&1   # expect: No such file (all four)

# (1) OPRA data kept — table model + freeze query still present
grep -n "class XspOptionBarRow" src/fxhnt/adapters/persistence/cockpit_models.py    # expect: 1 hit
grep -n "def xsp_freeze_max_date" src/fxhnt/adapters/persistence/forward_nav.py     # expect: 1 hit

# (2) Dagster code-location + cockpit app both import clean (no false-execute / no outage)
uv run python -c "import fxhnt.adapters.orchestration.definitions; import fxhnt.adapters.web.app; print('definitions + app import clean')"

# no residual vrp mentions in infra
grep -rln "vrp\|ingest-dvol\|execute-vrp\|backfill-xsp-opra" infra/     # expect: no hits
```

**Constraint 2 spot-check:** confirm `forward_ingest`'s promotion loop and the cockpit gate
default to WAIT for every surviving strategy (the recon-gate never false-PASSes) — covered by
`test_forward_health.py` / `test_dashboard_service.py` in the full run; if either regresses, the
removal touched a shared gate path and must be reverted to the last green task.

**Commit (only after everything above is green):** `chore(vrp): verify full VRP removal — suite green, registry clean, OPRA data intact`

---

## Post-removal note

After merge, update `docs/superpowers/VRP-REMOVAL-TODO.md` and project memory
(`pearl_fxhnt_diversifier_hunt_2026_07_15.md` already says "VRP now fully DELETED (shelved)") to
reflect that the code deletion — not just shelving — is complete, and that the OPRA
`xsp_option_bars` data was retained per Constraint 1.