diff --git a/api_relay_audit/latency_variance.py b/api_relay_audit/latency_variance.py index 6f70a11..c60f097 100644 --- a/api_relay_audit/latency_variance.py +++ b/api_relay_audit/latency_variance.py @@ -28,6 +28,7 @@ Given ``count`` successful samples: count < 3 -> "inconclusive" + mean <= 0 -> "inconclusive" bimodality detected -> "bimodal" CV < 0.25 -> "stable" 0.25 <= CV < 0.5 -> "variable" @@ -164,6 +165,8 @@ def classify_variance(stats, is_bimodal): """ if not stats or stats.get("count", 0) < 3: return "inconclusive" + if stats.get("mean", 0.0) <= 0: + return "inconclusive" if is_bimodal: return "bimodal" cv = stats.get("cv", 0.0) diff --git a/audit.py b/audit.py index 65c406b..bfa843d 100644 --- a/audit.py +++ b/audit.py @@ -4,8 +4,8 @@ # Regenerate after modular audit changes with: # python3 scripts/build-standalone.py # CI verifies this generated artifact plus key behavior regressions. -# source_sha256: 6fb11df52ddf05eeab8989ad23f0039c9038f369a0db942427cad02e883e980b -# standalone_body_sha256: badbe213d9e8f5ee25a551fec8cb7a6e82b6253b38c5bcb2e9b62ca58ce57aae +# source_sha256: 9efb15db9395ea199650974647bb458bcd05a81c2efbca3769322c8b87d7a351 +# standalone_body_sha256: 55332e36882d1a25938b9b30243e8a0da9340a89b571784bf3eec7f3fd8eca5f # END GENERATED STANDALONE HEADER """ @@ -4274,6 +4274,7 @@ def run_infra_fingerprint(client): Given ``count`` successful samples: count < 3 -> "inconclusive" + mean <= 0 -> "inconclusive" bimodality detected -> "bimodal" CV < 0.25 -> "stable" 0.25 <= CV < 0.5 -> "variable" @@ -4410,6 +4411,8 @@ def classify_variance(stats, is_bimodal): """ if not stats or stats.get("count", 0) < 3: return "inconclusive" + if stats.get("mean", 0.0) <= 0: + return "inconclusive" if is_bimodal: return "bimodal" cv = stats.get("cv", 0.0) @@ -6191,6 +6194,13 @@ def test_latency_variance(client, report, probe_count=10): f"Latency **stable** (CV={stats['cv']:.2f}). " "Consistent with a single honest upstream.", ) + elif stats.get("mean", 0.0) <= 0: + report.flag( + "yellow", + "Latency variance **inconclusive**: successful probes measured " + "zero or non-positive latency. This indicates mocked or broken " + "timing infrastructure; re-run in a real network environment.", + ) else: # inconclusive report.flag( "yellow", diff --git a/scripts/audit.py b/scripts/audit.py index 225fd9a..0a1d697 100644 --- a/scripts/audit.py +++ b/scripts/audit.py @@ -1386,6 +1386,13 @@ def test_latency_variance(client, report, probe_count=10): f"Latency **stable** (CV={stats['cv']:.2f}). " "Consistent with a single honest upstream.", ) + elif stats.get("mean", 0.0) <= 0: + report.flag( + "yellow", + "Latency variance **inconclusive**: successful probes measured " + "zero or non-positive latency. This indicates mocked or broken " + "timing infrastructure; re-run in a real network environment.", + ) else: # inconclusive report.flag( "yellow", diff --git a/tests/test_latency_variance.py b/tests/test_latency_variance.py index 26a4d94..4f80de8 100644 --- a/tests/test_latency_variance.py +++ b/tests/test_latency_variance.py @@ -137,6 +137,10 @@ def test_fewer_than_three_samples_inconclusive(self): stats = summarize_latencies([1.0, 1.1]) assert classify_variance(stats, False) == "inconclusive" + def test_zero_mean_stats_inconclusive(self): + stats = summarize_latencies([0.0, 0.0, 0.0]) + assert classify_variance(stats, False) == "inconclusive" + def test_bimodal_takes_precedence(self): """Even if the CV is below the stable cutoff, a detected bimodal distribution wins -- clustering is a stronger