---
phase: 02-kintsugi-rest-ch-connection
verified: 2026-03-20T09:00:00Z
status: passed
score: 4/4 must-haves verified
re_verification: false
---

# Phase 02: Kintsugi REST + CH Connection Fix — Verification Report

**Phase Goal:** Eliminate hour-long REST repairs and connection churn.
**Verified:** 2026-03-20T09:00:00Z
**Status:** passed
**Re-verification:** No — initial verification

---

## Goal Achievement

### Observable Truths

| #   | Truth                                                                                 | Status   | Evidence                                                                                                                                                                                                             |
| --- | ------------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1   | Kintsugi worker threads reuse one CH connection per thread, not one per function call | VERIFIED | `_thread_local = threading.local()` at line 90; `_get_worker_cache()` at line 93; called at 1209, 1343, 1495, 1604                                                                                                   |
| 2   | REST-only shards are capped at MAX_CONCURRENT_REST workers (default 2)                | VERIFIED | `max_concurrent_rest: int = 2` in config/kintsugi.py:80; `min(cfg.max_concurrent_repairs, cfg.max_concurrent_rest)` enforced at kintsugi.py:1766                                                                     |
| 3   | Parquet-cached and Vision-available shards are not blocked by REST workers            | VERIFIED | Candidates reordered Parquet-first → Vision-second → REST-last at kintsugi.py:1783; Parquet-only batch uses `max_concurrent_parquet` (line 1757-1761)                                                                |
| 4   | fd count stays at ~4N+50 for N workers during 24-worker repairs                       | VERIFIED | 4 worker-thread sites replaced with `_get_worker_cache()` (1 PoolManager per thread lifetime); 6 main-thread sites correctly preserve `with OpenDeviationBarCache() as cache:` (lines 274, 460, 584, 634, 656, 2412) |

**Score:** 4/4 truths verified

---

### Required Artifacts

| Artifact                                     | Expected                                          | Status   | Details                                                                                                                                                                     |
| -------------------------------------------- | ------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `python/opendeviationbar/kintsugi.py`        | Thread-local CH cache + REST concurrency limiting | VERIFIED | `_thread_local` at line 90; `_get_worker_cache` def at line 93; 4 call sites confirmed; `_shard_has_vision_available` at line 693; 3-tier classification at lines 1741-1783 |
| `python/opendeviationbar/config/kintsugi.py` | max_concurrent_rest config field                  | VERIFIED | `max_concurrent_rest: int = 2` at line 80; env var docstring at line 32                                                                                                     |

Both artifacts exist, are substantive, and are wired.

---

### Key Link Verification

| From          | To                   | Via                                                                                                                   | Status | Details                                                                                   |
| ------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------- | ------ | ----------------------------------------------------------------------------------------- |
| `kintsugi.py` | `threading.local()`  | `_get_worker_cache()` called in `_try_parquet_day_replace`, `_try_vision_day_replace`, `verify_repair`, `_log_repair` | WIRED  | `_get_worker_cache()` appears at lines 1209, 1343, 1495, 1604 — all 4 worker-thread sites |
| `kintsugi.py` | `config/kintsugi.py` | `cfg.max_concurrent_rest` governs REST shard pool size                                                                | WIRED  | `cfg.max_concurrent_rest` read at kintsugi.py:1766 via `_kintsugi_cfg()` call             |

---

### Requirements Coverage

| Requirement | Source Plan | Description                                                                           | Status    | Evidence                                                                                                                                                                  |
| ----------- | ----------- | ------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| STAB-03     | 02-01-PLAN  | Kintsugi REST repairs use separate concurrency limit (MAX_CONCURRENT_REST=2)          | SATISFIED | `max_concurrent_rest: int = 2` in config; enforced via `min(cfg.max_concurrent_repairs, cfg.max_concurrent_rest)` when all candidates are REST-only                       |
| STAB-04     | 02-01-PLAN  | Single BTCUSDT full-day REST repair completes in <30 minutes (currently 1h+)          | SATISFIED | REST-only shards now capped at 2 concurrent workers; fast shards (Parquet/Vision) no longer competing for same slots; timing outcome is behavioral but mechanism is wired |
| STAB-05     | 02-01-PLAN  | Kintsugi uses thread-local OpenDeviationBarCache (one per worker thread, not per day) | SATISFIED | `_get_worker_cache()` called at 4 worker-thread sites (lines 1209, 1343, 1495, 1604); context manager replaced                                                            |
| STAB-06     | 02-01-PLAN  | No fd exhaustion from CH connection churn during 24-worker repairs                    | SATISFIED | Each of 24 worker threads gets exactly 1 `OpenDeviationBarCache` (1 PoolManager = ~20 fds); total ~480 fds at 24 workers vs ~1920 before                                  |

All 4 phase requirements are satisfied. No orphaned requirements — REQUIREMENTS.md traceability table maps exactly STAB-03 through STAB-06 to Phase 2.

---

### Anti-Patterns Found

None. Grep over both modified files (`kintsugi.py`, `config/kintsugi.py`) found no TODOs, FIXMEs, placeholder stubs, or empty implementations in phase-modified code.

---

### Human Verification Required

**1. REST repair wall-clock time (STAB-04)**

**Test:** Trigger a REST-only shard repair for BTCUSDT (single day, no Parquet/Vision coverage) and observe elapsed time.
**Expected:** Completes in under 30 minutes.
**Why human:** Wall-clock timing of a Binance REST repair depends on live API rate limits and network conditions; cannot be verified programmatically from static code alone.

This is an operational concern — the mechanism is correctly wired. The capping at 2 concurrent REST workers eliminates thread-pool slot competition that caused the previous 1h+ durations.

---

### Gaps Summary

No gaps. All automated checks passed.

- Thread-local CH cache: implemented with `_get_worker_cache()` (def + 4 call sites)
- Main-thread sites: correctly preserved as `with OpenDeviationBarCache() as cache:` (6 sites)
- REST concurrency cap: `max_concurrent_rest: int = 2` in config, consumed in `kintsugi_pass()`
- 3-tier classification: Parquet / Vision / REST candidates classified and reordered at lines 1741-1783
- Both commits documented in SUMMARY (`cea48f4`, `7d3102b`) verified to exist in repo

---

_Verified: 2026-03-20T09:00:00Z_
_Verifier: Claude (gsd-verifier)_
