Skill 方案导入1627 字·2026/11/14·被检索 0 次

Skill 方案 S1 · 站点健康巡检与自愈

把门户3000、词汇站3001、笔记站3102与Cloudflare隧道的体检和自愈固化成一条命令:四层检查矩阵(端口/HTTP/内容指纹/隧道)、L0-L3分级自愈、outbox告警与锁幂等。253次巡检会话0.99亿token可压到0.15亿,省85%。

挂靠在《二、重复操作与 Skill 方案》之下

版本
使用说明
v1reused-preview2026/11/14 11:16:39

Skill 方案 S1 · 站点健康巡检与自愈

一句话:把「检测门户 3000、词汇站 3001、笔记站 3102、隧道,坏了自动重启,域名变了发邮件」这句每次都要重说一遍的话,固化成一条命令;253 次巡检会话消耗的 0.99 亿 token,可压到 0.15 亿以内,省 85%。

一、为什么需要它

按「首条消息模板相似度」聚类,命中巡检模板的会话有 253 个。它们的用户原话几乎逐字相同:

「检测考研学习导航门户(3000)、词汇站(3001)和 natapp 隧道的健康状态,坏了就自动重启,域名变了就发邮件通知」

指标数值说明
会话数253占 277 个总会话的 91%
累计 token0.99 亿占两个月总消耗 6.3%
工具调用1402 次平均每会话 5.5 次
平均每会话 token39 万其中输入占 96%
用户消息1–2 条没有一次是"讨论",全是"执行"

痛点不在判断难度,而在三处结构性浪费:

  1. 开场靠记忆。每次都要重新列端口、任务名、日志路径、隧道模式,约 1.2 万 token 的固定开销乘以 253 次,就是 300 万 token 白烧。
  2. 判据不统一。有时看端口监听、有时 curl 首页、有时读日志里的 Tunnel established,同一个故障在两次会话里可能得出相反结论。
  3. 自愈无分级。现状只有「不动」和「全量重启」两档,进程活着但反代 502 这种中间态,往往被直接推成全量重启,把本来正常的词汇站也打断。

二、触发词与边界

触发词不适用场景
「网站能打开吗」「巡检一下」「体检」要改代码或路由 → S3 构建发布
「网站 502 / 404 / 打不开」「白屏」要重建计划任务本身 → S2 附录
「坏了就自动重启」「重启一下网站」要验证并发/压测 → 不做,明确拒绝
「域名是什么」「把链接发我」要看一月内的可用率趋势 → 查日志,不跑巡检
「cag.quest 通吗」「隧道正常吗」只要一张页面长图 → S6

边界一条:巡检只读 + 重启,不改配置。任何涉及 config.yml、mode.txt、计划任务定义的改动,一律转 S2 并单独确认。

三、输入与前置检查

站点与探针是固定的,写死在 skill 里,不再向用户追问:

服务端口本地探针通过标准
门户 portal/server.js3000/healthzJSON 里 portal=ok
词汇站 Next3001/vocab/200 且含站名
笔记站 Next3102/notes/200 且含「笔记」
C 语言实验室3103/c-lab/200
Cloudflare Tunnel—https://cag.quest/200 且 TLS 正常

跑之前先核三件事:

Get-ScheduledTask -TaskName "Kaoyan*" | Select-Object TaskName, State
Get-NetTCPConnection -LocalPort 3000,3001,3102,3103 -State Listen | Select-Object LocalPort, OwningProcess
Get-Content "C:\Users\cag\WorkBuddy\2026-10-11-06-00-16\kaoyan-vocab\natapp\mode.txt"

判定:KaoyanPortal/KaoyanNextServer/KaoyanNotes/KaoyanTunnel 四个任务必须是 Running 或 Ready;mode.txt 内容为 tunnel 才用 https 探公网,否则说明已回落 natapp,只能用 http——这条判错会把「隧道正常」误报成「隧道已断」。

四、执行步骤

步骤 1 · 只读体检。 先不碰任何进程:

& "C:\Users\cag\.workbuddy\binaries\node\versions\22.22.2-6\node.exe" `
  "C:\Users\cag\WorkBuddy\2026-10-11-06-00-16\kaoyan-vocab\natapp\selfheal.mjs" --dry-run --json

步骤 2 · 四层检查矩阵。 缺一层就会有盲区:

层级命令失败含义
端口Get-NetTCPConnection -LocalPort 3001 -State Listen进程没起来
HTTPInvoke-WebRequest -UseBasicParsing http://127.0.0.1:3001/vocab/ -TimeoutSec 8起来了但不服务
内容指纹响应体长度 > 2000 字节且匹配 <title> 关键字反代返回了错误页却仍是 200
隧道node "C:\Users\cag\WorkBuddy\2026-10-11-06-00-16\ops\cf\verify-tunnel.mjs" --json本地全好但公网不通

内容指纹是最容易被省掉的一层,也是唯一能抓住「反代把 500 页面当 200 吐出来」的手段。

步骤 3 · 分级自愈。 按最小必要动作升级,不许跳级:

级别触发条件动作耗时
L0全绿只记录,不动作3 s
L1单端口无监听Start-ScheduledTask -TaskName "KaoyanNotes"15 s
L2L1 后仍不通launch.ps1 -Name notes(先杀端口占用者再起)40 s
L3门户 3000 或隧道异常全量:vocab/notes → portal → tunnel120 s

L1 遇到 0x800710E0 说明有卡死实例,必须先 Stop-ScheduledTask 再 Start,脚本已内置这一分支。

步骤 4 · 告警。 后台进程调不到邮箱连接器,所以只落 outbox/mail-*.json + 桌面 toast;用户要邮件时先 --flush 看积压,再用 mcp__agent-mail__SendMessage 发一封汇总,发完把对应 json 的 status 改成 sent。cag.quest 已固定,正常不该再有域名变化通知;真出现就说明 mode.txt 落回了 natapp,按故障处理而不是按通知处理。

步骤 5 · 收敛成四句话。 可直接点的链接、三个入口状态、本次动作(actions 为空就说"没动,本来就正常")、域名是否刚变。

步骤 6 · 幂等。 一次自愈最长 3 分钟,30 分钟一跑也可能叠加,用 selfheal.lock 加锁,超过 10 分钟的锁视为陈旧锁回收;重复执行不产生第二个 cloudflared,否则两个连接器会抢 20241 指标端口。

五、输出与验收

{
  "healthy": true,
  "domain": "https://cag.quest",
  "entries": { "portal": 200, "vocab": 200, "notes": 200, "clab": 200, "public": 200 },
  "actions": [],
  "mode": "tunnel",
  "checkedAt": "2026-11-14T03:20:11.000Z"
}

三条硬断言,任一不满足即非零退出,不许静默通过:

  1. healthy=true 时 actions 必须是空数组——有动作就说明刚才不健康,两者不能同时成立。
  2. 每个入口的 HTTP 码必须是 200,且响应体大于 2000 字节;只验状态码不算通过。
  3. checkedAt 距当前时间不超过 90 秒,防止把上一次的缓存结果当本次结论。

六、失败处理与回滚

现象根因动作
Start-ScheduledTask 报 0x800710E0有卡死实例占着先 Stop-ScheduledTask 再 Start
重启后端口仍不通卡死进程只占端口不退按端口找 PID,Stop-Process -Force 后再拉一次
隧道任务正常但公网 502Stop-ScheduledTask 不带走 cloudflared,成了孤儿进程Get-Process cloudflared 后强杀,再 Start-ScheduledTask -TaskName KaoyanTunnel
公网探测全红、本地全绿误用了 https 探 natapp 模式读 mode.txt,改 http 重探
全量重启后仍失败代码或数据库层面坏了停止自愈,读 portal/portal-server.log、kaoyan-vocab/next-server.log、ops/cf/cloudflared.out.err 尾部,转人工

回滚:隧道退回 natapp 用 ops\cf\rollback.ps1(免提权,支持 -Check 试运行);服务层面没有"回滚"概念,重启即恢复,真正的回滚是 S3 的构建产物回退。

与现有 kaoyan-site-health skill 的关系:S1 是它的超集,不是替代。原 skill 已经解决了 80% 的问题(端口、健康端点、隧道校验、mode.txt 分流),S1 增量补三块:把 3103 纳入矩阵、加内容指纹层、把自愈从两档拆成 L0–L3。落地方式是把原 skill 收缩成薄入口——保留它的名字和触发词做别名,正文只写一句「执行 site-report.mjs,按 S1 的矩阵解读」,巡检逻辑全部沉到 selfheal.mjs,避免两份文档各说一套。

七、收益测算

项目现状改造后
单次 token39 万(重载上下文 + 5.5 次工具往返)1.5 万(一条命令 + 读 JSON)
年化次数253 次253 次(其中 150 次由计划任务静默完成,不进对话)
对话内消耗0.99 亿0.15 亿
单次耗时2–6 分钟20–40 秒

拆开看:固定开场 1.2 万 × 253 ≈ 300 万;工具往返 1402 次 × 约 6 万 ≈ 0.84 亿。前者靠把站点清单写进 skill 消掉,后者靠一条脚本命令把 5.5 次往返压成 1 次。节省 0.84 亿,约 85%,与父篇测算一致。