| """CPU-only mechanical contract for the frozen v2 inversion policy. |
| |
| Expected public API: music3lab.inversion_v2 exposes the pure functions/classes |
| called below. Metric inputs are [batch, 2, samples] float tensors. The v1.3 |
| loader returns all four bound E2 final latents, never a selected-only latent. |
| """ |
| from __future__ import annotations |
|
|
| import hashlib |
| from pathlib import Path |
|
|
| import pytest |
| import torch |
| from safetensors.torch import save as save_safetensors |
|
|
| from music3lab import inversion_v2 as v2 |
|
|
|
|
| def _audio(samples: int = 128) -> torch.Tensor: |
| time = torch.arange(samples, dtype=torch.float32) / samples |
| return torch.stack((0.25 * torch.sin(2 * torch.pi * 7 * time), 0.20 * torch.cos(2 * torch.pi * 5 * time))).unsqueeze(0) |
|
|
|
|
| def test_time_nmse_and_stft_distinguish_identity_distortion_and_polarity() -> None: |
| target = _audio() |
| assert torch.equal(v2.target_energy_normalized_time_nmse(target, target), torch.zeros(1)) |
| assert v2.target_energy_normalized_time_nmse(target + 0.2, target).item() > 0.1 |
| assert v2.mrstft_magnitude_distance(-target, target, fft_sizes=(32, 64)).item() < 1e-6 |
| assert v2.time_and_complex_stft_distance(-target, target, fft_sizes=(32, 64)).item() > 0.5 |
|
|
|
|
| def test_selection_score_is_identical_at_every_training_stage() -> None: |
| metrics = { |
| "time_nmse": 0.125, |
| "complex_stft_nmse": 0.25, |
| "legacy_mrstft": 0.375, |
| "mid_side_nmse": 0.2, |
| "relative_envelope": 0.1, |
| } |
| scores = [v2.selection_score(metrics, stage=stage) for stage in ("fp32", "bf16", "handoff")] |
| assert scores == [scores[0]] * 3 |
|
|
|
|
| @pytest.mark.parametrize(("stage", "warmup", "total", "peak"), (("fp32", 4, 20, 0.02), ("bf16", 2, 10, 0.01))) |
| def test_warmup_cosine_schedule_has_exact_frozen_endpoints(stage: str, warmup: int, total: int, peak: float) -> None: |
| minimum = peak / 10 |
| schedule = v2.FrozenStageSchedule( |
| name=stage, |
| warmup_steps=warmup, |
| total_steps=total, |
| maximum_learning_rate=peak, |
| minimum_learning_rate=minimum, |
| ) |
| assert v2.warmup_cosine_learning_rate(schedule, 0) == 0.0 |
| assert v2.warmup_cosine_learning_rate(schedule, warmup) == peak |
| with pytest.raises(ValueError, match="step"): |
| v2.warmup_cosine_learning_rate(schedule, total + 1) |
|
|
|
|
| def _authority(path: Path) -> dict[str, object]: |
| data = path.read_bytes() |
| return {"path": path.name, "sha256": hashlib.sha256(data).hexdigest(), "size": len(data), "required_restart_count": 4, "tensor_key": "final_latents"} |
|
|
|
|
| def test_v11_e2_loader_requires_all_four_bound_final_latents(tmp_path: Path) -> None: |
| path = tmp_path / "latents.safetensors" |
| expected = torch.arange(24, dtype=torch.float32).reshape(4, 2, 3) |
| path.write_bytes(save_safetensors({"final_latents": expected, "selected_latent": expected[:1].clone()})) |
| authority = _authority(path) |
| path.chmod(0o644) |
| assert torch.equal(v2.load_v11_e2_final_latents(path, authority), expected) |
| selected_only = tmp_path / "selected-only.safetensors" |
| selected_only.write_bytes(save_safetensors({"selected_latent": expected[:1]})) |
| selected_only.chmod(0o644) |
| with pytest.raises((ValueError, RuntimeError), match="final|four|restart|sha|authority"): |
| v2.load_v11_e2_final_latents(selected_only, authority) |
| cherry_picked = tmp_path / "cherry-picked.safetensors" |
| cherry_picked.write_bytes(save_safetensors({"final_latents": expected[:3]})) |
| cherry_picked.chmod(0o644) |
| with pytest.raises((ValueError, RuntimeError), match="four|restart|sha"): |
| v2.load_v11_e2_final_latents(cherry_picked, authority) |
| path.write_bytes(save_safetensors({"final_latents": expected + 1})) |
| with pytest.raises((ValueError, RuntimeError), match="sha|authority|size"): |
| v2.load_v11_e2_final_latents(path, authority) |
|
|
|
|
| def test_restart_ledger_is_monotone_and_breaks_objective_ties_by_index() -> None: |
| ledger = v2.RestartLedger(restart_count=4) |
| ledger.record((4.0, 3.0, 2.0, 1.0)) |
| ledger.record((5.0, 2.0, 3.0, 1.0)) |
| assert ledger.best_so_far == (4.0, 2.0, 2.0, 1.0) |
| assert ledger.select((1.0, 1.0, 2.0, 3.0)) == 0 |
| with pytest.raises((ValueError, RuntimeError), match="regress|monotone"): |
| ledger.record_best_so_far((4.1, 2.0, 2.0, 1.0)) |
|
|
|
|
| def test_evaluator_cannot_run_before_lock_or_change_locked_selection() -> None: |
| lock = v2.SelectionLock() |
| with pytest.raises((ValueError, RuntimeError), match="lock|select"): |
| lock.evaluate(lambda index: {"rank": index}) |
| assert lock.lock((3.0, 1.0, 1.0, 2.0)) == 1 |
| assert lock.evaluate(lambda index: {"rank": index}) == {"rank": 1} |
| with pytest.raises((ValueError, RuntimeError), match="locked|selection"): |
| lock.lock((0.0, 3.0, 3.0, 3.0)) |
|
|
|
|
| def test_distributional_prior_has_no_oracle_distance_input() -> None: |
| latents = torch.tensor([[[0.0, 1.0, 9.0, -9.0]]], dtype=torch.float32) |
| prior = v2.distributional_prior(latents, mean=0.0, std=1.0, tail_threshold=3.0) |
| assert prior["mean_error"] == pytest.approx(0.25) |
| assert prior["mean_term"] == pytest.approx(0.25**2) |
| assert prior["tail_term"] == pytest.approx(18.0) |
| expected = prior["mean_term"] + prior["std_term"] + 0.1 * prior["tail_term"] |
| assert prior["prior"] == pytest.approx(expected) |
| assert "oracle" not in " ".join(prior.keys()).lower() |
|
|
|
|
| class _TinyFrozenDecoder(torch.nn.Module): |
| def __init__(self) -> None: |
| super().__init__() |
| self.projection = torch.nn.Conv1d(2, 2, 1, bias=False) |
| torch.nn.init.eye_(self.projection.weight[..., 0]) |
| for parameter in self.parameters(): |
| parameter.requires_grad_(False) |
|
|
| def forward(self, latents: torch.Tensor) -> torch.Tensor: |
| return self.projection(latents) |
|
|
|
|
| def test_frozen_decoder_keeps_weights_grad_free_but_latents_receive_gradient() -> None: |
| decoder = _TinyFrozenDecoder() |
| latents = torch.full((1, 2, 32), 0.1, requires_grad=True) |
| audit = v2.frozen_decoder_step(decoder, latents, torch.zeros_like(latents)) |
| assert audit.weight_sha256_before == audit.weight_sha256_after |
| assert audit.finite_loss and audit.finite_latent_gradient and audit.nonzero_latent_gradient |
| assert all(parameter.grad is None for parameter in decoder.parameters()) |
|
|
|
|
| def test_progress_never_substitutes_for_feasibility_or_high_fidelity() -> None: |
| failed = v2.quality_gate(progress_fraction=0.99, feasibility_metrics={"time_nmse": 2.0}, high_fidelity_metrics={"si_sdr_db": -10.0}) |
| assert not failed.feasibility_pass |
| assert not failed.high_fidelity_pass |
| assert failed.quality_claim == "NO_QUALITY_CLAIM" |
|
|
|
|
| def test_authority_tamper_and_atomic_publication(tmp_path: Path) -> None: |
| staged = tmp_path / "staged" |
| staged.mkdir() |
| staged.chmod(0o755) |
| payload = b"v2 evidence" |
| (staged / "metrics.json").write_bytes(payload) |
| (staged / "metrics.json").chmod(0o644) |
| authority = {"metrics.json": hashlib.sha256(payload).hexdigest()} |
| published = tmp_path / "published" |
| v2.atomic_publish_verified(staged, published, authority) |
| assert (published / "metrics.json").read_bytes() == payload |
| assert not staged.exists() |
| (published / "metrics.json").write_bytes(b"tampered") |
| with pytest.raises((ValueError, RuntimeError), match="sha|authority|tamper"): |
| v2.verify_published_authority(published, authority) |
| replacement = tmp_path / "replacement" |
| replacement.mkdir() |
| replacement.chmod(0o755) |
| (replacement / "metrics.json").write_bytes(payload) |
| (replacement / "metrics.json").chmod(0o644) |
| with pytest.raises((ValueError, RuntimeError), match="authority|sha"): |
| v2.atomic_publish_verified(replacement, published, {"metrics.json": "0" * 64}) |
| assert (published / "metrics.json").read_bytes() == b"tampered" |
|
|