"""Operational mode flags read from the environment. Cerbero Bite supports two independent runtime switches: * ``CERBERO_BITE_ENABLE_DATA_ANALYSIS`` — when ``true``, the periodic market-snapshot job is scheduled and writes 15-minute snapshots to ``market_snapshots``; when ``false``, the bot still pings MCP for health and reconciliation but does not record any market dataset. * ``CERBERO_BITE_ENABLE_STRATEGY`` — when ``true``, the entry and monitor cycles are scheduled and may propose/execute trades; when ``false``, no entry or monitor logic runs autonomously (the methods remain callable from the CLI ``dry-run`` and via manual actions, so the operator can still test code paths on demand). The default profile is "analysis only": data analysis on, strategy off. This is the mode used during the post-deploy soak window where the team observes data quality before opening any position. """ from __future__ import annotations import os from dataclasses import dataclass __all__ = [ "DATA_ANALYSIS_ENV", "STRATEGY_ENV", "RuntimeFlags", "load_runtime_flags", ] DATA_ANALYSIS_ENV = "CERBERO_BITE_ENABLE_DATA_ANALYSIS" STRATEGY_ENV = "CERBERO_BITE_ENABLE_STRATEGY" _TRUE_TOKENS = frozenset({"1", "true", "yes", "on", "enabled"}) _FALSE_TOKENS = frozenset({"0", "false", "no", "off", "disabled"}) @dataclass(frozen=True) class RuntimeFlags: """Boolean switches that gate optional cycles. Both fields default to the canonical "analysis only" profile. """ data_analysis_enabled: bool = True strategy_enabled: bool = False def _parse_bool(raw: str, *, var: str, default: bool) -> bool: cleaned = raw.strip().lower() if not cleaned: return default if cleaned in _TRUE_TOKENS: return True if cleaned in _FALSE_TOKENS: return False raise ValueError( f"{var}: expected one of " f"{sorted(_TRUE_TOKENS | _FALSE_TOKENS)}, got {raw!r}" ) def load_runtime_flags(env: dict[str, str] | None = None) -> RuntimeFlags: """Build a :class:`RuntimeFlags` from environment variables.""" e = env if env is not None else os.environ return RuntimeFlags( data_analysis_enabled=_parse_bool( e.get(DATA_ANALYSIS_ENV, ""), var=DATA_ANALYSIS_ENV, default=True, ), strategy_enabled=_parse_bool( e.get(STRATEGY_ENV, ""), var=STRATEGY_ENV, default=False, ), )