feat/hooks-install-purge-first-and-repair-on-any-hook-error #18

Merged
admin merged 3 commits from feat/hooks-install-purge-first-and-repair-on-any-hook-error into develop 2026-08-25 10:20:03 +00:00
Member

安裝一律先清空 hook,出錯就轉修正

摘要

  • 需求描述:把使用者兩條規則落實到 jsc-hooks:hooks-install 技能。第一條:hook 只要有錯誤就轉 jsc-hooks:repair 修正,不分接線失敗或執行期錯誤;此時允許中止剩下的安裝流程,但修正一定要開始,並且一定要 PR 到 develop。第二條:安裝一律先移除該 CLI 的所有 hook,含非 jsc 的第三方 hook,備份之後只重新安裝 jsc 的 hook 技能組。第一條規則的收尾關卡是 jsc-hooks:repair 技能,它已隨 PR #16 合併進 develop,本 PR 只帶三個新 commit,接在它後面。
  • 計畫名稱:無
  • 計畫頁:無
  • 分析頁:無

變更內容

檔案 為什麼改
tools/wire-cli.sh 加上 purge {cli} 子命令,備份後移除該 CLI 的所有 hook,讓「先清空再安裝」這條規則落在程式碼裡而不是技能文字裡;再加上 smoke {cli} 子命令,五支 hook 各跑一次,補上接線驗證看不到的執行期那一半。原有的接線行為與回報格式不動。
tools/scan-hook-errors.sh 新檔。接線寫對、hook 也真的觸發,還是可能跑起來出錯,這種錯誤只留在 CLI 的原生紀錄裡。這支掃 claude 的 hook 結果紀錄把它撈出來,另外四個 CLI 沒有等價紀錄就回 unavailable,缺口據實講明。每筆錯誤標上 jsc 欄位,分得出是不是 jsc 自己的 hook,才知道該不該轉修正。
skills/hooks-install/SKILL.md 流程從四步改成七步:purge、接線、smoke、scan、報錯轉修正、回報。兩條規則都寫進步驟的完成條件,description 也一併改寫,讓技能被挑中時就看得到「先全清」與「出錯轉修正」這兩件事。
README.md 工具表補上 scan-hook-errors.sh 一列、改寫 wire-cli.sh 一列講三個用法;hooks-install 技能說明改成四道關卡的敘述;環境變數表補上 JSC_CLAUDE_SETTINGS_DIR。
plugin.json、.claude-plugin/plugin.json、.codex-plugin/plugin.json 三份 manifest 同步升版 0.1.5 → 0.1.6,版本前置檢查才認得這次的新工具。

設計重點

  • 移除邏輯下放到 wire-cli.sh purge 子命令,不留在技能文字裡。規則寫在程式碼裡才驗得到行為:purge 自己回報 status=purged|skipped|failed,也自己重讀檔案確認鍵真的不見了,技能只要判讀那一行。
  • 備份先行。每個要動的檔案在移除前原樣複製到 $JSC_HOME/backup/hooks/{cli}/{yyyyMMdd_HHmmss}/,一次 purge 一個目錄;備份失敗就不移除,移除後驗不過就自動還原備份。移除做一半的環境比沒動過更難修,所以失敗出口 pfail 一律先還原再回報。
  • 沒有 jq 也刪得掉 JSON 鍵。jq 在目標機器上不保證存在,所以備一條純 awk 的路:逐字元掃描,追蹤引號與括號深度,字串裡的括號不算深度,hooks 是最後一個成員時改刪前面那個逗號。解析不出來就 exit 1,不輸出半份檔案。
  • codex 只移除根層 notify。[profiles.dev] 這類 profile 層底下的 notify 是使用者自己的設定,跟 hook 接線無關,逐表頭判斷後保留。TOML 的值可能是多行陣列或多行行內表,所以刪鍵要追括號深度收齊才停,只刪一行會留下孤兒括號。
  • claude 的其他 plugin 自帶 hooks.json,purge 動不到,只能靠移除那個 plugin 才會消失(jsc 自己的 hooks/hooks.json 也一樣)。這件事在 purge 的輸出裡直接講明,不假裝已經清乾淨。
  • 執行期偵測依各 CLI 條件分兩路。只有 claude 有 hook 結果紀錄,掃得出 hook_non_blocking_error 與非空 hookErrors;codex、copilot、antigravity、kiro 只留工作階段與提示內容,沒記退出碼與 stderr,只能靠 smoke 主動跑一輪。回報時 unavailable 就講 unavailable,不寫成 clean。
  • 第三方 hook 的錯誤只回報,不轉修正。jsc 欄位用 command 與 stderr 是否命中五支 hook 檔名來判定;jsc=true 才走 repair,jsc=false 原樣列出來交給使用者自己處理。
  • smoke 放行一個非零退出:sdlc-gate.sh check 的 exit 2 是階段鎖刻意擋下該輪提示,屬設計行為。不放行的話,每個正在上鎖的工作階段都會誤報一次失敗。
  • JSC_CLAUDE_SETTINGS_DIR 是測試用的逃生門。刪 JSON 鍵的預設目標是使用者本人的設定檔,指向一份複製品才測得動整條刪鍵流程,不必拿使用者的環境當測試場。

測試結果

  • sh -n tools/wire-cli.sh、sh -n tools/scan-hook-errors.sh:兩支都通過語法檢查。
  • 用法護欄:兩支腳本在無參數與錯誤 CLI 名的情況下一律 exit 2。
  • wire-cli.sh purge claude(在設定檔複製品上跑,JSC_CLAUDE_SETTINGS_DIR 指向複製品):hooks 鍵確實刪除,其他鍵完整保留,備份檔與原檔位元組相同,重跑冪等。
  • 壞掉的 JSON:purge claude 拒絕處理並 exit 4,還原備份,原檔完全沒動。
  • wire-cli.sh purge codex(在假 HOME 跑):根層 notify 移除,含第三方設的值;[profiles.dev] 底下的 notify 保留;第三方的 rc 段落保留。
  • wire-cli.sh smoke claude:五支 hook 全部 exit 0。
  • tools/scan-hook-errors.sh --cli claude:掃到 30 筆,27 筆 hook_non_blocking_error 加 3 筆非空 hookErrors,與 grep 計數一致;30 筆全部 jsc=false,另外以 fixture 驗證 jsc=true 的判定正確。
  • tools/scan-hook-errors.sh --cli {codex|copilot|antigravity|kiro}:四個都回 unavailable,並指向 smoke。
  • 真實環境未受影響:~/.claude/settings.json、~/.bashrc、~/.codex/config.toml 全程未被修改。
  • meta/tools/ste100-lint.sh hooks:通過,無簡體字,無半形標點誤用。

前置 Push Request

  • 無
# 安裝一律先清空 hook,出錯就轉修正 ## 摘要 - 需求描述:把使用者兩條規則落實到 `jsc-hooks:hooks-install` 技能。第一條:hook 只要有錯誤就轉 `jsc-hooks:repair` 修正,不分接線失敗或執行期錯誤;此時允許中止剩下的安裝流程,但修正一定要開始,並且一定要 PR 到 `develop`。第二條:安裝一律先移除該 CLI 的所有 hook,含非 jsc 的第三方 hook,備份之後只重新安裝 jsc 的 hook 技能組。第一條規則的收尾關卡是 `jsc-hooks:repair` 技能,它已隨 PR #16 合併進 `develop`,本 PR 只帶三個新 commit,接在它後面。 - 計畫名稱:無 - 計畫頁:無 - 分析頁:無 ## 變更內容 | 檔案 | 為什麼改 | | --- | --- | | `tools/wire-cli.sh` | 加上 `purge {cli}` 子命令,備份後移除該 CLI 的所有 hook,讓「先清空再安裝」這條規則落在程式碼裡而不是技能文字裡;再加上 `smoke {cli}` 子命令,五支 hook 各跑一次,補上接線驗證看不到的執行期那一半。原有的接線行為與回報格式不動。 | | `tools/scan-hook-errors.sh` | 新檔。接線寫對、hook 也真的觸發,還是可能跑起來出錯,這種錯誤只留在 CLI 的原生紀錄裡。這支掃 claude 的 hook 結果紀錄把它撈出來,另外四個 CLI 沒有等價紀錄就回 `unavailable`,缺口據實講明。每筆錯誤標上 `jsc` 欄位,分得出是不是 jsc 自己的 hook,才知道該不該轉修正。 | | `skills/hooks-install/SKILL.md` | 流程從四步改成七步:purge、接線、smoke、scan、報錯轉修正、回報。兩條規則都寫進步驟的完成條件,`description` 也一併改寫,讓技能被挑中時就看得到「先全清」與「出錯轉修正」這兩件事。 | | `README.md` | 工具表補上 `scan-hook-errors.sh` 一列、改寫 `wire-cli.sh` 一列講三個用法;`hooks-install` 技能說明改成四道關卡的敘述;環境變數表補上 `JSC_CLAUDE_SETTINGS_DIR`。 | | `plugin.json`、`.claude-plugin/plugin.json`、`.codex-plugin/plugin.json` | 三份 manifest 同步升版 0.1.5 → 0.1.6,版本前置檢查才認得這次的新工具。 | ## 設計重點 - 移除邏輯下放到 `wire-cli.sh purge` 子命令,不留在技能文字裡。規則寫在程式碼裡才驗得到行為:purge 自己回報 `status=purged|skipped|failed`,也自己重讀檔案確認鍵真的不見了,技能只要判讀那一行。 - 備份先行。每個要動的檔案在移除前原樣複製到 `$JSC_HOME/backup/hooks/{cli}/{yyyyMMdd_HHmmss}/`,一次 purge 一個目錄;備份失敗就不移除,移除後驗不過就自動還原備份。移除做一半的環境比沒動過更難修,所以失敗出口 `pfail` 一律先還原再回報。 - 沒有 `jq` 也刪得掉 JSON 鍵。`jq` 在目標機器上不保證存在,所以備一條純 awk 的路:逐字元掃描,追蹤引號與括號深度,字串裡的括號不算深度,`hooks` 是最後一個成員時改刪前面那個逗號。解析不出來就 exit 1,不輸出半份檔案。 - codex 只移除根層 `notify`。`[profiles.dev]` 這類 profile 層底下的 `notify` 是使用者自己的設定,跟 hook 接線無關,逐表頭判斷後保留。TOML 的值可能是多行陣列或多行行內表,所以刪鍵要追括號深度收齊才停,只刪一行會留下孤兒括號。 - claude 的其他 plugin 自帶 `hooks.json`,purge 動不到,只能靠移除那個 plugin 才會消失(jsc 自己的 `hooks/hooks.json` 也一樣)。這件事在 purge 的輸出裡直接講明,不假裝已經清乾淨。 - 執行期偵測依各 CLI 條件分兩路。只有 claude 有 hook 結果紀錄,掃得出 `hook_non_blocking_error` 與非空 `hookErrors`;codex、copilot、antigravity、kiro 只留工作階段與提示內容,沒記退出碼與 stderr,只能靠 `smoke` 主動跑一輪。回報時 `unavailable` 就講 `unavailable`,不寫成 `clean`。 - 第三方 hook 的錯誤只回報,不轉修正。`jsc` 欄位用 command 與 stderr 是否命中五支 hook 檔名來判定;`jsc=true` 才走 `repair`,`jsc=false` 原樣列出來交給使用者自己處理。 - `smoke` 放行一個非零退出:`sdlc-gate.sh check` 的 exit 2 是階段鎖刻意擋下該輪提示,屬設計行為。不放行的話,每個正在上鎖的工作階段都會誤報一次失敗。 - `JSC_CLAUDE_SETTINGS_DIR` 是測試用的逃生門。刪 JSON 鍵的預設目標是使用者本人的設定檔,指向一份複製品才測得動整條刪鍵流程,不必拿使用者的環境當測試場。 ## 測試結果 - `sh -n tools/wire-cli.sh`、`sh -n tools/scan-hook-errors.sh`:兩支都通過語法檢查。 - 用法護欄:兩支腳本在無參數與錯誤 CLI 名的情況下一律 exit 2。 - `wire-cli.sh purge claude`(在設定檔複製品上跑,`JSC_CLAUDE_SETTINGS_DIR` 指向複製品):`hooks` 鍵確實刪除,其他鍵完整保留,備份檔與原檔位元組相同,重跑冪等。 - 壞掉的 JSON:`purge claude` 拒絕處理並 exit 4,還原備份,原檔完全沒動。 - `wire-cli.sh purge codex`(在假 HOME 跑):根層 `notify` 移除,含第三方設的值;`[profiles.dev]` 底下的 `notify` 保留;第三方的 rc 段落保留。 - `wire-cli.sh smoke claude`:五支 hook 全部 exit 0。 - `tools/scan-hook-errors.sh --cli claude`:掃到 30 筆,27 筆 `hook_non_blocking_error` 加 3 筆非空 `hookErrors`,與 grep 計數一致;30 筆全部 `jsc=false`,另外以 fixture 驗證 `jsc=true` 的判定正確。 - `tools/scan-hook-errors.sh --cli {codex|copilot|antigravity|kiro}`:四個都回 `unavailable`,並指向 `smoke`。 - 真實環境未受影響:`~/.claude/settings.json`、`~/.bashrc`、`~/.codex/config.toml` 全程未被修改。 - `meta/tools/ste100-lint.sh hooks`:通過,無簡體字,無半形標點誤用。 ## 前置 Push Request - 無
jiantw83 added 3 commits 2026-08-25 10:18:38 +00:00
admin approved these changes 2026-08-25 10:19:59 +00:00
admin merged commit 291909cfed into develop 2026-08-25 10:20:03 +00:00
admin deleted branch feat/hooks-install-purge-first-and-repair-on-any-hook-error 2026-08-25 10:20:03 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: plugins/hooks#18