# SPDX-License-Identifier: AGPL-3.0-or-later
# Commercial license available
# © Concepts 1996–2026 Miroslav Šotek. All rights reserved.
# © Code 2020–2026 Miroslav Šotek. All rights reserved.
# ORCID: 0009-0009-3560-0851
# Contact: www.anulum.li | protoscience@anulum.li
# SCPN Fusion Core — Exactness-class reproduction comparator (fleet WS-2)
"""The exactness-class reproduction comparator — FUSION's WS-2 reference implementation.
The fleet honesty model says an in-browser recompute "matches" a committed claim, but its two
pins are in tension for floating-point kernels: H2 (digest equality) and H3 (tolerance-aware).
Float kernels are not bit-reproducible across toolchains (x86 / ARM / WASM-SIMD, FMA contraction,
compiler flags, libm), so a *correct* recompute yields a different digest and a naive digest check
fires a false drift alarm. WS-2 resolves this with a per-claim **exactness class** that decides how
the verifier compares:
* ``bit-exact`` — the recomputed value's content digest must equal the committed digest. For
integer / fixed-point / genuinely bit-reproducible kernels (the producer asserts toolchain
independence; CI must cross-check it).
* ``tolerance`` — the recomputed value must match the committed reference value within a band
(``atol + rtol * |ref|``, NumPy ``allclose`` semantics). The band is static ``{rtol, atol}`` or a
scalar reduced from a UQ envelope (``reduce_to_scalar(uq)``, supplied by the producer). For float
kernels — the majority of FUSION and the fleet.
* ``stochastic`` — reproduction needs the committed seed and RNG identity, after which it reduces to
``bit-exact`` or ``tolerance``. (This module compares the reduced form; seeding is the caller's.)
This is a pure comparison function over (recomputed, committed, exactness-class) — no I/O, no
signing (signing is WS-1). It returns an honest verdict, including ``unverifiable`` when the
exactness class is absent, never silently defaulting (a default would false-drift floats or mask a
bit-exact regression). The browser ``@anulum/verify`` lib mirrors this verdict-for-verdict.
"""
from __future__ import annotations
from dataclasses import dataclass
import hashlib
import numpy as np
from numpy.typing import NDArray
# The axis (the exactness-class + verdict vocabulary and the dependency-free bit-exact
# digest compare) is owned by the platform SDK — single source, no N² divergence. FUSION
# re-exports it and adds the numpy tolerance/stochastic numerics behind the shared enums.
from scpn_studio_platform.exactness import (
ExactnessClass,
ReproVerdict,
compare_bit_exact as _sdk_compare_bit_exact,
parse_exactness_class,
)
[docs]
@dataclass(frozen=True)
class ComparisonResult:
"""One reproduction comparison verdict with a human-readable rationale.
Parameters
----------
verdict
The :class:`ReproVerdict`.
detail
A one-line explanation (the band, the digest mismatch, the absent class).
"""
verdict: ReproVerdict
detail: str
@property
def reproduced(self) -> bool:
"""Return whether the recompute counts as an honest reproduction.
``True`` for a bit-exact match or a within-tolerance float recompute; ``False`` for drift
or an unverifiable (un-declared) claim.
"""
return self.verdict in (ReproVerdict.MATCH, ReproVerdict.WITHIN_TOLERANCE)
[docs]
def compare_bit_exact(recomputed_digest: str, committed_digest: str) -> ComparisonResult:
"""Compare two content digests for a bit-exact claim, wrapping the SDK verdict.
The actual digest comparison is delegated to the platform SDK's dependency-free
:func:`scpn_studio_platform.exactness.compare_bit_exact` (the single source for the axis);
this wrapper adds FUSION's :class:`ComparisonResult` rationale so the bit-exact and the
numpy tolerance paths return one consistent type.
Parameters
----------
recomputed_digest
The ``sha256:<hex>`` digest of the in-browser recompute.
committed_digest
The committed claim's digest.
Returns
-------
ComparisonResult
``MATCH`` on exact digest equality, else ``DRIFT`` (loud, tamper-evident).
"""
verdict = _sdk_compare_bit_exact(recomputed_digest, committed_digest)
if verdict is ReproVerdict.MATCH:
return ComparisonResult(verdict, "bit-exact digest equality")
return ComparisonResult(
verdict,
f"bit-exact digest mismatch: {recomputed_digest!r} != {committed_digest!r}",
)
def _finite_aware_close(
recomputed: NDArray[np.float64],
reference: NDArray[np.float64],
*,
rtol: float,
atol: float,
) -> bool:
"""Return whether two arrays agree within tolerance, treating NaN≡NaN and ±Inf by sign.
IEEE ``NaN != NaN`` and ``inf - inf = nan`` would make :func:`numpy.allclose` reject a faithful
reproduction of a result that legitimately contains non-finite values, so non-finite positions
are matched structurally (same NaN mask, same signed-infinity mask) and only the finite
positions are compared within ``atol + rtol * |reference|``.
"""
if recomputed.shape != reference.shape:
return False
nan_a, nan_b = np.isnan(recomputed), np.isnan(reference)
if not np.array_equal(nan_a, nan_b):
return False
posinf_a, posinf_b = np.isposinf(recomputed), np.isposinf(reference)
neginf_a, neginf_b = np.isneginf(recomputed), np.isneginf(reference)
if not (np.array_equal(posinf_a, posinf_b) and np.array_equal(neginf_a, neginf_b)):
return False
finite = ~(nan_a | posinf_a | neginf_a)
if not np.any(finite):
return True # all positions non-finite and structurally matched
return bool(
np.all(
np.abs(recomputed[finite] - reference[finite])
<= atol + rtol * np.abs(reference[finite])
)
)
[docs]
def compare_tolerance(
recomputed: NDArray[np.float64] | float,
reference: NDArray[np.float64] | float,
*,
rtol: float = 1.0e-9,
atol: float = 0.0,
) -> ComparisonResult:
"""Compare a recomputed float value/array against a committed reference within tolerance.
Parameters
----------
recomputed
The in-browser recompute (scalar or array).
reference
The committed reference value(s).
rtol, atol
The relative and absolute tolerance band (``atol + rtol * |reference|``). For a
UQ-grounded band, pass ``atol = reduce_to_scalar(uq)`` and ``rtol = 0.0``.
Returns
-------
ComparisonResult
``WITHIN_TOLERANCE`` if the recompute is inside the band, else ``DRIFT``.
Raises
------
ValueError
If ``rtol`` or ``atol`` is negative (a tolerance band must be non-negative).
"""
if rtol < 0.0 or atol < 0.0:
raise ValueError(f"tolerance band must be non-negative, got rtol={rtol!r}, atol={atol!r}")
a = np.asarray(recomputed, dtype=np.float64)
b = np.asarray(reference, dtype=np.float64)
if _finite_aware_close(a, b, rtol=rtol, atol=atol):
return ComparisonResult(
ReproVerdict.WITHIN_TOLERANCE, f"within tolerance (rtol={rtol:g}, atol={atol:g})"
)
return ComparisonResult(ReproVerdict.DRIFT, f"beyond tolerance (rtol={rtol:g}, atol={atol:g})")
[docs]
def canonical_value_digest(value: NDArray[np.float64] | float) -> str:
"""Return a language-independent content digest of a committed reference value series.
For a ``tolerance`` or ``stochastic`` claim, large reference arrays do not belong inline in
the signed envelope; the envelope carries only this digest, and the values live in a side
artifact. The verifier fetches the side artifact, recomputes this digest, and checks it equals
the signed one BEFORE the tolerance compare — so the fetched values are tamper-evident.
The digest is taken over the raw IEEE-754 ``float64`` little-endian bytes, NOT a decimal string
representation, so the producer (Python) and consumer (browser/JS) agree byte-for-byte
regardless of float formatting — it sidesteps the ``json.dumps(1e-6)='1e-06'`` vs JS
``'0.000001'`` divergence entirely (you digest the bytes, not a language-dependent repr).
Parameters
----------
value
The committed reference value(s) (scalar or array).
Returns
-------
str
A ``sha256:<hex>`` digest of the canonical little-endian ``float64`` byte image.
"""
arr = np.ascontiguousarray(np.asarray(value, dtype="<f8"))
return "sha256:" + hashlib.sha256(arr.tobytes()).hexdigest()
[docs]
def reproduce(
exactness_class: ExactnessClass | None,
*,
recomputed_digest: str | None = None,
committed_digest: str | None = None,
recomputed_value: NDArray[np.float64] | float | None = None,
reference_value: NDArray[np.float64] | float | None = None,
rtol: float = 1.0e-9,
atol: float = 0.0,
) -> ComparisonResult:
"""Dispatch a reproduction comparison on the claim's exactness class.
A ``stochastic`` claim must be reduced by the caller (seed the RNG, then pass the reduced
``bit-exact`` or ``tolerance`` class with its payload); passing ``STOCHASTIC`` here is itself an
error because the reduction is the caller's responsibility.
Parameters
----------
exactness_class
The declared class, or ``None`` (which yields ``UNVERIFIABLE`` — never a silent default).
recomputed_digest, committed_digest
Required for ``bit-exact``.
recomputed_value, reference_value
Required for ``tolerance``.
rtol, atol
The tolerance band for ``tolerance``.
Returns
-------
ComparisonResult
The verdict; ``UNVERIFIABLE`` when no class is declared.
Raises
------
ValueError
If the class is ``STOCHASTIC`` (must be reduced first), or the payload required for the
declared class is missing.
"""
if exactness_class is None:
return ComparisonResult(
ReproVerdict.UNVERIFIABLE, "no exactness class declared (absent = loud unverifiable)"
)
if exactness_class is ExactnessClass.STOCHASTIC:
raise ValueError(
"stochastic claims must be reduced to bit-exact or tolerance by the caller "
"(seed the RNG first), then dispatched with the reduced class"
)
if exactness_class is ExactnessClass.BIT_EXACT:
if recomputed_digest is None or committed_digest is None:
raise ValueError("bit-exact reproduction requires recomputed_digest + committed_digest")
return compare_bit_exact(recomputed_digest, committed_digest)
if recomputed_value is None or reference_value is None:
raise ValueError("tolerance reproduction requires recomputed_value + reference_value")
return compare_tolerance(recomputed_value, reference_value, rtol=rtol, atol=atol)
__all__ = [
"ComparisonResult",
"ExactnessClass",
"ReproVerdict",
"canonical_value_digest",
"compare_bit_exact",
"compare_tolerance",
"parse_exactness_class",
"reproduce",
]