From 2de653070af1702af8b5331e48f0a827f20b736e Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 15 Jul 2026 09:30:36 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=A2=9E=E5=8A=A0=E8=BF=9C=E7=A8=8B?= =?UTF-8?q?=E4=B8=B4=E6=97=B6=E5=AE=9E=E9=AA=8C=20smoke=20=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agents/skills/unidesk-trans/SKILL.md | 10 +- .../unidesk-trans/references/operations.md | 5 + .../references/remote-experiment-smoke.md | 194 ++++++++++++++++++ .../R1_Task_Report.md | 46 +++++ docs/MDTODO/trans-remote-experiment-smoke.md | 9 + 5 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 .agents/skills/unidesk-trans/references/remote-experiment-smoke.md create mode 100644 docs/MDTODO/details/trans-remote-experiment-smoke/R1_Task_Report.md create mode 100644 docs/MDTODO/trans-remote-experiment-smoke.md diff --git a/.agents/skills/unidesk-trans/SKILL.md b/.agents/skills/unidesk-trans/SKILL.md index eb8c4350..9d3eef1b 100644 --- a/.agents/skills/unidesk-trans/SKILL.md +++ b/.agents/skills/unidesk-trans/SKILL.md @@ -27,7 +27,12 @@ trans D601:win/c/test git exact-commit gc-auto --confirm trans gh:/owner/repo/issue/ cat ``` -Host workspace、k3s、Windows、GitHub issue/PR route 见 [references/routes.md](references/routes.md);sh/bash/argv/py/upload/download/kubectl/logs/skills/tcp-pool 操作见 [references/operations.md](references/operations.md);apply-patch envelope 和 quoting 陷阱见 [references/apply-patch.md](references/apply-patch.md)。 +专项参考: + +- Host workspace、k3s、Windows、GitHub issue/PR route 见 [references/routes.md](references/routes.md)。 +- sh/bash/argv/py/upload/download/kubectl/logs/skills/tcp-pool 操作见 [references/operations.md](references/operations.md)。 +- 跨 60 秒短连接的临时 build、GPU、模型或硬件 smoke 见 [references/remote-experiment-smoke.md](references/remote-experiment-smoke.md)。 +- apply-patch envelope 和 quoting 陷阱见 [references/apply-patch.md](references/apply-patch.md)。 ## P0 边界 @@ -53,6 +58,9 @@ Host workspace、k3s、Windows、GitHub issue/PR route 见 [references/routes.md - 当前 HWLAB node/lane source workspace 的正式预检/同步入口是 `bun scripts/cli.ts hwlab nodes control-plane source-workspace sync --node --lane --confirm` 和 `source-workspace status`;不要把裸 `trans : git fetch ...` 当成当前 HWLAB node/lane workspace 预检/修复入口。 - `sh`/`bash` 必须显式声明 shell;单进程命令优先 direct argv 或已知 operation。 - 普通 trans/ssh 短连接硬预算 60s;长 CI/CD、trace、logs、build、硬件流程必须 submit-and-poll。 +- 一次性远程实验不得临时发明第二套状态协议: + - 使用 [远程临时实验 smoke](references/remote-experiment-smoke.md) 的参数合同; + - 复用同一模板的后台 job、证据和清理合同。 - `/mnt/` WSL host workspace 由 root 透传执行时,CLI 自动把 workspace owner uid 桥接到进程级 `SUDO_UID`,让 Git 信任 Windows 挂载目录而不写全局 `safe.directory`;非 Git 命令和普通 Linux workspace 不改变所有权信任。 - Windows route 的 `win` 是 route plane,operation 直接写 `ps`、`cmd`、`git` 或只读 fs 操作 `pwd|ls|cat|head|tail|stat|wc|rg`;不要写成 `trans D601:win/... win ps`,也不要把 POSIX shell 当 Windows shell。 - Windows `rg`: diff --git a/.agents/skills/unidesk-trans/references/operations.md b/.agents/skills/unidesk-trans/references/operations.md index 6d66823b..73981206 100644 --- a/.agents/skills/unidesk-trans/references/operations.md +++ b/.agents/skills/unidesk-trans/references/operations.md @@ -31,3 +31,8 @@ - 验证独立 worktree 时显式设置 `UNIDESK_TRANS_REPO_ROOT=`。 - 普通 trans/SSH 必须满足短连接预算;长 build、CI/CD、trace、probe 或 rollout 使用受控 job/status submit-and-poll。 + +- 临时 build、Docker GPU、模型下载或硬件 smoke: + - 使用 [远程临时实验 smoke](remote-experiment-smoke.md) 的单次参数化模板; + - 长步骤只提交后台 job,后续使用有界 status/log tail 轮询; + - 结束时输出统一 evidence 摘要,并复查资源前缀或 label 无残留。 diff --git a/.agents/skills/unidesk-trans/references/remote-experiment-smoke.md b/.agents/skills/unidesk-trans/references/remote-experiment-smoke.md new file mode 100644 index 00000000..474d71b1 --- /dev/null +++ b/.agents/skills/unidesk-trans/references/remote-experiment-smoke.md @@ -0,0 +1,194 @@ +# 远程临时实验 Smoke + +## 适用范围 + +本模板用于一次性远程 build、Docker GPU、模型下载或硬件 smoke。目标是让执行者在一个实验目录内完成: + +- 一次 preflight; +- 一个或多个串行后台 job; +- 一次原入口 smoke; +- 一份有界 evidence; +- 一次幂等 cleanup。 + +正式 CI/CD、YAML-first apply、常驻服务、Secret 下发和公网暴露继续使用对应专项 CLI 或 skill,不能套用本模板。 + +## 必填参数 + +开始写入目标前必须明确以下参数,不得根据宿主名、历史目录或上一任务猜测: + +| 参数 | 约束 | +| --- | --- | +| `route` | 任务上下文提供的 `Target:absoluteWorkspace` 或对应 k3s route。 | +| `work_dir` | 目标允许范围内的绝对临时目录,默认位于 `/tmp`。 | +| `resource_prefix` | 容器、镜像、网络、PID 和证据文件共享的任务前缀。 | +| `job_id` | 当前长步骤的稳定短标识,例如 `model-download` 或 `image-build`。 | +| `command` | 写入 job 脚本的单一长命令,不在同步 `trans` 中等待完成。 | +| `artifact_allowlist` | 允许保留的模型缓存、WAV、JSON 或摘要文件。 | +| `stop_condition` | OOM、ABI、许可证、上游 ref 或硬件能力等首次确定停止条件。 | + +参数缺失时先返回可操作错误: + +- 不要创建第二条执行路径; +- 不要把 Secret、token 或完整环境变量写入参数、脚本、日志和 evidence。 + +## 单次 Smoke 流程 + +### 1. Preflight + +只做一次有界探测,确认目录、资源前缀、依赖入口和停止条件: + +```bash +trans :/tmp sh <<'SH' +set -eu +work_dir= +resource_prefix= + +test "${work_dir#/tmp/}" != "$work_dir" +case "$resource_prefix" in + ''|*[!a-zA-Z0-9_.-]*) echo 'invalid resource_prefix' >&2; exit 2 ;; +esac + +mkdir -p "$work_dir/jobs" "$work_dir/artifacts" +printf 'host='; hostname +df -h "$work_dir" | tail -1 +docker version --format 'docker={{.Server.Version}}' 2>/dev/null || true +nvidia-smi --query-gpu=name,driver_version,memory.total,memory.free --format=csv,noheader 2>/dev/null || true +docker ps -a --filter "label=unidesk.task=$resource_prefix" --format '{{.Names}} {{.Status}} {{.Image}}' 2>/dev/null || true +SH +``` + +若目标范围不是 `/tmp`,必须由 owning issue 或任务上下文明确授权,再相应替换目录断言。 + +### 2. 写入 Job 脚本 + +远端文本修改只使用 `apply-patch`。每个长步骤的脚本必须写最终 exit code 和 done 标记: + +```bash +trans : apply-patch <<'PATCH' +*** Begin Patch +*** Add File: jobs/.sh ++#!/bin/sh ++set +e ++ ++ ++code=$? ++printf '%s\n' "$code" > /absolute/work-dir/jobs/.exit ++touch /absolute/work-dir/jobs/.done ++exit "$code" +*** End Patch +PATCH +``` + +job 脚本只能引用任务已确认的绝对目录、资源前缀和公开依赖身份。需要 Secret 的任务不使用本模板自行读取运行面值。 + +### 3. Submit + +submit 只负责清理旧状态、后台启动和返回 PID,不等待长命令: + +```bash +trans : sh <<'SH' +set -eu +job_id= +job_dir=/absolute/work-dir/jobs + +rm -f "$job_dir/$job_id.done" "$job_dir/$job_id.exit" "$job_dir/$job_id.stdout" "$job_dir/$job_id.stderr" +chmod +x "$job_dir/$job_id.sh" +nohup sh "$job_dir/$job_id.sh" \ + > "$job_dir/$job_id.stdout" \ + 2> "$job_dir/$job_id.stderr" \ + < /dev/null & +printf '%s\n' "$!" > "$job_dir/$job_id.pid" +printf 'job=%s state=submitted pid=%s\n' "$job_id" "$(cat "$job_dir/$job_id.pid")" +SH +``` + +### 4. Poll + +每次 poll 只输出状态和有界日志尾部。不得重复 submit,也不得恢复完整 stdout dump: + +```bash +trans : sh <<'SH' +set -eu +job_id= +job_dir=/absolute/work-dir/jobs +pid=$(cat "$job_dir/$job_id.pid" 2>/dev/null || true) + +if [ -f "$job_dir/$job_id.done" ]; then + state=finished + exit_code=$(cat "$job_dir/$job_id.exit") +elif [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then + state=running + exit_code=- +else + state=lost + exit_code=- +fi + +printf 'job=%s state=%s exit=%s pid=%s\n' "$job_id" "$state" "$exit_code" "${pid:--}" +printf '%s\n' '--- stdout tail ---' +tail -n 20 "$job_dir/$job_id.stdout" 2>/dev/null || true +printf '%s\n' '--- stderr tail ---' +tail -n 20 "$job_dir/$job_id.stderr" 2>/dev/null || true +SH +``` + +`state=lost` 表示 PID 已消失但没有 done 标记: + +- 先保留状态文件和日志; +- 不要自动重提; +- 根据首个确定错误决定停止或创建新的 `job_id`。 + +### 5. 原入口 Smoke 与 Evidence + +只执行 owning issue 要求的一个 smoke。通用 evidence 至少包含: + +- `sourceRef`、模型或依赖 ref、许可证; +- 容器基础镜像 digest、构建镜像 ID、runtime 和 GPU request; +- 精确 API 或命令参数; +- 首次调用和热调用耗时; +- GPU 基线、峰值显存和 OOM 状态; +- 生成物大小、哈希和原生解码/检查摘要; +- 首个失败点和是否触发 `stop_condition`; +- cleanup 结果和允许保留的 artifact 路径。 + +证据文件只写摘要、presence、fingerprint、ID、digest 和有界日志尾部,不复制 Secret、完整环境、模型正文或无界 stdout。 + +### 6. Cleanup + +cleanup 必须幂等,并按资源前缀或 label 精确删除: + +```bash +trans : sh <<'SH' +set -eu +work_dir=/absolute/work-dir +resource_prefix= + +for container in $(docker ps -aq --filter "label=unidesk.task=$resource_prefix"); do + docker rm -f "$container" +done +for image in $(docker images -q --filter "label=unidesk.task=$resource_prefix"); do + docker image rm "$image" || true +done +for network in $(docker network ls -q --filter "label=unidesk.task=$resource_prefix"); do + docker network rm "$network" || true +done + +find "$work_dir/jobs" -type f \( -name '*.pid' -o -name '*.done' -o -name '*.exit' \) -delete + +printf '%s\n' 'containers:' +docker ps -a --filter "label=unidesk.task=$resource_prefix" --format '{{.Names}} {{.Status}} {{.Image}}' +printf '%s\n' 'images:' +docker images --filter "label=unidesk.task=$resource_prefix" --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.Size}}' +printf '%s\n' 'networks:' +docker network ls --filter "label=unidesk.task=$resource_prefix" --format '{{.Name}}' +SH +``` + +只保留 `artifact_allowlist` 明确列出的缓存和证据。临时容器、镜像、网络、PID 和非复用 scratch 不得伪装成正式运行面。 + +## 停止判定 + +- 首个确定的 OOM、ABI、许可证、上游 ref 或硬件能力错误触发 `stop_condition` 后立即停止同族试配。 +- 依赖下载失败与模型失败必须分层记录,不能把网络、registry 或包 ABI 问题误判为模型不可用。 +- smoke 未进入原入口时,首次调用、热调用、峰值显存和生成物必须明确写 `未执行`,不能填推测值。 +- 后续候选模型或依赖组合使用新的 issue、MDTODO、资源前缀和实验目录,不能在当前 smoke 中无界扩展。 diff --git a/docs/MDTODO/details/trans-remote-experiment-smoke/R1_Task_Report.md b/docs/MDTODO/details/trans-remote-experiment-smoke/R1_Task_Report.md new file mode 100644 index 00000000..78d0877d --- /dev/null +++ b/docs/MDTODO/details/trans-remote-experiment-smoke/R1_Task_Report.md @@ -0,0 +1,46 @@ +# R1 任务报告 + +## 关联 + +- 来源任务:[UniDesk #2133](https://github.com/pikasTech/unidesk/issues/2133),MDTODO `R9.1`。 +- 改进 issue:[UniDesk #2153](https://github.com/pikasTech/unidesk/issues/2153)。 +- 后续语音主线:[UniDesk #2148](https://github.com/pikasTech/unidesk/issues/2148),本改进不构成其门禁。 + +## 问题判断 + +R9.1 的远程 Docker GPU 实验需要多次手写后台 PID、status、log、证据和清理命令。仓库已有 60 秒短连接规则及专用 async 实现,但 `unidesk-trans` 没有面向一次性远程实验的参数化模板。 + +已查重: + +- `#431/#435` 只处理 Playwright 专用 submit; +- `#2148` 已吸收稳定 Torch/TorchAudio ABI 预检经验,但不是工具或 skill 改进; +- 未发现覆盖通用临时 build、Docker GPU、模型下载和硬件 smoke 的重复 issue 或 MDTODO。 + +## 交付 + +- 新增 `.agents/skills/unidesk-trans/references/remote-experiment-smoke.md`: + - 定义 `route`、`work_dir`、`resource_prefix`、`job_id`、`command`、artifact allowlist 和停止条件; + - 提供一次 preflight; + - 提供 job 脚本、submit 和 bounded poll; + - 统一原入口 evidence 字段; + - 提供按 label 或资源前缀执行的幂等 cleanup; + - 明确网络、registry、ABI、OOM 和模型失败必须分层记录。 +- 更新 `unidesk-trans` skill 与 operation reference 索引。 +- 新增独立 MDTODO,避免把改进夹入 SelfMedia 业务任务。 + +## 验证 + +- 五个 Bash 代码块替换占位符后均通过 `sh -n`。 +- Markdown fence、reference 文件和 `git diff --check` 通过。 +- NC01 原入口完成一个真实最小 smoke: + - submit 返回 PID; + - poll 返回 `state=finished exit=0`; + - artifact 内容为 `template-smoke-ok`; + - stdout/stderr 均为 `0` bytes; + - cleanup 复查为 `clean`。 + +## 边界 + +- 未新增 CLI 子命令、后台服务、安全机制或正式运行面。 +- 未硬编码 Qwen、CosyVoice、D518、镜像、模型或端口。 +- 未修改 `#2148`,未触发 Docker、GPU、CI/CD 或 rollout。 diff --git a/docs/MDTODO/trans-remote-experiment-smoke.md b/docs/MDTODO/trans-remote-experiment-smoke.md new file mode 100644 index 00000000..d40f1121 --- /dev/null +++ b/docs/MDTODO/trans-remote-experiment-smoke.md @@ -0,0 +1,9 @@ +## R1 [completed] + +依据 [UniDesk #2153](https://github.com/pikasTech/unidesk/issues/2153) 为 `unidesk-trans` 增加参数化远程临时实验 smoke 模板: + +- 统一一次 preflight、后台 job submit/poll、原入口 evidence、停止条件和幂等 cleanup; +- 不得硬编码节点、模型、镜像或端口; +- 不新增 CLI 子命令; +- 不阻塞 SelfMedia R9.1.1; +- 完成任务后将详细报告写入[任务报告](./details/trans-remote-experiment-smoke/R1_Task_Report.md)。