Skip to content

diag(hrv): size the cross-second R-R over-count with a windowed shadow candidate (#1331/#1118) - #1399

Merged
ryanbr merged 1 commit into
mainfrom
diag/1331-cross-second-dedup-sizing
Aug 17, 2026
Merged

diag(hrv): size the cross-second R-R over-count with a windowed shadow candidate (#1331/#1118)#1399
ryanbr merged 1 commit into
mainfrom
diag/1331-cross-second-dedup-sizing

Conversation

@ryanbr

@ryanbr ryanbr commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Why

The latest #1331 4.0 logs read crossSecondOverCount every night. #1352's shadow de-dup only tests same-second collapses (exact + 40 ms), which by definition can't reach duplicates that straddle the second boundary — so cov40 stays ~1.7–2.0 on the heavy nights, beatAccurate stays ~0.46, and RSA-respiration stays blanked by #1127's 0.5 gate. Nothing currently measures how much of the over-count is cross-second.

What

Adds a third shadow candidate, xsec — the 40 ms collapse widened to a 1-second window — logged beside the existing ones in the hrv dedup line, so a capture shows whether a cross-second collapse would drive coverage → ~1.0 and clear the beat-accuracy gate. collapseOverCount gains a windowSec param (default 0 = same-second, byte-identical for every existing caller).

Deliberately instrumentation-only (not the fix)

The shipped HRV/resp path is unchanged. A cross-second window is a strict UPPER BOUND, not a shippable de-dup: a steady real HR has near-identical intervals one second apart, so it over-merges real beats — the test pins this (a 10-beat steady stream drops to 5 at windowSec=1). The real fix is density/timeline-based and must be validated against ground truth (@artemc's H10) before it touches the read path; this just quantifies the target, matching #1352's "validate before it becomes the read path" pattern.

Verification

  • Both platforms, byte-identical hrv dedup line + twin tests (HrvCollapseOverCount* gets a windowSec case on each side).
  • Android: compiles clean + HrvCollapseOverCount/HrvRrCoverage tests green locally.
  • Swift: StrandAnalytics (swift-packages) covers the function + test; app-target IntelligenceEngine.swift via the app-build gate (below).
  • No shipped-scoring / stored-data / BLE change.

…w candidate (#1331/#1118)

The #1331 4.0 logs read `crossSecondOverCount` every night: the same-second shadow
collapses (#1352's exact + 40 ms candidates) can't reach the duplicate twins
because they straddle the second boundary, so `cov40` stays ~1.7-2.0 on the heavy
nights and RSA-respiration stays blanked by #1127's beat-accuracy gate.

Add a THIRD shadow candidate, `xsec` — the 40 ms collapse widened to a 1-second
window — logged beside the others so we can SIZE how much of a night is
cross-second (does coverage fall to ~1.0, does beat-accuracy clear the 0.5 gate?).
`collapseOverCount` gains a `windowSec` param (default 0 = same-second, byte-
identical for every existing caller).

Instrumentation ONLY — the shipped HRV/resp path is unchanged. The window is a
strict UPPER BOUND, deliberately NOT a shippable de-dup: a steady real HR has
near-identical intervals one second apart, so a cross-second collapse over-merges
real beats (the test pins this: a 10-beat steady stream drops to 5 at window=1).
The real fix is density/timeline-based and must be validated against ground truth
(@artemc's H10) before it becomes the read path — this just quantifies the target.

Both platforms (byte-identical `hrv dedup` line + twin tests).
@ryanbr
ryanbr force-pushed the diag/1331-cross-second-dedup-sizing branch from ba443a1 to 1820100 Compare August 17, 2026 04:01
@ryanbr ryanbr mentioned this pull request Aug 17, 2026
@ryanbr
ryanbr merged commit 7e146ae into main Aug 17, 2026
16 checks passed
@ryanbr
ryanbr deleted the diag/1331-cross-second-dedup-sizing branch August 17, 2026 04:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant