v0.13.0 — raw binary ingestion, measured CWRU benchmark, guarded documentation restructure
LatestThree additions. load_signal now opens headerless raw binary waveforms
(.bin, .raw, .dat) when — and only when — the caller declares how to
decode them: vendor-neutral by design, no format parsers ship in the core and
nothing is inferred from file content or names; translating a vendor's
metadata into the declaration is the user's (or an external adapter's) job.
A blind, reproducible CWRU diagnostic benchmark measures the pipeline on
public data and commits the results as a re-runnable, drift-guarded artifact.
And the public documentation is restructured around audience entry paths,
with every count, version, and coverage figure on every public surface
guarded by CI against the code itself.
Added
- Blind, reproducible CWRU diagnostic benchmark (
benchmarks/cwru/,
python -m benchmarks.cwru all). Measures the deterministic diagnostic
pipeline on the CWRU Bearing Data Center 12 kHz drive-end subset (60 fault
records + 4 normal baselines): download-on-demand with vendored SHA-256
pins (fail-closed; no data redistributed), opaque signal ids with a
data-level ops/label split so the scorer is the only label reader,
a symmetric hit criterion (including the CWRU 2×BSF ball-fault convention),
and results stratified by the Smith & Randall (2015) per-record
diagnosability grades. Measured results are committed as a re-runnable
artifact (benchmarks/cwru/results/results.json); README and methodology
numbers are slot-bound to that artifact and drift-guarded by CI-run tests,
alongside executable blindness, checksum and determinism guards. Full
methodology:docs/benchmark-methodology.md. - Raw binary ingestion via declaration parameters on
load_signal.
Additive keyword parameters describe the layout:sample_format
(float32/float64/int16/int32),byte_order(documented default
little),n_channels/channel_index(interleaved extraction; a
multi-channel derived id gains a_ch<k>suffix so channels never
collide),header_offset, and an optionalscale_factor. Required for a
raw file:sample_formatANDsampling_rate— explicit or from the
companion<stem>_metadata.json(explicit wins) — because a headerless
file has zero self-description; a load missing either is refused with ONE
message naming everything missing and both remedies. The declaration is
validated, never trusted blindly: payload-divisibility failures show the
arithmetic (the best detector of a wrong dtype/channel count), and a float
payload decoding to NaN/Inf is refused as a likely endianness/dtype
mismatch. Declaring raw parameters on a self-describing format (CSV, WAV,
...) is refused as a contradiction — no-inference cuts both ways. Integer
formats decode to raw ADC counts;scale_factoris the user's declared
calibration multiplier into the physical unit — without it, declaring a
unit on raw counts would have produced dangerously wrong ISO verdicts. raw_formatprovenance on stored signals. The six EFFECTIVE decode
parameters (after the explicit > companion > default merge) are recorded
onStoredSignalInfo, soget_signal_infocan answer "how was this file
decoded" after the fact instead of leaving the decode contract implicit.PMM_MAX_SIGNAL_SIZEpre-read size cap (bytes, default 500 MB) for
raw loads, checked withstat()before a single byte is read — an
explicit refusal with the env-var remedy instead of an OOM. Read from the
environment at each call (thePMM_SIGNAL_CACHE_GBpattern), so it is
overridable at runtime and testable. The 100 MB figure CLAUDE.md promised
was never implemented and is too low for legitimate captures (1 h at
25.6 kHz float32 ≈ 368 MB). Extending the cap to the other formats is
follow-up work.docs/TOOL_CATALOG.md— the complete endpoint reference. The full
tool/prompt catalog migrated out of the README onto a dedicated page,
guarded by CI against the registered surface: the set of listed names
must equal the registered endpoints exactly, so the catalog can neither
list a phantom endpoint nor silently omit a real one.docs/ADAPTER_GUIDE.md— external adapter guide. Documents how an
external adapter translates vendor metadata into theload_signal
declaration and companion-file parameters. The guide's parameter table —
names, allowed values, defaults, required flags — is guarded by CI
against the code's own exports, in both directions.
Changed
- README restructured around audience entry paths. Readers are routed
by goal (use, evaluate, extend, contribute), with the measured-benchmark
section above the fold; the full tool catalog moved to its own page
(docs/TOOL_CATALOG.md), leaving the README a short guarded summary.
Fixed
.datwas listed but unloadable. The extension sat in
SUPPORTED_EXTENSIONS— solist_signals(scope="disk")showed such
files — but no loader branch existed, so every load failed..datis now
raw-eligible on the same terms as.bin/.raw: it loads with a declared
decode contract and is refused with the full remedy message without one.- Stale public claims corrected and guarded. Endpoint counts, the
plugin skill count, the landing page's software version, and the test
coverage figure (now stated as the CI-enforced minimum rather than a
measured snapshot) had drifted on public surfaces; the CI guards now
scan every copy on every public surface, so the next drift goes red
instead of shipping.
Security
- Path-containment tests extended to raw reads: relative traversal,
Windows backslash traversal, and sibling-directory escapes with.bin
paths are asserted rejected on the same closed-oracle terms as the
existing formats (refusals reveal neither external file content nor
directory listings).