Configuration reference¶
Everything a user writes is one of four document kinds: an experiment, a sweep, a schedule, or a reward specification. This page is their complete field-level contract. Every field on it is checked against the models when the documentation is tested, so a field added to the code without a row here fails the build.
Two rules hold for all four:
- An unknown key is an error, not a no-op. Every model rejects a key it does not declare, with a message naming it — so a misspelled or misplaced key fails at load rather than silently changing nothing.
- The free-form surfaces are deliberate.
kwargsandparamsmappings pass through untouched to whatever they construct; a schedule's axes are an open set; trace rows and bundle manifests tolerate extra fields. Everything else is closed.
The experiment document¶
One document fully specifies a run — L1 walks a complete one.
Loaded by skyfall-crl run --config, or in Python via ExperimentConfig.from_yaml_file /
from_dict.
| Section | Required | Meaning |
|---|---|---|
env |
yes | which environment to build |
algorithm |
yes | which backend trains, and with what |
rollout |
no | how much experience per update, and in total |
regime |
no | which configuration-shift provider labels (and may drive) the run |
run |
no | identity and outputs |
reward |
no | hand scoring to the composable reward system — absence is meaningful: without it the environment scores itself, which is the Tier-1 path |
env¶
| Field | Type | Default | Meaning |
|---|---|---|---|
id |
str | required | A registered Gymnasium id (CartPole-v1) or a dotted package.module:factory — how anything not in the registry, including a module loaded with --plugin, is selected. |
kwargs |
mapping | {} |
Passed to the factory verbatim. Free-form. |
algorithm¶
| Field | Type | Default | Meaning |
|---|---|---|---|
name |
str | required | A registered backend (discrete_hill_climbing, ppo, ppo_ewc, ppo_lcm, or one a plugin registered). Checked against the registry at load, so a typo fails before any compute — which also means a plugin's config must be read after the plugin registers. |
params |
mapping | {} |
The backend's constructor arguments. Free-form; seeds like replay_seed and fisher_seed live here. |
policy |
mapping or absent | absent | The policy the backend trains, when it should not build its own default — required for export, since the bundle must record how to rebuild it. |
algorithm.policy¶
| Field | Type | Default | Meaning |
|---|---|---|---|
id |
str | required | A dotted package.module:factory. Resolved at build time, so naming a policy that needs torch costs nothing until the run starts. |
kwargs |
mapping | {} |
Passed to the factory verbatim. Free-form. |
rollout¶
| Field | Type | Default | Meaning |
|---|---|---|---|
window_steps |
int > 0 | 64 |
Steps per window — an administrative slice, one update each; a window boundary ends nothing. |
total_steps |
int > 0 | 1024 |
Steps the whole run collects. |
auto_reset |
bool | false |
Start a new episode when one genuinely ends. Off is the safe default: in a persistent world a reset destroys the world. An environment with real terminal states — CartPole — needs it on. |
regime¶
| Field | Type | Default | Meaning |
|---|---|---|---|
provider |
str | constant |
A registered provider. constant is a stationary control; scheduled follows a schedule; a plugin may register a detector. |
params |
mapping | {} |
The provider's constructor arguments — for scheduled, {schedule: <the mapping, or a path to a YAML file holding it>}. Free-form. |
An environment that reports its own labels (info["regime"], the Tier-2 way) wins over this
section, which may then be omitted entirely.
run¶
Everything here ends up in the trace's run metadata, which is what grouping and aggregation key on.
| Field | Type | Default | Meaning |
|---|---|---|---|
name |
str | run |
Becomes the rows' run_id. |
seed |
int | unset | Seeds the environment's reset — and nothing else. Anything else the seed should reach is written where it belongs (params, kwargs), which in a sweep is what ${seed} is for. |
task |
str | unset | The task label, when a sweep varies one. |
policy_id |
str | unset | Recorded policy identity. |
algorithm_id |
str | unset | The family label a comparison groups on. Filled in from algorithm.name when unset; a sweep sets it to the family's name. |
output_dir |
str | unset | Directory to write <run name>/traces.jsonl under. |
trace_path |
str | unset | Exact trace file path; overrides output_dir. |
reward¶
| Field | Type | Default | Meaning |
|---|---|---|---|
spec |
str or mapping | required if the section is present | A registered spec name (paper), an inline specification, or a path to a YAML/JSON file. Naming the section and omitting the spec is an error — there is no default reward, deliberately. |
The sweep document¶
A matrix of experiments as one document — L4 builds one.
Loaded by skyfall-crl run --matrix.
| Field | Type | Default | Meaning |
|---|---|---|---|
base |
mapping | required | What every cell shares: an experiment document, minus whatever the axes supply. |
families |
mapping | one unnamed arm | Name → overrides. Each family is one arm; its name becomes the cells' algorithm_id. Two arms may share a backend and differ only in params — a family is an arm, not necessarily an algorithm. |
seeds |
list of int | [0] |
One cell per seed per family (per task). |
tasks |
list or mapping | none | A task axis: a list of names (labels only) or name → overrides (a task that changes the environment). Cells record the task in run.task; a family that pools several tasks is flagged by aggregate. |
output_dir |
str | unset | Where every cell writes <cell name>/traces.jsonl. |
Merging is section-wise, one level deep. A family's {algorithm: {params: ...}} replaces
base's algorithm.params mapping wholesale and keeps algorithm.name; deeper merging is
deliberately not done, because a nested merge cannot express removing a key.
${seed} is substituted wherever it appears — exact string matches, however deeply nested —
and becomes that cell's integer seed. This is how the seed reaches the policy's initialisation or
a replay draw: the author writes it where it belongs, rather than the harness guessing which knob
was meant.
Cell names are <family>-seed<N>, or <family>-<task>-seed<N> with a task axis, and become
each cell's run.name. Expansion order is family, then task, then seed — families outermost, so
an interrupted sweep leaves whole arms finished.
The schedule mapping¶
The scheduled provider's document — regimes and schedules
explains the concepts. Written inline under regime.params.schedule, or as its own YAML file.
| Key | Type | Default | Meaning |
|---|---|---|---|
regimes |
list | required | The configurations, in order. |
shift_mode |
abrupt | cyclic | linear_drift |
abrupt |
How one gives way to the next: whole at the boundary; wrapping around for as long as the run lasts; or easing numeric axes over the final drift_window steps (values that cannot be blended switch at the window's midpoint). |
drift_window |
int ≥ 1 | 50 |
The easing window for linear_drift. |
Each entry in regimes:
| Key | Type | Default | Meaning |
|---|---|---|---|
regime_id |
str | required | The label the trace records. |
duration_steps |
int | until the run ends | May be omitted only on the last entry. |
alias_of |
str | — | Repeat another entry's axes under this new label — the recurrence forgetting requires. The origin is recorded on every row. |
| anything else | An axis. The set is deliberately open. Known names something ships code to read: 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. A key within a small edit distance of one of these warns (tickt_arival_rate is almost never intentional); a key literally named axes is rejected as certain nesting-by-mistake; a genuinely new name passes untouched. |
The reward specification¶
The reward as data — rewards as data explains the model.
Selected by name, written inline, or loaded from a file; resolvable from all three by
resolve_reward_spec.
| Field | Type | Default | Meaning |
|---|---|---|---|
name |
str | required | The specification's own name, recorded wherever the reward travels. |
components |
list | required | The terms. |
aggregation |
str | weighted_sum |
How contributions combine. weighted_sum is the only shipped aggregation. |
gates |
list | [] |
Conditional zeroing rules. |
Each entry in components:
| Field | Type | Default | Meaning |
|---|---|---|---|
type |
str | required | A registered component — one of the seven built-ins, or one a plugin registered. Resolved when the engine is built, not when the document parses. |
weight |
float | the component's own | Override for this specification. |
clip |
[low, high] |
the component's own | Override for this specification. The clip is also what makes the ceiling derivable. |
params |
mapping | {} |
The component's constructor arguments. Free-form. |
Each entry in gates:
| Field | Type | Default | Meaning |
|---|---|---|---|
component |
str | required | Whose contribution is gated. |
unless_any_positive |
list of str | [] |
The contribution is zeroed for the step unless at least one named component's contribution is positive — for terms that should pay only alongside real progress. |
Four specifications ship as both registered names and editable YAML templates
(skyfall_crl/rewards/spec_files/): paper, experiment, eval8, verification_progress —
all describing MORPHEUS's operational model, which is why none of them is ever a default.