---
phase: 24-hot-path-allocation-reduction
verified: 2026-03-27T23:15:00Z
status: gaps_found
score: 3/4 must-haves verified
re_verification: false
gaps:
  - truth: "Per-flush ouroboros_mode lookup eliminated — mode resolved from pre-computed symbol_modes dict"
    status: partial
    reason: >
      arrow_flush.py still calls get_symbol_entries() at startup (line 135) and resolves
      per-pair mode via _entries registry lookup (line 159-160) instead of the symbol_modes
      parameter already passed in. The symbol_modes param is only used for the cross-midnight
      Day-mode filter (lines 86-106), not for per-pair ouroboros_mode resolution in the write
      path. The fallback _write_batch_with_retry call (line 181) also omits both cache=
      and ouroboros_mode=, dropping the shared cache and threading a stale default "day" mode.
      Plan acceptance criteria explicitly required: grep -c "get_symbol_entries"
      arrow_flush.py returns 0. Actual: returns 1.
    artifacts:
      - path: "python/opendeviationbar/sidecar/arrow_flush.py"
        issue: >
          get_symbol_entries() still called per sync_flush (line 129/135).
          Per-pair mode uses _entries.get(sym) not symbol_modes (line 159-160).
          Fallback _write_batch_with_retry call missing cache= and ouroboros_mode= args (line 181).
    missing:
      - "Replace _entries/_get_entries() with _modes = symbol_modes or {} for per-pair mode resolution (lines 129-160)"
      - "Use _modes.get(sym, 'day') instead of _e.ouroboros_mode.value for _mode resolution"
      - "Update fallback _write_batch_with_retry call to pass cache=_cache and ouroboros_mode=_mode (line 181)"
---

# Phase 24: Hot-Path Allocation Reduction Verification Report

**Phase Goal:** Eliminate redundant allocations in sidecar startup and per-flush write paths
**Verified:** 2026-03-27T23:15:00Z
**Status:** gaps_found
**Re-verification:** No — initial verification

## Goal Achievement

### Observable Truths

| #   | Truth                                                                                                      | Status   | Evidence                                                                                                                                                                                                                                                                                                                             |
| --- | ---------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 1   | Single OpenDeviationBarCache() instance created in \_create_engine, reused by run_sidecar main loop        | VERIFIED | `ch_cache = OpenDeviationBarCache()` appears exactly once in `__init__.py` (line 221). `return engine, loaded, min_tid_guard, symbol_modes, ch_cache` confirmed. No `with OpenDeviationBarCache() as cache:` blocks remain. `run_sidecar` destructures 5-tuple.                                                                      |
| 2   | \_write_bars_batch_to_clickhouse accepts pl.DataFrame directly without converting to dicts first           | VERIFIED | `bars: pl.DataFrame \| list[dict]` signature confirmed in `clickhouse_write.py` (line 22). `isinstance(bars, list)` dispatch present. `ouroboros_mode: str` param present. `get_symbol_entries` import fully removed.                                                                                                                |
| 3   | Per-flush ouroboros_mode lookup eliminated — mode resolved from pre-computed symbol_modes dict             | FAILED   | `arrow_flush.py` still imports and calls `get_symbol_entries()` (lines 129, 135). Per-pair mode uses `_entries.get(sym)` registry lookup (lines 159-160), not `symbol_modes`. The `symbol_modes` param is used only for cross-midnight filter, not write-path mode resolution. Fallback call missing `cache=` and `ouroboros_mode=`. |
| 4   | arrow_flush.py uses shared cache and pre-computed symbol_modes instead of per-pair cache + registry lookup | PARTIAL  | Cache sharing: VERIFIED (`_cache = cache if cache is not None else OpenDeviationBarCache()` at line 147). Per-pair registry lookup: FAILED (still calls `_get_entries()` for mode, not `symbol_modes`).                                                                                                                              |

**Score:** 3/4 truths verified (Truth 3 FAILED, Truth 4 PARTIAL — same root cause)

### Required Artifacts

| Artifact                                              | Expected                                                                    | Status   | Details                                                                                                                                                                                                                                                                                                      |
| ----------------------------------------------------- | --------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `python/opendeviationbar/sidecar/__init__.py`         | Single cache in \_create_engine, 5-tuple return, symbol_modes threading     | VERIFIED | 5-tuple return confirmed. Zero `with OpenDeviationBarCache` blocks. `_flush_all_batches` uses `symbol_modes.get(symbol, "day")` at line 905 and passes `ouroboros_mode=mode` at line 911. Cache threaded to `_sync_flush_rest_bars` at line 487.                                                             |
| `python/opendeviationbar/sidecar/clickhouse_write.py` | Dual-type bars parameter, ouroboros_mode parameter, cache parameter         | VERIFIED | Both `_write_bars_batch_to_clickhouse` and `_write_batch_with_retry` have `bars: pl.DataFrame \| list[dict]` and `ouroboros_mode: str` params. `get_symbol_entries` fully removed (count=0).                                                                                                                 |
| `python/opendeviationbar/sidecar/arrow_flush.py`      | Shared cache and symbol_modes parameters, no per-pair OpenDeviationBarCache | PARTIAL  | Cache param accepted and shared cache used (VERIFIED). `symbol_modes` param accepted and used for cross-midnight filter (VERIFIED). But per-pair mode resolution still uses `_entries`/`get_symbol_entries()` instead of `symbol_modes` (FAILED). Fallback path missing `cache=` and `ouroboros_mode=` args. |
| `python/opendeviationbar/sidecar/recovery.py`         | 5-tuple destructuring from \_create_engine                                  | VERIFIED | `new_engine, _, new_min_tid_guard, new_symbol_modes, new_ch_cache = _create_engine(...)` at line 54. Returns `new_ch_cache` on success.                                                                                                                                                                      |
| `tests/test_sidecar_alloc.py`                         | Unit tests for ALLOC-01, ALLOC-02, ALLOC-03                                 | VERIFIED | 122 lines, 15 tests. All 15 pass: `...............` 100%. Tests cover all three requirement classes via source-file inspection.                                                                                                                                                                              |

### Key Link Verification

| From                        | To                                         | Via                                                                                                 | Status    | Details                                                                                                                                                                                                                                     |
| --------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sidecar/__init__.py`       | `sidecar/clickhouse_write.py`              | `_flush_all_batches` passes `cache=ch_cache` and `ouroboros_mode=mode` to `_write_batch_with_retry` | WIRED     | Lines 906-911 confirmed. `ouroboros_mode=mode` where `mode = symbol_modes.get(symbol, "day")` at line 905.                                                                                                                                  |
| `sidecar/__init__.py`       | `sidecar/arrow_flush.py` (via midnight.py) | `_sync_flush_rest_bars` receives `cache=ch_cache` at line 487                                       | WIRED     | `__init__.py:487` passes `cache=ch_cache`. `midnight.py:502` forwards `cache=cache` to `_sync_flush_rest_bars_arrow`. `arrow_flush.py:25` accepts `cache`.                                                                                  |
| `arrow_flush.py` write path | `symbol_modes` param                       | Per-pair ouroboros_mode resolved from symbol_modes                                                  | NOT_WIRED | `symbol_modes` is received but used only for cross-midnight filter. Per-pair mode resolution at line 159-160 uses `_entries.get(sym)` (registry). Fallback `_write_batch_with_retry` at line 181 does not pass `cache` or `ouroboros_mode`. |

### Data-Flow Trace (Level 4)

Not applicable — phase modifies write-path plumbing, not data rendering components.

### Behavioral Spot-Checks

| Behavior                                           | Command                                                         | Result                                                              | Status |
| -------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------- | ------ |
| All 15 alloc tests pass                            | `uv run --python 3.13 pytest tests/test_sidecar_alloc.py -x -q` | 15 passed                                                           | PASS   |
| Existing sidecar tests pass                        | `uv run --python 3.13 pytest tests/test_sidecar.py -x -q`       | 4 passed (1 expected UserWarning re: ClickHouse server not running) | PASS   |
| Zero `with OpenDeviationBarCache` in `__init__.py` | `grep -c "with OpenDeviationBarCache" __init__.py`              | 0                                                                   | PASS   |
| Zero `get_symbol_entries` in `clickhouse_write.py` | `grep -c "get_symbol_entries" clickhouse_write.py`              | 0                                                                   | PASS   |
| Zero `get_symbol_entries` in `arrow_flush.py`      | `grep -c "get_symbol_entries" arrow_flush.py`                   | 1 — FAIL                                                            | FAIL   |
| Commits documented in SUMMARY exist                | `git show 7128087 08e2d80 de9f2d8`                              | All 3 confirmed                                                     | PASS   |

### Requirements Coverage

| Requirement | Source Plan   | Description                                                                                              | Status    | Evidence                                                                                                                                                                                                                                                                                                                                                                                              |
| ----------- | ------------- | -------------------------------------------------------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ALLOC-01    | 24-01-PLAN.md | Single `OpenDeviationBarCache()` instance reused across `_create_engine`                                 | SATISFIED | Exactly 1 `ch_cache = OpenDeviationBarCache()` in `__init__.py`. Zero `with OpenDeviationBarCache() as cache:` blocks. 5-tuple return threaded to `run_sidecar` and `recovery.py`.                                                                                                                                                                                                                    |
| ALLOC-02    | 24-01-PLAN.md | `_write_bars_batch_to_clickhouse` accepts Arrow/Polars directly (no dict→DataFrame conversion per flush) | SATISFIED | `bars: pl.DataFrame \| list[dict]` in both `_write_bars_batch_to_clickhouse` and `_write_batch_with_retry`. `isinstance(bars, list)` dispatch. `get_symbol_entries` removed.                                                                                                                                                                                                                          |
| ALLOC-03    | 24-01-PLAN.md | `get_symbol_entries()` cached at sidecar startup, not re-called per flush                                | BLOCKED   | `clickhouse_write.py` SATISFIED: `get_symbol_entries` removed (count=0). `midnight.py` dict path SATISFIED: `_modes = symbol_modes or {}` at line 652, `_mode = _modes.get(symbol, "day")` at line 658. `arrow_flush.py` BLOCKED: `get_symbol_entries()` still called per sync_flush invocation (line 135); per-pair mode resolved from `_entries` registry (line 159-160) instead of `symbol_modes`. |

**Orphaned requirements check:** REQUIREMENTS.md maps ALLOC-01, ALLOC-02, ALLOC-03 to Phase 24 — all three are declared in plan frontmatter. No orphans.

**REQUIREMENTS.md status field:** All three marked "Complete" in REQUIREMENTS.md, but ALLOC-03 is only partially complete — arrow_flush.py retains the registry call.

### Anti-Patterns Found

| File             | Line     | Pattern                                                                                 | Severity | Impact                                                                                                           |
| ---------------- | -------- | --------------------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------- |
| `arrow_flush.py` | 129, 135 | `get_symbol_entries()` called per sync_flush invocation                                 | Warning  | Per-flush registry lookup not eliminated in Arrow path; contradicts ALLOC-03 goal                                |
| `arrow_flush.py` | 159-160  | `_e = _entries.get(sym)` / `_mode = _e.ouroboros_mode.value`                            | Warning  | `symbol_modes` param already available; registry lookup is redundant                                             |
| `arrow_flush.py` | 181      | `_write_batch_with_retry(sym, threshold, bar_dicts)` — no `cache=` or `ouroboros_mode=` | Warning  | Fallback path drops shared cache (creates new one internally) and silently uses "day" default for ouroboros_mode |

### Human Verification Required

None. All critical paths are verifiable via static analysis and test execution.

### Gaps Summary

Three truths verified cleanly: single cache instance (ALLOC-01), dual-type write function (ALLOC-02), and ouroboros_mode threading in the main `_flush_all_batches` path and the dict-based `_sync_flush_rest_bars_dict` in midnight.py (ALLOC-03 partial).

One truth failed: `arrow_flush.py` — the Arrow drain path — still calls `get_symbol_entries()` per sync_flush and resolves per-pair ouroboros_mode from the registry rather than from the `symbol_modes` parameter it already receives. The SUMMARY noted this file was absent from the execution worktree, and the agent applied the cache sharing to `midnight.py` instead. When Phase 23 (arrow_flush.py creation) merged, the file appeared with its own implementation that accepts the `cache` and `symbol_modes` params but doesn't fully thread them through to per-pair write mode resolution.

The fix is localized: replace lines 129-160 in `arrow_flush.py` to use `_modes = symbol_modes or {}` for mode resolution and update the fallback call at line 181 to pass `cache=_cache, ouroboros_mode=_mode`.

---

_Verified: 2026-03-27T23:15:00Z_
_Verifier: Claude (gsd-verifier)_
