spinor-os / tests /test_server.py
luguog's picture
Deploy spinor-os as static HF Space receiver
bf3cbf1 verified
Raw
History Blame Contribute Delete
10.4 kB
"""Tests for the FastAPI backend."""
from __future__ import annotations
import pytest
from fastapi.testclient import TestClient
from spinor_os.config import EventType, LoopStage
from spinor_os.server import app, get_os
from spinor_os.assignment import AssignmentProviderRouter, LocalConstrainedAllocationProvider
from spinor_os.engine import ExperimentationOS
from spinor_os.models import PredictedEffect, Strategy
@pytest.fixture
def client():
"""Yield a TestClient with a fresh OS instance."""
with TestClient(app) as c:
yield c
def test_health(client):
response = client.get("/health")
assert response.status_code == 200
data = response.json()
assert data["status"] == "healthy"
assert data["server"] == "ok"
def test_ladder(client):
response = client.get("/ladder")
assert response.status_code == 200
data = response.json()
assert "maturity_ladder" in data
assert "canonical_loop" in data
def test_schema(client):
response = client.get("/schema")
assert response.status_code == 200
data = response.json()
assert "experiment" in data
assert "rl_action" in data
def test_full_experiment_flow(client):
os = get_os()
# Register employee.
r = client.post("/employees", json={
"employee_id": "api-001",
"role": "rep",
"territory": "northeast",
"skills": {"enterprise": 0.8},
})
assert r.status_code == 200
# Propose hypothesis.
r = client.post("/hypotheses", json={
"statement": "X increases Y",
"causal_claim": "X causes Y to increase.",
"predicted_effect": {
"metric": "y_rate",
"direction": "increase",
"magnitude": 0.1,
"unit": "pp",
"timing": "7d",
},
"employee_owner": "api-001",
"falsification_criteria": ["Y does not increase"],
"customer_segment": "enterprise",
"territory": "northeast",
"modification": "mod-api",
"required_replications": 1,
})
assert r.status_code == 200
hypothesis_id = r.json()["hypothesis_id"]
# Start experiment.
r = client.post("/experiments", json={"hypothesis_id": hypothesis_id})
assert r.status_code == 200
experiment_id = r.json()["experiment_id"]
# Allocate mission.
r = client.post(f"/experiments/{experiment_id}/missions", json={
"employee_id": "api-001",
"candidates": [{
"hypothesis_id": hypothesis_id,
"modification": "mod-api",
"customer_segment": "enterprise",
"territory": "northeast",
"timing": "2026-W31",
"resource_allocation": 1.0,
}],
})
assert r.status_code == 200
mission_id = r.json()["mission_id"]
# Record outcome event.
r = client.post(f"/experiments/{experiment_id}/events", json={
"mission_id": mission_id,
"event_type": "outcome_observed",
"actor_id": "api-001",
"outcome_value": 0.2,
"metric": "y_rate",
"execution_quality": 0.85,
})
assert r.status_code == 200
# Attribute.
r = client.post(f"/experiments/{experiment_id}/attributes", json={
"outcome_metric": "y_rate",
"outcome_value": 0.2,
"counterfactual_estimate": 0.05,
"method": "rct",
"confidence": 0.95,
"falsification_survived": True,
})
assert r.status_code == 200
claim = r.json()
assert claim["causal_effect"] == 0.15
# Advance to systemize.
r = client.post(f"/experiments/{experiment_id}/advance", json={"target": "systemize"})
assert r.status_code == 200
assert r.json()["current_stage"] == "systemize"
# Systemize and promote.
r = client.post("/systemize", json={
"experiment_id": experiment_id,
"name": "API Strategy",
"description": "Validated via API",
"automation_ready": True,
})
assert r.status_code == 200
strategy_id = r.json()["strategy_id"]
# Lower the registry threshold so this single experiment can promote.
os.golden_registry.rules.required_replications = 1
r = client.post("/promote", json={
"strategy_id": strategy_id,
"mechanism": "Validated via API test",
"automation_layer_id": "auto-api",
"adverse_retests": 1,
})
assert r.status_code == 200
assert r.json()["success"] is True
# ────────────────────────────── snapshot endpoints ──────────────────────────────
def test_snapshot_capture(client):
r = client.post("/snapshots/capture")
assert r.status_code == 200
data = r.json()
assert "snapshot_id" in data
assert "engine_state" in data
def test_snapshot_list(client):
client.post("/snapshots/capture")
r = client.get("/snapshots")
assert r.status_code == 200
data = r.json()
assert isinstance(data, list)
assert len(data) >= 1
def test_snapshot_latest(client):
client.post("/snapshots/capture")
r = client.get("/snapshots/latest")
assert r.status_code == 200
assert "snapshot_id" in r.json()
def test_snapshot_get_by_id(client):
cap = client.post("/snapshots/capture").json()
sid = cap["snapshot_id"]
r = client.get(f"/snapshots/{sid}")
assert r.status_code == 200
assert r.json()["snapshot_id"] == sid
def test_snapshot_ingest(client):
payload = {
"snapshot_id": "ingest-test-001",
"created_at": "2026-01-01T00:00:00Z",
"machine": "test-machine",
"sequence": 1,
"engine_state": {"employees": {}},
"working_tree": {"branch": "main", "head_sha": "abc", "status_short": "", "diff_stat": "", "file_hashes": {}},
"transcript": [],
}
r = client.post("/snapshots/ingest", json=payload)
assert r.status_code == 200
assert r.json()["status"] == "ok"
# ────────────────────────────── oracle endpoints ──────────────────────────────
def test_oracle_provenance(client):
r = client.get("/oracle/provenance")
assert r.status_code == 200
data = r.json()
assert "files" in data
assert "attestations" in data
assert data["file_count"] >= 1
def test_oracle_seo(client):
r = client.get("/oracle/seo")
assert r.status_code == 200
data = r.json()
assert "keywords" in data
assert "title_suggestion" in data
assert "sitemap_entry" in data
def test_oracle_full(client):
r = client.post("/oracle", json={"base_url": "https://test.local"})
assert r.status_code == 200
data = r.json()
assert "provenance" in data
assert "attribution_audit" in data
assert "seo" in data
def test_sitemap_xml(client):
r = client.get("/oracle/sitemap.xml")
assert r.status_code == 200
assert "urlset" in r.text
def test_robots_txt(client):
r = client.get("/robots.txt")
assert r.status_code == 200
assert "User-agent" in r.text
# ────────────────────────────── resume endpoint ──────────────────────────────
def test_resume_no_snapshot(client):
# Clear any existing snapshots by using a fresh manager dir is hard,
# so just test that resume works when a snapshot exists.
client.post("/snapshots/capture")
r = client.post("/resume", json={"steps": 1})
assert r.status_code == 200
data = r.json()
assert "engine_health" in data
assert "transitions" in data
def test_resume_with_steps(client):
client.post("/snapshots/capture")
r = client.post("/resume", json={"steps": 3})
assert r.status_code == 200
assert "steps_attempted" in r.json()
# ────────────────────────────── UI endpoint ──────────────────────────────
def test_ui_dashboard(client):
r = client.get("/ui")
assert r.status_code == 200
assert "<html" in r.text.lower()
assert "SPINOR" in r.text
def test_assign_endpoint_uses_real_strategy_library(client, monkeypatch):
"""/assign should route through the live OS and pick from the real strategy library."""
from spinor_os import server
os = ExperimentationOS(
persistence=None,
assignment_router=AssignmentProviderRouter(
primary=LocalConstrainedAllocationProvider(),
local=LocalConstrainedAllocationProvider(),
),
)
os.register_employee(
employee_id="assign-api-001",
role="field_representative",
territory="northeast",
)
strategy = Strategy(
name="Server /assign strategy",
description="Real strategy used by the server /assign endpoint test.",
hypothesis_id="HYP-ASSIGN-SERVER",
modification="server_assign_mod",
customer_segment="enterprise",
territory="northeast",
timing="2026-W31",
expected_effect=PredictedEffect(
metric="appointment_rate",
direction="increase",
magnitude=0.12,
unit="percentage_point",
timing="7d",
confidence=0.8,
),
owner="assign-api-001",
maturity="validated_mechanism",
replication_count=3,
automation_ready=True,
)
os.strategies[strategy.strategy_id] = strategy
monkeypatch.setattr(server, "get_os", lambda: os)
r = client.post("/assign", json={
"organization_id": "org_server_test",
"employee_id": "assign-api-001",
"role": "field_representative",
"context": {"territory": "northeast"},
})
assert r.status_code == 200
data = r.json()
assert data["count"] == 1
assert data["decisions"][0]["assigned_strategy_id"] == strategy.strategy_id
library = data["provenance"][0]["sanitized_request"]["context"]["strategy_library"]
assert any(s["strategy_id"] == strategy.strategy_id for s in library)
def test_dashboard_alias(client):
r = client.get("/dashboard")
assert r.status_code == 200
assert "<html" in r.text.lower()