CLI¶
The current experiment surface is validate → launch/submit → inspect.
Validation is pure YAML/Pydantic checking; launch runs one typed
ExperimentConfig in-process; submit wraps that launch in an sbatch script;
inspect reads the run manifest and event log.
See chassis-invariants.md
for the four architectural properties (drift resistance, MLflow as
state store, reproduction contract, render purity).
| Stage | Command | Module |
|---|---|---|
| config | graphids exp config <yaml> |
config |
| launch | graphids exp launch <yaml> |
launch |
| submit | graphids exp submit <yaml> |
submit |
| status | graphids exp status <run> |
status |
| manifest | graphids exp manifest <run> |
manifest |
| results | graphids exp results |
results |
There is no separate ops CLI surface. The run config itself carries
the stage and the stage-specific payload, so fit / test / extract
/ analyze all go through graphids.exp.runtime.launch_run
and the run manifest records the exact config that launched.
app.py owns the root Typer app + shared option types.
__main__.py imports each submodule to register commands.
graphids.cli¶
cli ¶
app ¶
Typer app + root callback. Login-node safe: no torch/model imports here.
Owns the structlog configuration since this module is the login-node
entry point that runs first; compute-side code imports
:func:configure_logging from here too.
configure_logging
cached
¶
structlog → JSON sync stderr with SLURM env auto-attached. Idempotent.
Source code in graphids/cli/app.py
exp ¶
New experiment-facing CLI.
This is the first replacement surface for the old row/submit mental model.
config ¶
config(path: Annotated[Path, Argument(help='YAML config file to validate as ExperimentConfig')]) -> None
Load a YAML config through OmegaConf and validate it as ExperimentConfig.
Source code in graphids/cli/exp.py
launch ¶
Launch one experiment config through the new primitive surface.
Source code in graphids/cli/exp.py
manifest ¶
Dump the manifest JSON for a run.
Source code in graphids/cli/exp.py
results ¶
results(view: Annotated[str, Option('--view', '-v', help='Result view in configs/result_views.yml')] = 'fusion', dataset: Annotated[list[str] | None, Option('--dataset', '-d', help='Dataset to query; repeat for multiple datasets')] = None, variant: Annotated[list[str] | None, Option('--variant', help='Variant to include; repeat for multiple variants')] = None, all_runs: Annotated[bool, Option('--all', help='Show all matching runs, not latest per variant')] = False, tracking_uri: Annotated[str | None, Option('--tracking-uri', help='Override MLflow tracking URI')] = None, output_format: Annotated[str, Option('--format', help='table or json')] = 'table') -> None
Query configured MLflow result views.
Source code in graphids/cli/exp.py
status ¶
Print manifest + latest event summary for one run.
Source code in graphids/cli/exp.py
submit ¶
submit(path: Annotated[Path, Argument(help='YAML experiment config')], cluster: Annotated[str | None, Option('--cluster', '-C', help='SLURM cluster override')] = None, partition: Annotated[str | None, Option('--partition', '-p', help='SLURM partition override')] = None, time_limit: Annotated[str | None, Option('--time', '-t', help='SLURM walltime override')] = None, gres: Annotated[str | None, Option('--gres', help='SLURM gres override')] = None, dry_run: Annotated[bool, Option('--dry-run', help='Print the sbatch script without submitting')] = False) -> None
Submit one experiment YAML as a SLURM batch job.