SOP:SessionStart 注入「HANDOFF 读取守卫」(2026-10-02)¶
主题目录:
handoff-read-guard-20261002/| 备份台账:backup/README.md
1. 背景¶
- 现象:连续两轮把已由 SessionStart 全文注入的
docs/HANDOFF.md又整篇Read一次 (MB §二十七 / §二十九 的 22:20 与 22:29 样本,各约 1.6~1.8 k tok)。 - 根因:注入内容是一大段文档正文,没有任何「它已在你上下文里」的标记; 而「改文件前先读一遍」是通用习惯,未为「已注入」开例外。
- 触发条件:凡「要改 HANDOFF」或「要读 HANDOFF 背景」的会话均有此风险。
2. 目标¶
- 会话启动注入段的末尾带一行显著提示,明确「已全文注入、勿再 Read、改它直接 SearchReplace」。
- 两个相关技能(
writing-handoff、reading-docs-for-context)各加一条禁令,作为 Hook 失效时的第二道防线。 - 可验证:演练输出末段出现
[HANDOFF 读取守卫];两个技能文件内均可搜索到对应条款。
3. 前置条件¶
- 对
sessionstart-hook/session-start-inject.py有写权限(属主 rain)。 hooks.json的SessionStart条目已指向该脚本——本次不改hooks.json,故无需重启 Trae。- 主题目录与
backup/已建(见第 7 章)。
4. 影响范围¶
| 项 | 内容 |
|---|---|
| 影响面 | 本机所有新会话(注入段多一行提示) |
| 停服 | 否 |
| 生效时点 | 改脚本后下一个新会话(SessionStart 仅在会话开始触发) |
| 体积影响 | 注入 +约 100 B(约 30 token),可忽略 |
5. 分步操作¶
步骤 1:备份(4 个文件)¶
cd ~/Documents/services/token_proxy
TS=$(date +%Y%m%d-%H%M%S); D=handoff-read-guard-20261002
mkdir -p $D/backup/token_proxy/sessionstart-hook \
$D/backup/token_proxy/backlog-review-20261002 \
$D/backup/trae-cn/skills/writing-handoff \
$D/backup/trae-cn/skills/reading-docs-for-context
cp -p sessionstart-hook/session-start-inject.py $D/backup/token_proxy/sessionstart-hook/session-start-inject.py.bak.$TS
cp -p backlog-review-20261002/RUNBOOK.md $D/backup/token_proxy/backlog-review-20261002/RUNBOOK.md.bak.$TS
cp -p ~/.trae-cn/skills/writing-handoff/SKILL.md $D/backup/trae-cn/skills/writing-handoff/SKILL.md.bak.$TS
cp -p ~/.trae-cn/skills/reading-docs-for-context/SKILL.md $D/backup/trae-cn/skills/reading-docs-for-context/SKILL.md.bak.$TS
find $D/backup -type f -exec chmod 600 {} +
坑(本轮已踩):备份后只对文件 chmod 600,不要 chmod -R 600 <目录>——
那会把目录的 x 位一并去掉,之后 cd 进不去、find 也遍历不了。目录保持 755。
预期:4 个 .bak.<TS>;stat -c '%a %n' 显示目录 755、文件 600。
步骤 2:给脚本加守卫(常量 + 输出 + 文件头修复记录(八))¶
grep -n "HANDOFF_READ_GUARD\|CHINESE_INSTRUCTION" sessionstart-hook/session-start-inject.py
常量区(CHINESE_INSTRUCTION 之前):
HANDOFF_READ_GUARD = (
"[HANDOFF 读取守卫] 以上即 docs/HANDOFF.md 的完整内容(除非上方标注「已截断」)。"
"**不要再 Read 这个文件**——需要修改时直接按上面注入的内容做 SearchReplace(或只读目标段);"
"只有上方标注「已截断」时才需要读原文。"
)
main() 内,命中后追加:
parts.append(text if text else MISSING_HANDOFF_NOTICE)
if text and not truncated:
parts.append(HANDOFF_READ_GUARD)
为什么带 not truncated:截断时上下文里那份不完整,「勿再 Read」就错了——那时恰恰该读原文。
步骤 3:给两个技能加禁令¶
~/.trae-cn/skills/writing-handoff/SKILL.md→ 「写作要求」节首条;~/.trae-cn/skills/reading-docs-for-context/SKILL.md→ 「上下文成本」节首条。
改 skill 正文不触发前缀重建,无需开新会话。
步骤 4:更新 RUNBOOK¶
backlog-review-20261002/RUNBOOK.md:服务概览「是什么」补「读取守卫」、第 8 章新增「场景 E」、修订记录追加一行。
6. 验证¶
cd /home/rain/Documents/services/token_proxy
python3 -m py_compile sessionstart-hook/session-start-inject.py && echo "语法 OK"
echo '{"cwd":"'"$PWD"'"}' | python3 sessionstart-hook/session-start-inject.py | tail -3
grep -c HANDOFF_READ_GUARD sessionstart-hook/session-start-inject.py # 预期 2(定义 + 使用)
grep -c '不要重复读' ~/.trae-cn/skills/writing-handoff/SKILL.md
grep -c '已注入的不重读' ~/.trae-cn/skills/reading-docs-for-context/SKILL.md
预期:末段出现 [HANDOFF 读取守卫] …;常量出现 2 次;两个技能各命中 1 次。
失败判断:无守卫行 → 脚本未生效或被回滚,按第 7 章回滚后重做。
幂等:脚本无状态(纯读 + 输出),连跑两次输出逐字一致。
7. 回滚¶
cd ~/Documents/services/token_proxy
TS=<备份时间戳> # 本次为 20261002-223934
cp -p handoff-read-guard-20261002/backup/token_proxy/sessionstart-hook/session-start-inject.py.bak.$TS sessionstart-hook/session-start-inject.py
cp -p handoff-read-guard-20261002/backup/token_proxy/backlog-review-20261002/RUNBOOK.md.bak.$TS backlog-review-20261002/RUNBOOK.md
cp -p handoff-read-guard-20261002/backup/trae-cn/skills/writing-handoff/SKILL.md.bak.$TS ~/.trae-cn/skills/writing-handoff/SKILL.md
cp -p handoff-read-guard-20261002/backup/trae-cn/skills/reading-docs-for-context/SKILL.md.bak.$TS ~/.trae-cn/skills/reading-docs-for-context/SKILL.md
回滚触发:演练不再输出守卫行且确实需要它 / 注入内容异常 / 技能条款被误改。 备份存放位置与清单见 backup/README.md(本主题目录下)。
8. 风险说明¶
| 风险 | 缓解 |
|---|---|
| 守卫行会污染注入内容? | 纯一行中文提示、不阻断;约 30 token,可忽略 |
| 提示在、模型仍重读 | 属行为层,靠两个技能禁令兜底;仍无效则考虑 PreToolUse 拦截(需另立变更) |
| 改脚本会否触发前缀重建? | 否——Hook 脚本不在请求前缀内,改它只需新会话生效 |
误用 chmod -R 600 致目录不可进入 |
已在步骤 1 与下方留痕;修复法:chmod 755 <各级目录> |
本轮实际踩坑留痕:首次备份时用了 chmod -R 600 backup/,使 backup/ 及其子目录失去 x 位;
随后一条组合命令里的 cd 失败,但其后的命令仍在项目根目录执行——误将项目根权限改为 700,
并全库列举一次(约 1.4 万行输出)。已修复:项目根恢复 775、backup/ 各级目录 755、备份文件 600。
教训:目录权限批量调整不得带 x 位;组合命令中 cd 失败必须让整条链中止(本轮用了 && 但后续用 ; 衔接)。
来源:
/home/rain/Documents/services/token_proxy/handoff-read-guard-20261002/SOP.md| 最后更新:2026-10-02 22:41(由build/sync.py同步,请勿在站点侧修改)