跳转至

SOP:误删 Hook 守卫脚本的恢复(2026-09-23)

交付物目录 hook-restore-20260923/;实现体 restore_hooks.py(幂等)。 第 5 章列出与实现等价的命令序列,供阅读与手工复现,以实现体为准。

1. 背景

2026-09-23 13:18~13:32,用户在清理工程目录时误删了两个 Hook 守卫脚本——当时的理解是「Hooks 只是 ~/.trae-cn/hooks.json 在生效」,脚本目录被当作临时产物清掉。

hooks.json 的三条命令都是 s="..."; [ -f "$s" ] && python3 "$s" || true; exit 0 形式:脚本缺失即静默跳过,既不报错也不注入。因此故障表现是一条「无错误、无注入」的静默失效:

事件 受影响脚本 静默失效的功能
SessionStart sessionstart-hook/session-start-inject.py 中文指令 + docs/HANDOFF.md 交接快照注入
PreToolUse(Read) docs-read-hook/docs-read-guard.py 读 docs/*.md 前的成本约束提示
PostToolUse(*) posttooluse-guard/skill-edit-guard.py 未受影响(文件未丢)

2. 目标

  1. 两个脚本内容与删除前的生产版本一致,不是近似重建;
  2. hooks.json 三条命令指向的路径全部存在;
  3. 离线用例恢复通过:正例注入、非目标文件静默、依赖目录静默。

3. 前置条件

项 值
主机 192.168.31.250(用户 rain)
工程根 /home/rain/Documents/services/token_proxy
镜像源 /tmp/regress-check2|3|4/("用例隔离"一轮留下的项目镜像,含三个守卫脚本)
校验锚点 docs-read-hook/__pycache__/docs-read-guard.cpython-312.pyc(生产第五版字节码)
解释器 系统 python3(3.12.3,脚本无第三方依赖)

4. 影响范围

单机变更,只新建文件,不覆盖任何现存文件,无需停服;代理服务 token-proxy、在跑的作业、logs/*.jsonl 均不受影响,无窗口期要求。

5. 分步操作

# 实现体:hook-restore-20260923/restore_hooks.py(以它为准;下列序列供阅读与手工复现)
# 高危动作:无——本次不覆盖、不删除任何现存文件;目标已存在且内容不同则报错退出

# 1) 先 dry-run:完成还原与 pyc 全等校验,但不写文件
#    预期输出: "[校验] 与生产 pyc 逐 code object 全等(co_code / co_consts / co_names 递归一致)"
./venv/bin/python hook-restore-20260923/restore_hooks.py --dry-run

# 2) 实际写入:新建 sessionstart-hook/session-start-inject.py 与 docs-read-hook/docs-read-guard.py
#    预期输出:两行 "[恢复] <目标路径>"
./venv/bin/python hook-restore-20260923/restore_hooks.py

# 3) 幂等复跑:第二次应零变更
#    预期输出:两行 "[跳过] ...",与第 2 步相比无任何文件改动
./venv/bin/python hook-restore-20260923/restore_hooks.py

# 4) 恢复 session-start-inject.py 的等价手工动作(镜像三份字节一致,可任取其一)
#    cp -p /tmp/regress-check4/sessionstart-hook/session-start-inject.py \
#          sessionstart-hook/session-start-inject.py

# 5) 恢复 docs-read-guard.py 不能靠 cp:镜像是第四版,生产是第五版
#    (两者 co_code 完全一致,仅 4 处常量不同),须由实现体按 pyc 常量还原并做全等校验

6. 验证

# 用例 命令要点 预期 实测(2026-09-23 13:55)
V1 还原保真 实现体内部 compile 与生产 pyc 逐 code object 比较 全等 通过(co_code/co_consts/co_names 递归一致)
V2 PreToolUse 正例 喂 Read + docs/SOP.md 输出 additionalContext 通过(364 字节,退出码 0、stderr 空)
V3 PreToolUse 负例 喂 Read + proxy.py 静默 通过(stdout 0 字节)
V4 PreToolUse 排除例 喂 Read + venv/.../docs/README.md 静默 通过(stdout 0 字节)
V5 SessionStart 注入 喂 SessionStart + 本工程 cwd 中文指令 + HANDOFF 均在 通过(9233 字节,两项特征串各命中 1 次)
V6 留痕字段完整 tail -n 1 sessionstart-hook/state/session-start.log 5 字段齐全 通过(event_cwd/proc_cwd/handoff/bytes/truncated)
V7 接线齐全 校验 hooks.json 三条命令指向的路径 三条均存在 通过

V2~V5 的判据同时包含「退出码 0」与「stderr 为空」两条红线(非 0 退出会把 stderr 塞进模型上下文)。

7. 回滚

回滚方式:删除本次新建的两个文件即可,即回到「脚本缺失、Hook 静默跳过」的状态。

# 高危:删除文件前先确认路径,不使用通配
rm -f sessionstart-hook/session-start-inject.py      # 删除本次恢复的脚本
rm -f docs-read-hook/docs-read-guard.py              # 删除本次恢复的脚本

本次未改动 hooks.json,也无需清理它。文档备份与台账位置见 hook-restore-20260923/backup/README.md。

8. 风险说明

风险 说明与缓解
session-start-inject.py 无生产 pyc 可比 保真依据是「三份镜像字节一致」+「含 (五):日志路径相对化 修复标记」。若该镜像落后于生产,可能丢掉 04:38 之后的最后一处微调;缓解:内容与 SES 第四十四节记录的改动范围核对一致
docs-read-guard.py 镜像是第四版 不直接使用镜像源码,而是用生产 pyc 的常量还原 4 处差异,并以全等校验证明与生产版字节码等价——校验通过即无残余风险
镜像位于 /tmp /tmp 会被系统清理;本次已把内容落回工程目录,镜像不再是单点
验证留下痕迹 docs-read-hook/state/verify-restore__solo_agent 与 session-start.log 的测试行,见 backup/README.md 登记;前者只影响同名假 session 的去重,不影响真实会话

来源:/home/rain/Documents/services/token_proxy/hook-restore-20260923/SOP.md | 最后更新:2026-09-23 13:55(由 build/sync.py 同步,请勿在站点侧修改)