test — prove the CP path is correct
Most CP correctness is parity: given identical inputs and weights, the distributed
forward+backward must numerically match the serial reference, which is the only value
oracle (Rule 13) — Steps 1–7 below. But some correctness properties have no serial value
oracle and need a different, property / invariant test (see
§Property tests) — most
notably anything random (RNG / noise), where no distributed RNG reproduces an all-gathered
single-device draw, so only the entropy structure is checkable. Either way: a test that
can pass with a broken implementation is worse than no test — follow the anti-vacuous rules
without exception. The worker skeleton, comparison matrix, and helper inventory are in
reference.md.
Preconditions
docs/cp_infra.md gives the launch recipe + world_size (run build_infra if
not).
- The source under test exists and has a serial twin to compare against.
Step 1 — Choose the level and the test path
| Level |
What it pins |
Compare |
| unit |
one op / autograd.Function |
op output + grad vs serial op |
| layer |
one layer in isolation |
layer fwd+bwd vs serial layer |
| module |
module with real feature inputs (from the shared synthetic DataModule — Step 2.2) |
module fwd+bwd vs serial module |
| workflow |
end-to-end inference or train step |
outputs / loss / weight deltas vs serial |
Test path mirrors the source path:
tests/distributed/<path>/test_dtensor_<file>.py for DTensor tests,
test_<file>.py otherwise. Write the parity test for a new operator before
anything downstream depends on it.
Step 2 — Get test data (real or synthesized)
Prefer real inference/training features if the user can provide them — ask
for a path and the feature format.
Otherwise synthesize through ONE shared synthetic Dataset + DataLoader + DataModule —
not per-test data-gen, and not loose one-off helper functions. Build a single synthetic
data stack in the project's distributed/testing/ subpackage (mirror src/boltz/testing/utils.py
and src/boltz/distributed/testing/):
- a
Dataset whose __getitem__ yields a synthesized input_feature_dict matching §3's
contract (names, shapes, dtypes, axis semantics, masks), with a feature_subset knob;
- a
DataLoader (bs=1 + the production collate);
- a
DataModule that REUSES the production CP distributor (distribute_input_feature_dict
/ the data module's distributor) — never a re-implementation — to emit, for the requested
subset, both the serial (full) and CP (DTensor) views. Every feature is emitted at the
data-feature sharding requirements (the §3 placements / the §4.5 data-feature→consumer
contract), which the reused distributor satisfies by construction — a synthetic
dataset/dataloader/featurizer must never hand-roll placements that violate that contract.
Every test — data, module, and workflow — draws its inputs from this one DataModule and SUBSETS
the feature set its target consumes. The common synth + distribution + divisibility-padding +
atom-index-remap code then lives in exactly one place; tests never duplicate it. Two payoffs:
- Because inputs flow through the real synthesizer + production distributor at the locked
placements, a feature-consuming module test (relative-position encoder, atom encoder, input
embedder, MSA module, diffusion conditioning, …) automatically exercises the featurizer→module
seam (Rule 4) and the featurizer's value semantics (valid ranges, coupled-feature
consistency, monotone indices) — drift is caught at the unit level, not deferred to the
workflow test. Do not hand-roll data features with ad-hoc
torch.randint/randn.
- Keep ad-hoc
randn only for genuine intermediate activations that are not featurizer
outputs (an upstream single/pair representation, a diffusion noise level).
Use the same inputs and weights on the serial and CP sides — load one state_dict into both,
and draw features from the DataModule with one deterministic seed so both sides see identical
inputs. Convert the module to the test dtype (fp64) before load_state_dict to avoid an fp32
round-trip (fold-cp test discipline).
Step 3 — Pre-check on a 1×1 mesh FIRST, then build the multi-rank worker
Before any multi-GPU run, verify the fwd+bwd decomposition on a 1×1 mesh (single
rank / single process, where every collective degenerates to a no-op), in fp64, CP ==
serial. This isolates math / placement-seam / op-order bugs from collective bugs, needs
no GPUs or multi-rank launch, and runs in seconds; a 4-rank 2×2 gloo run is a cheap second
step. Modules that pass this 1×1 pre-check hit multi-GPU parity on the first try —
treat it as routine, not optional. Only then build the multi-rank worker:
- Spawn with
spawn_multiprocessing(worker, world_size, *args) (Boltz testing
utils) or mp.spawn.
- Init the process group with a per-collective timeout (e.g. 60s) so deadlocks
fail fast; build the
DeviceMesh for the selected 2D mesh.
- Monkeypatch the distributed cleanup to a no-op when a test reinitializes groups
in one process (port reuse) — see
tests/distributed/test_dtensor_stop_and_go.py.
- Wrap the worker body in
try/finally to destroy_process_group() and free the GPU on exit;
do not try/except to swallow a rank's error and continue — the throwing rank skips its
remaining collectives and deadlocks the others (broadcast an ok/error sentinel instead — Rule 20).
seed_by_rank(rank) for per-rank inputs that must differ; use a contained
torch.Generator rather than global manual_seed.
Step 4 — Compare against serial (the right reassembly)
| Comparison |
Use |
| DTensor vs serial reference |
full_tensor() to reassemble, then assert_close |
| DTensor vs DTensor (same placements) |
to_local() on both — no communication |
| Gradients (replicated params) |
grad.full_tensor() — Partial(Sum) needs the reduce; to_local() is only this rank's contribution |
Run serial fwd+bwd on full tensors; run CP fwd+bwd on sharded DTensors; compare.
Step 5 — Anti-vacuous assertions (all required)
- Explicit random
grad_output for backward — never .sum().backward()
(uniform grads mask sign/permutation bugs).
- Sharding is active when either 2D mesh axis has size > 1:
local.shape[sharded_dim] < global.shape[sharded_dim] — skip for cp=(1,1)
(a valid debugging mesh where local == global).
- Replicated values identical across ranks (
assert_all_identical).
- Gradients non-zero (and finite).
- Perturb/randomize zero-initialized params first — AF/residual "final" projections
are zero-init, so output and all grads are vacuously zero (
0 == 0 passes).
- Per-PARAMETER grad parity, not only input-grad — for any module with parameters
replicated over a sharded axis, assert
param.grad.full_tensor() vs serial. A replicated
param whose grad is a per-rank partial (missing all-reduce) passes forward + input-grad
parity but is wrong; only the param-grad check catches it.
- fp64 +
assert_close default tolerances. If it only passes after loosening
atol, that is a bug signal — derive the tolerance from the error budget, do not
tune it (Rule 15).
- At least one adversarial/boundary case (a non-power-of-two per-axis 2D mesh such as
cp=(3,3), a padded axis, a single-element shard).
Step 6 — Parametrize and prefer CUDA
One test function parametrized over a tuple of mesh configs (do not copy-paste per
size). Prefer CUDA parametrizations; keep at most one CPU param (e.g. a 3×3 mesh) for
CI path coverage.
Step 7 — Run, with timeout and logs
timeout 120 python -m pytest <test path> -x -q |& tee /tmp/$USER/<name>.log
Make the log self-verifying (Rule 22). Print the evidence on success, not only on
failure: the measured max abs/rel difference and the tolerance, the mesh / world_size, and a
one-line confirmation of each non-vacuous check (sharding-active, replicated-identical, grads
non-zero, per-param-grad). An orchestrator or reviewer then verifies the gate by reading this
log instead of re-running the GPU test (Rule 22) — a silent assert_close that prints nothing on
green forces a needless re-run. Emit the numbers.
Inspect the log even on green (catch silent skips / warnings). When a test fails,
assume the implementation is wrong (Rule 14) — diagnose the CP code; do not weaken
the test.
A second test class: property / invariant tests (not serial parity)
Some correctness properties are not numerical equality to the serial reference — the
serial run is not a value oracle for them. The oracle is a structural invariant the
distributed run must satisfy. Write a property test when:
- the quantity is random / not reproducible across mesh configurations — RNG and noise: no
distributed RNG numerically reproduces an all-gathered single-device draw today, so you
can assert only its entropy structure, not its values; or
- the property is about layout / determinism / consistency rather than numbers — e.g.
replicated values agree across ranks, control-flow counts match, sharding is active.
Canonical example — test_rng_entropy (tests/distributed/test_dtensor_predict.py):
asserts every per-rank RNG draw obeys single-device RNG entropy equivalence (the
fold-cp RNG rule) — sharded-axis draws carry independent entropy (the cp0 diffusion noise
must not tile), replicate-axis draws are identical (via broadcast) — without comparing
to any serial value. Mechanism (skeleton in reference.md):
- run the real workflow (e.g. DP=1, CP=(2,2), smallest sample) under
spawn_multiprocessing;
- monkeypatch the python
random / numpy / torch RNG entry points to fingerprint every
drawn sample per rank, and save the per-rank fingerprints to the test context (one JSON
per rank);
- after the join, in the parent process, assert the invariant across ranks: sizable
sharded draws are pairwise disjoint across ranks (no tiling); replicated draws agree.
Anti-vacuous rules for property tests (these replace parity's grad_output/fp64/tolerance):
- Negative control is mandatory. Prove the test catches the bug: run it once against the
known-bad implementation (e.g.
git stash the fix) and confirm it FAILS, then restore.
For test_rng_entropy, the pre-fix shared seed fails on the tiled coordinate noise.
- Exercise threshold. Assert the property was actually exercised —
>= N ranks drew
sizable samples (numel above a threshold so scalar/degenerate draws don't make it vacuous),
never zero.
- Capture must not perturb the run — wrap fingerprinting in try/except, skip un-patchable
C-extension entry points, never raise from the capture path.
- Assert in the parent post-join — the per-rank files are the test context; the workflow
may have already torn down the process group, so do not rely on a live PG in the worker.
- Same infra as parity:
timeout-wrap, per-collective PG timeout, tee logs, CUDA-preferred.
More test classes & hygiene (details in reference.md)
- Dtype-path unit test per
autograd.Function, parametrized over (activation dtype × aux/
mask dtype × autocast on/off) — end-to-end parity is vacuous against a cast inserted and
reverted inside one Function (Rule 19). Make intermediate dtypes observable with a forward-
pre-hook profiler (post-hooks miss the recompute pass under use_reentrant=False).
- Triton-kernel trio: parity · edge cases · a register-spill gate (dump PTX,
ptxas -v,
assert 0 bytes spill). Triton kernels are often fp32-only (raise on fp64), so do the fp64
CP-vs-serial parity via the REFERENCE path on both sides, and gate the kernel separately
(compiles + matches its own fp32 reference + 0 spill). To force the reference path, override the
has-kernel flag in every module that imported it into its own namespace (grep the flag name) —
setting it only on the defining module is insufficient; run eager + kernel in one process.
- Stochastic outputs: compare distributions (energy distance + Hungarian-matched lDDT/
RMSD), never point values — sampled ensembles have no per-sample oracle.
- Hygiene: no global grad/RNG state in
setUp (use fork_rng/local no_grad); an OOM
poisons the shared CUDA context and cascades (must-fix); classify a failing dist test in a
fresh process; log grad_norm in on_after_backward (it is 0 before backward).
Test workflow & post-landing
- Identify the proving test cases before implementing; after, confirm the new code
paths are actually exercised — if not, extend an existing test (preferred) or add one.
- Checkpoint / serialization changes: cover both save and load, including
backward-compatibility with the prior format (load an old-format checkpoint), not just
a round-trip of the new format. (See
/fold-cp:dist_lifecycle for the resume test.)
- Sweep
TODO/FIXME after a feature lands: grep the distributed tree + tests for
markers referencing the new capability and resolve stale ones (remove if done, or convert
to a concrete follow-up) so they don't rot.
Output contract
- A parity test at the chosen level that passes against the serial reference and
contains every anti-vacuous assertion above, parametrized over the selected 2D
mesh configs.
- The test log on disk; a one-line statement of the tolerance used and why. The log is
self-verifying — it prints the measured difference vs the tolerance and a one-line pass of
each non-vacuous check on success, so the gate is checkable by reading it (Rule 22), not by a
re-run.
- If the new code path is not exercised by the test, extend the test or add one —
do not declare done on an untested path.
- For a property / invariant test (non-parity): the across-rank invariant assertion, an
exercise-threshold check, and a documented negative-control result (the test fails on
the known-bad implementation, passes after the fix).
1---2name: test3description: Write and run multi-rank pytest parity tests that prove a CP implementation is numerically equivalent to its serial reference, using mp.spawn / spawn_multiprocessing as in the Boltz-CP test framework. Covers unit, layer-integration, module-integration, and workflow-integration levels; handles missing test data by asking the user or synthesizing random features in the correct format; and enforces the anti-vacuous rules (serial ground truth, explicit random grad_output, fp64 default tolerances, sharding-active and replicated-identical assertions). Also covers a second, non-parity class — property / invariant tests (e.g. test_rng_entropy) that assert a structural invariant such as RNG entropy when there is no serial value oracle. Use to verify any output of shard_data_feats or dtensor_modules.4---56# test — prove the CP path is correct78Most CP correctness is **parity**: given identical inputs and weights, the distributed9forward+backward must numerically match the serial reference, which is the **only** value10oracle (Rule 13) — Steps 1–7 below. But some correctness properties have **no serial value11oracle** and need a different, **property / invariant** test (see12[§Property tests](#a-second-test-class-property--invariant-tests-not-serial-parity)) — most13notably anything random (RNG / noise), where no distributed RNG reproduces an all-gathered14single-device draw, so only the *entropy structure* is checkable. Either way: a test that15can pass with a broken implementation is worse than no test — follow the anti-vacuous rules16without exception. The worker skeleton, comparison matrix, and helper inventory are in17[reference.md](reference.md).1819## Preconditions2021- `docs/cp_infra.md` gives the launch recipe + `world_size` (run `build_infra` if22 not).23- The source under test exists and has a serial twin to compare against.2425## Step 1 — Choose the level and the test path2627| Level | What it pins | Compare |28|---|---|---|29| unit | one op / `autograd.Function` | op output + grad vs serial op |30| layer | one layer in isolation | layer fwd+bwd vs serial layer |31| module | module with real feature inputs (from the shared synthetic DataModule — Step 2.2) | module fwd+bwd vs serial module |32| workflow | end-to-end inference or train step | outputs / loss / weight deltas vs serial |3334**Test path mirrors the source path**:35`tests/distributed/<path>/test_dtensor_<file>.py` for DTensor tests,36`test_<file>.py` otherwise. Write the parity test for a new operator **before**37anything downstream depends on it.3839## Step 2 — Get test data (real or synthesized)40411. Prefer **real** inference/training features if the user can provide them — ask42 for a path and the feature format.432. Otherwise **synthesize through ONE shared synthetic `Dataset` + `DataLoader` + `DataModule`** —44 **not** per-test data-gen, and **not** loose one-off helper functions. Build a single synthetic45 data stack in the project's `distributed/testing/` subpackage (mirror `src/boltz/testing/utils.py`46 and `src/boltz/distributed/testing/`):47 - a **`Dataset`** whose `__getitem__` yields a synthesized `input_feature_dict` matching §3's48 contract (names, shapes, dtypes, axis semantics, masks), with a **`feature_subset`** knob;49 - a **`DataLoader`** (bs=1 + the production collate);50 - a **`DataModule`** that **REUSES the production CP distributor** (`distribute_input_feature_dict`51 / the data module's distributor) — never a re-implementation — to emit, for the requested52 subset, both the **serial** (full) and **CP** (DTensor) views. Every feature is emitted at the53 **data-feature sharding requirements** (the §3 placements / the §4.5 data-feature→consumer54 contract), which the reused distributor satisfies **by construction** — a synthetic55 dataset/dataloader/featurizer must never hand-roll placements that violate that contract.5657 **Every test — data, module, and workflow — draws its inputs from this one DataModule and SUBSETS58 the feature set its target consumes.** The common synth + distribution + divisibility-padding +59 atom-index-remap code then lives in exactly one place; tests never duplicate it. Two payoffs:60 - Because inputs flow through the real synthesizer + production distributor at the locked61 placements, a **feature-consuming** module test (relative-position encoder, atom encoder, input62 embedder, MSA module, diffusion conditioning, …) automatically exercises the **featurizer→module63 seam (Rule 4)** and the featurizer's **value semantics** (valid ranges, coupled-feature64 consistency, monotone indices) — drift is caught at the *unit* level, not deferred to the65 workflow test. Do **not** hand-roll data features with ad-hoc `torch.randint`/`randn`.66 - Keep ad-hoc `randn` **only** for genuine intermediate **activations** that are not featurizer67 outputs (an upstream single/pair representation, a diffusion noise level).683. Use the **same** inputs and weights on the serial and CP sides — load one `state_dict` into both,69 and draw features from the DataModule with one deterministic seed so both sides see identical70 inputs. Convert the module to the test dtype (fp64) **before** `load_state_dict` to avoid an fp3271 round-trip (fold-cp test discipline).7273## Step 3 — Pre-check on a 1×1 mesh FIRST, then build the multi-rank worker7475**Before any multi-GPU run, verify the fwd+bwd decomposition on a 1×1 mesh** (single76rank / single process, where every collective degenerates to a no-op), in fp64, CP ==77serial. This isolates math / placement-seam / op-order bugs from collective bugs, needs78no GPUs or multi-rank launch, and runs in seconds; a 4-rank 2×2 gloo run is a cheap second79step. Modules that pass this 1×1 pre-check hit multi-GPU parity on the first try —80treat it as routine, not optional. Only then build the multi-rank worker:8182- Spawn with `spawn_multiprocessing(worker, world_size, *args)` (Boltz testing83 utils) or `mp.spawn`.84- Init the process group with a **per-collective timeout** (e.g. 60s) so deadlocks85 fail fast; build the `DeviceMesh` for the selected 2D mesh.86- Monkeypatch the distributed cleanup to a no-op when a test reinitializes groups87 in one process (port reuse) — see `tests/distributed/test_dtensor_stop_and_go.py`.88- Wrap the worker body in **`try/finally`** to `destroy_process_group()` and free the GPU on exit;89 **do not `try/except` to swallow a rank's error and continue** — the throwing rank skips its90 remaining collectives and deadlocks the others (broadcast an ok/error sentinel instead — Rule 20).91- `seed_by_rank(rank)` for per-rank inputs that must differ; use a contained92 `torch.Generator` rather than global `manual_seed`.9394## Step 4 — Compare against serial (the right reassembly)9596| Comparison | Use |97|---|---|98| DTensor vs serial reference | `full_tensor()` to reassemble, then `assert_close` |99| DTensor vs DTensor (same placements) | `to_local()` on both — no communication |100| Gradients (replicated params) | `grad.full_tensor()` — `Partial(Sum)` needs the reduce; `to_local()` is only this rank's contribution |101102Run serial fwd+bwd on full tensors; run CP fwd+bwd on sharded DTensors; compare.103104## Step 5 — Anti-vacuous assertions (all required)105106- **Explicit random `grad_output`** for backward — never `.sum().backward()`107 (uniform grads mask sign/permutation bugs).108- **Sharding is active when either 2D mesh axis has size > 1:**109 `local.shape[sharded_dim] < global.shape[sharded_dim]` — skip for `cp=(1,1)`110 (a valid debugging mesh where local == global).111- **Replicated values identical across ranks** (`assert_all_identical`).112- **Gradients non-zero** (and finite).113- **Perturb/randomize zero-initialized params first** — AF/residual "final" projections114 are zero-init, so output and all grads are vacuously zero (`0 == 0` passes).115- **Per-PARAMETER grad parity, not only input-grad** — for any module with parameters116 replicated over a sharded axis, assert `param.grad.full_tensor()` vs serial. A replicated117 param whose grad is a per-rank partial (missing all-reduce) passes forward + input-grad118 parity but is wrong; only the param-grad check catches it.119- **fp64 + `assert_close` default tolerances.** If it only passes after loosening120 `atol`, that is a bug signal — derive the tolerance from the error budget, do not121 tune it (Rule 15).122- At least one **adversarial/boundary** case (a non-power-of-two per-axis 2D mesh such as123 `cp=(3,3)`, a padded axis, a single-element shard).124125## Step 6 — Parametrize and prefer CUDA126127One test function parametrized over a tuple of mesh configs (do not copy-paste per128size). Prefer CUDA parametrizations; keep at most one CPU param (e.g. a 3×3 mesh) for129CI path coverage.130131## Step 7 — Run, with timeout and logs132133```bash134timeout 120 python -m pytest <test path> -x -q |& tee /tmp/$USER/<name>.log135```136137**Make the log self-verifying (Rule 22).** Print the evidence on **success**, not only on138failure: the measured max abs/rel difference **and** the tolerance, the mesh / `world_size`, and a139one-line confirmation of each non-vacuous check (sharding-active, replicated-identical, grads140non-zero, per-param-grad). An orchestrator or reviewer then verifies the gate by **reading this141log** instead of re-running the GPU test (Rule 22) — a silent `assert_close` that prints nothing on142green forces a needless re-run. Emit the numbers.143144Inspect the log even on green (catch silent skips / warnings). When a test fails,145assume the implementation is wrong (Rule 14) — diagnose the CP code; do not weaken146the test.147148## A second test class: property / invariant tests (not serial parity)149150Some correctness properties are **not** numerical equality to the serial reference — the151serial run is not a value oracle for them. The oracle is a **structural invariant** the152distributed run must satisfy. Write a *property test* when:153154- the quantity is **random / not reproducible across mesh configurations** — RNG and noise: no155 distributed RNG numerically reproduces an all-gathered single-device draw today, so you156 can assert only its *entropy structure*, not its values; or157- the property is about **layout / determinism / consistency** rather than numbers — e.g.158 replicated values agree across ranks, control-flow counts match, sharding is active.159160**Canonical example — `test_rng_entropy`** (`tests/distributed/test_dtensor_predict.py`):161asserts every per-rank RNG draw obeys **single-device RNG *entropy* equivalence** (the162fold-cp RNG rule) — sharded-axis draws carry **independent** entropy (the cp0 diffusion noise163must not tile), replicate-axis draws are **identical** (via broadcast) — **without** comparing164to any serial value. Mechanism (skeleton in [reference.md](reference.md)):1651661. run the real workflow (e.g. DP=1, CP=(2,2), smallest sample) under `spawn_multiprocessing`;1672. monkeypatch the python `random` / numpy / torch RNG entry points to fingerprint every168 drawn sample per rank, and save the per-rank fingerprints to the test context (one JSON169 per rank);1703. **after the join**, in the parent process, assert the invariant across ranks: sizable171 sharded draws are **pairwise disjoint** across ranks (no tiling); replicated draws agree.172173**Anti-vacuous rules for property tests** (these replace parity's grad_output/fp64/tolerance):174175- **Negative control is mandatory.** Prove the test catches the bug: run it once against the176 known-bad implementation (e.g. `git stash` the fix) and confirm it **FAILS**, then restore.177 For `test_rng_entropy`, the pre-fix shared seed fails on the tiled coordinate noise.178- **Exercise threshold.** Assert the property was actually exercised — `>= N` ranks drew179 sizable samples (numel above a threshold so scalar/degenerate draws don't make it vacuous),180 never zero.181- **Capture must not perturb the run** — wrap fingerprinting in try/except, skip un-patchable182 C-extension entry points, never raise from the capture path.183- **Assert in the parent post-join** — the per-rank files are the test context; the workflow184 may have already torn down the process group, so do not rely on a live PG in the worker.185- Same infra as parity: `timeout`-wrap, per-collective PG timeout, tee logs, CUDA-preferred.186187## More test classes & hygiene (details in [reference.md](reference.md))188189- **Dtype-path unit test** per `autograd.Function`, parametrized over (activation dtype × aux/190 mask dtype × autocast on/off) — end-to-end parity is *vacuous* against a cast inserted and191 reverted inside one Function (Rule 19). Make intermediate dtypes observable with a forward-192 **pre**-hook profiler (post-hooks miss the recompute pass under `use_reentrant=False`).193- **Triton-kernel trio:** parity · edge cases · a **register-spill gate** (dump PTX, `ptxas -v`,194 assert `0 bytes spill`). Triton kernels are often **fp32-only** (raise on fp64), so do the fp64195 CP-vs-serial **parity via the REFERENCE path on both sides**, and gate the kernel *separately*196 (compiles + matches its own fp32 reference + 0 spill). To force the reference path, override the197 has-kernel flag in **every module that imported it into its own namespace** (grep the flag name) —198 setting it only on the defining module is insufficient; run eager + kernel in one process.199- **Stochastic outputs:** compare **distributions** (energy distance + Hungarian-matched lDDT/200 RMSD), never point values — sampled ensembles have no per-sample oracle.201- **Hygiene:** no global grad/RNG state in `setUp` (use `fork_rng`/local `no_grad`); an OOM202 poisons the shared CUDA context and cascades (must-fix); classify a failing dist test in a203 **fresh process**; log `grad_norm` in `on_after_backward` (it is 0 before backward).204205## Test workflow & post-landing206207- **Identify the proving test cases *before* implementing**; after, confirm the new code208 paths are actually exercised — if not, extend an existing test (preferred) or add one.209- **Checkpoint / serialization changes:** cover **both save and load**, including210 **backward-compatibility with the prior format** (load an old-format checkpoint), not just211 a round-trip of the new format. (See `/fold-cp:dist_lifecycle` for the resume test.)212- **Sweep `TODO`/`FIXME` after a feature lands:** grep the distributed tree + tests for213 markers referencing the new capability and resolve stale ones (remove if done, or convert214 to a concrete follow-up) so they don't rot.215216## Output contract217218- A parity test at the chosen level that passes against the serial reference and219 contains every anti-vacuous assertion above, parametrized over the selected 2D220 mesh configs.221- The test log on disk; a one-line statement of the tolerance used and why. The log is222 **self-verifying** — it prints the measured difference vs the tolerance and a one-line pass of223 each non-vacuous check on success, so the gate is checkable by reading it (Rule 22), not by a224 re-run.225- If the new code path is not exercised by the test, extend the test or add one —226 do not declare done on an untested path.227- For a property / invariant test (non-parity): the across-rank invariant assertion, an228 exercise-threshold check, and a documented **negative-control** result (the test fails on229 the known-bad implementation, passes after the fix).