版本前置檢查新增相依落後擋人、新增技能行為清單 #54

Member

摘要

  • 需求描述:版本前置檢查要多擋一種情況。技能所屬 plugin 的 manifest 在 jsc.requires 宣告的相依 plugin 版本落後時,擋下該次技能呼叫並提示怎麼補。同時補上技能行為清單,當作技能驗證的比對基準。
  • 計畫名稱:無
  • 計畫頁:無
  • 分析頁:無

變更內容

檔案 為什麼改
references/behaviors.md 新增。逐支列出 jsc-hooks 兩支技能的觸發時機、關鍵步驟、外部呼叫、完成條件與可驗證跡象,當作技能驗證的基準。技能行為以後有異動,要在同一個 PR 內更新這一頁
hooks/version-guard.sh 加上第二種擋人情況。新增 install_path 與 requires_pairs 兩支函式,讀 installPath 底下那份 plugin.json 的 jsc.requires,逐項比對相依 plugin 的本機實際載入版本,有一項落後就以 exit 2 擋下。檔頭改寫,把兩種擋人情況、四種新的 fail-open 與豁免清單共用的理由都寫進去
tools/wire-cli.sh smoke 補上相依版本檢查那一類,共 13 條斷言,跑在一份暫時的 HOME 裡。新增計數器 smoke_n_vg 與預期值 SMOKE_EXPECT_VG,接進原本的自我斷言與 lines 行數比對,判定路徑增減時只改腳本裡的預期值
README.md 對照表跟上實況。version-guard.sh 那一列改寫成擋兩種情況,wire-cli.sh 那一列補一句新的沙箱說明。斷言條數不寫死,散文一律引用 smoke 自己印的 lines 那一行
plugin.json 版本推進到 0.3.3
.claude-plugin/plugin.json 版本推進到 0.3.3,與根目錄那份一致
.codex-plugin/plugin.json 版本推進到 0.3.3,與根目錄那份一致

設計重點

  • 相依落後改判成擋人,是這次唯一的行為變更。兩種擋人情況共用同一份 7 項豁免清單,相依落後不另立短清單。那幾支同樣是更新與修復的唯一路徑,用哪一個理由擋都是死鎖。
  • 新的檢查排在豁免清單與逃生門之後、遠端比對之前。這一段全部讀本機檔案,不必連網,離線的機器也判得動。
  • 判定邏輯在這支 hook 裡自己實作,不去呼叫 jsc-cli 的 check-requires.sh。兩個理由:hook 要專屬留在 jsc-hooks,不可散落到別的 domain;而且 jsc-cli 已經宣告相依 jsc-hooks,反向呼叫會做出循環相依。部署那端照樣更新、只回報,阻擋落在這支 hook。
  • 四種情況一律 fail-open:解不出安裝路徑、讀不到 manifest、manifest 沒有 jsc.requires、讀不到某一項相依的本機載入版本。五支 CLI 只有 claude 讀得到本機載入版本,任何一條改成擋人,另外四支就會被整批鎖死。沒有證據不等於落後。
  • 相依 plugin 的現況只認 installPath 底下那份 plugin.json,不拿 installed_plugins.json 的 version 欄位當備援。註冊值可能比實際載入的版本新,拿它比對會放過真正被載入的舊版。
  • smoke 那 13 條斷言涵蓋每一條判定路徑:相依落後的擋人與訊息內容、相等與超前的放行、豁免技能在相依落後時照樣放行、同一個 plugin 底下非豁免技能被擋的對照、四種 fail-open、逃生門,另加一條回歸——多行縮排的 manifest,jsc.requires 的最後一個鍵也要解得到。
  • README 只寫「擋兩種情況」與新沙箱那一句,不抄斷言條數。條數的唯一來源是 smoke 自己印的 lines 那一行。

測試結果

  • sh -n /root/plugins/hooks/hooks/version-guard.sh:exit 0。
  • sh -n /root/plugins/hooks/tools/wire-cli.sh:exit 0。
  • bash -n /root/plugins/hooks/hooks/version-guard.sh:exit 0。
  • bash -n /root/plugins/hooks/tools/wire-cli.sh:exit 0。
  • sh /root/plugins/meta/tools/lint-scripts.sh /root/plugins/hooks:exit 0。輸出「腳本檢查通過:15 支(語法、可執行、結束碼宣告),其中 1 支判定為函式庫」,被豁免的那一支是 hooks/lib.sh。
  • sh /root/plugins/meta/tools/check-behaviors.sh /root/plugins/hooks:exit 0。輸出「行為清單檢查通過:/root/plugins/hooks/references/behaviors.md 對上 2 支技能,五個欄位齊全」。
  • sh /root/plugins/meta/tools/ste100-lint.sh 對 hooks/version-guard.sh、tools/wire-cli.sh、references/behaviors.md、README.md 四個檔案:exit 0,一項都沒命中。
  • sh /root/plugins/hooks/tools/wire-cli.sh smoke 這一輪沒有跑,原因是它不是整支跑在沙箱裡。讀過原始碼確認:新加的相依版本那 13 條斷言確實跑在 mktemp -d 建出來的暫時 HOME 裡,工作包、重啟閘門、寫入閘門與模型來源那幾類也各自用暫時的 $JSC_HOME;但是前段 smoke_one 那 17 條(第 805 行到第 814 行、第 963 行到第 975 行)用的是這台機器真正的 $JSC_HOME,其中 session-timer.sh mark 會覆寫 $JSC_HOME/sessions/{session}.end,動到目前工作階段的計時狀態,腳本自己在第 971 行到第 972 行也註明那一輪用的是真正的 $JSC_HOME。它不會動到任何 CLI 的設定檔或 hook 接線,那是 wire 與 purge 才會做的事,但它仍然不是唯讀,所以這一輪不跑。請在乾淨的容器或拋棄式環境裡補跑一次,確認 status=ok 而且 lines 是 77 行。

前置 Push Request

  • 無
## 摘要 - 需求描述:版本前置檢查要多擋一種情況。技能所屬 plugin 的 manifest 在 `jsc.requires` 宣告的相依 plugin 版本落後時,擋下該次技能呼叫並提示怎麼補。同時補上技能行為清單,當作技能驗證的比對基準。 - 計畫名稱:無 - 計畫頁:無 - 分析頁:無 ## 變更內容 | 檔案 | 為什麼改 | | --- | --- | | `references/behaviors.md` | 新增。逐支列出 jsc-hooks 兩支技能的觸發時機、關鍵步驟、外部呼叫、完成條件與可驗證跡象,當作技能驗證的基準。技能行為以後有異動,要在同一個 PR 內更新這一頁 | | `hooks/version-guard.sh` | 加上第二種擋人情況。新增 `install_path` 與 `requires_pairs` 兩支函式,讀 `installPath` 底下那份 `plugin.json` 的 `jsc.requires`,逐項比對相依 plugin 的本機實際載入版本,有一項落後就以 exit 2 擋下。檔頭改寫,把兩種擋人情況、四種新的 fail-open 與豁免清單共用的理由都寫進去 | | `tools/wire-cli.sh` | smoke 補上相依版本檢查那一類,共 13 條斷言,跑在一份暫時的 `HOME` 裡。新增計數器 `smoke_n_vg` 與預期值 `SMOKE_EXPECT_VG`,接進原本的自我斷言與 `lines` 行數比對,判定路徑增減時只改腳本裡的預期值 | | `README.md` | 對照表跟上實況。`version-guard.sh` 那一列改寫成擋兩種情況,`wire-cli.sh` 那一列補一句新的沙箱說明。斷言條數不寫死,散文一律引用 smoke 自己印的 `lines` 那一行 | | `plugin.json` | 版本推進到 0.3.3 | | `.claude-plugin/plugin.json` | 版本推進到 0.3.3,與根目錄那份一致 | | `.codex-plugin/plugin.json` | 版本推進到 0.3.3,與根目錄那份一致 | ## 設計重點 - 相依落後改判成擋人,是這次唯一的行為變更。兩種擋人情況共用同一份 7 項豁免清單,相依落後不另立短清單。那幾支同樣是更新與修復的唯一路徑,用哪一個理由擋都是死鎖。 - 新的檢查排在豁免清單與逃生門之後、遠端比對之前。這一段全部讀本機檔案,不必連網,離線的機器也判得動。 - 判定邏輯在這支 hook 裡自己實作,不去呼叫 jsc-cli 的 `check-requires.sh`。兩個理由:hook 要專屬留在 jsc-hooks,不可散落到別的 domain;而且 jsc-cli 已經宣告相依 jsc-hooks,反向呼叫會做出循環相依。部署那端照樣更新、只回報,阻擋落在這支 hook。 - 四種情況一律 fail-open:解不出安裝路徑、讀不到 manifest、manifest 沒有 `jsc.requires`、讀不到某一項相依的本機載入版本。五支 CLI 只有 claude 讀得到本機載入版本,任何一條改成擋人,另外四支就會被整批鎖死。沒有證據不等於落後。 - 相依 plugin 的現況只認 `installPath` 底下那份 `plugin.json`,不拿 `installed_plugins.json` 的 `version` 欄位當備援。註冊值可能比實際載入的版本新,拿它比對會放過真正被載入的舊版。 - smoke 那 13 條斷言涵蓋每一條判定路徑:相依落後的擋人與訊息內容、相等與超前的放行、豁免技能在相依落後時照樣放行、同一個 plugin 底下非豁免技能被擋的對照、四種 fail-open、逃生門,另加一條回歸——多行縮排的 manifest,`jsc.requires` 的最後一個鍵也要解得到。 - README 只寫「擋兩種情況」與新沙箱那一句,不抄斷言條數。條數的唯一來源是 smoke 自己印的 `lines` 那一行。 ## 測試結果 - `sh -n /root/plugins/hooks/hooks/version-guard.sh`:exit 0。 - `sh -n /root/plugins/hooks/tools/wire-cli.sh`:exit 0。 - `bash -n /root/plugins/hooks/hooks/version-guard.sh`:exit 0。 - `bash -n /root/plugins/hooks/tools/wire-cli.sh`:exit 0。 - `sh /root/plugins/meta/tools/lint-scripts.sh /root/plugins/hooks`:exit 0。輸出「腳本檢查通過:15 支(語法、可執行、結束碼宣告),其中 1 支判定為函式庫」,被豁免的那一支是 `hooks/lib.sh`。 - `sh /root/plugins/meta/tools/check-behaviors.sh /root/plugins/hooks`:exit 0。輸出「行為清單檢查通過:/root/plugins/hooks/references/behaviors.md 對上 2 支技能,五個欄位齊全」。 - `sh /root/plugins/meta/tools/ste100-lint.sh` 對 `hooks/version-guard.sh`、`tools/wire-cli.sh`、`references/behaviors.md`、`README.md` 四個檔案:exit 0,一項都沒命中。 - `sh /root/plugins/hooks/tools/wire-cli.sh smoke` 這一輪沒有跑,原因是它不是整支跑在沙箱裡。讀過原始碼確認:新加的相依版本那 13 條斷言確實跑在 `mktemp -d` 建出來的暫時 `HOME` 裡,工作包、重啟閘門、寫入閘門與模型來源那幾類也各自用暫時的 `$JSC_HOME`;但是前段 `smoke_one` 那 17 條(第 805 行到第 814 行、第 963 行到第 975 行)用的是這台機器真正的 `$JSC_HOME`,其中 `session-timer.sh mark` 會覆寫 `$JSC_HOME/sessions/{session}.end`,動到目前工作階段的計時狀態,腳本自己在第 971 行到第 972 行也註明那一輪用的是真正的 `$JSC_HOME`。它不會動到任何 CLI 的設定檔或 hook 接線,那是 `wire` 與 `purge` 才會做的事,但它仍然不是唯讀,所以這一輪不跑。請在乾淨的容器或拋棄式環境裡補跑一次,確認 `status=ok` 而且 `lines` 是 77 行。 ## 前置 Push Request - 無
jiantw83 added 5 commits 2026-08-31 05:41:48 +00:00
版本前置檢查多一種擋人情況。技能所屬 plugin 的 manifest 在 jsc.requires
宣告的相依 plugin,只要有一項的本機實際載入版本落後宣告的最低版本,
就以 exit 2 擋下這一次技能呼叫。訊息逐項講明哪一個 plugin、需要哪一版、
目前哪一版、怎麼補。

相依宣告原本只有部署那一端會回報,沒有任何一道閘門擋。機器上因此會出現
版本互相搭不起來的 plugin 組合,技能跑到一半才失敗,使用者也看不出要更新
哪一個 plugin。

判定邏輯自己實作,不呼叫 jsc-cli 的 check-requires.sh。hook 一律專屬存放在
jsc-hooks,不可散落到別的 domain;jsc-cli 也已經宣告相依 jsc-hooks,
反向呼叫會做出循環相依。安裝路徑解析抽成 install_path(),與本機載入版本
共用同一條規則,各寫一份就會漂移。相依檢查排在豁免清單與逃生門之後、
遠端比對之前,全部讀本機檔案,離線的機器也判得動。豁免沿用同一份 7 項清單,
相依落後不另立短清單:這幾支同樣是更新與修復的唯一路徑,用哪一個理由擋
都是死鎖。四種情況一律安靜放行:解不出安裝路徑、讀不到 manifest、
manifest 沒有 jsc.requires、讀不到相依 plugin 的本機載入版本。五支 CLI
只有 claude 讀得到本機載入版本,fail-closed 會把另外四支整批鎖死。

所屬功能:版本前置檢查的相依版本閘門。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
接線腳本的 smoke 多一個沙箱,逐條跑相依版本檢查的判定路徑並比對結束碼:
相依落後的擋人與訊息內容、相依相等與超前的放行、豁免技能在相依落後時
照樣放行、同一個 plugin 底下非豁免技能照樣被擋、四種 fail-open、
逃生門蓋過相依落後,另加一條回歸——多行縮排的 manifest,jsc.requires
的最後一個鍵也要解得到。

原本的 hook 模式只驗那支腳本跑得完,相依版本這一段一條判定路徑都沒走到。
新的擋人情況判錯方向,不是把每一次技能呼叫鎖死,就是整道護欄形同虛設,
沒有斷言就看不出來。多行縮排是真實 manifest 的樣子,解析漏掉最後一個鍵
會讓落後的相依靜靜被放行,那一條非釘住不可。

沙箱自備一份暫時的 HOME,註冊檔路徑由 $HOME 決定,不覆寫就會讀到使用者
真正的安裝清單。假的 installed_plugins.json 與各 plugin 的 manifest 都放進
那份 HOME,註冊欄位故意寫成很新的版本、installPath 底下的 manifest 寫舊版,
把「只認 installPath 底下那份檔案」的規則一起釘住。GITEA_HOST 一律清空,
放行的案例才不會往下走到遠端比對真的連網。擋人的兩條另外比訊息字串,
比的是同一次執行留下的輸出。新增計數器 smoke_n_vg 與預期值
SMOKE_EXPECT_VG,一併納入總數、逐類比對訊息與結果摘要,判定路徑增減時
只改腳本裡的預期值。

所屬功能:版本前置檢查的相依版本閘門。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
比較表的 version-guard.sh 那一列改寫成擋兩種情況,逐項寫明相依版本檢查
讀哪一份 manifest、比哪一個版本、訊息講到什麼程度,也把新增的四種
fail-open 併進原本的放行清單,並註明兩種擋人情況共用同一份 7 項豁免清單。
wire-cli.sh 那一列補一句新的冒煙沙箱與它涵蓋的判定路徑。

文件停在只擋一種情況的舊敘述,讀的人會以為相依落後照樣放行,被擋下來時
找不到規則的出處。冒煙那一列不提新沙箱,維護者也看不出相依版本這一段
已經有斷言守著。

兩種擋人情況、fail-open 清單與共用的豁免清單都寫進表格,清單的唯一真實
來源仍然指向 hooks/version-guard.sh 的檔頭。冒煙那一句只講沙箱與涵蓋範圍,
不抄斷言條數;條數以腳本自己印出來的 lines 那一行為準,散文不另記一份數字。

所屬功能:版本前置檢查的相依版本閘門。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
新增 references/behaviors.md,逐支列出本存取庫 hooks-install 與 repair
兩支技能的行為:觸發時機、關鍵步驟、外部呼叫、完成條件與可驗證跡象。

技能驗證原本沒有一份基準可比。驗的人只能回頭讀技能內文,讀到的是當下的
寫法,不是講好的行為;技能改壞了、少走一道關卡,比對不出來。

一支技能一張表,一項一列,內容寫成看得出對錯的敘述,可驗證跡象逐條指到
磁碟上真的留得下的東西。技能異動時,在同一個 PR 內一起更新這一頁。

所屬功能:技能驗證基準。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
plugin.json、.claude-plugin/plugin.json 與 .codex-plugin/plugin.json
的版本一起從 0.3.2 推到 0.3.3。

這一輪改了版本前置檢查的行為,多擋一種情況。版本不推上去,版本前置檢查
就看不出機器上載入的是舊版,使用者會拿舊的閘門跑新的流程,相依落後
一樣不會被擋下來。

三份設定檔改成同一個版本,避免不同 CLI 讀到不一樣的宣告。

所屬功能:版本前置檢查的相依版本閘門。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jiantw83 merged commit 30c395b4d0 into feat/skill-behaviors-and-version-block/main 2026-08-31 08:09:22 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Reference: plugins/hooks#54