"""Possession stability: a single number expressing how cleanly a spirit holds the channel for one reply. Shared contract between the backend audio degradation and the frontend text-glitch renderer (see docs/superpowers/specs/2026-07-23-possession-presentation-design.md).""" import random from typing import Callable _BASE_BY_RARITY = { "common": 0.35, "uncommon": 0.5, "rare": 0.65, "mythic": 0.8, } _MIN_STABILITY = 0.05 _MAX_STABILITY = 0.98 _MAX_MAGNITUDE_BONUS = 0.15 _JITTER_SPAN = 0.1 # rng() in [0, 1) is scaled to +/- this amount def compute_stability( rarity: str, magnitude: float, rng: Callable[[], float] = random.random, ) -> float: """How cleanly the spirit holds the channel for this reply, 0.05-0.98. Rarer spirits hold the channel more steadily (higher base). A stronger triggering anomaly gives a cleaner line, up to a capped bonus. A final rng-driven jitter of +/- 0.1 keeps it from feeling deterministic to the seeker. `rng` is injectable so a later quantum-RNG source can swap in real entropy without touching call sites. """ base = _BASE_BY_RARITY.get(rarity, _BASE_BY_RARITY["common"]) magnitude_bonus = min(_MAX_MAGNITUDE_BONUS, magnitude / 100) jitter = (rng() * 2 - 1) * _JITTER_SPAN stability = base + magnitude_bonus + jitter return max(_MIN_STABILITY, min(_MAX_STABILITY, stability))