"""Integration test for the REAL scorer seam (ObservableScorer -> backend pipeline -> live model). Skipped unless a scoring endpoint is configured (OPENBMB_BASE_URL / OPENBMB_TOKEN). Runs base-only (DISABLE_LORA) so it doesn't require Modal. Proves the adopted scoring path end-to-end on a fixture export. OPENBMB_BASE_URL=... OPENBMB_TOKEN=... python -m pytest ui/tests/test_scoring_live.py -q """ from __future__ import annotations import os import pytest pytestmark = pytest.mark.skipif( not (os.environ.get("OPENBMB_BASE_URL") and os.environ.get("OPENBMB_TOKEN")), reason="no scoring endpoint configured (set OPENBMB_BASE_URL / OPENBMB_TOKEN)", ) FIXTURE = os.path.join(os.path.dirname(__file__), "fixtures", "chatgpt_sample.json") def test_observable_scorer_end_to_end(): os.environ.setdefault("DISABLE_LORA", "1") # base-only: no Modal dependency from ui.parsing.parser import parse_export from ui.scoring.observable import ObservableScorer from ui.scoring import score_to_card from ui.data import AXES parsed = parse_export(FIXTURE) card = score_to_card(ObservableScorer().score(parsed), "Test") assert [a.name for a in card.axes] == AXES # canonical UI axis order assert all(0.0 <= a.score <= 10.0 for a in card.axes) # scores in range assert all(a.confidence in ("high", "medium", "low") for a in card.axes) assert 0.0 <= card.overall <= 10.0 assert card.tier[0] in ("D", "C", "B", "A", "S") # critical counts are real non-negative tallies assert all(n >= 0 for _, n in card.critical.as_pairs()) assert card.improvement