fix/skill-check-compliance-and-flow #13

Merged
admin merged 4 commits from fix/skill-check-compliance-and-flow into develop 2026-08-31 03:16:18 +00:00
Member

摘要

  • 需求描述:把還原路線的前提從技能內文下放成腳本,擋在程式層;讓「停留在舊版」有對應的產生路徑;並把推不出建置與測試指令的情況提前到動任何檔案之前發現。
  • 計畫名稱:無
  • 計畫頁:無
  • 分析頁:無

變更內容

檔案 為什麼改
tools/git-guard.sh 新檔。還原會跑 git clean -fd,未追蹤檔案刪掉沒有 reflog 可救。前提只寫在技能內文擋不住誤觸,所以寫成腳本,revert 在破壞性指令之前擋五道,任一道不過就結束且不動任何檔案。
tools/build-test.sh 新增 --detect 唯讀模式。原本「推不出建置與測試指令」要等版本檔全部改寫完才發現,使用者答不出指令時前面全數作廢還得還原;唯讀模式讓呼叫方在動檔案之前就問出結果。
skills/pkg-update/SKILL.md stop 的定義說「不改任何檔案」,但步驟 3 起的 stop 已經改寫過版本檔,定義與行為對不上;「停留在舊版要寫註解」的要求沒有任何路由會產生;git 閘門排在全專案掃描之後,工作區髒時整輪白做。一併把流程由 7 步併成 5 步。
README.md 新腳本沒進工具表,讀者找不到它,也不知道還原需要 --confirm-destructive;「五支工具都靠 python3」的敘述不成立,會誤判環境需求;還原策略改了,摘要與結束碼總表要跟上。
.claude-plugin/plugin.json 描述停在「失敗還原」,與實際行為不符;補上 jsc-hooks 相依,因為註解內容由它的掃描在程式層強制;版本推進。
.codex-plugin/plugin.json 同上,三份外掛資訊檔的描述、相依與版本必須一致,否則各 CLI 讀到的說明會分歧。
plugin.json 同上,根目錄資訊檔一併同步。

設計重點

  • 還原前的五道防護寫在 git-guard.sh 裡,不寫在技能內文,依序是:目錄存在、git 指令存在、確實是 git 工作樹(不是裸存取庫)、呼叫端明確帶 --confirm-destructive、目標不是檔案系統根目錄。五道全過才會執行第一個破壞性指令,任何一道不過就回 1、4、5 或 6,工作區一個位元組都不動。
  • 判定從嚴、動手從窄:check 的乾淨判定看整個存取庫,連未追蹤的 ?? 行都算髒;revert 的 checkout 與 clean 只作用在專案目錄以下,不會波及上層。clean 固定用 -fd 不用 -fdx,被 gitignore 的 node_modules、__pycache__、bin、obj 要留著。
  • build-test.sh --detect 是唯讀模式,只做偵測與前置檢查,一個檔案都不寫,結束碼與路由跟執行模式一致。它把「推不出指令」這個問題移到工作區還完全乾淨的時候發現,使用者答不出來就在原地停手,沒有東西需要還原。
  • git 閘門前置:工作區髒的時候只付一次閘門呼叫的成本,不做整份套件盤點。
  • 新增「釘回舊版重試一次」的路由:建置或測試真的失敗時,先從失敗輸出點名嫌疑套件,釘回舊版、重裝、重試一次;過了就標記成停留在舊版,仍失敗才還原。這條路由讓技能既有的「停留在舊版要寫註解說明原因」有了實際的產生路徑。
  • stop 照實描述:第一步之前的 stop 確實沒動過檔案,第二步起的 stop 要報出失敗工具與結束碼、已套用的套件、已改寫的版本來源檔案。
  • 結束碼總表由「一個數字一個意思」改成「一個數字一個類別」,同一個碼在各工具指的對象寫在該列,既容納新腳本的子指令與前提不成立,也不動既有的跳過路由。

測試結果

  • 語法檢查:sh -n tools/git-guard.sh 與 sh -n tools/build-test.sh 都回 0。
  • git-guard.sh 用法與前提,全程未執行任何破壞性還原:
    • 無參數:印出用法,結束碼 1。
    • 子命令給 bogus:印出未知子命令,結束碼 2。
    • revert 故意不帶旗標:印出用法,結束碼 1,工作區完全沒動。
    • check 指向不存在的目錄:印出找不到專案目錄,結束碼 6。
    • check 指向非 git 目錄:印出不是 git 存取庫,結束碼 5。
    • check 指向乾淨的存取庫:印出 check ok,結束碼 0。
    • check 指向髒的工作區:印出未乾淨,並附上原始的 git status --porcelain 輸出,結束碼 5。
  • build-test.sh --detect 唯讀模式:
    • nodejs,臨時專案備妥 build 與 test 指令:兩者都印出,結束碼 0,專案目錄事後檢查沒有被改動。
    • nodejs,空目錄:印出推不出建置與測試指令,結束碼 5。
    • python,臨時專案備妥測試檔,本機沒有 pytest:印出 pytest 不存在,結束碼 4。
    • dotnet,臨時專案備妥專案檔,本機沒有 dotnet:印出 dotnet 不存在,結束碼 4。
    • 生態系給 ruby:印出未知生態系,結束碼 2。
    • nodejs 指向不存在的目錄:結束碼 6。
    • 少一個參數:印出用法,結束碼 1。
  • 未測項目與原因:
    • 對真的有改動的工作區執行 revert,未測。這是破壞性動作,本輪不執行。
    • 檔案系統根目錄那道防線未實際執行,改以讀碼確認:revert / 會先被「確實是 git 工作樹」擋在前面,根目錄那道是路徑組錯時的最後一層,兩道都排在第一個破壞性指令之前。
    • nodejs 以外生態系的實際建置與測試執行未測,本機沒有 pytest 與 dotnet,只驗到「指令不存在」這條分支。

前置 Push Request

  • 無
## 摘要 - 需求描述:把還原路線的前提從技能內文下放成腳本,擋在程式層;讓「停留在舊版」有對應的產生路徑;並把推不出建置與測試指令的情況提前到動任何檔案之前發現。 - 計畫名稱:無 - 計畫頁:無 - 分析頁:無 ## 變更內容 | 檔案 | 為什麼改 | | --- | --- | | `tools/git-guard.sh` | 新檔。還原會跑 `git clean -fd`,未追蹤檔案刪掉沒有 reflog 可救。前提只寫在技能內文擋不住誤觸,所以寫成腳本,`revert` 在破壞性指令之前擋五道,任一道不過就結束且不動任何檔案。 | | `tools/build-test.sh` | 新增 `--detect` 唯讀模式。原本「推不出建置與測試指令」要等版本檔全部改寫完才發現,使用者答不出指令時前面全數作廢還得還原;唯讀模式讓呼叫方在動檔案之前就問出結果。 | | `skills/pkg-update/SKILL.md` | stop 的定義說「不改任何檔案」,但步驟 3 起的 stop 已經改寫過版本檔,定義與行為對不上;「停留在舊版要寫註解」的要求沒有任何路由會產生;git 閘門排在全專案掃描之後,工作區髒時整輪白做。一併把流程由 7 步併成 5 步。 | | `README.md` | 新腳本沒進工具表,讀者找不到它,也不知道還原需要 `--confirm-destructive`;「五支工具都靠 python3」的敘述不成立,會誤判環境需求;還原策略改了,摘要與結束碼總表要跟上。 | | `.claude-plugin/plugin.json` | 描述停在「失敗還原」,與實際行為不符;補上 jsc-hooks 相依,因為註解內容由它的掃描在程式層強制;版本推進。 | | `.codex-plugin/plugin.json` | 同上,三份外掛資訊檔的描述、相依與版本必須一致,否則各 CLI 讀到的說明會分歧。 | | `plugin.json` | 同上,根目錄資訊檔一併同步。 | ## 設計重點 - 還原前的五道防護寫在 `git-guard.sh` 裡,不寫在技能內文,依序是:目錄存在、git 指令存在、確實是 git 工作樹(不是裸存取庫)、呼叫端明確帶 `--confirm-destructive`、目標不是檔案系統根目錄。五道全過才會執行第一個破壞性指令,任何一道不過就回 1、4、5 或 6,工作區一個位元組都不動。 - 判定從嚴、動手從窄:`check` 的乾淨判定看整個存取庫,連未追蹤的 `??` 行都算髒;`revert` 的 `checkout` 與 `clean` 只作用在專案目錄以下,不會波及上層。`clean` 固定用 `-fd` 不用 `-fdx`,被 gitignore 的 `node_modules`、`__pycache__`、`bin`、`obj` 要留著。 - `build-test.sh --detect` 是唯讀模式,只做偵測與前置檢查,一個檔案都不寫,結束碼與路由跟執行模式一致。它把「推不出指令」這個問題移到工作區還完全乾淨的時候發現,使用者答不出來就在原地停手,沒有東西需要還原。 - git 閘門前置:工作區髒的時候只付一次閘門呼叫的成本,不做整份套件盤點。 - 新增「釘回舊版重試一次」的路由:建置或測試真的失敗時,先從失敗輸出點名嫌疑套件,釘回舊版、重裝、重試一次;過了就標記成停留在舊版,仍失敗才還原。這條路由讓技能既有的「停留在舊版要寫註解說明原因」有了實際的產生路徑。 - stop 照實描述:第一步之前的 stop 確實沒動過檔案,第二步起的 stop 要報出失敗工具與結束碼、已套用的套件、已改寫的版本來源檔案。 - 結束碼總表由「一個數字一個意思」改成「一個數字一個類別」,同一個碼在各工具指的對象寫在該列,既容納新腳本的子指令與前提不成立,也不動既有的跳過路由。 ## 測試結果 - 語法檢查:`sh -n tools/git-guard.sh` 與 `sh -n tools/build-test.sh` 都回 0。 - `git-guard.sh` 用法與前提,全程未執行任何破壞性還原: - 無參數:印出用法,結束碼 1。 - 子命令給 `bogus`:印出未知子命令,結束碼 2。 - `revert` 故意不帶旗標:印出用法,結束碼 1,工作區完全沒動。 - `check` 指向不存在的目錄:印出找不到專案目錄,結束碼 6。 - `check` 指向非 git 目錄:印出不是 git 存取庫,結束碼 5。 - `check` 指向乾淨的存取庫:印出 check ok,結束碼 0。 - `check` 指向髒的工作區:印出未乾淨,並附上原始的 `git status --porcelain` 輸出,結束碼 5。 - `build-test.sh --detect` 唯讀模式: - nodejs,臨時專案備妥 build 與 test 指令:兩者都印出,結束碼 0,專案目錄事後檢查沒有被改動。 - nodejs,空目錄:印出推不出建置與測試指令,結束碼 5。 - python,臨時專案備妥測試檔,本機沒有 pytest:印出 pytest 不存在,結束碼 4。 - dotnet,臨時專案備妥專案檔,本機沒有 dotnet:印出 dotnet 不存在,結束碼 4。 - 生態系給 `ruby`:印出未知生態系,結束碼 2。 - nodejs 指向不存在的目錄:結束碼 6。 - 少一個參數:印出用法,結束碼 1。 - 未測項目與原因: - 對真的有改動的工作區執行 `revert`,未測。這是破壞性動作,本輪不執行。 - 檔案系統根目錄那道防線未實際執行,改以讀碼確認:`revert /` 會先被「確實是 git 工作樹」擋在前面,根目錄那道是路徑組錯時的最後一層,兩道都排在第一個破壞性指令之前。 - nodejs 以外生態系的實際建置與測試執行未測,本機沒有 pytest 與 dotnet,只驗到「指令不存在」這條分支。 ## 前置 Push Request - 無
jiantw83 added 4 commits 2026-08-31 03:10:07 +00:00
What:新增 `tools/git-guard.sh`,把工作區乾淨檢查與還原序列從技能內文搬進腳本。`tools/build-test.sh` 加上 `--detect` 唯讀模式,只偵測建置與測試指令,不執行。

Why:還原會執行 `git clean -fd`。這個指令刪掉未追蹤的檔案,沒有 reflog 可救,也沒有任何救回的路徑。前提原本只寫在技能內文,讀的人漏掉一行,就可能對著一個根本不該還原的目錄動手,把整個工作區的未追蹤檔案清光。前提要擋得住,就得寫成程式碼。另一件事是「推不出建置與測試指令」,原本要等所有版本來源檔案都改寫完才發現,使用者又答不出指令時,前面全部作廢,還得走一次還原。

How:`revert` 在跑第一個破壞性指令之前擋五道——目錄存在、git 指令存在、確實是 git 工作樹(不是裸存取庫)、呼叫端明確帶 `--confirm-destructive`、目標不是檔案系統根目錄。任何一道不過就直接結束,工作區一個位元組都不動。`check` 的乾淨判定看整個存取庫,`revert` 只作用在專案目錄以下,判定從嚴、動手從窄。`clean` 用 `-fd` 不用 `-fdx`,被 gitignore 的安裝產物要留著。`--detect` 只做偵測與前置檢查,一個檔案都不寫,結束碼與路由跟執行模式完全一致。

Who:套件批次更新的前置檢查與還原路線。
What:改寫 stop 路由的定義,新增「把嫌疑套件釘回舊版重試一次」的路由,把 git 閘門提到最前面,流程由七步併成五步。

Why:原本寫 stop「不改任何檔案」,但流程走到後段才 stop 時,版本來源檔案已經被改寫過。定義跟行為對不上,使用者會以為工作區沒動過,實際上留了一地改過的檔案沒人回報。另外技能要求「套件停留在舊版時要寫註解說明原因」,卻沒有任何一條路由會產生停留在舊版的結果,這個要求等於永遠踩不到。閘門排在套件盤點後面也不划算,工作區髒的時候,整輪全專案掃描白做。

How:stop 照實描述——第一步之前確實沒動過檔案;第二步起的 stop 要一併報出失敗工具與結束碼、已套用的套件、已改寫的版本來源檔案。建置或測試真的失敗時,先從失敗輸出點名嫌疑套件,把它們釘回舊版,重裝後只重試一次;重試過了就算通過,並標記成停留在舊版,仍失敗才走還原。git 閘門移到第一步的第一個動作,建置與測試指令也在動任何檔案之前先問清楚。

Who:pkg-update 的路由表與流程步驟。
What:工具表補上還原閘門腳本一列與 `--detect` 用法,新增「還原的破壞性前提」一節,改寫結束碼總表與技能摘要。

Why:新腳本沒進工具表,讀 README 的人找不到它,也不知道還原多了一個必要旗標。原本寫「五支工具都靠 python3」也不對——新的閘門腳本只用 git,安裝那支根本不碰 python3,照著讀會誤判環境需求。還原策略已經改成先釘回舊版再重試,摘要卻還停在舊寫法。

How:工具表逐支列出真正需要的指令。新增一節寫清楚 `git clean -fd` 的風險與那五道前提,並說明判定從嚴、動手從窄。結束碼總表改成「一個數字一個類別」,同一個碼在各工具指的對象寫在該列裡。技能摘要改成先把嫌疑套件釘回舊版重試一次,真失敗才還原。

Who:pkg domain 的說明文件。
What:三份外掛資訊檔的描述改成「先把嫌疑套件釘回舊版重試一次,真失敗才還原」,補上 jsc-hooks 相依,版本號往前推一版。

Why:描述停在「失敗還原」,跟現在的行為不一樣,使用者從外掛清單看到的是錯的說明。技能靠 jsc-hooks 的註解掃描在程式層把關註解內容,相依沒宣告的話,環境缺了它也沒人擋得住。

How:claude、codex 與根目錄三份資訊檔一起改,欄位內容保持一致。

Who:jsc-pkg 外掛的中繼資料。
admin merged commit c9e1f52709 into develop 2026-08-31 03:16:18 +00:00
admin deleted branch fix/skill-check-compliance-and-flow 2026-08-31 03:16:18 +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/pkg#13