"""Thermal governor — maps a node agent snapshot to a 0..1 capacity score. A score of 1.0 means the node can accept a full build slot; 0.2 means it's near thermal throttling and should only get small jobs. Used by the recommendation engine + scheduler. """ from __future__ import annotations import logging from typing import Any, Mapping, Optional log = logging.getLogger(__name__) def thermal_cap(agent: Optional[Mapping[str, Any]]) -> float: """Return a 0..1 capacity score for the node described by ``agent``. Returns 0.3 (conservative) if ``agent`` is falsy or unreadable. """ if not agent: return 0.3 temp = agent.get("temp", "") load = agent.get("load", "1 1 1") try: cpu = float(str(load).split()[0]) except (ValueError, IndexError, AttributeError): log.debug("could not parse load=%r from agent; falling back to 1.0", load) cpu = 1.0 # safe X99 operating envelope if "90" in temp: return 0.2 if "80" in temp: return 0.5 if cpu > 4: return 0.6 return 1.0