Skip to content

Configuration shifts — API reference

Every public symbol in skyfall_crl.regime, generated from the source.

Generated page — built from the source docstrings, so this file is blank when read on GitHub. Run mkdocs serve to read it locally, or read the docstrings in the module itself.

Providers

base

Who decides which configuration is active.

The environment asks one question -- what configuration are we in at this step -- and the answer can come from a schedule that was written in advance or, in principle, from something watching the world and inferring that it has changed. Both answer the same question, so both satisfy the same contract, and neither is privileged.

Providers register by name so a run can name one in configuration rather than importing it.

DEFAULT_REGIME_ID module-attribute

DEFAULT_REGIME_ID = 'baseline'

REGIME_PROVIDERS module-attribute

REGIME_PROVIDERS: dict[
    str, Callable[..., RegimeProvider]
] = {
    "constant": ConstantRegime,
    "scheduled": ScheduledRegime,
}

RegimeProvider

Bases: Protocol

Reports which configuration is active at a given step.

regime_id
regime_id(step: int) -> str

The active configuration's name.

ConstantRegime

A world whose configuration never changes.

A run under this provider is stationary -- a useful control, and not a continual-learning setting.

regime_id
regime_id(step: int) -> str
regime_at
regime_at(step: int) -> Regime

ScheduledRegime

Follows a schedule written in advance -- the default way to shift a world.

schedule may be a RegimeSchedule, the mapping one is built from, or the path to a YAML file holding it. The last two exist because a run is selected by configuration: {"provider": "scheduled", "params": {"schedule": ...}} builds this class directly, and a document cannot name an object. Accepting only the built form made that path silently produce a provider that raised on its first step.

schedule instance-attribute
schedule = _as_schedule(schedule)
from_yaml_file classmethod
from_yaml_file(path: str) -> ScheduledRegime
from_dict classmethod
from_dict(config: Mapping[str, Any]) -> ScheduledRegime
regime_id
regime_id(step: int) -> str
regime_at
regime_at(step: int) -> Regime
is_boundary
is_boundary(step: int) -> bool

register_provider

register_provider(
    name: str, factory: Callable[..., RegimeProvider]
) -> None

Make a provider available by name, so a run can select it without importing it.

get_provider

get_provider(name: str) -> Callable[..., RegimeProvider]

The provider factory registered under name.

Raises KeyError naming what is registered, so a typo in a config reports the available options rather than a bare miss.

available_providers

available_providers() -> tuple[str, ...]

The names a config may select, sorted. Registering a provider adds to this.

Schedules

schedule

What configuration a world is running under, and when it changes.

A world's configuration shifts while an agent works in it. A schedule says which configuration is active at each step and how one gives way to the next -- abruptly, on a loop, or by drifting gradually into it.

One detail carries more weight than it looks: a configuration can recur under a new name (alias_of). Measuring whether an agent has forgotten something requires meeting the same conditions twice and comparing, so a schedule with no recurrence gives a forgetting metric nothing to work with.

A repeat keeps its own label and records what it repeats (Regime.origin), so a trace shows which visit this is while the metrics can still tell what is being visited. Without that second half a repeat would read as an unrelated configuration and forgetting would come back unavailable for both.

SHIFT_MODES module-attribute

SHIFT_MODES = ('abrupt', 'cyclic', 'linear_drift')

KNOWN_AXES module-attribute

KNOWN_AXES: frozenset[str] = frozenset(
    {
        "ticket_arrival_rate",
        "chaos_type_distribution",
        "capacity_multiplier",
        "priority_distribution",
        "affected_service_distribution",
        "deadline_tightness_multiplier",
        "demand_surge_multiplier",
        "workforce_capacity",
        "job_duration_distribution",
        "service_level_distribution",
    }
)

Regime dataclass

One configuration: what it is called, how long it lasts, and how it behaves.

regime_id instance-attribute
regime_id: str
duration_steps class-attribute instance-attribute
duration_steps: int | None = None
axes class-attribute instance-attribute
axes: Mapping[str, Any] = field(default_factory=dict)
origin class-attribute instance-attribute
origin: str | None = None
identity property
identity: str

What configuration this is, whatever it is called here.

Two entries share an identity when one repeats the other. Forgetting is measured over identities rather than labels, because meeting the same conditions twice is the whole of what it asks about.

get
get(name: str, default: Any = None) -> Any
select
select(names: Collection[str] | str) -> dict[str, Any]

The axes named here that this configuration actually sets.

exclude
exclude(names: Collection[str] | str) -> dict[str, Any]

Every axis except the ones named.

Which axes an environment can be told about is the environment's business, not the schedule's, so the schedule offers the split and lets the adapter decide where it falls.

to_dict
to_dict() -> dict[str, Any]

RegimeSchedule

The configurations a run passes through, and when.

Parameters

regimes: In order. Each needs a regime_id; duration_steps may be omitted on the last one to mean "until the run ends". An entry with alias_of repeats another configuration under a new name. shift_mode: abrupt switches at the boundary, cyclic loops back to the start, and linear_drift eases into the next configuration over drift_window steps.

shift_mode instance-attribute
shift_mode = shift_mode
drift_window instance-attribute
drift_window = max(int(drift_window), 1)
seed instance-attribute
seed = int(seed)
regimes property
regimes: tuple[Regime, ...]
total_steps property
total_steps: int

Steps before the schedule repeats, or 0 if the last configuration runs forever.

from_dict classmethod
from_dict(config: Mapping[str, Any]) -> RegimeSchedule
from_yaml_file classmethod
from_yaml_file(path: str | Path) -> RegimeSchedule
regime_at
regime_at(step: int) -> Regime

The configuration active at step.

regime_id
regime_id(step: int) -> str

The active configuration's name -- the reporting contract the environment uses.

is_boundary
is_boundary(step: int) -> bool

Whether step is where a configuration begins.

Axes and the chaos payload

chaos

Turning a configuration into something a deployment can be told.

Only two of a configuration's axes mean anything to the deployment: how often incidents arrive, and which kinds. Everything else describes conditions this side reasons about.

Kept separate from the schedule so that what a configuration is and how it is pushed can change independently -- and so the payload can be checked without a world to push it to.

BACKEND_AXES module-attribute

BACKEND_AXES = (
    "ticket_arrival_rate",
    "chaos_type_distribution",
)

KNOWN_CHAOS_TYPES module-attribute

KNOWN_CHAOS_TYPES = frozenset(
    {
        "missing_data",
        "stale_data",
        "format_change",
        "rate_limit",
        "dependency_failure",
        "invalid_state",
        "partial_data",
        "duplicate_data",
        "timing_issue",
        "permission_denied",
        "data_corruption",
    }
)

DEFAULT_ARRIVAL_RATE module-attribute

DEFAULT_ARRIVAL_RATE = 0.3

backend_axes

backend_axes(regime: Regime) -> dict[str, Any]

The axes of regime a deployment can be told about.

local_axes

local_axes(regime: Regime) -> dict[str, Any]

The axes a deployment has no notion of -- capacity, priorities, demand, and so on.

Reported rather than pushed, so a task view can act on them.

chaos_payload

chaos_payload(
    regime: Regime, *, seed: int = 42
) -> dict[str, Any]

Describe a configuration in the form a deployment accepts.

A failure kind the deployment would not recognise is left out rather than allowed to fail the whole shift: losing one weight from a distribution is a far better outcome than a configuration change that silently never happened.