跳转至

SOP:守卫判据与文档口径同步 + 新判据 T(2026-10-09)

交付物目录 guard-sync-20261009/;备份与台账见 backup/README.md。 本次为配置/代码变更(改 hook 脚本 + 全局规则 + skill 引用 + 工程文档),单机、不停服。

1. 背景

一次对 hook / skill / rule 三层的失效与过时审计后,需一次收口三类问题:

  1. 死代码:merge-guard.py 在 2026-10-09 把判据 M / B / K 由强制降为提醒后, DENY_PROMPTS 里 B / K / M / P / Q 的「已拦截」文案永不会触发(只有 ENFORCE_MARKS 内的判据会 deny); 紧邻注释「R/E/A/L 保留强制」易被读成「只剩 4 项强制」。
  2. 失效引用与旧口径:多处仍指向已删除的文件(agent-config-fix-20260923/tests_guard_cases.py、 skills/ops-execution-efficiency/references/measured-baselines.md),或用旧口径 (writing-handoff 的注入护栏「16 KB」实为 20 KB、lessons-and-retractions 的「红线 8 = 开新会话」已被推翻、 optimization-backlog #30 仍在标定已删除的「E 组 8 条」、rule-agent-efficiency 残留「D 组」术语、 BASELINE/execution-playbook/SKILL 的强制条数与实况不一致)。
  3. 踩坑待推进:踩坑账 2026-10-09 01:09「跑·中 输出 6463 tok(基准 1699 tok 的 3.8×)」——需推进成拦截。

2. 目标

  1. merge-guard 的强制判据清单在代码、注释、BASELINE、execution-playbook 四处一致:12 强制 + 5 提醒;
  2. 全仓(hook 脚本 + ~/.trae-cn 规则/skill + docs/)无指向已删文件的失效引用、无与现行口径矛盾的旧表述;
  3. 新增判据 T:只读聚合命令串联多段却未设输出上限 → 拦(可机检、可复跑、有反例)。

3. 前置条件

项 值
主机 192.168.31.250(用户 rain)
工程根 /home/rain/Documents/services/token_proxy
解释器 系统 python3(3.12,脚本无第三方依赖)
备份 改动前对 13 个文件留 .bak,见 backup/README.md

4. 影响范围

单机;不涉及远端主机、不涉及 token-proxy 服务本身(它不加载这些脚本),无需停服、无窗口要求。

类别 文件
hook 脚本(逻辑) merge-guard/merge-guard.py
hook 脚本(仅注释) docs-read-hook/docs-read-guard.py、posttooluse-guard/skill-edit-guard.py
全局规则 ~/.trae-cn/user_rules/rule-agent-efficiency.md
skill / references writing-handoff/SKILL.md、ops-execution-efficiency/SKILL.md、.../references/execution-playbook.md、.../lessons-and-retractions.md、.../optimization-backlog.md
工程文档 docs/BASELINE.md、docs/measured-baselines.md、docs/HANDOFF.md、cost_audit/ops_incidents.md

生效方式:hook 脚本与规则同会话下一次请求即生效;未改 hooks.json,故不需重启 Trae。

5. 分步操作

步骤 0:备份(机械首步)

cd /home/rain/Documents/services/token_proxy
TS=$(date +%Y%m%d-%H%M%S); mkdir -p guard-sync-20261009/backup
cp -p merge-guard/merge-guard.py            guard-sync-20261009/backup/merge-guard.py.bak.$TS
cp -p docs-read-hook/docs-read-guard.py     guard-sync-20261009/backup/docs-read-guard.py.bak.$TS
cp -p posttooluse-guard/skill-edit-guard.py guard-sync-20261009/backup/skill-edit-guard.py.bak.$TS
cp -p docs/BASELINE.md docs/measured-baselines.md docs/HANDOFF.md \
      cost_audit/ops_incidents.md           guard-sync-20261009/backup/   # 逐名保留原名即可
cp -p ~/.trae-cn/skills/writing-handoff/SKILL.md                 guard-sync-20261009/backup/writing-handoff-SKILL.md.bak.$TS
cp -p ~/.trae-cn/skills/ops-execution-efficiency/SKILL.md        guard-sync-20261009/backup/ops-execution-efficiency-SKILL.md.bak.$TS
cp -p ~/.trae-cn/skills/ops-execution-efficiency/references/execution-playbook.md        guard-sync-20261009/backup/execution-playbook.md.bak.$TS
cp -p ~/.trae-cn/skills/ops-execution-efficiency/references/lessons-and-retractions.md   guard-sync-20261009/backup/lessons-and-retractions.md.bak.$TS
cp -p ~/.trae-cn/skills/ops-execution-efficiency/references/optimization-backlog.md      guard-sync-20261009/backup/optimization-backlog.md.bak.$TS
cp -p ~/.trae-cn/user_rules/rule-agent-efficiency.md             guard-sync-20261009/backup/rule-agent-efficiency.md.bak.$TS
ls -1 guard-sync-20261009/backup | wc -l     # 预期 13

实际落盘备份的时间戳为 20261009-011529(本次执行记录)。

步骤 1:merge-guard.py 四处编辑

  • 1a:ENFORCE_MARKS 增加 "T";重写上方注释为「2026-10-09 按空转率回收 M/B/K,现强制 12 项」。
  • 1b:新增判据 T 的常量段(紧邻「判据 F」前):SEG_MIN=4、SEG_RE、CAP_RE、WRITE_VERB_RE。
  • 1c:PROMPTS 增加 "T"(提醒文案);DENY_PROMPTS 删除 B/K/M/P/Q 五条死文案、增加 "T"。
  • 1d:判定链(判据 O 之后)新增 T 的 hit 计算;修正「L / K / M 判定」那句注释。

坑:2>&1 含 >,故 WRITE_VERB_RE 的重定向分支用 (?<![0-9&])>(?!&)——排除 2>&1 / >&2,只认真实文件重定向; 否则例行的 ... 2>&1 会被误判成「变更命令」,判据 T 恒不触发。

步骤 2:失效注释改指现存来源

文件 原文 改为
docs-read-guard.py 离线用例见 agent-config-fix-20260923/tests_guard_cases.py 见 hook-restore-20260923/SOP.md 第 6 章(V2~V4)
skill-edit-guard.py 回归用例见 ...tests_guard_cases.py(已扩至 24 项) 见 hook-restore-20260923/SOP.md 第 6 章(V1~V7)

步骤 3:文档口径同步

  • writing-handoff/SKILL.md:失效引用改指 docs/BASELINE.md §2.1;注入护栏「16 KB」→「20 KB」(两处)。
  • execution-playbook.md:B/K/M 三行由「已强制」移入「仅提醒」(并补 Q);表下加「台账 §N 指已删文件」注;DENY_MAX=1 注。
  • ops-execution-efficiency/SKILL.md:条数改「已强制 18 / 仅提醒 5 / 仅沉淀 6」。
  • lessons-and-retractions.md:红线 8 改为「已推翻——不必为此开新会话」。
  • optimization-backlog.md:#30 标「已作废」;#44 条数同步。
  • rule-agent-efficiency.md:删「D 组」术语。
  • docs/BASELINE.md:判据条数→「12 强制 + 5 提醒」;§2.1 台账两处引用改指现存来源。
  • docs/measured-baselines.md:页首加「历史归档·口径已废」横幅。
  • cost_audit/ops_incidents.md:01:09 条状态改「已推进 → 判据 T」。

步骤 4:新判据 T 的实现要点

判据 T 命中条件(三者同时成立才拦):

  1. RunCommand;
  2. 命令分段数 ≥ 4(; / && / || 计数 + 1);
  3. 整条命令无输出上限(无 head / tail / --max-count / -m N),且无状态变更动词(rm/mv/cp/mkdir/chmod/chown/tee/touch/sed -i/truncate/dd/mkfs/kill/systemctl/apt/yum/dnf/pip install/真实文件重定向)。

与判据 E 的关系:E 鼓励「多次只读合并成一条命令」(省往返),T 要求「合并可以、但要设上限」——互补,不冲突。

6. 验证

# 用例 命令要点 预期 实测(2026-10-09 01:15)
V1 语法 python3 -m py_compile 三个脚本 rc=0 通过(PYC OK)
V2 判据 T 正例 载入模块对「7 段只读、无上限」命令判命中 命中 通过(incident run1=True run2=True)
V3 判据 T 反例-有上限 同命令加 \| head -n 20 不命中 通过(capped False)
V4 判据 T 反例-变更命令 同命令含 rm -f 不命中 通过(write False)
V5 判据 T 反例-短命令 cd /x && python3 s.py(2 段) 不命中 通过(short False)
V6 幂等复验 V2~V5 各跑两遍 两遍同结果 通过(T-selftest PASS)
V7 清单一致 grep ENFORCE_MARKS {A,C,D,E,F,I,J,L,N,O,R,T} 通过
V8 死代码已清 grep DENY_PROMPTS 内 B/K/M/P/Q 无命中 通过(仅 PROMPTS 保留)

V2~V6 为纯函数自测(不落盘、不写日志)——因该 hook 正常路径会向 logs/guard_events.jsonl 追加事件, 故不直接以 stdin 触发真机路径,避免污染不可再生日志。

7. 回滚

  • 整体回滚:把 backup/ 内 13 个 .bak.20261009-011529 逐名 cp -p 回原路径即可(原路径见 backup/README.md)。
  • 只停用判据 T(最小回滚):把 merge-guard.py 的 ENFORCE_MARKS 中的 "T" 去掉即可——T 随即退化为提醒 (PROMPTS["T"] 仍在,不会报错)。
# 高危(覆盖文件):先确认路径,再执行;执行前建议再备一次当前版本
cp -p guard-sync-20261009/backup/merge-guard.py.bak.20261009-011529 merge-guard/merge-guard.py

8. 风险说明

风险 说明与缓解
判据 T 误拦只读命令 只认「≥4 段 + 零输出上限 + 无变更动词」,且被拦后原样重发即放行(记 allow_fp)、每会话每判据最多 1 次;误拦只是「停一下」。
判据 T 空转率高(拦了做法没变) 按项目既有验收口径(allow_fp ÷ 被拦),空转率偏高即降级——改 ENFORCE_MARKS 一处即可(见第 7 章)。取数见 token_proxy/hook-audit-20261009/。
规则/skill 改动影响面 全局规则与 skill 为非注入/按需加载,改动只影响后续会话的判断依据;已同步 BASELINE 与 HANDOFF,避免新会话读旧口径。
measured-baselines.md 误保留风险 未删除(可能含历史数据),改以页首横幅声明口径已废;若确认无留存价值,由用户另行删除。

RUNBOOK 判定

本次未产生新的可复用交付物(仅改动既有 hook 脚本的判据与若干既有文档); hook 的运行/验证参考文档为 hook-restore-20260923/SOP.md 第 6 章与 docs/BASELINE.md §2(均未受影响、无需新建 RUNBOOK)。


附:判据 U 增补 + 踩坑账全量 triage(2026-10-09 01:24,同一主题续做)

背景:用户裁定「把所有能机检的踩坑都先上拦截,DENY_MAX=1,后续再统一核查是否降级」。

新增判据 U(强制):Edit(SearchReplace)的 len(old_str)+len(new_str) > 6000 字符 → 拦。 源:踩坑账 2026-10-08/09「改 · 小」多条输出偏大 3.1~4.7×(该步输出 token 主要来自编辑入参)。 反例自测:小改(700 字符)不拦、边界(=6000,非「>」)不拦、大改(6500)拦;双跑同结果(U-selftest 通过)。

踩坑账全量 triage(50 行,state「待推进」全部结清):

归类 行数 处置
输出偏大 · RunCommand 4 已推进 → 判据 T
输出偏大 · SearchReplace 6 已推进 → 判据 U
输出偏大 · Read/Grep/TodoWrite/Task 5 非机检(模型输出 token,无入参信号)
耗时偏大(各类工具) 35 非机检(工具执行延迟 = 机器/IO 抖动)

为何这 40 行不能上拦截(如实):PreToolUse 只看得到「工具名 + 入参」,看不到「将输出多少 token」, 也预判不了工具执行耗时——这两类由模型自身与机器负载决定,没有可机检的前置信号。 硬造判据只会变成「永远通过」的假判据(违反《批量项》锚点③)。

现场观测(首例真机):判据 U 与 T 上线后,T 在本次收尾当场拦下我自己一条 8 段、无输出上限的取数命令 (提示加 | head -n N);该命令实为「用 python 脚本改文件」的非只读命令 —— 说明 T 的误报面包含 「多段 python 脚本」,属已知形态,已记入观察;按提示加 | head 后重发通过。

同步:BASELINE(13 强制)、execution-playbook(已强制 19 条)、SKILL、optimization-backlog #44 条数一致。


附二:三层一致性复查(重复 / 相背)收口(2026-10-09 01:37,同一主题续做)

背景:对 hook / skill / rule 三层再做一次「重复 + 与当前结论相背」复查(三路只读子智能体 + 抽验关键项), 查出 17 处(相背 8 / 重复 5 / 其它 4)。本轮一次修掉 8 相背 + 2 重复,另 2 处重复经判定为「双层设计」不改,其它 4 处本轮未纳入。

变更(6 文件):

  • merge-guard.py(仅注释 / 文档串,逻辑零改动):文件头标记 B 【强制】→【仅提醒】、C 【仅提醒】→【强制】、 L 【仅提醒】→【强制】;补 M/N/O/P/Q/R/T/U 头注一行;重写「为什么 C 只提醒……」整段(该口径 2026-10-08 已作废, C/I 均已扩面升强制);修正 R 模板注释、及「非强制判据(C)」→「(B/K/M/P/Q)」。
  • execution-playbook.md:补 R 行(第 20 条,写文件扎堆)。
  • optimization-backlog.md:#51 作废(台账回填机制已移除)、#54 改 999→3→1、#44 条数 19→20。
  • ops-execution-efficiency/SKILL.md:条数 19→20。
  • rule-ops-scenario-routing.md:3 处「加载 X 技能」改为指向《技能加载索引》(去掉与 rule-skill-index 的重复触发)。
  • rule-python-script-safety.md:备份口径改为指向 rule-ops-scenario-routing C 类(去掉复述)。

判定不改(2 处,如实):ops SKILL 收尾自查清单 ↔ wrapup-expand §A、ops SKILL §6.2 ↔ execution-playbook —— 前者 SKILL 已自述「不另立口径」、后者属「原则正文 vs 状态总表」,均非需逐字同步的事实副本,无漂移风险,故不动。

验证:python3 -m py_compile merge-guard.py = COMPILE_OK;关键标记 grep 全命中(B/C/L 标记、playbook 第 20 行、

51 作废、#54、条数 20、《技能加载索引》);双跑输出一致(幂等复验通过)。备份见 backup/README.md 第三批(20261009-013704)。


附三:hook 层复查后清尾(2026-10-09 01:48,单层复查的收尾)

背景:对 hook 层单独复查(1 个只读子智能体、报告 ≤20 行)——本轮注释改动自洽、0 死代码、接线 0 缺陷; 剩 3 处上轮记录的「低优先」遗留,本轮清 2 处、判 1 处为误报。

  • webfetch-guard.py:日志注释改掉过时句「logs/guard_events.jsonl 里只有 merge-guard / glob-grep-guard / skill-edit-guard」, 改为「写入者已远不止 3 个」并列举。
  • skill-edit-guard.py:删除已停用的死函数 _rule_warning(调用点在 2026-10-07 已移除、仅存定义)。
  • 判定误报、不动:webfetch-guard/tests_guard_cases.py 被 webfetch-guard/SOP.md(第 110、153 行)引用为 手动离线用例(7 项,7/7 通过)——测试文件本就不挂 hooks.json,「未接线」不构成缺陷。

验证:两脚本 python3 -m py_compile = COMPILE_OK;grep -n _rule_warning 无命中(定义已清);双跑输出一致。 备份见 backup/README.md 第四批(20261009-014803)。


附四:踩坑账分类口径 + 入账幂等(2026-10-09 02:00,据用户反馈修)

背景:用户看「跑·小 偏离基准 3.0×(1158 ms)」问"这是坑还是只是偏离基准"。定性:偏离基准(机器/IO 抖动), 与既往 35 行同类;被写进「待推进成拦截」清单是口径缺陷——耗时类根本不可拦截(PreToolUse 看不到将执行多久)。

改法(cost_audit/baseline_check.py):

  1. analyse() 为异常条目加 kind(耗时 / 输出)。
  2. append_incidents() 状态由类型自动定:耗时 → 非机检:工具延迟抖动(不进待推进清单); 输出 且类属 改/增/跑 → 待推进(输出即编辑 / 命令内容,可从入参机检,如判据 U / T); 输出 其余类 → 非机检:模型输出,无入参信号。
  3. 修幂等缺陷:append_incidents 原无幂等(同轮跑两遍会重复入账,台账里已有 4 行一字不差), 改为与 save_baseline 共用「本轮一次性」标记(首遍入账、次遍跳过)——两条调用路径都改: baseline_check.main() 与 wrapup.run_baseline()(后者原先绕过 saved 门,而它才是每轮实际走的路径, 首修漏掉它时实测又重复入账 3 行、已删)。
  4. selftest() 增分类反例(耗时偏离须判 kind=耗时、输出偏离须判 kind=输出)。
  5. wrapup.py 回吐文案改为带类型标签(- [待推进] / [非机检] …),并修掉写死的「(待你推进成拦截)」。
  6. ops_incidents.md 顶部口径注同步;历史 10 行 待推进 按规则归位(现仅剩 1 行 改·中 真属可机检)。
  7. 判定门槛 MIN_SAMPLES 3 → 5:薄基准会产出假异常——实测「改|中」n=3、基准 723 tok 偏低, 把与之相当的 3018 tok 误判成 4.2×(该步编辑体量其实 < 判据 U 阈值)。该历史行改标 已评估:薄基准(n=3)误判;ops_incidents.md 状态口径增 已评估:… 一类。故本轮不动判据 U 阈值 (调 U 反而会误伤常规改),动的是"基准可信度"。

验证:py_compile = COMPILE_OK;--selftest PASS;状态分支三反例(耗时 / 改·输出 / 读·输出)→ 分别得 非机检:工具延迟抖动 / 待推进 / 非机检:模型输出,无入参信号;grep 待推进 = 1 行; wrapup.py 双跑输出完全一致、且均不再出现「入账」行(幂等,两条路径均已改); --dry-run 复核:n<5 的类一律判 沉淀基准(不再产出假异常)。 备份见 backup/README.md 第五批(20261009-015510 / 20261009-015740 / 20261009-020126)。


附五:效率 / 成本「分析」行——机器产出(2026-10-09 02:12,用户要求)

背景:用户发现收尾自查只有「列」、缺「分析」,且两边不对称——成本侧有 cost_lines()(必出), 效率侧只有 efficiency_alerts()(命中才出)→ 正常轮效率整块消失,答复里常缺效率结论。 根因:效率结论没有机器产出、也没有验收方(Trae 无「最终答复」事件,Hook 拦不到)。

改法:

  • baseline_check.cost_lines() 由「成本分布(按操作)」改为单行「成本分析」:本轮金额 | 分布(类×次数 金额 占比)| 最贵单步 | 一句判定(集中在 X,下轮可压 / 较分散)。
  • wrapup.py 新增 efficiency_analysis():单行「效率分析」 = 步数 | 合并率(未合并 K 组/M 步)| 一句判定(无异常 / 有返工 / 碎步偏多 / 大输出 / 未命中偏高)。
  • 两者在 main() 中并列打印、每轮必有;run_baseline() 不再重复打成本(改为接收 pre_steps,只做基准 / 入账)。
  • 效率告警明细(efficiency_alerts)保留,作为「效率分析」命中时的明细。

验证:py_compile = COMPILE_OK;wrapup 双跑输出一致、且都出现「效率分析」与「成本分析」两行; grep -rn 成本分布 在规则 / 工程内无残留。备份见 backup/README.md 第六批(20261009-021236)。


来源:/home/rain/Documents/services/token_proxy/guard-sync-20261009/SOP.md | 最后更新:2026-10-09 02:14(由 build/sync.py 同步,请勿在站点侧修改)