| name | tao-artifacts |
| description | The contract home for TAO's SDK-free execution pipeline — authoritative JSON Schemas for the four typed artifacts (spec-bundle, job-record, results_dir layout, best_rec) plus the fixed job-status vocabulary and the nested-not-dotted spec rule. Use when authoring or validating a spec-bundle before submit, writing or reading a .tao/jobs job-record, resolving where results land, or consuming AutoML's best_rec.json. Trigger phrases include "validate the spec bundle", "job record schema", "status vocabulary", "results_dir layout", "best_rec schema". |
| license | Apache-2.0 |
| compatibility | Python 3.10+ with jsonschema for validation. No nvidia-tao-sdk. |
| metadata | {"author":"NVIDIA Corporation","version":"0.1.0"} |
| allowed-tools | Read Bash |
| tags | ["core"] |
tao-artifacts
Four typed artifacts flow through every TAO job. Their schemas live here and
nowhere else — producers (model/data skills) and consumers (platform skills)
both validate against this skill's references/.
| Artifact | Schema | Produced by → consumed by |
|---|
| spec-bundle | references/spec_bundle.schema.json | model/data skill → platform skill (at the submit seam) |
| job-record | references/job_record.schema.json | scripts/tao_job_record.py (the ONLY writer) → any re-attaching agent/poller |
| results_dir layout | references/results_dir.contract.md | platform skill at submit → whoever collects outputs |
| best_rec | references/best_rec.schema.json | tao-run-automl adapter → DEFT warm-start |
Quick Start — validate an artifact
python - <<'PY'
import json, yaml, jsonschema, pathlib
ref = pathlib.Path("${TAO_SKILL_BANK_PATH:?}/skills/core/tao-artifacts/references")
schema = json.loads((ref / "spec_bundle.schema.json").read_text())
bundle = yaml.safe_load(open("/path/to/bundle.yaml"))
jsonschema.validate(bundle, schema)
print("bundle OK")
PY
Validate the bundle before the verify-before-launch gate; validate a
job-record only when debugging (the writer script already enforces the schema).
The two rules the schemas enforce structurally
- Nested, not dotted. A
spec is a nested dict mirroring the container's
config shape — {"train": {"num_epochs": 12}}. Any key containing . at
any depth is rejected ({"train.num_epochs": 12} is the #1 authoring
mistake). Note the distinction: declared_inputs[].spec_key and
gpu_spec_key are dotted/indexed pointers into the spec
(dataset.train_data_sources[0].image_dir) — dots are correct there.
- Mode discrimination.
mode: config requires spec + config_format
and a command containing {config_path}, and forbids args.
mode: args requires args and forbids spec. There is no other mode.
Fixed status vocabulary
Every job state anywhere in the pipeline is exactly one of:
PENDING · RUNNING · COMPLETE · ERROR · CANCELED · UNKNOWN
Platform-native sub-states (ImagePullBackOff, PENDING-because-resources,
Insufficient-GPU, slurm COMPLETING…) are never new states — they ride in
the transition's message field. Terminal = COMPLETE | ERROR | CANCELED.
This is what lets the in-turn poll loop and the detached poller share one code
path across docker/slurm/kubernetes/brev.
Ordering invariants (enforced at the seam, stated here)
- The verify-before-launch gate runs on the spec-bundle, before any job id
exists.
tao_job_record.py open writes PENDING + the resolved results_dir
first and returns the id — the only handle a launch can use. A submit
that skipped the gate has no id, so it cannot launch.
transitions is append-only; .tao/ lives outside every synced results
tree.