# Puck Telemetry & Gap Analysis Reference

## Two Gap Detection Layers

| Layer             | Location                | Detects                           | Metric                     | Triggers                      |
| ----------------- | ----------------------- | --------------------------------- | -------------------------- | ----------------------------- |
| **StreamManager** | `stream_manager.rs:329` | Bar-to-bar trade-ID discontinuity | `continuity_gaps_detected` | Bar sequence gap (structural) |
| **LiveBarEngine** | `live_engine.rs:1065`   | Trade-to-trade WS discontinuity   | `gap_fills`                | Puck inline REST fill         |

**Key insight**: `continuity_gaps_detected > 0` but `gap_fills = 0` means the bar sequence has a gap but the WS trade stream is continuous. This is the **backfill-to-sidecar transition gap** — NOT a Puck failure.

## The Transition Gap (By Design)

When the inline backfill runs before engine start:

1. Backfill writes bars up to `end_ms` (time of last REST page)
2. Backfill's forming bar is flushed as orphan at Ouroboros boundary
3. WS starts after backfill completes
4. Fresh processor accumulates WS trades into a new forming bar
5. First completed bar has `first_agg_trade_id` > backfill's `last_agg_trade_id`
6. The trades between backfill's last bar and sidecar's first bar are IN THE FORMING BAR (not lost)
7. StreamManager detects the bar-level gap (`continuity_gaps_detected`)
8. Puck does NOT trigger (no trade-level gap in WS stream)

**Resolution**: Kintsugi day-recompute tomorrow, or checkpoint-based restart (no transition gap).

## Current Puck Telemetry (v13.27.0)

### Available (via health endpoint)

| Metric                     | Source                 | Meaning                                           |
| -------------------------- | ---------------------- | ------------------------------------------------- |
| `gap_fills`                | `LiveEngineMetrics`    | Trade-level gaps detected + Puck fill attempted   |
| `gap_trades_recovered`     | `LiveEngineMetrics`    | Total trades fetched via REST fill                |
| `continuity_gaps_detected` | `StreamManagerMetrics` | Bar-level gaps detected                           |
| `continuity_verified`      | `StreamManagerMetrics` | Bars with verified trade-ID continuity            |
| `reconnections`            | `LiveEngineMetrics`    | Incremented on each Puck fill (same as gap_fills) |
| `rate_limiter_remaining`   | `StreamManagerMetrics` | REST budget remaining                             |
| `rate_limiter_utilization` | `StreamManagerMetrics` | REST budget usage ratio                           |

### Missing (needed for deeper diagnosis)

| Telemetry                                     | Why Needed                                      |
| --------------------------------------------- | ----------------------------------------------- |
| Puck fill attempt duration_ms                 | Distinguish timeout vs rate limit vs REST error |
| Puck fill REST response status                | 429 (rate limit) vs 5xx (server) vs timeout     |
| Puck fill trades_requested vs trades_received | Partial fill detection                          |
| Gap detector seed value per symbol            | Verify CH seed was applied correctly            |
| Min-TID guard drop count per pair             | Confirm guard is working (currently DEBUG only) |
| Backfill orphan bar flush events              | Track when forming bars are abandoned           |

### Adding Telemetry (Future)

Puck telemetry improvements require Rust changes (new `.so` build):

1. Add `tracing::info!` before/after REST call in `puck_fill()` with duration
2. Add `gap_fill_failures` counter to `LiveEngineMetrics`
3. Emit `GapEvent::FillResult` to the gap event channel (already exists for `GapEvent::Detected`)
4. Surface in Python via `engine.get_metrics()` → health endpoint
