docs: 增加远程临时实验 smoke 模板
This commit is contained in:
@@ -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 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`:
|
||||
|
||||
@@ -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)。
|
||||
Reference in New Issue
Block a user