---
phase: 27-stathera-reporting-separation
plan: 01
subsystem: monitoring
tags: [heartbeat, stathera, telegram, clickhouse, kintsugi]

requires:
  - phase: 26-exchange-gap-classification-dismiss
    provides: kintsugi_log exchange_gap classification entries
provides:
  - Pipeline vs exchange gap split in heartbeat Stathera reporting
  - CRITICAL alerts gated on pipeline_gap_count only (exchange gaps informational)
  - Per-symbol pipeline/exchange breakdown in Telegram messages
affects: [heartbeat, stathera, deploy]

tech-stack:
  added: []
  patterns:
    - "Cross-reference kintsugi_log for exchange gap classification"
    - "Backward-compatible state persistence with optional pipeline/exchange fields"

key-files:
  created: []
  modified:
    - scripts/heartbeat/checks/stathera.py
    - scripts/heartbeat/formatter.py
    - scripts/heartbeat/config.py
    - scripts/heartbeat/state.py

key-decisions:
  - "Cap exchange_gaps per pair at total gaps to prevent over-counting when kintsugi_log has stale entries"
  - "Use pipeline_gap_delta (not total gap_delta) for anomalies_growing detection -- exchange gap growth during retroactive classification is expected"
  - "Wrap kintsugi_log query in try/except -- if table unavailable, all gaps treated as pipeline (fail-safe)"

patterns-established:
  - "Pipeline/exchange gap split pattern: query kintsugi_log, cross-reference with Stathera per-symbol, cap at pair total"

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

duration: 2min
completed: 2026-03-28
---

# Phase 27 Plan 01: Stathera Reporting Separation Summary

**Heartbeat Stathera section splits gaps into pipeline_gaps (actionable, CRITICAL) and exchange_gaps (permanent, informational) by cross-referencing kintsugi_log exchange_gap entries**

## Performance

- **Duration:** 2 min
- **Started:** 2026-03-28T00:56:21Z
- **Completed:** 2026-03-28T00:58:30Z
- **Tasks:** 2
- **Files modified:** 4

## Accomplishments

- stathera.py queries kintsugi_log for exchange_gap entries and subtracts from total to compute pipeline_gap_count
- Health gating (stathera_gaps boolean) uses pipeline_gap_count -- exchange gaps alone never trigger CRITICAL
- Formatter shows `pipeline_gaps=N, exchange_gaps=M` with per-symbol `Np + Mx gaps` breakdown
- Reassuring "all gaps are exchange-level (permanent, no action needed)" note when pipeline_gaps=0

## Task Commits

Each task was committed atomically:

1. **Task 1: Query kintsugi_log for exchange gap counts and split Stathera results** - `6644264` (feat)
2. **Task 2: Update formatter to display pipeline_gaps and exchange_gaps separately** - `a092a7a` (feat)

## Files Created/Modified

- `scripts/heartbeat/checks/stathera.py` - Added kintsugi_log exchange_gap query, pipeline/exchange split, updated health gating
- `scripts/heartbeat/formatter.py` - Pipeline/exchange display with per-symbol breakdown and reassuring notes
- `scripts/heartbeat/config.py` - Updated stathera_gaps comment to document v7.2 pipeline-only gating
- `scripts/heartbeat/state.py` - Extended save/load_stathera_counts with pipeline_gap_count and exchange_gap_count

## Decisions Made

- Cap exchange_gaps per pair at pair's total Stathera gaps -- kintsugi_log may have more entries than current gaps if gaps were healed
- Use pipeline_gap_delta for anomalies_growing check -- exchange gap growth during Phase 28 retroactive sweep is expected behavior
- Backward-compatible state persistence: first run after upgrade uses prev_gaps as default for pipeline count, 0 for exchange count

## Deviations from Plan

None - plan executed exactly as written.

## Known Stubs

None.

## Issues Encountered

None.

## User Setup Required

None - no external service configuration required.

## Next Phase Readiness

- Phase 28 (retroactive sweep) can proceed -- exchange_gap classification in kintsugi_log is the prerequisite
- Heartbeat will correctly display pipeline vs exchange split as soon as exchange_gap entries exist in kintsugi_log

## Self-Check: PASSED

- All 4 modified files exist on disk
- Both task commits (6644264, a092a7a) found in git log
- All verification assertions pass

---

_Phase: 27-stathera-reporting-separation_
_Completed: 2026-03-28_
