07 — Testing Strategy¶
This document specifies how Lensemble is tested: the layered test pyramid, the machine-learning-specific tests that constitute the differentiating verification layer, the ablation ladder realized as CPU-runnable integration tests, the numerical-tolerance policy, and the continuous-integration gates. It is the stable contract for what every change must satisfy before it merges. RFCs hold the rationale for each subsystem; this section names the tests and the properties they pin, and binds each ML test to a named invariant (conventions §7) and the error it forces (conventions §6, 04 — Error Model).
Two non-negotiable principles govern the entire suite:
- Every named invariant
INV-*has at least one test that fails when the invariant is violated. The invariant id appears in the test docstring. Security-critical invariants (INV-RESIDENCY,INV-COMMIT-BINDING,INV-AGG-DETERMINISM) have property tests, not just example tests. - The full unit + property + integration suite runs on CPU with tiny synthetic fixtures. No CI job downloads a model checkpoint, a dataset, or a probe. CUDA-only paths are exercised in a separate, non-blocking nightly job (see §8).
1. The test pyramid¶
The suite is organized into six layers under tests/. Proportions are guidance for where effort and
test count concentrate, not hard quotas. The mapping to the package layout (conventions §1) is given so a
contributor knows where a new test belongs.
┌───────────────────────┐
end-to-end ~3% │ full round lifecycle │ tests/e2e/
├───────────────────────┤
ml-specific ~17%│ gauge / sigreg / dp / │ tests/ml/
│ merkle / determinism │
├───────────────────────┤
integration ~20%│ round SM, eval harness,│ tests/integration/
│ ablation ladder rungs │
├───────────────────────┤
property ~20%│ hypothesis invariants │ tests/property/
├───────────────────────┤
unit ~40%│ pure functions, schemas│ tests/unit/
└───────────────────────┘
regression (cross-cutting) golden values tests/regression/
| Layer | Owns | Directory | Runtime budget (full layer, CPU) |
|---|---|---|---|
| Unit | Pure functions, dataclass/pydantic validation, error construction, hashing, canonicalization | tests/unit/ |
< 60 s |
| Property | Invariant-preserving randomized inputs via hypothesis (conventions §11) |
tests/property/ |
< 120 s |
| Integration | Multi-module flows wired without network: round state machine, eval harness on a toy env, ablation-ladder rungs | tests/integration/ |
< 300 s |
| ML-specific | The mathematical contracts: gauge invariance, anchor pinning, Procrustes, SIGReg, DP, determinism, Merkle, reproducibility | tests/ml/ |
< 300 s |
| Regression | Golden-value snapshots (committed hashes, manifest hashes, drift curves on a fixed fixture) that must not change silently | tests/regression/ |
included above |
| End-to-end | One full simulated federation round through Coordinator/Participant on a synthetic two-participant fixture |
tests/e2e/ |
< 120 s |
Layer boundaries: unit tests touch the filesystem only under tmp_path and build no torch.nn.Module
larger than a 2-layer toy; integration tests spawn no network socket (the coordinator runtime runs
in-process, RFC-0013); ML tests depend on no pretrained
warm-start — a 2-layer linear "encoder" with output dim d=8 exercises the gauge mathematics.
2. ML-specific tests (the differentiating layer)¶
These tests verify the mathematical contracts that make Lensemble correct, not merely runnable. Each is
listed with its file, the property it checks, the invariant it pins (conventions §7), and the error it forces on
violation (conventions §6). Tolerances are defined in §6. All run on CPU with
d small (typically d=8 or d=16).
2.1 Gauge invariance of the objective¶
tests/ml/test_gauge_invariance.py::test_objective_invariant_under_random_rotation
Property: the full objective $\mathcal{L} = \lambda_{\text{pred}}\lVert g_\phi(f_\theta(x_t),a_t) -
\text{sg}[f_\theta(x_{t+1})]\rVert^2 + \lambda_{\text{sig}}\mathrm{SIGReg}A(f\theta(x)) +
\lambda_{\text{anc}}\mathcal{L}{\text{anchor}}$ is unchanged under the gauge transform $f\theta \mapsto
Qf_\theta,\ g_\phi \mapsto Qg_\phi Q^\top$ for a random $Q\in O(d)$ (RFC-0002 §4).
The anchor term ($\lambda_{\text{anc}}>0$) is the only term that breaks the symmetry by design, so this
test runs in two modes: (a) prediction + SIGReg only ($\lambda_{\text{anc}}=0$) must be invariant to
within rtol_loss; (b) with the anchor active the loss must NOT be invariant (a regression-guard against
an anchor that silently does nothing).
def test_objective_invariant_under_random_rotation(rng) -> None:
"""INV: gauge symmetry. Objective with lambda_anc=0 is invariant under Q in O(d)."""
Q = random_orthogonal(d=8, rng=rng) # Haar-distributed via QR of a Gaussian
base = objective(f, g, batch, lambda_anc=0.0)
rot = objective(rotate_encoder(f, Q), conjugate_predictor(g, Q), batch, lambda_anc=0.0)
assert math.isclose(base.total, rot.total, rel_tol=RTOL_LOSS, abs_tol=ATOL_LOSS)
Property variant: tests/property/test_gauge_property.py draws many random $Q$ via hypothesis and
asserts invariance over the distribution (catches non-generic $Q$ that an example test would miss).
2.2 The anchor pins the frame¶
tests/ml/test_anchor.py::test_landmark_anchor_recovers_identity
Property (Variant A, RFC-0002 §4): with $k \ge d$ generic
landmark points and fixed targets $t_i = f_{\text{ref}}(p_i)$, the only orthogonal map satisfying all
landmark constraints is $Q\approx I$. Construct $f_{\text{ref}}$, apply a known rotation $Q_0$ to produce a
drifted encoder, minimize $\mathcal{L}{\text{anchor}}$ over an orthogonal correction, and assert the
recovered map drives the probe Procrustes rotation back to identity (rotation angle < ANGLE_TOL_DEG).
A companion negative case uses $k < d$ landmarks and asserts the frame is NOT pinned (the constraint is
under-determined), guarding the documented $k \ge d$ requirement (RFC-0004 §3).
Enforces the precondition behind INV-PROBE-PIN: landmark targets derive only from $f{\text{ref}}$.
Companion probe-integrity tests alter targets and hash metadata independently and require load, save,
anchor, drift, and public recomputation to fail closed. They also assert the versioned full digest binds
targets and is device/layout invariant; the separately domain-labelled points-only source fingerprint is
never accepted as the full probe commitment.
2.3 Procrustes closed-form correctness¶
tests/ml/test_procrustes.py::test_procrustes_matches_brute_force
Property: procrustes_align(source, target) -> (Q*, residual) (conventions §5)
returns the closed-form solution $Q^\star = VU^\top$ from the SVD $E_{\text{ref}}^\top f_\theta(\mathcal{P})
= U\Sigma V^\top$. Verify against a small-angle brute-force search in $d=3$: the closed-form residual must
be <= every sampled candidate's residual within RTOL_PROC, and $Q^\star$ must be orthogonal
($\lVert Q^{\star\top}Q^\star - I\rVert_F < ATOL_ORTHO$) with $\det Q^\star = +1$ for the proper-rotation
case. Degenerate-input case: near-equal singular values trigger the conditioning path and must raise
DegenerateProcrustes (conventions §6) rather than return a NaN/non-orthogonal matrix —
see 04 — Error Model §5.3.
2.4 SIGReg statistic correctness¶
tests/ml/test_sigreg.py::test_sigreg_statistic_against_known_samples
Property (RFC-0002 §3, RFC-0008 §6):
the Epps–Pulley characteristic-function statistic (Cramér–Wold), projected onto the shared sketch matrix
$A$ (sketch dim 64, ~17 integration knots — the LeJEPA defaults), is near zero for a large standard-normal
sample and clearly positive for a known non-normal sample (e.g. a uniform or bimodal mixture). Two
asserts: stat(N(0,1) sample) < SIGREG_NULL_TOL and stat(non_normal) > SIGREG_SIGNAL_FLOOR. The shared
$A$ derives from the round sketch seed $s_t$; a second assert checks two participants given the same $s_t$
compute the identical $A$ — this is INV-SKETCH-CONSISTENCY, enforced in model.sigreg /
federation.round, with mismatch surfacing as a ConfigError at round open.
2.5 Aggregation determinism (bitwise)¶
tests/ml/test_aggregation_determinism.py::test_outer_step_is_bitwise_reproducible
Property: INV-AGG-DETERMINISM. Given fixed (committed deltas, round seed, prior global params), the
outer Nesterov step (RFC-0003 §2) is a pure, bitwise-identical
function. Run the aggregation path twice in the same process and once in a fresh subprocess; assert
byte-equality of the resulting flat tensor (torch.equal AND identical safetensors content hash). A
second assert shuffles the input delta order and confirms the fixed reduction order yields the SAME result
(no order-dependence). The self-check that runs each real outer step (conventions §9) is exercised by injecting a
deliberately non-deterministic reduction and asserting it raises NonDeterministicAggregation (conventions §6),
which aborts the round and triggers recompute — never silently averages.
This determinism is also the Phase-1 proof-ready requirement of
RFC-0006 §3.
2.6 DP clip bound¶
tests/ml/test_dp.py::test_clip_enforces_bound
Property: INV-DP-BOUND. After clipping ($\Delta_c \leftarrow \Delta_c\cdot\min(1, C_{\text{clip}}/
\lVert\Delta_c\rVert)$) and before noising, $\lVert\Delta_c\rVert \le C_{\text{clip}}(1 + \text{rtol})$
for every input, including the boundary case $\lVert\Delta_c\rVert = C_{\text{clip}}$ and a zero vector
(no division by zero). hypothesis draws delta vectors across magnitudes. A companion test asserts the
Gaussian noise is calibrated to $\sigma C_{\text{clip}}$ (empirical std over many draws within RTOL_DP)
and that clipping itself is deterministic given the input. These are primitive/mechanism tests; they do
not make the current shared-seed replay path effective DP. Target budget exhaustion is tested in
tests/integration/test_dp_accountant.py: the accountant raises PrivacyBudgetExceeded (conventions §6) when the
planned $(\varepsilon,\delta)$ is spent, stopping training rather than continuing —
RFC-0012 §Testing Strategy.
2.7 Residency guard refuses to emit raw data¶
tests/ml/test_residency.py::test_residency_guard_fails_closed
Property: INV-RESIDENCY, security-critical. The guard in data.residency MUST refuse to serialize a raw
observation, action, or private-data embedding into any outbound message or artifact. The test attempts to
place each forbidden tensor type into an Update payload and an outbound artifact header and asserts each
attempt raises ResidencyViolation (conventions §6). ResidencyViolation is fail-closed and is on the
never-swallow list — a paired test asserts no except in the egress path catches it. A permitted-payload
case confirms hashes, L2 norms, shapes, and scalar counts pass the guard (so the guard is not vacuously
rejecting everything). Cross-referenced by 05 — Observability §5 and
06 — Security §3.
2.8 Merkle root and inclusion proofs¶
tests/ml/test_merkle.py::test_merkle_root_and_inclusion
Property: the dataset Merkle root $R_c$ over domain-separated episode-leaf hashes is correct and stable,
and every committed episode has a verifying inclusion proof (RFC-0014).
Asserts: (a) the root is invariant to recomputation (deterministic); (b) a valid inclusion proof verifies;
(c) a tampered leaf or a proof for a non-member episode fails verification with MerkleVerificationError
(conventions §6); (d) leaf and node domain separation differ so a leaf hash can never be confused with an internal
node. Binding is tested separately: a PseudoGradient bound to the wrong dataset_root is rejected with
CommitmentMismatch (INV-COMMIT-BINDING, never swallowed), in
tests/integration/test_commit_binding.py.
2.9 Checkpoint hash round-trip and tamper detection¶
tests/ml/test_checkpoint.py::test_checkpoint_hash_roundtrip_and_tamper
Property: INV-CHECKPOINT-HASH. A Checkpoint written and re-read yields identical tensors (safetensors,
conventions §8/§11) and an identical SHA-256 content_hash over the canonical byte serialization, across two
processes (cross-platform stability of the canonicalization, RFC-0010).
A flipped byte in the weight file or a mutated header field causes the recomputed hash to differ from the
committed hash and raises CheckpointIntegrityError (conventions §6). A separate assert confirms the loader
refuses any non-safetensors (e.g. pickle) payload — no arbitrary-code-execution path
(06 — Security §7).
2.10 Schema round-trip and migration¶
tests/ml/test_schema.py::test_schema_roundtrip_and_migration
Property: every on-disk pydantic v2 model (RunManifest, DatasetCommitment, ModelArtifact header,
EvalReport, FrameDriftReport, ContributionRecord; conventions §8) round-trips JSON without loss and carries an
integer schema_version. A reader given an older schema_version migrates it via the registered migration
function; a reader given an unknown/too-new version raises SchemaVersionMismatch (conventions §6, conventions §10). The
test parametrizes over each schema and over (current, current-1, current+1) versions.
2.11 Reproducibility — same seed, same manifest hash¶
tests/ml/test_reproducibility.py::test_same_seed_same_manifest_hash
Property: same LensembleConfig + same root seed ⇒ identical RunManifest config-hash and seed-derivation,
and per-round sketch seeds $s_t = \mathrm{derive}(\text{root_seed}, t)$ are deterministic (conventions §9,
RFC-0009). Two runs of a tiny single-site
train_local config produce identical config/seed hashes in their manifests. With the determinism flag
(torch.use_deterministic_algorithms) set, the aggregation-path outputs are bitwise identical across the
two runs (reusing the §2.5 assertion). Anchors INV-WARMSTART-T0 at the unit level: a round-0 encoder load
test asserts every participant's encoder weights are hash-identical to the pinned warm-start before any
local step.
2.12 WMCP conformance¶
tests/ml/test_wmcp.py::test_latent_state_and_actionspec_conformance
Property: INV-WMCP. Every LatentState conforms to the pinned wmcp_version — shape (N, d), dtype,
and semantics; a malformed latent (wrong rank, wrong d, wrong dtype) raises ContractViolation (conventions §6,
RFC-0007). Every ActionSpec is validated before an action head
is constructed; an invalid spec raises ContractViolation. A two-embodiment fixture (a quadruped and a
7-DoF arm) confirms both conform to one shared latent contract while their action heads differ. Paired
assert for INV-ACTIONHEAD-LOCAL: an attempt to include an action head $h_\psi^{(c)}$ in an outbound
aggregation payload is rejected (it is never broadcast or aggregated).
3. The ablation ladder as integration tests¶
The ablation ladder (RFC-0005 §6) is the core scientific experiment. Each
rung is also a CPU-runnable integration test on a tiny synthetic federation (two to four toy participants,
d small, a synthetic probe), wired through Coordinator/Participant in-process. The tests assert the
qualitative ordering the science predicts, not paper-grade numbers — they are smoke-and-monotonicity guards
that the mechanisms compose, runnable in CI.
tests/integration/test_ablation_ladder.py:
| Rung | Mechanism added | Test assertion (synthetic, CPU) |
|---|---|---|
| 1 | Naive end-to-end FedAvg (no gauge control) | On synthetically rotated silos, the frame-drift diagnostic INCREASES over rounds (the negative control diverges). |
| 2 | + shared sketch matrix $A$ (RFC-0002 §3) | All participants compute the identical $A$ from $s_t$ (INV-SKETCH-CONSISTENCY); drift behavior unchanged (Layer 1 does NOT close the gauge — an explicit assert that drift is still high). |
| 3 | + Procrustes align-then-average (RFC-0002 §5) | Post-alignment inter-participant residual drops at aggregation; the backstop fires only when drift exceeds threshold. |
| 4 | + frame-anchor loss, Variant A (RFC-0002 §4) | Frame drift stays flat/low across rounds where rung 1 diverged. This is the expected recommended configuration. |
| 5 | + function-space distillation (RFC-0002 §6) | Aggregating behaviors on the probe produces a gauge-invariant consensus; drift is low by construction. |
tests/integration/test_lambda_anc_sweep.py realizes the $\lambda_{\text{anc}}$ sweep
(RFC-0002 §7) on the toy federation: it asserts the
monotone trade-off direction — very large $\lambda_{\text{anc}}$ pins the frame hard (drift near zero) at
the cost of representational freedom, very small $\lambda_{\text{anc}}$ lets drift grow — so the
drift-vs-quality curve has the predicted shape. The full quantitative sweep is a Stage-B experiment, not a
CI test; see RFC-0005 §6.
tests/integration/test_eval_harness.py: the latent-MPC eval harness (RFC-0005 §3)
runs end-to-end on a toy stable-worldmodel-style synthetic env with a CEM planner over a 2-step horizon;
asserts evaluate(...) returns a well-formed EvalReport with a finite success_rate, deterministic under
a fixed seed and pinned probe hash. The individual metric implementations (frame-drift, effective
dimension, success rate, communication bytes) each get a unit test in tests/unit/test_metrics.py
(05 — Observability §2).
tests/integration/test_non_iid_partition.py: confirms the factor-of-variation partition produces
controlled, reproducible heterogeneity across silos (same seed ⇒ same partition) so the non-IID sweep
(RFC-0005 §7) is deterministic.
4. End-to-end and round-lifecycle tests¶
tests/e2e/test_full_round.py wires one complete simulated federation round through the public surface
(conventions §5): Coordinator.run(num_rounds=1) over two in-process Participants on a synthetic fixture, with
clip/noise and aggregation mechanism plumbing, the frame anchor, and a hash-committed result. It asserts the round state
machine traverses OPEN → COLLECTING → AGGREGATING → ALIGNING → COMMITTING → CLOSED
(RFC-0013), that INV-RESIDENCY holds across the round (no raw
tensor in any message — reuses the §2.7 guard), and that the committed global hash matches the
RoundClose hash (INV-CHECKPOINT-HASH).
tests/integration/test_secure_agg.py (RFC-0011 §Testing Strategy):
mask cancellation correctness (the revealed sum equals the plaintext sum within exact integer/RTOL_AGG
bound), dropout recovery above the threshold succeeds and below it raises SecureAggregationError (conventions §6),
and a no-individual-leak property check. Masking must not perturb the determinism of the revealed sum
(INV-AGG-DETERMINISM), asserted by composing with §2.5.
Those tests establish primitive behavior. They do not establish that the live optimizer consumes a secure sum: the current coordinator commits from plaintext updates and reports the backend result only afterward.
tests/integration/test_recompute_alignment.py is the Phase-1 proof-readiness test
(RFC-0006 §4): recompute_alignment (conventions §5) reproduces the
coordinator's frame alignment from the public probe + committed weights alone, bit-for-bit, with no access
to private data. This makes the alignment publicly recomputable and needs no proof
(RFC-0002 §5). A ProbeError is raised if the probe content
hash differs from the hash committed in RoundOpen (INV-PROBE-PIN).
5. Module-boundary and import tests¶
tests/unit/test_module_boundaries.py asserts the dependency layering of
01 — Architecture holds and that there are no import cycles. It walks the import
graph of the lensemble package and fails if a forbidden edge appears, e.g. contracts importing
federation, or model/gauge importing anything outside {contracts, config, errors, observability}.
This keeps the documented layering (RFC-0001 §Testing Strategy) machine-
enforced rather than aspirational. A companion assert confirms the public re-exports in
lensemble/__init__.py match the surface in 02 — Public API (no accidental
public-symbol drift) and that nothing prefixed _ or under _internal is re-exported.
6. Numerical-tolerance policy¶
ML tests compare floating-point quantities; the policy below states where exact equality is required and
where approximate equality applies. Tolerances are named constants in tests/conftest.py so they are set
in one place and cited by id, not scattered as magic numbers.
| Quantity | Comparison | Tolerance (constant) | Rationale |
|---|---|---|---|
| Aggregation / outer-step output | Exact (torch.equal, identical content hash) |
none — bitwise | INV-AGG-DETERMINISM; the proof-ready path (conventions §9) must be reproducible bit-for-bit |
| Checkpoint / Merkle / manifest hashes | Exact (string equality) | none | INV-CHECKPOINT-HASH, INV-COMMIT-BINDING; hashes are discrete |
| Schema round-trip | Exact (structural equality) | none | JSON is lossless for the typed fields |
SIGReg null statistic on N(0,1) |
Approximate, upper-bounded | SIGREG_NULL_TOL = 5e-2 |
finite-sample statistic; loose by design |
| SIGReg signal floor on non-normal | Approximate, lower-bounded | SIGREG_SIGNAL_FLOOR = 1e-1 |
must be clearly separated from the null |
| Objective gauge-invariance loss | Relative | RTOL_LOSS = 1e-5, ATOL_LOSS = 1e-6 (fp32) |
fp32 accumulation (conventions §9); rotation is exact in real arithmetic, error is roundoff |
| Procrustes residual / orthogonality | Relative / Frobenius | RTOL_PROC = 1e-5, ATOL_ORTHO = 1e-5 |
SVD roundoff |
| Recovered rotation angle (anchor) | Absolute, degrees | ANGLE_TOL_DEG = 1.0 |
optimization residual on a toy problem |
| DP clip bound | Relative, upper-bounded | RTOL_DP = 1e-6 |
INV-DP-BOUND; clip is a scalar multiply |
| DP empirical noise std | Relative | RTOL_DP_STD = 1e-1 |
sampling variance over a finite draw |
| bf16 forward vs fp32 reference | Relative | RTOL_BF16 = 1e-2, ATOL_BF16 = 1e-2 |
bf16 has ~3 decimal digits; compute dtype default (conventions §9) |
| Secure-agg revealed sum | Relative (or exact for integer masks) | RTOL_AGG = 1e-6 |
float masking roundoff; integer masking is exact |
Rule: any test that compares the aggregation path, a hash, or a schema uses exact equality. Approximate equality is permitted only for genuinely continuous quantities, and the tolerance must be a named constant with the rationale above. New tolerances require an entry in this table.
RISK: the cross-platform stability of content_hash (conventions §8, RFC-0010)
depends on a fixed canonical byte ordering of the safetensors payload. If the canonicalization is
under-specified, §2.9 may pass on the development platform and fail on another. Resolution plan: pin the
exact canonical-byte ordering in RFC-0010 and run §2.9 on both an x86-64 and an arm64 CI runner in the
nightly job before the v0.1 release gate. Owner @AbdelStark, resolved in Stage A.
7. Test fixtures and data discipline¶
- No large downloads. Tests never fetch the V-JEPA 2 warm-start, a real dataset, or a real probe
(conventions §11). A
tiny_warmstartfixture is a 2-layer linear encoder withd=8; asynthetic_probeis a small deterministic tensor with $k \ge d$ landmarks; atoy_envis an in-memorystable-worldmodel-style environment with a closed-form transition. - Determinism in fixtures. Every fixture takes the test's seeded
rng; none calls a global RNG, so the property layer is reproducible on failure (hypothesisderandomizes on replay). - Episode fixtures cover all three formats round-trip —
lance(default),hdf5(portable), and alerobot://adapter stub — intests/integration/test_data_formats.py(RFC-0004). The matrix skips a variant whose optional dependency is absent, but at least one format always runs. - Redaction fixtures for 05 — Observability: a test sink that records everything
written;
tests/ml/test_redaction.pyasserts no raw observation/action/embedding tensor ever reaches the sink (INV-RESIDENCY), only hashes, norms, shapes, counts, and scalar metrics. The redaction guard fails closed.
8. CI gates¶
Every push and pull request runs the blocking gate below on CPU. The pipeline configuration and the relationship to release tagging are owned by 09 — Release & Versioning; this section states what must be green to merge.
Blocking gates (ordered; fail fast):
- Lint —
ruff checkandruff format --check(conventions §11). Zero findings. - Type-check —
pyright(conventions §11) onlensemble/andtests/. Zero errors. - Unit + property —
pytest tests/unit tests/propertyon CPU. All pass;hypothesisruns with a fixed profile (deadline disabled, derandomized for replay). - Integration + ML + e2e —
pytest tests/integration tests/ml tests/e2eon CPU. All pass. - Determinism check — a dedicated job that runs §2.5 in two processes and asserts bitwise equality of
the aggregation path. Any drift fails the build (
INV-AGG-DETERMINISM). - Coverage threshold — line coverage
>= 85%overall and100%ondata.residency,aggregation.secure_agg(the reveal path),provenance.commit, andprivacy.dp(the security-critical modules). Below threshold fails the build. - Docs link-check — every relative cross-reference in
docs/(the convention of conventions §3) resolves to an existing file and, where a#anchoris used, to an existing heading. Broken links fail the build.
Non-blocking nightly jobs:
- CUDA suite — the GPU-only paths (FSDP/TP inner loop, differentiable SVD on CUDA,
torch.use_deterministic_algorithmson GPU). Failures open an issue; they do not block merges, because CI runners are CPU-only and tests MUST pass on CPU (conventions §9). - Cross-platform hash check — §2.9 on x86-64 and arm64 runners (see the
RISK:in §6). - Performance smoke — the tiny-config wall-time ceiling that guards against perf regressions; the budget and its measurement live in 08 — Performance Budget.
What CI explicitly does NOT do: download any model/dataset/probe; require a GPU for a blocking gate; run the full ablation sweep or non-IID/scale sweeps (those are Stage-B research runs, RFC-0005 §6–7, reproduced from the released configs, not CI gates).
9. Coverage of invariants (traceability matrix)¶
Every invariant in conventions §7 maps to at least one test. This matrix is the audit substrate: if an invariant lacks a row, the suite is incomplete.
| Invariant | Test(s) | Error on violation |
|---|---|---|
INV-RESIDENCY |
§2.7, §7 redaction, §4 e2e | ResidencyViolation (fail-closed) |
INV-WARMSTART-T0 |
§2.11 round-0 load | (assertion; mismatch is a ConfigError at load) |
INV-SKETCH-CONSISTENCY |
§2.4, ladder rung 2 | ConfigError at round open |
INV-AGG-DETERMINISM |
§2.5, gate 5, §4 secure-agg | NonDeterministicAggregation |
INV-PROBE-PIN |
§2.2, §4 recompute | ProbeError |
INV-COMMIT-BINDING |
§2.8 binding | CommitmentMismatch |
INV-CHECKPOINT-HASH |
§2.9, §4 e2e | CheckpointIntegrityError |
INV-DP-BOUND |
§2.6 | (assertion; budget exhaustion is PrivacyBudgetExceeded) |
INV-WMCP |
§2.12 | ContractViolation |
INV-ACTIONHEAD-LOCAL |
§2.12 paired | ResidencyViolation / ContractViolation on outbound attempt |
10. Open questions¶
OPEN QUESTION: the coverage threshold for the non-security modules (currently >= 85%) may be too low for
the gauge and aggregation math, where a missed branch can silently degrade the science rather than crash.
Owner @AbdelStark; resolution: revisit per-module thresholds after the Stage-B ablation suite stabilizes
(milestone v0.2), raising gauge and aggregation toward 100% if the math paths prove brittle.
OPEN QUESTION: whether the ablation-ladder integration tests (§3)
should assert quantitative drift thresholds on the synthetic fixture, or remain qualitative
monotonicity/ordering checks. Quantitative thresholds risk flakiness from optimizer noise on a toy problem;
qualitative checks risk passing while the real mechanism is subtly wrong. Owner @AbdelStark; resolution:
decide after the Stage-B frame-drift diagnostic (RFC-0005 §2) is
characterized on real silos (milestone v0.2), then back-port a calibrated threshold into the synthetic test.
OPEN QUESTION: the drift threshold that fires the Layer-3 Procrustes backstop in the ladder rung-3 test
inherits the same open value as RFC-0002 §Open Questions. Until
that value is set in Stage B, the rung-3 test uses a fixture-local threshold and asserts only the
fire/no-fire behavior, not the production value. Owner @AbdelStark; resolution: adopt the Stage-B value
once RFC-0002 fixes it (milestone v0.2).
11. References¶
- Conventions document: §6 (error taxonomy), §7 (invariants), §9 (determinism/dtype/device), §11
(dependencies:
pytest,hypothesis,pytest-benchmark,ruff,pyright), §12 (milestones). - RFCs (each RFC's Testing Strategy section is the source for the corresponding tests above): RFC-0001 (module-boundary, round lifecycle), RFC-0002 (gauge invariance, anchor, Procrustes, $\lambda_{\text{anc}}$ sweep, drift diagnostic), RFC-0003 (state machine, pseudo-gradient, int8 round-trip), RFC-0004 (residency, format round-trip, probe pin), RFC-0005 (ablation ladder, baselines, metrics, reproducibility), RFC-0006 (proof-readiness: determinism, recompute, binding, pinned probe), RFC-0007, RFC-0008, RFC-0009, RFC-0010, RFC-0011, RFC-0012, RFC-0013, RFC-0014, RFC-0015.
- Sibling spec sections: 01 — Architecture, 02 — Public API, 03 — Data Model, 04 — Error Model, 05 — Observability, 06 — Security, 08 — Performance Budget, 09 — Release & Versioning.