---
phase: 01-crossover-tid-utility
plan: 01
subsystem: api
tags: [crossover, midnight, sidecar, heartbeat, binance-rest, clickhouse]

# Dependency graph
requires: []
provides:
  - "get_crossover_tid(symbol, date) shared utility in opendeviationbar.crossover"
  - "Date-parameterized CH query (_ch_date_last_tid) instead of hardcoded yesterday()"
affects:
  [02-seeder-day-boundary, 03-kintsugi-parquet-trust, 04-heartbeat-coverage]

# Tech tracking
tech-stack:
  added: []
  patterns: ["shared utility extraction with backward-compatible wrapper"]

key-files:
  created:
    - python/opendeviationbar/crossover.py
    - tests/test_crossover.py
  modified:
    - python/opendeviationbar/sidecar/midnight.py
    - scripts/heartbeat/checks/yesterday.py
    - tests/test_heartbeat_yesterday_junction.py

key-decisions:
  - "Kept backward-compatible _get_midnight_crossover_tid wrapper in midnight.py for sidecar/__init__.py import"
  - "Used date-parameterized CH query with explicit prior_date instead of yesterday() SQL function"

patterns-established:
  - "Shared crossover utility: import from opendeviationbar.crossover, not sidecar internals"

requirements-completed: [XOVER-01, XOVER-02]

# Metrics
duration: 4min
completed: 2026-03-25
---

# Phase 1 Plan 1: Crossover TID Utility Summary

**Shared get_crossover_tid(symbol, date) utility extracted from sidecar internals with 2-tier CH+REST lookup, date parameterization, and backward-compatible sidecar wrapper**

## Performance

- **Duration:** 4 min
- **Started:** 2026-03-25T07:33:05Z
- **Completed:** 2026-03-25T07:37:09Z
- **Tasks:** 2 (TDD task 1 + rewire task 2)
- **Files modified:** 5

## Accomplishments

- Created shared crossover module at `python/opendeviationbar/crossover.py` with public `get_crossover_tid(symbol, date=None)` API
- Removed 213 lines of duplicated crossover logic from sidecar/midnight.py (replaced with 5-line wrapper)
- Removed 44 lines of independent crossover implementation from heartbeat/yesterday.py (replaced with import)
- Date-parameterized CH query enables seeder, kintsugi, and heartbeat to look up any date's crossover TID

## Task Commits

Each task was committed atomically:

1. **Task 1 RED: Failing tests** - `2154d39` (test)
2. **Task 1 GREEN: Crossover module** - `79bb1a3` (feat)
3. **Task 2: Rewire sidecar and heartbeat** - `57c8a68` (refactor)

## Files Created/Modified

- `python/opendeviationbar/crossover.py` - Shared crossover TID utility with 2-tier lookup (CH-seed + API-max) and self-validation
- `tests/test_crossover.py` - 5 unit tests covering midnight_ms computation, default date, CH parameterization, seed validation, WARNING logging
- `python/opendeviationbar/sidecar/midnight.py` - Crossover functions removed, replaced with backward-compatible wrapper delegating to shared module
- `scripts/heartbeat/checks/yesterday.py` - Local crossover function removed, now imports from shared module
- `tests/test_heartbeat_yesterday_junction.py` - Mock path updated to new import location

## Decisions Made

- Kept backward-compatible `_get_midnight_crossover_tid` wrapper in midnight.py so `sidecar/__init__.py` line 141 import continues to resolve
- Used `date - timedelta(days=1)` for CH query parameterization instead of `yesterday()` SQL function, enabling lookups for any date

## Deviations from Plan

None - plan executed exactly as written.

## Issues Encountered

None

## User Setup Required

None - no external service configuration required.

## Next Phase Readiness

- `get_crossover_tid(symbol, date)` is importable from `opendeviationbar.crossover` without any sidecar dependency
- Phases 2-4 can now use this utility for day-boundary completeness checks
- No circular imports: crossover.py imports only from `opendeviationbar._core` and `opendeviationbar.clickhouse.cache`

---

_Phase: 01-crossover-tid-utility_
_Completed: 2026-03-25_
