docs: 增加远程临时实验 smoke 模板

This commit is contained in:
Codex
2026-07-15 09:30:36 +02:00
parent 880abd78b8
commit 2de653070a
5 changed files with 263 additions and 1 deletions
+9 -1
View File
@@ -27,7 +27,12 @@ trans D601:win/c/test git exact-commit gc-auto --confirm
trans gh:/owner/repo/issue/<number> 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 <node> --lane <lane> --confirm``source-workspace status`;不要把裸 `trans <node>:<workspace> 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/<drive>` WSL host workspace 由 root 透传执行时,CLI 自动把 workspace owner uid 桥接到进程级 `SUDO_UID`,让 Git 信任 Windows 挂载目录而不写全局 `safe.directory`;非 Git 命令和普通 Linux workspace 不改变所有权信任。
- Windows route 的 `win` 是 route planeoperation 直接写 `ps``cmd``git` 或只读 fs 操作 `pwd|ls|cat|head|tail|stat|wc|rg`;不要写成 `trans D601:win/... win ps`,也不要把 POSIX shell 当 Windows shell。
- Windows `rg`
@@ -31,3 +31,8 @@
- 验证独立 worktree 时显式设置 `UNIDESK_TRANS_REPO_ROOT=<worktree>`
- 普通 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 无残留。
@@ -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 <Target>:/tmp sh <<'SH'
set -eu
work_dir=<absolute-work-dir>
resource_prefix=<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 <Target>:<absolute-work-dir> apply-patch <<'PATCH'
*** Begin Patch
*** Add File: jobs/<job-id>.sh
+#!/bin/sh
+set +e
+
+<one-long-command>
+code=$?
+printf '%s\n' "$code" > /absolute/work-dir/jobs/<job-id>.exit
+touch /absolute/work-dir/jobs/<job-id>.done
+exit "$code"
*** End Patch
PATCH
```
job 脚本只能引用任务已确认的绝对目录、资源前缀和公开依赖身份。需要 Secret 的任务不使用本模板自行读取运行面值。
### 3. Submit
submit 只负责清理旧状态、后台启动和返回 PID,不等待长命令:
```bash
trans <Target>:<absolute-work-dir> sh <<'SH'
set -eu
job_id=<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 <Target>:<absolute-work-dir> sh <<'SH'
set -eu
job_id=<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 <Target>:<absolute-work-dir> sh <<'SH'
set -eu
work_dir=/absolute/work-dir
resource_prefix=<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 中无界扩展。
@@ -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。
@@ -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)。