# Roadmap

## Milestones

- ✅ **v1.0 Junction Fix** — Phases 1-3 (shipped 2026-03-19) → [archive](milestones/v1.0-ROADMAP.md)
- ✅ **v1.2 Performance** — Phases 1-4 (shipped 2026-03-20) → [archive](milestones/v1.2-ROADMAP.md)
- 🚧 **v1.3 Atomic Restart Recovery** — Phases 1-2 (in progress)

## v1.3 Atomic Restart Recovery

**Goal:** Every sidecar restart produces a clean bar chain for today — zero gaps, zero overlaps, zero legacy fragments — using the proven kintsugi `store_bars_replacing()` pattern.

## Phases

- [ ] **Phase 1: Atomic Replace + Heal Scoping** - sync_flush uses store_bars_replacing(); heal operations scoped to today; Stathera verifies clean chain
- [x] **Phase 2: Legacy Pruning** - Remove dead startup backfill, tid reconciliation, watchdog gap_fill, and dead config (completed 2026-03-20)

## Phase Details

### Phase 1: Atomic Replace + Heal Scoping

**Goal**: Every sidecar restart produces exactly one clean bar chain per (symbol, threshold) for today -- no overlaps from prior sessions, no heal queries hitting historical data
**Depends on**: Nothing (first phase)
**Requirements**: ATOM-01, ATOM-02, HEAL-01, HEAL-02
**Plans:** 2 plans

Plans:

- [x] 01-01-PLAN.md — Atomic replace: \_sync_flush_rest_bars() uses store_bars_replacing() with Polars DataFrame + fallback
- [x] 01-02-PLAN.md — Heal scoping: \_heal_day_boundary_gaps() today-only filter + \_check_and_heal_overlaps() uses valid_pairs

**Success Criteria** (what must be TRUE):

1. After a sidecar restart, `_sync_flush_rest_bars()` atomically replaces stale bars in the trade-ID range via `store_bars_replacing()` -- no manual DELETE needed
2. After sync_flush + engine start, a Stathera audit on today's bars for any (symbol, threshold) pair returns zero overlaps and zero gaps
3. `_heal_day_boundary_gaps()` only queries ClickHouse for today's UTC date -- historical days are never touched by heal
4. `_check_and_heal_overlaps()` operates on `valid_pairs` (actively streaming pairs) instead of the full cartesian product of symbols x thresholds

### Phase 2: Legacy Pruning

**Goal**: Dead restart-gap code paths are removed -- sidecar.py is smaller, config is cleaner, no confusion about which restart mechanism is active
**Depends on**: Phase 1
**Requirements**: PRUNE-01, PRUNE-02, PRUNE-03, PRUNE-04
**Plans:** 2/2 plans complete

Plans:

- [x] 02-01-PLAN.md — Delete dead functions: \_inline_startup_backfill(),\_startup_tid_reconciliation(), \_gap_fill() watchdog call
- [x] 02-02-PLAN.md — Remove dead config: gap_fill_on_startup from SidecarConfig, stubs, CLI, tests

**Success Criteria** (what must be TRUE):

1. `_inline_startup_backfill()` function does not exist in sidecar.py
2. `_startup_tid_reconciliation()` function does not exist in sidecar.py and its call site in `run_sidecar()` is removed
3. `_gap_fill()` is not called from `_restart_engine_with_recovery()` watchdog restart path
4. `gap_fill_on_startup` field does not exist in `SidecarConfig` or `config/sidecar.py`
5. All existing tests pass after removal (no test depends on deleted code paths)

## Progress

| Phase                            | Plans Complete | Status      | Completed |
| -------------------------------- | -------------- | ----------- | --------- |
| 1. Atomic Replace + Heal Scoping | 0/2            | Not started | -         |
| 2. Legacy Pruning                | 2/2 | Complete   | 2026-03-20 |
