sf submit → console assembly and scheduling → a container actually trains → ingest of metrics/logs/artifacts → SUCCEEDED → assertions. Physical GPU attach is simulated. The rest is not mocked. Run it before go-live, after upgrades, and after executor changes.
Running locally (macOS/OrbStack or any Docker machine)
--keep preserves the scene. The harness runs the real sf from this repository’s cli/, creates an independent temporary project with sf init, then submits from there.
GPU simulation switches
Scheduling, quotas, capacity, and the ledger all execute with real semantics. Production keeps the default (passthrough).
Assertion coverage
- The state machine reaches SUCCEEDED (passing through PENDING / RUNNING);
- Metrics closed loop:
train/losscan be read back from the API; - Logs closed loop: training log lines are stored and queryable;
- Artifacts closed loop: checkpoint registration is visible.
CI
.github/workflows/e2e.yml: unit tests → local closed loop (sim + real SFT matrix) → kuberay closed loop (kind + operator), with no cross-repository token.
Coverage boundaries
The slurm backend is not yet in the closed loop (requires containerized slurmrestd + Apptainer): batch script rendering, the REST client, hetjob, and status mapping are covered by unit tests. Details and roadmap in the repo’sdocs/ops/e2e-closed-loop.md.