runner — sim runner / controller dispatch front-end
Purpose
Thin front-end from a run-spec YAML to a finished run: load the spec, build a
RunContract,
dispatch to the right controller (base/com/arm) or a guidance-only rollout, return aRunResult.
One run in, one logged result out — it owns dispatch, not the analyze→plot→report loop.
Role in the system
- Driven by orchestrator (the pipeline loop): orchestrator builds contexts and calls
Runner.run;
runner is never reached across module boundaries by logger/plotter/reporter. - Spec loading delegates to pre_run_loader (
RunSpecLoader.prepare→ spec, built cfg, ctx, names). - Live path constructs a GNC controller — base_controller (
base), com_controller (com),
or breve_controller (arm, the live workhorse) — and calls itsrun_all. - Guidance-only path uses ee_guidance + guidance_rollout (
build_guidance_only_rollout): selection /
coverage without controller dynamics. - Output flows into logger (
Logger/LogStore) → NPZ → data_analyzer.
Inputs / Outputs
- In: a run-spec stem (default
"run"); optional per-run overridectx(a config-override object). - Out:
RunResult— the prepared contract (spec,cfg,ctx,run_name,run_dir) plus the
populatedloggerandlog_path.
Key methods / functions
Runner.run— prepare → safety-check → execute → wrap asRunResult—analysis/runner.py:77Runner.prepared_context— prepared contract for an overridectx, cached byid(ctx)—analysis/runner.py:61Runner.confirm_live_run_is_safe— interactive guard before a full run discards its log —analysis/runner.py:83Runner.run_live— branch to controller vs guidance-only rollout —analysis/runner.py:98Runner.make_controller— select the controller class bycontroller.name—analysis/runner.py:107Runner.run_guidance_only— EE guidance rollout with no controller dynamics —analysis/runner.py:133RunContract/RunResult— the prepared-inputs / finished-run dataclasses —analysis/runner.py:14/:25
Footguns
make_controllermutatessys.path(GNC sibling imports)GNC modules import each other with bare sibling names (
from com_guidance import …), somake_controller
insertsGNC/at the front ofsys.pathbefore importing any controller. The insertion is guarded to be
idempotent. (analysis/INSIGHTS.md[run][io])
prepared_contextcaches byid(ctx)— re-prepares on identity driftPrepared contracts are cached keyed on
id(ctx), and re-prepared if the cached object identity no longer
matches. This prevents a reusedRunnerfrom serving stale config across runs with different override
dicts. (analysis/INSIGHTS.md[run])
A full run with
save_log=Falseand nodebug_time_limitwould silently discard everything
confirm_live_run_is_safeis the last safety net before a long sim throws away all its output: it
prompts interactively and aborts on any non-Yinput. Adebug_time_limit(short debug run) or
save_log=Truebypasses the prompt. (analysis/INSIGHTS.md[run])
Pseudocode (one run)
Runner(stem):
prepared = RunSpecLoader(stem).prepare() # spec, built cfg, ctx, run_name/dir
self.prepared_run = RunContract(prepared)
run(ctx=None):
prepared = prepared_context(ctx) # cache by id(ctx); re-prepare on drift
confirm_live_run_is_safe(prepared) # abort a logless full run unless confirmed
run_data = run_live(prepared):
if not controller.enable: return guidance_only rollout
ctrl = make_controller(prepared) # base | com | arm (inserts GNC/ on sys.path)
ctrl.run_all(debug_time_limit)
return RunResult(prepared, run_data.logger, run_data.log_path)
Related
orchestrator · pre_run_loader · logger · breve_controller · com_controller ·
base_controller · ee_guidance · guidance_rollout · data_analyzer · terminology