Skip to content

docs(claude-code-hooks): land two rounds of independent-review fixes (conflict with #295 resolved) - #296

Merged
daymade merged 5 commits into
mainfrom
integrate/hooks-skill-plus-docs-cleaner
Aug 15, 2026
Merged

docs(claude-code-hooks): land two rounds of independent-review fixes (conflict with #295 resolved)#296
daymade merged 5 commits into
mainfrom
integrate/hooks-skill-plus-docs-cleaner

Conversation

@daymade

@daymade daymade commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Lands the claude-code-hooks work that has been sitting unmerged on perf/history-search-date-prefilter (e9c8235, never had a PR), with its conflict against main resolved.

Authorship: the substantive content here is not mine — it is two rounds of independent-review work by another session (5ab1dca, e9c8235). My contribution is the merge resolution and verification.

Why it needed a new branch

perf/history-search-date-prefilter was left untouched on purpose — another session may still be working on it, so nothing was rebased or force-pushed. This branch is that branch plus a merge of main.

Two of its four commits (7ec58f7, 2ade890, docs-cleaner v1.7.0) turn out to be already in main under different SHAs, so the net addition here is only the claude-code-hooks bundle:

 claude-code-hooks/.security-scan-passed        |   4 +-
 claude-code-hooks/SKILL.md                     | 179 ++++++++++++++++---
 claude-code-hooks/references/hook_patterns.md  |  61 ++++++-
 claude-code-hooks/references/hook_pitfalls.md  |  44 +++--
 claude-code-hooks/scripts/test_hook.sh         |   6 +-

The conflict, and how it was resolved

Exactly one file conflicted — claude-code-hooks/SKILL.md — at the one anchor #295 predicted in its own body: both sides append nested sub-bullets under rule 4's "If the guard needs a release valve, make it a human gate, not an env var."

The three-way base for that hunk is empty: both sides are pure additions, neither modifies the other's text. They are also complementary rather than competing — this branch's bullets are about the Tier-0 human gate's mechanics (/dev/tty is unusable per the official docs; a gate that outlives the hook timeout fails open; the in-UI permissionDecision: "ask" channel), while #295's is explicitly scoped to below Tier-0 and opens by restating that the Tier-0 rule does not bend.

Resolution: keep both sides in full, this branch's three bullets first, #295's fourth. Nothing was dropped, reworded, or reordered within either side.

Verification

🤖 Generated with Claude Code

daymade and others added 5 commits August 14, 2026 20:28
docs-cleaner 从「合并冗余文档」扩成文档治理工具:新增 Mode 1(改动后治理:
从改动而非仓库定范围、分清哪个文件"定义"事实哪个只是"提到"、实现是证据但
不是改代码的授权、动手前先定 disposition、改一处前先找齐所有副本),
原有四阶段合并流程完整保留为 Mode 2。两者共用新的 Drift Test 三问。

两处会自我盖章的检查换成可证伪的:勾选式 Value Preservation Checklist →
按处置给逐项证据;计划里的 "Value preserved: 100%" → 执行后填的带分母计数。

七轮 fresh-context 独立审阅(22/13/13/15/11/14/8)。发现数没收敛但缺陷性质
收敛了:1-2 轮是内容缺失,3-4 轮是我新写的命令本身错的,5-7 轮是我为修上一轮
而写的规则可以被"正在做错的 agent"合规执行。正解反复是删掉而不是修补——
自写检索脚本→ripgrep、自写死链管线→lychee、机械计数网→诚实说明。

故意推翻旧版一处(已在 CHANGELOG 正文点名,回归审计记 true_gap_fixed):
旧版 worked example 教人把测试结果当 one-time record 删掉,而新规则把
dated measurement 列为审计痕迹类、禁止安静删除。示例改用重复内容。

闸门:quick_validate 通过;回归审计 46 候选全部分类验证通过
(baseline git-ref:937a84d);security_scan 通过 + 人工通读无私有数据。
审阅档案在作者私有知识库(含第 6 轮 reviewer 报告英文原文逐字存档)。

--- 顺带提交的并行 session 改动(非本次工作,为避免滞留本地一并带上)---
- daymade-claude-code/claude-code-history-files-finder/scripts/analyze_sessions.py
- daymade-claude-code/claude-code-history-files-finder/tests/test_analyze_sessions.py
- .claude-plugin/marketplace.json 里 daymade-claude-code 1.43.0 → 1.44.0
  ⚠️ 该版本号 bump 目前没有对应的 CHANGELOG 条目,需由那条工作线补齐。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A74M2erSjc3cHuFnADFsmS
轴 ① 报告是从其 transcript 打捞的(它做完了但没发回来)。裁决:
11 RESOLVED(3 条带新缺陷、2 条带残留)+ 3 PARTIAL,零条 RELOCATED。

三条新缺陷,都是我第 6 轮修复的副产品:
- B5-NEW(静默错误输出):我为消除「正确合并的段落被误报为删除」这个假阳性
  而加的「Keep 已合并」软路径,没有绑定到任何更早的产物——于是它由
  **刚刚搜索落空的那一方在检查时自己选**。一个 Keep 段被顺手改写、后果子句丢了,
  只要改标成「已合并」就能换宽松判据、对着削弱后的句子拿到命中。硬闸变自选软闸,
  且只在它刚抓到东西时才打开。修法:该行仅在合并于重写前已记录时可用,否则 miss 就是 miss。
- B3-NEW:清单扩到含 Delete 段后,分母里混进了按构造就不会幸存的项,
  「all N survived」变成不可达。修法:分母只算 Keep/Condense,Delete 项单列。
- A3-NEW:与另一条轴独立命中同一处(示例表演示本节禁止的删除),上一个 commit 已修。

三条 PARTIAL + 两条残留,全部靠恢复或如实承认限制解决,未发明新机制:
- A5:恢复我重写时删掉的三个粒度锚点(passage 出现 8 次却无处定义)
- B2:两类子句白名单标成下限而非边界,点名漏网的排序约束/作用域限定词/散文阈值
- B6:撤回「Phase 3 交给人来兜底」——它只拿到结构和行数,兜不住判断失败
- A4:优先级扩到 Q1(带日期的计数会被 Q1 重算成今天的数,破坏路径与 Q2 不同)
- A7:前提已死的单个 section 归 Delete 但理由写死前提,且必须在计划里点名给 owner

闸门:quick_validate 通过;回归审计 46 候选全部分类验证通过;
security_scan 通过 + 人工脱敏扫描零命中。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A74M2erSjc3cHuFnADFsmS
三条独立失败轴的审阅(自洽性 / 契约 vs 官方文档 / 对增长政策的忠实度),
20 条实质发现,其中 6 条带可复跑实测。档案:PKM
next/_meta/skill-reviews/claude-code-hooks/independent-review-bundle-20260814.md
(commit 198c85bc,含三段 prompt 逐字、逐条 disposition、未验证项)。

⚠️ 刻意推翻一条既有处方(DELIBERATE REVERSAL,非副作用)
  rule 4 不再把「/dev/tty 手输 YES」列为人类闸门的第二通道。官方文档明确:
  hook「run in their own session without a controlling terminal」「can't open
  /dev/tty」。后果是 Pattern B 的两通道实为一个,无 GUI 环境永远无法批准。
  本机佐证:某生产 guard 带通道标签的审计日志 1801 条中,tty 通道确认放行 0 次、
  弹窗通道 361 次。(日志只证明它从未担任过确认通道;"不可能"由文档承担。)
  osascript 保留为处方。文档另有 permissionDecision:"ask" 的 in-UI 通道,
  但它在 bypassPermissions/auto-accept 下是否仍弹出未经验证——而那正是 Tier-0
  闸门的全部威胁模型,故只提及并标注未验证,不改推荐。

两处实测矛盾(照着做会造出规则自己禁止的东西)
- rule 5 与 rule 7 对「状态读不到时往哪边失败」给相反命令,而 rule 7 引用
  rule 5 当权威。实测:mechanism 3 片段放进本 bundle 自己的 Stop 骨架、
  TMPDIR 不可写,连跑 5 次全 exit=2,N 恒为 1 —— 正是 rule 7 上方那句话禁止的
  无变体循环,且失败方向由一个该片段并不携带的 set 标志决定。
  修法:判据压过标签,两侧都给出 mechanism 2/3 的成品答案。
- pitfall #11 标着 Fix 的 bullet 仍给已被取代的文本切分 cmd.split("\n"),
  实测误杀本文件自己 harness 的 quoted-multiline 行(want 0 got 2);订正在
  17 行之下且未标注前者作废。test_hook.sh 内 :89 与 :93 相隔 4 行直接互斥,
  且 :89 声称「Pattern A / walker 都做文本切分」是事实错误(两处 ship 的都是
  split_shell_lines)。三处一并收口。

骨架改为教生产形态(pitfall #22 此前只活在 reference)
  INPUT=$(cat) → builtin IFS= read -rd '',并在付 python3 成本前加 builtin case
  粗筛。实测(探针先做阳性标定):无关输入下 python3 调用 2 → 0。
  同时写明两条边界:本骨架对无关输入本就 fail-open 故加粗筛只改成本不改语义,
  而 fail-closed guard 必须先读 #22 的完整门;以及注册层的 if 字段能让 hook
  进程根本不启动,但它 fails open,只能当成本优化不能当闸门。

契约对齐(官方文档已搬家并扩容至 269KB,逐条自核)
- SessionStart 任何退出码都无法 block(此前写成「always exit 0 才不会 block」,
  建议对、机制错);且它有 matcher(startup/resume/clear/compact/fork),
  hook_patterns.md 此前断言它没有。
- 「其它退出码=非阻塞错误」补限定:仅在 stdout 无合法 JSON 时成立。
- matcher 求值规则此前完全缺失:仅含字母数字 _ - 空格 , | 时是精确串,
  否则是无锚定正则 —— Edit.* 会同时匹配 NotebookEdit,mcp__memory 匹配不到
  任何东西。这是静默失配面,每次注册都要消费。
- 人类闸门补 timeout 会 fail-open 的警告(超时的 hook 不阻断工具调用,
  未应答的弹窗不会变成「否」而是放行)。
- 两处「这个没有文档」的元断言已过期,改为外科手术式订正:保留计数器归零
  条件等二进制逆向所得(文档至今只说 "without progress" 未定义),只撤回
  「文档里没有」的部分并标注其认识论状态。

其余订正:#25 归属(它挡的是只读 git config 查询,不是卸载命令);
group-name harness 的描述与实际不符(无 says rows、无 stop_hook_active 反循环行,
且需传 hook 路径为 $1);Pattern C 空 hooks 目录下的假告警(补 nullglob,
双向标定:空目录静默、真悬空 symlink 仍抓得到)及其作用域不自洽(改用
CLAUDE_CONFIG_DIR 与同段 settings 检查对齐);1 处 HTML 实体转义。

闸门:bash -n 双脚本过;harness 对真实 hook 回归 8 pass/0 fail;quick_validate 过;
security_scan 过并刷新 marker;description 未动(1009/1024,已知其 UserPromptSubmit
那句过宽但无余量,正文由 #30 限定,已记录在档);public repo L4 语义自查零命中。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A74M2erSjc3cHuFnADFsmS
5ab1dca 的独立复审(新 agent,只审那次 diff)报了 13 项,其中 8 项确认并修复。
最严重的是我自己造的:

🔴 新加的 case 快筛不是 superset,照 SKILL.md 的话抄进 Pattern A 会把拦截变放行
   实测:TRIG''GER -x —— bash 把引号拼接消掉后执行 TRIGGER,而裸 substring
   匹配不到,于是 Pattern A 从 exit 2 翻转成 exit 0(完全绕过),
   同时 test_hook.sh 仍报 21 pass/0 fail(没有任何一行带拼接触发)。
   Pattern A 自己的注释早写着「fast path 必须是 SUPERSET:先 de-splice 再查,
   false negative 就是完全绕过」——而我把裸过滤放在了那道兜底之前,让它永不可达。
   而我还专门写了「before you copy the case line anywhere else」,等于主动邀请。
   修:caveat 由两条改三条,新增的那条排在最前;首选处方改为「过滤 splice 碰不到的
   东西」(JSON key / 工具名),de-splice 作为次选——因为需要自己写对转义的过滤器
   本身就是会静默写错的东西。两种形态均实测。

🔴 rule 7 新加的处方按字面执行会让 guard 一次都不响
   我写的是「把 || exit 0 写进状态读取那步」。实测:counter 文件首次运行本就不存在
   → cat 失败 → 直接 exit 0 → 在完全健康的环境里永不触发。失败的那步是**写**。
   修:处方改为守卫写那步,并明写读那步必须保持现状。实测五轮:
   守卫写 → 可写 2,2,2,0,0 / 不可写 0,0,0,0,0(两侧都对);
   守卫读 → 两侧都是 0,0,0,0,0(guard 死掉)。

其余六处:
- rule 4 撤回了 /dev/tty,但 Pattern B 原封不动还在教整套两通道实现(且它未改动的
  注释把「存在但打不开」当沙箱特例,与新的绝对断言互相矛盾)。补显式警告块 +
  代码内警告,说明留着它是因为硬拦是安全方向,不是背书。
- 骨架改用 builtin read,但 5 个 runnable pattern 仍是 $(cat)。转换非纯机械
  ($(cat) 丢 NUL 保留其后,read -d '' 在首个 NUL 截断;blocking guard 还需 #22
  的载荷门),故加显式分歧说明+指向 #22 配方,未硬改,并记为未完成。
- 断链:我写的「escape routes 在 #1 的清单」实为 #3(#1 是 stdin 被 heredoc 吃掉)。
- 我写的「three rows the shipped harness asserts」不成立——harness 里只有
  wrapper-timeout 一行,实跑 compact walker 是 20 pass/1 fail 不是 3 fail。
  三种命令形态的断言是真的(逐条探针验过),改的是口径。
- 审计日志数字重核:360 不是 361;且 360 = 236 真放行 + 124 拒绝/超时,
  原文把两者并列会被读成放行数;日志是多个 guard 共写不是「a production guard's」;
  生产里三个 hook 实现了 tty 通道。tty=0 的正确含义是该分支从未被进入
  (macOS 上弹窗必先应答),故降级措辞为「与本地观察一致」而非「佐证」。
- 「the reference now lists many more」在本 bundle 里指不到东西,补 official + 说明。
- hook_patterns.md 的「Pattern C below」实际在其上方 265 行。
- 契约节「anything else = non-blocking error / SessionStart must always exit 0」
  两个半句同步限定。

闸门:harness 回归 8 pass/0 fail;quick_validate 过;security_scan 过并刷新;
audit_skill_regression verify 通过(22 候选全分类,含 /dev/tty 的
DELIBERATE REVERSAL 与 test_hook.sh 的 semantic_review);
「Three caveats」与实际 3 条 bullet 计数一致。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A74M2erSjc3cHuFnADFsmS
…-plus-docs-cleaner

# Conflicts:
#	daymade-claude-code/claude-code-hooks/SKILL.md
@daymade
daymade merged commit 7a8145a into main Aug 15, 2026
4 checks passed
@daymade
daymade deleted the integrate/hooks-skill-plus-docs-cleaner branch August 15, 2026 13:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant