"""Mode-conflict guard — assist vs practice mutual exclusivity (REQ-IDEATE-03, TASK-01-05). D-061 states assist is a separate mode (not concurrent with practice). This module enforces mutual exclusivity on the server side: starting an assist shift while a practice session is active (or vice versa) raises ModeConflictError. The existing /pipecat/webrtc endpoint (practice) calls enforce_mutual_exclusivity( ..., 'practice'); the new /api/assist/shift/start endpoint calls it with 'assist'. """ from __future__ import annotations from db.store import PraxisStore class ModeConflictError(Exception): """Raised when a learner tries to start a session of one type while an active session of the other type exists (REQ-IDEATE-03).""" async def enforce_mutual_exclusivity( store: PraxisStore, learner_id: str, requested_type: str ) -> None: """Raise ModeConflictError if the learner has an active session of the *other* type. requested_type: 'assist' or 'practice'. Ended sessions don't trigger the conflict (only active sessions count — ended_at IS NULL). """ other_type = "practice" if requested_type == "assist" else "assist" active = await store.get_active_session(learner_id, other_type) if active is not None: if requested_type == "assist": raise ModeConflictError( "Cannot start assist shift: a practice session is active. " "End the practice session first." ) raise ModeConflictError( "Cannot start practice session: an assist shift is active. " "End the shift first." ) __all__ = ["enforce_mutual_exclusivity", "ModeConflictError"]