"""Scoring seam (Task 3). The UI depends only on the `Scorer` protocol, never on a concrete implementation. Swap `DummyScorer` for a real ML scorer with the same signature to go live. """ from .interface import Scorer, score_to_card # noqa: F401 from .dummy import DummyScorer # noqa: F401 def get_scorer(): """Return the REAL ObservableScorer when the backend scoring endpoint is configured (OPENBMB_BASE_URL / OPENBMB_TOKEN), else the heuristic DummyScorer. Import of the backend is lazy so the UI keeps running standalone with no ML deps installed.""" try: from .observable import ObservableScorer, backend_available if backend_available(): return ObservableScorer() except Exception: pass return DummyScorer()