# RECENT VIOLET 34E — trade/slot-granularity comparison harness This pass implemented the next numbered comparison item from the main Violet spec: the trade/slot-granularity comparison that was still deferred after the V3.4c live-source work and shadow journal wiring. ## What existed before Before this pass, Violet already had: - `VioletDecisionEngine` producing shadow decisions - `VioletDecisionJournal` persisting actuated decisions to `violet_decisions` - live-source adapters for BLUE-published factors - full sizing parity through `VioletSizer` What was still missing was a dedicated comparison unit that could collapse those journaled decisions into episode-sized runs and compare them against the terminal trade surface at the same granularity. ## What was added I added a new Violet-only comparator: - [prod/clean_arch/violet/trade_slot_compare.py](/mnt/dolphinng5_predict/prod/clean_arch/violet/trade_slot_compare.py) - [prod/clean_arch/violet/test_violet_trade_slot_compare.py](/mnt/dolphinng5_predict/prod/clean_arch/violet/test_violet_trade_slot_compare.py) The new module provides: - `DecisionEpisode`: a collapsed run of contiguous shadow decisions for one asset/side - `TradeEpisode`: a collapsed terminal trade record grouped by `trade_id` - `EpisodeMatch`: a paired decision/trade episode with timing and row-count gaps - `TradeSlotComparison`: the full comparison result - `compare_trade_slot_granularity(...)`: the top-level collapse-and-compare API ## How it works The comparator is deliberately narrow: - it groups decision rows by `asset` + `side` - it splits them into episodes when the scan number gap exceeds the configured `max_scan_gap` - it groups trade rows by `trade_id` - it ignores malformed rows rather than failing on them - it matches episodes by asset/side and preserves unmatched decision/trade rows This is downstream of the existing shadow journal. It does not reimplement ACB, EsoF, OB, or sizing math. It only compares the surfaces that already exist. ## Anomaly handling The comparator rejects or skips bad inputs instead of letting them pollute the episode view: - missing asset or side - missing or invalid scan number - malformed or missing trade id - non-finite numeric fields That keeps the harness usable against noisy journal extracts and historical trade rows that may contain replay artifacts. ## Tests The new tests cover: - episode collapse across contiguous decision rows - terminal trade dedupe through `trade_id` - scan-gap splitting - malformed row handling - empty-input behavior Verification on this pass: - `PYTHONPATH=/mnt/dolphinng5_predict rtk python -m pytest -q /mnt/dolphinng5_predict/prod/clean_arch/violet/test_violet_trade_slot_compare.py` - result: `3 passed` ## Why this is the right next step The main Violet plan explicitly defers trade/slot-granularity comparison until the shadow side has a comparable execution surface. That condition is now met well enough to build the comparison harness without touching BLUE or the live executor.