# harbor-qwen-grpo-experiment

本项目曾在 AutoDL GPU 节点运行 rLLM + verl + vLLM，并以 GRPO 和原生 critic/GAE PPO 驱动工具调用训练。项目已于2026-08-30完成P0并进入阶段性归档：原始SFT与父checkpoint step20在统一64K协议下，test38均为6/38，Verified27按全部attempt均为9/27，两个面板都没有呈现总体增益；parent在Sphinx 8621发生一次8Gi sandbox Pod OOM，但不改变“不追加PPO训练”的结论。腾讯云CVM、云硬盘及相关计费资源已经释放，k3s、BuildKit、sandbox和verifier当前均不在线；下文部署结构与命令作为已验证的历史架构和未来重建手册保留。Qwen Code仅作历史回退。

## 当前状态（2026-08-30）

| 项目 | 状态 |
| --- | --- |
| 实验决策 | P0完成，停止追加PPO训练，项目阶段性归档 |
| 64K test38 | SFT 6/38；parent step20 6/38 |
| 64K Verified27 | SFT 9/27；parent step20 9/27（26个scoreable，1个基础设施异常） |
| 配对结论 | test38为3胜32平3负；Verified27为2胜23平2负；两者exact McNemar p均为1.0 |
| 效率结论 | parent消耗更多input tokens、agent steps和运行时间，但没有提高总体成功数 |
| 云端状态 | 腾讯云CVM、CBS及相关计费资源已释放；原k3s运行面不可直接恢复 |
| 恢复前提 | 重新创建CPU节点、k3s、BuildKit/PVC、KubeConfig/RBAC和GPU模型网络入口 |

## 已验证的历史架构与边界

```text
Mac: 源码/补丁/证书
  ├── Registry: TCR个人版为当前主仓；ACR仅作迁移源/兼容回退
  └── AutoDL: Harbor + rLLM + verl + vLLM + GRPO / PPO
          │  kubeconfig / model gateway / BuildKit tunnel
          ▼
        腾讯CVM/k3s（已释放）: BuildKit + sandbox Pod + verifier + CPU数据治理
```

- Harbor 是 AutoDL 上的训练调度库，不需要部署成常驻 Web 服务。
- 历史k3s节点不承担模型训练；它负责构建任务镜像、隔离执行代码和返回verifier reward。该节点现已释放。
- `make canary` 只验证环境、harness、轨迹和 reward 闭环；`make train` 才会更新模型。

### 2026-08-30 最终实验快照

- 当前正式训练数据为 `swesmith-curated-grpo-267-v1`：train/validation/test 为187/42/38，共267题、89个仓库；split manifest语义摘要为 `ae5df9a3f4a3fc8af44fac420b36529e283839e1bd3de9daba65d5bcda51447d`。
- TCR已验证267/267个冻结任务镜像，基础镜像为103个available、2个skipped、0个pending；700题是候选扩充目标，不是当前训练集规模。
- `Klear-AgentForge-8B-SFT`在该数据集validation中按seed `20260817`抽取30题完成64K Canary：12/30、Mean 0.400、Exceptions 0，作业为 `state/harbor-jobs/2026-08-17__16-14-11`。该题集与此前统一32K固定57题不是同一口径，不能直接比较涨跌。
- GRPO入口及64K Canary保持现状。PPO的5卡分离拓扑固定为4卡actor/critic FSDP加1卡单实例TP=1 vLLM；第二轮40K、900秒、并发8的20-step warm-start完整运行，160个episode无error、32个成功、12个timeout，末步导出177.5MiB actor PEFT adapter与14.11GiB critic BF16 model shards。训练成功率前10步为22.5%、后10步为17.5%；32次成功中16次来自同一Pygments任务，critic VF loss虽降至0.0078但explained variance仍为负，不能据此放行继续训练。三模型能力评测已经完成；历史SWE-Smith30包含train任务，不作为放行指标。PPO训练与test38评测使用40K Plus guard并保留256-token安全余量；Verified27由Agent侧限制为32K，不能因同一vLLM以40K启动而写成40K评测。
- 父checkpoint `20260820T154406Z/global_step_20`已在seed `20260822`、并发8、retry 0下完成正式基线：test38为6/38（15.79%，0 exceptions，Wilson 95%为7.44%–30.42%）；Verified27为6/26有效trial（23.08%，Wilson 95%为11.03%–42.05%），按全部27次attempt为6/27（22.22%），`pylint-4661`有1个`RuntimeError`。运行ID为`20260822-parent-full-184437Z`。后续current在test38降至4/38、Verified27按全部attempt仍为6/27，因此未形成随step单调提升。
- 原始`Klear-AgentForge-8B-SFT`已以base模式、相同seed `20260822`、并发8、retry 0完成正式基线，运行ID为`20260822-sft-full-204740Z`。test38为4/38（10.53%，Wilson 95%为4.17%–24.13%），Verified27为4/27（14.81%，Wilson 95%为5.92%–32.48%）；两面板均0 exceptions、0 timeouts。父checkpoint相对本次SFT在test38多2题（+5.26个百分点），在Verified27按全部attempt多2题（+7.41个百分点），但区间高度重叠且每题仅采样一次，当前只能记录点估计，不能判定能力提升。历史SFT曾在同一Verified27得到8/27，进一步说明单次小样本方差不可忽略。
- Effective step 40 checkpoint `20260821T114029Z/global_step_20`以run `20260822-current-full-214727Z`完成同口径评测。test38为4/38（10.53%，Wilson 95%为4.17%–24.13%），与SFT同分、较parent少2题；Verified27为6/27（22.22%，Wilson 95%为10.61%–40.76%），较SFT多2题、与parent按全部attempt成功数和通过率相同。两面板均0 exceptions、0 timeouts。current与SFT在test38虽然总分相同，但4个成功任务完全不同；Verified27与SFT仅共享3个成功任务，且与parent也仅共享3个，说明单次结果存在显著任务级翻转，尚无稳定的整体提升证据。
- 同一固定Verified27的历史约64K SFT恢复口径为10/27（37.04%），当前正式32K SFT为4/27（14.81%），观察差为-6题、-22.22个百分点。两者可以作为运行口径的实际成绩比较，但历史10/27由offline-v2主批次与2个offline-v3异常恢复任务拼接，并非与当前相同的单作业受控A/B；并发生成也不保证逐token确定性。当前P0扩大为统一64K协议下的SFT与parent step20双面板比较，同时覆盖test38和既有Verified27，不把历史差值直接解释为上下文效应。
- P0的SFT侧以run `p0-klear64k-sft-20260828T145119Z`完成统一64K公开协议：test38为6/38（15.79%，Wilson 95%为7.44%–30.42%），Verified27为9/27（33.33%，Wilson 95%为18.64%–52.18%）；两个面板均0 exceptions、0 timeouts，真实64512-token探针和ACK Pod模型端点门禁通过。Verified27相对历史同任务32K SFT的4/27观察上升5题，但parent同协议最终也为9/27；单次temperature 1.0生成存在任务翻转，不能把该差异单独归因为context。
- P0的parent step20侧以run `p0-klear64k-parent-20260828T160138Z`完成：test38为6/38（15.79%，0 exceptions）；Verified27按全部attempt为9/27（33.33%），scoreable为9/26（34.62%），Sphinx 8621的agent Pod触及8Gi limit后以OOMKilled/exit 137终止并被Harbor记录为1个`NonZeroAgentExitCodeError`。相对SFT，test38配对为3胜32平3负，Verified27 benchmark为2胜23平2负，两个面板delta均为0、exact McNemar p均为1.0。parent的平均input tokens和agent steps在两个面板均明显更高，但没有换来总体成功率提升；该P0不支持继续追加PPO训练。
- 2026-08-30完成资源收尾：腾讯云CVM、CBS和相关计费资源已释放。历史`ACK_*`变量和`environment_type=ack`仍是代码兼容接口名称，不代表当前存在可连接的ACK或k3s集群。

以下按日期保留历史里程碑；历史500题、700题候选和32K模型选择结果不覆盖上述当前快照。

2026-08-13最新里程碑：Oracle累计记录1440条、接受981条；正式冻结train/validation/test为350/75/75，共覆盖77个仓库并返回 `freeze_ready=true`。500条冻结集已在AutoDL导入并注册为 `swesmith-curated-poc-500-v2`。64K服务探针三档全部通过，边界档总token为64544/65536。runtime v3 + `official-public-repro`的空轨迹守卫、`environment -> env`兼容和`working_dir`运行时注入均已完成；最终1-task Canary通过基础设施闭环：Exceptions=0、Submitted、模型调用37次、assistant/Shell各37轮、输入/输出token为332761/4814、reward字段完整且vLLM无上下文400/OOM。下一阶段为A800 80GB单卡上的10-task并发Canary：vLLM先采用`max-num-seqs=4`、32K scheduler token batch、chunked prefill和0.90显存利用率，Canary采用tasks=10、concurrency=4、retry=0；若启动日志给出的64K最大并发低于4则降为2，不降低单请求65,536窗口。

2026-08-14追加里程碑：64K服务探针三档全部通过，边界档总token为64544/65536，Canary启动前的真实40K请求gate也已通过。固定SWE-bench Verified 27题Canary产生10个成功；原offline-v2批次为25个正常评分加2个verifier异常，两个异常任务随后在offline-v3分别复测为 `Exceptions=0, reward=0`，校正结果为10/27 = 37.04%。该点估计与论文SFT的38.2%数值接近，但它是固定27题诊断子集上的“原批次 + 异常恢复”口径，不是单一 `27 Trials / 0 Exceptions` 作业，也不等价于完整500题榜单复现。

2026-08-14 SWE-Smith RL重叠集诊断：从166题中固定筛选的30个train任务实际以并发10运行，27题正常评分，其中reward 1为2题、reward 0为25题，scoreable-only `pass@1=2/27=7.41%`；另有2题agent容器在8GiB Pod上限内OOMKilled（exit 137）和1题ACK自动label超过Kubernetes 63字节限制。该作业在30/30后被人工中断收尾，因此job级 `finished_at` 为空，不能报告为无异常的2/30。当前证据已足以判定该候选集的pass@1过低：不重跑本轮Canary，也不从这30题继续选择8题进入train smoke。ACK自动label现统一进行确定性63字符净化；普通Canary默认并发硬上限为4，Verified专用目标显式允许10。并发上限只防止再次意外放大节点负载，不代表两个单Pod OOM已被复测修复；本轮停止后不盲目提高Pod内存。

2026-08-14 Klear数据调研补充：公开的66K SWE-Smith数据是SFT消息轨迹集，固定revision共65,994行且schema仅含`instance_id`、`messages`。论文没有披露这些SWE轨迹由哪些模型生成；文中“强教师模型至少成功一次”描述的是另行的RL任务筛选，不能作为66K轨迹来自强模型或逐条成功的证据。提交标记、模型自测、shell返回码以及本项目的`klear_trajectory_count`均不等价于官方verifier的reward 1。

2026-08-14 强模型验证交集已固定：2,614题静态通过集与官方Claude/GPT成功轨迹、SWE-Master教师池成功统计取并集式成功交集后得到487题`filter-pro`；再与当前正式冻结500题及completed镜像取交集，得到125题`freeze-pro`，其中train/validation/test为90/18/17。`freeze-pro`中8题被两个独立数据源验证，7题有Claude 3.5成功证据；当前静态通过集没有GPT-4o成功任务交集。详细口径与证据边界见`output/docs/SWESMITH_STRONG_MODEL_FILTER.md`。

同日已从`freeze-pro`固定模型选择用SWE-Smith 30题（validation18 + priority/sha256排序的train12），并增加统一32K的Verified27 + SWE-Smith30测评入口。8B主候选、SERA-14B条件门槛、32B硬件门槛和仅供用户在AutoDL执行的命令见`output/docs/SWE_AGENT_MODEL_SELECTION_PLAN.md`。

2026-08-15数据扩充名单已固定：阶段A保留125题`freeze-pro`并从已有镜像的`filter-pro`增加225题，阶段B从官方59,136题与完整3,748题`swe-smith-filtered`的差集中选择350题，总计700题；另有阶段A 137题和阶段B 350题候补。阶段B主名单350题全部同时具有官方Claude/GPT成功轨迹与SWE-Master教师池成功证据。该名单尚未完成新增任务Oracle和镜像验收，不能直接注册为训练集。详见`output/docs/SWESMITH_GRPO_700_EXPANSION.md`。

freeze-700执行链已实现：阶段A从已验收数据包复用任务目录，阶段B从固定官方revision通过Harbor SWE-Smith adapter生成；每题记录任务树与verifier指纹。历史177个accepted和103个终止失败可对账复用，4个`RuntimeError`重新进入Oracle队列。最终解析强制Stage A/B各350、split 490/105/105、仓库隔离、单仓上限20和至少90个仓库。新基础镜像以`baseanchor-*`分散到现有80个TCR分片，不新增仓库；基础镜像copy前和每个Oracle批次云端作业前均以实tag做100 tag增量投影门禁。代码就绪不代表数据已freeze；仍须在CVM/AutoDL完成实际作业。

2026-08-15统一32K模型选择进展：`Klear-AgentForge-8B-SFT`与最终`Klear-AgentForge-8B`均在SWE-Smith30得到5/30、在SWE-bench Verified27得到8/27，合计均为13/57（22.81%），两组作业均无异常。当前固定57题上未观察到最终RL模型相对SFT模型的通过率增益；这不是完整Verified 500题或论文64K口径结论。其他候选模型仍在评测，当前不提前选择GRPO基模。

2026-08-15 `mini-coder-4b`完成同一统一32K、mini-swe-agent-plus、runtime v3的固定57题评测：SWE-Smith Pro 30题1/30（3.33%），SWE-bench Verified 27题7/27（25.93%），合计8/57（14.04%），两个作业均为`Exceptions=0`。对应Harbor作业为`2026-08-15__23-02-43`和`2026-08-15__23-18-14`；该固定小样本结果低于两个Klear 8B候选的13/57，不等价于完整Verified 500题结论。

`GLM-4_7-swesmith-SFT`已完成相同32K、mini-swe-agent-plus、runtime v3口径的固定57题评测：SWE-Smith Pro为3/30（10.00%），SWE-bench Verified offline-v3为6/27（22.22%），合计9/57（15.79%）。两个作业分别为`2026-08-15__23-32-59`和`2026-08-16__00-29-43`，耗时1h0m13s和48m38s，均使用并发8、retry=0；两部分分别有7和8个`NonZeroAgentExitCodeError`，合计15/57。当前摘要按全部trial原样计分，不因agent异常调整分母；该成绩略高于`mini-coder-4b`的8/57、低于两个Klear 8B候选的13/57，且有效运行率明显更低，因此不足以据此选择GRPO基模。

`a3-rl-swesmith`也完成了同一32K、mini-swe-agent-plus、runtime v3入口的两组请求，但两项作业几乎全程重叠并共同以并发8使用单个ACK节点，因此必须保留资源竞争边界。SWE-bench Verified offline-v3作业`2026-08-16__01-21-05`记录27/27，reward 1为6题、reward 0为21题，Mean为0.222，另有10个`NonZeroAgentExitCodeError`，耗时1h15m3s。SWE-Smith Pro作业`2026-08-16__01-23-40`请求30题但摘要只记录29个trial，29题reward均为0，Mean为0.000；异常为13个`NonZeroAgentExitCodeError`和1个`PodReadyTimeoutError`，耗时1h19m59s。同期ACK调度明确出现CPU/内存不足，freeze-700首批Oracle因此在正式写入前安全中断，Oracle结果仍保持历史280条不变。当前按原始作业记录保留`6/27`和`0/29 recorded`，不把缺失trial或`PodReadyTimeoutError`归因为模型能力，也不将两项直接合并成可与无资源竞争作业等价的57题排名；如需正式比较，应在ACK独占窗口复测受影响任务。

2026-08-16 freeze-700首批40题已在ACK独占窗口完成并通过验收。NOP为38题reward 0、2题`VerifierTimeoutError`；排除这2题后的Oracle为35题reward 1、1题reward 0和2题`VerifierTimeoutError`。正式结果由280条增加到320条，其中accepted为212条；首批接受35/40，Stage A/B分别接受23/12。按静态、alignment、镜像和指纹全部门禁计算，当前有效可冻结185题，其中Stage A为173、Stage B为12，距350/350分别缺177和338；`final_ready=false`。正式`oracle/results.jsonl` SHA-256为`5530c01e04030193ef33a34ab7416387c32e0739c9e33f5326e850a3386b650e`，`reports/oracle-summary.json`为`81cc0c417a26ed8fee945935a691b85755ec40a7065f0c280b4051d5e1811fbb`。下一批前必须先审计Stage A剩余候选的理论可达性，不能只按raw accepted数量判断。

## 配置与本地文件（重建环境时使用）

```bash
cd /absolute/path/harbor-qwen-grpo-experiment
cp .env.example .env
# 在 .env 中填写 KubeConfig、Registry、BuildKit 证书、model gateway 等真实值
make help
```

- `.env.example` 是完整模板；`.env` 是本机配置，两者变量名应保持同步。`.env` 可含凭证，已被 Git 和 AutoDL 打包流程排除。
- `ACK_REGISTRY_PREFIX`、Registry凭证和 `ACK_IMAGE_PULL_SECRET` 必须匹配。切换ACR/TCR后必须重新执行 `make ack-prepare`。
- 当前主仓为 `ccr.ccs.tencentyun.com/harbor-qwen-grpo-tcr`，使用 `ACK_TASK_IMAGE_LAYOUT=base-sharded-tags`、80个 `task-XX` 分片仓库和 `ACK_TASK_IMAGE_BASE_SHARDS=5`。该布局为2614个静态通过任务及 `basecache-*` 预热标签保留单仓库100个版本配额余量；旧 `sharded-tags` 和ACR `repository-per-task` 路径仅作兼容。
- 已有ACR镜像可在CVM使用 `make registry-migrate-linux` 直接复制到TCR；迁移脚本同时处理3个基础设施镜像、已完成的基础镜像及completed/skipped状态，不经Mac下载镜像层。
- 有效管理员 KubeConfig 应保存在项目外，并由 `KUBECONFIG_PATH` 指向。项目根目录的 `ack-admin-public.yaml` 是 0 字节空文件，未被任何代码引用，可手动删除。
- `docker/base-images-*.json` 和 `docker/base-image-rewrites.json` 是 Mac 侧便携镜像队列/快照。`make dataset-images-mirror` 默认使用 `docker/base-images-manifest.json`；可用 `IMAGE_MANIFEST=/absolute/path/...` 覆盖。AutoDL 运行时仍使用 `state/datasets/.../profiles/...` 下的 profile 文件。
- CVM/Linux 可安装 `skopeo` 后运行 `make dataset-images-mirror-linux`；已导出 `CURATION_IMAGE_MANIFEST_FILE` 时自动读取当前 profile 清单。`DATASET_IMAGE_DOCKERHUB_PROXY_PREFIXES` 是逗号分隔的显式代理前缀；代理失败会回退原始 Docker Hub。目标 manifest digest 与源 linux/amd64 digest 一致后才进入 completed，失败项保留 pending。2 GiB 搬运阈值只限制尚未复制的镜像，ACR 中已存在且 digest 一致的镜像直接复用。

## 阶段与 Make 入口（历史流程/重建手册）

以下命令不能在当前归档状态直接执行；必须先重新配置CPU云节点、k3s、Registry访问、BuildKit证书与PVC、KubeConfig/RBAC，以及AutoDL到sandbox和model gateway的网络链路。

### 1. Mac 准备

```bash
make mac-preflight
make prepare-sources
make buildkit-certs
make push-infra-images
make package-autodl
```

### 2. AutoDL 与 ACK 准备

```bash
make install-conda
make autodl-ack-network

# Mac 管理员身份
make ack-prepare
make buildkit-up

# AutoDL 运行身份；buildkit-tunnel 需常驻
make buildkit-tunnel
make buildkit-status
make buildkit-smoke
make network-smoke
make preflight
```

### 3. 数据筛选与镜像

```bash
make pull
make dataset-plan
make dataset-download
make dataset-filter
make dataset-images-plan

# 在 Mac 上同步镜像；默认读 docker/base-images-manifest.json
make dataset-images-mirror

# 或在 CVM/Linux 上使用 skopeo 直接复制；默认读取当前 profile 清单
make dataset-images-mirror-linux

# 回到 AutoDL/ACK 验收、oracle 验证、冻结 split
make dataset-images-check
make dataset-oracle
make dataset-freeze-check
make dataset-freeze
make dataset-register
make dataset-status
```

### 3.1 从ACR切换到TCR个人版

迁移必须在没有运行Oracle/Canary/GRPO任务时执行。Mac用腾讯云CLI准备命名空间和仓库；CVM的同一个skopeo auth文件同时登录ACR和TCR，然后复制已有镜像：

```bash
# Mac：TCR_PERSONAL_REGION固定为ap-guangzhou；个人版中国大陆主服务位于广州
make tcr-prepare-personal

# CVM：先把ACK_REGISTRY_PREFIX指向TCR，但暂不改CURATION_IMAGE_REGISTRY_PREFIX
skopeo login --authfile "$DATASET_IMAGE_REGISTRY_AUTH_FILE" "$ACR_PUBLIC_REGISTRY_HOST"
skopeo login --authfile "$DATASET_IMAGE_REGISTRY_AUTH_FILE" "$TCR_REGISTRY_HOST"
make registry-migrate-linux

# CVM：迁移成功后令基础镜像目标也指向TCR
# CURATION_IMAGE_REGISTRY_PREFIX=${ACK_REGISTRY_PREFIX}
make dataset-images-plan
```

迁移已有任务镜像或进行大批量Oracle前，在CVM按顺序执行 `make registry-prewarm-plan`、`make registry-task-migrate`、`make registry-prewarm-linux` 和 `make registry-prewarm-check`。该流程先校验每个任务仓库最多100个标签，再把基础层预热到对应 `task-XX` 仓库。随后由Mac管理员使用TCR凭证运行 `make ack-prepare`，更新两个namespace的pull secret；再执行 `make buildkit-up`、`make dataset-images-check`、`make buildkit-smoke`。CVM与AutoDL的 `.env` 均需使用同一TCR前缀和80分片布局。

2026-08-11验收快照：3个基础设施镜像的源/目标digest一致；84个可用基础镜像已迁移、3个超限项保持skipped、pending为0；166个历史任务镜像目标完成布局迁移；357个“基础镜像 × 任务仓库”组合已预热并通过digest校验，单仓库最大投影标签数为93/100。`registry-migrate-linux` 只处理infra、基础镜像和镜像队列状态；历史任务镜像由 `registry-task-migrate` 单独处理。

### 3.2 批量Oracle与冻结停止条件

CVM使用 `CURATION_ORACLE_BATCH_SIZE=40`、`CURATION_ORACLE_CONCURRENCY=10` 和 `CURATION_ORACLE_VERIFIER_TIMEOUT_SEC=180`。`oracle-batch` 按split缺口和仓库覆盖做确定性轮询，优先选未覆盖/低覆盖仓库，避免任务名排序导致仓库集中。2026-08-11批量循环已在 `freeze_ready=true` 时输出 `BULK_ORACLE_FREEZE_READY` 并停止；最终Oracle为1440条记录、981条接受，冻结选择为350/75/75和77个仓库。

`buildkit-tunnel` 和 `dataset-oracle-bulk` 必须是两个独立tmux会话。CVM重启后，BuildKit Pod/PVC会保留，但本机 `127.0.0.1:1234` 的port-forward不会自动恢复；必须先重启隧道并通过 `make buildkit-status` 和 `make buildkit-smoke`，再启动Oracle。若出现 `dial tcp 127.0.0.1:1234: connect: connection refused`，应立即停止bulk，严格按受影响batch的task ID恢复，不得笼统删除所有 `RuntimeError`。详细命令和恢复流程见 `output/docs/DATASET_EXPANSION_500_RUNBOOK.md`。

### 4. Canary、GRPO、PPO 与评估

已验证的两卡colocated配置为 `TRAIN_N_GPUS_PER_NODE=2`、`TRAIN_TENSOR_PARALLEL_SIZE=1`、`TRAIN_MODEL_DTYPE=bf16`、`TRAIN_GPU_MEMORY_UTILIZATION=0.35`，并关闭actor、optimizer与reference CPU offload。当前AutoDL机器必须设置 `NCCL_P2P_DISABLE=1`，否则原始 `all_reduce` 即会死锁；该规避项不是正常机器的通用默认值。独立Canary vLLM必须在GRPO前停止。

```bash
make canary
make fsdp2-smoke
make train-smoke
make train
make eval-curated
make ppo-eval-checkpoint
make ack-status
make ack-stop
```

PPO不由现有 `make train` 隐式启用。`ppo-smoke`固定1个update；`ppo-soak`只允许2–3个update，超过3步会在preflight前失败；`make ppo`是唯一正式入口，强制使用完整187题train split、`TRAIN_TOTAL_BATCHES=-1`和按epoch训练。正式batch默认为8，因此每个epoch有24个update：187题各出现一次，尾批确定性补5次暴露，不再静默丢掉3题。训练期validation固定为validation42中的确定性21题（约10%），在step 0/10/20/24执行；checkpoint保存step 10/20/24。完整42题只用于训练后复评。每个epoch输出`TRAIN_EPOCH_COVERAGE`；若末步不落在常规保存间隔上，会额外保存最终checkpoint并输出`PPO_FINAL_CHECKPOINT_PASSED`。完整边界见 [`output/docs/PPO_TRAINING_RUNBOOK.md`](PPO_TRAINING_RUNBOOK.md)。

## scripts/ 与 Makefile 对照

| 阶段     | Make 指令                                                                | 脚本                                  | 作用                                                                                                                                                                                    |
| ------ | ---------------------------------------------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 通用     | —                                                                      | `scripts/lib.sh`                    | 加载 `.env`、检查变量/工具、激活 Conda、组装 BuildKit 与镜像重写参数。                                                                                                                                       |
| Mac    | `make mac-preflight`                                                   | `09_macos_preflight.sh`             | 检查 Intel Mac、Git、Docker daemon、Buildx 和基础命令。                                                                                                                                          |
| Mac    | `make prepare-sources`                                                 | `10_prepare_sources_macos.sh`       | 拉取固定 commit 的 Harbor/rLLM，幂等应用 `patches/`。                                                                                                                                            |
| Mac    | `make package-autodl`                                                  | `12_package_autodl_bundle.sh`       | 打包已打补丁源码，排除 `.env`、凭证、state 和运行输出。                                                                                                                                                    |
| Mac    | `make tcr-prepare-personal`                                            | `14_prepare_tcr_personal.sh`        | 幂等创建TCR个人版命名空间、基础仓库和配置数量的任务分片仓库。                                                                                                                                               |
| CVM    | `make registry-prewarm-plan`、`make registry-task-migrate`、`make registry-prewarm-linux` | `17_prewarm_task_repositories_linux.sh` | 校验TCR标签配额、迁移旧分片任务镜像，并将基础层预热到当前任务仓库。 |
| Mac    | `make push-infra-images`                                               | `13_push_infra_images_macos.sh`     | 将 BuildKit、curl 和 uv 的 `linux/amd64` 镜像推入当前Registry。                                                                                                                                |
| CVM    | `make registry-migrate-linux`                                          | `16_migrate_registry_images_linux.sh` | 使用skopeo把现有基础设施与基础镜像从旧Registry复制到当前Registry，并迁移镜像队列状态。                                                                                                                        |
| Mac    | `make buildkit-certs`                                                  | `15_generate_buildkit_certs.sh`     | 在 `.secrets/buildkit/` 生成 BuildKit mTLS CA/server/client 证书。                                                                                                                          |
| AutoDL | `make install-conda`                                                   | `11_install_conda_autodl.sh`        | 在已激活 Conda 环境安装项目、Harbor、rLLM 和 verl，并验证 CUDA。                                                                                                                                        |
| AutoDL | `make autodl-ack-network`                                              | `25_autodl_ack_network.sh`          | 验证 AutoDL 出口 IP、Registry、k3s API、KubeConfig、RBAC 和 Secret。                                                                                                                           |
| ACK    | `make ack-prepare`                                                     | `20_ack_prepare.sh`                 | 创建 runtime/builder namespace、匹配 Registry 域名的 pull secret、ServiceAccount 和 BuildKit TLS Secret。                                                                                        |
| ACK    | `make buildkit-up`                                                     | `21_buildkit_up.sh`                 | 渲染 `k8s/buildkit` 模板，部署 rootful BuildKit、Service 和持久缓存 PVC。                                                                                                                           |
| ACK    | `make buildkit-tunnel`                                                 | `24_buildkit_port_forward.sh`       | 在当前执行端（CVM做Oracle，AutoDL做Canary/GRPO）循环维持 `127.0.0.1:1234` 到 ACK BuildKit 的端口转发。                                                                                                      |
| ACK    | `make buildkit-status`                                                 | `22_buildkit_status.sh`             | 查看 BuildKit Deployment/Pod/Service/PVC，并查询 `buildctl` worker。                                                                                                                         |
| ACK    | `make buildkit-smoke`                                                  | `26_buildkit_smoke.sh`              | 通过 mTLS tunnel 执行无残留的最小 OCI 构建。                                                                                                                                                       |
| ACK    | `make network-smoke`                                                   | `23_ack_network_smoke.sh`           | 从 ACK Pod 请求 GPU model gateway，验证反向网络。                                                                                                                                                |
| 验收     | `make preflight`                                                       | `00_preflight.sh`                   | 只读检查 Python/库版本、Kubernetes权限、Registry、gateway和BuildKit。                                                                                                                              |
| 数据     | `make pull`                                                            | `30_pull_dataset.sh`                | 使用 rLLM 拉取 Harbor SWE-Smith 入口数据。                                                                                                                                                     |
| 数据     | `make dataset-plan/download/filter/images-plan/freeze/register/status` | `31_curate_dataset.sh`              | 调用 Python 筛选器，完成候选计划、下载、静态过滤、镜像计划、split 冻结/注册和状态统计。                                                                                                                                   |
| 数据     | `make dataset-images-mirror`                                           | `33_mirror_dataset_images_macos.sh` | Mac 上逐项处理 pending 镜像：复用本地镜像或 pull，push 到 ACR，验证后删除对应本地 tag；超限镜像转 skipped。                                                                                                             |
| 数据     | `make dataset-images-mirror-linux`                                     | `35_mirror_dataset_images_linux.sh` | CVM/Linux 使用 skopeo 按 linux/amd64 直接复制；支持单进程有界并发、命令超时、Docker Hub代理与源站回退，状态迁移串行提交，digest验证成功后才归档。                                                                                      |
| 数据     | `make dataset-images-check`                                            | `34_check_dataset_images.sh`        | 通过Registry API检查completed队列的镜像覆盖率。                                                                                                                                                    |
| 数据     | `make dataset-oracle`                                                  | `32_oracle_validate.sh`             | 按 split 和仓库确定性轮询，在 ACK 分批跑 NOP baseline 和 oracle verifier；verifier 默认180秒超时，NOP失败任务直接拒绝，其余任务继续Oracle。                                                                            |
| 数据     | `make dataset-freeze-check`                                            | `31_curate_dataset.sh freeze-check` | 只读模拟冻结，检查三个split目标数和最少仓库覆盖；以 `freeze_ready=true` 作为停止Oracle的条件。                                                                                                                        |
| 数据     | `make swesmith-pro-derive`                                             | `56_derive_swesmith_pro.sh`         | 从固定Claude/GPT成功轨迹、SWE-Master教师池统计和正式数据包派生`filter-pro`/`freeze-pro`，不运行Canary。                                                                                                             |
| 实验     | `make canary`                                                          | `40_canary.sh`                      | 从冻结并注册的 curated validation 确定性选题，用指定 harness 跑 Harbor canary。                                                                                                                         |
| 实验     | `make fsdp2-smoke`                                                      | `51_fsdp2_smoke.sh`                 | 两卡运行不依赖Harbor/CVM的最小NCCL、FSDP2、backward和optimizer step，先隔离多卡运行时。                                                                                                                     |
| 实验     | `make train-smoke`                                                     | `50_train_grpo.sh`                  | 默认运行1个train task、每组4条rollout、最多1个optimizer step；支持精确task、短rollout和LoRA rank A/B，每次自动使用独立run目录；不执行validation或checkpoint。                                                               |
| 实验     | `make train`                                                           | `50_train_grpo.sh`                  | 检查冻结数据和镜像覆盖后，启动 rLLM + verl + vLLM + GRPO。                                                                                                                                            |
| 实验     | `make ppo-smoke`、`make ppo-soak`、`make ppo`                           | `59_train_ppo.sh`                   | 保持GRPO默认不变；smoke固定1步，soak只允许2–3步，formal完整遍历187题并以确定性尾批补齐batch。                                                                                                                |
| 实验     | `make eval-curated`                                                    | `55_eval_curated.sh`                | 只读取冻结 test split 执行独立评估，避免训练泄漏。                                                                                                                                                       |
| 实验     | `make ppo-eval-checkpoint`                                             | `61_eval_ppo_checkpoint.sh`         | 单卡启动原始SFT或指定actor LoRA；P0统一以官方64K协议评测冻结test38与既有Verified27，并按面板输出benchmark/scoreable Pass@1、Wilson区间及配对统计。                                                                  |
| 运维     | `make ack-status`                                                      | `60_ack_status.sh`                  | 汇总 ACK builder 和 runtime sandbox 状态。                                                                                                                                                  |
| 运维     | `make ack-stop`                                                        | `90_ack_stop.sh`                    | 删除实验Pod/Job，保留BuildKit、PVC和Registry数据。                                                                                                                                                 |

## src/ 与 tests/

`src/harbor_qwen_grpo_experiment/` 是项目自有 Python 控制层，不复制 Harbor/rLLM 上游实现：

- `check_registry_images.py`：检查 Registry manifest，以原子写方式维护 pending/completed/skipped 队列。
- `curate_swesmith.py`：Hugging Face 分页下载、静态过滤、难度/仓库平衡、oracle 结果归一化、镜像计划和 split 冻结。
- `select_canary.py`：按 seed 选择/排除 canary，复制任务并保存 verifier 日志。
- `train_harbor_ack.py`：加载冻结 train/validation split，注入 ACK 环境参数，通过 rLLM `AgentTrainer` 连接 verl。

`tests/` 是离线单元测试：`test_curate_swesmith.py` 覆盖队列迁移、分页、过滤、平衡、允许短缺冻结和确定性 split；`test_select_canary.py` 覆盖排除、确定性选题和 verifier 日志补丁的幂等性。

## patches/ 与 upstream/

`upstream/harbor` 和 `upstream/rllm` 是固定 commit 的上游工作树，由 `make prepare-sources` 创建，不应在其中另行积累未记录的手工修改。`patches/` 是可审计、可重放的改造来源：

- `rllm-harbor-ack-env-kwargs.patch`：rLLM 将 `environment_kwargs` 从配置透传到 Harbor runtime，供 ACK namespace、ServiceAccount、BuildKit、Registry 重写等参数使用。
- `rllm-verl-native-ppo.patch`：为unified Verl + Harbor remote runtime增加native critic/GAE、critic optimizer、actor/critic联合checkpoint及同步separated-rollout路径。
- `rllm-context-budget-empty-trace.patch`：拒绝输出预算耗尽的请求和失败/空token trace，并在PPO转换层过滤空prompt/response step，避免上下文边界错误污染训练batch。
- `rllm-separated-rollout.yaml.patch`：为固定rLLM配置增加与`async_training`互相独立的`separated_rollout`开关。
- `harbor-ack-buildkit-mtls.patch`：增加 Harbor ACK environment，支持 rootful BuildKit mTLS、基础镜像重写、ACR 认证、资源/超时调整和 uv 预置。
- `harbor-ack-k8s-name-sanitization.patch`：将 ACK Pod 名规范化为 RFC 1123，并用哈希后缀避免长 trial 名截断碰撞。
- `harbor-ack-task-image-shards.patch`：为受仓库配额约束的Registry增加确定性任务镜像分片仓库与唯一tag布局。
- `harbor-job-verifier-timeout.patch`：为 Harbor job CLI 增加绝对 verifier 超时覆盖，Oracle 将任务自带的3000秒上限统一收紧到180秒。
- `harbor-swesmith-verifier-offline.patch`：去掉 verifier 对 `apt`/`astral.sh` 的运行时依赖，使用镜像中的 uv 和可配置 Python 镜像源，并区分基础设施失败与 reward 0。
- `harbor-qwen-skip-preinstalled.patch`：ACK 中优先复用预装 Node/Qwen Code，避免依赖 `raw.githubusercontent.com`；仅在 `APPLY_QWEN_PREINSTALL_PATCH=1` 时应用。

## 其他目录

| 路径                | 作用                                                                  |
| ----------------- | ------------------------------------------------------------------- |
| `.secrets/`       | Registry用户名/密码和BuildKit mTLS证书；被Git与打包排除。                         |
| `configs/`        | harness 配置；当前为 mini-swe-agent 文本 Bash 动作 YAML。                      |
| `docker/`         | 回退用 Qwen Code overlay Dockerfile，以及 Mac 侧 SWE-Smith 基础镜像队列/重写快照。    |
| `k8s/`            | ACK BuildKit Deployment、Service、PVC 的参数化模板。                         |
| `output/docs/`    | 架构、ACK、AutoDL、harness/SFT 和阶段总结文档。                                  |
| `output/pdf/`     | 已生成的架构和操作 PDF。                                                      |
| `output/bundles/` | `make package-autodl` 产生的可上传 AutoDL 源码包；不入 Git。                     |
| `state/`          | AutoDL 运行时数据、筛选 profile、Harbor jobs、oracle 结果和冻结 split；按需生成，不入 Git。 |
| `logs/`           | 本地运行日志；按需生成，不入 Git。                                                 |

## 验收与停止条件

- `make preflight`、`make buildkit-smoke` 和 `make network-smoke` 必须通过。
- `make canary` 必须在冻结并注册的 curated validation 上产生真实 Shell observation、可解析 trajectory 和 verifier reward；环境异常或 reward 缺失时不进入训练。
- GRPO首轮保持 `TRAIN_PARALLEL_TASKS=2`，确认 AutoDL GPU/KV cache、ACK Pod 容量和 W&B 指标稳定后再递增并发。
- Oracle 使用 `CURATION_ORACLE_VERIFIER_TIMEOUT_SEC=180` 筛除长尾任务；训练使用 `TRAIN_VERIFIER_TIMEOUT_MULTIPLIER=0.06`，将 SWE-Smith 任务自带的3000秒 verifier 上限等效收紧为180秒。
- 历史500题profile已在350/75/75与77/70仓库覆盖后结束；当前grpo700 profile按显式短缺规则冻结为187/42/38、共267题和89个仓库。
- 当前267题正式冻结集已落盘、导出、导入并注册；后续GRPO/PPO不得向该freeze混入新Oracle任务或改变validation/test。
- 两卡FSDP1 GRPO smoke已在禁用故障P2P路径后完成optimizer step和权重同步。rank 32 `safetensors` 同条件复测已恢复合法动作并证明首次基础权重加载修复有效；正式训练前还必须得到至少一个非零学习信号batch，并验证实际LoRA更新后的再次同步。
- PPO的40K、900秒model-only warm-start第二轮20步已通过工程门禁；能力门禁尚未通过。下一步仅执行P0：在统一64K公开协议下比较原始SFT与父checkpoint step20的test38和Verified27 Pass@1；不得仅依据训练reward继续追加step。

## 详细文档

- [架构与配置](ARCHITECTURE.md)
- [ACK 注册和网络](ACK_SETUP.md)
- [AutoDL 配置](AUTODL_SETUP.md)
- [Harness、SFT 与 mini-swe-agent](HARNESS_SFT_MINI_SWE_AGENT.md)
- [监控与验收](MONITORING.md)
- [概念与常见问题](FAQ.md)
- [3000候选到500冻结任务运行手册](DATASET_EXPANSION_500_RUNBOOK.md)
- [SWE Agent候选模型统一测评方案](SWE_AGENT_MODEL_SELECTION_PLAN.md)
- [项目分层架构](PROJECT_LAYERED_ARCHITECTURE.md)
- [PPO训练设计与验收手册](PPO_TRAINING_RUNBOOK.md)
