chore(hooks): 输出门禁三脚本更新 + 新增技能加载闸门 skill-load-guard.py
This commit is contained in:
1 parent
c8b514832f
commit
bda9b10161
4 files changed
+385
-10
No files matched your search
@@ -78,8 +78,26 @@ def lock_owner() -> str:
|
||||
|
||||
|
||||
def out(obj: dict) -> None:
|
||||
sys.stdout.write(json.dumps(obj, ensure_ascii=False))
|
||||
sys.stdout.flush()
|
||||
# ⚠️ 2026-09-16 修复(**根因**):必须走 **`sys.stdout.buffer` 写 bytes**,⛔ 不能走文本层
|
||||
# (`sys.stdout.write(str)`)。
|
||||
# 实证:宿主 spawn 本脚本时 stdout 编码**不保证是 UTF-8**(本机 `PYTHONUTF8=1` 在 hook 环境下
|
||||
# 不保证生效),而 deny 文案里含 `⛔` / `🔐` 等字符 ⇒ 文本层写抛 `UnicodeEncodeError` ⇒
|
||||
# 异常冒泡、**stdout 为空** ⇒ 宿主**收不到 deny** ⇒ **静默放行**。
|
||||
# 而 `hook_log()` 已经把 `PreToolUse-deny` 写进日志 ⇒ 表现成 **「日志里有 DENY,但拦不住」**
|
||||
# (2026-09-16 受控自测:无锁时 Write 文档库 ⇒ 文件真被创建)。
|
||||
# 对照:`bash-output-guard.py` 用 `sys.stdout.buffer.write(bytes)` ⇒ **实测拦得住**。
|
||||
# 📌 教训:本脚本的 `stdin` 早前已按 buffer 加固(见 main 顶部注释),**stdout 漏了** ——
|
||||
# 「读写要同时加固」,只修一半等于没修。
|
||||
data = json.dumps(obj, ensure_ascii=False).encode('utf-8')
|
||||
try:
|
||||
sys.stdout.buffer.write(data)
|
||||
sys.stdout.buffer.flush()
|
||||
except Exception:
|
||||
try:
|
||||
sys.stdout.write(data.decode('utf-8', 'replace'))
|
||||
sys.stdout.flush()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
LOG_FILE = os.environ.get(
|
||||
@@ -120,6 +138,15 @@ def main() -> None:
|
||||
tool = payload.get("tool_name")
|
||||
event = payload.get("hook_event_name") or payload.get("hook_event") or ""
|
||||
|
||||
# ★ 入口即留痕(2026-09-16 加)—— 与 stop-dialog-guard.py / skill-load-guard.py 同款。
|
||||
# 为什么不只记 SessionStart 与 deny:2026-09-16 实测 —— 重启后本钩子**一行都没写**,
|
||||
# 当时无法区分"没被宿主调用"与"被静默放行",只能靠猜(最后查明:SessionStart 的
|
||||
# `matcher: "startup"` 不匹配"恢复会话",钩子压根没被执行)。
|
||||
# 留痕里带上**实际收到的字段名**(keys):下次宿主字段一变,日志里立刻能看出来,
|
||||
# 而不是等某天发现守卫早已失效。低频:每次调用一行。
|
||||
hook_log("entry", "event=%s|tool=%s|keys=%s" % (
|
||||
event or "?", tool or "-", ",".join(sorted(payload.keys()))[:220]))
|
||||
|
||||
# ── SessionStart:只提示(该事件的输出只给用户看,不会进 Agent 上下文)──
|
||||
if event == "SessionStart" or (tool is None and "source" in payload):
|
||||
src = payload.get("source", "?")
|
||||
|
||||
Reference in new issue
Block a user