# Add /status endpoint to sidecar HTTP server

**Commit:** 6adfc7a
**File modified:** `python/opendeviationbar/sidecar.py` (+54 lines)

## What was done

Added `/status` HTTP endpoint to the sidecar health server for junction telemetry, consumed by `scripts/heartbeat/checks/junction.py`.

### Changes in sidecar.py

1. **`_junction_state` module-level dict** (line ~1285): Stores per-symbol junction data, populated during `_sync_flush_rest_bars()`.

2. **Population in `_sync_flush_rest_bars()`** (lines ~857-866): After draining REST bars and writing to ClickHouse, records `rest_last_tid` (max `last_agg_trade_id` across bars) per symbol into `_junction_state`.

3. **`_health_state["start_monotonic"]`** (line ~2113): Stores sidecar start time for uptime computation.

4. **`/status` route** in `do_GET` (line ~1518): Routes to `_handle_status()`.

5. **`_handle_status()` method** (lines ~1561-1594): Returns JSON with:
   - `engine`: cached engine metrics (same source as /health)
   - `symbols`: per-symbol dict with `rest_last_tid`, `forming_bar` (null), `committed_floors` (null)
   - `uptime_s`: seconds since sidecar start

### What junction.py already expects

The heartbeat check at `scripts/heartbeat/checks/junction.py` already queries `http://localhost:8081/status` and handles missing fields gracefully. It extracts `rest_last_tid`, `ws_first_tid`, `forming_bar`, and `committed_floors` from the `symbols` dict. Fields not yet available (`forming_bar`, `committed_floors`) return null and the check falls through to journalctl fallback.

## Future enhancements

- Wire `forming_bar` from `take_forming_bar_watcher()` if engine supports it
- Wire `committed_floors` once available from Rust engine
- Populate `ws_first_tid` from WS trade tracking

## Deviations from Plan

None - plan executed exactly as written.
