Commit & PR Conventions
How to commit and open PRs in verl-project/verl-omni. Load this before any
commit or PR. The rules here come from AGENTS.md / CLAUDE.md and are
enforced by maintainers — breaching them can result in banning.
When to Use
- Any
git commit in this repo.
- Any PR creation (including delegated/agent commits).
- Whenever you infer a module/type label for a change.
Step 0: Contribution policy (fail-closed)
Before proposing a PR, run the duplicate-work checks:
gh issue view <issue_number> --repo verl-project/verl-omni --comments
gh pr list --repo verl-project/verl-omni --state open --search "<issue_number> in:body"
gh pr list --repo verl-project/verl-omni --state open --search "<short area keywords>"
- If an open PR already addresses it → do not open another.
- If your approach differs materially → explain the difference in the issue.
- No low-value busywork PRs (single typo, one style tweak, one mutable
default). Mechanical cleanups are acceptable only bundled with substantive work.
- If the work is duplicate/trivial → stop and report what's missing.
PR title format
[{modules}] {type}: {description}
- modules (comma-separated if several). The gate is
tests/special_sanity/check_pr_title.py, not AGENTS.md — it accepts the official
AGENTS.md set (vllm_omni, diffusion, omni, rollout, trainer, reward,
model, algo, fsdp, ray, worker, data, cfg, ckpt, doc, ci,
tests, docker, misc) plus training_utils, single_controller,
recipe, perf, env, tool. Prefer the official set; the extras are real
(recipe for examples/ work, perf for perf changes). Anything outside the
validator's list fails the check.
- type:
feat, fix, refactor, chore, test.
[BREAKING] if it breaks any API (CLI args, config, signatures) — placed
immediately before the module bracket: [BREAKING][cfg] refactor: ..., not
[cfg] [BREAKING] ... (the validator only strips a leading [BREAKING]).
- For a stacked/multi-part PR series, prefix
[N/N] (single digits only), e.g.
[1/N][omni] feat: .... Combined with [BREAKING] the order is
[N/N][BREAKING][module].
Module inference from changed paths
| Path |
Module |
verl_omni/pipelines/ |
diffusion |
verl_omni/pipelines/qwen3_omni/ |
omni |
verl_omni/trainer/ |
trainer |
verl_omni/trainer/config/, */config/ |
cfg |
verl_omni/utils/reward_score/, verl_omni/reward_loop/ |
reward |
verl_omni/workers/rollout/ |
rollout |
verl_omni/workers/ |
worker |
verl_omni/models/ |
model |
verl_omni/utils/vllm_omni/ |
vllm_omni |
docs/ |
doc |
tests/ |
tests |
.github/, CI |
ci |
docker/ |
docker |
Title examples
[reward] feat: add pickscore visual reward
[diffusion, cfg] feat: add teacher-anchored distillation losses for OPD
[omni] fix: correct attention mask for Qwen3-Omni text+image inputs
[tests] test: cover qwen-image DPO adapter guidance branching on CPU
[BREAKING][cfg] refactor: rename guidance_scale to cfg_scale
Real history to match style: [trainer, algo, cfg] feat: ...,
[diffusion, cfg, tests] feat: ..., [1/N][omni] feat: ....
Commit messages
Body explains why, not what. Wrap ~72 chars. For AI-assisted commits, add an
explicit disclosure line in the body and attribution trailers (this is
the actual repo convention — see recent history):
[reward] feat: add pickscore visual reward
Add a PickScore-based scorer routed via default_compute_score_image so
flow-GRPO runs can optimize human-preference reward.
AI assistance (<your tool name>) was used for this change.
Co-authored-by: <your tool name>
Signed-off-by: Your Name <your.email@example.com>
The Co-authored-by trailer names the assisting tool actually used —
substitute your own tool name, do not copy Claude Code verbatim unless
you are Claude Code. Signed-off-by with a real name/email is required.
PR description (AI-assisted work — mandatory)
The PR body must include:
- Why this is not duplicating an existing PR (cite your Step 0 checks).
- Test commands run and their results.
- A clear statement that AI assistance was used.
- A note that a human submitter has reviewed every changed line — pure
code-agent PRs are not allowed.
Pre-commit
Ensure hooks pass before committing (pre-commit install once). If you touched
config dataclasses, run scripts/generate_trainer_config.sh and commit the
regenerated _generated_*.yaml (see config rule).
Common Mistakes
- ❌ Title with a module not in
check_pr_title.py, or an invalid type.
- ❌
[BREAKING] after the module bracket ([cfg] [BREAKING]) instead of before it.
- ❌ Opening a PR without the duplicate-work checks.
- ❌ Omitting the AI-assistance disclosure or trailers.
- ❌ Committing a stale
_generated_*.yaml.
1---2name: commit-and-pr3description: verl-omni commit message + PR conventions and the mandatory contribution policy. MUST load before any git commit or PR creation -- enforces the [{modules}] {type}: {description} title format, commit trailers, duplicate-work checks, and AI-assistance disclosure.4---56# Commit & PR Conventions78How to commit and open PRs in `verl-project/verl-omni`. **Load this before any9commit or PR.** The rules here come from `AGENTS.md` / `CLAUDE.md` and are10enforced by maintainers — breaching them can result in banning.1112## When to Use1314- Any `git commit` in this repo.15- Any PR creation (including delegated/agent commits).16- Whenever you infer a module/type label for a change.1718## Step 0: Contribution policy (fail-closed)1920Before proposing a PR, run the duplicate-work checks:2122```bash23gh issue view <issue_number> --repo verl-project/verl-omni --comments24gh pr list --repo verl-project/verl-omni --state open --search "<issue_number> in:body"25gh pr list --repo verl-project/verl-omni --state open --search "<short area keywords>"26```2728- If an open PR already addresses it → **do not open another.**29- If your approach differs materially → explain the difference in the issue.30- **No low-value busywork PRs** (single typo, one style tweak, one mutable31 default). Mechanical cleanups are acceptable only bundled with substantive work.32- If the work is duplicate/trivial → **stop** and report what's missing.3334## PR title format3536```37[{modules}] {type}: {description}38```3940- **modules** (comma-separated if several). The gate is41 `tests/special_sanity/check_pr_title.py`, not `AGENTS.md` — it accepts the official42 `AGENTS.md` set (`vllm_omni`, `diffusion`, `omni`, `rollout`, `trainer`, `reward`,43 `model`, `algo`, `fsdp`, `ray`, `worker`, `data`, `cfg`, `ckpt`, `doc`, `ci`,44 `tests`, `docker`, `misc`) **plus** `training_utils`, `single_controller`,45 `recipe`, `perf`, `env`, `tool`. Prefer the official set; the extras are real46 (`recipe` for `examples/` work, `perf` for perf changes). Anything outside the47 validator's list fails the check.48- **type**: `feat`, `fix`, `refactor`, `chore`, `test`.49- `[BREAKING]` if it breaks any API (CLI args, config, signatures) — placed50 **immediately before the module bracket**: `[BREAKING][cfg] refactor: ...`, *not*51 `[cfg] [BREAKING] ...` (the validator only strips a leading `[BREAKING]`).52- For a stacked/multi-part PR series, prefix `[N/N]` (single digits only), e.g.53 `[1/N][omni] feat: ...`. Combined with `[BREAKING]` the order is54 `[N/N][BREAKING][module]`.5556### Module inference from changed paths5758| Path | Module |59| -------------------------------------- | ------------- |60| `verl_omni/pipelines/` | `diffusion` |61| `verl_omni/pipelines/qwen3_omni/` | `omni` |62| `verl_omni/trainer/` | `trainer` |63| `verl_omni/trainer/config/`, `*/config/` | `cfg` |64| `verl_omni/utils/reward_score/`, `verl_omni/reward_loop/` | `reward` |65| `verl_omni/workers/rollout/` | `rollout` |66| `verl_omni/workers/` | `worker` |67| `verl_omni/models/` | `model` |68| `verl_omni/utils/vllm_omni/` | `vllm_omni` |69| `docs/` | `doc` |70| `tests/` | `tests` |71| `.github/`, CI | `ci` |72| `docker/` | `docker` |7374### Title examples7576```77[reward] feat: add pickscore visual reward78[diffusion, cfg] feat: add teacher-anchored distillation losses for OPD79[omni] fix: correct attention mask for Qwen3-Omni text+image inputs80[tests] test: cover qwen-image DPO adapter guidance branching on CPU81[BREAKING][cfg] refactor: rename guidance_scale to cfg_scale82```8384Real history to match style: `[trainer, algo, cfg] feat: ...`,85`[diffusion, cfg, tests] feat: ...`, `[1/N][omni] feat: ...`.8687## Commit messages8889Body explains **why**, not what. Wrap ~72 chars. For AI-assisted commits, add an90explicit disclosure line in the **body** and attribution **trailers** (this is91the actual repo convention — see recent history):9293```94[reward] feat: add pickscore visual reward9596Add a PickScore-based scorer routed via default_compute_score_image so97flow-GRPO runs can optimize human-preference reward.9899AI assistance (<your tool name>) was used for this change.100101Co-authored-by: <your tool name>102Signed-off-by: Your Name <your.email@example.com>103```104105The `Co-authored-by` trailer names the assisting tool **actually used** —106substitute your own tool name, do **not** copy `Claude Code` verbatim unless107you are Claude Code. `Signed-off-by` with a real name/email is required.108109## PR description (AI-assisted work — mandatory)110111The PR body **must** include:1121131. Why this is **not** duplicating an existing PR (cite your Step 0 checks).1142. **Test commands run and their results.**1153. A clear statement that **AI assistance was used**.1164. A note that a **human submitter** has reviewed every changed line — pure117 code-agent PRs are not allowed.118119## Pre-commit120121Ensure hooks pass before committing (`pre-commit install` once). If you touched122config dataclasses, run `scripts/generate_trainer_config.sh` and commit the123regenerated `_generated_*.yaml` (see [config rule](../../rules/config.md)).124125## Common Mistakes126127- ❌ Title with a module not in `check_pr_title.py`, or an invalid type.128- ❌ `[BREAKING]` after the module bracket (`[cfg] [BREAKING]`) instead of before it.129- ❌ Opening a PR without the duplicate-work checks.130- ❌ Omitting the AI-assistance disclosure or trailers.131- ❌ Committing a stale `_generated_*.yaml`.