fix: a loaded recording is filtered into its buffer, not truncated

The loader pushed one slot per file row while the plan decimated by
eight, so a 10 M-row file overran the ring and only its last 4.19 s
survived -- a 20 s recording that read as a 4 s one. Each group of
`time_stride` rows is now averaged into one slot at the group's mean
stamp, as the packet path already does, and the load line reports
rows and decimation so a filtered file cannot be mistaken for a
truncated one.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-10-14 00:54:31 +02:00
1 parent 50a1ddca62
commit 345145c52b
7 files changed
+104 -11

No files matched your search

+11
View File
@@ -63,6 +63,17 @@ Part of [CLAUDE.md](../../CLAUDE.md). These are rules that cost a defect to lear
length. The LOD min/max pyramid still preserves the extremes *of what is stored*; a spike
narrower than a group is now filtered away rather than aliased, which is the correct
trade and is why the status line's `rate` field is worth reading.
- **A file is ingested too, so the loader decimates by the same factor.** `load_waveform_into_model()`
sets the target span to the recording's own length and enables every column, and the plan that
comes back may well decimate: 20 s of 10 channels at 500 kS/s is 480 MB of rings, and the budget is
`--buffer-mb`. The loader therefore reads `partition().time_stride` **after** the enables and pushes
one slot per that many rows, carrying the group's mean at the group's mean stamp — the packet path's
filter, written a second time because a file does not arrive in packets. Pushing every row instead
overruns the ring and leaves the file as **its own tail**, with nothing to say so: a 20 s event
opened as its last 4 s, `stored=10000000` against `published=2097152` in the channel dump, and a
trace that looks like a short recording rather than a truncated one. The `waveform loaded:` line
carries `rows=` and `decim=` beside `samples=` for exactly this reason — `samples * decim == rows`
is the arithmetic that says the whole file is in the buffer.
- **One bad packet is bridged; only a run of them changes the time source.** The stream-time
checks in `build_stamps()` reject three things: stamps that are not finite, a packet with no
span at all, and a packet whose stamps do not advance past the previous packet's last. A