# Phase 1: Junction Fix (Root Cause) - Context

**Gathered:** 2026-03-19
**Status:** Ready for planning

<domain>
## Phase Boundary

Fix the forming-bar abandonment bug at the REST→WS junction in `symbol_task()` within `live_engine.rs`. When `fill_from_rest()` pre-creates a processor, the transition to WS streaming must preserve the forming bar, suppress Puck for the expected junction gap, and handle trade-ID monotonicity for overlapping WS buffer trades.

</domain>

<decisions>
## Implementation Decisions

### Claude's Discretion

All implementation choices are at Claude's discretion — pure infrastructure phase. The fix is ~15 lines in `symbol_task()` between processor reuse and the main `loop { select! {} }`.

Key constraints from research:

- Reuse `puck_fill()` for the junction gap (no new abstraction)
- Peek first WS trade to compute junction gap from processor's `last_agg_trade_id`
- Re-seed gap detector past junction before entering main loop
- Silently drop WS trades with trade-IDs <= processor's last known trade (monotonicity guard)

</decisions>

<code_context>

## Existing Code Insights

### Reusable Assets

- `puck_fill()` in `live_engine.rs` — existing inline REST gap-fill function, reusable for junction fill
- `processor.last_agg_trade_id()` — returns the last processed trade ID, used to compute junction gap
- `gap_detector.seed(tid)` — re-seeds the gap detector to suppress Puck for a known gap
- `pre_buffered_rx` — mpsc receiver for WS trades buffered during `fill_from_rest()`

### Established Patterns

- `fill_from_rest()` returns pre-created processors keyed by (symbol, threshold)
- `symbol_task()` reuses these processors when starting the WS loop
- Gap detector fires when `current_tid - last_known_tid > 1`
- Puck fills gaps via parallel REST fetch through the same processor

### Integration Points

- Between processor reuse (line ~XXX) and main `loop { select! {} }` in `symbol_task()`
- Must set gap detector's `last_known_tid` AFTER junction fill completes

</code_context>

<specifics>
## Specific Ideas

Root cause proven on SOLUSDT@500 (2026-03-19): fill_from_rest fetched 149,405 trades, produced 9 bars + forming bar with ~100K accumulated trades. At junction, Puck fired on the expected gap, disrupting the forming bar. Result: 99,882-trade gap.

Fix must work for all 18 symbols × 4 thresholds (72 pairs total).

</specifics>

<deferred>
## Deferred Ideas

None — discussion stayed within phase scope

</deferred>
