--- title: Contributing description: Repository layout, the test suites, CI labels, and PR conventions for miles-diffusion. --- miles-diffusion is the diffusion-model sibling of [miles](https://github.com/radixark/miles). It shares miles' conventions — conventional commits, `pre-commit`, English-only PRs — but has its own test topology, because almost everything meaningful needs GPUs. ## Repository layout ```text miles_diffusion/ ├── train_diffusion.py # the entry point — the whole train loop, ~90 lines ├── miles/ │ ├── backends/ │ │ ├── fsdp_utils/ # the training half │ │ │ ├── actor.py # FSDPTrainRayActor: wrap, forward, loss, step │ │ │ ├── configs/ # TrainPipelineConfig per model family │ │ │ ├── models/ # native model packages (ltx) + diffusers parallel plans │ │ │ ├── loss_hub/ # flow_grpo / nft / sft objectives │ │ │ ├── sequence_parallel/ # USP = Ulysses × Ring │ │ │ ├── monkey_patches/ # FSDP2 param-dtype patch (torch 2.11 gated) │ │ │ ├── mixed_precision.py # per-parameter dtype map compilation │ │ │ └── sde_step_backend.py# SDE dynamics + log-prob scoring │ │ └── sglang_diffusion_utils/# the rollout half: engine wrapper + parity patches │ ├── ray/ # RolloutManager, train actor group, placement groups │ │ └── data_conversion_hub/ # samples → train pairs │ ├── rollout/ # rollout fn, data source, rm_hub, filters, step strategies │ ├── router/ # miles router │ ├── dashboard/ # offline telemetry │ └── utils/ # arguments.py, types, metrics, debug tooling ├── scripts/ # run_*.py launchers — Typer CLIs, also the e2e entry points ├── tests/ # fast / fast-gpu / e2e / ci ├── docker/ # Dockerfile + pinned version tags └── docs/ # this site ``` If you are adding a **model family**, you will touch: `miles/backends/fsdp_utils/configs/.py` (register with `@register_train_pipeline_config`), optionally `miles/backends/fsdp_utils/models/...` for a native package or FSDP plan, a launcher in `scripts/`, and a page under `docs/models/`. ## Local dev loop ```bash cd /root/miles_diffusion git remote add me git@github.com:/miles_diffusion.git git checkout -b feat/awesome pip install -e . --no-deps # editable install picks up changes pytest tests/fast -x -q # CPU suite: no GPU, seconds pytest tests/fast/backends/fsdp_utils/test_mixed_precision.py -xvs git add -p && git commit -m "feat(fsdp): short imperative description" git push me feat/awesome gh pr create ``` ## Tests Four tiers, by what they need: | Directory | Needs | What it is | |---|---|---| | `tests/fast/` | CPU only | Argument validation, config registry, dtype-map compilation, loss math, data splitting. The bulk of the suite. | | `tests/fast-gpu/` | 1-2 GPUs | FSDP behaviour that only exists on device: param-dtype maps, hybrid shard, SP attention parity, LoRA weight sync. Includes ported upstream PyTorch FSDP tests. | | `tests/e2e/short/` | 2-5 GPUs | Runs an actual launch script for a few rollouts and compares its **metric series** against a recorded standard. | | `tests/ci/` | — | The harness itself: registry, label filter, suite runner, e2e standards. | Run the CPU tier before every push; it is fast and catches most regressions. On a CPU-only box without sglang's GPU kernels, install the stubs first the way CI does: `uv pip install tests/ci/cpu_stubs`. CI does not call `pytest` directly — it goes through the suite runner, which is also the way to reproduce a CI failure locally: ```bash python tests/ci/run_suite.py --hw cpu --suite stage-a-cpu --labels run-ci-fsdp python tests/ci/run_suite.py --hw cuda --suite stage-b-3-gpu-h200 --match-all-labels ``` Stage A (CPU) gates every GPU stage: a broken import should not burn GPU runner slots. ### Registering a test with CI CI discovers tests by **AST-parsing** a `register_*_ci(...)` call at the top of the file — the call is a runtime no-op and never executes. ```python from tests.ci.ci_register import register_cpu_ci register_cpu_ci(est_time=5, suite="stage-a-cpu", labels=["fsdp"]) ``` | Parameter | Meaning | |---|---| | `est_time` | Seconds. Used to pack the suite. | | `suite` | Which runner it lands on (below). | | `labels` | Domain gate. Empty/omitted = runs on **every** PR. | | `nightly` | Nightly only. | | `disabled` | A string reason; the test is skipped. | ### Suites | Suite | Runner | |---|---| | `stage-a-cpu`, `stage-b-cpu` | CPU | | `stage-b-3-gpu-h200`, `stage-b-5-gpu-h200` | H200, split into 3-GPU and 5-GPU runners via per-runner `CUDA_VISIBLE_DEVICES` | | `stage-c-3-gpu-h200`, `stage-c-5-gpu-h200` | Same hardware; stage C holds the long e2e runs | ### Labels A test with a non-empty `labels` list runs only when the PR carries `run-ci-