# Requirements Archive: v1.3 Atomic Restart Recovery

**Archived:** 2026-03-21
**Status:** SHIPPED

For current requirements, see `.planning/REQUIREMENTS.md`.

---

# Requirements: v1.3 — Atomic Restart Recovery

**Defined:** 2026-03-20
**Core Value:** Every sidecar restart produces a clean bar chain for today — zero gaps, zero overlaps, zero legacy fragments.

## v1 Requirements

### Atomic Replace

- [x] **ATOM-01**: `_sync_flush_rest_bars()` uses `store_bars_replacing()` to atomically DELETE stale bars in the trade-ID range and INSERT new bars from `fill_from_rest()`
- [x] **ATOM-02**: After sync_flush + engine start, ClickHouse contains exactly ONE bar chain per (symbol, threshold) for today — zero overlaps from prior sessions, verified by Stathera audit

### Legacy Pruning

- [x] **PRUNE-01**: `_inline_startup_backfill()` function deleted from sidecar.py (dead code, never called, superseded by fill_from_rest #286)
- [x] **PRUNE-02**: `_startup_tid_reconciliation()` function deleted from sidecar.py (redundant when fill_from_rest runs; call site in run_sidecar removed)
- [x] **PRUNE-03**: `_gap_fill()` call removed from `_restart_engine_with_recovery()` watchdog restart path (let fill_from_rest handle via \_create_engine)
- [x] **PRUNE-04**: Dead config field `gap_fill_on_startup` removed from `SidecarConfig` and `config/sidecar.py`

### Heal Scoping

- [x] **HEAL-01**: `_heal_day_boundary_gaps()` Stathera query scoped to today's UTC date only (add `AND toDate(open_time_ms/1000) = today()` to WHERE clause)
- [x] **HEAL-02**: `_check_and_heal_overlaps()` call site in main loop uses `valid_pairs` instead of `config.symbols × config.thresholds`

## v2 Requirements

- **ATOM-10**: Extend atomic replace to watchdog restarts (currently only checkpoint-cleared restarts)
- **ATOM-11**: Expose Stathera overlap/gap count in /health endpoint for monitoring

## Out of Scope

| Feature                     | Reason                                                                                            |
| --------------------------- | ------------------------------------------------------------------------------------------------- |
| Midnight-fill approach      | Different processor state = different bar boundaries = RMT can't resolve (git history: 3 reverts) |
| Whole-day DELETE on startup | Tried 3x, reverted 3x — data vacuum for downstream consumers                                      |
| Delayed/timer-based heal    | Irreducible race during CH slowness; no amount of delay is reliable                               |
| Rust-side CH write path     | Would require new PyO3 API + Rust→CH connection; Python path is proven                            |
| Staging table + RENAME      | ClickHouse EXCHANGE TABLES requires identical schema + full table clone                           |

## Traceability

| Requirement | Phase | Status  |
| ----------- | ----- | ------- |
| ATOM-01     | 1     | Complete |
| ATOM-02     | 1     | Complete |
| PRUNE-01    | 2     | Complete |
| PRUNE-02    | 2     | Complete |
| PRUNE-03    | 2     | Complete |
| PRUNE-04    | 2     | Complete |
| HEAL-01     | 1     | Complete |
| HEAL-02     | 1     | Complete |

**Coverage:**

- v1 requirements: 8 total
- Mapped to phases: 8
- Unmapped: 0

---

_Requirements defined: 2026-03-20_
_Last updated: 2026-03-20 after roadmap creation_
