修正四支 CLI 的 pre-tool hook 接線,補上技能名解析與阻擋輸出共用腳本 #57

Merged
jiantw83 merged 4 commits from feat/cli-hook-rewire/four-cli-pre-tool into feat/cli-hook-rewire/main 2026-09-01 00:56:10 +00:00
Member

摘要

  • 需求描述:修正 codex、copilot、antigravity、kiro 四支 CLI 的 hook 接線。這四支都有能介入的 pre-tool 事件,但原本接錯位置,導致版本前置檢查與部署後重啟閘門長期完全失效,而且文件還寫著「這些 CLI 沒有 pre-tool hook」。本輪抓到四個同一類的無聲失效:codex 的 matcher 用了不存在的 Skill 工具、codex 的 hooks 鍵寫成內嵌物件而非路徑字串、antigravity 的 PreToolUse 寫成 Flat 而非 Grouped、三支新接的命令沒帶 JSC_CLI={代號}。另外 copilot 的接線位置指向 $COPILOT_HOME/hooks/,那是腳本目錄不是設定目錄,設定從來不會被讀。版本推進到 0.3.4。
  • 計畫名稱:無
  • 計畫頁:無
  • 分析頁:無

變更內容

檔案 為什麼改
hooks/skill-name.sh 新增。技能名解析集中成唯一真實來源,五支 CLI 各一個子命令:claude 讀 skill 欄位、codex 讀 tool_input.command 裡的 SKILL.md 路徑、copilot 讀字串化的 toolArgs 並剝一層跳脫、antigravity 讀 toolCall.args.AbsolutePath 加提示字串、kiro 讀提示開頭的斜線指令。輸出一行「{domain}<TAB>{技能名}」,解不出印空字串並 exit 0。規則寫在各閘門裡一定會漂移,只留這一份
hooks/deny.sh 新增。阻擋形態集中成唯一真實來源,共四種:claude、codex、copilot 走 stderr 加 exit 2;antigravity 印 stdout 的 {"decision":"deny","reason":"..."} 並固定回 0;kiro 擋不下來,改印警告。訊息會先跳脫成合法 JSON 字串值,壞掉的 JSON 等於沒送出拒絕
hooks/codex-hooks.json 新增。Codex 的 plugin manifest 只吃 hooks 路徑字串,而且那個鍵是覆寫。這一份由 hooks/hooks.json 推導產生,只把 matcher Skill 改寫成 Bash,其餘事件照抄,讓 Claude 那份維持唯一真實來源。每條命令都帶 JSC_CLI=codex 前綴
hooks/version-guard.sh 改用 skill-name.sh 解技能名、deny.sh 出擋人輸出。原本先篩工具名 Skill,那是 Claude 專屬的工具名,等於把另外四支整批擋在判定之外,這正是失效的直接原因。工具名篩選整段移除,接線端的 matcher 已經篩過一輪。豁免清單那 7 支與 fail-open 原則不變。訊息整段走同一條管線送進 deny.sh,分次呼叫會做出好幾份 deny JSON,antigravity 只認第一份
hooks/restart-gate.sh 同上,改用兩支共用腳本。移除 Skill 工具名篩選,技能名改由 skill-name.sh 解析,並用 awk 判 NF==2 才取值,避免沒有定位字元時把整行當技能名。豁免清單那 10 支與 fail-open 原則不變
tools/wire-cli.sh 四支 CLI 的接線、purge、status、smoke 全面重寫。codex 改指 hooks/codex-hooks.json、copilot 改寫 ~/.copilot/settings.json 的頂層 hooks 鍵並只合併不覆寫、antigravity 的 PreToolUse 改成 Grouped 加錨定 matcher ^view_file$、kiro 改寫 ~/.kiro/agents/jsc.json 的 hooks 鍵並補 chat.defaultAgent=jsc。四支的接線命令一律帶 JSC_CLI={代號} 前綴,並在接線、status、smoke 三處各斷言一次。status 從只驗「鍵在不在」改成驗形狀與位置,並新增第三格 unverified,把「驗不了」跟「驗過了」分開,只有 missing 算缺項
.codex-plugin/plugin.json 加 hooks 路徑鍵指向 ./hooks/codex-hooks.json。原本沒有這個鍵,codex 讀不到任何 jsc hook。同時版本推進到 0.3.4
.claude-plugin/plugin.json 版本推進到 0.3.4,三份 manifest 版本必須一致
plugin.json 版本推進到 0.3.4,三份 manifest 版本必須一致
README.md 移除「這四支 CLI 都沒有 pre-tool hook」這句錯誤敘述。新增「各 CLI 的 pre-tool 接線位置」表與逐支原因說明、「驗證等級」表,並更新兩道閘門的事件欄、write-guard.sh 的覆蓋範圍敘述、kiro 的設定檔路徑、新增的三個環境變數說明
references/behaviors.md hooks-install 與 repair 兩支技能的行為描述要跟實際接線一致:完成條件改成四支回 wired、kiro 回 degraded,可驗證跡象逐支寫明新的設定位置與形狀,repair 註明技能名與阻擋形態的修正要落在那兩支新腳本,不在閘門裡各補一份
skills/hooks-install/SKILL.md 同步接線事實與回報規則:新增五支 CLI 的接線位置表與驗證等級表、各 CLI 的形狀陷阱說明、JSC_CLI 前綴的必要性、kiro-cli agent validate 一律回 0 所以要判輸出不判結束碼、status 與接線階段的結束碼語意更新、smoke 新增的端到端斷言,並改掉「只有 claude 有 pre-tool hook」的錯誤前提

設計重點

  • 技能名解析與阻擋形態各只留一份。hooks/skill-name.sh 與 hooks/deny.sh 是唯一真實來源,兩道閘門只管判定、不各留一份輸出邏輯。改了一支忘了另一支,就會做出「判定要擋、CLI 卻沒收到拒絕」的無聲失效。
  • 不再篩工具名。五支 CLI 的工具名各不相同(Skill、Bash、skill、view_file),拿 Claude 那一個當通用條件,等於把另外四支整批擋在判定之外。接線端的 matcher 已經篩過一輪,解得出技能名就是該判的那一次。
  • antigravity 絕不可靠結束碼。那支 CLI 的結束碼語意兩邊文件都沒寫,拒絕整個靠 stdout 那一行 deny JSON,所以 deny.sh 固定回 0,而且 stdout 只准有那一行。訊息也要整段一次送進去,分次呼叫會做出好幾份 deny JSON,只有第一份被採用。
  • JSC_CLI={代號} 是四支非 claude CLI 的接線前提。閘門要先認出自己跑在哪一支上,才取得到技能名與阻擋形態;缺了它一律安靜放行,設定寫得完全正確、matcher 也對,卻一次都擋不下來。所以 status 把它列成單獨一項。
  • hooks/codex-hooks.json 由 hooks/hooks.json 推導產生,只改寫 matcher,其餘照抄。Codex 的 hooks 鍵是覆寫,手寫第二份一定會跟本尊漂移。
  • status 從兩態改成三態。原本只驗「鍵在不在」,形狀錯了照樣回 wired;現在驗形狀與位置,並把「驗不了」記成 unverified,跟「驗過了」分開,只有 missing 算缺項。
  • kiro-cli agent validate 一律回結束碼 0。合法、事件名非法、hooks 裡放 on/run、缺 command,四種情況都是 0。拿結束碼當判準會做出一支永遠通過的檢查,跟這一輪在修的錯是同一類,所以判準是輸出,空的才算通過。
  • kiro 的 verdict 是 degraded,理由是 CLI 限制,不是接線問題。技能走 ResolveSkill 這個 agent 內部請求,不經工具管線,preToolUse 攔不到技能叫用;userPromptSubmit 的非零結束碼也擋不下那一輪。唯一可用的介入是 stdout 注入警告。

測試結果

  • tools/wire-cli.sh smoke 逐條斷言接線內容與腳本邏輯,接線形狀斷言共 26 條,每條正向配一條反向,確保斷言本身真的在判別、不是一支永遠通過的檢查。斷言範圍涵蓋技能名解析、四種阻擋形態、各 CLI 的接線形狀、fail-open 放行、豁免清單放行、kiro 的注入路徑,並把各 CLI 的真實負載端到端跑過 restart-gate.sh——兩端各自健康、中間卻靜靜放行,正是三支 CLI 失守的形態。
  • 驗證等級逐項據實標明。「形狀」是那支 CLI 真的讀得懂這份設定;「觸發」是 hook 真的被叫用過。兩件事分開記,不得混為一談:
CLI 形狀 觸發
claude 實證 實證
codex 實證 未驗證
antigravity 實證(agy -p "/hooks" 確認四條全載入) 未驗證,對話 quota 用盡
copilot 未證(沒有唯讀列出管道) 未驗證
kiro 實證(agent validate 加三種反證) 部分實證:agentSpawn、userPromptSubmit 實跑觸發
  • 觸發不在 smoke 的斷言範圍內,表中「未驗證」就是未驗證,不得當成已驗證回報。
  • kiro 的 verdict 是 degraded,理由是 CLI 限制:技能走 ResolveSkill 這個 agent 內部請求,preToolUse 攔不到技能叫用,userPromptSubmit 的非零結束碼也擋不下那一輪。不是接線問題。
  • 尚未做的事,一併記明:四支非 claude 的 CLI 上,write-guard.sh 三種模式與 SDLC 模型鎖還沒接線,那是還沒做、不是驗不過;kiro 的 resources 兩層 glob 能不能真的修好技能可見性未驗證。

前置 Push Request

  • 無
## 摘要 - 需求描述:修正 codex、copilot、antigravity、kiro 四支 CLI 的 hook 接線。這四支都有能介入的 pre-tool 事件,但原本接錯位置,導致版本前置檢查與部署後重啟閘門長期完全失效,而且文件還寫著「這些 CLI 沒有 pre-tool hook」。本輪抓到四個同一類的無聲失效:codex 的 matcher 用了不存在的 `Skill` 工具、codex 的 `hooks` 鍵寫成內嵌物件而非路徑字串、antigravity 的 `PreToolUse` 寫成 Flat 而非 Grouped、三支新接的命令沒帶 `JSC_CLI={代號}`。另外 copilot 的接線位置指向 `$COPILOT_HOME/hooks/`,那是腳本目錄不是設定目錄,設定從來不會被讀。版本推進到 0.3.4。 - 計畫名稱:無 - 計畫頁:無 - 分析頁:無 ## 變更內容 | 檔案 | 為什麼改 | | --- | --- | | `hooks/skill-name.sh` | 新增。技能名解析集中成唯一真實來源,五支 CLI 各一個子命令:claude 讀 `skill` 欄位、codex 讀 `tool_input.command` 裡的 `SKILL.md` 路徑、copilot 讀字串化的 `toolArgs` 並剝一層跳脫、antigravity 讀 `toolCall.args.AbsolutePath` 加提示字串、kiro 讀提示開頭的斜線指令。輸出一行「{domain}&lt;TAB&gt;{技能名}」,解不出印空字串並 exit 0。規則寫在各閘門裡一定會漂移,只留這一份 | | `hooks/deny.sh` | 新增。阻擋形態集中成唯一真實來源,共四種:claude、codex、copilot 走 stderr 加 exit 2;antigravity 印 stdout 的 `{"decision":"deny","reason":"..."}` 並固定回 0;kiro 擋不下來,改印警告。訊息會先跳脫成合法 JSON 字串值,壞掉的 JSON 等於沒送出拒絕 | | `hooks/codex-hooks.json` | 新增。Codex 的 plugin manifest 只吃 `hooks` 路徑字串,而且那個鍵是覆寫。這一份由 `hooks/hooks.json` 推導產生,只把 matcher `Skill` 改寫成 `Bash`,其餘事件照抄,讓 Claude 那份維持唯一真實來源。每條命令都帶 `JSC_CLI=codex` 前綴 | | `hooks/version-guard.sh` | 改用 `skill-name.sh` 解技能名、`deny.sh` 出擋人輸出。原本先篩工具名 `Skill`,那是 Claude 專屬的工具名,等於把另外四支整批擋在判定之外,這正是失效的直接原因。工具名篩選整段移除,接線端的 matcher 已經篩過一輪。豁免清單那 7 支與 fail-open 原則不變。訊息整段走同一條管線送進 `deny.sh`,分次呼叫會做出好幾份 deny JSON,antigravity 只認第一份 | | `hooks/restart-gate.sh` | 同上,改用兩支共用腳本。移除 `Skill` 工具名篩選,技能名改由 `skill-name.sh` 解析,並用 `awk` 判 NF==2 才取值,避免沒有定位字元時把整行當技能名。豁免清單那 10 支與 fail-open 原則不變 | | `tools/wire-cli.sh` | 四支 CLI 的接線、purge、status、smoke 全面重寫。codex 改指 `hooks/codex-hooks.json`、copilot 改寫 `~/.copilot/settings.json` 的頂層 `hooks` 鍵並只合併不覆寫、antigravity 的 `PreToolUse` 改成 Grouped 加錨定 matcher `^view_file$`、kiro 改寫 `~/.kiro/agents/jsc.json` 的 `hooks` 鍵並補 `chat.defaultAgent=jsc`。四支的接線命令一律帶 `JSC_CLI={代號}` 前綴,並在接線、`status`、`smoke` 三處各斷言一次。`status` 從只驗「鍵在不在」改成驗形狀與位置,並新增第三格 `unverified`,把「驗不了」跟「驗過了」分開,只有 `missing` 算缺項 | | `.codex-plugin/plugin.json` | 加 `hooks` 路徑鍵指向 `./hooks/codex-hooks.json`。原本沒有這個鍵,codex 讀不到任何 jsc hook。同時版本推進到 0.3.4 | | `.claude-plugin/plugin.json` | 版本推進到 0.3.4,三份 manifest 版本必須一致 | | `plugin.json` | 版本推進到 0.3.4,三份 manifest 版本必須一致 | | `README.md` | 移除「這四支 CLI 都沒有 pre-tool hook」這句錯誤敘述。新增「各 CLI 的 pre-tool 接線位置」表與逐支原因說明、「驗證等級」表,並更新兩道閘門的事件欄、`write-guard.sh` 的覆蓋範圍敘述、kiro 的設定檔路徑、新增的三個環境變數說明 | | `references/behaviors.md` | `hooks-install` 與 `repair` 兩支技能的行為描述要跟實際接線一致:完成條件改成四支回 `wired`、kiro 回 `degraded`,可驗證跡象逐支寫明新的設定位置與形狀,`repair` 註明技能名與阻擋形態的修正要落在那兩支新腳本,不在閘門裡各補一份 | | `skills/hooks-install/SKILL.md` | 同步接線事實與回報規則:新增五支 CLI 的接線位置表與驗證等級表、各 CLI 的形狀陷阱說明、`JSC_CLI` 前綴的必要性、`kiro-cli agent validate` 一律回 0 所以要判輸出不判結束碼、`status` 與接線階段的結束碼語意更新、smoke 新增的端到端斷言,並改掉「只有 claude 有 pre-tool hook」的錯誤前提 | ## 設計重點 - 技能名解析與阻擋形態各只留一份。`hooks/skill-name.sh` 與 `hooks/deny.sh` 是唯一真實來源,兩道閘門只管判定、不各留一份輸出邏輯。改了一支忘了另一支,就會做出「判定要擋、CLI 卻沒收到拒絕」的無聲失效。 - 不再篩工具名。五支 CLI 的工具名各不相同(`Skill`、`Bash`、`skill`、`view_file`),拿 Claude 那一個當通用條件,等於把另外四支整批擋在判定之外。接線端的 matcher 已經篩過一輪,解得出技能名就是該判的那一次。 - antigravity 絕不可靠結束碼。那支 CLI 的結束碼語意兩邊文件都沒寫,拒絕整個靠 stdout 那一行 deny JSON,所以 `deny.sh` 固定回 0,而且 stdout 只准有那一行。訊息也要整段一次送進去,分次呼叫會做出好幾份 deny JSON,只有第一份被採用。 - `JSC_CLI={代號}` 是四支非 claude CLI 的接線前提。閘門要先認出自己跑在哪一支上,才取得到技能名與阻擋形態;缺了它一律安靜放行,設定寫得完全正確、matcher 也對,卻一次都擋不下來。所以 `status` 把它列成單獨一項。 - `hooks/codex-hooks.json` 由 `hooks/hooks.json` 推導產生,只改寫 matcher,其餘照抄。Codex 的 `hooks` 鍵是覆寫,手寫第二份一定會跟本尊漂移。 - `status` 從兩態改成三態。原本只驗「鍵在不在」,形狀錯了照樣回 `wired`;現在驗形狀與位置,並把「驗不了」記成 `unverified`,跟「驗過了」分開,只有 `missing` 算缺項。 - `kiro-cli agent validate` 一律回結束碼 0。合法、事件名非法、`hooks` 裡放 `on`/`run`、缺 `command`,四種情況都是 0。拿結束碼當判準會做出一支永遠通過的檢查,跟這一輪在修的錯是同一類,所以判準是輸出,空的才算通過。 - kiro 的 verdict 是 `degraded`,理由是 CLI 限制,不是接線問題。技能走 `ResolveSkill` 這個 agent 內部請求,不經工具管線,`preToolUse` 攔不到技能叫用;`userPromptSubmit` 的非零結束碼也擋不下那一輪。唯一可用的介入是 stdout 注入警告。 ## 測試結果 - `tools/wire-cli.sh smoke` 逐條斷言接線內容與腳本邏輯,接線形狀斷言共 26 條,每條正向配一條反向,確保斷言本身真的在判別、不是一支永遠通過的檢查。斷言範圍涵蓋技能名解析、四種阻擋形態、各 CLI 的接線形狀、fail-open 放行、豁免清單放行、kiro 的注入路徑,並把各 CLI 的真實負載端到端跑過 `restart-gate.sh`——兩端各自健康、中間卻靜靜放行,正是三支 CLI 失守的形態。 - 驗證等級逐項據實標明。「形狀」是那支 CLI 真的讀得懂這份設定;「觸發」是 hook 真的被叫用過。兩件事分開記,不得混為一談: | CLI | 形狀 | 觸發 | | --- | --- | --- | | claude | 實證 | 實證 | | codex | 實證 | 未驗證 | | antigravity | 實證(`agy -p "/hooks"` 確認四條全載入) | 未驗證,對話 quota 用盡 | | copilot | 未證(沒有唯讀列出管道) | 未驗證 | | kiro | 實證(`agent validate` 加三種反證) | 部分實證:`agentSpawn`、`userPromptSubmit` 實跑觸發 | - 觸發不在 smoke 的斷言範圍內,表中「未驗證」就是未驗證,不得當成已驗證回報。 - kiro 的 verdict 是 `degraded`,理由是 CLI 限制:技能走 `ResolveSkill` 這個 agent 內部請求,`preToolUse` 攔不到技能叫用,`userPromptSubmit` 的非零結束碼也擋不下那一輪。不是接線問題。 - 尚未做的事,一併記明:四支非 claude 的 CLI 上,`write-guard.sh` 三種模式與 SDLC 模型鎖還沒接線,那是還沒做、不是驗不過;kiro 的 `resources` 兩層 glob 能不能真的修好技能可見性未驗證。 ## 前置 Push Request - 無
jiantw83 added 4 commits 2026-08-31 11:07:40 +00:00
What:
- 新增 hooks/skill-name.sh。五支 CLI 各一個子命令,從各自的負載解析出這一次要用哪一支 jsc 技能,印一行「{domain}<TAB>{技能名}」。解不出來就印空字串並回 0。
- 新增 hooks/deny.sh。依當前 CLI 產出四種阻擋形態,訊息從參數或標準輸入進。
- version-guard.sh 與 restart-gate.sh 改用這兩支,各自那份工具名判定與技能名取值一併移除。

Why:
- 兩道閘門原本都拿 Claude 的工具名 Skill 當通用條件。另外四支 CLI 的工具名分別是 Bash、skill、view_file,一律被擋在判定之外,兩道閘門在那四支上長期完全失效,而且一聲都不吭。
- 阻擋形態每支 CLI 都不一樣,判定卻是同一件事。各自留一份輸出邏輯,改了一支忘了另一支,就會做出「判定擋下、CLI 照樣放行」的無聲失效。

How:
- 技能名取值規則只留 skill-name.sh 這一份,環境變數 JSC_SKILL、SKILL 優先。claude 讀 skill 欄位、codex 認 tool_input.command 裡那條 SKILL.md 路徑、copilot 先剝一層字串化 JSON 再讀 toolArgs、antigravity 讀 toolCall.args.AbsolutePath 並另收提示字串、kiro 取提示開頭那個斜線指令。
- 閘門端用 awk 判 NF == 2 才取值。少一欄就當成解析不出來,免得沒有定位字元時 cut -f2 把整行當成技能名,拼出一個不存在的技能名去比對豁免清單。
- deny.sh 定形態:claude、codex、copilot 走 stderr 加 exit 2;antigravity 印 stdout 的單行 deny JSON 並固定回 0,因為那支 CLI 的結束碼語意兩邊文件都沒寫、絕不可靠;kiro 擋不下技能叫用,改印警告後回 0;認不得的代號走 stderr 加 2 這個保守預設。
- 訊息整段走同一條管線送進 deny.sh。分次呼叫會做出好幾份 deny JSON,antigravity 只認第一份,後面幾段使用者永遠看不到。
- 豁免清單與 fail-open 原則不變。這兩支刻意以子行程呼叫、不用 source 載入:讀不到只會讓技能名解不出來而安靜放行,不會反過來擋掉每一次呼叫。

Who:codex、copilot、antigravity、kiro 四支 CLI 的 pre-tool hook 接線修正。
What:
- tools/wire-cli.sh 重寫 codex、copilot、antigravity、kiro 四支的接線、purge、status 與 smoke。
- 新增 hooks/codex-hooks.json,由 hooks/hooks.json 推導產生。
- .codex-plugin/plugin.json 加上 hooks 路徑鍵,指向那份檔案。

Why:這四支其實都有能介入的 pre-tool 事件,原本卻接錯位置,抓到五個同一類的無聲失效——設定看起來正確、CLI 靜默不理、不報錯:
- codex 的 matcher 用 Skill,但 Codex 沒有 Skill 這個工具,技能是模型自己用 Bash 讀 SKILL.md 載入的。
- codex 的 hooks 鍵寫成內嵌物件,實際規格是路徑字串,內嵌物件解析不了。
- antigravity 的 PreToolUse 寫成 Flat,實際要 matcher 加 hooks 包一層的 Grouped。Flat 的那一段整個被丟掉,hook 名稱照樣登記,檔案讀起來還是對的。
- copilot 的設定寫到 $COPILOT_HOME/hooks/,那是 hook 要跑的腳本目錄、不是設定目錄,設定從來不會被讀。
- 三支新接的命令沒帶 JSC_CLI={代號},閘門認不出自己跑在哪支 CLI 上,一次都擋不下來。

How:
- codex:PreToolUse matcher 換成 Bash。codex-hooks.json 由 hooks/hooks.json 整份複製,再把 matcher 的 Skill 改寫成 Bash,其餘事件原樣保留,Claude 那份維持唯一真實來源,第二份絕不手寫。
- copilot:pre-tool hook 併進 ~/.copilot/settings.json 的頂層 hooks 鍵,matcher 用小寫 skill,事件名只寫一種大小寫。那份檔案同時裝著 enabledPlugins 與 extraKnownMarketplaces,所以合併不覆寫:寫前備份、只動 jsc 自己那幾筆、寫後回讀核對最上層鍵與別人的條目,對不上就還原。指引檔改寫到 $COPILOT_HOME 底下。
- antigravity:寫 ~/.gemini/config/hooks.json 的 jsc 段落。PreToolUse 改成 Grouped、matcher 是錨定的 view_file,錨點不能省,省了會連 view_file_outline 一起命中;另接 Flat 的 PreInvocation,攔斜線指令那條不產生工具呼叫的路。
- kiro:hook 宣告搬到 ~/.kiro/agents/jsc.json 的 hooks 鍵,事件只用 agentSpawn、userPromptSubmit、stop,欄位是 command 與 timeout_ms,並把 settings/cli.json 的 chat.defaultAgent 設成 jsc。kiro-cli agent validate 四種情況一律回 0,所以判準看輸出、不看結束碼。
- 四支非 claude 的接線命令一律以 JSC_CLI={代號} 前綴自帶代號,接線時、status 與 smoke 各斷言一次。
- status 從只驗「鍵在不在」改成驗形狀與位置,並新增第三格 unverified,把「驗不了」跟「驗過了」分開,只有 missing 算缺項。
- smoke 新增 26 條接線形狀斷言,每條正向配一條反向,另把五支 CLI 的真實負載直接餵進 restart-gate.sh,驗解析、判定、輸出整條串得起來。前兩段分開看都會顯示正常,中間接不上照樣是全程放行,那正是先前失效的樣子。

Who:codex、copilot、antigravity、kiro 四支 CLI 的 pre-tool hook 接線修正。
What:README.md、references/behaviors.md 與 skills/hooks-install/SKILL.md 同步這一批的接線事實。

Why:
- 文件寫著「這些 CLI 沒有 pre-tool hook」。那句話是錯的,也正是三支 CLI 長期沒有守門的原因。照著它報告,會讓使用者以為只有 claude 有保護、其餘四支本來就接不上。
- kiro 的 degraded 原本被寫成接線缺東西,實際上是那支 CLI 擋不下技能叫用。兩件事的處理方式完全不同。

How:
- 一支 CLI 一列,列出接線位置、事件與 matcher、阻擋形態與判定,並寫明 claude、codex、copilot、antigravity 回 wired,kiro 回 degraded。
- 新增驗證等級表,把「形狀」與「觸發」分開記:形狀是那支 CLI 真的讀得懂設定,觸發是 hook 真的被叫用過。copilot 的形狀未證、antigravity 與 codex 的觸發未驗證,一律照實列出,不含糊帶過。
- README 補上 hooks/skill-name.sh 與 hooks/deny.sh 兩列,並補 COPILOT_HOME、KIRO_HOME、JSC_ANTIGRAVITY_HOOKS、JSC_COPILOT_INSTRUCTIONS、JSC_ANTIGRAVITY_RULES 幾個環境變數。
- kiro 的接線位置從 .kiro/hooks/jsc-hooks.json 全面改寫成 ~/.kiro/agents/jsc.json。
- 講明 write-guard.sh 三個模式與 SDLC 模型鎖在另外三支上是「還沒接」,不是「沒有 hook 可接」。
- behaviors.md 的完成條件與可驗證跡象跟著改,repair 那一列加上「技能名解析改 skill-name.sh、阻擋形態改 deny.sh,兩支是唯一真實來源」。

Who:codex、copilot、antigravity、kiro 四支 CLI 的 pre-tool hook 接線修正。
What:plugin.json 與 .claude-plugin/plugin.json 的 version 由 0.3.3 改為 0.3.4。

Why:
- 這一批補上四支 CLI 的 pre-tool hook 接線,屬於新增能力,要發一個新版本。
- 三份 manifest 的版本號必須一致。版本前置檢查比對的就是這個號,對不上會讓 hook 判出錯誤的落後結論。

How:
- 由主流程的 sync-skill-manifest.sh 同步,三份一起改,不手動各寫一次。
- .codex-plugin/plugin.json 那一份的版本號隨接線提交一起進來,因為同一個檔案還加了 hooks 路徑鍵。

Who:jsc-hooks 0.3.4 發佈收尾。
jiantw83 merged commit 453b576050 into feat/cli-hook-rewire/main 2026-09-01 00:56:10 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: plugins/hooks#57