fix: make spectral evidence fail inconclusive (#183)

This commit is contained in:
Joseph Magly
2026-08-28 23:25:14 -04:00
parent ef82652f44
commit 41654bdcdf
7 changed files with 220 additions and 23 deletions
+29
View File
@@ -95,3 +95,32 @@ assert "🔴" in card
check=False,
)
assert result.returncode == 0, result.stdout + result.stderr
@pytest.mark.operator_ui
def test_result_card_exposes_spectral_inconclusive_reason():
script = r'''
from types import SimpleNamespace
import app
pipeline = SimpleNamespace(
_quality_metrics={
"spectral_certification": "INCONCLUSIVE",
"spectral_diagnostic_reason": "insufficient_samples",
},
_strong_layers=[1],
)
card = app._format_obliteration_metrics(pipeline, "advanced", "1s")
assert "Spectral Diagnostic" in card
assert "INCONCLUSIVE (insufficient_samples)" in card
assert "" in card
'''
result = subprocess.run(
[sys.executable, "-c", script],
capture_output=True,
text=True,
timeout=60,
check=False,
)
assert result.returncode == 0, result.stdout + result.stderr
+52
View File
@@ -10,6 +10,7 @@ from __future__ import annotations
import math
import pytest
import torch
from obliteratus.analysis.riemannian_manifold import (
@@ -687,6 +688,57 @@ class TestSpectralCertification:
assert result.confidence < 0.95
assert "inconclusive" in result.recommendation.lower()
def test_qwen_width_dual_space_case_is_inconclusive_not_zero_threshold_red(self):
"""The production n=40, d=5120 regime cannot self-certify via signal size."""
torch.manual_seed(42)
harmful = torch.randn(20, 5120) * 0.3
harmless = torch.randn(20, 5120) * 0.3
result = SpectralCertifier().certify(harmful, harmless)
assert result.level == CertificationLevel.INCONCLUSIVE
assert result.diagnostic_reason == "insufficient_samples"
assert result.effective_noise_rank > 1
assert math.isfinite(result.bbp_threshold)
assert result.bbp_threshold > 0
assert result.n_samples_required >= math.ceil(math.sqrt(5120))
def test_zero_noise_scale_is_machine_readable_inconclusive(self):
harmful = torch.ones(30, 32)
harmless = torch.ones(30, 32)
result = SpectralCertifier().certify(harmful, harmless)
assert result.level == CertificationLevel.INCONCLUSIVE
assert result.diagnostic_reason == "zero_or_non_finite_noise_scale"
assert result.effective_noise_rank == 0
assert result.is_sample_sufficient is False
def test_non_finite_activations_are_machine_readable_inconclusive(self):
harmful = torch.randn(30, 32)
harmless = torch.randn(30, 32)
harmful[0, 0] = float("nan")
result = SpectralCertifier().certify(harmful, harmless)
assert result.level == CertificationLevel.INCONCLUSIVE
assert result.diagnostic_reason == "non_finite_activations"
assert result.is_sample_sufficient is False
assert math.isfinite(result.bbp_threshold)
assert math.isfinite(result.leading_eigenvalue)
@pytest.mark.parametrize(
("harmful", "harmless", "message"),
[
(torch.zeros(2, 2, 2), torch.zeros(2, 2), "2-D"),
(torch.zeros(2, 3), torch.zeros(2, 4), "hidden width"),
(torch.zeros(1, 3), torch.zeros(2, 3), "two samples"),
],
)
def test_invalid_activation_shapes_fail_closed(self, harmful, harmless, message):
with pytest.raises(ValueError, match=message):
SpectralCertifier().certify(harmful, harmless)
def test_overall_prefers_sufficient_red_over_inconclusive(self):
"""A reliable RED layer remains actionable in a mixed result set."""
torch.manual_seed(42)
+16
View File
@@ -231,6 +231,22 @@ class TestBuildReport:
"refusal_rate": "measured",
}
def test_spectral_inconclusive_reason_and_rank_are_public_metrics(self):
report = build_report(**self._base_kwargs(quality_metrics={
"spectral_certification": "INCONCLUSIVE",
"spectral_diagnostic_reason": "insufficient_samples",
"spectral_effective_noise_rank": 38,
"spectral_samples_required": 72,
}))
assert report["quality_metrics"] == {
"spectral_certification": "INCONCLUSIVE",
"spectral_diagnostic_reason": "insufficient_samples",
"spectral_effective_noise_rank": 38.0,
"spectral_samples_required": 72.0,
}
assert set(report["quality_metric_status"].values()) == {"measured"}
def test_public_payload_redacts_paths_tokens_and_secret_keys(self):
report = build_report(**self._base_kwargs(
architecture="/private/models/LlamaForCausalLM",