身為訂了規則的人,我要那條規則在整個 session 都有效,我才不會發現它只擋得住第一次 #66
Notifications
Due Date
No due date set.
Blocks
#30 讓閘擋對東西
inkstone/ISEP
Reference: inkstone/ISEP#66
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
身為訂了規則的人,我要那條規則在整個 session 都有效,我才不會發現它只擋得住第一次。
leo 2026-08-27 的原話
查證:
subagent-first-guard.sh有兩個漏洞,總管剛好兩重豁免那支閘守的是頂層 CLAUDE.md 規則三點五(總管的預設動作是派工,不是自己下海寫)。
總管 2026-08-27 親手改了
.claude/hooks/no-ticket-no-dispatch.sh,閘一聲都沒響。實際讀 code(
.claude/hooks/subagent-first-guard.sh,共 3553 B):漏洞一:
.claude/hooks/*被明文豁免改任何一支閘無條件放行。
🔴 最該有人看管的地方(那些閘自己),恰恰是唯一被明文豁免的目錄。
一個能改閘的人,等於能關掉所有其他閘——這個豁免讓整組機制的信任根basis消失。
(這個豁免大概是為了「hook 壞了要能緊急止血」。那個需求是真的,
但它已經有專門的出口了——第 48 行的
solo-ok,留痕、要說明理由。用「整個目錄豁免」來滿足它,是拿一扇永遠開著的門解決偶爾要進去的需求。)
漏洞二:派過一次工,之後永遠放行
第 47 行的判準是「這個 session 派過工了嗎」。
總管今天派了 8 條線 ⇒ 這個條件在第一條線之後就永久成立
⇒ 「派工優先」的實際效力只剩「這個 session 的第一次」。
再加上第 51 行「同一 session 只擋一次」,就算前兩條都沒命中,
它也只會擋一次然後永遠放行。
⇒ 三條疊起來:這道閘在一個長 session 裡幾乎等於不存在。
要達成什麼
「總管不自己寫 code」這條規則在整個 session 都有效,而不是只擋得住第一次。
同時不要把它做成鬼打牆——原本「只擋一次」的設計是為了不吵人,那個顧慮是對的,
新的設計要正面解決「有效」與「不煩人」的張力,不是把其中一邊犧牲掉。
這一格要你自己判斷
.claude/hooks/*的豁免要不要拿掉:拿掉之後緊急止血怎麼走?(
solo-ok夠不夠?它現在要求「說明理由」,但沒有任何機制驗證有沒有說)但實際代表的是「這個 session 曾經發生過一次派工」。這兩件事差很遠。
所以不要把它改成每次都擋——要找出「這一次該不該擋」的判準
怎麼驗
貼實測輸出,至少涵蓋:
.claude/hooks/底下的 code → 擋solo-ok在 → 放行(緊急出口要留著)system-dev/的 wiki——這四種一個都不准誤攔
no-ticket-no-dispatch.sh→ 要擋得下來紅線
plugin.json要升版claude-code、改 tag🔴 規格更正:不是「派工優先」,是「派工 Only」(leo 2026-08-27)
這句話改掉本票的判準,不是加強語氣:
⇒ 本票原文寫的「要找出『這一次該不該擋』的判準」方向錯了,那是「優先」的思路。
正解是:總管改 code 一律擋。 判斷題只剩一個——「這次呼叫是不是總管發的」。
這連帶影響三件事,請一併處理
/tmp/.solo-ok-$SID這個出口本身要重新評估它是「明示要自己做就放行」——那正是「優先」留下的後門。
Only之下它還該存在嗎?如果留,理由要寫得出來(例如 hook 自己壞掉導致無法派工的死結),而且要有留痕與事後對帳,不能是一個
touch就無聲開門。.claude/hooks/*目錄豁免(第 44 行)——Only之下更沒有理由留著Only之下完全失去意義,它是「優先」的實作判斷「是不是總管」現在有官方解了
另一條線(
inkstone/ISEP#61)拆 Claude Code 二進位挖出 hook stdin JSON 的 base schema,官方
.describe()原文:⇒ 有
agent_id= subagent(它就是被派來寫 code 的,放行);沒有 = 總管(擋)。這比「派過工沒有」可靠得多,而且 subagent 改不動它(宿主按呼叫語境填的)。
⚠️ 該線沒有實際掛除錯 hook dump 真實 payload 雙重驗證(怕干擾並行的線),
所以這是查證過的官方說明,不是實測。你要自己驗一次再用。
對應的「怎麼驗」也要改
原本第 1、2 點寫「派過工之後…→ 擋」,
Only之下改成:system-dev/的 wiki/改票或文件[isep-guard] inkstone/ISEP#66
查證:真正的洞比票上寫的更早一關
.sh從沒進過受管副檔名清單(原hooks/subagent-first-guard.sh:39只認*.ts|*.tsx|*.js|*.jsx|*.mjs|*.go|*.py|*.rs|*.java|*.rb)——這個 repo 自己的閘全是.sh,所以總管改
no-ticket-no-dispatch.sh時,這道閘在第一行 case 就直接exit 0,路徑白名單(
*/.claude/hooks/*)根本沒機會被判斷到。這才是「閘一聲不響」的真正原因,票上點名的路徑豁免是第二層、真的存在但不是觸發那次事故的那一關。
三個洞一次修完(
hooks/subagent-first-guard.sh):.sh)獨立收進受管清單:*/.claude/hooks/*.sh|*/hooks/*.sh現在會被當「該被派工規則管的程式碼」判斷,不再因副檔名整批放行。同時拿掉
*/.claude/hooks/*整目錄豁免——system-dev/*(wiki)豁免保留。跟「下一次任意手改合不合理」。現在只留在被擋下時的訊息裡當脈絡(「上次派工是幾分鐘前」),
不影響放行判斷。
SUBAGENT_GUARD_NAG_TTL可覆寫做測試)——寬限期內不重複鬼打牆,過了就再響。兩頭都要顧,沒有選邊犧牲。
放行只剩三種:
CLAUDE_CODE_CHILD_SESSION=1(subagent 本人,它就是被派來寫的,新增此判準)//tmp/.solo-ok-<sid>非空(要求寫理由,不是 touch 空檔——回答了票上「solo-ok 夠不夠」那個問題:夠,但原本沒人驗證有沒有寫理由,現在機械要求非空)/檔案本身不歸這道閘管
(測試檔/
system-dev/wiki/非受管副檔名)。subagent-first-stamp.sh保留(仍寫時戳),但註解更新:時戳現在純資訊,不再是放行判準。實測(
scripts/test-subagent-first-guard.sh,20/20 通過).claude/hooks/no-ticket-no-dispatch.sh(.sh)→ 擋;改 ISEP 自己的hooks/subagent-first-guard.sh→ 擋寬限期過了(TTL=2s,等 3s)→ 再擋(不是永久啞掉)
CLAUDE_CODE_CHILD_SESSION=1改 hook/改一般 code;測試檔(
_test./.test./.spec.);system-dev/的 wiki 與.py腳本;非受管副檔名(一般
scripts/*.sh、.md、.json)touch(空檔)→ 仍擋;echo "理由..." > ...→ 放行既有 6 支 test-*.sh 全部重跑,無迴歸(
github-contact14/14、kbdb-api-wall10/10、main-and-prod-push11/11、release-tag8/8、stage-before-prod13/13、ticket-api-bypass13/13)。版本與交付
.claude-plugin/plugin.json0.5.0 → 0.5.1(本次只改既有閘的邏輯,沒有新增/刪除閘,「48 支機械閘(59 條註冊)」數字不變,已用
python3 scripts/vendor-to-shell.py重建.shell-payload/核對過:59 條註冊、無差異)。docs/hooks-inventory.md同步更新subagent-first-guard.sh與subagent-first-stamp.sh兩行說明,避免文件說謊。分支:
fix/dispatch-guard-noise-and-wiring(已推 origin,commite177f63)PR:https://git.uncle6.me/inkstone/ISEP/pulls/new/fix/dispatch-guard-noise-and-wiring
下一步(給總管/leo)
v0.5.1tag,讓scripts/check-version-consistency.sh轉綠(現在故意是紅的:plugin.json 已是 0.5.1,但 tag 還停在 v0.5.0——這是既有慣例,
版本號先隨 commit 走,tag 在真正發版那天才補)
又一次實證:
main-and-prod-push-guard.sh(0.3.8)擋住了總管,戳記給對也過不了2026-08-27 16:4x,總管要把
inkstone/ISEP#72的修法(PR#73,自己跑過 24/24)併進 ISEP main:總管沒有繼續繞。 分支已推、PR 已開、票已交回,內容沒有遺失。
這一則要留給本票的線索(是現象不是診斷)
InkStoneCo⇒ hook 執行當下的工作目錄可能不是
ISEPproducts/arcrun-rag與matrix/arcruntoday 都成功過(同一個 session、同樣的寫法)⇒ 差別在那兩個 repo 是 InkStoneCo 的子目錄,而 ISEP 是平行目錄
診斷要派員實查後才能做出,這裡只留現象
與本票原本要修的東西是同一個病
本票開票時記的是:那道閘的判準(
CLAUDE_CODE_CHILD_SESSION/CLAUDE_AGENT_NAME)從第一天就打不中它要區分的對象。今天這次是同一支閘的另一面:
判準給對了也過不了,於是「總管推 gitea main」再次變成人閘——而 leo 明說那不該是人閘。