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

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

摘要

  • 需求描述:tools/model-tags.sh 的 gate 用同一個結束碼表示「模型缺標籤」與「腳本被叫錯」,delegate 因此把用法錯誤讀成模型不合格,默默丟掉可用的模型。順著這條線把五支技能的合規缺口一併補齊:補上每一步的完成條件、改掉不存在的 plugin 引用、把腳本早就做得到的事從文字敘述換成腳本呼叫,並讓每一次腳本呼叫都依結束碼分流。同時把 doctor 與 setup 各寫一次的「待修項目」合併規則收成共用腳本 tools/build-todo.sh,並讓互不相干的檢查改為併行。版本推進到 0.2.5。
  • 計畫名稱:無
  • 計畫頁:無
  • 分析頁:無

變更內容

檔案 為什麼改
tools/model-tags.sh usage 原本結束碼 1,與 gate 的「模型缺標籤」撞在一起。呼叫端分不出自己打錯指令,還是模型不夠格。改成 2,並在檔頭寫出全域結束碼約定:0 通過、1 缺標籤或沒寫出檔案、2 用法錯誤與兩種無法判定
tools/model-config.sh 與 model-tags.sh 是同一組腳本,usage 一併改成 2,兩支的結束碼契約才一致。檔頭補上結束碼宣告
tools/check-requires.sh 機器沒有 python3 時,腳本直接讓 shell 回 127,呼叫端看到一個沒宣告過的碼,也讀不到原因。改成先檢查 python3,印出 status=blocked 與理由再結束,jsc.requires 這項宣告才是真的檢查得到
skills/delegate/SKILL.md 七個步驟一個完成條件都沒有;引用了不存在的 plugin;CLI 偵測與標籤篩選寫成文字敘述,可是腳本早就存在;第四步需要模型 id,前面卻沒有任何步驟產得出來。整篇重寫:每步一個完成條件、資料一律取自 detect-clis.sh 與 list-models.sh、合格與否由 model-tags.sh gate 的三個結束碼判定、回傳採固定 TSV 契約逐項驗證
skills/setup/SKILL.md 環境變數重驗去讀目前這個 shell,而寫進 rc 檔的值要等新 shell 起來才存在,所以重驗永遠回報「沒設到」。改成只驗 rc 段落裡確實有那一行。另外補上重建清單的併行、build-todo.sh 合併、apply-config.sh 結束碼分流,並把已確認的模式與版本報告傳給 deploy
tools/build-todo.sh 新增。「待修項目」的合併與排序規則原本 doctor 與 setup 各寫一次,兩邊遲早漂移。收成一支腳本:吃三種輸入、固定排成 missing、invalid、unwired、落後,一項都沒有時仍印一列「無」
tools/config-spec.tsv 登錄新的環境變數 JSC_WIKI_REPO_TOOLING,技能盤點頁 TOOLING_CONTENTS 與 TOOLING_{HASH} 才有指定的 repo 可寫;沒登錄的變數會被 scan-config.sh orphans 抓成漏登錄
templates/check-page.md 待修項目表的欄位改成對齊 build-todo.sh 的 todo 列(多出「類別」欄,「判定」換成「現況」),排序交給腳本,範本這裡不再另訂一套
templates/check-contents.md 補上寫入語意:目錄頁一列一台機器,要先讀回再更新自己那一列。整頁覆蓋會把別台機器的紀錄抹掉,而這個寫入沒有備份也沒有合併
skills/doctor/SKILL.md 四項檢查彼此不共用資料,改為同時啟動;設定掃描一次跑 scan all 涵蓋全域與專案兩個範圍;待修項目改呼叫 build-todo.sh;每支腳本補結束碼分流;所有 wire-cli.sh 呼叫一律帶 JSC_READONLY=1,把「打錯子命令就改檔或刪檔」的風險移進程式層;CHECK_CONTENTS 改為讀回後 upsert
skills/deploy/SKILL.md CLI 偵測、版本結論、marketplace domain 清單三者互不相干,改為併行;版本結論改讀 version-guard.sh recommend 的單行輸出,並保留舊版沒有這個子命令時的降級路徑;每個 CLI 的 sub agent 全部同時啟動;新增呼叫方可傳入的模式與版本報告,讓 setup 不必被重問一次;deploy.sh、write-guides.sh 補結束碼分流
skills/models/SKILL.md 三支取資料的腳本改為併行,階段偏好模型鏈提前一起取;model-tags.sh sync 補上結束碼分流,並寫明 2 這個碼永遠不代表模型不合格
tools/detect-clis.sh 檔頭補上結束碼宣告。這支腳本一律回 0,找不到執行檔只是不輸出那一列。約定不寫出來,呼叫端就會拿結束碼判斷「有沒有裝到 CLI」。行為未動
tools/list-models.sh 同上。讀不到設定檔只是少掉那個 CLI 的列,不算失敗,檔頭補上宣告。行為未動
README.md 腳本表補上 build-todo.sh,model-tags.sh 那列補上 gate 的三個結束碼;五支技能的說明同步改寫成併行與腳本判定後的流程,讓 README 與技能內容一致
plugin.json jsc.requires 補 jsc-ask,版本推進到 0.2.5
.claude-plugin/plugin.json 同上,Claude CLI 讀的 manifest
.codex-plugin/plugin.json 同上,Codex 讀的 manifest

設計重點

  • 同一個結束碼不可以承載兩種語意。 gate 的 1 只留給「模型缺標籤」,用法錯誤與兩種無法判定一律走 2。兩者共用一個碼時,呼叫端會把自己打錯的指令讀成模型不夠格,把可用的模型默默丟掉,錯在哪永遠不會浮出來。model-config.sh 照同一套調整,五支腳本的檔頭都寫出自己的結束碼表。
  • 判斷放在程式裡,技能只說什麼時候呼叫、每個碼怎麼解讀。 CLI 清單來自 detect-clis.sh,模型清單來自 list-models.sh,合格與否來自 model-tags.sh gate。技能不再用文字敘述重講一次腳本做過的事,也不讓模型自評自己的能力標籤。
  • 唯讀契約寫進環境變數,不靠指令打對。 doctor 與 setup 取狀態時,wire-cli.sh 一律帶 JSC_READONLY=1。打錯一個子命令會被拒絕,而不是把只該被量測的機器重新接線或刪掉檔案。
  • 每一步都要有完成條件。 沒有完成條件的步驟無法判斷做完沒有,delegate 原本七步全數如此。現在每一步都寫出「做到什麼算完成」,delegate 更要求驗收條件本身可以只憑子代理回傳的文字判 pass 或 fail。
  • 互不相干的工作併行,會互相影響的維持循序。 doctor 的四項檢查、deploy 的三項前置、models 的三支收集腳本、setup 的重驗都改成併行。setup 的逐項確認刻意保持循序:前一個答案會改變下一項該怎麼做。
  • 同一份合併規則只留一個真實來源。 build-todo.sh 的輸入是三支檢查腳本的輸出,它自己不執行任何檢查,維持唯讀。空輸入視為用法錯誤(結束碼 2),因為空跑會印出「沒有待修項目」,那是假通過。
  • 內容頁整頁覆蓋,目錄頁先讀回再 upsert。 CHECK_{HASH} 只留最新一次,整頁改寫是對的;CHECK_CONTENTS 一列一台機器,同樣做法會抹掉別人的紀錄。讀回時只有結束碼 4 開啟建立路徑,7 與 8 代表舊資料狀態不明,一律不寫。
  • 重驗要驗「已經成立的事實」。 rc 檔寫進去的變數,要等新 shell 起來才進得了環境。重驗改成確認 rc 段落裡有那一行,環境層面交給下一次 /jsc-cli:doctor,因為它本來就在新的 shell 裡開始。

測試結果

  • sh -n 語法檢查六支腳本全數通過:build-todo.sh、check-requires.sh、detect-clis.sh、list-models.sh、model-config.sh、model-tags.sh。
  • python3 -m json.tool 檢查三份 manifest 全數為有效 JSON:plugin.json、.claude-plugin/plugin.json、.codex-plugin/plugin.json,三份的版本一致為 0.2.5,且都含 jsc-ask 相依。
  • tools/config-spec.tsv 欄位盤點:61 列資料每列皆為 8 欄,16 列為註解或空行;新增的 JSC_WIKI_REPO_TOOLING 列確認為 8 欄。
  • 結束碼實測,model-tags.sh:子命令打錯回 2、gate 缺參數回 2、gate plan {表上沒有的模型} 印 UNKNOWN-MODEL 回 2、gate {不存在的階段} {模型} 印 UNKNOWN-STAGE 回 2。對照修改前的版本,同一個 gate 缺參數的呼叫回 1,正是本次修掉的碰撞。
  • 結束碼實測,model-config.sh:子命令打錯回 2。
  • 結束碼實測,check-requires.sh:缺參數回 2、CLI 代號不在五個之內回 2、manifest 不存在印 status=blocked 回 1;把 PATH 換掉模擬沒有 python3 的機器,印出 status=blocked reason=找不到 python3… 回 1,不再是未宣告的 127。
  • build-todo.sh 實跑合併(自製三份輸入檔,未動任何專案檔案):四列 todo 依 missing、invalid、unwired、落後排出,summary 為 1 1 1 1,結束碼 0;只給一份沒有問題的設定輸出時,印出類別為「無」的單列,結束碼 0;不給任何輸入回 2;輸入檔讀不到回 3;--wiring 少了 {cli}= 前綴回 2。四種錯誤路徑都與檔頭宣告相符。
  • 全庫搜尋 jsc-shared:零筆命中,確認 delegate 引用的不存在 plugin 已完全移除。
  • 未執行的項目:deploy.sh、apply-config.sh、write-guides.sh、wire-cli.sh 會寫入機器,本次只做唯讀檢查,一律沒有執行。實際部署驗證留給合併後的 /jsc-cli:doctor 一次體檢。

前置 Push Request

無

## 摘要 - **需求描述**:`tools/model-tags.sh` 的 `gate` 用同一個結束碼表示「模型缺標籤」與「腳本被叫錯」,`delegate` 因此把用法錯誤讀成模型不合格,默默丟掉可用的模型。順著這條線把五支技能的合規缺口一併補齊:補上每一步的完成條件、改掉不存在的 plugin 引用、把腳本早就做得到的事從文字敘述換成腳本呼叫,並讓每一次腳本呼叫都依結束碼分流。同時把 `doctor` 與 `setup` 各寫一次的「待修項目」合併規則收成共用腳本 `tools/build-todo.sh`,並讓互不相干的檢查改為併行。版本推進到 0.2.5。 - **計畫名稱**:無 - **計畫頁**:無 - **分析頁**:無 ## 變更內容 | 檔案 | 為什麼改 | | --- | --- | | `tools/model-tags.sh` | `usage` 原本結束碼 1,與 `gate` 的「模型缺標籤」撞在一起。呼叫端分不出自己打錯指令,還是模型不夠格。改成 2,並在檔頭寫出全域結束碼約定:0 通過、1 缺標籤或沒寫出檔案、2 用法錯誤與兩種無法判定 | | `tools/model-config.sh` | 與 `model-tags.sh` 是同一組腳本,`usage` 一併改成 2,兩支的結束碼契約才一致。檔頭補上結束碼宣告 | | `tools/check-requires.sh` | 機器沒有 python3 時,腳本直接讓 shell 回 127,呼叫端看到一個沒宣告過的碼,也讀不到原因。改成先檢查 python3,印出 `status=blocked` 與理由再結束,`jsc.requires` 這項宣告才是真的檢查得到 | | `skills/delegate/SKILL.md` | 七個步驟一個完成條件都沒有;引用了不存在的 plugin;CLI 偵測與標籤篩選寫成文字敘述,可是腳本早就存在;第四步需要模型 id,前面卻沒有任何步驟產得出來。整篇重寫:每步一個完成條件、資料一律取自 `detect-clis.sh` 與 `list-models.sh`、合格與否由 `model-tags.sh gate` 的三個結束碼判定、回傳採固定 TSV 契約逐項驗證 | | `skills/setup/SKILL.md` | 環境變數重驗去讀目前這個 shell,而寫進 rc 檔的值要等新 shell 起來才存在,所以重驗永遠回報「沒設到」。改成只驗 rc 段落裡確實有那一行。另外補上重建清單的併行、`build-todo.sh` 合併、`apply-config.sh` 結束碼分流,並把已確認的模式與版本報告傳給 `deploy` | | `tools/build-todo.sh` | 新增。「待修項目」的合併與排序規則原本 `doctor` 與 `setup` 各寫一次,兩邊遲早漂移。收成一支腳本:吃三種輸入、固定排成 missing、invalid、unwired、落後,一項都沒有時仍印一列「無」 | | `tools/config-spec.tsv` | 登錄新的環境變數 `JSC_WIKI_REPO_TOOLING`,技能盤點頁 `TOOLING_CONTENTS` 與 `TOOLING_{HASH}` 才有指定的 repo 可寫;沒登錄的變數會被 `scan-config.sh orphans` 抓成漏登錄 | | `templates/check-page.md` | 待修項目表的欄位改成對齊 `build-todo.sh` 的 `todo` 列(多出「類別」欄,「判定」換成「現況」),排序交給腳本,範本這裡不再另訂一套 | | `templates/check-contents.md` | 補上寫入語意:目錄頁一列一台機器,要先讀回再更新自己那一列。整頁覆蓋會把別台機器的紀錄抹掉,而這個寫入沒有備份也沒有合併 | | `skills/doctor/SKILL.md` | 四項檢查彼此不共用資料,改為同時啟動;設定掃描一次跑 `scan all` 涵蓋全域與專案兩個範圍;待修項目改呼叫 `build-todo.sh`;每支腳本補結束碼分流;所有 `wire-cli.sh` 呼叫一律帶 `JSC_READONLY=1`,把「打錯子命令就改檔或刪檔」的風險移進程式層;`CHECK_CONTENTS` 改為讀回後 upsert | | `skills/deploy/SKILL.md` | CLI 偵測、版本結論、marketplace domain 清單三者互不相干,改為併行;版本結論改讀 `version-guard.sh recommend` 的單行輸出,並保留舊版沒有這個子命令時的降級路徑;每個 CLI 的 sub agent 全部同時啟動;新增呼叫方可傳入的模式與版本報告,讓 `setup` 不必被重問一次;`deploy.sh`、`write-guides.sh` 補結束碼分流 | | `skills/models/SKILL.md` | 三支取資料的腳本改為併行,階段偏好模型鏈提前一起取;`model-tags.sh sync` 補上結束碼分流,並寫明 2 這個碼永遠不代表模型不合格 | | `tools/detect-clis.sh` | 檔頭補上結束碼宣告。這支腳本一律回 0,找不到執行檔只是不輸出那一列。約定不寫出來,呼叫端就會拿結束碼判斷「有沒有裝到 CLI」。行為未動 | | `tools/list-models.sh` | 同上。讀不到設定檔只是少掉那個 CLI 的列,不算失敗,檔頭補上宣告。行為未動 | | `README.md` | 腳本表補上 `build-todo.sh`,`model-tags.sh` 那列補上 `gate` 的三個結束碼;五支技能的說明同步改寫成併行與腳本判定後的流程,讓 README 與技能內容一致 | | `plugin.json` | `jsc.requires` 補 `jsc-ask`,版本推進到 0.2.5 | | `.claude-plugin/plugin.json` | 同上,Claude CLI 讀的 manifest | | `.codex-plugin/plugin.json` | 同上,Codex 讀的 manifest | ## 設計重點 - **同一個結束碼不可以承載兩種語意。** `gate` 的 1 只留給「模型缺標籤」,用法錯誤與兩種無法判定一律走 2。兩者共用一個碼時,呼叫端會把自己打錯的指令讀成模型不夠格,把可用的模型默默丟掉,錯在哪永遠不會浮出來。`model-config.sh` 照同一套調整,五支腳本的檔頭都寫出自己的結束碼表。 - **判斷放在程式裡,技能只說什麼時候呼叫、每個碼怎麼解讀。** CLI 清單來自 `detect-clis.sh`,模型清單來自 `list-models.sh`,合格與否來自 `model-tags.sh gate`。技能不再用文字敘述重講一次腳本做過的事,也不讓模型自評自己的能力標籤。 - **唯讀契約寫進環境變數,不靠指令打對。** `doctor` 與 `setup` 取狀態時,`wire-cli.sh` 一律帶 `JSC_READONLY=1`。打錯一個子命令會被拒絕,而不是把只該被量測的機器重新接線或刪掉檔案。 - **每一步都要有完成條件。** 沒有完成條件的步驟無法判斷做完沒有,`delegate` 原本七步全數如此。現在每一步都寫出「做到什麼算完成」,`delegate` 更要求驗收條件本身可以只憑子代理回傳的文字判 pass 或 fail。 - **互不相干的工作併行,會互相影響的維持循序。** `doctor` 的四項檢查、`deploy` 的三項前置、`models` 的三支收集腳本、`setup` 的重驗都改成併行。`setup` 的逐項確認刻意保持循序:前一個答案會改變下一項該怎麼做。 - **同一份合併規則只留一個真實來源。** `build-todo.sh` 的輸入是三支檢查腳本的輸出,它自己不執行任何檢查,維持唯讀。空輸入視為用法錯誤(結束碼 2),因為空跑會印出「沒有待修項目」,那是假通過。 - **內容頁整頁覆蓋,目錄頁先讀回再 upsert。** `CHECK_{HASH}` 只留最新一次,整頁改寫是對的;`CHECK_CONTENTS` 一列一台機器,同樣做法會抹掉別人的紀錄。讀回時只有結束碼 4 開啟建立路徑,7 與 8 代表舊資料狀態不明,一律不寫。 - **重驗要驗「已經成立的事實」。** rc 檔寫進去的變數,要等新 shell 起來才進得了環境。重驗改成確認 rc 段落裡有那一行,環境層面交給下一次 `/jsc-cli:doctor`,因為它本來就在新的 shell 裡開始。 ## 測試結果 - `sh -n` 語法檢查六支腳本全數通過:`build-todo.sh`、`check-requires.sh`、`detect-clis.sh`、`list-models.sh`、`model-config.sh`、`model-tags.sh`。 - `python3 -m json.tool` 檢查三份 manifest 全數為有效 JSON:`plugin.json`、`.claude-plugin/plugin.json`、`.codex-plugin/plugin.json`,三份的版本一致為 0.2.5,且都含 `jsc-ask` 相依。 - `tools/config-spec.tsv` 欄位盤點:61 列資料每列皆為 8 欄,16 列為註解或空行;新增的 `JSC_WIKI_REPO_TOOLING` 列確認為 8 欄。 - 結束碼實測,`model-tags.sh`:子命令打錯回 2、`gate` 缺參數回 2、`gate plan {表上沒有的模型}` 印 `UNKNOWN-MODEL` 回 2、`gate {不存在的階段} {模型}` 印 `UNKNOWN-STAGE` 回 2。對照修改前的版本,同一個 `gate` 缺參數的呼叫回 1,正是本次修掉的碰撞。 - 結束碼實測,`model-config.sh`:子命令打錯回 2。 - 結束碼實測,`check-requires.sh`:缺參數回 2、CLI 代號不在五個之內回 2、manifest 不存在印 `status=blocked` 回 1;把 `PATH` 換掉模擬沒有 python3 的機器,印出 `status=blocked reason=找不到 python3…` 回 1,不再是未宣告的 127。 - `build-todo.sh` 實跑合併(自製三份輸入檔,未動任何專案檔案):四列 `todo` 依 missing、invalid、unwired、落後排出,`summary` 為 `1 1 1 1`,結束碼 0;只給一份沒有問題的設定輸出時,印出類別為「無」的單列,結束碼 0;不給任何輸入回 2;輸入檔讀不到回 3;`--wiring` 少了 `{cli}=` 前綴回 2。四種錯誤路徑都與檔頭宣告相符。 - 全庫搜尋 `jsc-shared`:零筆命中,確認 `delegate` 引用的不存在 plugin 已完全移除。 - 未執行的項目:`deploy.sh`、`apply-config.sh`、`write-guides.sh`、`wire-cli.sh` 會寫入機器,本次只做唯讀檢查,一律沒有執行。實際部署驗證留給合併後的 `/jsc-cli:doctor` 一次體檢。 ## 前置 Push Request 無
jiantw83 added 4 commits 2026-08-31 03:15:56 +00:00
model-tags.sh 的 gate 原本用同一個結束碼表示兩件事:模型缺能力標籤,
以及這支腳本被叫錯。delegate 讀到用法錯誤時,會當成模型沒通過檢查,
默默把一個能用的模型丟掉。真正的錯在哪,永遠不會浮出來。現在用法錯誤
改走另一個碼,兩種「無法判定」也歸到同一個碼,呼叫端只要認碼就分得出
三種結果。model-config.sh 照同一套規則調整,兩支腳本的契約才一致。

check-requires.sh 在沒有 python3 的機器上,會直接讓 shell 回一個沒宣告過
的碼,呼叫端讀不到原因。現在先確認 python3 在不在,並印出擋下的理由,
manifest 相依檢查才是真的做得到的事。

delegate 的七個步驟原本沒有任何完成條件,引用了不存在的 plugin,也把
CLI 偵測與標籤篩選寫成文字敘述,可是這兩件事早就有腳本負責。挑模型那
一步需要模型 id,全篇卻沒有任何步驟產得出來。現在每一步都寫出完成條件,
資料一律取自腳本,模型夠不夠格由結束碼判定,不讓模型自評標籤。

setup 的環境變數重驗原本去讀目前這個 shell。可是寫進 rc 檔的值,要等新的
shell 起來才存在,所以重驗永遠回報「沒設到」,把修好的項目誤判成失敗。
現在只驗 rc 段落裡確實有那一行,環境層面交給下一次體檢。
「待修項目」表原本由 doctor 與 setup 各寫一次。同一套合併與排序規則寫在
兩個地方,遲早各自漂移:一邊改了排序,另一邊漏掉一整類項目,而且沒有
任何地方看得出來。現在規則只留一份,兩支技能都呼叫它。輸入與輸出都是
TSV,一項都沒有時照樣印一列,呼叫端永遠有東西可以呈現。

doctor 的四項檢查彼此不共用資料,排成一列跑只是把等待時間乘上四倍,
現在同時啟動。doctor 呼叫接線腳本一律帶唯讀旗標,把「打錯一個子命令就
改到或刪掉檔案」的風險移進程式層,不再只靠指令打對。

deploy 的 CLI 偵測、版本結論與 marketplace 清單同樣互不相干,改成併行
取得。版本結論改讀版本守門腳本的單行結論,不再自己從表格推導。setup 把
已經確認過的模式與版本報告直接交給 deploy,操作者不必再答一次同樣的問題。

deploy、doctor、models 都補上結束碼分流:腳本回什麼碼就走哪條路,不再從
輸出內容猜。體檢目錄頁改成先讀回再更新自己那一列,整頁覆蓋會把別台機器
的紀錄一次抹掉。設定規格表補上技能盤點頁要用的環境變數,盤點頁才有地方
可寫。
detect-clis.sh 與 list-models.sh 一律回零:找不到執行檔,或讀不到設定檔,
都只是少掉那一列,不算失敗。這個約定過去只存在讀過腳本的人腦袋裡。
呼叫端很容易拿結束碼去判斷「這台機器有沒有裝 CLI」,然後永遠判斷錯。
現在把它寫在檔頭,兩支腳本的行為都不動。

README 的腳本表與技能說明同步更新,讀 README 的人看到的流程,才跟技能
裡實際寫的一致。
delegate 與 setup 都靠決策樹問使用者,deploy 問部署模式也是。這份相依
過去沒有寫進 manifest,安裝順序沒排對,就會執行到一半才失敗。現在三份
manifest 都補上這一項,更新前的相依檢查才擋得住。同時做一次版本推進,
讓已發佈版本對得上這一輪的內容。
admin merged commit 8d17f231cf into develop 2026-08-31 03:19:16 +00:00
admin deleted branch fix/skill-check-compliance-and-flow 2026-08-31 03:19:16 +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#42