跳转至

SOP:新增判据 L(批量接口提醒)+ BASELINE 记「逐条 vs 批量入参」

主题目录:batch-interface-20261007/|变更日期:2026-10-07|起因:slurm_ins 系统侧 deploy 阶段优化结果(累计墙钟 −95.8%)

1. 背景

slurm_ins 的 deploy 阶段三项优化实测:整体墙钟 13.83 → 10.34 s、deploy 阶段 7.2 → 4.0 s、 远端命令 41 → 18,变更记录 225/25/200 逐条一致;三层堆叠后本会话累计 247.7 → 10.3 s(−95.8%)。

拆开看,三项改动其实是两类不同模式:

# 原状 改后 模式
1 _stage_build 3 条探测逐条 拼一段 shell 一次往返 合并调用(省握手/往返)
2 _is_install_current 3~4 条探测逐条 同上 合并调用
3 installed_packages_cmd:for p in …; do rpm -q $p; done rpm -q --qf … pkg1 pkg2 … 整批入参(省进程启动与解析)

关键:第 3 条不是"合并"——它把 N 次调用变成 1 次调用处理 N 个对象;而图上明确标注 「第三条是这次最大的单项收益」。

对照 agent 侧:第 1、2 类已由 判据 A/E 强制合并覆盖;第 3 类在 agent 侧没有任何判据(缺口)。

2. 目标

  1. 新增 判据 L(仅提醒):RunCommand 命令含逐项循环 → 提醒确认目标命令是否支持一次传多个参数;
  2. 把「合并调用 ≠ 整批入参」写进稳定层 BASELINE.md §2,附 slurm_ins 实测数据;
  3. 不强制——循环有时确属必要(目标命令不支持批量、或需在循环内分支),Hook 无命令语义。

3. 前置条件

  • 可写 merge-guard/merge-guard.py 与 docs/BASELINE.md;
  • Hook 脚本改动即时生效(10-07 实测),故先离线验证再交;
  • 判据 L 与已有判据 A/E 的分工必须写清(否则会被误认为重复)。

4. 影响范围

项 说明
涉及对象 merge-guard(新增判据 L)、docs/BASELINE.md(新增机制条)
是否停服 否;无窗口要求,改完下一次调用即生效
行为变化 RunCommand 命令含循环时多注入一行提醒(每会话至多一次、约 70 字)
不受影响 A/B/D/E/F/I/J 强制判据、C/K 提醒、指纹放行、DENY_MAX / INJECT_MAX

5. 分步操作

步骤 1:备份(必做)

TS=$(date +%Y%m%d-%H%M%S)
D=~/Documents/services/token_proxy/batch-interface-20261007/backup/home/rain/Documents/services/token_proxy
mkdir -p "$D/merge-guard" "$D/docs"
cp -p ~/Documents/services/token_proxy/merge-guard/merge-guard.py "$D/merge-guard/merge-guard.py.bak.$TS"
cp -p ~/Documents/services/token_proxy/docs/BASELINE.md            "$D/docs/BASELINE.md.bak.$TS"
cp -p ~/Documents/services/token_proxy/docs/HANDOFF.md             "$D/docs/HANDOFF.md.bak.$TS"

步骤 2:加判据 L(四处,成套)

  1. 常量 LOOP_RE(\bfor\s+\w+\s+in\b|\bwhile\s+read\b|\bxargs\b);
  2. PROMPTS["L"] 与文档头判据列表同步;
  3. 主流程独立判定块(不进 _detect——L 是单次调用即可判的形态,且仅提醒);
  4. 状态加 l_fired 键(每会话一次)。

坑: - L 的提示文本不含 %d,故不能用 PROMPTS[mark] % args,直接取字符串; - L 走独立标记(l_fired)而不占 INJECT_MAX——否则会与判据 C 争提醒额度; - 可复用 _cmd_raw(tool_input) 取命令原文(它兼容 command / cmd / script 三个字段), 不要自己再解析 tool_input。

cd ~/Documents/services/token_proxy
python3 -m py_compile merge-guard/merge-guard.py && echo "语法通过"
grep -n "LOOP_RE\|l_fired" merge-guard/merge-guard.py | head

步骤 3:离线验证(每个分支用独立 session)

坑:l_fired 是"每会话一次",若四个用例共用一个 session,只有第一条会触发—— 这是设计而非缺陷,但会让验证误判"分支失效"。故每个用例给独立 session_id。

cd ~/Documents/services/token_proxy && python3 - <<'PY'
import json, subprocess, sys
H = "merge-guard/merge-guard.py"
def run(cmd, sid):
    e = {"hook_event_name": "PreToolUse", "session_id": sid, "agent_id": "a",
         "tool_name": "RunCommand", "tool_input": {"command": cmd}}
    return subprocess.run([sys.executable, H], input=json.dumps(e), capture_output=True, text=True).stdout
for cmd, sid, desc in [("for p in a b; do rpm -q $p; done", "T1", "for 循环"),
                       ("printf x | xargs -n1 echo",       "T2", "xargs"),
                       ("while read l; do echo $l; done < f", "T3", "while read"),
                       ("ls -l /tmp",                      "T4", "无循环")]:
    out = run(cmd, sid)
    print("%-12s -> %s" % (desc, "含批量接口提醒" if "批量接口提醒" in out else "静默"))
PY

预期:前三条触发、第四条静默。验证后清理 guard_events 里的测试行与 merge-guard/state/T*。

步骤 4:BASELINE.md 记「逐条 vs 批量入参」

在 §2「机制与陷阱」加一条,须写明:① 合并调用省往返、整批入参省进程,二者不可替代; ② slurm_ins 的实测数字与"整批入参是最大单项收益";③ 同族口径——exec_linux 内部是 for cmd: conn.run_cmd(cmd),一次传多条命令不减往返。

坑:本条要追加在「诊断工具口径必须自证」那条之后,不要替换它(本轮第一次编辑即误替换, 已当场恢复并校验)。

grep -c "口径必须自证" ~/Documents/services/token_proxy/docs/BASELINE.md   # 预期 1
grep -c "逐条」与「批量入参" ~/Documents/services/token_proxy/docs/BASELINE.md  # 预期 1

6. 验证

层级 命令 预期
语法 python3 -m py_compile merge-guard/merge-guard.py 无输出
三分支 步骤 3(独立 session) for / xargs / while read 均触发,无循环静默
每会话一次 同一 session 连发两次循环命令 第一次触发、第二次静默
真机 在真实会话里发一条含循环的 RunCommand 注入「【批量接口提醒】…」
稳定层 步骤 4 的两条 grep -c 均 1

7. 回滚

备份位置:batch-interface-20261007/backup/home/rain/Documents/services/token_proxy/{merge-guard,docs}/, 台账见 backup/README.md。

cp -p ~/Documents/services/token_proxy/batch-interface-20261007/backup/home/rain/Documents/services/token_proxy/merge-guard/merge-guard.py.bak.20261007-082707 \
      ~/Documents/services/token_proxy/merge-guard/merge-guard.py
python3 -m py_compile ~/Documents/services/token_proxy/merge-guard/merge-guard.py && echo "回滚后语法通过"

回滚后验证:grep -c "LOOP_RE" merge-guard/merge-guard.py 为 0(判据 L 消失)。 BASELINE.md 的机制条建议保留(它记录的是事实,与判据 L 是否存在无关)。

8. 风险说明

风险 缓解
L 与 A/E 重复、造成噪声 分工写进 docstring:A/E 管合并省往返,L 管整批入参省进程;L 每会话至多一次
循环本是必要的(误报) 只提醒不强制;文本为"先确认目标命令是否支持批量入参",非"必须改"
验证时误判"分支失效" 步骤 3 明确要求每个用例独立 session(l_fired 每会话一次)
编辑 BASELINE 时误替换相邻条目 步骤 4 的两条 grep -c 断言(各 1 处);本轮已实际踩到并修复
正则误伤(如命令里含字符串 for) \bfor\s+\w+\s+in\b 要求完整 for … in 结构,普通文本不会命中

附录:交付物清单

文件 说明
merge-guard/merge-guard.py(改) 判据 L:LOOP_RE + PROMPTS["L"] + 独立判定块 + l_fired 状态键
docs/BASELINE.md(改) §2 新增「逐条 vs 批量入参」机制条
docs/HANDOFF.md(改) 判据数 9 → 10;3.2 的 K 行扩为 K/L
batch-interface-20261007/SOP.md 本文档
batch-interface-20261007/backup/ 三份备份与台账

来源:/home/rain/Documents/services/token_proxy/batch-interface-20261007/SOP.md | 最后更新:2026-10-07 08:28(由 build/sync.py 同步,请勿在站点侧修改)