Skip to main content
Miles is open source under the LICENSE file in the repo. Contributions of every size are welcome: bug reports, doc fixes, new model recipes, full features.

Repository layout

The local loop

Code style

Formatting is not a matter of taste here, it is a hook. .pre-commit-config.yaml is the enforcement, the pre-commit workflow runs pre-commit run --all-files on every PR, and you can reproduce it exactly with the same command locally. Three hooks are Miles-specific bans, each pointing at the API you should use instead: If a commit legitimately needs an exception, the hooks carry exclude patterns; extend those in the same PR rather than disabling a hook. Beyond formatting, the conventions a reviewer will hold you to live in .claude/rules/general-code-style.md: prefer stateless and immutable, keep functions under roughly 100 lines and files under roughly 1000, initialize derived values once, keep imports at the top, use absolute imports, prefer keyword arguments where they add clarity. It applies to miles/**/*.py, scripts/**/*.py, tools/**/*.py, train.py and train_async.py.

What lives in .claude

The .claude directory is how the repo hands its conventions to coding agents, and it is worth reading even if you never run one, because it is where several rules are written down exactly once. .claude/rules/ holds conventions. A file with a paths: front matter list applies to any file matching it; a file without one applies everywhere. general-code-style.md is the one described above, and AGENTS.md at the repo root points Codex at it too, so both agents and humans review against one document. ci-test-registration.md holds the rules for adding a CI test (see Registering a test), and ci-failure-triage.md what to do when a CI check goes red. .claude/skills/ holds procedures, one directory per skill with a SKILL.md. They are workflows rather than style rules:

The doc-dev sentinel

Some files are bound to a document. A # doc-dev: line in a file’s own comment syntax is the opt-in: bare, it binds the file’s own header block; with a repo-relative path, it also binds that central document. Editing such a file means updating its documentation in the same change, and editing the document means finding the files that name it.
Current sentinels, so you know when you have walked into one: Grep for doc-dev: before editing anything under .github/workflows/ or docker/. A change that lands the code and leaves the document stale is the failure mode this convention exists to prevent.

Running CI

What a PR runs

Two things start automatically: the pre-commit workflow on every PR, and PR Test (.github/workflows/pr-test.yml) on every PR based on main. A PR based on another branch, such as a stacked PR, runs PR Test only with a run-ci* label (see Labels). PR Test resolves a policy and an image, runs the two CPU stages, and then the GPU stages, which are gated on stage-a-cpu succeeding so a formatting or import error does not burn GPU time. A PR that touches docker/Dockerfile, docker/build.py, docker/verify_transformer_engine.py, docker/patch/** or requirements.txt additionally builds the image first and runs every GPU suite inside it.

Registering a test

Selection is declared in the test file, never in the workflow YAML. Every test_*.py under tests/fast/ is auto-registered as a CPU test in stage-a-cpu; a file under tests/fast-gpu, tests/e2e or tests/ci declares a top-level register_*_ci(...) call, or collection fails with No CI registry found. Where the file goes, which stage runs it, how it is declared, which PRs run it, how est_time is measured with /rerun-test, and when disabled= is allowed are rules, written once in .claude/rules/ci-test-registration.md. Telling your failure from an infra one, and reporting either, is in .claude/rules/ci-failure-triage.md.

Labels

Labels are how a PR opts into the expensive matrix. A test’s labels=["megatron"] is triggered by the GitHub label run-ci-megatron: the workflow forwards the labels, Python strips the run-ci- prefix and intersects with each test’s list. The canonical set lives in tests/ci/labels.py, and a value outside it is a collection-time error. If your fork PR sits waiting for approval, that is GitHub holding first-time contributor runs; any maintainer-applied run-ci-* label doubles as the approval.

PR-description CI tags

Three directives are read out of the PR description itself, one per line, matched at the start of a line: For the two ref directives, <ref> is a branch or commit, and the shorthand #1234 resolves to refs/pull/1234/head, which is how you test against an unmerged SGLang or Megatron-LM PR:
Precedence, when several sources disagree: a workflow_dispatch input wins, then the PR-description line, then the default. ci-image-tag: has one more rule: on a PR that built its own image, the fresh pr-<number> tag outranks the directive, so a docker PR always tests what it just built.

PR conventions

Commit subjects follow conventional commits, under 70 characters, and the body explains why:
Before marking a PR ready for review:
  • pre-commit run --all-files is clean.
  • pytest tests/fast passes, plus tests/fast-gpu if you have a GPU.
  • New behavior has a test.
  • Each new or moved CUDA test has its CI timing: line in the PR description, from a /rerun-test run (see .claude/rules/ci-test-registration.md).
  • A new flag appears in CLI Reference, and python3 train.py --help still parses.
  • A change to a doc-dev: governed file updates its document in the same PR.
  • The PR description carries the CI directives your change needs.
Commenting /run-lint on a PR runs the hooks in CI and pushes the autofixes back to your branch, which is the quick way out of a red pre-commit job.

Issue triage

Comment to claim an issue before you start. For an infra failure or a flake, file the issue with the fields .claude/rules/ci-failure-triage.md lists (job URL, runner name, suite, log line), so a maintainer can map it to a host.

Where to ask

  • Quick questions: the #miles-rl channel of the SGLang Slack.
  • Design discussions: a GitHub Discussion, or an Issue labeled discussion.
  • CI internals: Stage (stages), Labels (label semantics), Docker build (images), and Metric history & regression gate (metric gate). The CI rules for contributors are .claude/rules/ci-test-registration.md and .claude/rules/ci-failure-triage.md.