Fix false short PCM windows in live speaker matching

Merged
GI
4d ago
+271-18

Fix a deterministic false short-window refusal in live speaker matching: full received PCM spans lost their last sample when epoch-time subtraction was truncated back to bytes. In a receiver-capture/send-proof-to-FIFO-runner reproduction, exactly 2+2+1 seconds of audio produced one extraction and no owner comparison. Preserving the stored span's integer end now delivers all five seconds, three initial queries and an owner decision under the existing policy.

One shared byte-window primitive corrects exact full-span ends for both extraction and physical byte proof. Interior endpoints retain the existing PCM16 floor; actual gaps, eviction and unavailable/unplaced capture windows remain refused. Transient restored-sample metadata stays inside the existing bytes contract; provider timestamps, stored transcript/audio fields, wire formats, thresholds/margins, manual veto, contention, authority/stale-generation fences, FIFO/proven-rejector behavior and recovery ledger are unchanged.

The new omi_speaker_id_pcm_windows_restored_total{reason="full_span_rounding"} counts selected candidate windows whose true received PCM reaches their current extraction floor while the old floored byte count on those selected windows would not. It is emitted before quota admission; it counts neither GPU reservations nor unique voices, owner comparisons, or recognition gains. The single preinitialized closed reason adds one total series (the shared runtime metrics endpoint suppresses created series). No IDs or content are metric labels or new log fields. Recovery's newer pool uses the caller's same floor for this observation, avoiding an insufficient-new-pool/fallback count. Existing #21181/#21235/#21298/#21222 telemetry stays compatible.

Production read-only evidence: source main b8076bab847f, primary listen 6ef38cd; current one-hour aggregate counters show ~34.7k Soniox outside-send refusals, ~20.4k explicitly wire-race-unplaceable intervals, ~7.85k short-window matcher exits. The dominant placement refusals are intentionally fail-closed under an uncertain reported finalize clock. This PR repairs the independent physical-window defect; it does not clamp untrusted provider timestamps, enlarge the ring, alter flags or claim those Soniox intervals are newly placeable. All reads used server-side Prometheus sums plus whitelisted deployment metadata, no account transcripts/audio/embeddings/log rows, no api.omi.me, no deployment or merge.

Request bounds remain twelve initial attempts, at most eighteen with already-approved eligible recovery, 16 tasks and ten seconds of PCM/query, all through the unchanged 16-token socket burst and 240/hour refill. Maximum GPU calls cannot rise beyond those bounds; realized calls can rise as false minimum refusals disappear (the five-second test spends 3 versus 1), or fall if an owner accepts earlier and stops retrying. Failures still spend. Production owner uplift is unmeasured; this is not a forecast that recovers the unplaced cohort. After deployment compare restored candidate windows, short exits, actual reservations/comparisons and owner accepts per conversation; owner_identified excluding single-speaker vs comparable-volume same-hour prior-day baselines, plus failures/contention/GPU.

Validation: new test suite 19 cases (four additional cases after the broader run) and broader 29-file matcher/capture/recovery/authority suite 778 cases pass through credential-stripped backend/test.sh. Before the fix all six complete-span/rate cases plus the real runner failed. Canonical make setup provisioned this worktree's Python 3.11 environment and refreshed the branch to then-current main. Committed head 2c6f61baeaa06c434a72cfe1c06e2d3b7cd2391e passed 32/32 exact-head make preflight in 491.18s and relevant run-unit-ci shard 2/6 passed 5,398 cases across 293 selected files, with zero typecheck errors. Normal push hooks passed, including 32/32 preflight (546.30s), zero-error typecheck, runtime closure, changed-file tests and OpenAPI compatibility. Exact-head GitHub Actions are terminal green: all 12 workflow runs succeeded; all six backend shards, guardrails, E2E/gauntlet and security passed. The first guardrail attempt passed all 2,040 tests then exceeded its 10-minute total job limit during wrap-up; rerunning only that job and its dependent aggregator succeeded on unchanged head, without any timeout/allowlist or source change. The external Cubic check is neutral because its monthly quota is exhausted; no automated review completion is claimed. No skip hatch or force-push.

Failure-Class: new

FC-audio-ring-full-span-rounding-loss records integer whole-span delivery and physical-proof parity with real-runner and gap/partial/eviction guards. The shared byte-window primitive removes the repeated arithmetic cause; this is same-clock quantization, not the existing independent-clock failure class. No existing registry definition or validator changes.

Product invariants affected

none

Reviewer risks: realistic epoch-end correction changes a tiny portion of the PCM and can move a query across an existing evidence floor; actual utilization/timing can change inside unchanged caps. The candidate counter is a comparison against old flooring on currently selected windows, not a historical counterfactual of all scheduler/evidence states or causal recognition saved. Dominant unplaced refusals remain; current diagnostics cannot identify what share of production short exits are true short utterances vs physical truncation vs this rounding defect. New direct regression cases use synthetic audio and mocked embeddings; production identity accuracy is not established. No release/deployment is authorized by this PR.