feat(cli): 部署收尾產生更新與移除指引,並掛上部署後重啟閘門 #28

Merged
admin merged 7 commits from feat/skillset-governance/main into develop 2026-08-27 08:54:45 +00:00
Member

PR 描述

摘要

  • 需求描述:使用者提出的 15 條工作規則中,群三(技能組治理)的兩條落在本存取庫。R9 要求部署後產生「更新」與「移除」兩份指引,讓下一次更新或整組移除的人手上有這台機器真正的指令。R15 要求部署後強制重啟,本存取庫負責掛上閘門、把重啟指示寫進部署收尾的回報。另外 tools/config-spec.tsv 補上這一批新增的設定,讓 scan-config.sh 掃得到。決策紀錄在 wiki knowledges/QUESTION 的 QUESTION_FB8DF0B5(2026-08-27 兩節共 12 題)。本 PR 是主幹 feat/skillset-governance/main 併回 develop 的釋出 PR,內容為已合併的子功能 PR #27。
  • 計畫名稱:無
  • 計畫頁:無
  • 分析頁:無

變更內容

檔案 為什麼改
tools/write-guides.sh 新增腳本。整份覆寫 $JSC_HOME/update-guide.md 與 $JSC_HOME/remove-guide.md,內容一律依實際偵測結果生成。退出碼:兩份都寫成 0、參數錯誤 2、目錄或檔案寫不進去 4
tools/deploy.sh 新增 mark_restart,install 或 update 全數成功時轉呼叫 jsc-hooks 的 restart-gate.sh require,並多印一行 restart<TAB>{路徑}。restart_gate_sh 依環境變數、並排工作樹、plugin 快取三個順序找那支腳本
skills/deploy/SKILL.md 原第 7 步的回報拆成三步:新增第 7 步整台機器跑一次 write-guides.sh、第 8 步回報、新增第 9 步收尾印出重啟指示與兩份指引路徑。description 同步補上這兩件收尾
tools/config-spec.tsv 補九列:JSC_RESTART_GATE、JSC_WIKI_REPO_SKILLSET、JSC_LANG_GUARD、JSC_COMMENT_SCOPE、JSC_CHANGED_FILE、JSC_SIMPLIFIED_FILE、$JSC_HOME/update-guide.md、$JSC_HOME/remove-guide.md、$JSC_HOME/restart-required。前六列裡有四項是既有但一直沒登記的設定
README.md 補上兩份指引、重啟狀態檔與新增的環境變數
plugin.json、.claude-plugin/plugin.json、.codex-plugin/plugin.json 三份 manifest 同步升版至 0.1.9

設計重點

  • deploy.sh 不自己寫狀態檔,轉呼叫 restart-gate.sh require。 這是實作期間攔下的第二個實質問題。起初 deploy.sh 自己寫了一份四欄 TSV,而 jsc-hooks 那端讀的是 key=value,結果狀態檔存在卻解不出欄位。改成轉呼叫之後,狀態檔的路徑、格式與判讀只留在 jsc-hooks/hooks/restart-gate.sh 一處,比照 jsc-sdlc 轉呼叫 sdlc-gate.sh wp-lock 的既有慣例。兩邊各拼一份格式,遲早會再對不上一次。
  • 找不到 restart-gate.sh 時不自己補寫一份。 這種情況只印 note 行說明這次沒掛上閘門。閘門本來就由 jsc-hooks 判讀,它不在就沒有判定點,硬寫下去只是留一個沒人讀的檔案,還會讓下一輪誤以為閘門掛上了。
  • 指引的指令字面來自 deploy.sh 的 dry-run,不另抄一份。 write-guides.sh 的 CLI 清單來自 detect-clis.sh,每支 CLI 的實際指令來自 deploy.sh -n 的輸出,kiro 走不走本地複製退路也是讀 deploy.sh 的 note 行判斷,不自己再探測一次。各 CLI 的指令差異只有 deploy.sh 一個真實來源,這裡再抄一份就會有兩套指令,改了一邊忘了另一邊,指引就開始騙人。
  • 指引一台機器跑一次,不隨每支 CLI 跑。 write-guides.sh 在第 5 步所有 CLI 都跑完之後才執行一次:deploy.sh 的職責是「對單一 CLI 部署」,而指引寫的是整台機器的樣貌。uninstall 模式不跑,指引描述的是一組已安裝的技能組。
  • uninstall 不掛閘門。 mark_restart 只在 install 或 update 生效,dry-run 也不掛。移除之後沒有新版要載入,擋人沒有意義。
  • 收尾的重啟指示用固定字句,並同時給出兩份指引的路徑。 第 9 步規定印出「請關閉目前的工作階段並重新啟動,新的技能內容才會載入」,並在同一段講明狀態檔位置與 JSC_RESTART_GATE=off 逃生門。操作者需要知道的三件事——重啟、狀態檔、指引在哪——在同一個區塊講完。
  • config-spec.tsv 順手補上四項既有卻沒登記的設定。 JSC_LANG_GUARD、JSC_COMMENT_SCOPE、JSC_CHANGED_FILE、JSC_SIMPLIFIED_FILE 早就在用,只是從未進規格表。這批既然要補列,就一併補齊,讓 scan-config.sh orphans 的零回報是真的零。

測試結果

  • tools/ste100-lint.sh 掃本存取庫全綠。
  • 三份 manifest(plugin.json、.claude-plugin/plugin.json、.codex-plugin/plugin.json)版本一致,皆為 0.1.9。
  • tools/config-spec.tsv 每一列欄位數一致;tools/scan-config.sh orphans 零回報,也就是程式碼裡用到的設定項在規格表都查得到。
  • cli 與 hooks 的跨存取庫狀態檔對齊實測:deploy.sh 轉呼叫 restart-gate.sh require 寫出的狀態檔,由 restart-gate.sh 的 hook 模式讀得出 at、mode、domains、cli 四個欄位並正確擋下技能呼叫。這一項就是修掉四欄 TSV 對 key=value 那個問題之後補上的驗證。
  • jsc-hooks 那批的重啟閘門實測(擋下、九支豁免、逃生門 JSC_RESTART_GATE=off、新工作階段清除)與 wire-cli.sh smoke claude 回 status=ok、14 項判定路徑符合預期,一併涵蓋本存取庫依賴的 require 子命令。
  • 未測試項目:write-guides.sh 只在本機偵測到的 CLI 組合上跑過,未涵蓋所有五支 CLI 同時安裝的機器;4 這個「目錄或檔案寫不進去」的退出碼未實測。另外非 claude 的四支 CLI(codex、copilot、antigravity、kiro)上的重啟閘門一次都擋不下來:那四支接不上 PreToolUse,沒有任何判定點,狀態檔照樣寫、下次工作階段開始照樣清,重啟只能靠本存取庫第 9 步收尾的提示由使用者自己動手。這是無法測試,不是還沒測試。

前置 Push Request

  • 無未結清的前置 PR。本存取庫的 tools/deploy.sh 依賴 jsc-hooks 的 hooks/restart-gate.sh(require 子命令與狀態檔格式),該檔已隨子功能 PR plugins/hooks#33 合併進 hooks 的主幹 feat/skillset-governance/main,跨存取庫依賴在主幹層已結清。合併順序上仍建議 hooks 的釋出 PR 先進 develop,本 PR 再進,避免 develop 上出現部署找不到 restart-gate.sh、只印 note 行的狀態。
# PR 描述 ## 摘要 - 需求描述:使用者提出的 15 條工作規則中,群三(技能組治理)的兩條落在本存取庫。R9 要求部署後產生「更新」與「移除」兩份指引,讓下一次更新或整組移除的人手上有這台機器真正的指令。R15 要求部署後強制重啟,本存取庫負責掛上閘門、把重啟指示寫進部署收尾的回報。另外 `tools/config-spec.tsv` 補上這一批新增的設定,讓 `scan-config.sh` 掃得到。決策紀錄在 wiki `knowledges/QUESTION` 的 `QUESTION_FB8DF0B5`(2026-08-27 兩節共 12 題)。本 PR 是主幹 `feat/skillset-governance/main` 併回 `develop` 的釋出 PR,內容為已合併的子功能 PR #27。 - 計畫名稱:無 - 計畫頁:無 - 分析頁:無 ## 變更內容 | 檔案 | 為什麼改 | | --- | --- | | `tools/write-guides.sh` | 新增腳本。整份覆寫 `$JSC_HOME/update-guide.md` 與 `$JSC_HOME/remove-guide.md`,內容一律依實際偵測結果生成。退出碼:兩份都寫成 `0`、參數錯誤 `2`、目錄或檔案寫不進去 `4` | | `tools/deploy.sh` | 新增 `mark_restart`,install 或 update 全數成功時轉呼叫 `jsc-hooks` 的 `restart-gate.sh require`,並多印一行 `restart<TAB>{路徑}`。`restart_gate_sh` 依環境變數、並排工作樹、plugin 快取三個順序找那支腳本 | | `skills/deploy/SKILL.md` | 原第 7 步的回報拆成三步:新增第 7 步整台機器跑一次 `write-guides.sh`、第 8 步回報、新增第 9 步收尾印出重啟指示與兩份指引路徑。description 同步補上這兩件收尾 | | `tools/config-spec.tsv` | 補九列:`JSC_RESTART_GATE`、`JSC_WIKI_REPO_SKILLSET`、`JSC_LANG_GUARD`、`JSC_COMMENT_SCOPE`、`JSC_CHANGED_FILE`、`JSC_SIMPLIFIED_FILE`、`$JSC_HOME/update-guide.md`、`$JSC_HOME/remove-guide.md`、`$JSC_HOME/restart-required`。前六列裡有四項是既有但一直沒登記的設定 | | `README.md` | 補上兩份指引、重啟狀態檔與新增的環境變數 | | `plugin.json`、`.claude-plugin/plugin.json`、`.codex-plugin/plugin.json` | 三份 manifest 同步升版至 0.1.9 | ## 設計重點 - **`deploy.sh` 不自己寫狀態檔,轉呼叫 `restart-gate.sh require`。** 這是實作期間攔下的第二個實質問題。起初 `deploy.sh` 自己寫了一份四欄 TSV,而 `jsc-hooks` 那端讀的是 key=value,結果狀態檔存在卻解不出欄位。改成轉呼叫之後,狀態檔的路徑、格式與判讀只留在 `jsc-hooks/hooks/restart-gate.sh` 一處,比照 `jsc-sdlc` 轉呼叫 `sdlc-gate.sh wp-lock` 的既有慣例。兩邊各拼一份格式,遲早會再對不上一次。 - **找不到 `restart-gate.sh` 時不自己補寫一份。** 這種情況只印 `note` 行說明這次沒掛上閘門。閘門本來就由 `jsc-hooks` 判讀,它不在就沒有判定點,硬寫下去只是留一個沒人讀的檔案,還會讓下一輪誤以為閘門掛上了。 - **指引的指令字面來自 `deploy.sh` 的 dry-run,不另抄一份。** `write-guides.sh` 的 CLI 清單來自 `detect-clis.sh`,每支 CLI 的實際指令來自 `deploy.sh -n` 的輸出,kiro 走不走本地複製退路也是讀 `deploy.sh` 的 `note` 行判斷,不自己再探測一次。各 CLI 的指令差異只有 `deploy.sh` 一個真實來源,這裡再抄一份就會有兩套指令,改了一邊忘了另一邊,指引就開始騙人。 - **指引一台機器跑一次,不隨每支 CLI 跑。** `write-guides.sh` 在第 5 步所有 CLI 都跑完之後才執行一次:`deploy.sh` 的職責是「對單一 CLI 部署」,而指引寫的是整台機器的樣貌。`uninstall` 模式不跑,指引描述的是一組已安裝的技能組。 - **`uninstall` 不掛閘門。** `mark_restart` 只在 install 或 update 生效,dry-run 也不掛。移除之後沒有新版要載入,擋人沒有意義。 - **收尾的重啟指示用固定字句,並同時給出兩份指引的路徑。** 第 9 步規定印出「請關閉目前的工作階段並重新啟動,新的技能內容才會載入」,並在同一段講明狀態檔位置與 `JSC_RESTART_GATE=off` 逃生門。操作者需要知道的三件事——重啟、狀態檔、指引在哪——在同一個區塊講完。 - **`config-spec.tsv` 順手補上四項既有卻沒登記的設定。** `JSC_LANG_GUARD`、`JSC_COMMENT_SCOPE`、`JSC_CHANGED_FILE`、`JSC_SIMPLIFIED_FILE` 早就在用,只是從未進規格表。這批既然要補列,就一併補齊,讓 `scan-config.sh orphans` 的零回報是真的零。 ## 測試結果 - `tools/ste100-lint.sh` 掃本存取庫全綠。 - 三份 manifest(`plugin.json`、`.claude-plugin/plugin.json`、`.codex-plugin/plugin.json`)版本一致,皆為 0.1.9。 - `tools/config-spec.tsv` 每一列欄位數一致;`tools/scan-config.sh orphans` 零回報,也就是程式碼裡用到的設定項在規格表都查得到。 - cli 與 hooks 的跨存取庫狀態檔對齊實測:`deploy.sh` 轉呼叫 `restart-gate.sh require` 寫出的狀態檔,由 `restart-gate.sh` 的 hook 模式讀得出 `at`、`mode`、`domains`、`cli` 四個欄位並正確擋下技能呼叫。這一項就是修掉四欄 TSV 對 key=value 那個問題之後補上的驗證。 - `jsc-hooks` 那批的重啟閘門實測(擋下、九支豁免、逃生門 `JSC_RESTART_GATE=off`、新工作階段清除)與 `wire-cli.sh smoke claude` 回 `status=ok`、14 項判定路徑符合預期,一併涵蓋本存取庫依賴的 `require` 子命令。 - 未測試項目:`write-guides.sh` 只在本機偵測到的 CLI 組合上跑過,未涵蓋所有五支 CLI 同時安裝的機器;`4` 這個「目錄或檔案寫不進去」的退出碼未實測。另外**非 claude 的四支 CLI(codex、copilot、antigravity、kiro)上的重啟閘門一次都擋不下來**:那四支接不上 `PreToolUse`,沒有任何判定點,狀態檔照樣寫、下次工作階段開始照樣清,重啟只能靠本存取庫第 9 步收尾的提示由使用者自己動手。這是無法測試,不是還沒測試。 ## 前置 Push Request - 無未結清的前置 PR。本存取庫的 `tools/deploy.sh` 依賴 `jsc-hooks` 的 `hooks/restart-gate.sh`(`require` 子命令與狀態檔格式),該檔已隨子功能 PR `plugins/hooks#33` 合併進 hooks 的主幹 `feat/skillset-governance/main`,跨存取庫依賴在主幹層已結清。合併順序上仍建議 hooks 的釋出 PR 先進 `develop`,本 PR 再進,避免 `develop` 上出現部署找不到 `restart-gate.sh`、只印 `note` 行的狀態。
jiantw83 added 7 commits 2026-08-27 08:52:27 +00:00
What:新增 `tools/write-guides.sh`(`write-guides.sh [-n] {install|update} {domain}...`),產生 `$JSC_HOME/update-guide.md` 與 `$JSC_HOME/remove-guide.md` 兩份指引,兩份都整份覆寫。輸出 TSV 四種行別:`cli`(偵測到的 CLI)、`plan`(dry-run 時會寫入的檔案)、`wrote`(實際寫入的檔案)、`note`(非致命說明);結束碼 0 寫成、2 參數錯誤、4 目錄或檔案寫不進去。

Why:更新與移除這兩件事原本只存在於技能內文裡。CLI 壞掉、沒有工作階段、或是換人接手的時候,機器上找不到任何一份寫著「這台機器要怎麼更新、怎麼移除」的東西,只能回頭讀技能。指引落成本機檔案,不開工作階段也照著走得完。

How:內容一律依實際偵測結果生成,不寫死。CLI 清單來自 `detect-clis.sh`;每支 CLI 的指令字面直接取自 `deploy.sh -n` 的輸出,所以指引寫的就是 `deploy.sh` 真正會跑的指令——各 CLI 的差異只有 `deploy.sh` 一個真實來源,這裡再抄一份就會有兩套指令,改了一邊忘了另一邊,指引就開始騙人。kiro 走不走本地複製退路,也是讀 `deploy.sh` 的 `note` 行判斷,不自己再探測一次。獨立成一支腳本、不併進 `deploy.sh`:`deploy.sh` 的職責是「對單一 CLI 部署」,一輪部署會逐個 CLI 呼叫它,而指引寫的是整台機器的樣貌,只該產生一次;併進去還會與 `deploy.sh -n` 形成雙向遞迴。寫檔走暫存檔再 `mv`,寫一半不會留下半份指引。移除指引另外列出 plugin 指令管不到的殘留物(`$JSC_HOME`、本地 clone、kiro 技能目錄、rc 檔的 `# jsc-config` 段落)與各自清掉的影響。

Who:`/jsc-cli:deploy` 的 install 與 update 收尾,以及日後要手動更新或整組移除的操作者。
What:`tools/deploy.sh` 新增 `restart_gate_sh()` 與 `mark_restart()` 兩個函式,並在全部指令成功、印出 `result` 之前呼叫 `mark_restart`。`install` 與 `update` 會轉呼叫 `jsc-hooks` 的 `hooks/restart-gate.sh require {模式} {domain}...` 掛上重啟閘門,成功就多印一行 `restart<TAB>{狀態檔路徑}`;`uninstall` 與 dry-run 不寫。輸出行別表與檔頭的環境變數說明同步補上。

Why:部署換掉的是磁碟上的技能檔,目前工作階段載入的還是舊版。這段落差期間跑技能,改動看起來沒生效,人會以為部署失敗又重跑一次。要有一個「這台機器有一輪部署還沒重啟」的證據留在檔案上,判定那一端才擋得下來。

How:狀態檔的路徑、格式與判讀全留在 `jsc-hooks` 的 `restart-gate.sh`,這裡只轉呼叫它的 `require` 子命令,比照 `jsc-sdlc` 轉呼叫 `sdlc-gate.sh wp-lock` 的慣例。兩邊各拼一份格式就會對不上:這裡一開始自己寫四欄 TSV,而 hooks 那端讀的是 `key=value`,狀態檔存在卻解不出欄位,改成轉呼叫才修好,格式只能有一個真實來源。找腳本的順序比照 `jsc-sdlc` 的 `wp-gate.sh`:環境變數 `JSC_HOOKS_DIR` 優先,再找並排的工作樹,最後找 plugin 快取;找不到就印 `note` 行據實說「這次沒有掛上重啟閘門」,不自己補寫一份——閘門本來就由 `jsc-hooks` 判讀,它不在就沒有判定點,寫下去只是留一個沒人讀的檔案,還會讓下一輪誤以為閘門掛上了。`require` 一律接 `</dev/null`:它不讀標準輸入,但這裡的標準輸入是宿主餵進來的管線,不關掉會卡住。

Who:`/jsc-cli:deploy` 的 install 與 update 收尾,與 `jsc-hooks` 的部署後重啟閘門對接。
What:`skills/deploy/SKILL.md` 新增兩個步驟並改寫 `description`。新的第 7 步:install 或 update 在所有 CLI 跑完之後,整台機器跑一次 `tools/write-guides.sh {mode} {domain}...`,完成條件是兩份指引都印出 `wrote` 行;原本的回報順延為第 8 步;新的第 9 步:收尾一律印出重啟指示「請關閉目前的工作階段並重新啟動,新的技能內容才會載入」,並把兩份指引的路徑講出來。

Why:兩份指引與重啟提示都是部署收尾的一部分,腳本做得到、技能流程沒寫,就等於沒人會跑。重啟這件事尤其要在收尾講清楚:`deploy.sh` 已經把這一輪記進 `$JSC_HOME/restart-required`,使用者不知道要重啟就會繼續用舊版技能,然後以為部署沒生效。

How:指引那一步明寫「整台機器跑一次」,排在每個 CLI 都跑完之後——第 5 步是一個 CLI 一個子代理,指引寫的卻是整台機器的樣貌,跟著 CLI 跑就會被覆寫成最後一支的內容。`uninstall` 跳過這一步:指引描述的是裝好的技能組。重啟指示用固定字句,不讓每次回報各講一套;`JSC_RESTART_GATE=off` 作為逃生門一併寫出,判讀在 `jsc-hooks`。

Who:`/jsc-cli:deploy` 技能的執行流程與收尾回報。
What:`tools/config-spec.tsv` 新增九列。這次新增的五項:`JSC_RESTART_GATE`、`JSC_WIKI_REPO_SKILLSET`、`$JSC_HOME/update-guide.md`、`$JSC_HOME/remove-guide.md`、`$JSC_HOME/restart-required`;補登既有但漏列的四項:`JSC_LANG_GUARD`、`JSC_COMMENT_SCOPE`、`JSC_CHANGED_FILE`、`JSC_SIMPLIFIED_FILE`。

Why:這一份是體檢與設定共用的唯一規格表,`scan-config.sh` 與 `/jsc-cli:doctor` 都讀它。沒登錄的設定項體檢查不到,等於機器上有一批設定沒人管;`orphans` 那一側也對不起來。準則寫的「新增設定時要同步補一列」就是為了這件事。

How:兩份指引標 `manual`,缺了就重跑 `/jsc-cli:deploy`,不由體檢自動補。`$JSC_HOME/restart-required` 與 `JSC_CHANGED_FILE`、`JSC_SIMPLIFIED_FILE` 都是執行期暫態,驗證與修法欄一律標 `none` 與 `-`:不存在是正常狀態,標成必要項會讓體檢把「沒有待重啟的部署」誤判成缺失。三個 `off` 開關(`JSC_RESTART_GATE`、`JSC_LANG_GUARD`、`JSC_COMMENT_SCOPE`)預設值一律寫 `on`,說明欄講明什麼情況才關。九列的欄位數與既有列一致為 8 欄。

Who:`scan-config.sh`、`/jsc-cli:doctor` 的執行環境體檢與 `/jsc-cli:setup` 的引導設定。
What:`README.md` 四處增修。工具表新增 `tools/write-guides.sh` 一列,`tools/deploy.sh` 那一列補上收尾寫重啟狀態檔與 `restart` 行;環境變數表新增 `JSC_HOME` 與 `JSC_RESTART_GATE` 兩列;新增「部署留在機器上的檔案」一節,用表列出三個檔案的產生時機與用途,並寫明兩份指引一律整份覆寫、`uninstall` 兩者都不產生。

Why:部署會在機器上留下三個檔案,這件事原本 README 一個字都沒寫。操作者不知道更新與移除的依據就在 `$JSC_HOME` 底下,也不知道 `restart-required` 存在代表什麼,只能去讀腳本註解。

How:三個檔案併成一張表,欄位是「何時產生」與「用途」,讓人一眼分得出哪些是可以放心刪的(指引重跑就有)、哪些有判定意義(重啟狀態檔)。閘門的判讀與逃生門明寫在 `jsc-hooks` 那一邊,`jsc-cli` 只負責寫狀態檔,避免兩份文件各寫一套判定規則。

Who:讀 `jsc-cli` 說明的操作者,以及要手動更新或移除技能組的人。
What:`plugin.json`、`.claude-plugin/plugin.json`、`.codex-plugin/plugin.json` 的 `version` 由 0.1.8 改為 0.1.9。

Why:本次新增 `write-guides.sh`、`deploy.sh` 收尾多掛一道重啟閘門、`deploy` 技能多兩個步驟,設定規格表也多九列,屬於行為變更,版本要跟著往上走,各 CLI 才知道要更新。

How:三份只改 `version` 一個欄位,其餘內容不動,三份保持同一版號。

Who:`jsc-cli` 外掛的套件描述檔。
Reviewed-on: #27
admin merged commit 07a652b309 into develop 2026-08-27 08:54:45 +00:00
admin deleted branch feat/skillset-governance/main 2026-08-27 08:54:46 +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/cli#28