发版从来不应该由人工记忆驱动。5 月那一轮 OTA 系列故障(FA-005 到 FA-008)和跨版本步进导致的漏 DLL 事故反复说明了这一点:发版是不可逆的、影响全部用户的、细节繁琐的操作,任何一个环节遗漏或顺序错误就导致客户端卡死、文件不一致、激活页死循环。我现在不是让 AI 执行发版——那是禁地——而是把 5 个已经踏过所有坑的发版流程全部固化成 skill,让执行者用最小脑力成本跑完完整链路,而不是依赖文档翻译和记忆。
触发词:不该触发时绝对不触发
一个 skill 最危险的时刻是被错误调用。"现在是什么版本"听起来像发版,"改一下版本号"听起来像发版,但它们完全不是。
Wakou 发版 skill 的触发词清单(必读触发词段)就是为了卡死这条线:
- 触发:
发版 / 发布 / release / 打个新版本 / OTA / OTA 死循环 / 版本 bump / /wakou-release - 不触发:
改一下 package.json 版本号(用户只想改文件),看看现在是什么版本(只查询)
反面教材我都经历过。改一下配置文件、改一个环境变量、查一个版本号,因为没有明确的触发词界限,最后莫名其妙走到了发版脚本的某一步。Connector OTA skill 同样列明了不触发场景:"Connector 现在是什么版本"(只查询) "改 tauri.conf 版本号"(用户只想改文件) — 这些都不触发,即使命令里含了 version、release 这类关键字。
这条最反直觉但最重要:不该触发时被触发,等于主动送一次误操作机会给自动化流程。
步骤不可跳过:验证链条硬卡
一旦 skill 确定要执行,每一步都必须有验证关卡,前一步没通过绝不进下一步。我用 Wakou 全自动发版流程作例子。
预检(Step 1)是整个流程的闸门。跑这些 Bash 检查:
cd /Users/xingye/Ai/new-openclaw
git status --short # 工作区干净
test -x /opt/homebrew/bin/sshpass # ssh 工具
test -x /opt/homebrew/bin/minisign # 签名工具
test -x <签名 CLI 路径> # 内部签名工具就位
test -f <发版签名私钥路径> # 私钥就位
test -f <CDN 上传凭据路径> # CDN 凭据就位
任何一条 fail,流程停止并告诉用户修什么。如果 git 工作区脏,不是自动 stash,而是问用户:工作区有未提交改动,要先 commit 还是 stash?发版会自动 bump 三个版本文件并 commit。这样做的目的很明确——让用户清晰意识到发版会改动工作区,而不是闭着眼睛走入自动流程。
收三个密码(Step 2)也有安全约定。不要把密码记到内存或 commit 进文件,只读 shell 的 export。如果用户在过去几分钟内说过这些密码(在 conversation context 里能直接拿到),可以直接传 env 跑;否则必须用户主动导入。
跑 release.sh(Step 3)用 run_in_background=true 避免 5-15 分钟阻塞主线,把输出 tee 到日志。然后(Step 4)用 Monitor 工具监控 10 个 stage 的进度:
- preflight
- detect FROM_VERSION
- tar + scp source to Win build host
- build on Win
- stage + diff-pack OTA full.zip
- minisign full.zip + release-manifest.json
- upload to CDN
- admin: create release + PATCH rollout
- git tag + commit version bump
每个 stage 完成给用户报一句。出现 ✗ FAILED 立刻 surface 错误。没有"继续试试能不能救",就是暴露失败。
这整套链条的目的是让人工审核点布满全流程。不是机器自动发版,而是 AI 陪着用户一步步走完发版,每步都看得清、验得出。
故障处置内联:把坑写在流程里
OTA 系列故障的教训不应该沉在 bug 复盘里。我把它们直接铺进 skill 的执行逻辑。
Wakou 发版 skill 有整整一章叫「🚨 阻塞性 bug 处置 SOP」。列出了从 G19 到 G31 的 11 个已知 bug:
G19 是 OTA modal 反复弹。原因是 state base 残留 stale download.zip.minisig,当时的修复是:
# 预检 sanity#3: data/ 不删
sanity#3 强制阻断 deletes 命中 data/。某次发版失败提示 sanity#3 一定是 build 步骤搞坏了 data/ 目录的同步,不要绕过 sanity check 去强发,先 debug 为什么 data/ 出现在 deletes 列表。
G25 是跨用户机器后 chat 权限错。根因是 sessions/audit 含绝对路径,guardian sync 扩散。这不是"修了以后的故事",而是发版前防御 checklist 的一部分:
# 发版前防御 checklist (每次发版前在 build host 做完整新用户回归)
# 3. dist 内 grep C:\Users\ 应该 0 命中(防 G25 类绝对路径泄露)
ssh CHANCHING@<构建机> 'powershell -Command "
Get-ChildItem D:\wakou-build\dist-X.Y.Z\WakouPanelPortable -Recurse -File -Include *.json,*.jsonl |
Where-Object { $_.Length -lt 200KB } |
Select-String C:\\Users\\Administrator -SimpleMatch -List |
Select-Object FullName
"'
任何一项 fail → 不要 GA,修了再 bump 一个 patch 版本。
Connector OTA skill 的故障字典(§4)则是一张病症与病因的对照表。"signature verification failed" 对应的处置是检查 TAURI_SIGNING_PRIVATE_KEY 是不是 .sec 文件base64 编码后的内容。"OTA 不跨级但用户期望直跳" 的处置是调整 findNextVersion 逻辑或在灰度模式放上一个 manifest。
关键在处置是写死在 skill 里,不是留在事后复盘让人去翻。OpenClaw Runtime 发版 skill 的故障字典甚至铺了 10 条常见陷阱:BuildKit context 缓存不清导致改动没编进去、gwbridge IP 池满导致 service 无法起、孤儿 docker-proxy 占着 host port、磁盘满导致 openclaw.json 被写成 0 字节。
每一条都带着:"现象是什么、根因是什么、怎么修"。拿 BuildKit 缓存那条:
症状:rsync/SFTP 把新源推上 prod repo,源文件 grep 确认是新的,但 docker build 出来的镜像里还是旧 bundle。根因:
--no-cache-filter不可靠,BuildKit 的 build context 层仍可能命中缓存。修法:clawpanel 源改动后,必须用整体--no-cache,不要用--no-cache-filter。代价:单次 ~20-30 分钟。但这是唯一能确保改动真编进去的方式。
这不是"高级技巧"或"经验之谈"。这是发版的必读须知,写进 skill 里才能确保每次都不遗漏。
为什么这样做有效
高风险操作的安全性来自流程的确定性,不来自执行者的谨慎。人会忘、会打错、会跳步。但固化的流程不会:
- 触发词明确化杀死了"我不是故意调用发版"的那类误操作。
- 步骤验证链条把每一步的前置条件和验收标准写成 Bash 检查,没法绕过。
- 故障处置内联把一个多月里积累的坑提前封死在流程里,新一轮发版不会重蹈覆辙。
5 个 skill 现在覆盖了:Wakou panel OTA、Connector 桌面端 OTA、OpenClaw runtime 容器全量发布、Codex 助手静默更新、加上客服远程调试的风险边界。它们没有一个是让 AI 执行发版的——都是让 AI 陪着用户,一步步走完一个铺满护栏的流程。
这是把"不要让 AI 碰发版"这条禁区,变成了"AI 执行发版的框架,确保每一步都验证、每个坑都已知、每种故障都有救法"的可行路径。
■