# Phase 29: DELETE Strategy + Exchange Gap Floor - Context

**Gathered:** 2026-03-28
**Status:** Ready for planning
**Mode:** Auto-generated (infrastructure phase — discuss skipped)

<domain>
## Phase Boundary

Spike the safest DELETE strategy for sidecar restart and implement exchange gap floor in the resume TID logic. The DELETE phase currently takes ~6 minutes for 42 partitions with `mutations_sync=1`. The goal is to find an approach that: (1) completes in under 60 seconds, (2) prefers extra bars over gaps (RMT dedup handles duplicates), (3) clamps resume TID above known exchange gaps from kintsugi_log.

</domain>

<decisions>
## Implementation Decisions

### Claude's Discretion

All implementation choices are at Claude's discretion — pure infrastructure phase. Use ROADMAP phase goal, success criteria, and codebase conventions to guide decisions.

Key context from this session:

- Aion resume logic already deployed in `sidecar/__init__.py` (resume from `min(max(last_agg_trade_id))` per symbol)
- Current DELETE: `ALTER TABLE DELETE IN PARTITION WHERE first_agg_trade_id > resume_tid SETTINGS mutations_sync=1` — 42 partitions × ~8.5s each
- User preference: "We don't mind extra bars, as long as it's safe. Not exaggeratingly large amount."
- Exchange gaps tracked in `kintsugi_log` table with `classification='exchange_gap'`
- Only 2 exchange gaps exist across all history — but floor is needed as guard

</decisions>

<code_context>

## Existing Code Insights

### Key Files

- `python/opendeviationbar/sidecar/__init__.py` — `_create_engine()` Aion startup path (lines 264-374)
- `python/opendeviationbar/sidecar/config_helpers.py` — `_seed_trade_ids_from_clickhouse()` (Aion crossover removed)
- `python/opendeviationbar/kintsugi/repair.py` — exchange gap classification (`_repair_aion()`)

### Current DELETE Strategy

```python
for sym in aion_symbols:
    resume_tid = resume_tids.get(sym)
    for thr in get_thresholds_for_symbol(sym):
        ch_cache.client.command(
            f"DELETE IN PARTITION ('{sym}', {thr}) "
            f"WHERE first_agg_trade_id > {resume_tid} "
            "SETTINGS mutations_sync=1"
        )
```

### Approaches to Spike

1. **Skip no-op DELETEs**: Query max_tid per partition first, skip if max_tid <= resume_tid
2. **Batch DELETE**: Single DELETE across all partitions instead of per-partition loop
3. **No DELETE + OPTIMIZE**: Insert new bars, rely on RMT dedup, OPTIMIZE later
4. **Async mutations**: Drop `mutations_sync=1`, verify after all DELETEs dispatched

</code_context>

<specifics>
## Specific Ideas

No specific requirements — infrastructure phase. Refer to ROADMAP phase description and success criteria.

</specifics>

<deferred>
## Deferred Ideas

None — infrastructure phase.

</deferred>
