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. 目标¶
- 两个脚本内容与删除前的生产版本一致,不是近似重建;
hooks.json三条命令指向的路径全部存在;- 离线用例恢复通过:正例注入、非目标文件静默、依赖目录静默。
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同步,请勿在站点侧修改)