SOP:守卫判据与文档口径同步 + 新判据 T(2026-10-09)¶
交付物目录
guard-sync-20261009/;备份与台账见backup/README.md。 本次为配置/代码变更(改 hook 脚本 + 全局规则 + skill 引用 + 工程文档),单机、不停服。
1. 背景¶
一次对 hook / skill / rule 三层的失效与过时审计后,需一次收口三类问题:
- 死代码:
merge-guard.py在 2026-10-09 把判据 M / B / K 由强制降为提醒后,DENY_PROMPTS里 B / K / M / P / Q 的「已拦截」文案永不会触发(只有ENFORCE_MARKS内的判据会 deny); 紧邻注释「R/E/A/L 保留强制」易被读成「只剩 4 项强制」。 - 失效引用与旧口径:多处仍指向已删除的文件(
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的强制条数与实况不一致)。 - 踩坑待推进:踩坑账 2026-10-09 01:09「跑·中 输出 6463 tok(基准 1699 tok 的 3.8×)」——需推进成拦截。
2. 目标¶
merge-guard的强制判据清单在代码、注释、BASELINE、execution-playbook四处一致:12 强制 + 5 提醒;- 全仓(hook 脚本 +
~/.trae-cn规则/skill +docs/)无指向已删文件的失效引用、无与现行口径矛盾的旧表述; - 新增判据 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 命中条件(三者同时成立才拦):
RunCommand;- 命令分段数 ≥ 4(
;/&&/||计数 + 1); - 整条命令无输出上限(无
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-routingC 类(去掉复述)。
判定不改(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):
analyse()为异常条目加kind(耗时/输出)。append_incidents()状态由类型自动定:耗时→非机检:工具延迟抖动(不进待推进清单);输出且类属改/增/跑→待推进(输出即编辑 / 命令内容,可从入参机检,如判据 U / T);输出其余类 →非机检:模型输出,无入参信号。- 修幂等缺陷:
append_incidents原无幂等(同轮跑两遍会重复入账,台账里已有 4 行一字不差), 改为与save_baseline共用「本轮一次性」标记(首遍入账、次遍跳过)——两条调用路径都改:baseline_check.main()与wrapup.run_baseline()(后者原先绕过 saved 门,而它才是每轮实际走的路径, 首修漏掉它时实测又重复入账 3 行、已删)。 selftest()增分类反例(耗时偏离须判kind=耗时、输出偏离须判kind=输出)。wrapup.py回吐文案改为带类型标签(- [待推进] / [非机检] …),并修掉写死的「(待你推进成拦截)」。ops_incidents.md顶部口径注同步;历史 10 行待推进按规则归位(现仅剩 1 行改·中真属可机检)。- 判定门槛
MIN_SAMPLES3 → 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同步,请勿在站点侧修改)