File size: 14,126 Bytes
4879fc7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
"""Automated verification on new SOTA (Β§5.7): unit + integration tests."""
import json

import pytest

from app.verification import DEFERRED, SKIPPED, WRITTEN
from app.verifier import compute_verdict
from fakes import seed_agent, seed_result


AUDIT = "auditor/test-audit"
SCRATCH = "test-org/test-agent-1"


@pytest.fixture
def venv(make_env):
    return make_env(
        VERIFIER_ENABLED="true",
        VERIFIER_GUARD_FIELD="ppl",
        VERIFIER_GUARD_CAP="2.42",
        VERIFIER_SCORE_TOL="0.05",
    )


def seed_submission(hub, bucket=SCRATCH, prefix="submissions/v1"):
    hub.seed(f"{prefix}/manifest.json", '{"serve": ["python", "serve.py"]}', bucket=bucket)
    hub.seed(f"{prefix}/serve.py", "print('hi')", bucket=bucket)


def post_result(env, *, score=200.0, artifacts="hf://buckets/test-org/test-agent-1/submissions/v1/", extra_fm=""):
    fm = f"---\nscore: {score}\nmethod: vllm-fp8\nstatus: agent-run\ndescription: fast\n"
    if artifacts is not None:
        fm += f"artifacts: {artifacts}\n"
    fm += extra_fm + "---\nnotes\n"
    env.hub.seed("results/run.md", fm, bucket=SCRATCH)
    r = env.client.post(
        "/v1/results",
        json={"source": f"hf://buckets/test-org/test-agent-1/results/run.md"},
    )
    assert r.status_code == 201, r.text
    return r.json()["filename"]


def central_index(env):
    raw = env.hub.buckets[env.settings.central_bucket].get(
        "results/verification_status.json"
    )
    return json.loads(raw) if raw else {}


def good_summary(launch_to_hub, score=199.0, ppl=2.30):
    """on_launch hook: simulate the completed job writing summary.json."""
    hub, = launch_to_hub
    def hook(launch):
        hub.seed(
            f"{launch['run_prefix']}/summary.json",
            json.dumps({"score": score, "ppl": ppl, "completed": 80}),
            bucket=AUDIT,
        )
    return hook


# ───────────────────────── should_verify (SOTA check) ─────────────────────────


def test_should_verify_cold_start_any_positive_score(venv):
    seed_agent(venv.hub, "agent-1")
    assert venv.verifier.should_verify("x_agent-1.md", {"status": "agent-run", "score": 1.0})


def test_should_verify_requires_beating_valid_champion(venv):
    seed_agent(venv.hub, "agent-1")
    champ = seed_result(venv.hub, "20260601-100000-000", "agent-1", 300.0)
    pending = seed_result(venv.hub, "20260601-110000-000", "agent-1", 500.0)
    venv.hub.seed(
        "results/verification_status.json",
        json.dumps({champ: "valid", pending: "pending"}),
    )
    fm = {"status": "agent-run", "score": 300.0}
    assert not venv.verifier.should_verify("y_agent-1.md", fm)  # tie: not strictly greater
    assert venv.verifier.should_verify("y_agent-1.md", {**fm, "score": 300.1})
    # the 500-score pending result does NOT raise the bar β€” only `valid` does
    assert venv.verifier.should_verify("y_agent-1.md", {**fm, "score": 301.0})


def test_should_verify_rejects_non_agent_run_and_bad_score(venv):
    assert not venv.verifier.should_verify("x.md", {"status": "negative", "score": 999.0})
    assert not venv.verifier.should_verify("x.md", {"status": "agent-run", "score": -1})
    assert not venv.verifier.should_verify("x.md", {"status": "agent-run", "score": True})
    assert not venv.verifier.should_verify("x.md", {"status": "agent-run"})


def test_should_verify_skips_decided_and_in_flight(venv):
    seed_agent(venv.hub, "agent-1")
    a = seed_result(venv.hub, "20260601-100000-000", "agent-1", 100.0)
    venv.hub.seed("results/verification_status.json", json.dumps({a: "invalid"}))
    fm = {"status": "agent-run", "score": 100.0}
    assert not venv.verifier.should_verify(a, fm)  # already decided
    venv.verifier._in_flight.add("b_agent-1.md")
    assert not venv.verifier.should_verify("b_agent-1.md", fm)  # in flight


# ───────────────────────── submission resolution ─────────────────────────


def test_resolve_direct_hf_uri(venv):
    seed_submission(venv.hub)
    loc = venv.verifier.resolve_submission(
        {"artifacts": "hf://buckets/test-org/test-agent-1/submissions/v1/"},
        "agent-1",
    )
    assert loc == (SCRATCH, "submissions/v1")


def test_resolve_artifacts_dir_is_central(venv):
    venv.hub.seed("artifacts/sub_agent-1/manifest.json", "{}")
    venv.hub.seed("artifacts/sub_agent-1/serve.py", "x")
    loc = venv.verifier.resolve_submission({"artifacts": "artifacts/sub_agent-1/"}, "agent-1")
    assert loc == (venv.settings.central_bucket, "artifacts/sub_agent-1")


def test_resolve_relative_path_is_scratch_bucket(venv):
    seed_submission(venv.hub)
    loc = venv.verifier.resolve_submission({"submission": "submissions/v1"}, "agent-1")
    assert loc == (SCRATCH, "submissions/v1")


def test_resolve_run_dir_via_run_request(venv):
    seed_submission(venv.hub)
    venv.hub.seed(
        "runs/7/run_request.json",
        json.dumps({"submission_bucket": SCRATCH, "submission_prefix": "submissions/v1"}),
        bucket=SCRATCH,
    )
    loc = venv.verifier.resolve_submission({"artifacts": "runs/7/"}, "agent-1")
    assert loc == (SCRATCH, "submissions/v1")


def test_resolve_run_dir_via_job_status(venv):
    seed_submission(venv.hub)
    venv.hub.seed(
        "runs/8/job_status.json",
        json.dumps({"submission_prefix": "submissions/v1", "status": "completed"}),
        bucket=SCRATCH,
    )
    loc = venv.verifier.resolve_submission({"artifacts": "runs/8/"}, "agent-1")
    assert loc == (SCRATCH, "submissions/v1")


def test_resolve_unresolvable(venv):
    assert venv.verifier.resolve_submission({"artifacts": "nowhere/"}, "agent-1") is None
    assert venv.verifier.resolve_submission({}, "agent-1") is None


# ───────────────────────── verdict computation ─────────────────────────


def _verdict_settings(**overrides):
    from app.config import Settings

    kwargs = dict(
        HF_TOKEN="test-token",
        ORG="test-org",
        COLLAB_SLUG="test",
        AUDIT_BUCKET="auditor/test-audit",
        VERIFIER_SCORE_TOL="0.05",
        VERIFIER_GUARD_FIELD="ppl",
        VERIFIER_GUARD_CAP="2.42",
    )
    kwargs.update(overrides)
    return Settings(**kwargs)


def test_verdict_score_boundary():
    s = _verdict_settings()
    # exactly Β±5% is valid; just past it is invalid (both directions)
    v, d = compute_verdict(s, 100.0, {"score": 95.0, "ppl": 2.0})
    assert v == "valid" and d["score_ok"]
    v, _ = compute_verdict(s, 100.0, {"score": 94.9, "ppl": 2.0})
    assert v == "invalid"
    v, _ = compute_verdict(s, 100.0, {"score": 105.1, "ppl": 2.0})
    assert v == "invalid"


def test_verdict_guard_boundary():
    s = _verdict_settings()
    v, _ = compute_verdict(s, 100.0, {"score": 100.0, "ppl": 2.42})
    assert v == "valid"
    v, d = compute_verdict(s, 100.0, {"score": 100.0, "ppl": 2.43})
    assert v == "invalid" and not d["guard_ok"]


def test_verdict_no_guard_configured_skips_guard_check():
    s = _verdict_settings(VERIFIER_GUARD_FIELD="")
    v, d = compute_verdict(s, 100.0, {"score": 100.0})
    assert v == "valid" and "guard_ok" not in d


def test_verdict_missing_fields_is_undecidable():
    s = _verdict_settings()
    assert compute_verdict(s, 100.0, {"ppl": 2.0})[0] is None
    assert compute_verdict(s, 100.0, {"score": 100.0})[0] is None
    assert compute_verdict(s, 100.0, {"score": "fast", "ppl": 2.0})[0] is None


# ───────────────────────── set_verdict CAS ─────────────────────────


def ledger_path(filename):
    return f"verification_runs/{filename}/verdict.json"


def test_set_verdict_writes_over_pending_and_records_ledger(venv):
    venv.hub.seed("results/verification_status.json", json.dumps({"a.md": "pending"}))
    assert venv.verification.set_verdict("a.md", "valid", by="ver", details={"rerun_score": 1.0}) == WRITTEN
    assert central_index(venv)["a.md"] == "valid"
    rec = json.loads(venv.hub.buckets[AUDIT][ledger_path("a.md")])
    assert rec["state"] == "valid" and rec["by"] == "ver" and rec["rerun_score"] == 1.0


def test_set_verdict_writes_when_absent(venv):
    assert venv.verification.set_verdict("a.md", "invalid", by="ver") == WRITTEN
    assert central_index(venv)["a.md"] == "invalid"


def test_set_verdict_overwrites_own_prior_verdict(venv):
    venv.hub.seed("results/verification_status.json", json.dumps({"a.md": "pending"}))
    venv.verification.set_verdict("a.md", "valid", by="ver")
    assert venv.verification.set_verdict("a.md", "invalid", by="ver") == WRITTEN
    assert central_index(venv)["a.md"] == "invalid"


def test_set_verdict_defers_to_human_verdict(venv):
    # no ledger record β†’ this `invalid` must be human-authored
    venv.hub.seed("results/verification_status.json", json.dumps({"a.md": "invalid"}))
    assert venv.verification.set_verdict("a.md", "valid", by="ver") == DEFERRED
    assert central_index(venv)["a.md"] == "invalid"


def test_set_verdict_defers_when_human_changed_our_verdict(venv):
    venv.hub.seed("results/verification_status.json", json.dumps({"a.md": "pending"}))
    venv.verification.set_verdict("a.md", "valid", by="ver")
    # a human flips it to invalid out-of-band
    venv.hub.seed("results/verification_status.json", json.dumps({"a.md": "invalid"}))
    assert venv.verification.set_verdict("a.md", "valid", by="ver") == DEFERRED
    assert central_index(venv)["a.md"] == "invalid"


def test_set_verdict_skips_on_unreadable_index(venv):
    venv.hub.seed("results/verification_status.json", "{corrupt")
    assert venv.verification.set_verdict("a.md", "valid", by="ver") == SKIPPED
    assert venv.hub.buckets[AUDIT].get(ledger_path("a.md")) is None


# ───────────────────────── integration (API + fakes) ─────────────────────────


def test_sota_post_triggers_launch_verdict_and_announcement(venv):
    seed_agent(venv.hub, "agent-1")
    seed_submission(venv.hub)
    venv.runner.on_launch = good_summary([venv.hub], score=199.0, ppl=2.30)

    filename = post_result(venv, score=200.0)

    # launch happened against the resolved submission, /state pre-created
    assert len(venv.runner.launches) == 1
    launch = venv.runner.launches[0]
    assert launch["submission_bucket"] == SCRATCH
    assert launch["submission_prefix"] == "submissions/v1"
    run_prefix = launch["run_prefix"]
    assert run_prefix == f"verification_runs/{filename}"
    request = json.loads(venv.hub.buckets[AUDIT][f"{run_prefix}/verification_request.json"])
    assert request["reported_score"] == 200.0

    # verdict recorded: index flipped + private ledger record
    assert central_index(venv)[filename] == "valid"
    rec = json.loads(venv.hub.buckets[AUDIT][ledger_path(filename)])
    assert rec["state"] == "valid" and rec["job_id"] == "job-1"
    assert rec["rerun_score"] == 199.0 and rec["reported_score"] == 200.0

    # job artifacts landed in the private run dir
    assert f"{run_prefix}/job_logs.txt" in venv.hub.buckets[AUDIT]
    assert f"{run_prefix}/job_status.json" in venv.hub.buckets[AUDIT]

    # board announcement by the verifier, fanned out to the owner's inbox
    msgs = venv.client.get("/v1/messages?expand=true&limit=1").json()["items"]
    assert msgs and "VERIFIED VALID" in msgs[0]["body"]
    assert "@agent-1" in msgs[0]["body"]
    assert msgs[0]["frontmatter"]["agent"] == "test-verifier"
    assert msgs[0]["frontmatter"]["refs"] == [filename]
    inbox = [p for p in venv.hub.buckets[venv.settings.central_bucket] if p.startswith("inbox/agent-1/")]
    assert inbox

    # API view reflects the verdict
    assert venv.client.get(f"/v1/results/{filename}").json()["verification"] == "valid"


def test_non_sota_post_does_not_launch(venv):
    seed_agent(venv.hub, "agent-1")
    seed_submission(venv.hub)
    champ = seed_result(venv.hub, "20260601-100000-000", "agent-1", 500.0)
    venv.hub.seed("results/verification_status.json", json.dumps({champ: "valid"}))
    filename = post_result(venv, score=200.0)
    assert venv.runner.launches == []
    assert central_index(venv)[filename] == "pending"


def test_invalid_verdict_announced_with_failing_check(venv):
    seed_agent(venv.hub, "agent-1")
    seed_submission(venv.hub)
    venv.runner.on_launch = good_summary([venv.hub], score=150.0, ppl=2.30)  # Ξ” 25%

    filename = post_result(venv, score=200.0)

    assert central_index(venv)[filename] == "invalid"
    msgs = venv.client.get("/v1/messages?expand=true&limit=1").json()["items"]
    assert "INVALID" in msgs[0]["body"] and "❌" in msgs[0]["body"]


def test_unresolvable_submission_nudges_and_stays_pending(venv):
    seed_agent(venv.hub, "agent-1")
    filename = post_result(venv, score=200.0, artifacts="nowhere/")
    assert venv.runner.launches == []
    assert central_index(venv)[filename] == "pending"
    msgs = venv.client.get("/v1/messages?expand=true&limit=1").json()["items"]
    assert msgs and "couldn't" in msgs[0]["body"] and "runnable submission" in msgs[0]["body"]


def test_failed_job_leaves_pending_no_announcement(venv):
    seed_agent(venv.hub, "agent-1")
    seed_submission(venv.hub)
    venv.runner.terminal = ("error", "ERROR", "boom")
    filename = post_result(venv, score=200.0)
    assert len(venv.runner.launches) == 1
    assert central_index(venv)[filename] == "pending"
    assert venv.client.get("/v1/messages").json()["items"] == []
    # single-flight marker released β†’ a later event may retry
    assert filename not in venv.verifier._in_flight


def test_disabled_verifier_is_inert(env):
    # default env: VERIFIER_ENABLED=false
    seed_agent(env.hub, "agent-1")
    seed_submission(env.hub)
    post_result(env, score=200.0)
    assert env.runner.launches == []
    assert env.client.get("/v1/messages").json()["items"] == []