Contributing

The canonical references are CONTRIBUTING.md and AGENTS.md. This chapter gives a working overview for anyone reading the book first.

The AI-first policy

Metrale Engine is explicitly an AI-first codebase. From CONTRIBUTING.md:

  • All PRs are expected to be AI-generated. Use the best AI tools available to write your kernels, Rust code, and benchmarks.
  • Human-written code must be justified. Indicate which parts are human-authored and explain why.
  • Human-only contributions will be reviewed by AI.

This is not branding — it's the operational consequence of the specialization thesis. If AI can hyperoptimize CUDA kernels for specific hardware targets, it can write the infrastructure too. Ports to new (H, M_q) targets are the clearest example: each is a bounded, well-scoped piece of work, and that's the unit AI-assisted engineering handles best.

What kinds of PRs are welcome

CONTRIBUTING.md lists four categories:

  • New (H, M_q) targets. Porting Metrale Engine kernels to new hardware (H100, B200, MI300X, Apple M4, Intel) or new models. Each target is a self-contained body of work. See the Adding a new hardware target and Adding a new model guides.
  • Kernel optimization. Profile existing kernels, experiment with tiling strategies, register pressure, shared-memory layouts. If you can beat the numbers in the Benchmarks chapter, send the PR.
  • Benchmark coverage. Add shapes and configurations not yet tested. More data points sharpen the hypercompiler.
  • Bug reports. Include hardware details, repro steps, and kernel timings.

Local checks before a PR

These are what CI runs (.github/workflows/ci.yml). Run them locally first:

# 1. Formatting
cargo fmt --all -- --check

# 2. Lints. BOTH env vars are needed: METRALE_SKIP_BUILD stubs the PTX build,
#    CUDARC_CUDA_VERSION stops cudarc shelling out to `nvcc --version`.
#    Deny-warnings comes from [workspace.lints], so CI passes no -D flag
#    and no --all-features. This is verbatim what ci.yml runs.
METRALE_SKIP_BUILD=1 CUDARC_CUDA_VERSION=13000 cargo clippy --workspace --tests

# 3. License headers
bash scripts/check-license-headers.sh

# 4. Typos
typos     # install once: cargo install typos-cli

All four are required to pass. Real CUDA build + test cycles require a GB10 host — not the laptop, the DGX Spark itself.

Ground rules (from AGENTS.md)

  • SPDX header on every source file. // SPDX-License-Identifier: MIT OR Apache-2.0 on line 1 of every .rs, .cu, .cuh, .h, .hpp, .cpp. Enforced by the license-headers CI job.
  • License is MIT OR Apache-2.0. Third-party code keeps its own licence and is listed in THIRD_PARTY_NOTICES.md. deny.toml controls allowed dependency licenses.
  • Don't regress supported models. The matrix in Supported Models is the contract; docs/GB10_DEPLOYMENT_GUIDE.md §2 is its SSOT, and kernels/gb10/ carries one leaf per (model, quant) target. If your PR might touch a hot path, validate against tests/run_all_models.py on a GB10 before opening.
  • One logical change per commit. Don't bundle cleanup with a bug fix.
  • Commit message format. <area>: <imperative summary> — e.g. server: preserve template-forced thinking through EP=2.

Failure modes that cost the project time

These are the classes of bug that have burned days. Know them; avoid introducing them.

  • Protocol drift between OpenAI (api/) and Anthropic (anthropic/) surfaces. A fix on one side often needs a matching change on the other.
  • Template mismatches subtly breaking tool-calling — different <tool_call> vs <minimax:tool_call> tokens, <think> seeded by the template vs emitted by the model, thinking budget enforcement.
  • FP8 / KV / quantization edge cases — BF16 paged cache routed into an FP8 kernel → silent NaN. If your change touches numeric paths, verify with a real model before claiming success.
  • Docs drift — CLI flags, release commands, quick-start snippets. Verify against the current binary, not memory.

The cardinal rule

Never assume the model is at fault. Always look for the Metrale Engine bug first.

The test matrix has caught many issues that would have looked like "model hallucination" in a lesser codebase. The heuristic is: if the model used to produce coherent output on this input and now doesn't, there's a Metrale Engine bug, not a model bug.

License

Metrale Engine is licensed under MIT OR Apache-2.0, at your option. Unless you state otherwise, any contribution you submit for inclusion is licensed the same way, without additional terms or conditions.

Adding a new hardware target

High-level (full walkthrough in docs/HARDWARE.md):

  1. kernels/<hw>/HARDWARE.toml with vendor = "..." and arch; [hardware] inherits to reuse another tree's sources.
  2. impl ComputeTarget for the vendor's compiler, registered in crates/kernels/build_target.rs::resolve_compute_target() (the build reads METRALE_TARGET_HW, default gb10, and the tree's vendor picks the ComputeTarget).
  3. impl GpuBackend in crates/gpu-runtime/src/<vendor>_backend.rs; some methods have defaults.
  4. Kernel sources under kernels/<hw>/common/, plus per-model shadows (declared in [shadow]) only where a target diverges.
  5. MODEL.toml + KERNEL.toml for at least one model.
  6. Backend selection in the server's startup (crates/server/src/main_modules/serve_phases/).
  7. Dockerfile for the new hardware.

Adding a new model

The model-specific surface is tiny:

  1. crates/model-arch/src/weight_loader/<your_model>.rs implementing ModelWeightLoader (~200–500 lines depending on architecture complexity).
  2. Module declaration + pub use in crates/model-arch/src/weight_loader/mod.rs.
  3. One match arm in crates/model-engine/src/factory.rs::loader_for_config.
  4. Optional: kernels/<hw>/<your-model>/MODEL.toml for sampling / behavior defaults.
  5. Optional: tool-call parser under crates/server/src/tool_parser/.
  6. Entry in tests/run_all_models.py for regression coverage.
  7. Entry in Supported Models.

Existing loaders for patterns: qwen35.rs, minimax.rs, nemotron.rs cover dense, SSM+MoE hybrid, and attention+MoE shapes respectively.

PR process

  1. Fork and create a feature branch.
  2. Atomic commits. Enforced by reviewers; squash only at the reviewer's request.
  3. CI must pass: ci.yml runs fmt, clippy, license-headers, typos, kernel-structure, cargo test --workspace, test-macos-metal and release-matrix; security.yml runs cargo-deny; file-size-cap.yml the 500-LoC cap; docs.yml mdBook + cargo doc. The pr-benchmark-gate job ("PR Benchmark Certifications") requires the committed benchmark records for the commit; see Certification.
  4. PR template asks for:
    • What — summary of the change.
    • Why — motivation and context.
    • Benchmarks — before/after numbers for perf-related changes.
    • Authorship — AI / human / mixed; justify human-written sections.
  5. A maintainer (and/or AI reviewer) merges.

Scope escalation

If a task is ambiguous, ask in the issue/PR before implementing. If scope grows past "one PR", split it. If you're modifying a shared trait, a build script, or CI config, flag it in the PR description so reviewers catch it.

References