feat(wiki): 體檢目錄頁改走專用存取庫,並補齊設定規格表

What:CHECK_CONTENTS 改由 wiki-repo CONTENTS 解析並透過 wiki-contents.sh upsert
寫入,CHECK_{HASH} 仍走 wiki-repo CHECK。目錄頁新增一欄裸 HASH 當比對鍵。主機名
改由程式取短名,不再交給模型自由填。

Why:比對鍵原本是含網址的儲存格,換主機或換存取庫就比對不到,每跑一次體檢就替同一台
機器多附一列,畫面上還看不出來。主機名短名與 FQDN 不一致時,同一台機器會分裂成兩張頁,
而助理巡檢那邊是用程式取值的,兩邊對不起來。

How:設定規格表同一輪補齊三處既有缺漏——補上漏掉的 JSC_WIKI_REPO_MONITOR,體檢本來
看不到它而孤兒掃描還會誤報;刪掉指向不存在頁面的 MAINTAIN 內容頁字樣;MAINTAIN 那一列
改成不需要使用者處理,免得體檢叫人去設一支管不到任何頁的變數。整列保留,刪掉會讓孤兒
掃描開始誤報那個變數。

Who:jsc-cli
This commit is contained in:
2026-09-02 11:03:07 +08:00
parent 225e33d2c8
commit fb80559159
10 changed files with 123 additions and 47 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "jsc-cli", "name": "jsc-cli",
"version": "0.2.7", "version": "0.2.8",
"description": "CLI 偵測、模型能力標籤、子代理派工與技能庫批次部署", "description": "CLI 偵測、模型能力標籤、子代理派工與技能庫批次部署",
"skills": "./skills", "skills": "./skills",
"author": { "author": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "jsc-cli", "name": "jsc-cli",
"version": "0.2.7", "version": "0.2.8",
"description": "CLI 偵測、模型能力標籤、子代理派工與技能庫批次部署", "description": "CLI 偵測、模型能力標籤、子代理派工與技能庫批次部署",
"skills": "./skills", "skills": "./skills",
"jsc": { "jsc": {
+4 -3
View File
@@ -54,11 +54,11 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安
### `doctor` ### `doctor`
一次體檢執行環境,只讀不改。四項檢查**同時啟動,各一個 sub agent**:技能版本(`jsc-hooks/hooks/version-guard.sh report`)、Hook 接線(`jsc-hooks/tools/wire-cli.sh status`,唯讀子命令)、設定現況(`tools/scan-config.sh scan all` 比對 `tools/config-spec.tsv`,一次掃完全域與專案兩個範圍)、漏登錄變數(`scan-config.sh orphans`)。唯讀契約下放程式層:呼叫 `wire-cli.sh` 一律帶 `JSC_READONLY=1`,打錯子命令也不會改到機器。每項各出一張表,專案那張一定寫出掃的是哪個目錄;待修項目由 `tools/build-todo.sh` 合併三份輸出並排序。整份結果寫進 wiki `CHECK_{HASH}`,`HASH` 取 `{主機名}/{登入帳號}`,只保留最新一次。修復交給 `/jsc-cli:setup`,體檢本身不動任何設定。 一次體檢執行環境,只讀不改。四項檢查**同時啟動,各一個 sub agent**:技能版本(`jsc-hooks/hooks/version-guard.sh report`)、Hook 接線(`jsc-hooks/tools/wire-cli.sh status`,唯讀子命令)、設定現況(`tools/scan-config.sh scan all` 比對 `tools/config-spec.tsv`,一次掃完全域與專案兩個範圍)、漏登錄變數(`scan-config.sh orphans`)。唯讀契約下放程式層:呼叫 `wire-cli.sh` 一律帶 `JSC_READONLY=1`,打錯子命令也不會改到機器。每項各出一張表,專案那張一定寫出掃的是哪個目錄;待修項目由 `tools/build-todo.sh` 合併三份輸出並排序。整份結果寫進 wiki `CHECK_{HASH}`,`HASH` 取 `{短主機名}/{登入帳號}`,兩個值都由程式取,主機名一律切掉網域,只保留最新一次。目錄頁 `CHECK_CONTENTS` 住另一個庫(`JSC_WIKI_REPO_CONTENTS`),改由 `jsc-gitea/tools/wiki-contents.sh upsert CHECK 4` 只寫本機那一列。鍵是第 4 欄的裸 `HASH`,不是第 1 欄的連結:網址會隨站台、存取庫與頁名編碼改變,拿網址當鍵就比不中,同一台機器每體檢一次就多附一列。第 1 欄的連結給人點,填絕對網址。修復交給 `/jsc-cli:setup`,體檢本身不動任何設定。
### `setup` ### `setup`
修復 `/jsc-cli:doctor` 找出的問題,一次一項,逐項確認才動手。待修清單優先讀 wiki `CHECK_{HASH}`,沒有頁面就當場重掃:**三支檢查腳本併行跑**,再用 `tools/build-todo.sh` 合併成同一張表。依修法分流:`auto` 用 `tools/apply-config.sh` 直接寫、`ask` 先用決策樹問到值再寫、`manual` 印出步驟交給操作者。複合修復交回原主:版本落後找 `/jsc-cli:deploy`(連同已確認的模式與版本報告一起傳過去,不讓它重問重查)、hook 未接線找 `/jsc-hooks:hooks-install`、缺 `model-tags.tsv` 找 `/jsc-cli:models`。逐項確認維持循序,**寫完的重驗併行**;環境變數類只驗「rc 段落裡確實有那一行」,環境層面交給下一次 `/jsc-cli:doctor`。最後覆寫 CHECK 頁。 修復 `/jsc-cli:doctor` 找出的問題,一次一項,逐項確認才動手。待修清單優先讀 wiki `CHECK_{HASH}`,沒有頁面就當場重掃:**三支檢查腳本併行跑**,再用 `tools/build-todo.sh` 合併成同一張表。依修法分流:`auto` 用 `tools/apply-config.sh` 直接寫、`ask` 先用決策樹問到值再寫、`manual` 印出步驟交給操作者。複合修復交回原主:版本落後找 `/jsc-cli:deploy`(連同已確認的模式與版本報告一起傳過去,不讓它重問重查)、hook 未接線找 `/jsc-hooks:hooks-install`、缺 `model-tags.tsv` 找 `/jsc-cli:models`。逐項確認維持循序,**寫完的重驗併行**;環境變數類只驗「rc 段落裡確實有那一行」,環境層面交給下一次 `/jsc-cli:doctor`。最後覆寫體檢頁 `CHECK_{HASH}`,並用 `jsc-gitea/tools/wiki-contents.sh upsert CHECK 4` 以裸 `HASH` 當鍵更新目錄頁 `CHECK_CONTENTS` 的本機那一列,兩頁分屬不同存取庫。
<!-- JSC-SKILLS:END --> <!-- JSC-SKILLS:END -->
@@ -71,7 +71,8 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安
| `JSC_LOCAL_PLUGINS` | antigravity 與 kiro 退路用的本地 clone 目錄 | 用 `$JSC_HOME/plugins`(即 `~/.jsc/plugins`) | | `JSC_LOCAL_PLUGINS` | antigravity 與 kiro 退路用的本地 clone 目錄 | 用 `$JSC_HOME/plugins`(即 `~/.jsc/plugins`) |
| `JSC_KIRO_SKILLS` | kiro 退路複製 skills 的目標目錄 | 用 `~/.kiro/skills` | | `JSC_KIRO_SKILLS` | kiro 退路複製 skills 的目標目錄 | 用 `~/.kiro/skills` |
| `JSC_DEPLOY_DRYRUN` | 設為 `1` 等同 `deploy.sh -n`,只印指令不執行 | 照常執行 | | `JSC_DEPLOY_DRYRUN` | 設為 `1` 等同 `deploy.sh -n`,只印指令不執行 | 照常執行 |
| `JSC_WIKI_REPO_CHECK` | 體檢頁 `CHECK_CONTENTS`、`CHECK_{HASH}` 所在的 `{owner}/{repo}` | 退回 `JSC_WIKI_REPO`;兩個都沒有就略過寫入,並把這一項列進待修 | | `JSC_WIKI_REPO_CHECK` | 體檢內容頁 `CHECK_{HASH}` 所在的 `{owner}/{repo}`;只管內容頁,管不到目錄頁 | 退回 `JSC_WIKI_REPO`;兩個都沒有就略過寫入,並把這一項列進待修 |
| `JSC_WIKI_REPO_CONTENTS` | 目錄頁 `CHECK_CONTENTS` 所在的 `{owner}/{repo}`。目錄頁與內容頁分屬不同存取庫:所有 `{TYPE}_CONTENTS` 一律住這一個庫,內容頁才看各自的型別變數 | 退回 `JSC_WIKI_REPO`;兩個都沒有就略過目錄頁寫入,並把這一項列進待修。不退回 `JSC_WIKI_REPO_CHECK` |
| `JSC_CONFIG_SPEC` | 改讀別份設定規格表(測試 `scan-config.sh` 時用) | 用 `tools/config-spec.tsv` | | `JSC_CONFIG_SPEC` | 改讀別份設定規格表(測試 `scan-config.sh` 時用) | 用 `tools/config-spec.tsv` |
| `JSC_HOME` | hook 資料目錄,兩份指引與重啟狀態檔都寫在這裡 | 用 `~/.jsc` | | `JSC_HOME` | hook 資料目錄,兩份指引與重啟狀態檔都寫在這裡 | 用 `~/.jsc` |
| `JSC_RESTART_GATE` | 設成 `off` 可略過部署後的重啟提示閘門(判讀在 `jsc-hooks`,`jsc-cli` 只負責寫狀態檔) | 照常提示重啟 | | `JSC_RESTART_GATE` | 設成 `off` 可略過部署後的重啟提示閘門(判讀在 `jsc-hooks`,`jsc-cli` 只負責寫狀態檔) | 照常提示重啟 |
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "jsc-cli", "name": "jsc-cli",
"version": "0.2.7", "version": "0.2.8",
"description": "CLI 偵測、模型能力標籤、子代理派工與技能庫批次部署", "description": "CLI 偵測、模型能力標籤、子代理派工與技能庫批次部署",
"skills": "./skills/", "skills": "./skills/",
"jsc": { "jsc": {
+8 -8
View File
@@ -27,10 +27,10 @@
| 項目 | 內容 | | 項目 | 內容 |
| --- | --- | | --- | --- |
| 觸發時機 | 裝完或更新完技能組、技能因設定或接線問題失敗、機器要交接前用。要動手修不用這支,那是 jsc-cli:setup | | 觸發時機 | 裝完或更新完技能組、技能因設定或接線問題失敗、機器要交接前用。要動手修不用這支,那是 jsc-cli:setup |
| 關鍵步驟 | 同時開四個 sub agent 收版本、hook 接線、設定與未登錄變數,每個 sub agent 回傳原始輸出行、把四份輸出各存成檔、依 templates/check-page.md 印出五個區塊並寫明掃描的專案目錄、用 tools/build-todo.sh 把三份輸出合成待修項目表、透過 jsc-gitea:wiki 整頁覆寫 CHECK_{HASH} 並把本機那一列 upsert 進 CHECK_CONTENTS、報出四項計數並視情況建議 /jsc-cli:setup | | 關鍵步驟 | 同時開四個 sub agent 收版本、hook 接線、設定與未登錄變數,每個 sub agent 回傳原始輸出行、把四份輸出各存成檔、依 templates/check-page.md 印出五個區塊並寫明掃描的專案目錄、用 tools/build-todo.sh 把三份輸出合成待修項目表、用程式取短主機名與登入帳號(主機名切掉第一個點之後的網域)交給 hash-id 算出 HASH、用 wiki-repo CHECK 解出的存取庫透過 jsc-gitea:wiki 整頁覆寫 CHECK_{HASH}、寫完再用 wiki-url 取該頁絕對網址填進第 1 欄的連結、用 wiki-contents.sh upsert CHECK 4 以第 4 欄的裸 HASH 當鍵把本機那一列寫進 CONTENTS 存取庫的 CHECK_CONTENTS、報出四項計數並視情況建議 /jsc-cli:setup |
| 外部呼叫 | jsc-hooks/hooks/version-guard.sh report、jsc-cli/tools/detect-clis.sh、jsc-hooks/tools/wire-cli.sh status(一律帶 JSC_READONLY=1)、jsc-cli/tools/scan-config.sh 的 scan all 與 orphans、jsc-cli/tools/build-todo.sh、jsc-gitea/tools/gitea.sh 的 wiki-repo 與 hash-id、jsc-gitea:wiki | | 外部呼叫 | jsc-hooks/hooks/version-guard.sh report、jsc-cli/tools/detect-clis.sh、jsc-hooks/tools/wire-cli.sh status(一律帶 JSC_READONLY=1)、jsc-cli/tools/scan-config.sh 的 scan all 與 orphans、jsc-cli/tools/build-todo.sh、jsc-gitea/tools/gitea.sh 的 wiki-repo、hash-id 與 wiki-url、jsc-gitea/tools/wiki-contents.sh upsert、jsc-gitea:wiki |
| 完成條件 | 四項檢查各有結論,或明寫無法驗證與原因;五個區塊與待修項目表都在畫面上;wiki 頁寫成功,或寫入略過連同結束碼一起回報;必要項缺漏、設定錯誤、CLI 未接線、domain 落後四項計數都講出來 | | 完成條件 | 四項檢查各有結論,或明寫無法驗證與原因;五個區塊與待修項目表都在畫面上;兩頁各自寫成功,或寫入略過連同結束碼一起回報,wiki-contents.sh 宣告的 0、1、2、3、4、7、8 每一碼都有分流,建不建新頁的判斷留在腳本裡,技能不自己建;必要項缺漏、設定錯誤、CLI 未接線、domain 落後四項計數都講出來 |
| 可驗證跡象 | wiki 的 CHECK_{HASH} 頁(雜湊來源是 {主機名}/{登入帳號})被整頁覆寫成這次的結果,CHECK_CONTENTS 多出本機那一列,或該列的缺漏數與最後體檢時間被更新。機器本身的設定、接線與版本都不動:這支技能不寫任何設定 | | 可驗證跡象 | wiki 的 CHECK_{HASH} 頁(雜湊來源是 {短主機名}/{登入帳號})被整頁覆寫成這次的結果;另一個存取庫的 CHECK_CONTENTS 多出本機那一列,或該列的缺漏數與最後體檢時間被更新;第 1 欄是連到體檢頁的絕對網址,第 4 欄是裸 HASH,也就是比對用的鍵,同一台機器重跑幾次都只有這一列,別台機器的列一個位元組都沒變。機器本身的設定、接線與版本都不動:這支技能不寫任何設定 |
## models ## models
@@ -47,7 +47,7 @@
| 項目 | 內容 | | 項目 | 內容 |
| --- | --- | | --- | --- |
| 觸發時機 | doctor 報出待修項目、要實際動手修這台機器時用。只想做唯讀體檢不用這支,那是 jsc-cli:doctor | | 觸發時機 | doctor 報出待修項目、要實際動手修這台機器時用。只想做唯讀體檢不用這支,那是 jsc-cli:doctor |
| 關鍵步驟 | 從 wiki CHECK_{HASH} 讀待修項目表,讀不到就以 sub agent 同時重跑設定、接線、版本三個檢查器再用 build-todo.sh 合併、依 jsc-ask 決策樹逐項循序確認、依 fix 欄分流(auto 與 ask 走 apply-config.sh 的 set 或 mkdir、manual 印出步驟交給操作者、domain 落後轉呼叫 jsc-cli:deploy 並附上手上的版本報告、hook 未接線轉呼叫 jsc-hooks:hooks-install、缺 model-tags.tsv 轉呼叫 jsc-cli:models)、同時重驗每個已套用項目、重寫 CHECK_{HASH} 並 upsert CHECK_CONTENTS、報出已修、略過、轉呼叫、未修好四項計數 | | 關鍵步驟 | 用程式取短主機名與登入帳號算出 HASH,從 wiki-repo CHECK 解出的存取庫讀 CHECK_{HASH} 的待修項目表,讀不到就以 sub agent 同時重跑設定、接線、版本三個檢查器再用 build-todo.sh 合併、依 jsc-ask 決策樹逐項循序確認、依 fix 欄分流(auto 與 ask 走 apply-config.sh 的 set 或 mkdir、manual 印出步驟交給操作者、domain 落後轉呼叫 jsc-cli:deploy 並附上手上的版本報告、hook 未接線轉呼叫 jsc-hooks:hooks-install、缺 model-tags.tsv 轉呼叫 jsc-cli:models)、同時重驗每個已套用項目、重寫 CHECK_{HASH}、再用 wiki-url 取它的絕對網址填進第 1 欄的連結並以 wiki-contents.sh upsert CHECK 4 用第 4 欄的裸 HASH 當鍵更新 CONTENTS 存取庫的 CHECK_CONTENTS、報出已修、略過、轉呼叫、未修好四項計數 |
| 外部呼叫 | jsc-cli/tools/scan-config.sh、jsc-cli/tools/detect-clis.sh、jsc-hooks/tools/wire-cli.sh status(一律帶 JSC_READONLY=1)、jsc-hooks/hooks/version-guard.sh report、jsc-cli/tools/build-todo.sh、jsc-cli/tools/apply-config.sh 的 set、mkdir 與 show、jsc-gitea/tools/gitea.sh 的 wiki-repo 與 hash-id、jsc-ask:ask、jsc-gitea:wiki、jsc-cli:deploy、jsc-hooks:hooks-install、jsc-cli:models | | 外部呼叫 | jsc-cli/tools/scan-config.sh、jsc-cli/tools/detect-clis.sh、jsc-hooks/tools/wire-cli.sh status(一律帶 JSC_READONLY=1)、jsc-hooks/hooks/version-guard.sh report、jsc-cli/tools/build-todo.sh、jsc-cli/tools/apply-config.sh 的 set、mkdir 與 show、jsc-gitea/tools/gitea.sh 的 wiki-repo、hash-id 與 wiki-url、jsc-gitea/tools/wiki-contents.sh upsert、jsc-ask:ask、jsc-gitea:wiki、jsc-cli:deploy、jsc-hooks:hooks-install、jsc-cli:models |
| 完成條件 | 每一項都有已修、略過、轉呼叫或未修好的結果;每個已套用項目都由自己那一列指定的檢查器重驗過;每個寫進去的環境變數都附上 export 那一行;頁面寫好或略過都有回報;四項計數都講出來 | | 完成條件 | 每一項都有已修、略過、轉呼叫或未修好的結果;每個已套用項目都由自己那一列指定的檢查器重驗過;每個寫進去的環境變數都附上 export 那一行;兩頁各自寫好或略過都有回報,wiki-contents.sh 宣告的 0、1、2、3、4、7、8 每一碼都有分流,建不建新頁的判斷留在腳本裡,技能不自己建;四項計數都講出來 |
| 可驗證跡象 | 各 shell rc 檔的 `# jsc-config` 區塊被改寫,改寫前的備份落在 $JSC_HOME/backup/config/{時間戳}/;auto 路線建立的目錄實際出現在磁碟上;wiki CHECK_{HASH} 被改寫成修完後的狀態,CHECK_CONTENTS 的本機列跟著更新;轉呼叫出去的項目留下各自技能的跡象,也就是 deploy 的重啟狀態檔、hooks-install 改寫的接線設定、models 產生的 model-tags.tsv | | 可驗證跡象 | 各 shell rc 檔的 `# jsc-config` 區塊被改寫,改寫前的備份落在 $JSC_HOME/backup/config/{時間戳}/;auto 路線建立的目錄實際出現在磁碟上;wiki CHECK_{HASH} 被改寫成修完後的狀態,另一個存取庫的 CHECK_CONTENTS 只有本機那一列跟著更新,第 1 欄是絕對網址,第 4 欄是當鍵用的裸 HASH;轉呼叫出去的項目留下各自技能的跡象,也就是 deploy 的重啟狀態檔、hooks-install 改寫的接線設定、models 產生的 model-tags.tsv |
+38 -9
View File
@@ -1,6 +1,6 @@
--- ---
name: doctor name: doctor
description: Health-check the execution environment in one pass and record the result, changing nothing. Four checks - plugin versions from jsc-hooks/hooks/version-guard.sh report, hook wiring from jsc-hooks/tools/wire-cli.sh status, settings from tools/scan-config.sh against tools/config-spec.tsv, and orphan variables. Report one findings table per check, build the 待修項目 table with tools/build-todo.sh, then write the whole run to wiki CHECK_{HASH} where HASH comes from {hostname}/{user}; the page keeps only the latest run. Use after installing or updating the skill set, when a skill fails on a settings or wiring problem, or before handing a machine over; not for applying fixes, which is jsc-cli:setup. description: Health-check the execution environment in one pass and record the result, changing nothing. Four checks - plugin versions from jsc-hooks/hooks/version-guard.sh report, hook wiring from jsc-hooks/tools/wire-cli.sh status, settings from tools/scan-config.sh against tools/config-spec.tsv, and orphan variables. Report one findings table per check, build the 待修項目 table with tools/build-todo.sh, then write the whole run to wiki CHECK_{HASH} where HASH comes from {short hostname}/{user}; the page keeps only the latest run, while its CHECK_CONTENTS row is upserted through wiki-contents.sh into the contents repo. Use after installing or updating the skill set, when a skill fails on a settings or wiring problem, or before handing a machine over; not for applying fixes, which is jsc-cli:setup.
--- ---
# doctor — execution environment health check # doctor — execution environment health check
@@ -102,18 +102,47 @@ Done when all five blocks of 2.1 are on screen with the scanned directory stated
### 3.1 Record ### 3.1 Record
Write the page through `jsc-gitea:wiki`: This run writes two pages, and they live in **two different wiki repos**. Resolve each repo on its own and never reuse one for the other.
- Wiki repo: `jsc-gitea/tools/gitea.sh wiki-repo CHECK`. **The HASH — take it from the machine, do not compose it by hand.** `jsc-assist`'s `MONITOR_{HASH}` claims the same hash source and takes it in code, so the two pages only ever line up when this skill takes it the same way:
- Page name: `CHECK_` plus `gitea.sh hash-id "{hostname}/{user}"` — the host and the login account, not `{owner}/{repo}`. Doctor checks a machine, and it has to work in directories that are not repositories at all.
- `CHECK_{HASH}` is a **content page**: overwrite the whole page, because this page type keeps only the latest run of this one machine.
- `CHECK_CONTENTS` is a **contents page** and follows the opposite rule: read it back first, then upsert this machine's row from `templates/check-contents.md` in the same pass — add the row if missing, otherwise refresh its 必要項缺漏、設定錯誤、最後體檢 columns. Never overwrite the whole page, and never touch a row belonging to another machine: those rows are other people's records, and this run never read them from anywhere else.
- The `CHECK_CONTENTS` read branches by exit code, and only exit 4 opens the create path. Exit 0 means the page is there, so upsert into what came back. Exit 4 means the page really does not exist yet, so build it from the template. Exit 7 (key invalid or no permission) and exit 8 (any other API failure) both mean the old rows are unknown, never that the page is missing: skip the `CHECK_CONTENTS` write, name the exit code in the report, and create nothing. Writing a fresh template over a directory whose rows were never read wipes every other machine's row, and the write carries no merge and no backup.
`wiki-repo` exiting 3 means no wiki repo is configured for CHECK. Print the tables, skip the wiki write, and put `JSC_WIKI_REPO_CHECK` at the top of 待修項目 — that unset variable is itself a finding, so a failed write never fails the health check. Any other non-zero exit from `wiki-repo`, `hash-id` or the wiki write is reported the same way: tables on screen, write skipped, exit code named. ```sh
host=$(hostname 2>/dev/null || uname -n 2>/dev/null || printf 'unknown'); host=${host%%.*}
user=${USER:-$(id -un 2>/dev/null || printf 'unknown')}
```
`${host%%.*}` is the point of the snippet: `hostname` prints the FQDN on some machines and the short name on others, so a hand-written value gives one machine two pages that never merge again. Pass `"{host}/{user}"` to `gitea.sh hash-id` and use exactly what it prints. It is the host and the login account, not `{owner}/{repo}` — doctor checks a machine, and it has to work in directories that are not repositories at all.
**`CHECK_{HASH}` — content page.** Repo: `jsc-gitea/tools/gitea.sh wiki-repo CHECK`. Write it through `jsc-gitea:wiki` and overwrite the whole page, because this page type keeps only the latest run of this one machine. Whole-page overwrite is correct here and forbidden on the page below.
**`CHECK_CONTENTS` — contents page, in the contents repo.** Repo: `gitea.sh wiki-repo CONTENTS`. Every contents page lives there now; it never falls back to `JSC_WIKI_REPO_CHECK`. Do not hand-edit it — write the row with
`jsc-gitea/tools/wiki-contents.sh upsert CHECK 4 "{HASH}" {row file} templates/check-contents.md`
The script reads the page back, replaces this machine's row or appends it, then writes the whole page. That keeps the rule in one place: one row per run, never a whole-page overwrite, never another machine's row — those rows are other people's records, and this run read them from nowhere else.
**The key is column 4, the bare `HASH`.** `4` is the 1-based index of the `HASH` column in `templates/check-contents.md`, and the key is the exact string `hash-id` printed — 40 uppercase hex characters, not shortened, not prefixed, not wrapped in a link. The script compares the whole cell, so the key and that cell must match character for character.
The key is the bare hash and not the link cell for a reason: a cell holding a URL changes whenever `GITEA_HOST` changes, whenever `JSC_WIKI_REPO_CHECK` moves to another repo, or whenever Gitea encodes the page name differently. The comparison then never matches, and every run appends another row for the same machine — silently, because the page still looks right.
Column 1 stays the human-facing link and is never the key. Build it as an **absolute URL** from `gitea.sh wiki-url {CHECK repo} CHECK_{HASH}`. `[[CHECK_{HASH}]]` resolves only inside its own wiki, and the two pages are no longer in the same one. Fetch the URL after `CHECK_{HASH}` is written: `wiki-url` exits 4 on a page that does not exist yet.
| Exit | Meaning | Action |
| --- | --- | --- |
| 0 | `updated` or `added` | Report which one it printed, with the repo and page it named |
| 1 | Write failed | Nothing landed. Report it with the stderr, and keep 2.1's tables on screen |
| 2 | Usage error | Report it as a defect in this skill. Do not retry with guessed arguments. A `templates/check-contents.md` that is not on disk also lands here — then name the path the script looked for, confirm the plugin install is complete, and rerun |
| 3 | No contents repo configured | Skip this write and put `JSC_WIKI_REPO_CONTENTS` at the top of 待修項目 |
| 4 | Page absent and no template given | Unreachable the way this skill calls the script — the command above always passes `templates/check-contents.md`. A template that is not on disk comes back as exit 2, not 4. So treat a 4 as a malformed call: report it as a defect in this skill, name the command that produced it, and do not retry with guessed arguments |
| 7 | Key invalid or no permission | Nothing was read and nothing written. Name the exit code and create nothing |
| 8 | Any other API failure | Same as 7: the old rows are unknown, so name the exit code and create nothing |
Exits 7 and 8 never mean the page is missing. Writing a fresh template over a directory whose rows were never read wipes every other machine's row, with no merge and no backup behind it — which is exactly why the script creates a page only when its own read reported that page absent, and why it owns that branch instead of this prose.
`wiki-repo` exiting 3 means that page type has no wiki repo configured: `JSC_WIKI_REPO_CHECK` for the content page, `JSC_WIKI_REPO_CONTENTS` for the contents page. Print the tables, skip that one write, and put the unset variable at the top of 待修項目 — it is itself a finding, so a failed write never fails the health check. Any other non-zero exit from `wiki-repo`, `wiki-url`, `hash-id` or the wiki write is reported the same way: tables on screen, write skipped, exit code named.
### 3.2 Hand off ### 3.2 Hand off
State the four counts from 2.2's `summary` line: required items missing, settings invalid, CLIs unwired, domains behind. Recommend `/jsc-cli:setup` when any of those is above zero. Never fix anything here. State the four counts from 2.2's `summary` line: required items missing, settings invalid, CLIs unwired, domains behind. Recommend `/jsc-cli:setup` when any of those is above zero. Never fix anything here.
Done when either the wiki page URL is reported or the skipped write is reported together with its reason, **and** the four counts are stated with the recommendation given or explicitly withheld. Done when each of the two pages is reported with its URL, or its skipped write is reported together with its reason, **and** the four counts are stated with the recommendation given or explicitly withheld.
+37 -6
View File
@@ -9,7 +9,14 @@ This skill writes. Every write is confirmed first, backed up, and verified after
## 1. Get the work list ## 1. Get the work list
Read the 待修項目 table from wiki `CHECK_{HASH}` — repo from `jsc-gitea/tools/gitea.sh wiki-repo CHECK`, page name from `gitea.sh hash-id "{hostname}/{user}"`. Read the 待修項目 table from wiki `CHECK_{HASH}` — repo from `jsc-gitea/tools/gitea.sh wiki-repo CHECK`, page name from `gitea.sh hash-id "{host}/{user}"`, where `host` is the **short hostname** and `user` the login account, both taken from the machine:
```sh
host=$(hostname 2>/dev/null || uname -n 2>/dev/null || printf 'unknown'); host=${host%%.*}
user=${USER:-$(id -un 2>/dev/null || printf 'unknown')}
```
`${host%%.*}` matters: `hostname` prints the FQDN on some machines, and a hash built on the long name reads a page doctor never wrote. This is the same value doctor hashes, so it must be taken the same way.
No page, or `wiki-repo` exits 3, or any other non-zero exit from `wiki-repo`, `hash-id` or the wiki read → rebuild the list here. Rebuilding **MUST run as a sub agent**, and its three checkers **start together**: they read different files and share no state, so serialising them only triples the wait. No page, or `wiki-repo` exits 3, or any other non-zero exit from `wiki-repo`, `hash-id` or the wiki read → rebuild the list here. Rebuilding **MUST run as a sub agent**, and its three checkers **start together**: they read different files and share no state, so serialising them only triples the wait.
@@ -88,14 +95,38 @@ Done when every applied item has a fresh verdict from the checker its own row na
## 5. Record ## 5. Record
Rewrite `CHECK_{HASH}` through `jsc-gitea:wiki` with the post-fix state, per `templates/check-page.md`. That page is a **content page** and keeps only the latest run, so this overwrites the pre-fix picture on purpose. The two pages live in **two different wiki repos**. Resolve each one on its own.
`CHECK_CONTENTS` is a **contents page** and gets the opposite treatment: read it back first, then upsert this machine's row per `templates/check-contents.md` — add the row if missing, otherwise refresh its counts and 最後體檢. Never overwrite the whole page, and never touch another machine's row. Rewrite `CHECK_{HASH}` through `jsc-gitea:wiki` with the post-fix state, per `templates/check-page.md` — repo from `gitea.sh wiki-repo CHECK`. That page is a **content page** and keeps only the latest run, so this overwrites the pre-fix picture on purpose.
The `CHECK_CONTENTS` read branches by exit code, and only exit 4 opens the create path. Exit 0 means upsert into the content that came back. Exit 4 means the page really is not there yet, so build it from the template. Exit 7 (key invalid or no permission) and exit 8 (any other API failure) mean the old rows are unknown, not that the page is missing: skip the `CHECK_CONTENTS` write, name the exit code, and create nothing — the overwrite that is correct for `CHECK_{HASH}` would here destroy every other machine's row, unread and unrecoverable. `CHECK_CONTENTS` is a **contents page**, it lives in the contents repo (`gitea.sh wiki-repo CONTENTS`, never a fallback to `JSC_WIKI_REPO_CHECK`), and it gets the opposite treatment. Write the row with
No wiki repo configured, or any non-zero exit from the wiki write → report the tables on screen, say the record was skipped, and name the exit code. `jsc-gitea/tools/wiki-contents.sh upsert CHECK 4 "{HASH}" {row file} templates/check-contents.md`
which reads the page back and refreshes this machine's row, or appends it when missing. Never overwrite the whole page, and never touch another machine's row.
**The key is column 4, the bare `HASH`.** `4` is the 1-based index of the `HASH` column in `templates/check-contents.md`, and the key is exactly what `hash-id` printed for `{host}/{user}` in step 1 — 40 uppercase hex characters, not shortened, not prefixed, not wrapped in a link. The script compares the whole cell, so the key and that cell must match character for character.
A cell holding a URL would make a moving key: it changes with `GITEA_HOST`, with a move of `JSC_WIKI_REPO_CHECK` to another repo, and with Gitea's encoding of the page name. The comparison then never matches, and every run appends a second row for the same machine instead of updating it.
Column 1 stays the human-facing link and is never the key. Build it as an **absolute URL** from `gitea.sh wiki-url {CHECK repo} CHECK_{HASH}`, fetched after `CHECK_{HASH}` is rewritten. `[[CHECK_{HASH}]]` resolves only inside its own wiki, and the two pages are no longer in the same one.
| Exit | Action |
| --- | --- |
| 0 | Report the `updated` or `added` result with the repo and page it named |
| 1 | Write failed and nothing landed. Report it with the stderr |
| 2 | Usage error. Report it as a defect in this skill; do not retry with guessed arguments. A `templates/check-contents.md` that is not on disk also lands here — then name the path the script looked for, confirm the plugin install is complete, and rerun |
| 3 | No contents repo configured. Skip this write and report `JSC_WIKI_REPO_CONTENTS` as still unfixed |
| 4 | Unreachable the way this skill calls the script — the command above always passes `templates/check-contents.md`, and a template that is not on disk comes back as exit 2. So treat a 4 as a malformed call: report it as a defect in this skill, name the command that produced it, and do not retry with guessed arguments |
| 7 | Key invalid or no permission. Nothing was read or written; name the exit code and create nothing |
| 8 | Any other API failure. Same as 7 |
Exits 7 and 8 never mean the page is missing: the whole-page overwrite that is correct for `CHECK_{HASH}` would here destroy every other machine's row, unread and unrecoverable. The script creates a page only when its own read reported that page absent, and it owns that branch.
`gitea.sh wiki-url` has its own exits, and they are read before the upsert runs. Exit 4 means `CHECK_{HASH}` is not on the wiki yet, so rewrite that page first and fetch the URL again. Any other non-zero exit: name the exit code and stop — never hand-build the URL, because a guessed link goes into the row and points nowhere.
No wiki repo configured, or any non-zero exit from `wiki-repo`, `hash-id`, `wiki-url` or the wiki write → report the tables on screen, say the record was skipped, and name the exit code.
Then state the counts: fixed, skipped, delegated, and 未修好. Recommend `/jsc-cli:doctor` for a clean re-check when anything was delegated. Then state the counts: fixed, skipped, delegated, and 未修好. Recommend `/jsc-cli:doctor` for a clean re-check when anything was delegated.
Done when the page is written or the skip is reported, and the four counts are stated. Done when each of the two pages is written or its skip is reported, and the four counts are stated.
+13 -5
View File
@@ -1,9 +1,17 @@
# 體檢目錄 # 體檢目錄
> 由 `jsc-cli:doctor` 維護。每台執行環境一列;`HASH` 取 `{主機名}/{登入帳號}`,算法與其他頁面共用。 > 由 `jsc-cli:doctor` 維護。每台執行環境一列;`HASH` 取 `{短主機名}/{登入帳號}`,算法與其他頁面共用。主機名取不含網域的短名,FQDN 要先切掉第一個點之後的部分,否則同一台機器會多出第二頁。
> >
> 寫入語意:一列代表一台執行環境,也就是一組主機加帳號。寫入前先讀回整頁,該執行環境已經有列就更新那一列,沒有才在文末附加一列,最後整頁寫回。禁止整頁覆蓋,也不得改動別人的列。體檢頁 `CHECK_{HASH}` 只留最新一次結果、可以整頁改寫,這份目錄頁不行。 > 本頁落在 `JSC_WIKI_REPO_CONTENTS` 解出的專用存取庫,與體檢頁 `CHECK_{HASH}` 不同庫。目錄頁全部住這裡,不退回 `JSC_WIKI_REPO_CHECK`。
>
> 寫入語意:一列代表一台執行環境,也就是一組主機加帳號。一律用 `jsc-gitea/tools/wiki-contents.sh upsert CHECK 4 {HASH} {列檔} {本範本}` 寫,它先讀回整頁,該執行環境已經有列就更新那一列,沒有才在表尾附加一列。禁止整頁覆蓋,也不得改動別人的列。體檢頁 `CHECK_{HASH}` 只留最新一次結果、可以整頁改寫,這份目錄頁不行。
>
> 鍵是第 4 欄的 `HASH`:`jsc-gitea/tools/hash-id` 印出什麼就填什麼,完整 40 碼大寫十六進位,不截短、不加前綴、不包成連結。腳本比對的是整格文字,鍵一定要跟這一格一字不差。
>
> 鍵用裸 `HASH` 才穩。`GITEA_HOST` 換掉、`JSC_WIKI_REPO_CHECK` 換過存取庫、Gitea 對頁名的網址編碼有差,網址就跟著變;拿含網址的儲存格當鍵,比對就永遠比不中,同一台機器每體檢一次就多附一列,畫面上還看不出來。
>
> 第 1 欄的連結只給人點,不當鍵用。連結一律填 `jsc-gitea/tools/gitea.sh wiki-url` 印出的絕對網址。`[[CHECK_{HASH}]]` 只在同一個 wiki 內解析,兩頁已經不同庫,寫成雙括號會連不到。
| 體檢頁 | 主機 | 帳號 | 必要項缺漏 | 設定錯誤 | 最後體檢 | | 體檢頁 | 主機 | 帳號 | HASH | 必要項缺漏 | 設定錯誤 | 最後體檢 |
| --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- | --- |
| [[CHECK_{HASH}]] | {hostname} | {使用者帳號} | {n} | {n} | {yyyy-MM-dd HH:mm} | | [CHECK_{HASH}]({體檢頁絕對網址}) | {短主機名} | {使用者帳號} | {HASH} | {n} | {n} | {yyyy-MM-dd HH:mm} |
+18 -13
View File
@@ -14,26 +14,31 @@
# fix auto=工具算得出,可直接寫入 ask=值要人給,問完才寫 manual=只能人手動處理 -=不需修 # fix auto=工具算得出,可直接寫入 ask=值要人給,問完才寫 manual=只能人手動處理 -=不需修
# desc 一句繁中說明,直接印給使用者看 # desc 一句繁中說明,直接印給使用者看
# #
# wiki 存取庫分兩路:目錄頁({TYPE}_CONTENTS)全部住 JSC_WIKI_REPO_CONTENTS 解出的專用存取庫,
# 內容頁({TYPE}_{HASH})才看自己的型別變數。目錄頁不退回型別變數,型別變數也管不到目錄頁。
#
GITEA_HOST env global yes - gitea-api ask Gitea 站台位址,所有 wiki 與 PR 操作的去處 GITEA_HOST env global yes - gitea-api ask Gitea 站台位址,所有 wiki 與 PR 操作的去處
GITEA_TOKEN env global yes - gitea-auth ask Gitea API token;未設定時退回 tea CLI 的登入金鑰 GITEA_TOKEN env global yes - gitea-auth ask Gitea API token;未設定時退回 tea CLI 的登入金鑰
JSC_HOME env global no ~/.jsc dir auto hook 資料目錄,放工作階段計時、用量統計、版本快取 JSC_HOME env global no ~/.jsc dir auto hook 資料目錄,放工作階段計時、用量統計、版本快取
JSC_WIKI_REPO env global no - wiki-repo ask 未逐類設定時的共用 wiki {owner}/{repo} JSC_WIKI_REPO env global no - wiki-repo ask 未逐類設定時的共用 wiki {owner}/{repo}
JSC_WIKI_REPO_QUESTION env global no JSC_WIKI_REPO wiki-repo ask QUESTION_CONTENTS、QUESTION_{HASH} 所在存取庫 JSC_WIKI_REPO_CONTENTS env global no JSC_WIKI_REPO wiki-repo ask 全部目錄頁({TYPE}_CONTENTS)所在存取庫;沒有型別變數可退,只退 JSC_WIKI_REPO
JSC_WIKI_REPO_PLAN env global no JSC_WIKI_REPO wiki-repo ask PLAN_CONTENTS、PLAN_{HASH} 所在存取庫 JSC_WIKI_REPO_QUESTION env global no JSC_WIKI_REPO wiki-repo ask QUESTION_{HASH} 內容頁所在存取庫
JSC_WIKI_REPO_ANALYZE env global no JSC_WIKI_REPO wiki-repo ask ANALYZE_CONTENTS、ANALYZE_{HASH} 所在存取庫 JSC_WIKI_REPO_PLAN env global no JSC_WIKI_REPO wiki-repo ask PLAN_{HASH} 內容頁所在存取庫
JSC_WIKI_REPO_DELIVER env global no JSC_WIKI_REPO wiki-repo ask DELIVER_CONTENTS、DELIVER_{HASH} 所在存取庫 JSC_WIKI_REPO_ANALYZE env global no JSC_WIKI_REPO wiki-repo ask ANALYZE_{HASH} 內容頁所在存取庫
JSC_WIKI_REPO_MAINTAIN env global no JSC_WIKI_REPO wiki-repo ask MAINTAIN_CONTENTS、MAINTAIN_{HASH} 所在存取庫 JSC_WIKI_REPO_DELIVER env global no JSC_WIKI_REPO wiki-repo ask DELIVER_{HASH} 內容頁所在存取庫
JSC_WIKI_REPO_REPO env global no JSC_WIKI_REPO wiki-repo ask REPO_CONTENTS、REPO_{HASH} 所在存取庫 JSC_WIKI_REPO_MAINTAIN env global no JSC_WIKI_REPO none - 保留待用,不必設定:MAINTAIN 只有目錄頁 MAINTAIN_CONTENTS,沒有內容頁,目錄頁又已改看 JSC_WIKI_REPO_CONTENTS,這一列目前沒有頁面可管;留著這一列是為了讓孤兒掃描認得這個變數
JSC_WIKI_REPO_LOG env global no JSC_WIKI_REPO wiki-repo ask LOG_CONTENTS、LOG_{HASH} 所在存取庫 JSC_WIKI_REPO_REPO env global no JSC_WIKI_REPO wiki-repo ask REPO_{HASH} 內容頁所在存取庫
JSC_WIKI_REPO_LEARN env global no JSC_WIKI_REPO wiki-repo ask LEARN_CONTENTS、LEARN_{HASH} 所在存取庫 JSC_WIKI_REPO_LOG env global no JSC_WIKI_REPO wiki-repo ask LOG_{HASH} 內容頁所在存取庫
JSC_WIKI_REPO_ERROR env global no JSC_WIKI_REPO wiki-repo ask ERROR_CONTENTS、ERROR_{HASH} 所在存取庫 JSC_WIKI_REPO_LEARN env global no JSC_WIKI_REPO wiki-repo ask LEARN_{HASH} 內容頁所在存取庫
JSC_WIKI_REPO_CHECK env global no JSC_WIKI_REPO wiki-repo ask CHECK_CONTENTS、CHECK_{HASH} 所在存取庫,體檢紀錄寫在這裡 JSC_WIKI_REPO_ERROR env global no JSC_WIKI_REPO wiki-repo ask ERROR_{HASH} 內容頁所在存取庫
JSC_WIKI_REPO_REPORT env global no JSC_WIKI_REPO wiki-repo ask REPORT_CONTENTS、REPORT_{HASH} 所在存取庫,年月週日報表寫在這裡 JSC_WIKI_REPO_CHECK env global no JSC_WIKI_REPO wiki-repo ask CHECK_{HASH} 內容頁所在存取庫,體檢紀錄寫在這裡
JSC_WIKI_REPO_REPORT env global no JSC_WIKI_REPO wiki-repo ask REPORT_{HASH} 內容頁所在存取庫,年月週日報表寫在這裡
JSC_VERSION_GUARD env global no on set ask 設成 off 可完全略過版本前置檢查,離線工作時用 JSC_VERSION_GUARD env global no on set ask 設成 off 可完全略過版本前置檢查,離線工作時用
JSC_VERSION_TTL env global no 600 set ask 版本查詢快取秒數 JSC_VERSION_TTL env global no 600 set ask 版本查詢快取秒數
JSC_RESTART_GATE env global no on set ask 設成 off 可略過部署後的重啟提示閘門,判讀在 jsc-hooks JSC_RESTART_GATE env global no on set ask 設成 off 可略過部署後的重啟提示閘門,判讀在 jsc-hooks
JSC_WIKI_REPO_SKILLSET env global no JSC_WIKI_REPO wiki-repo ask SKILLSET_CONTENTS、SKILLSET_{HASH} 所在的 {owner}/{repo},技能組異動報告寫在這裡 JSC_WIKI_REPO_SKILLSET env global no JSC_WIKI_REPO wiki-repo ask SKILLSET_{HASH} 內容頁所在的 {owner}/{repo},技能組異動報告寫在這裡
JSC_WIKI_REPO_TOOLING env global no JSC_WIKI_REPO wiki-repo ask TOOLING_CONTENTS、TOOLING_{HASH} 所在的 {owner}/{repo},技能盤點寫在這裡 JSC_WIKI_REPO_TOOLING env global no JSC_WIKI_REPO wiki-repo ask TOOLING_{HASH} 內容頁所在的 {owner}/{repo},技能盤點寫在這裡
JSC_WIKI_REPO_MONITOR env global no JSC_WIKI_REPO wiki-repo ask MONITOR_{HASH} 內容頁所在存取庫,助理巡檢紀錄寫在這裡
JSC_LANG_GUARD env global no on set ask 設成 off 可關閉繁中編碼與簡體字守門,誤判時用 JSC_LANG_GUARD env global no on set ask 設成 off 可關閉繁中編碼與簡體字守門,誤判時用
JSC_COMMENT_SCOPE env global no on set ask 設成 off 可關閉註解夾帶文件編號的守門,誤判時用 JSC_COMMENT_SCOPE env global no on set ask 設成 off 可關閉註解夾帶文件編號的守門,誤判時用
JSC_CHANGED_FILE internal runtime no - none - 非 Claude CLI 傳入的變更檔路徑,註解範圍與繁中編碼守門讀它 JSC_CHANGED_FILE internal runtime no - none - 非 Claude CLI 傳入的變更檔路徑,註解範圍與繁中編碼守門讀它
1 # config-spec.tsv — jsc 技能組的設定規格表。體檢(/jsc-cli:doctor)與設定(/jsc-cli:setup)共用這一份。
14 # fix auto=工具算得出,可直接寫入 ask=值要人給,問完才寫 manual=只能人手動處理 -=不需修
15 # desc 一句繁中說明,直接印給使用者看
16 #
17 # wiki 存取庫分兩路:目錄頁({TYPE}_CONTENTS)全部住 JSC_WIKI_REPO_CONTENTS 解出的專用存取庫,
18 # 內容頁({TYPE}_{HASH})才看自己的型別變數。目錄頁不退回型別變數,型別變數也管不到目錄頁。
19 #
20 GITEA_HOST
21 GITEA_TOKEN
22 JSC_HOME
23 JSC_WIKI_REPO
24 JSC_WIKI_REPO_QUESTION JSC_WIKI_REPO_CONTENTS
25 JSC_WIKI_REPO_PLAN JSC_WIKI_REPO_QUESTION
26 JSC_WIKI_REPO_ANALYZE JSC_WIKI_REPO_PLAN
27 JSC_WIKI_REPO_DELIVER JSC_WIKI_REPO_ANALYZE
28 JSC_WIKI_REPO_MAINTAIN JSC_WIKI_REPO_DELIVER
29 JSC_WIKI_REPO_REPO JSC_WIKI_REPO_MAINTAIN
30 JSC_WIKI_REPO_LOG JSC_WIKI_REPO_REPO
31 JSC_WIKI_REPO_LEARN JSC_WIKI_REPO_LOG
32 JSC_WIKI_REPO_ERROR JSC_WIKI_REPO_LEARN
33 JSC_WIKI_REPO_CHECK JSC_WIKI_REPO_ERROR
34 JSC_WIKI_REPO_REPORT JSC_WIKI_REPO_CHECK
35 JSC_WIKI_REPO_REPORT
36 JSC_VERSION_GUARD
37 JSC_VERSION_TTL
38 JSC_RESTART_GATE
39 JSC_WIKI_REPO_SKILLSET
40 JSC_WIKI_REPO_TOOLING
41 JSC_WIKI_REPO_MONITOR
42 JSC_LANG_GUARD
43 JSC_COMMENT_SCOPE
44 JSC_CHANGED_FILE
+2
View File
@@ -97,6 +97,8 @@ if [ "$cmd" = orphans ]; then
# 去掉再比對,否則每次體檢都會多報一個不存在的變數。 # 去掉再比對,否則每次體檢都會多報一個不存在的變數。
name=${name%_} name=${name%_}
printf '%s\n' "$known" | grep -qx "$name" && continue printf '%s\n' "$known" | grep -qx "$name" && continue
# 只排掉樣板佔位字那一個名字,不做前綴比對:CONTENTS、MONITOR 這些是真的頁面類型,
# 排寬了就等於把整族存取庫變數從孤兒掃描裡挖掉,漏登錄再也看不出來。
case "$name" in JSC_WIKI_REPO_TYPE) continue ;; esac case "$name" in JSC_WIKI_REPO_TYPE) continue ;; esac
printf 'orphan\t%s\t%s\n' "$name" "$count" printf 'orphan\t%s\t%s\n' "$name" "$count"
done done