ADR-01: Compatibility ledger semantics¶
Status: accepted (2026-05-28) Blocks: workstream B (schema additions), workstream E (bridge), workstream F (parity validation)
Context¶
The integration replaces nirs4all’s PipelineRunner + SpectroDataset backend with dag-ml + dag-ml-data. “No regression” must be enforceable, not aspirational. Without a written ledger, every B/D/E task can succeed locally and still miss a public behavior — Codex’s #1 pushback on roadmap v1.
Decision¶
A nirs4all/docs/compatibility.md ledger is the single source of truth for what counts as parity. It enumerates every public API surface with one of the following states:
supported — the bridge reproduces the behavior byte-identical (categorical) or within ADR-declared tolerance (numeric).
changed — the behavior changes; an entry documents the diff, why, and the migration path.
deprecated — kept working for two releases past G6; emits a deprecation warning carrying the target removal version per ADR-14.
refused-with-error — explicitly unsupported; the bridge raises a typed error pointing at the migration ADR.
migration-path — documented procedure to move a workspace / bundle / pipeline from legacy to dag-ml.
Tolerance ledger¶
Numeric comparison tolerances are per model class × per metric:
Model class |
RMSE / MAE |
R² |
Notes |
|---|---|---|---|
Linear (PLS, Ridge, OLS) |
1e-6 |
1e-6 |
deterministic under fixed seed |
Tree ensembles (RF, GBR) |
1e-3 |
1e-3 |
seed-respecting but library-version-sensitive |
Neural networks (NICON, custom TF/PT) |
1e-2 |
1e-2 |
mini-batch shuffle + numerical reductions |
Bit-identical parity is not a goal (Codex hidden risk #4). Tolerance is set per (model class, metric) and pinned in the ledger.
What counts as public API¶
nirs4all.run / predict / explain / retrain / session / generateand their result objects (frozen since 0.9.0 pernirs4all/CLAUDE.md).The pipeline DSL keyword table in
nirs4all/CLAUDE.md.Workspace SQLite/Parquet schemas, run manifest layout,
.n4abundle format.The
examples/reference/*.pyset — examples are API; a broken example is a user-visible regression (Codex hidden risk #5).The CLI subcommand surface (
nirs4all workspace | dataset | artifacts | config).
Consequences¶
Every entry in
nirs4all/CLAUDE.md’s keyword table needs a ledger row before workstream E (bridge) can ship.The parity oracle test set (
nirs4all/tests/integration/parity/) is the executable arm of the ledger — keyword coverage is asserted intest_parity_compiles.py.The bridge raises a typed error referencing this ledger when called on a
refused-with-errorshape.The compatibility ledger is checked into nirs4all (not dag-ml) so it follows the consumer’s release cycle.
Open follow-ups¶
Generate per-case “legacy-observed” parity manifests (Codex Phase-3 review actionable). A scripted run of every runnable parity case captures exact prediction count / variant count / fold-partition shape / best metric / score keys per case, committed alongside the ledger.