docs(series4): generate IDF filenames rather than detecting record type

Closes the record-type gap flagged earlier, and corrects the premise behind it.

Series III does NOT detect record type from file content --
event_file_io.derive_record_type_from_filename() reads the last character of
the extension (M529LKIQ.G10H -> H -> Histogram). Nothing in the codebase infers
record type from content, for either family.

Nor is there an obvious type field to find in an IDF: the first 64 bytes of a
histogram and a waveform are byte-identical, and they diverge at ~0x0947 into
wholly different structures rather than differing by a flag.

The answer is the Series III pattern -- generate the name. Series III has
blastware_filename(); Series IV needs the same, and its convention is far
simpler:

    <serial>_<YYYYMMDDHHMMSS>.IDF{W,H}     e.g. UM12947_20260923163319.IDFW

against Series III's <letter><serial3><base-36 stem><AB0T ext>.

All three inputs are already available on a direct download: serial and
timestamp from extract_binary_metadata(), and type from the chain walk (SUB
0x0A returns 0x1E for a histogram, 0x00 for a waveform). Verified on all five
bench events -- generated names match real production-store filenames byte for
byte, so a directly downloaded event can be filed under exactly the name Thor
would have given it and /db/import/idf_file needs no change.

The type still comes from the protocol rather than the payload, so a
downloader must carry it out of the chain walk; losing it means losing the
ability to name the file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ru8Lg9HkkYvX9VWWo65SmL
This commit is contained in:
2026-09-23 19:50:45 -04:00
co-authored by Claude Opus 5
parent 02ed22f561
commit 701af47170
+39 -10
View File
@@ -723,18 +723,47 @@ Read-only, over USB, no Instantel software:
Every event arrived at exactly its declared size, every channel came out equal
length, and the timestamps are sequential across the recording session.
### ⚠ Gap: no content-based record-type discriminator
### Record type + filename: generate it, don't detect it
`read_idf_file()` decides waveform vs histogram from the **filename suffix**
(`.IDFH` / `.IDFW`) — and there is no filename when downloading over the wire.
The first 64 bytes of a histogram and a waveform are **byte-identical**, so the
header does not obviously carry the type either.
`read_idf_file()` decides waveform vs histogram from the **filename suffix** —
and there is no filename when downloading over the wire.
The protocol does supply one: **`SUB 0x0A` returns length `0x1E` for a
histogram and `0x00` for a waveform** (see the event-chain section). Any
direct-download implementation must carry the type from the chain walk rather
than inferring it from the payload, or find the type field inside the IDF
header.
⚠ Worth correcting a natural assumption: **Series III does not detect this from
content either.** `event_file_io.derive_record_type_from_filename()` reads the
last character of the extension (`M529LKIQ.G10H` → `H` → Histogram). Nothing
in the codebase infers record type from file content, for either family.
And there is no obvious type field to find. The first 64 bytes of a histogram
and a waveform are byte-identical; they diverge at ~`0x0947` into wholly
different structures rather than differing by a flag.
**The answer is the Series III pattern — generate the name.** Series III has
`blastware_filename()`, which builds a name from serial + timestamp + type.
Series IV needs the same thing, and its convention is far simpler:
```
<serial>_<YYYYMMDDHHMMSS>.IDF{W,H} e.g. UM12947_20260923163319.IDFW
```
versus Series III's `<letter><serial3><4-char base-36 stem><AB0T ext>`, where
the stem is base-36 of seconds-since-1985 ÷ 1296.
All three inputs are already available on a direct download:
| input | source |
|---|---|
| serial | `extract_binary_metadata()` — decoded from the IDF header |
| timestamp | `extract_binary_metadata()` — same |
| **type** | **the chain walk** — `SUB 0x0A` length `0x1E` = histogram, `0x00` = waveform |
Verified against all five bench events: the generated names match the
convention of real files in the production store byte for byte. A directly
downloaded event can therefore be filed under exactly the name Thor would have
given it, and `/db/import/idf_file` needs no change at all.
⚠ The type still comes from the *protocol*, not the payload — so a downloader
must carry it out of the chain walk. Losing it means losing the ability to
name the file correctly.
### ⚠ Unresolved: the `0x0C` peak float