> ## Documentation Index
> Fetch the complete documentation index at: https://starforge.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Recipe 与版本锁定

> 方法目录（recipe catalog）、实验锁文件与框架版本矩阵

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
sf methods                    # 这套部署发布了什么
sf recipe status my-grpo      # 我的实验锁在什么上
sf recipe upgrade my-grpo     # 把它升到当前 catalog
```

**recipe** 是一种后训练方法的完整声明：entrypoint、可调超参及其类型与取值范围、
支持的框架版本、镜像产物、指标契约、产物契约。它们全体构成 **catalog**。

客户端和服务端从 `starforge-core` 加载同一批文件，所以两边不可能对「一个方法是什么」产生分歧。

## 方法标识

方法用 `<framework>/<method>` 两段式标识：

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
sf methods                  # 列出全部方法
sf methods nemo-rl/grpo     # 查看该方法的超参声明
```

当前 catalog 覆盖 **NeMo-RL**、**verl**、**TRL**、**OpenRLHF**、**evalkit**（benchmark）和 **custom**。完整表见[方法目录](/zh-Hans/guides/methods)。

## 实验锁文件：recipe.lock.json

`sf new` 创建实验时会写入 `recipe.lock.json`，锁定：

| 字段                           | 含义                                          |
| ---------------------------- | ------------------------------------------- |
| `recipe.name` / `version`    | 方法与 recipe 版本                               |
| `recipe.digest`              | manifest + 模板的内容摘要，防漂移                      |
| `framework.kind` / `version` | 框架与**精确**版本（如 `nemo-rl@0.7.0`、`verl@0.9.0`） |
| `framework.runtime_id`       | 部署侧执行工件（镜像 / SIF）的解析键                       |
| `requires.core`              | starforge 兼容范围                              |

提交时 CLI 与服务端 catalog 做**握手**：锁内容与服务端发布的 recipe 精确一致才放行。这保证了「你本地校验通过的配置，就是集群上实际运行的配置」。

<Warning>
  catalog 更新后（平台发布了新 recipe 版本），旧锁会导致提交被拒。这不是故障，是防止静默行为漂移的设计。用 `sf recipe status` 看差异，`sf recipe upgrade` 显式升级。
</Warning>

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
sf recipe status my-exp          # 锁与当前 catalog 的差异
sf recipe upgrade my-exp         # 升级锁（默认不改框架版本）
sf recipe upgrade my-exp --framework-version 0.9.0   # 同时切框架版本
sf submit my-exp --upgrade-recipe                     # 提交前顺手升级
```

## 框架版本矩阵

一个 recipe 可以同时发布多个框架版本（如 `verl/grpo` 支持 `0.8.0` 与 `0.9.0`）。版本间的差异——训练入口变化、参数路径迁移、镜像工件——全部声明在 recipe 的版本矩阵里，adapter 代码不写版本分支：

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
sf new my-verl --method verl/grpo --framework-version 0.9.0
```

* **入口覆盖**：如 verl 0.9 移除 `main_ppo_sync` 统一为 `main_ppo`，在 0.9.0 变体上声明 `entrypoint` 覆盖即可；
* **参数路径覆盖**：超参在不同版本的配置树位置不同，用 `path_overrides` 声明；
* **执行工件**：每个版本绑定精确 `runtime_id`，由框架默认、部署侧 runtime registry 或单次 `--image` 解析成 OCI 镜像（生产建议 digest）或 SIF/SQSH（Slurm）。

<Tip>
  这套机制让「适配上游新版本」大多数情况下只是**改 YAML + 发布镜像**，不动平台代码。详见[上游版本采纳 SOP](/zh-Hans/ops/upgrades)。
</Tip>

## Custom recipe：自己的框架和镜像

catalog 里没有的框架走 `custom/custom`。平台只跑实验目录里的 `train.sh`，不猜入口，也不会在别的 adapter 失败后落到 custom。

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
sf new my-custom --method custom/custom
sf submit my-custom --profile h200:8 \
  --image myregistry.io/my-train:v1
```

`--image` 必填。tag 能用，生产最好钉 digest。仓库要在 `FORGE_ALLOWED_IMAGE_REGISTRIES` 里。

默认 recipe 是外部观测（wandb 等），那种提交还要加 `--observability-url`。日志会跟 stdout 走；控制台曲线要在训练代码里调 `starforge.report`。Cookbook：[自定义训练](/zh-Hans/guides/custom-training)。镜像怎么打：[自定义镜像](/zh-Hans/guides/custom-images)。

## 配置分层

实验最终生效的配置由四层叠加，**后者覆盖前者**：

```text theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
recipe 模板 config.yaml          # 方法的官方基底（如 grpo_math_1B.yaml 链）
└─ 实验 config.yaml              # 你的调参（defaults 继承 + 差异覆盖）
   └─ 硬件 profile 覆盖          # 服务端注册表按 profile 下发（并行度 / 显存调优）
      └─ sf submit --set k=v    # 单次提交的临时覆盖（本地校验类型与区间）
```

`sf validate` 在本地完整走一遍这个叠加，struct 模式拼错键立即报错。
