fix/literal-absolute-paths-for-hooks-wiring
develop
skills/hooks-install/SKILL.md
readlink
[ -d ]
references/behaviors.md
plugin.json
.claude-plugin/plugin.json
.codex-plugin/plugin.json
ls
JSC_HOME
readlink -f "$JSC_HOME/current"
/current
check-behaviors.sh
lint-scripts.sh
lint-frontmatter.sh
ste100-lint.sh
wire-cli.sh status claude
status=wired
無人看管的輪次會在第一支腳本就被擋下,整輪還沒開始就結束。2026-09-02 到 09-03 以非互動模式比照排程環境實測七種寫法,結論很乾淨:權限層比對的是還沒展開的字面字串,帶變數或帶波浪號的路徑一律解不出來,一律要人核准;路徑中段的萬用字元也不匹配,所以帶版本號的快取路徑放不進允許清單。連 readlink、ls 這種只讀指令都要有自己的規則。放寬允許清單救不了這件事,只有把路徑寫成字面絕對值才跑得動。 技能因此多兩節。路徑守則寫明每一次腳本呼叫都要是字面絕對路徑,並說清楚為什麼不能為了可攜性換回變數寫法——變數寫法買不到可攜性,只買到一輪還沒跑到第一階段就死掉。前置步驟把可攜性挪到執行期:兩個根目錄各以 readlink 解一次,只在這裡解,之後不重解,也不為此新增腳本。主代理人解完把兩條字面路徑交給每一個 sub agent,sub agent 自己不解。技能內九處腳本呼叫都改成由這兩個根目錄開頭。 兩條 readlink 各自在同一步用 [ -d ] 查過印出來的目錄真的存在。JSC_HOME 沒設時第一條會印出 /current、結束碼 0,非空又是絕對路徑,只查前三項擋不下來。 解兩個根目錄不是重複。連結農場根目錄給跨 domain 呼叫用;jsc-hooks 的實體根目錄只給接線腳本用,而這一條的理由與權限無關:那支腳本從自身位置推出自己的根目錄,又會改寫自己正踩著的那條連結。走連結跑下去,連結會被指向自己,全機器的 hook 一起失效——這件事實際發生過。 存放庫自帶的 hook 設定檔刻意保留變數寫法,技能文件也把這個例外寫明。那是檔案內容,由 hook 自己的 shell 在執行當下展開,不經過權限層,也不是誰在提示裡打出來的路徑;改成實體路徑等於把某一台機器的路徑寫死進要發佈的檔案。 行為清單的 hooks-install 四列跟著校準。 受影響的是每一個跑 hooks-install 的人,最直接的是排程觸發、沒有人在旁邊核准的那些輪次。
行為清單檢查拿 HEAD 的內容跑就過不了,它點名 repair 那一列的可驗證跡象沒寫到收尾的 skill-end 事件。這是既有欠帳,跟這一批的路徑處理沒有關係,所以單獨一筆,之後要回退哪一邊都不會牽連另一邊。 補上的內容照準則寫:收尾在本機事件流留下這一輪的 skill-end,status 從 ok、blocked、failed、degraded、aborted 五個裡取一個,中途停下的那幾輪也照寫——只有 start 沒有配對的 end,會被讀成中斷。 受影響的是驗收 repair 有沒有跑完的人,還有把行為清單檢查掛在流程裡的每一個存放庫。
hooks-install 的路徑處理與行為清單都變了,版號要帶得出這批變更,版本前置檢查才會要求機器端更新。 三份 manifest 由 sync-skill-manifest.sh 同步,只動版本欄位,內容一致。 受影響的是靠版號判斷要不要更新的每一台機器。
No dependencies set.
The note is not visible to the blocked user.
摘要
變更內容
skills/hooks-install/SKILL.mdreadlink各自用[ -d ]查過目錄存在;並寫明存放庫自帶的 hook 設定檔為什麼刻意保留變數寫法references/behaviors.mdplugin.json.claude-plugin/plugin.json.codex-plugin/plugin.json設計重點
readlink與ls都要有自己的規則;路徑中段的萬用字元不匹配,所以帶版本號的快取路徑放不進允許清單。放寬允許清單不是解法,寫成字面絕對值才是。readlink解一次,只在前置步驟解,不重解、不為此新增腳本;主代理人解完把兩條字面路徑交給每一個 sub agent,sub agent 自己不解。JSC_HOME沒設時readlink -f "$JSC_HOME/current"印出/current、結束碼 0,非空又是絕對路徑,前三項全部放行,而那個目錄並不存在。所以兩條readlink各自在同一步用[ -d ]查過才算數。測試結果
check-behaviors.sh(工作目錄):結束碼 0,回「對上 2 支技能,五個欄位齊全,跡象欄都寫了收尾事件」。check-behaviors.sh(HEAD 內容的快照):結束碼 1,點名 repair 那一列沒寫到收尾的 skill-end 事件。這一筆用來證明那是既有欠帳,不是這次改壞的。lint-scripts.sh:結束碼 0,20 支腳本過語法、可執行與結束碼宣告,其中 1 支判定為函式庫。lint-frontmatter.sh:結束碼 0。ste100-lint.sh:結束碼 0。wire-cli.sh status claude:結束碼 0,回status=wired,九支 hook 的接線點逐項 present。前置 Push Request