提交前确认 · Pre-submission checklist
问题类别 · Category
Bug(hooks 机制)
涉及的 Agent 框架 · Agent framework
ZCode 桌面版(Windows)——PreToolUse hooks(用户级 config 注册,Bash matcher)
严重程度 · Severity
高:PreToolUse 是安全护栏通道(拦截危险命令/保护文件写入),裁决被丢弃 = 护栏间歇失效,且失效形态对上层不可见(命令静默执行成功)。
复现频率 · Reproducibility
间歇性:同会话同载荷,13 次应拦事件丢 3(≈23%,单审计窗统计,样本小非确率)。单次不可确定性复现,需批量统计复现。
问题描述 · Description
PreToolUse hook 脚本对命中规则的 Bash 工具调用返回 exit 2(block 语义)+ stderr 拦截理由时,ZCode 平台层间歇性不采纳该裁决——对应命令仍被执行。hook 本体已排除嫌疑(证据四链见下),丢失发生在平台对 hook 裁决的分发/合并处理层。
复现步骤 · Steps to reproduce
- 注册一个 PreToolUse hook(Bash matcher),逻辑为无条件拦截:读 stdin 后 stderr 输出一行理由,
process.exit(2);同时在 hook 入口写一行心跳日志(时间戳+pid),用于区分「hook 没被拉起」与「裁决被丢弃」。
- 会话中连续发起 N 次(建议 ≥15)任意 Bash 命令。
- 三方对账:hook 心跳日志(每次都该在场)/ 拦截台账(hook 自记)/ 工具执行结果。
期望表现 · Expected behavior
exit 2 + stderr → 该次工具调用被阻止、命令不执行、拦截理由注入模型上下文——每次都应如此。
实际表现 · Actual behavior
约 23% 的命中事件中命令仍被执行。证据四链(单次实例,2026-10-02T07:03:50.596Z,摘自审计台账):
- hook 进程被拉起:心跳日志在场
{ts:07:03:50.596Z, pid:8900}(同刻并行另一 hook 07:03:50.484 亦在场);
- stdin 已送达:hook 内读异常/空串两路径均有留痕逻辑(在位),该时刻零记录;
- 同载荷直调 hook 脚本 100% exit 2(20/20 对照);
- 命令仍执行:exit 0、效果落盘。
对照面:同会话 Edit 工具路径(插件层 hooks.json 注册的 PreToolUse)零丢失;config 层注册的多个 Bash 闸有采纳有丢失——间歇、非按闸/按层恒定。
ZCode 版本 · ZCode version
3.14.4.7912(案发窗口与当前实测同版)
设备 / 系统 · Device / OS
Windows x64(10.0.26200),桌面版
截图 / 录屏 / 日志 · Screenshots / Recordings / Logs
可按需补充心跳日志/拦截台账/工具结果三方对账原文(脱敏后)。定位线索供参考:app 内部见 hook 相关 60s 默认超时与 hookInvocation 遥测 schema,但本机 ZCode 数据库中无对应落地表——建议排查 PreToolUse 裁决合并/分发层(是否超时竞态、裁决合并选择性采纳、或遥测丢写同源)。
提交前确认 · Pre-submission checklist
问题类别 · Category
Bug(hooks 机制)
涉及的 Agent 框架 · Agent framework
ZCode 桌面版(Windows)——PreToolUse hooks(用户级 config 注册,Bash matcher)
严重程度 · Severity
高:PreToolUse 是安全护栏通道(拦截危险命令/保护文件写入),裁决被丢弃 = 护栏间歇失效,且失效形态对上层不可见(命令静默执行成功)。
复现频率 · Reproducibility
间歇性:同会话同载荷,13 次应拦事件丢 3(≈23%,单审计窗统计,样本小非确率)。单次不可确定性复现,需批量统计复现。
问题描述 · Description
PreToolUse hook 脚本对命中规则的 Bash 工具调用返回 exit 2(block 语义)+ stderr 拦截理由时,ZCode 平台层间歇性不采纳该裁决——对应命令仍被执行。hook 本体已排除嫌疑(证据四链见下),丢失发生在平台对 hook 裁决的分发/合并处理层。
复现步骤 · Steps to reproduce
process.exit(2);同时在 hook 入口写一行心跳日志(时间戳+pid),用于区分「hook 没被拉起」与「裁决被丢弃」。期望表现 · Expected behavior
exit 2 + stderr → 该次工具调用被阻止、命令不执行、拦截理由注入模型上下文——每次都应如此。
实际表现 · Actual behavior
约 23% 的命中事件中命令仍被执行。证据四链(单次实例,2026-10-02T07:03:50.596Z,摘自审计台账):
{ts:07:03:50.596Z, pid:8900}(同刻并行另一 hook 07:03:50.484 亦在场);对照面:同会话 Edit 工具路径(插件层 hooks.json 注册的 PreToolUse)零丢失;config 层注册的多个 Bash 闸有采纳有丢失——间歇、非按闸/按层恒定。
ZCode 版本 · ZCode version
3.14.4.7912(案发窗口与当前实测同版)
设备 / 系统 · Device / OS
Windows x64(10.0.26200),桌面版
截图 / 录屏 / 日志 · Screenshots / Recordings / Logs
可按需补充心跳日志/拦截台账/工具结果三方对账原文(脱敏后)。定位线索供参考:app 内部见 hook 相关 60s 默认超时与 hookInvocation 遥测 schema,但本机 ZCode 数据库中无对应落地表——建议排查 PreToolUse 裁决合并/分发层(是否超时竞态、裁决合并选择性采纳、或遥测丢写同源)。