whassan's picture
Deploy Sensorflow Studio (part 3)
963e554 verified
Raw History Blame Contribute Delete
6.08 kB
"""API lifecycle over the /api/agentic router via TestClient."""
from __future__ import annotations
import copy
import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from sensorflow.agentic.api import router
@pytest.fixture(scope="module")
def client(agentic_env):
app = FastAPI()
app.include_router(router)
return TestClient(app)
@pytest.fixture(scope="module")
def ped_cone_id(client):
res = client.post("/api/agentic/failures/detect", json={})
assert res.status_code == 200
events = res.json()["failures"]
assert events
flip = next(e for e in events
if e["kind"] == "classification_flip"
and "pedestrian" in e["title"]
and "construction_cone" in e["title"])
return flip["failure_id"]
def test_detect_and_queue(client, ped_cone_id):
res = client.get("/api/agentic/failures")
assert res.status_code == 200
queue = res.json()["failures"]
assert any(f["failure_id"] == ped_cone_id for f in queue)
res = client.get(f"/api/agentic/failures/{ped_cone_id}")
basis = res.json()["failure"]["detection_basis"]
assert basis["denominator"] > 0 and basis["candidate_events"] > 0
def test_staged_analysis_and_evidence(client, ped_cone_id):
# step stage by stage; stage order is enforced by the orchestrator
for stage in ("EVIDENCE_AGGREGATION", "FAILURE_ANALYSIS",
"LAUNCH_DECISION"):
res = client.post(
f"/api/agentic/failures/{ped_cone_id}/analyze?stage={stage}",
json={})
assert res.status_code == 200, res.text
state = res.json()["state"]
rec = next(s for s in state["stages"] if s["stage"] == stage)
assert rec["status"] == "complete"
res = client.get(f"/api/agentic/failures/{ped_cone_id}/evidence")
graph = res.json()["graph"]
assert {n["node_type"] for n in graph["nodes"]} >= {"Object", "GroundTruth",
"Frequency"}
res = client.get(f"/api/agentic/failures/{ped_cone_id}/snippets")
assert res.json()["snippets"]
res = client.post(f"/api/agentic/failures/{ped_cone_id}/cluster", json={})
assert res.status_code == 200
res = client.post(
f"/api/agentic/failures/{ped_cone_id}/safety-assessment", json={})
assert res.status_code == 200
res = client.post(
f"/api/agentic/failures/{ped_cone_id}/launch-assessment", json={})
body = res.json()
assert body["policy_evaluation"]["outcome"] in (
"AUTOMATIC_STOP_SHIP", "LAUNCH_REVIEW_REQUIRED",
"CONTINUE_INVESTIGATION", "NO_LAUNCH_IMPACT", "INDETERMINATE")
assert body["policy_evaluation"]["policy_version"]
def test_human_review_and_flywheel(client, ped_cone_id):
res = client.post(
f"/api/agentic/failures/{ped_cone_id}/human-review",
json={"reviewer": "api-test-reviewer",
"decision": "confirm_failure",
"rationale": "GT verified against synthetic vendor labels",
"evidence_reviewed": ["evidence_graph", "snippets"]})
assert res.status_code == 200
res = client.get(f"/api/agentic/failures/{ped_cone_id}/human-review")
assert any(d["reviewer"] == "api-test-reviewer"
for d in res.json()["decisions"])
# LEARNING_FLYWHEEL now permitted (failure validated by the human)
res = client.post(
f"/api/agentic/failures/{ped_cone_id}/analyze?stage=LEARNING_FLYWHEEL",
json={})
assert res.status_code == 200
res = client.get("/api/agentic/evaluation-suites")
suites = res.json()["suites"]
assert suites
suite = suites[0]
res = client.get(f"/api/agentic/evaluation-suites/{suite['suite_id']}")
assert res.status_code == 200
# contamination guard over the API: promotion without override -> 4xx
member_id = suite["members"][0]["member_id"]
res = client.post(
f"/api/agentic/evaluation-suites/{suite['suite_id']}/promote-member",
json={"member_id": member_id})
assert res.status_code in (400, 403, 409, 422)
def test_policy_endpoints(client):
res = client.get("/api/agentic/policy")
assert res.status_code == 200
doc = res.json()["policy"]
assert doc["policy_version"]
mutated = copy.deepcopy(doc)
mutated["expected_loss"]["delay_cost"] = 123.0
res = client.post("/api/agentic/policy",
json={"policy": mutated, "actor": "api-test"})
assert res.status_code == 200
new_version = res.json()["policy_version"]
assert new_version != doc["policy_version"]
res = client.get(f"/api/agentic/policy?version={doc['policy_version']}")
assert res.status_code == 200
res = client.get("/api/agentic/policy/versions")
assert len(res.json()["versions"]) >= 2
# restore the original as active for other tests
res = client.post("/api/agentic/policy",
json={"policy": doc, "actor": "api-test"})
assert res.status_code == 200
def test_regression_scorecard_audit_and_worked_example(client, ped_cone_id):
res = client.post("/api/agentic/regression/evaluate", json={})
assert res.status_code == 200
assert res.json()["suites"]
res = client.get(f"/api/agentic/audit/{ped_cone_id}")
body = res.json()
assert body["records"]
assert body["chain"]["valid"] is True
res = client.get("/api/agentic/worked-example")
assert res.status_code == 200
we = res.json()["walkthrough"]
assert we["layers"]["4_launch_decision"]["outcome"]["value"]
card_id = we["scorecard_id"]
res = client.get(f"/api/agentic/scorecards/{card_id}")
assert res.status_code == 200
card = res.json()["scorecard"]
for field in ("frequency", "exposure", "severity", "confidence",
"novelty", "concentration", "downstream_impact",
"mitigations", "residual_risk"):
f = card[field]
assert f["tag"] in ("OBSERVED", "PREDICTED", "HYPOTHETICAL",
"REQUIRED_EVIDENCE")
assert f["evidence_ref"]