Skip to content

JSON output contracts

Pipeline driver commands reserve standard output for compact JSON. Logging goes to standard error, so automation should parse stdout and preserve stderr for operators. Each object occupies exactly one line.

Slurm submission

lan-sbatch generate, lan-sbatch jaxtrain, and lan-sbatch torchtrain emit one object per generated script (one per selected resource lane). When --script-only is used, job_id is null because no Slurm submission occurs:

{
  "command": "generate --config-path /repo/config.yaml --output /shared/data ...",
  "job_id": 9876543,
  "mlflow_experiment_id": "42",
  "mlflow_run_id": null,
  "sbatch_script": "/shared/data/runs/20260822T120000000000_ddm_generate_sbatch.sh",
  "output_path": "/shared/data",
  "account": "example-condo",
  "partition": "batch",
  "array_size": 10,
  "lane": 0,
  "n_lanes": 1
}
Field Type Contract
command string Fully assembled downstream command embedded in the script
job_id integer or null Parsed Slurm job ID; null for --script-only or submission failure
mlflow_experiment_id string or null Generation/training experiment when initialization succeeded
mlflow_run_id string or null Parent training run; null for generation and --script-only
sbatch_script string Timestamped generated script path
output_path string Absolute data/network output root
account, partition string Resolved lane destination
array_size integer Tasks in this lane's array
lane integer Zero-based lane index
n_lanes integer Number of submissions produced by this invocation

--use-all-lanes emits one line per lane. Consumers must read the stream rather than assume one object. If any sbatch call fails, already-submitted lanes are not rolled back; the process exits non-zero after emitting every result.

--script-only is side-effect-free with respect to Slurm and MLflow. It still writes and reports one object for every generated script, with job/run/experiment IDs null. An MLflow initialization error in a real invocation is logged and submission can continue with null MLflow fields, so automation that requires lineage must validate them.

Validation result

The validator writes the detailed report to disk and prints a compact result:

{
  "passed": true,
  "report": "/staged/validation_report.json",
  "gates": {
    "structure": "passed",
    "parity": "skipped",
    "hssm_load": "passed",
    "density": "passed"
  }
}

Gate states are passed, failed, or skipped. The process exits non-zero when aggregate passed is false. For promotion, do not rely on that aggregate: the publisher additionally requires structure, HSSM load, and density to be present and not skipped.

The detailed report has schema_version: 1, artifact/model/network identity, aggregate passed, and a gates list whose entries include thresholds, scores, errors, or skip reasons as applicable.

Parameter-recovery shard

After its arguments are accepted, the recovery worker writes one shard and prints one object:

{
  "shard": "results/recovery_ddm_sdv_approx_differentiable@candidate_L1_n500@v_0007.json",
  "error": null
}

The on-disk shard uses schema_version: 2 and records model, design, dataset/seed, likelihood and arm identity, prior and outlier choices, ONNX path, data sanity checks, sampler settings and diagnostics, per-parameter recovery summaries, posterior correlations, and environment versions. A failed fit still writes a shard with its identity plus an error string, prints that error in the compact object, and exits non-zero.

Parameter-recovery report

The aggregator writes a schema-version-2 report and prints a compact verdict:

{
  "passed": true,
  "report": "results/recovery_report.json",
  "n_shards": 24,
  "n_usable_fits": 24,
  "n_errored_shards": 0,
  "failures": []
}

The report records all thresholds, cell summaries, errored shards, coverage failures, and aggregate passed. n_shards includes errored shards, whereas n_usable_fits is the sum of n_converged across the reported parameter cells, not a count of distinct shard files. The process exits non-zero when passed is false and also rejects an empty shard directory; too few eligible fits and failed calibration gates therefore cannot be mistaken for a clean sweep.

Publication result

A successful dry run returns a publication plan without uploading to Hugging Face or recording a publication run in MLflow. It can still copy artifacts into the staging directory and write validation_report.json there:

{
  "published": false,
  "dry_run": true,
  "model": "ddm",
  "network_type": "lan",
  "hf_repo": "example/HSSM_staging",
  "root_filename": "ddm.onnx",
  "training_run_id": "0123456789abcdef",
  "run_uuid": "run-uuid",
  "staged": ["run-uuid_lan_ddm__network.onnx", "validation_report.json"],
  "gate": "all required gates ran and passed"
}

A successful upload adds:

{
  "published": true,
  "hf_url": "<Hugging Face commit URL>",
  "hf_commit": "abc123",
  "hf_commit_verified": true,
  "publish_run_id": "fedcba9876543210"
}

The plan fields are present in the real result as well. If head cannot be verified, hf_commit_candidate replaces hf_commit and may be null; hf_commit_verified is false.

A handled refusal or gate failure returns published: false plus error and any plan fields established before the refusal. A real publication attempt exits non-zero in that case. A dry run can exit successfully with published: false, because not publishing is its intended outcome.