在 #3430(stash 共享栈)实现过程中读 .claude/settings.json 的钩子注册时发现,记录一下,不在 #3430 的范围内改。
现象
.claude/settings.json 里 guard-main-checkout.sh 的 matcher 是:
"matcher": "Edit|Write|NotebookEdit"
也就是说它只拦工具化的文件写入。同一个写操作换成 Bash 就完全不经过这个钩子:
sed -i 's/foo/bar/' packages/fields/src/x.tsx
cat > packages/fields/src/x.tsx ... EOF
tee / printf / python -c ... 同理
在共享主 checkout 里这样改文件,钩子一声不响,而 CLAUDE.md / AGENTS.md 给出的心智模型是「PreToolUse 钩子强制此规则」。#3430 记录的正是同一个心智模型的另一个洞(worktree 隔离盖不住 refs/stash),两者同族:声明的强制范围 > 实际的强制范围。
为什么标 finding 而不是缺陷
今天没有用户会踩到,也没有证据表明有 agent 真的靠 Bash 绕过去写过共享 checkout —— agent 写文件基本都走 Edit/Write。属于「防线比宣称的窄」这一类观察,是否值得补由 PM 定级。
如果要补,可能的做法(未实现,仅备选)
相关
在 #3430(stash 共享栈)实现过程中读
.claude/settings.json的钩子注册时发现,记录一下,不在 #3430 的范围内改。现象
.claude/settings.json里guard-main-checkout.sh的 matcher 是:也就是说它只拦工具化的文件写入。同一个写操作换成 Bash 就完全不经过这个钩子:
在共享主 checkout 里这样改文件,钩子一声不响,而 CLAUDE.md / AGENTS.md 给出的心智模型是「PreToolUse 钩子强制此规则」。#3430 记录的正是同一个心智模型的另一个洞(worktree 隔离盖不住
refs/stash),两者同族:声明的强制范围 > 实际的强制范围。为什么标
finding而不是缺陷今天没有用户会踩到,也没有证据表明有 agent 真的靠 Bash 绕过去写过共享 checkout —— agent 写文件基本都走 Edit/Write。属于「防线比宣称的窄」这一类观察,是否值得补由 PM 定级。
如果要补,可能的做法(未实现,仅备选)
Bashmatcher 再挂一个钩子,识别常见的写文件命令(sed -i/tee/> path重定向 /cat > path)并按目标路径判断是否在 linked worktree 里 —— 与 [process] git worktree 共享 refs/stash:并行 agent 之间 stash push/pop 会互相顶掉在途改动 #3430 新增的guard-shared-stash.sh同一形状([process] git worktree 共享 refs/stash:并行 agent 之间 stash push/pop 会互相顶掉在途改动 #3430 的 PR objectui#3433 已经把Bashmatcher 建起来了,可以复用其分段/引号解析)。相关