# HRL 续作执行说明:交给 Sol 的工程任务书 适用日期:2026-09-11。工作目录:本仓库根目录。先检查当前代码与本轮测试结果,再按 P0 → P1 → P2 → P3 顺序执行。 目标是交付可运行、可审计的整场调度学习系统;训练收益由完整场景验证决定,不把训练脚本存在或局部奖励上升视为完成。 本说明更新了原粘贴 Prompt 与 `.zcode/plans/plan-sess_cf390556-4ef3-4ce6-b91e-782aee1718f9.md` 中不符合现有协议或证据的部分。 ## 1. 现在有什么,缺什么 | 组件 | 当前状态 | Sol 的操作 | | --- | --- | --- | | `protocol/`、`referee/`、`harness.py` | 已有客户端、独立评测机、内存回环与计时审计 | 复用,不另建模拟器客户端 | | `belief/`、`particles.py`、`planner/` | 已有保守候选、网格幸存集、覆盖证明、证书清除与后备清除 | 保持证明前提;改调度时复用 | | `rl/`、`train_rl.py`、现有 RL 检查点 | 已有单源选点 PPO/MaskablePPO 与完整对照 | 作为局部策略和对照,勿命名为端到端 PPO | | `hrl/constants.py`、`scheduler.py`、`planner/hrl_loop.py` | 已有高层候选、特征、执行与闭环骨架;存在本轮需修复的 P0 项 | 先完成第 4 节门槛 | | `hrl/hierarchical_env.py`、`curriculum.py` | 已有训练环境和课程;奖励、终止、训练配置仍需审核 | 在长训前修正,覆盖独立环境/部署一致性 | | `hrl/low_level_env.py`、`executor.py`、`train_hrl_low.py` | 有八方向到达实验;训练入口尚有掩码等缺陷 | 作为可选离线实验,不能卡住主线 | | `tests/test_hrl.py` | 有接口和启发式 episode 测试 | 增补行为验证,不能只检验公式与实现一致 | | `train_hrl_high.py`、`pretrain_hrl_expert.py` | 尚未实现 | P1 编写最小可训练闭环,P2 再加入 BC | | `benchmark_hrl.py`、`ablate_hrl.py`、`tune_hrl.py` | 尚未实现 | 先评测,再训练,再做消融,最后受限调参 | | CLI 的 `hrl` 策略和 `--hrl-model` | 当前入口尚未接入 | P1 接入并检验 `--help` 与离线闭环 | | `output/hrl/` 的高层模型、曲线、评测表 | 本次审阅未发现这些产物 | 不声称已有 HRL 模型或训练成绩 | 现有证据:修订单步 RL 的 Q3 独立验证均值比 `bayes` 低 0.69%,区间跨 0;Q4 比 `directional` 低 14.38%,比旧 PPO 低 2.26%,后一比较区间跨 0。 这些来自固定模型、本地 18 场/题的验证;新 Q4 的后备清除次数更多,边界压力性能有退化。详情见 `docs/强化学习适用性审核与改进-20260911.md`。 没有证据证明 HRL 已优于上述基线,没有证据支持“Q4 迁移节约 80% 训练成本”或“全部合法场景小于 4000 秒”。 ## 2. 必须纠正的原 Prompt 假设 1. `/measure` 与 `/clear` 提交终点,移动按两次实际动作位置间的直线距离除以 5 计费;没有朝向、转弯或八方向移动协议。 2. 八方向策略仅在本地推演再强制补上终点,无法影响模拟器实际路径;不能把这段推演称为比赛收益来源。 3. `/clear` 不切换接收机频道,目标频道与当前接收机频道应分别记录;`near` 是测量结果,清除仍需独立请求。 4. 接收半径逐源未知,动作掩码只能使用观测与保守界,不能读真实半径、源位置、类型或朝向。 5. Q3 的 `no_signal` 只能按已证明的保守半径规则删格;Q4 的 `no_signal` 可能由方向遮挡造成,不能直接删空间候选。 6. Q4 联合位置/半径/朝向粒子是后续研究选项;普通二维粒子加“角度门控”并不会自动得到正确联合后验。 7. 固定地点误差固定;同地重测不是新独立样本。保留读数舍入裕量,不收紧真实的 ±1° 误差界来追求表面收敛。 8. 源数最多 16 不等于只有 16 个频道;所有按频道编号索引的动作必须覆盖 1–20。 9. 连续无信号次数不能作为全场结束条件;覆盖参数不能随意调到破坏已证明的发现覆盖。 10. “无信息增益”“无动作掩码”“无粒子滤波”必须精确定义;不能通过取消清除证书或真源保留约束制造消融。 11. 原 Prompt 的 6 个状态与实现里的状态枚举不一致;以 `ChannelStatus` 为准,额外 TRACKING/LOCATED 只能定义为派生特征。 12. 协议文档 §6 仍写持续搜索默认开启;当前 `config.py` 为 `persistent_search=False`,CLI 用 `--persistent` 显式开启。先同步文档,不恢复过时默认值。 ## 3. 推荐架构与工程边界 采用“高层学习调度 + 低层局部选点 + 协议执行”的分层架构。高层学习先处理哪个频道、继续覆盖还是定位、何时使用后备清除。 低层默认调用成熟几何选点;可切换现有 `PointSelectionPolicy` 学习局部检测点,形成第二个学习层。直线移动与设备动作继续由协议客户端执行。 Q3 首版低层用 `bayes` 几何选点;Q4 先保留 `directional` 的遮挡处理,待接线一致性通过后对比旧/新局部 PPO。 ```text SimulatorClient.state + belief + particles + coverage ledger ↓ 同一份候选快照和动作掩码 高层 MaskablePPO:选择频道/覆盖站/清除任务 ↓ 局部选点:geometry | 已有 v2 PointSelectionPolicy ↓ 证书/预算/覆盖约束 + 实际 measure/clear 宏动作 ↓ accepted 请求与响应 → 时间、信念、清除与覆盖账本 ``` 八方向 PPO 保留为 `low_level_env.py` 的离线附录实验;生产默认无需加载。若论文要求字面双 PPO,用高层调度 PPO + 局部选点 PPO 对应真正可影响成绩的两个层次。 现有高层一个动作可以包含整站逐频道扫描或多次后备清除,因此是变长宏动作。记录每个宏动作的实际持续时间、请求数和中断原因。 先采用 `gamma=1` 与实际时间成本,避免把“每宏动作折扣一次”误当成“每秒折扣一次”;只有明确改变目标才引入按持续时间折扣。 第一版保留 120 槽位 MLP,不同时重写注意力网络或连续动作;需要多候选/频道时另升动作版本并独立比较。 建议新增的共享接口如下;这些是待实现契约,避免训练和 CLI 分别拼接策略。 ```python @dataclass(frozen=True) class HRLPolicyConfig: local_selector: str = "geometry" # geometry | rl local_model_path: str | None = None def make_hrl_loop(client, config, *, problem: int, high_policy=None, policy_config=HRLPolicyConfig()) -> HRLLoop: ... def validate_episode(summary: dict, events: list[dict], truth_channels: set[int]) -> dict: ... # 仅评测模块 def run_episode(scene: dict, variant: dict, *, output_dir: Path) -> dict: ... ``` ## 4. P0:修复正确性,未过门槛不得长训 以下表中的状态以本轮提交和测试报告为准;Sol 接手时先查看 diff,已完成的项只做回归,不重复实现。 | 项目 | 精确入口与问题 | 目标与验收 | | --- | --- | --- | | P0.1 槽位冲突 | `constants.py`;`scheduler.build_candidates/heuristic_action`:clear 频道 17–20 与 locate 频道 1–4 重叠 | 本轮优先修复;每类按 20 频道分配,构造同时就绪冲突场景验证任务均保留 | | P0.2 清除事件遗漏 | `scheduler._hrl_execute_fallback` 成功未写 `_step_clears` | 本轮优先修复;证书/后备/宏动作内部清除均由相同成功事件口径计数,一次且仅一次 | | P0.3 候选过期 | `HRLLoop._coverage_phase` 在构建候选后 `_measure_at_stop` 可改变信念 | 本轮优先修复;选动作前候选/特征/掩码属于同一个状态快照 | | P0.4 奖励对齐 | `HierarchicalEnv.step/_reward_from/HRLReward` | 改默认奖励,成功/异常/安全网/截断均计入已经发生的真实时间 | | P0.5 回合终止 | `HierarchicalEnv.step/reset/close` | 实际完成、失败终止与采样截断分开;收尾不丢 /exit,不把零观测用于有效截断 bootstrap | | P0.6 训练部署配置 | `curriculum.training_config` 默认网格 29.3m,部署 14.65m | 首个可比较模型使用生产几何配置;粗网格只能显式快速预训练,后接完整保真微调与评测 | | P0.7 无进展循环 | `scheduler` 的 locate/probe/fallback 掩码及预算检查 | 去重、已清除/无效证书、后备预算不足在动作前处理;合法动作不能无限零成本自循环 | | P0.8 测试与依赖 | `tests/test_hrl.py` 导入守卫、`policy.py/scheduler.py` 顶层 numpy | 不安装 RL 组时基础 CLI 可导入;完整 RL 环境运行测试时不得意外全部 skip | 建议槽位布局为 clear 0–19、locate 20–39、station 40–88、fallback 89–108、保留 109–119;所有槽位互斥且小于 120。 槽位含义改变必须升 `FEATURE_VERSION`,即使仍是 1248 维/120 动作,也必须拒绝旧语义检查点。 模型元数据应要求 `level/problem/algorithm/feature_version/action_layout_version/reward_version`,并记录模型 SHA、配置、依赖版本、代码版本。 缺字段不能默认为兼容;Q3 权重初始化 Q4 必须走显式训练迁移参数,部署加载仍严格检查题号。 默认奖励先用:`r = -实际本步虚拟时间增量 / 100`;证明完成时加固定完成奖,未完成的真实终止加失败罚。 失败惩罚按冻结的 episode 最大成本界设置并记录,不随意用不足以覆盖数千秒的 `-100`。 相同全清场景里逐源常数奖可能只是常数偏移,但不同终止路径、事件漏记和失败场景会改变激励;故首版去掉新发现/熵减/每源清除附加奖。 如需塑形,另做势函数差 `gamma * Phi(next_state) - Phi(state)`,真正终止态统一势函数值,并检验总和望远镜消去。 如果优化题目平均时间,用整场时间作为训练目标时明确这是所选代理;不同源数的跨场景均值与 `T/N` 均值不等价,不能暗称完全一致。 人工步数上限若仅为采样截断,返回可用的终末观测并允许 bootstrap;若定义为任务失败期限,应作为真实终止计罚。按该语义设计测试。 P0 验收至少覆盖以下行为,不只验证 reward 按代码相加: - 20 个频道的各类槽位唯一;频道 17–20 与 1–4 同时有 clear/locate 不丢任务。 - 同一观测轨迹分别构建独立训练环境与部署闭环,比较候选、mask、特征、下一实际请求及状态。 - 固定动作序列跨成功、失败、后备与安全网路径:reward 的时间分项总和等于 accepted 日志复算时间。 - Q4 保证盘内/盘外无信号不误删真源;正读数重置遮挡序列;无效证书不能执行清除。 - 10/16 源、频道含 20、边界源与预算中断均检查真实源集合、缺席集合、正常退出、异常与计时。 - 评测端真值仅进 `validate_episode`,策略构建、候选、mask、观测与模型选择均不得读取真值。 ## 5. P1:最小完整闭环,先评测再短训 先实现 `scripts/benchmark_hrl.py` 与共享审计函数,使 `HRLLoop(high_policy=None)` 可以与原 `bayes/directional` 同场景对比。 这个启发式 HRL 骨架是重要对照:若差距来自任务候选、机会测量、Q4 保底或预算语义变化,先修或如实量化,不归因给神经网络。 每次运行将 scene、误差种子、配置、summary、完整 JSONL/accepted 事件、时间复算和模型 SHA 写入新目录;目录已存在则拒绝覆盖。 单场异常也写结果;聚合存在任一无效局时 `all_valid=false` 且脚本非零退出,不从平均值表中静默删除失败场景。 随后实现 `scripts/train_hrl_high.py`,第一版提供以下参数并通过 `--help` 验证: ```text --problem {3,4} --stage {1,2,3,4} --timesteps INT --seed INT --envs INT --vec-env {dummy,subproc} --device {cpu,cuda,mps,auto} --config-profile {production,coarse-pretrain} --model PATH --resume PATH --eval-manifest PATH --verbose INT --local-selector {geometry,rl} --local-model PATH ``` 阶段 1 即保持 20 频道与固定观测维度,只改变布景复杂度;早期课程可减少源数,但完整训练必须覆盖 10/13/16 源与实际 ±1° 固定地点误差。 Q4 完整课程同时覆盖少量/半数/大量定向源及近边界向外朝向;Q3→Q4 迁移与 Q4 随机初始化作为配对实验。 禁止让策略知道课程场景真实源数或隐藏的占用频道列表;初始位置保持官方 `(0,0)`,除非任务被明确标为局部交接课程。 先测 1/2/4 个环境的采样吞吐、内存和每次决策耗时,再选择 Dummy/Subproc;小 MLP 不假定 GPU 更快。 Subproc 环境类内部提供 `action_masks()`;Windows/macOS 使用入口守卫及可序列化工厂。 随机种子覆盖 Python/NumPy/Torch、PPO、每个环境、场景误差;每个 worker 使用独立 Monitor 文件。 保存实际 `model.num_timesteps` 与请求步数,恢复时说明增量还是累计;续训加载正确算法/特征版本且不覆盖原模型。 使用掩码评估接口,如 `MaskableEvalCallback`;同时在确定性推理中传入同源 mask。 CLI 加入 `--strategy hrl`、`--q4-strategy hrl`、`--hrl-model` 与局部策略选项,经 `make_hrl_loop` 统一构建;默认策略保持现状。 显式指定缺失模型应报可操作错误,不能把启发式降级结果记成 HRL 模型成绩;启发式骨架单独命名 `hrl_heuristic`。 P1 门槛:启发式骨架全场审计通过;512–2048 步训练冒烟可保存、重载、确定性推理;CLI 内存回环至少 Q3/Q4 各一场通过。 短训先用单个种子验证流程,不用这次模型的成功率作论文结论;完成后记录吞吐再定时间预算,不预设 1–2 小时足够。 ## 6. P2:完整保真训练、独立评测与消融 实现 `pretrain_hrl_expert.py`:运行 `hrl_heuristic`,保存 `(episode_id, state, candidates, mask, action)`;按 episode 划分训练/验证。 BC 与 PPO 的网络层、激活、归一化、mask 处理保持一致;复制后在真实样本上逐位比较 logits,critic 单独初始化。 记录专家动作无法映射到候选的比率与原因;若大量回退到最近候选,先改专家映射,不用假专家标签继续训练。 至少比较 BC+PPO 与随机初始化 PPO;BC 准确率单独报告,不能代替独立闭环用时与有效全清率。 冻结数据集分工: | 集合 | 用途与约束 | | --- | --- | | 已有 700–702 开发场景 | 查实现错误、探索配置与性能分解 | | 已有 91000–91005 场景 | 历史回归;结果已经被审阅,不再宣称是本次全新盲测 | | 新开发/选择清单 | 固定 JSON manifest,记录 seed、源数、定向组成、error_seed;用于训练选择和调参 | | 新冻结最终测试清单 | 与训练、BC、调参及选择清单不重叠;模型冻结后运行,失败后修改则新开一轮测试 | | 压力场景 | 圆周边界、1000m 半径、向外/切向定向、高频道、固定误差与预算边界;单独汇总 | 同场景每个变体用相同位置、频道、半径、朝向和地点误差函数。每个模型至少跑 30 个完整场景,再按预算扩大;“30”是工程起点,不是统计充分性证明。 最终用于稳定收益结论的主方法至少 5 个独立训练种子;场景种子与训练种子分开报告,不能用 5 个场景替代 5 次训练。 Q3、Q4 分开统计,并按源数/定向占比分层;所有基线与候选使用相同停止、预算和计时口径。 | 指标 | 固定定义 | | --- | --- | | 有效全清 | 成功清除频道集合等于评测真值;缺席集合与真值不交;completed、正常 exit、无异常、计时一致 | | `virtual_time_s` | 实际退出前的完整虚拟时间;主竞赛口径显式 `persistent_search=False` | | `avg_locate_clear_time_s` | 每场 `T / 实际清除数`;有效全清主表再做逐场平均,另报源数分组 | | `accounted_virtual_time_s` | 首次完成证明的时间;与最终时间并列,不悄悄用它替换正式计分 | | 运行时间 | 每场实际墙钟、模型推理耗时分位数;本地内存回环时间不冒充官方程序运行时间 | | 成本分解 | 移动秒、测量秒、换频秒、成功/失败 clear 秒、后备尝试、重复测量、总请求数 | | 尾部与失败 | 中位数/P90/P95/最大值、有效全清率、失败明细;小样本尾分位注明估计局限 | 平均 `T/N` 不等于 `平均 T / 平均 N`;若另用总体总时间/总源数,明确标为按源数加权口径。 配对效应以同场景时间差为基础,报告均值相对变化、胜出场数、95% 配对 bootstrap 区间;相同场景家族共享种子时按家族重采样。 多训练种子结果报告种子间分散程度;必要时对训练种子和场景做分层重采样,不能用单一场景区间代表训练稳定性。 最小比较矩阵:`bayes/directional`、旧局部 PPO、修订局部 MaskablePPO、`hrl_heuristic`、高层 PPO+几何、后续高层 PPO+局部 PPO。 此矩阵先回答“改调度是否有用”和“增加局部学习是否有用”;既有单步 RL 不能命名为无几何的端到端基线。 若仍要端到端 PPO,必须单独定义输入、实际动作、安全执行边界并训练,标记预算;它不是 P1 完成条件。 每项消融使用相同训练步数/场景预算/种子和评测集,单次只改变一个因素: - 调度:学习高层 vs `hrl_heuristic`,保持候选生成和局部选点一致。 - 局部策略:同一高层与执行接口下,geometry vs 现有局部 PPO;报告是冻结替换还是联合重训。 - 塑形:纯时间目标 vs 经过恒等式核验的势函数塑形;无信息增益奖励就是系数为 0。 - 课程:相同总交互步数的课程训练 vs 从完整场景开始训练;Q4 迁移另列,不预设节约百分比。 - 掩码:只取消重复/低效候选等策略性屏蔽;协议合法性、证书和预算硬守卫始终保留,标明实际取消范围。 - 粒子特征:保留几何守恒内核,先将粒子统计输入和评分消融;若真的移除粒子模块,另实现保守几何替代并重新验证。 - 八方向:只报告离线到达率/路径效率/推演耗时,以及实际协议终点相同时成绩相同的事实。 P2 推广门槛:所有最终与压力场景有效,Q4 相对最强已冻结基线的时间差区间上界小于 0;尾部容忍度先写入 manifest。 建议初始尾部门槛为 P95 不退化超过 5%,这是可调整的工程标准,不是题设要求;任何调整都在重跑最终测试前完成。 Q3 若未显示稳定收益,保留 `bayes` 默认并交付负结果。仅比手写基线快、却未优于现有 PPO,不能宣布替换默认模型。 ## 7. P3:受限调参、论文与官方验证 只有 P2 主方法具备竞争力才实现并运行 `tune_hrl.py`。先搜索学习率、熵系数、网络宽度、GAE、合法候选排序参数。 不搜索真实误差上限、光学清除半径、无信号停止次数或破坏覆盖证明的网格间距;确定性网格没有粒子重采样阈值可调。 Optuna 只用开发/选择清单,失败配置先按有效性淘汰;预算与失败/剪枝逻辑写入结果。最终模型重新用固定配置多种子训练。 文档、流程图与论文表明确:学习负责哪些决策、证明由哪些模块提供、本地生成分布未知是否对应官方分布。 训练曲线、实际步数、配置、全部对照与失败明细均归档;不要只挑最好种子或去掉不利的边界场景。 官方三次测试需要对应演练已经启动、真实案例码与官方导出日志;本地 referee 的三场不能填写成“三次正式测试”。 不覆盖旧官方归档;官方结果与本地结果分表,不对不同官方案例直接计算改进百分比。 ## 8. 命令:已经存在与待实现的严格区分 以下入口当前已经存在;依赖需先安装,命令失败要修复或如实报告,不能跳过错误声称通过: ```bash uv sync --group dev --group rl uv run python -m pytest -q --tb=short uv run python -m pytest -q tests/test_hrl.py --tb=short uv run mcm26b run --help uv run mcm26b run --robot-id 2026001 --self-test --strategy bayes uv run mcm26b run --robot-id 2026001 --self-test --problem 4 --q4-strategy directional uv run python scripts/train_rl.py --help uv run python scripts/train_hrl_low.py --help ``` `train_hrl_low.py` 目前仅 `--help` 可用于检查入口,不把完整训练列为已可用: 其 `MaskablePPO.learn()` 需要环境掩码,当前 `LowLevelEnv` 没有 `action_masks()`;改普通 PPO 或提供全 True 掩码后再试。 还需修 BC 按 episode 划分、统一随机种子、每 worker 独立 Monitor 文件、评估 seed 生效、实际路径长度与成功率分开统计。 低层到达失败不能靠 executor 最后强制补终点伪装成策略到达;环境裁剪后的实际移动长度也不能简单记为 `steps*100m`。 下面是 P1/P2 实现后必须支持并实测的命令契约,当前尚不能直接运行: ```bash # P1:先验证不加载模型的共享调度闭环 uv run python scripts/benchmark_hrl.py --variants hrl_heuristic,bayes,directional --manifest output/hrl/manifests/dev.json --output output/hrl/p1-heuristic # P1:完整保真冒烟;模型目录必须是新目录 uv run python scripts/train_hrl_high.py --problem 3 --stage 1 --timesteps 2048 --seed 320001 --envs 1 --vec-env dummy --device cpu --config-profile production --model output/hrl/p1-smoke/q3.zip --verbose 0 # P1:CLI 明确加载高层模型 uv run mcm26b run --robot-id 2026001 --self-test --strategy hrl --hrl-model output/hrl/p1-smoke/q3.zip # P2:正式阶段训练;步数先依据采样吞吐与学习曲线再调整 uv run python scripts/train_hrl_high.py --problem 4 --stage 4 --timesteps 60000 --seed 420001 --envs 2 --vec-env dummy --device cpu --config-profile production --model output/hrl/p2/q4-seed420001.zip --eval-manifest output/hrl/manifests/select.json --verbose 0 # P2:冻结模型完整对照;variants 的模型位置来自同目录的配置清单 uv run python scripts/benchmark_hrl.py --variants hrl,hrl_heuristic,legacy,revised,baseline --manifest output/hrl/manifests/final.json --output output/hrl/p2-final ``` 命令使用的 manifests 也要由脚本生成、校验并归档;尚不存在的模型不能当作初始化输入。 添加 `--full` 一键课程入口时,它应展开并记录每阶段命令/配置/检查点链,失败即停,可继续,不是忽略错误的 shell 包装。 参考现有依赖配置:基础运行依赖仅 requests;RL 为可选组。固定环境版本并记录硬件,勿假定当前执行机就是旧报告中的 RTX 4060。 ## 9. 可以直接粘贴给 Sol 的续作 Prompt ```text 继续当前仓库的 HRL 工作。先读 docs/hrl-sol-execution.md、最新测试结果与 git diff,保留现有修改。 已有客户端/referee/几何/PPO 都要复用;不要重写骨架,不把缺失脚本或 CLI 说成已完成。 先完成 P0 尚未关闭的奖励、终止、完整保真配置、掩码和依赖问题;本轮已修的槽位/清除事件/候选过期只回归。 采用高层 MaskablePPO 调度 + 几何/已有局部 PPO 选点 + 协议直线执行;八方向只作为可选离线实验。 按 P1 先实现 benchmark_hrl 与真值隔离审计,再实现 train_hrl_high、模型元数据和 CLI,跑可重载的短训冒烟。 P0/P1 没通过就修实现,不用加训练步数掩盖问题。通过后再开展 BC、完整保真课程、多训练种子、冻结场景配对评测。 保持 Q3 bayes/Q4 现有默认策略;完整实验胜出前不覆盖默认模型。主指标包含有效全清、T、逐场 T/N、请求分解和尾部。 每阶段交付具体文件、实际执行命令、测试结果、模型/日志路径与未完成项;不预设 Q4 80% 节约或 4000 秒保证。 官方测试只有真实演练开始并获得案例码/导出日志才记正式结果,本地实验单独标注。 ``` 接口参考:[MaskablePPO 官方文档](https://sb3-contrib.readthedocs.io/en/master/modules/ppo_mask.html),[Gymnasium 终止与时间限制](https://gymnasium.farama.org/tutorials/gymnasium_basics/handling_time_limits/)。