fleetmind / validate_submission.py
Rishav
Harden v3 scoring contract
9850bda
Raw
History Blame Contribute Delete
5.62 kB
from __future__ import annotations
import json
import os
import subprocess
import sys
from pathlib import Path
import yaml
from fastapi.testclient import TestClient
sys.path.insert(0, str(Path(__file__).resolve().parent / "src"))
from delivery_dispatch_v3.api import app
from delivery_dispatch_v3.environment import V3DeliveryDispatchEnv
from delivery_dispatch_v3.models import V3Action, V3Observation, V3StepResult
from delivery_dispatch_v3.task_adapter import PUBLIC_TASK_IDS
def check(condition: bool, message: str) -> None:
if not condition:
raise AssertionError(message)
def validate_openenv_yaml() -> dict:
path = Path("openenv.yaml")
check(path.exists(), "openenv.yaml is missing")
data = yaml.safe_load(path.read_text())
check(data["name"] == "fleetmind-v3-openenv", "openenv.yaml name mismatch")
task_ids = [task["id"] for task in data["tasks"]]
check(tuple(task_ids) == PUBLIC_TASK_IDS, "openenv.yaml tasks do not match public v3 tasks")
return data
def validate_environment_contract() -> None:
env = V3DeliveryDispatchEnv("medium_dispatch")
observation = env.reset(task_id="easy_dispatch", seed=17031)
check(isinstance(observation, V3Observation), "reset() must return V3Observation")
check(observation.task_id == "easy_dispatch", "reset() should expose public task id")
state = env.state()
check(isinstance(state, V3Observation), "state() must return V3Observation")
step_result = env.step(V3Action(target_allocations=[]))
check(isinstance(step_result, V3StepResult), "step() must return V3StepResult")
check(step_result.reward.cumulative_reward == step_result.reward.cumulative_reward, "reward object should be accessible")
def validate_inference() -> dict:
import inference
result = inference.score_tasks("baseline")
check("tasks" in result and "overall_score" in result, "inference output missing keys")
check(len(result["tasks"]) >= 3, "inference must score at least three tasks")
for task in result["tasks"]:
check(0.0 < float(task["score"]) < 1.0, f"task score must be strictly between 0 and 1 for {task['task_id']}")
return result
def validate_inference_cli_output() -> None:
env = os.environ.copy()
env.pop("HF_TOKEN", None)
env.pop("OPENAI_API_KEY", None)
completed = subprocess.run(
[sys.executable, "inference.py"],
cwd=Path(__file__).resolve().parent,
capture_output=True,
text=True,
env=env,
check=True,
)
stdout = completed.stdout
check("[START]" in stdout, "inference.py stdout is missing [START] block")
check("[STEP]" in stdout, "inference.py stdout is missing [STEP] block")
check("[END]" in stdout, "inference.py stdout is missing [END] block")
def validate_inference_cli_output_with_configured_llm_if_present() -> None:
env = os.environ.copy()
token = env.get("HF_TOKEN") or env.get("OPENAI_API_KEY")
if not token:
return
completed = subprocess.run(
[sys.executable, "inference.py"],
cwd=Path(__file__).resolve().parent,
capture_output=True,
text=True,
env=env,
check=True,
)
stdout = completed.stdout
check("[START]" in stdout, "configured inference.py stdout is missing [START] block")
check("[STEP]" in stdout, "configured inference.py stdout is missing [STEP] block")
check("[END]" in stdout, "configured inference.py stdout is missing [END] block")
def validate_http_api() -> None:
client = TestClient(app)
health = client.get("/health")
check(health.status_code == 200, "/health must return 200")
for task_id in PUBLIC_TASK_IDS:
reset = client.post("/reset", params={"task_id": task_id, "seed": 12345})
check(reset.status_code == 200, f"/reset must return 200 for {task_id}")
reset_body = reset.json()
check(reset_body["task_id"] == task_id, f"/reset should expose requested public task {task_id}")
invalid_reset = client.post("/reset", params={"task_id": "unknown_dispatch"})
check(invalid_reset.status_code == 400, "/reset must reject unknown task_id with 400")
reset = client.post("/reset")
check(reset.status_code == 200, "/reset without task_id must return 200")
check(reset.json()["task_id"] in PUBLIC_TASK_IDS, "/reset without task_id should choose a public task")
state = client.get("/state")
check(state.status_code == 200, "/state must return 200")
step = client.post("/step", json={"target_allocations": []})
check(step.status_code == 200, "/step must return 200")
step_body = step.json()
check("observation" in step_body and "reward" in step_body, "/step response shape is invalid")
def validate_docker_build() -> None:
completed = subprocess.run(
["docker", "build", "-t", "fleetmind-v3-openenv", "."],
cwd=Path(__file__).resolve().parent,
capture_output=True,
text=True,
)
check(completed.returncode == 0, f"Docker build failed:\n{completed.stderr}")
def main() -> None:
yaml_data = validate_openenv_yaml()
validate_environment_contract()
inference_result = validate_inference()
validate_inference_cli_output()
validate_inference_cli_output_with_configured_llm_if_present()
validate_http_api()
validate_docker_build()
summary = {
"status": "ok",
"openenv_name": yaml_data["name"],
"tasks": [task["id"] for task in yaml_data["tasks"]],
"inference": inference_result,
}
print(json.dumps(summary, indent=2))
if __name__ == "__main__":
main()