Operators
How one attempt is made. The draft, debug, improve, ensemble scaffolds.
Operator registry: name -> class, mirroring policies and tuners.
The registry is the harness's operator vocabulary: candidate.OPERATORS,
policy check's known operators and the route preflight all derive from it,
so registering an operator is the only step that makes it usable.
class Operator(ABC):
"""One way of making an attempt. Subclasses set `name` and `role` and
implement `prepare`; `params` is the operator's own configuration."""
name: str
role: str
needs_target: bool = False
def __init__(self, params: Mapping | None = None):
self.params = dict(params or {})
def valid_target(self, target: Candidate | None) -> str | None:
"""Why this operator cannot run on `target`, or None when it can.
Checked by the harness before anything is created or spent."""
if self.needs_target and target is None:
return f"{self.name} without a target_id"
return None
@abstractmethod
def prepare(self, ctx: OperatorContext) -> Preparation: ...