### What does this PR do?
Type of change: Chore
Standardize YAML file extensions in `modelopt_recipes/` to `.yaml` for
consistency. The existing recipes used a mix of `.yml` (PTQ recipes) and
`.yaml` (speculative decoding, model-specific recipes).
#### Changes
**Renamed files:**
- `modelopt_recipes/general/ptq/fp8_default-fp8_kv.yml` → `.yaml`
- `modelopt_recipes/general/ptq/nvfp4_default-fp8_kv.yml` → `.yaml`
- `modelopt_recipes/general/ptq/nvfp4_experts_only-fp8_kv.yml` → `.yaml`
- `modelopt_recipes/general/ptq/nvfp4_mlp_only-fp8_kv.yml` → `.yaml`
- `modelopt_recipes/general/ptq/nvfp4_omlp_only-fp8_kv.yml` → `.yaml`
**New pre-commit hook:** `normalize-yaml-ext`
- `tools/precommit/normalize_yaml_ext.py` — auto-renames `.yml` to
`.yaml`
for any staged file under `modelopt_recipes/`. Runs before recipe
validation so future contributions are caught automatically.
**Updated references:**
- `tests/unit/recipe/test_loader.py` — built-in recipe paths updated to
`.yaml`
Note: `load_recipe()` and `load_config()` probe both `.yml` and `.yaml`
suffixes, so callers using paths without extensions (e.g.,
`load_recipe("general/ptq/fp8_default-fp8_kv")`) are unaffected.
### Testing
Existing recipe loader tests pass with updated paths.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Standardized recipe file extensions and added an automated pre-commit
normalization hook to enforce the convention.
* **Tests**
* Updated unit tests to reference the new recipe filename convention and
ensure consistency with configuration loading.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
### What does this PR do?
Add pre-commit hook to validate modelopt recipes
- Adds a pre-commit hook (check-modelopt-recipes) that validates recipe
YAML files under modelopt_recipes/ on commit.
- Checks that quant_cfg uses the list-of-dicts format (rejects legacy
dict format), PTQ recipes use quantize as the top-level key (not
ptq_cfg), and recipes load successfully via load_recipe().
- Scopes validation to PTQ recipes only for now — non-PTQ YAML files
(e.g. speculative decoding training configs like eagle3.yaml) are
silently skipped. Will defer to future.
### Testing
- Modify a PTQ recipe to use the legacy quant_cfg dict format → hook
should reject
- Modify a PTQ recipe to use ptq_cfg instead of quantize → hook should
reject
- Commit a valid PTQ recipe change → hook should pass
- Commit a non-PTQ YAML file (e.g. eagle3.yaml) → hook should skip it
without errors
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Added a pre-commit validation that checks ModelOpt PTQ recipe files
for correct structure and schema, rejects legacy/incorrect quantization
config formats, enforces proper top-level keys, and surfaces clear error
messages to block commits with invalid recipes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>