# RELEASE 2.17 — Shared SignalJoin + Lifecycle + All-Pairs RT

Production cut unifying classic PP/ST/SBT and VPOF behind one Signal API, with durable lifecycle journals and roster freshness SLA.

## What shipped

- **SignalJoin** (`Include/GSignalX/SignalJoin.mqh`) — single join path for Core, Desk, Chart
- **OfvpInputs** — shared Premium OF/VP inputs + per-class mode overrides (`InpOFVPModeFX/CMD/CR`)
- **FX PROXY policy** — classic drives; VPOF abstains from VOTE/SOLO (`fx_proxy_abstain`); bus quality labels always emit
- **PositionLifecycle** — SIGNAL → ARMED → FILLED → MANAGED → CLOSED tags
- **SignalEvent** — batched `signals/events.jsonl` journal + flush per Core cycle
- **Peaks / StratStop** — PersistPeaks default true; close clears ticket peaks; catastrophe SL open log Confirm-aligned
- **All-pairs RT** — adaptive engine budget, starve watchdog (`InpRosterFreshMaxSec`), `calc_age_sec` / `starve` on bus
- Chart EA join DRY onto SignalJoin (no local VOTE fork)

## Operator defaults

- `InpOFVPEnable=false` (legacy Velocity until Premium armed)
- Class modes `-1` = inherit global `InpOFVPMode`
- `InpRosterFreshMaxSec=30`
- Topology A unchanged: DeskExecute + Scouter owns exits + Prop soft STOP

## Verify

```bat
deploy\Confirm-GSignalX.bat
deploy\Clean-and-Deploy.bat
deploy\Confirm-After-Start.bat
deploy\Confirm-VpofSoak.bat
```

Run `GSX_SignalJoin_Test.mq5` once in MT5 (Experts log).
