12 / 14 · audits

Dataset Diff

A forensic diff for spectral datasets: names what kind of change each record underwent and gates the release on it.

figure generated by the instrument itself. hover to let the light in.

The problem

Version control tells you bytes changed; nothing tells you what kind of change a spectral record underwent. A re-measurement carries fresh noise on the same shape, a recalibration is a systematic gain and offset, and silent smoothing of a claimed measurement is a provenance violation wearing the same record id. A curator staring at two 38-number arrays cannot tell these apart by eye, and the distinction is exactly what decides whether the new version of a dataset should ship.

The method

Records are matched by id and each changed pair is classified by its numerical signature. A least-squares gain and offset fit that absorbs nearly all of the change reads as recalibration. Noise-band energy is measured as the residual against a Savitzky-Golay quadratic fit, which passes local curvature exactly while keeping per-sample noise, so a collapse in that band reads as smoothing while preserved noise energy on a near-identical shape reads as renoising, a re-measurement; everything beyond these signatures is a replacement. Every matched record also carries its perceptual impact as ΔE_OK under D65, because a change can be numerically large and perceptually nothing, or the reverse. The corpus verdict is a CI gate: it fails on smoothed records unless smoothing was explicitly allowed, and on records whose appearance moved beyond the stated ΔE budget without being declared replacements.

What it promises

  • Every matched record gets a named verdict, identical, renoised, smoothed, rescaled, or replaced, together with the RMS change, a written justification, and its ΔE_OK under D65.
  • The gate states its reasons: silent smoothing of claimed measurements and undeclared appearance changes each fail it with counts attached, and added or removed record ids are listed in full.
  • Perceptual and numerical change are kept separate on purpose, so a loud edit nobody can see and a quiet edit everybody will see are both caught for what they are.

Calling it

{
  "tool": "diff_spectral_datasets",
  "arguments": {
    "before": [
      {
        "id": "munsell-5R-4-14",
        "values": "<38 samples>"
      }
    ],
    "after": [
      {
        "id": "munsell-5R-4-14",
        "values": "<38 samples>"
      }
    ],
    "allow_smoothed": false,
    "max_perceptual_delta": 0.05
  }
}

Clone the maryslab repo, run cd mcp && npm install && npm run build, then claude mcp add maryslab -- node mcp/dist/server.js

Known limits

  • Classification is a signature match, not a chain of custody: the verdicts come from thresholded numerical fingerprints, and a smoothed curve with realistic synthetic noise added back can read as a re-measurement.
  • Perceptual impact is judged under D65 for the standard observer only; a change that is invisible there can still matter under another light.
  • Both versions must already sit on the canonical 38-sample grid and matching is by record id alone, so a renamed record shows up as one removal plus one addition, not a tracked change.