New streaming::buffer_trim module with two pure helpers:
- sample_index_for_seconds(end_secs, sample_rate) -> u64: converts
LocalAgreement::last_committed_end_secs() into an absolute sample
index. Defensive against negative end_secs (treats as 0) so a future
clock-skewed timestamp cannot wrap to a huge u64.
- trim_buffer_to_commit_point(buffer, buffer_start_sample,
commit_sample_index) -> new_buffer_start_sample: drains the prefix
of the capture buffer that falls below the commit point and returns
the new absolute-index origin.
Edge cases covered by tests:
- commit before buffer start → no drain
- commit equal to buffer start → no drain
- commit inside buffer → drain prefix, advance origin
- commit at buffer end → drain all, origin moves forward
- commit past buffer end → drain all, origin parks at commit (rare
edge after a committer reset)
- sample_index_for_seconds rounds nearest, negatives clamp to 0
- integration with LocalAgreement::last_committed_end_secs
trim_bounds_buffer_over_long_session is the acceptance fixture for
the ufal #120/#102 failure mode: 100 cycles of 16_000 captured samples
with a 200-sample tentative tail per cycle, and the buffer stays below
2× the tentative envelope instead of growing to 1.6M samples.
Integration into src-tauri/src/commands/live.rs deferred to the
dogfood session that wires VadChunker and LocalAgreement end-to-end —
the trim is a one-line replacement at the maybe_dispatch_chunk drain
site once the committer is feeding it commit points.