onescience-runtime · git:20260814.1419d1c · 2026-08-14 · sha256 cf83e09533b2df64

onescience-runtime git:20260814.1419d1cA

Immutable. This exact content is served forever at /api/v1/blob/cf83e09533b2df64.

---
name: onescience-runtime
description: 【统一运行与基础诊断技能】按 discover、preflight、execute、diagnose 固定闭环执行测试任务,依据 onescience.json 的 execution_profile 三元组路由执行通道。preflight 阶段完整委托 onescience-installer 执行环境就绪预检(installer_reason=preflight_validation),runtime 只消费 readiness 结果;SCnet 提交任务时必须读取根级 onescience.json.runtime.scnet 并把 region、partition/queue、work_dir 和资源参数交给 scnet-chat;配置问题自动委托 onescience-runsite 补齐;环境问题由 onescience-installer 安装或修复并 verify 成功后回到 runtime 继续原测试任务;当 execution_mode 为 slurm 且提交或运行反馈表明 partition、gpus_per_node、memory 等资源不可用时,探测可用 SLURM 资源并受控调整后重试。
type: executor
---

## 输入获取方式

本技能支持两种输入方式:

1. **上下文 handoff**(默认):从调用方传入的 `step_handoff` 获取任务信息。
2. **文件 handoff**(autonomous_mode):从 `.onescience/handoff/step_{step_id}.yaml`
   读取任务信息。执行后,将结果写入 `.onescience/handoff/step_{step_id}_result.yaml`。

启动时优先检查 `.onescience/handoff/` 目录是否存在对应的交接文件;若存在则使用文件模式,否则使用上下文模式。

文件交接格式参见 `skills/onescience-orchestrator/references/file_handoff_contract.md`。

# OneScience Runtime

## 执行流程

每次任务固定按 `discover -> preflight -> execute -> diagnose` 顺序处理。`execute` 是硬门禁阶段:只有 `preflight` 明确产出 `preflight_passed=true`、`execution_readiness=ready` 且 `evidence.preflight.status=passed` 后,才能读取和执行任何 execute 分支。缺少这些证据时,必须回到 `preflight`,不得直接提交本地、SSH、SLURM 或 SCnet 任务。

### 1. discover

先读取项目根目录 `onescience.json`,并立即调用 `skills/onescience-runsite/SKILL.md` 对当前运行站点配置做校验、复用或补齐;不要直接信任已有 `onescience.json`。只有 `onescience-runsite` 完成已有配置检查、远程连接验证或缺失字段补齐并写回后,runtime 才重新读取 `onescience.json`,再优先消费:

- `runtime.execution_profile.run_site`
- `runtime.execution_profile.execution_mode`
- `runtime.execution_profile.access_mode`

`execution_channel` 由这三个字段派生;当前约定是 `run_site=local` 时 `access_mode` 允许为空,`execution_mode` 为空/`none` 视为非调度直接执行。若配置中已有 `execution_channel`,只作为对照证据,不作为唯一 routing 来源。

需要进入 discover 细节时,读取:

- `./references/discover.md`

### 2. preflight

discover 得到通道后,runtime 不再自行执行环境检测。preflight 阶段改为**完整委托** `onescience-installer` 执行环境就绪预检:

1. 组装 preflight 上下文:`execution_channel`、`runtime.conda`、入口脚本路径、业务依赖列表等
2. 以 `installer_reason=preflight_validation` 委托 `skills/onescience-installer/SKILL.md` 执行完整的环境就绪检查
3. installer 返回 `preflight_result`:
   - `status=passed`:设置 `preflight_passed=true`、`execution_readiness=ready`,进入 execute
   - `status=partial`:记录警告和建议,若可继续执行则进入 execute
   - `status=failed`:installer 已进入修复流程;修复成功后重新读取 `onescience.json`,从 preflight 重新开始
   - `status=blocked`:记录阻断原因,停止并向 orchestrator 报告

**职责说明**:环境就绪检测(conda 校验、Python 解释器、onescience/torch 导入、CUDA 扩展、入口脚本语法、环境依赖一致性、GPU 可访问性、GPU 显存预算、共享库检查等)全部由 installer 的 `preflight-validation.md` 统一执行。runtime 只消费 installer 返回的 readiness 结果,不自行做环境探测。

### 3. execute

preflight 确认可执行后,根据 `execution_channel` 只读取一个执行分支;只有 `runtime.conda.enabled=true` 时才会在对应模板中渲染 `activate_script`。

进入 execute 前必须重新核对(证据来自 installer 的 `preflight_result`):

- `preflight_passed=true`(installer 返回 `status=passed` 或可继续执行的 `partial`)
- `execution_readiness=ready`
- `blocking_reason` 为空或 `none`
- `evidence.preflight.status=passed`(来自 installer 的 preflight_result.status)

任一缺失或为 false 时,禁止读取 execute 分支,必须回到 `preflight` 重新委托 installer 做环境就绪检查。若阻断原因是 installer 返回 `failed` 且 installer 已在修复流程中,等待 installer 修复完成后重新读取 `onescience.json` 并从 `preflight` 恢复。

execute 分支映射:

- `local_direct` -> `./references/execute-local-direct.md`
- `local_slurm` -> `./references/execute-local-slurm.md`
- `ssh_direct` -> `./references/execute-ssh-direct.md`
- `ssh_slurm` -> `./references/execute-ssh-slurm.md`
- `scnet_mcp` -> `./references/execute-scnet-skill.md`

### 进度监控与超时策略

对于预估执行时间 > 10 分钟的任务,应采用分段式执行策略,避免单次长超时后进度完全丢失:

1. **分段超时**:将单次长超时(如 3600000ms)拆分为多段较短的超时(如每段 600000ms),每段结束后检查中间产物:
   - 检查日志文件是否有新的输出行(对比行数变化)
   - 检查预期输出目录是否出现新的中间文件
   - 若连续 2 段无任何进度变化,判定为卡死,触发 diagnose

2. **中间产物检查点**:
   - 批量任务应在每个批次完成后写入中间状态文件(如 `checkpoint_batch_<N>.json`),记录已完成的数据项索引
   - 超时恢复时,通过中间状态文件判断已完成进度,仅处理剩余任务,避免全部重来
   - 参考案例:大批量序列推理被超时中断,若有进度文件则可在超时后从断点续跑

3. **默认并行化引导**:
   - 当任务涉及 N > 100 个独立数据项且按任务目标可并行处理时,runtime 应在 execute 前检查可用 GPU 数量并输出并行化建议
   - 建议格式:`本任务涉及 {N} 个独立数据项,当前可用 {G} 个 GPU,建议拆分为 {S} 个分片并行执行`

### 日志落盘策略

进入 execute 阶段后,先解析当前测试目录 `work_dir`:优先取 `runtime.script.work_dir`,缺失时回退到 `runtime.script.code_path` 所在目录。所有执行通道的本地日志目录统一为 `<work_dir>/logs/`,`local_log_dir` 必须输出该路径;不要再把远程任务日志下载到项目根目录 `.onescience/logs/<job_name>/`。

- `local_direct` / `local_slurm`:在测试目录内创建 `logs/`,stdout/stderr、`*.out`、`*.err` 均写入或复制到该目录。
- `ssh_direct` / `ssh_slurm`:远端上传目录为 `<runtime.ssh.work_dir>/<测试目录名>/`,远端日志目录为该目录下的 `logs/`;任务结束后用 `rsync/scp` 同步到本地 `<work_dir>/logs/`。
- `scnet_mcp`:交接给 `scnet-chat` 时显式要求平台日志下载到当前测试目录的 `logs/`,并在 runtime 输出中记录 `local_log_dir=<work_dir>/logs/`。
- `job_name` 只用于作业名、日志文件名前缀或远端任务识别;不再作为本地日志目录的额外子目录。

> `<work_dir>/logs/` 下的日志与 runtime 声明的输出文件,只有在 preflight 通过并进入真实 `execute` 阶段后,才可作为权威训练 / 推理 / 评测运行证据。runtime 不得为了满足 expected outputs 而创建占位或合成的 `trainer.log`、`train.log`、`metrics.json`、`predictions.json`、`targets.json` 等证据文件;若在 `execute` 前被阻断,应输出结构化状态、阻断原因和缺失产物信息,而不是补造运行结果。

若 `execution_mode=slurm` 且 `sbatch`、`squeue`、`sacct` 或作业日志反馈 partition / GRES / GPU 数 / memory / CPU / node 资源不可用,继续读取:

- `./references/slurm-resource-retry.md`

渲染脚本模板时只使用最小模板资产,并按执行通道与目标硬件做确定映射:

- `local_direct` -> `./assets/templates/local_direct.sh`
- `ssh_direct` -> `./assets/templates/local_direct.sh`
- `local_slurm` 且目标硬件为 CPU -> `./assets/templates/slurm_cpu.sh`
- `ssh_slurm` 且目标硬件为 CPU -> `./assets/templates/slurm_cpu.sh`
- `local_slurm` 且目标硬件为 DCU -> `./assets/templates/slurm_dcu.sh`
- `ssh_slurm` 且目标硬件为 DCU -> `./assets/templates/slurm_dcu.sh`
- `local_slurm` 且目标硬件为 GPU -> `./assets/templates/slurm_gpu.sh`
- `ssh_slurm` 且目标硬件为 GPU -> `./assets/templates/slurm_gpu.sh`
- 仅当预检已确认多机多卡 torchrun 入口与所需字段齐备时,SLURM 分支才允许改用 `./assets/templates/slurm_gpu_multinode_torchrun.sh`
- `./assets/tpl.slurm` 只作为兼容兜底参考,不作为 `local_slurm` / `ssh_slurm` 的默认模板选择结果

### 4. diagnose

执行结束后,基于状态、日志与错误证据进入基础诊断。

需要进入诊断细节时,读取:

- `./references/diagnose.md`

不要把所有执行分支一次性读入上下文;只继续当前命中的通道文件。

## Resume Invariant

`onescience-runsite` 和 `onescience-installer` 是 runtime 的中途修复步骤,不是最终任务终点。

- runtime 允许自动委托的下游技能仅限 `onescience-runsite`、`onescience-installer`,以及文档中已明确的平台动作执行方 `scnet-chat`;这些委托只用于恢复当前 runtime 步骤,不决定新的业务 executor。
- 调用 `onescience-runsite` 解决配置问题后,重新读取 `onescience.json`,从 `discover` 恢复,并继续原测试任务直到进入 `execute/diagnose` 或遇到新的真实阻断。
- 调用 `onescience-installer` 解决环境问题且 verify 成功后,重新读取 `onescience.json` 与 `runtime.conda`,从 `preflight` 恢复,并继续原测试任务直到进入 `execute/diagnose` 或遇到新的真实阻断。
- `next_action=onescience-runsite` 或 `next_action=onescience-installer` 只是一次性内部交接;只有对方阻断、需要用户补充信息、verify 失败,或恢复后出现新的阻断时,才停止并向用户报告。
- 恢复时沿用原始用户意图、测试入口、运行通道候选和已确认的远程边界;不要因修复完成而替换成新的本地最小验证。
- 若 diagnose 或执行证据表明后续问题已超出 runtime 的运行治理边界(例如需要新的业务代码实现、训练/推理策略重定义、后续评估阶段选择等),runtime 只返回 `execution_result` 中的 observation / recommendation,由 `onescience-orchestrator` 决定下一技能;runtime 不自行切换到 `onescience-coder`、`onescience-trainer`、`onescience-infer` 等业务 executor。

## Hard Gates

- runtime 自身不要直接改写用户的 `onescience.json`;discover 每次进入时都必须立即加载并执行 `skills/onescience-runsite/SKILL.md` 做运行站点校验。已有配置时先让 runsite 走检查/复用/远程连接验证分支,缺失或冲突时再由 runsite 按其边界写回或补问。
- `onescience-runsite` 完成校验、确认可复用或补齐配置后,runtime 必须重新读取 `onescience.json` 并从 `discover` 继续;不要直接使用 runsite 调用前缓存的三元组或历史 `execution_channel`。
- `onescience.json` 缺失、三元组无法归一或关键字段冲突时,设置 `next_action=onescience-runsite` 作为内部交接标记,并直接调用 `onescience-runsite` 补齐配置;无需向用户二次确认,也不要自行猜测后继续执行。`onescience-runsite` 完成后,重新读取 `onescience.json` 并从 `discover` 恢复,继续原测试任务。
- 远程执行意图优先于任何本地最小验证建议。只要用户明确要求远程执行、提交到 SLURM 或提交到 SCnet,就不要在本地执行业务脚本替代远程验证。
- 未完成 preflight 或 preflight 未通过时,禁止进入 execute。不得因为已有 `execution_channel`、已有脚本路径、用户说"跑一下"或存在历史 `onescience.json` 就跳过环境就绪检查。preflight 已完整委托 `onescience-installer` 执行,runtime 只消费 installer 返回的 `preflight_result.status`。
- 若 installer 返回 `preflight_result.status=failed` 且 installer 已在修复流程中,等待 installer 修复完成后重新读取 `onescience.json` 并从 `preflight` 恢复;不自行判断环境是否可用。
- 命中 SCnet 作业、文件、账户、区域、队列、集群、日志下载等平台动作时,继续委托 `scnet-chat` 技能执行;runtime 只负责交接输入、消费结果与基础诊断。
- 通过 `scnet-chat` 提交任务前,必须先读取 `onescience.json.runtime.scnet` 中的 `region`、`partition`/`queue`、`remote_work_dir`/`work_dir`、资源参数和作业名等信息;`partition` 归一为 scnet-chat 的 `--queue` 参数。不要依赖 scnet-chat 的缓存默认区域或默认队列,也不要用用户自然语言里的 region/partition 直接覆盖该配置。
- 不要在代码入口、探针脚本或远端提交目标缺失时继续提交空作业。

### autonomous_mode 下的预检自动修复

当上游 `step_handoff.execution_flags.autonomous_mode` 为 `true` 时:

1. 若 preflight 返回 `preflight_passed=false`,自动委托 `onescience-installer`(传入 `installer_reason=preflight_validation` 和 `execution_flags.autonomous_mode: true`)进行环境修复。
2. 修复完成后重新读取 `onescience.json`,从 `preflight` 恢复。
3. 最多自动重试 2 次;2 次后仍失败则返回 `status: blocked` 并输出具体原因。
4. 若执行的业务代码运行失败(execute 阶段返回非零),自动进入 diagnose 流程获取诊断信息,并尝试基础修复;修复后自动重跑,最多 2 次重试。

## Output Contract

阶段汇报和最终输出至少包含:

- `execution_channel`
- `execution_mode`
- `access_mode`
- `preflight_passed`
- `submission_state`
- `execution_state`
- `log_state`
- `blocking_reason`
- `next_action`

若进入执行阶段,建议继续输出:

- `config_source`
- `region`
- `partition` 或 `queue`
- `submission_target`
- `job_id` 或 `task_id`
- `local_log_dir`
- `synced_logs`
- `sync_status`
- `status_source`
- `log_readiness`

若 `execution_mode=slurm` 且进入资源反馈调整流程,继续输出:

- `slurm_resource_adjusted`
- `adjusted_cluster_overrides`
- `retry_count`
- `retry_reason`
- `candidate_partitions`