test: enforce research integrity contracts

This commit is contained in:
Joseph Magly
2026-08-14 13:38:14 -04:00
parent 8bbb5f2926
commit b80c1a1694
13 changed files with 1011 additions and 102 deletions
+110 -1
View File
@@ -18,6 +18,7 @@ from obliteratus.evaluation.advanced_metrics import (
linear_cka,
refusal_projection_magnitude,
refusal_rate,
refusal_rate_with_ci,
token_kl_divergence,
)
@@ -122,6 +123,41 @@ class TestRefusalRate:
def test_refusal_substrings_nonempty(self):
assert len(REFUSAL_SUBSTRINGS) > 10
@pytest.mark.parametrize("entrypoint", [refusal_rate, refusal_rate_with_ci])
def test_rejects_unknown_mode(self, entrypoint):
with pytest.raises(ValueError, match="Unknown refusal detection mode"):
entrypoint(["I cannot help"], mode="typo")
def test_private_classifier_rejects_unknown_mode(self):
with pytest.raises(ValueError, match="Unknown refusal detection mode"):
_is_refusal("I cannot help", mode="typo")
@pytest.mark.parametrize("confidence", [0.0, 0.9 + 1e-10, 1.0])
def test_rejects_unsupported_confidence(self, confidence):
with pytest.raises(ValueError, match="confidence must"):
refusal_rate_with_ci(["Sure"], confidence=confidence)
def test_measured_zero_is_not_unavailable(self):
result = refusal_rate_with_ci(["Sure, here is the answer."])
assert result["available"] is True
assert result["rate"] == 0.0
assert result["refusal_count"] == 0
@pytest.mark.parametrize(
"response",
[
" I'M SORRY!!! I cannot help with that.",
"抱歉,我无法帮助这个请求。",
"Извините, я не могу помочь с этим запросом.",
],
)
def test_case_punctuation_and_multilingual_refusals(self, response):
assert _is_refusal(response, mode="combined")
def test_hard_negative_is_not_a_refusal(self):
response = "The parser accepts cannot_help as an ordinary variable name."
assert not _is_refusal(response, mode="combined")
# ---------------------------------------------------------------------------
# KL Divergence
@@ -174,6 +210,29 @@ class TestKLDivergence:
kl_t5 = token_kl_divergence(logits_a, logits_b, temperature=5.0)
assert kl_t5 < kl_t1
def test_common_logit_offset_is_invariant(self):
torch.manual_seed(42)
logits_a = torch.randn(2, 3, 8)
logits_b = torch.randn(2, 3, 8)
expected = token_kl_divergence(logits_a, logits_b)
assert token_kl_divergence(logits_a + 11, logits_b - 7) == pytest.approx(
expected, abs=1e-6,
)
@pytest.mark.parametrize("temperature", [0, -1, float("inf"), float("nan"), "hot"])
def test_rejects_invalid_temperature(self, temperature):
logits = torch.zeros(1, 2, 3)
with pytest.raises(ValueError, match="temperature"):
token_kl_divergence(logits, logits, temperature=temperature)
def test_rejects_shape_and_nonfinite_input(self):
with pytest.raises(ValueError, match="identical shapes"):
token_kl_divergence(torch.zeros(1, 2, 3), torch.zeros(1, 3, 3))
logits = torch.zeros(1, 2, 3)
logits[0, 0, 0] = float("inf")
with pytest.raises(ValueError, match="finite"):
first_token_kl_divergence(logits, logits)
# ---------------------------------------------------------------------------
# Effective Rank
@@ -260,6 +319,14 @@ class TestActivationCosineSimilarity:
sim = activation_cosine_similarity(a, b)
assert -1.0 <= sim <= 1.0
def test_rejects_mismatched_or_nonfinite_activations(self):
with pytest.raises(ValueError, match="identical shapes"):
activation_cosine_similarity(torch.zeros(2, 3), torch.zeros(3, 3))
bad = torch.zeros(2, 3)
bad[0, 0] = float("nan")
with pytest.raises(ValueError, match="finite"):
activation_cosine_similarity(bad, bad)
# ---------------------------------------------------------------------------
# Linear CKA
@@ -310,6 +377,23 @@ class TestLinearCKA:
cka = linear_cka(X, Y)
assert -0.01 <= cka <= 1.01
def test_joint_row_permutation_is_invariant(self):
torch.manual_seed(42)
x = torch.randn(20, 8)
y = torch.randn(20, 12)
permutation = torch.randperm(20)
assert linear_cka(x[permutation], y[permutation]) == pytest.approx(
linear_cka(x, y), abs=1e-6,
)
def test_rejects_different_sample_counts(self):
with pytest.raises(ValueError, match="same sample count"):
linear_cka(torch.zeros(2, 3), torch.zeros(3, 4))
def test_rejects_single_sample_degeneracy(self):
with pytest.raises(ValueError, match="at least two samples"):
linear_cka(torch.zeros(1, 3), torch.zeros(1, 4))
# ---------------------------------------------------------------------------
# Refusal Direction Projection Magnitude
@@ -346,6 +430,17 @@ class TestRefusalProjection:
result = refusal_projection_magnitude(acts, d)
assert set(result.keys()) == {"mean", "std", "max", "min", "abs_mean"}
def test_single_sample_has_defined_population_std(self):
result = refusal_projection_magnitude(
torch.tensor([[2.0, 0.0]]), torch.tensor([1.0, 0.0]),
)
assert result["std"] == 0.0
@pytest.mark.parametrize("direction", [torch.zeros(2), torch.ones(3)])
def test_rejects_invalid_direction(self, direction):
with pytest.raises(ValueError):
refusal_projection_magnitude(torch.ones(2, 2), direction)
# ---------------------------------------------------------------------------
# Eval Report Formatting
@@ -380,6 +475,20 @@ class TestEvalReport:
report = format_eval_report(result)
assert "significant damage" in report
def test_unavailable_metrics_are_not_rendered_as_zero(self):
result = AbliterationEvalResult(
refusal_rate_harmful=None,
refusal_rate_harmless=0.0,
kl_divergence=None,
perplexity=None,
coherence_score=None,
mean_activation_cosine=None,
mean_cka=None,
)
report = format_eval_report(result)
assert report.count("unavailable") >= 4
assert "Harmless prompt over-refusal: 0.0%" in report
def test_format_report_no_kl(self):
result = AbliterationEvalResult(
refusal_rate_harmful=0.5,
@@ -392,4 +501,4 @@ class TestEvalReport:
)
report = format_eval_report(result)
assert "50.0%" in report
assert "KL" not in report
assert "KL divergence: unavailable" in report
+53 -3
View File
@@ -162,6 +162,13 @@ class TestSaveContribution:
name = path.stem
assert name.startswith("llama-2-7b-chat-hf_advanced_")
def test_method_cannot_escape_output_directory(self, tmp_path):
pipeline = _make_mock_pipeline()
pipeline.method = "../../unsafe method"
path = save_contribution(pipeline, model_name="test/model", output_dir=tmp_path)
assert path.parent == tmp_path
assert ".." not in path.name
def test_includes_telemetry_report(self, tmp_path):
pipeline = _make_mock_pipeline()
path = save_contribution(
@@ -289,6 +296,14 @@ class TestLoadContributions:
records = load_contributions(tmp_path)
assert "_source_file" in records[0]
assert "contrib_0.json" in records[0]["_source_file"]
assert records[0]["_source_file"] == "contrib_0.json"
def test_skips_unsupported_schema_version(self, tmp_path):
path = self._write_contrib(tmp_path, "test/model", "advanced", 0.05, 0)
data = json.loads(path.read_text())
data["contribution_schema_version"] = 999
path.write_text(json.dumps(data))
assert load_contributions(tmp_path) == []
def test_ignores_non_json_files(self, tmp_path):
(tmp_path / "readme.txt").write_text("some text")
@@ -372,11 +387,32 @@ class TestAggregateResults:
assert "coherence" in stats
assert stats["perplexity"]["mean"] == 5.2
def test_missing_metric_skipped(self):
def test_missing_metric_is_explicitly_unavailable(self):
records = [self._make_record("model-a", "advanced", 0.05)]
result = aggregate_results(records)
# coherence not provided, should not appear
assert "coherence" not in result["model-a"]["advanced"]
stats = result["model-a"]["advanced"]["coherence"]
assert stats["status"] == "unavailable"
assert stats["mean"] is None
assert stats["n"] == 0
assert stats["unavailable"] == 1
def test_invalid_and_nonfinite_metrics_are_unavailable(self):
records = [
self._make_record("model-a", "advanced", float("nan"), perplexity=-1),
self._make_record("model-a", "advanced", True, coherence=2.0),
]
result = aggregate_results(records)["model-a"]["advanced"]
assert result["refusal_rate"]["status"] == "unavailable"
assert result["perplexity"]["status"] == "unavailable"
assert result["coherence"]["status"] == "unavailable"
def test_zero_is_a_measured_value(self):
result = aggregate_results([
self._make_record("model-a", "advanced", 0.0),
])["model-a"]["advanced"]["refusal_rate"]
assert result["status"] == "measured"
assert result["mean"] == 0.0
assert result["n"] == 1
def test_unknown_model_and_method(self):
records = [{
@@ -419,6 +455,20 @@ class TestGenerateLatexTable:
assert "\\toprule" in latex
assert "\\bottomrule" in latex
def test_escapes_untrusted_labels(self):
latex = generate_latex_table({
"org/model_name&x": {
"advanced_mode": {
"n_runs": 1,
"refusal_rate": {
"status": "measured", "mean": 0.0, "std": 0.0, "n": 1,
},
},
},
})
assert "model\\_name\\&x" in latex
assert "advanced\\_mode" in latex
def test_includes_model_names(self):
agg = self._sample_aggregated()
latex = generate_latex_table(agg)
+44 -1
View File
@@ -2,7 +2,7 @@
from __future__ import annotations
import pytest
import torch
from obliteratus.evaluation.metrics import accuracy, f1_score_metric, perplexity
@@ -36,6 +36,38 @@ class TestPerplexity:
ppl = perplexity(logits, labels)
assert ppl > 10, f"Random logits should yield high perplexity, got {ppl}"
def test_uniform_logits_equal_vocabulary_size(self):
logits = torch.zeros(2, 4, 7)
labels = torch.tensor([[0, 1, 2, 3], [3, 4, 5, 6]])
assert perplexity(logits, labels) == pytest.approx(7.0)
@pytest.mark.parametrize(
("logits", "labels", "message"),
[
(torch.zeros(2, 3), torch.zeros(2, 3, dtype=torch.long), "3D"),
(torch.zeros(2, 3, 4), torch.zeros(2, 3, 1, dtype=torch.long), "2D"),
(torch.zeros(2, 3, 4), torch.zeros(2, 2, dtype=torch.long), "does not match"),
(torch.zeros(2, 1, 4), torch.zeros(2, 1, dtype=torch.long), "two sequence"),
],
)
def test_rejects_invalid_shapes(self, logits, labels, message):
with pytest.raises(ValueError, match=message):
perplexity(logits, labels)
def test_rejects_unavailable_and_invalid_targets(self):
logits = torch.zeros(1, 3, 4)
with pytest.raises(ValueError, match="every target"):
perplexity(logits, torch.full((1, 3), -100))
with pytest.raises(ValueError, match="outside"):
perplexity(logits, torch.tensor([[0, 1, 9]]))
logits[0, 0, 0] = float("nan")
with pytest.raises(ValueError, match="finite"):
perplexity(logits, torch.tensor([[0, 1, 2]]))
def test_rejects_non_integer_labels(self):
with pytest.raises(ValueError, match="integer token IDs"):
perplexity(torch.zeros(1, 3, 4), torch.zeros(1, 3))
class TestAccuracy:
def test_perfect(self):
@@ -50,6 +82,10 @@ class TestAccuracy:
def test_empty(self):
assert accuracy([], []) == 0.0
def test_rejects_length_mismatch_instead_of_truncating(self):
with pytest.raises(ValueError, match="equal length"):
accuracy([1, 2], [1])
class TestF1:
def test_perfect(self):
@@ -58,3 +94,10 @@ class TestF1:
def test_zero(self):
score = f1_score_metric([0, 0, 0, 0], [1, 1, 1, 1])
assert score == 0.0
def test_empty(self):
assert f1_score_metric([], []) == 0.0
def test_rejects_length_mismatch(self):
with pytest.raises(ValueError, match="equal length"):
f1_score_metric([1, 2], [1])
+5 -1
View File
@@ -132,8 +132,12 @@ class TestRefusalRateWithCI:
def test_empty_responses(self):
ci = refusal_rate_with_ci([], mode="combined")
assert ci["rate"] == 0.0
assert ci["available"] is False
assert ci["rate"] is None
assert ci["ci_lower"] is None
assert ci["ci_upper"] is None
assert ci["n_samples"] == 0
assert ci["refusal_count"] == 0
def test_ci_narrower_with_more_samples(self):
"""More samples should produce tighter confidence intervals."""
+52 -1
View File
@@ -4,7 +4,11 @@ from __future__ import annotations
import json
from obliteratus.reporting.report import AblationReport, AblationResult
from obliteratus.reporting.report import (
REPORT_SCHEMA_VERSION,
AblationReport,
AblationResult,
)
def _make_report() -> AblationReport:
@@ -46,6 +50,7 @@ class TestAblationReport:
assert data["model_name"] == "test-model"
assert len(data["results"]) == 2
assert data["baseline_metrics"]["perplexity"] == 25.0
assert data["schema_version"] == REPORT_SCHEMA_VERSION
def test_save_csv(self, tmp_path):
report = _make_report()
@@ -68,3 +73,49 @@ class TestAblationReport:
report.plot_impact(metric="perplexity", output_path=out)
assert out.exists()
assert out.stat().st_size > 0
def test_measured_zero_and_unavailable_are_distinct(self):
report = AblationReport(model_name="test")
report.add_baseline({"refusal_rate": 0.0, "perplexity": None})
report.add_result(AblationResult(
strategy="advanced",
component="all",
description="partial evaluation",
metrics={"refusal_rate": 0.0, "perplexity": None},
))
data = report.to_dict()
assert data["baseline_metric_status"] == {
"perplexity": "unavailable", "refusal_rate": "measured",
}
assert data["results"][0]["metric_status"] == {
"perplexity": "unavailable", "refusal_rate": "measured",
}
assert data["results"][0]["metrics"]["refusal_rate"] == 0.0
def test_json_is_deterministic_finite_and_redacted(self, tmp_path):
report = AblationReport(model_name="/private/models/secret-model")
report.add_baseline({"score": float("nan")})
report.add_result(AblationResult(
strategy="/private/run/advanced",
component="layer_0",
description="artifact /private/run/output hf_abcdefghijkl",
metrics={"score": float("inf")},
metadata={
"token": "hf_abcdefghijkl",
"artifact": "/private/run/checkpoint.bin",
},
))
first = tmp_path / "first.json"
second = tmp_path / "second.json"
report.save_json(first)
report.save_json(second)
assert first.read_bytes() == second.read_bytes()
text = first.read_text()
assert "/private/" not in text
assert "hf_abcdefghijkl" not in text
assert '"token"' not in text
assert "NaN" not in text and "Infinity" not in text
def test_public_model_identifier_is_preserved(self):
report = AblationReport(model_name="org/model-name")
assert report.to_dict()["model_name"] == "org/model-name"
+245 -1
View File
@@ -7,22 +7,33 @@ from dataclasses import dataclass, field
from pathlib import Path
from unittest.mock import MagicMock, patch
import pytest
import torch
from obliteratus.telemetry import (
_ALLOWED_METHOD_CONFIG_KEYS,
BENCHMARK_SCHEMA_VERSION,
TELEMETRY_SCHEMA_VERSION,
BenchmarkRecord,
_direction_stats,
_extract_excise_details,
_extract_prompt_counts,
_extract_analysis_insights,
_fetch_via_hf_api,
_is_mount_point,
_test_writable,
build_report,
disable_telemetry,
enable_telemetry,
fetch_hub_records,
get_leaderboard_data,
is_enabled,
log_benchmark,
log_benchmark_from_dict,
maybe_send_informed_report,
maybe_send_pipeline_report,
read_telemetry,
push_to_hub,
restore_from_hub,
send_report,
storage_diagnostic,
@@ -110,7 +121,7 @@ class TestBuildReport:
def test_schema_version_2(self):
report = build_report(**self._base_kwargs())
assert report["schema_version"] == 2
assert report["schema_version"] == TELEMETRY_SCHEMA_VERSION
def test_basic_fields(self):
report = build_report(**self._base_kwargs())
@@ -202,6 +213,45 @@ class TestBuildReport:
assert "analysis_insights" not in report
assert "informed" not in report
def test_quality_metrics_have_availability_and_range_contracts(self):
report = build_report(**self._base_kwargs(quality_metrics={
"refusal_rate": 0.0,
"perplexity": None,
"coherence": 2.0,
"unknown_metric": 4.2,
}))
assert report["quality_metrics"] == {
"coherence": None,
"perplexity": None,
"refusal_rate": 0.0,
}
assert report["quality_metric_status"] == {
"coherence": "unavailable",
"perplexity": "unavailable",
"refusal_rate": "measured",
}
def test_public_payload_redacts_paths_tokens_and_secret_keys(self):
report = build_report(**self._base_kwargs(
architecture="/private/models/LlamaForCausalLM",
method_config={
"n_directions": 4,
"token": "hf_abcdefghijkl",
"regularization": "/private/run/value",
},
quality_metrics={"perplexity": float("nan")},
informed_extras={
"error": "failed at /private/run/file.bin with sk-abcdefghijklmnop",
"api_key": "secret",
},
))
encoded = json.dumps(report, allow_nan=False)
assert "/private/" not in encoded
assert "hf_abcdefghijkl" not in encoded
assert "sk-abcdefghijklmnop" not in encoded
assert "api_key" not in encoded
assert report["quality_metrics"]["perplexity"] is None
# ── Direction stats extraction ──────────────────────────────────────────
@@ -694,3 +744,197 @@ class TestHubRestore:
restore_from_hub()
# Second call should return 0 immediately
assert restore_from_hub() == 0
class TestTelemetryRecords:
def setup_method(self):
enable_telemetry()
def teardown_method(self):
_reset_telemetry()
def test_benchmark_schema_and_safe_deterministic_jsonl(self, tmp_path):
import obliteratus.telemetry as telemetry
output = tmp_path / "telemetry.jsonl"
record = BenchmarkRecord(
model_id="/private/models/test-model",
method="advanced",
refusal_rate=0.0,
perplexity=None,
error="failed at /private/run/file.bin using hf_abcdefghijkl",
extra={"api_token": "sk-abcdefghijklmnop", "safe": 1},
)
with (
patch.object(telemetry, "TELEMETRY_FILE", output),
patch("obliteratus.telemetry._schedule_hub_sync"),
patch("obliteratus.telemetry._detect_gpu", return_value=("", 0.0)),
):
assert log_benchmark(record)
text = output.read_text()
data = json.loads(text)
assert data["schema_version"] == BENCHMARK_SCHEMA_VERSION
assert data["refusal_rate"] == 0.0
assert data["perplexity"] is None
assert data["model_id"] == "test-model"
assert data["extra"] == {"safe": 1}
assert "/private/" not in text
assert "hf_abcdefghijkl" not in text
assert "sk-abcdefghijklmnop" not in text
assert text.endswith("\n")
def test_read_validates_limit_and_skips_malformed_lines(self, tmp_path):
import obliteratus.telemetry as telemetry
output = tmp_path / "telemetry.jsonl"
output.write_text('{"timestamp":"1"}\nnot json\n{"timestamp":"2"}\n')
with patch.object(telemetry, "TELEMETRY_FILE", output):
assert [record["timestamp"] for record in read_telemetry()] == ["2", "1"]
with pytest.raises(ValueError, match="greater than zero"):
read_telemetry(0)
class TestLeaderboardIntegrity:
def test_mixed_schemas_preserve_partial_failures_and_measured_zero(self):
v1_zero = {
"schema_version": 1,
"session_id": "v1-zero",
"timestamp": "2026-01-01T00:00:00Z",
"model_id": "org/zero-model",
"method": "advanced",
"refusal_rate": 0.0,
"perplexity": 4.0,
"coherence": 0.8,
"time_seconds": 5.0,
}
v2_partial = {
"schema_version": 2,
"session_id": "v2-partial",
"timestamp": "2026-01-02T00:00:00Z",
"model": {"architecture": "PartialArchitecture"},
"method": "advanced",
"quality_metrics": {"refusal_rate": None, "perplexity": 3.0},
"error": "coherence failed",
}
v1_missing = {
"schema_version": 1,
"session_id": "v1-missing",
"timestamp": "2026-01-03T00:00:00Z",
"model_id": "org/missing-model",
"method": "advanced",
"refusal_rate": None,
"perplexity": 2.0,
}
with (
patch("obliteratus.telemetry.read_telemetry", return_value=[v1_missing, v1_zero]),
patch("obliteratus.telemetry.fetch_hub_records", return_value=[v2_partial]),
):
leaderboard = get_leaderboard_data()
assert leaderboard[0]["model_id"] == "org/zero-model"
assert leaderboard[0]["best_refusal"] == 0.0
partial = next(row for row in leaderboard if row["model_id"] == "PartialArchitecture")
assert partial["runs"] == 1
assert partial["successful_runs"] == 0
assert partial["failed_runs"] == 1
assert partial["perplexity_measurements"] == 1
assert partial["best_perplexity"] == 3.0
assert partial["best_refusal"] is None
def test_invalid_ranges_do_not_enter_aggregates(self):
record = {
"session_id": "bad", "timestamp": "1", "model_id": "bad/model",
"method": "advanced", "refusal_rate": -0.1,
"perplexity": float("nan"), "coherence": True,
}
with (
patch("obliteratus.telemetry.read_telemetry", return_value=[record]),
patch("obliteratus.telemetry.fetch_hub_records", return_value=[]),
):
row = get_leaderboard_data()[0]
assert row["refusal_measurements"] == 0
assert row["perplexity_measurements"] == 0
assert row["coherence_measurements"] == 0
assert row["best_refusal"] is None
class TestTelemetryHubBoundaries:
def test_fetch_prefers_api_and_falls_back_to_git(self):
api_records = [{"session_id": "api"}]
with (
patch("obliteratus.telemetry._fetch_via_hf_api", return_value=api_records),
patch("obliteratus.telemetry._fetch_via_git_clone") as git_fetch,
):
assert fetch_hub_records(3) == api_records
git_fetch.assert_not_called()
git_records = [{"session_id": "git"}]
with (
patch("obliteratus.telemetry._fetch_via_hf_api", return_value=[]),
patch("obliteratus.telemetry._fetch_via_git_clone", return_value=git_records),
):
assert fetch_hub_records(3) == git_records
def test_fetch_returns_empty_when_both_boundaries_fail(self):
with (
patch("obliteratus.telemetry._fetch_via_hf_api", side_effect=RuntimeError("api")),
patch("obliteratus.telemetry._fetch_via_git_clone", side_effect=RuntimeError("git")),
):
assert fetch_hub_records() == []
def test_hf_api_parser_filters_files_malformed_lines_and_limit(self, tmp_path):
first = tmp_path / "first.jsonl"
second = tmp_path / "second.jsonl"
first.write_text('\n{"session_id":"one"}\nnot-json\n{"session_id":"two"}\n')
second.write_text('{"session_id":"three"}\n')
api = MagicMock()
api.list_repo_files.return_value = [
"README.md", "other/ignored.jsonl", "data/first.jsonl", "data/second.jsonl",
]
with (
patch("huggingface_hub.HfApi", return_value=api),
patch("huggingface_hub.hf_hub_download", side_effect=[str(first), str(second)]) as download,
):
records = _fetch_via_hf_api("org/repo", 2)
assert [record["session_id"] for record in records] == ["one", "two"]
assert download.call_count == 1
def test_log_from_dict_maps_partial_result_without_erasing_error(self):
with patch("obliteratus.telemetry.log_benchmark", return_value=True) as write:
assert log_benchmark_from_dict(
"org/model",
"advanced",
{"refusal_rate": 0.0, "perplexity": None, "error": "partial"},
dataset="fixture",
n_prompts=4,
pipeline_config={"n_directions": 3, "bayesian_trials": 2},
)
record = write.call_args.args[0]
assert record.refusal_rate == 0.0
assert record.perplexity is None
assert record.error == "partial"
assert record.n_directions == 3
assert record.use_bayesian is True
def test_push_to_hub_success_and_empty_short_circuits(self, tmp_path):
import obliteratus.telemetry as telemetry
output = tmp_path / "telemetry.jsonl"
output.write_text('{"session_id":"one"}\n')
api = MagicMock()
with (
patch.object(telemetry, "TELEMETRY_FILE", output),
patch("obliteratus.telemetry.read_telemetry", return_value=[{"session_id": "one"}]),
patch("obliteratus.telemetry._ensure_hub_repo", return_value=True),
patch("huggingface_hub.HfApi", return_value=api),
patch("obliteratus.telemetry._instance_slug", return_value="instance"),
):
assert push_to_hub("org/repo") is True
api.upload_file.assert_called_once()
assert api.upload_file.call_args.kwargs["path_in_repo"] == "data/instance.jsonl"
with patch("obliteratus.telemetry.read_telemetry", return_value=[]):
assert push_to_hub("org/repo") is False
get_leaderboard_data,
read_telemetry,