Merge feat/offset-histogram-scan: BlastMate serials + the histogram scan

Two things, both starting from the same root cause.

The BW filename encodes the serial NUMBER only; the two-letter family prefix
is not in it. Every offset scanner synthesised "BE", which mislabels the four
BlastMates in the archive (BA9229, BA10060, BA10895, BA15957) and — in the
store's import path — would have filed a BlastMate under a unit that does not
exist. BlastMates are Series III and byte-identical to MiniMate Plus, so the
serial string was the only thing blocking SFM support; reading it from the
file body is the whole fix.

Separately, the archive's 63,535 histograms were scanned for offsets for the
first time. The result is largely a documented dead end — the detector finds
2 of the 5 confirmed units and a clean histogram is not evidence of health —
but it produced the BA10895 reclassification and a labelling caveat on
offset_scan3's spread gate. Journal §8b.
This commit is contained in:
2026-09-06 08:01:52 +00:00
6 changed files with 629 additions and 18 deletions
+9 -1
View File
@@ -30,6 +30,7 @@ from __future__ import annotations
import datetime
import logging
import re
import struct
from typing import Optional
@@ -2532,10 +2533,17 @@ def _decode_0a_partial_header(raw_data: bytes, index: int, key4: bytes) -> Optio
ts2 = try_ts(raw_data[ts1_end + 1:ts1_end + 1 + ts_size])
# Extract serial and geo threshold from "BE11529\0" and "Geo: X.XXX in/s\0".
#
# Match any two-letter family prefix, not a literal "BE" — a BlastMate
# reports "BA10895", and the old `find(b"BE")` returned -1 on one. That
# skipped this whole block, so the geo threshold went missing along with
# the serial. Requiring the NUL terminator in the pattern also makes the
# match stricter than the bare two-byte search it replaces.
serial: Optional[str] = None
geo_ips: Optional[float] = None
serial_pos = raw_data.find(b"BE")
serial_match = re.search(rb"[A-Z]{2}\d{3,6}(?=\x00)", raw_data)
serial_pos = serial_match.start() if serial_match else -1
if serial_pos >= 0:
# Read null-terminated serial starting at serial_pos.
null_pos = raw_data.find(b"\x00", serial_pos)