釋出技能委派判定的地基與接線至 master,版本 0.2.8 升到 0.3.3 #70
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "jsc-meta",
|
"name": "jsc-meta",
|
||||||
"version": "0.2.8",
|
"version": "0.2.9",
|
||||||
"description": "技能組自我管理:新建、更新、刪除技能與技能準則",
|
"description": "技能組自我管理:新建、更新、刪除技能與技能準則",
|
||||||
"skills": "./skills",
|
"skills": "./skills",
|
||||||
"author": {
|
"author": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "jsc-meta",
|
"name": "jsc-meta",
|
||||||
"version": "0.2.8",
|
"version": "0.2.9",
|
||||||
"description": "技能組自我管理:新建、更新、刪除技能與技能準則",
|
"description": "技能組自我管理:新建、更新、刪除技能與技能準則",
|
||||||
"skills": "./skills",
|
"skills": "./skills",
|
||||||
"jsc": {
|
"jsc": {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安
|
|||||||
| `references/pr-report.md` | PR 收尾回報格式唯一來源,所有會開 PR 的技能都指向這裡 |
|
| `references/pr-report.md` | PR 收尾回報格式唯一來源,所有會開 PR 的技能都指向這裡 |
|
||||||
| `references/deploy-verify.md` | 四支異動技能共用的部署與驗證流程:判路線、部署或工作樹、**在新的 CLI 行程裡驗證**、失敗分流 |
|
| `references/deploy-verify.md` | 四支異動技能共用的部署與驗證流程:判路線、部署或工作樹、**在新的 CLI 行程裡驗證**、失敗分流 |
|
||||||
| `references/behaviors.md` | 本 domain 的技能行為清單:一支技能一節,五列記下觸發時機、關鍵步驟、外部呼叫、完成條件、可驗證跡象,供稽核與驗證比對。格式合約見 `references/guidelines.md` 的「技能行為清單」 |
|
| `references/behaviors.md` | 本 domain 的技能行為清單:一支技能一節,五列記下觸發時機、關鍵步驟、外部呼叫、完成條件、可驗證跡象,供稽核與驗證比對。格式合約見 `references/guidelines.md` 的「技能行為清單」 |
|
||||||
| `templates/skillset-contents.md` | `SKILLSET_CONTENTS` 目錄頁樣板。一列代表一個 domain 存取庫;本頁落在 `JSC_WIKI_REPO_CONTENTS`,指向內容頁的連結用絕對網址,一律用 `jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}"` 只寫自己那一列 |
|
| `templates/skillset-contents.md` | `SKILLSET_CONTENTS` 目錄頁樣板。一列代表一個 domain 存取庫;本頁落在 `JSC_WIKI_REPO_CONTENTS`,連結一律寫成 `[{文字}]({連結})` 的絕對網址並先過 `link-check.sh` 驗證,寫入一律用 `jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}"` 只寫自己那一列 |
|
||||||
| `templates/skillset-page.md` | `SKILLSET_{HASH}` 內容頁樣板。歷次異動**累積**分節,每節記日期、異動類型、異動需求、動到的技能、改動檔案、PR 網址、部署路線判定與驗證結果;`skill-check` 那一節另含優化建議表,決議與決議日期兩欄供下一輪讀回 |
|
| `templates/skillset-page.md` | `SKILLSET_{HASH}` 內容頁樣板。歷次異動**累積**分節,每節記日期、異動類型、異動需求、動到的技能、改動檔案、PR 網址、部署路線判定與驗證結果;`skill-check` 那一節另含優化建議表,決議與決議日期兩欄供下一輪讀回 |
|
||||||
| `templates/tooling-contents.md` | `TOOLING_CONTENTS` 目錄頁樣板。一列代表一組「機器、CLI、帳號」;只更新自己那一列,別人的列原樣保留,**禁止整頁覆蓋** |
|
| `templates/tooling-contents.md` | `TOOLING_CONTENTS` 目錄頁樣板。一列代表一組「機器、CLI、帳號」;只更新自己那一列,別人的列原樣保留,**禁止整頁覆蓋** |
|
||||||
| `templates/tooling-page.md` | `TOOLING_{HASH}` 內容頁樣板。分節對應 `inventory-tooling.sh` 的輸出;**每次盤點覆寫整頁**,只留現況,不留歷史 |
|
| `templates/tooling-page.md` | `TOOLING_{HASH}` 內容頁樣板。分節對應 `inventory-tooling.sh` 的輸出;**每次盤點覆寫整頁**,只留現況,不留歷史 |
|
||||||
@@ -72,6 +72,7 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安
|
|||||||
| `tools/lint-scripts.sh` | 一個 domain 的腳本檢查三合一:`sh -n` 語法、執行權限、檔頭結束碼宣告;有不合格 exit 1,沒有腳本可掃 exit 3(**不等於通過**) |
|
| `tools/lint-scripts.sh` | 一個 domain 的腳本檢查三合一:`sh -n` 語法、執行權限、檔頭結束碼宣告;有不合格 exit 1,沒有腳本可掃 exit 3(**不等於通過**) |
|
||||||
| `tools/lint-frontmatter.sh` | 一個 domain 每支 `skills/*/SKILL.md` 的 frontmatter 解析檢查:分隔線成對、必要鍵齊全、未加引號的純量不含「冒號加空白」也不以 YAML 特殊字元起頭、引號收得起來。不相依任何 YAML 套件。不合格 exit 1(清單在 stderr),用法錯誤 exit 2,沒有 SKILL.md 可掃 exit 3(**不等於通過**)。frontmatter 壞掉時 Antigravity 會**靜默丟棄整支技能**,沒有任何錯誤訊息 |
|
| `tools/lint-frontmatter.sh` | 一個 domain 每支 `skills/*/SKILL.md` 的 frontmatter 解析檢查:分隔線成對、必要鍵齊全、未加引號的純量不含「冒號加空白」也不以 YAML 特殊字元起頭、引號收得起來。不相依任何 YAML 套件。不合格 exit 1(清單在 stderr),用法錯誤 exit 2,沒有 SKILL.md 可掃 exit 3(**不等於通過**)。frontmatter 壞掉時 Antigravity 會**靜默丟棄整支技能**,沒有任何錯誤訊息 |
|
||||||
| `tools/check-behaviors.sh` | 比對一個 domain 的 `references/behaviors.md` 與 `skills/`:節對技能、字典序、每節一張表、五個欄位齊全且內容欄非空;不符 exit 1,用法錯誤 exit 2,找不到清單或找不到技能 exit 3(**不等於通過**) |
|
| `tools/check-behaviors.sh` | 比對一個 domain 的 `references/behaviors.md` 與 `skills/`:節對技能、字典序、每節一張表、五個欄位齊全且內容欄非空;不符 exit 1,用法錯誤 exit 2,找不到清單或找不到技能 exit 3(**不等於通過**) |
|
||||||
|
| `tools/check-link-format.sh` | 檢查一個 domain 全部 `*.md` 的連結寫法:一律 `[{文字}]({連結})`,不留同 wiki 的雙括號連結。判定前先剝掉行內程式碼與圍籬區塊,所以說明用的字面與 shell 條件測試不會誤判。有命中 exit 1(清單在 stdout),用法錯誤 exit 2,沒有文件可掃 exit 3(**不等於通過**) |
|
||||||
| `tools/check-page-name.sh` | 比對 wiki 頁名樣式三處是否一致:`jsc-gitea/tools/page-name.sh`(正本)、`jsc-hooks/hooks/comment-scope.sh`、`jsc-log/tools/worklog-pending.sh`。三處刻意不共用函式,因為 hook 必須自足;斷言十五種型別、40 碼與 8 碼兩種長度。不一致 exit 1,用法錯誤 exit 2,三處一支都找不到 exit 3(**不等於通過**) |
|
| `tools/check-page-name.sh` | 比對 wiki 頁名樣式三處是否一致:`jsc-gitea/tools/page-name.sh`(正本)、`jsc-hooks/hooks/comment-scope.sh`、`jsc-log/tools/worklog-pending.sh`。三處刻意不共用函式,因為 hook 必須自足;斷言十五種型別、40 碼與 8 碼兩種長度。不一致 exit 1,用法錯誤 exit 2,三處一支都找不到 exit 3(**不等於通過**) |
|
||||||
| `tools/deploy-route.sh` | 判定改動有沒有進存取庫的預設分支,決定走部署路線(exit 0)或工作樹路線(exit 3);判不出來 exit 1,**不等於工作樹路線** |
|
| `tools/deploy-route.sh` | 判定改動有沒有進存取庫的預設分支,決定走部署路線(exit 0)或工作樹路線(exit 3);判不出來 exit 1,**不等於工作樹路線** |
|
||||||
| `tools/sync-domains.sh` | 依 Gitea 正本 marketplace 把所有 domain 存取庫 clone 或 pull 到本機,印出 `domain<TAB>path`;**只有 exit 0 代表全部到位且最新**,exit 3 代表有存取庫跳過或 pull 失敗(stderr 列路徑),exit 2 代表有 domain clone 失敗 |
|
| `tools/sync-domains.sh` | 依 Gitea 正本 marketplace 把所有 domain 存取庫 clone 或 pull 到本機,印出 `domain<TAB>path`;**只有 exit 0 代表全部到位且最新**,exit 3 代表有存取庫跳過或 pull 失敗(stderr 列路徑),exit 2 代表有 domain clone 失敗 |
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "jsc-meta",
|
"name": "jsc-meta",
|
||||||
"version": "0.2.8",
|
"version": "0.2.9",
|
||||||
"description": "技能組自我管理:新建、更新、刪除技能與技能準則",
|
"description": "技能組自我管理:新建、更新、刪除技能與技能準則",
|
||||||
"skills": "./skills/",
|
"skills": "./skills/",
|
||||||
"jsc": {
|
"jsc": {
|
||||||
|
|||||||
+20
-20
@@ -7,50 +7,50 @@
|
|||||||
| 項目 | 內容 |
|
| 項目 | 內容 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 觸發時機 | 手上沒有異動需求,要對整組技能做例行或臨時稽核時用。帶著異動需求要改多支技能走 skillset-update、只改一支走 skill-update |
|
| 觸發時機 | 手上沒有異動需求,要對整組技能做例行或臨時稽核時用。帶著異動需求要改多支技能走 skillset-update、只改一支走 skill-update |
|
||||||
| 關鍵步驟 | 先跑 sync-domains.sh 同步全部 domain 存取庫、再平行跑三組審查(第一組平行跑腳本檢查、frontmatter 檢查、行為清單檢查、語言檢查、wiki 規則檢查、頁名樣式檢查與 hook smoke,第二組以 sub agent 逐 domain 對 guidelines 檢查清單稽核,第三組先用 wiki-repo SKILLSET 與 hash-id 讀回各 domain SKILLSET_{HASH} 上已決議的優化建議再以 sub agent 分六個面向審查流程與成本;讀取回 7、8 或存取庫解不出來時只停掉該 domain 的第三組,第一組、第二組與後續步驟照跑)、合併三組結果並用決策樹逐項確認(第二組留白的八項由第一組的結論補上,其中頁名樣式與 wiki 規則兩項是整輪一份,同一個結論填進每個 domain;優化建議記下決議與決議日期)、以平行 sub agent 套用確認過的修正並跑 sync-skill-manifest.sh、跑 sync-marketplace.sh 同步兩份正本 marketplace、重跑三組驗證直到接受的修正全通過、每個受影響存取庫各開一條 PR、最後以平行 sub agent 逐 domain 把本輪稽核結果附加到 SKILLSET_{HASH},再取 wiki-url 的絕對網址、用 wiki-contents.sh upsert SKILLSET 2 把自己那一列寫進 CONTENTS 存取庫的 SKILLSET_CONTENTS |
|
| 關鍵步驟 | 先跑 sync-domains.sh 同步全部 domain 存取庫、再平行跑三組審查(第一組平行跑腳本檢查、frontmatter 檢查、行為清單檢查、語言檢查、連結寫法檢查、wiki 規則檢查、頁名樣式檢查與 hook smoke,第二組以 sub agent 逐 domain 對 guidelines 檢查清單稽核,第三組先用 wiki-repo SKILLSET 與 hash-id 讀回各 domain SKILLSET_{HASH} 上已決議的優化建議再以 sub agent 分六個面向審查流程與成本;讀取回 7、8 或存取庫解不出來時只停掉該 domain 的第三組,第一組、第二組與後續步驟照跑)、合併三組結果並用決策樹逐項確認(第二組留白的九項由第一組的結論補上,其中頁名樣式與 wiki 規則兩項是整輪一份,同一個結論填進每個 domain;優化建議記下決議與決議日期)、以平行 sub agent 套用確認過的修正並跑 sync-skill-manifest.sh、跑 sync-marketplace.sh 同步兩份正本 marketplace、重跑三組驗證直到接受的修正全通過、每個受影響存取庫各開一條 PR、最後以平行 sub agent 逐 domain 把本輪稽核結果附加到 SKILLSET_{HASH},再取 wiki-url 的絕對網址、把頁上與列上的每個連結交給 link-check.sh 驗證、退出 0 才用 wiki-contents.sh upsert SKILLSET 2 把自己那一列寫進 CONTENTS 存取庫的 SKILLSET_CONTENTS |
|
||||||
| 外部呼叫 | tools/sync-domains.sh、tools/lint-scripts.sh、tools/lint-frontmatter.sh、tools/check-behaviors.sh、tools/ste100-lint.sh、tools/check-page-name.sh、tools/sync-skill-manifest.sh、tools/sync-marketplace.sh、jsc-gitea/tools/check-wiki-rules.sh、jsc-gitea/tools/gitea.sh 的 wiki-repo、hash-id 與 wiki-url、jsc-gitea/tools/wiki-contents.sh upsert(目錄頁那一列)、jsc-cli/tools/detect-clis.sh、jsc-hooks/tools/wire-cli.sh smoke、jsc-ask:ask、jsc-git:pr、jsc-gitea:wiki、templates/skillset-page.md、templates/skillset-contents.md |
|
| 外部呼叫 | tools/sync-domains.sh、tools/lint-scripts.sh、tools/lint-frontmatter.sh、tools/check-behaviors.sh、tools/ste100-lint.sh、tools/check-link-format.sh、tools/check-page-name.sh、tools/sync-skill-manifest.sh、tools/sync-marketplace.sh、jsc-gitea/tools/check-wiki-rules.sh、jsc-gitea/tools/link-check.sh、jsc-gitea/tools/gitea.sh 的 wiki-repo、hash-id 與 wiki-url、jsc-gitea/tools/wiki-contents.sh upsert(目錄頁那一列)、jsc-cli/tools/detect-clis.sh、jsc-hooks/tools/wire-cli.sh smoke、jsc-ask:ask、jsc-git:pr、jsc-gitea:wiki、templates/skillset-page.md、templates/skillset-contents.md |
|
||||||
| 完成條件 | 每個 domain 都有腳本檢查、frontmatter 檢查、行為清單檢查與語言檢查的結論,wiki 規則檢查與頁名樣式檢查各有一次結論(frontmatter 檢查退出 3 是「什麼都沒掃」、頁名樣式檢查退出 3 是「什麼都沒查」,都不算通過)、每個 domain 的檢查清單在合併後補齊且那兩項整輪一份的結論在每個 domain 都填上同一個值、讀不到已決議清單的 domain 記成「本輪未取得已決議清單,優化建議暫不提出」、每項不合規與每項優化建議都有決策紀錄且優化建議帶決議日期、接受的修正重驗通過、每個受影響存取庫都拿到 PR 網址、每個受影響 domain 的 wiki 頁都寫成功,或列為未寫入並附完整內容 |
|
| 完成條件 | 每個 domain 都有腳本檢查、frontmatter 檢查、行為清單檢查、語言檢查與連結寫法檢查的結論(連結寫法檢查退出 3 是「什麼都沒掃」,不算通過),wiki 規則檢查與頁名樣式檢查各有一次結論(frontmatter 檢查退出 3 是「什麼都沒掃」、頁名樣式檢查退出 3 是「什麼都沒查」,都不算通過)、每個 domain 的檢查清單在合併後補齊且那兩項整輪一份的結論在每個 domain 都填上同一個值、讀不到已決議清單的 domain 記成「本輪未取得已決議清單,優化建議暫不提出」、每項不合規與每項優化建議都有決策紀錄且優化建議帶決議日期、接受的修正重驗通過、每個受影響存取庫都拿到 PR 網址、寫進 wiki 的每個連結都先經 link-check.sh 退出 0、每個受影響 domain 的 wiki 頁都寫成功,或列為未寫入並附完整內容 |
|
||||||
| 可驗證跡象 | 受影響存取庫留下檔案改動、改到行為的技能連帶改寫該存取庫的 references/behaviors.md、每個 domain 的 lint-frontmatter.sh 與 ste100-lint.sh 退出 0、check-page-name.sh 退出 0、README 的「Skills 目錄」重寫、三份 manifest 版本號提升、兩份 marketplace 檔逐位元一致、每個受影響存取庫一條 PR、每個受影響 domain 的 SKILLSET_{HASH} 各附加一節,並由 wiki-contents.sh upsert 退出 0 在 SKILLSET_CONTENTS 留下自己那一列、列裡以絕對網址指向該內容頁;本輪無 domain 被改動時,改成 plugins/meta 那一頁記「本輪無發現」 |
|
| 可驗證跡象 | 受影響存取庫留下檔案改動、改到行為的技能連帶改寫該存取庫的 references/behaviors.md、每個 domain 的 lint-frontmatter.sh、ste100-lint.sh 與 check-link-format.sh 退出 0、check-page-name.sh 退出 0、README 的「Skills 目錄」重寫、三份 manifest 版本號提升、兩份 marketplace 檔逐位元一致、每個受影響存取庫一條 PR、每個受影響 domain 的 SKILLSET_{HASH} 各附加一節,並由 wiki-contents.sh upsert 退出 0 在 SKILLSET_CONTENTS 留下自己那一列、列裡以 `[SKILLSET_{HASH}]({連結})` 的絕對網址指向該內容頁;本輪無 domain 被改動時,改成 plugins/meta 那一頁記「本輪無發現」 |
|
||||||
|
|
||||||
## skill-delete
|
## skill-delete
|
||||||
|
|
||||||
| 項目 | 內容 |
|
| 項目 | 內容 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 觸發時機 | 要把一支技能從技能組移除時用。改名不走這支,走 skill-update |
|
| 觸發時機 | 要把一支技能從技能組移除時用。改名不走這支,走 skill-update |
|
||||||
| 關鍵步驟 | 跑 sync-domains.sh 同步、跑 list-skills.sh 列出全部技能、讓使用者挑一支確認刪除、跑 find-skill-refs.sh 盤點所有引用檔案、以平行 sub agent 逐檔修正到檢查清單全過、刪掉 skills/{name}/ 目錄、移除 references/behaviors.md 對應那一節、跑 sync-skill-manifest.sh、開 PR、依 deploy-verify.md 部署、用新的 CLI 行程驗證、跑 verify-skill-removed.sh 查磁碟殘留、用 wiki-repo SKILLSET 解出存取庫並依 templates/skillset-page.md 把異動報告附加到 SKILLSET_{HASH}、再取 wiki-url 的絕對網址、用 wiki-contents.sh upsert SKILLSET 2 把自己那一列寫進 CONTENTS 存取庫的 SKILLSET_CONTENTS 並依 0、1、2、3、4、7、8 各自分流 |
|
| 關鍵步驟 | 跑 sync-domains.sh 同步、跑 list-skills.sh 列出全部技能、讓使用者挑一支確認刪除、跑 find-skill-refs.sh 盤點所有引用檔案、以平行 sub agent 逐檔修正到檢查清單全過、刪掉 skills/{name}/ 目錄、移除 references/behaviors.md 對應那一節、跑 sync-skill-manifest.sh、開 PR、依 deploy-verify.md 部署、用新的 CLI 行程驗證、跑 verify-skill-removed.sh 查磁碟殘留、用 wiki-repo SKILLSET 解出存取庫並依 templates/skillset-page.md 把異動報告附加到 SKILLSET_{HASH}、再取 wiki-url 的絕對網址、把頁上與列上的每個連結交給 link-check.sh 驗證、退出 0 才用 wiki-contents.sh upsert SKILLSET 2 把自己那一列寫進 CONTENTS 存取庫的 SKILLSET_CONTENTS 並依 0、1、2、3、4、7、8 各自分流 |
|
||||||
| 外部呼叫 | tools/sync-domains.sh、tools/list-skills.sh、tools/find-skill-refs.sh、tools/check-behaviors.sh、tools/sync-skill-manifest.sh、tools/deploy-route.sh、tools/verify-skill-removed.sh、jsc-gitea/tools/gitea.sh 的 wiki-repo、hash-id 與 wiki-url、jsc-gitea/tools/wiki-contents.sh upsert(目錄頁那一列)、jsc-ask:ask、jsc-git:pr、jsc-gitea:wiki、templates/skillset-page.md、templates/skillset-contents.md |
|
| 外部呼叫 | tools/sync-domains.sh、tools/list-skills.sh、tools/find-skill-refs.sh、tools/check-behaviors.sh、tools/sync-skill-manifest.sh、tools/deploy-route.sh、tools/verify-skill-removed.sh、jsc-gitea/tools/link-check.sh、jsc-gitea/tools/gitea.sh 的 wiki-repo、hash-id 與 wiki-url、jsc-gitea/tools/wiki-contents.sh upsert(目錄頁那一列)、jsc-ask:ask、jsc-git:pr、jsc-gitea:wiki、templates/skillset-page.md、templates/skillset-contents.md |
|
||||||
| 完成條件 | 盤點清單每一檔都有「已修正」或「無需修正」的結論、技能目錄與行為清單那一節都不存在、list-skills.sh 查不到那一列、殘留檢查退出 0 或據實記成「無處可查」並帶進報告、PR 網址到手、SKILLSET_{HASH} 附加一節且舊節原樣留著、wiki-contents.sh upsert 退出 0 |
|
| 完成條件 | 盤點清單每一檔都有「已修正」或「無需修正」的結論、技能目錄與行為清單那一節都不存在、list-skills.sh 查不到那一列、殘留檢查退出 0 或據實記成「無處可查」並帶進報告、PR 網址到手、寫進頁與列的每個連結都經 link-check.sh 退出 0、SKILLSET_{HASH} 附加一節且舊節原樣留著、wiki-contents.sh upsert 退出 0 |
|
||||||
| 可驗證跡象 | skills/{name}/ 目錄消失、references/behaviors.md 少一節、README 與三份 manifest 更新、一條 PR、wiki SKILLSET_{HASH} 附加一節,並在 CONTENTS 存取庫的 SKILLSET_CONTENTS 留下自己那一列、列裡以絕對網址指向該內容頁 |
|
| 可驗證跡象 | skills/{name}/ 目錄消失、references/behaviors.md 少一節、README 與三份 manifest 更新、一條 PR、wiki SKILLSET_{HASH} 附加一節,並在 CONTENTS 存取庫的 SKILLSET_CONTENTS 留下自己那一列、列裡以 `[SKILLSET_{HASH}]({連結})` 的絕對網址指向該內容頁 |
|
||||||
|
|
||||||
## skill-new
|
## skill-new
|
||||||
|
|
||||||
| 項目 | 內容 |
|
| 項目 | 內容 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 觸發時機 | 要在技能組新增一支技能時用。改既有技能走 skill-update |
|
| 觸發時機 | 要在技能組新增一支技能時用。改既有技能走 skill-update |
|
||||||
| 關鍵步驟 | 平行跑 list-skills.sh 與 sync-domains.sh 預取技能清單與 domain 清單、用決策樹問出目標、觸發時機、輸入輸出與所屬 domain、domain 未註冊就先確認存取庫在不在、依 template 結構補齊內容再跑 sync-marketplace.sh 註冊、以 sub agent 產生 skills/{name}/SKILL.md、在 references/behaviors.md 依字典序插入該技能一節、跑 sync-skill-manifest.sh、自查 guidelines 檢查清單並跑 check-behaviors.sh、開 PR、依 deploy-verify.md 部署並用新的 CLI 行程驗證、用 wiki-repo SKILLSET 解出存取庫並依 templates/skillset-page.md 把異動報告附加到 SKILLSET_{HASH}、再取 wiki-url 的絕對網址、用 wiki-contents.sh upsert SKILLSET 2 把自己那一列寫進 CONTENTS 存取庫的 SKILLSET_CONTENTS 並依 0、1、2、3、4、7、8 各自分流 |
|
| 關鍵步驟 | 平行跑 list-skills.sh 與 sync-domains.sh 預取技能清單與 domain 清單、用決策樹問出目標、觸發時機、輸入輸出與所屬 domain、domain 未註冊就先確認存取庫在不在、依 template 結構補齊內容再跑 sync-marketplace.sh 註冊、以 sub agent 產生 skills/{name}/SKILL.md、在 references/behaviors.md 依字典序插入該技能一節、跑 sync-skill-manifest.sh、自查 guidelines 檢查清單並跑 check-behaviors.sh、開 PR、依 deploy-verify.md 部署並用新的 CLI 行程驗證、用 wiki-repo SKILLSET 解出存取庫並依 templates/skillset-page.md 把異動報告附加到 SKILLSET_{HASH}、再取 wiki-url 的絕對網址、把頁上與列上的每個連結交給 link-check.sh 驗證、退出 0 才用 wiki-contents.sh upsert SKILLSET 2 把自己那一列寫進 CONTENTS 存取庫的 SKILLSET_CONTENTS 並依 0、1、2、3、4、7、8 各自分流 |
|
||||||
| 外部呼叫 | tools/list-skills.sh、tools/sync-domains.sh、tools/sync-marketplace.sh、tools/check-behaviors.sh、tools/sync-skill-manifest.sh、tools/deploy-route.sh、jsc-gitea/tools/gitea.sh 的 clone-url、api、wiki-repo、hash-id 與 wiki-url、jsc-gitea/tools/wiki-contents.sh upsert(目錄頁那一列)、jsc-ask:ask、jsc-git:pr、jsc-gitea:wiki、templates/skillset-page.md、templates/skillset-contents.md |
|
| 外部呼叫 | tools/list-skills.sh、tools/sync-domains.sh、tools/sync-marketplace.sh、tools/check-behaviors.sh、tools/sync-skill-manifest.sh、tools/deploy-route.sh、jsc-gitea/tools/link-check.sh、jsc-gitea/tools/gitea.sh 的 clone-url、api、wiki-repo、hash-id 與 wiki-url、jsc-gitea/tools/wiki-contents.sh upsert(目錄頁那一列)、jsc-ask:ask、jsc-git:pr、jsc-gitea:wiki、templates/skillset-page.md、templates/skillset-contents.md |
|
||||||
| 完成條件 | 四項提問都有紀錄、SKILL.md 與行為清單那一節都在、README 與三份 manifest 同步、檢查清單全過且 check-behaviors.sh 退出 0、PR 網址到手、deploy-verify.md 第 1 到第 5 節的完成條件全數成立、SKILLSET_{HASH} 附加一節且舊節原樣留著、wiki-contents.sh upsert 退出 0 |
|
| 完成條件 | 四項提問都有紀錄、SKILL.md 與行為清單那一節都在、README 與三份 manifest 同步、檢查清單全過且 check-behaviors.sh 退出 0、PR 網址到手、deploy-verify.md 第 1 到第 5 節的完成條件全數成立、寫進頁與列的每個連結都經 link-check.sh 退出 0、SKILLSET_{HASH} 附加一節且舊節原樣留著、wiki-contents.sh upsert 退出 0 |
|
||||||
| 可驗證跡象 | 新增 skills/{name}/SKILL.md、references/behaviors.md 多一節、README 與三份 manifest 更新、新 domain 時兩份 marketplace 檔多一筆 plugin 條目並同步到每個 domain 存取庫、一條 PR、wiki SKILLSET_{HASH} 附加一節,並在 CONTENTS 存取庫的 SKILLSET_CONTENTS 留下自己那一列、列裡以絕對網址指向該內容頁 |
|
| 可驗證跡象 | 新增 skills/{name}/SKILL.md、references/behaviors.md 多一節、README 與三份 manifest 更新、新 domain 時兩份 marketplace 檔多一筆 plugin 條目並同步到每個 domain 存取庫、一條 PR、wiki SKILLSET_{HASH} 附加一節,並在 CONTENTS 存取庫的 SKILLSET_CONTENTS 留下自己那一列、列裡以 `[SKILLSET_{HASH}]({連結})` 的絕對網址指向該內容頁 |
|
||||||
|
|
||||||
## skill-update
|
## skill-update
|
||||||
|
|
||||||
| 項目 | 內容 |
|
| 項目 | 內容 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 觸發時機 | 要改一支既有技能時用。新增走 skill-new、刪除走 skill-delete、一次改多支或跨 domain 走 skillset-update |
|
| 觸發時機 | 要改一支既有技能時用。新增走 skill-new、刪除走 skill-delete、一次改多支或跨 domain 走 skillset-update |
|
||||||
| 關鍵步驟 | 跑 sync-domains.sh 同步、跑 list-skills.sh 列出全部技能、讓使用者挑一支、用決策樹問出改動細節、以 sub agent 改 SKILL.md 與相關檔案、同步更新 references/behaviors.md 該技能那一節、跑 sync-skill-manifest.sh、對 guidelines 檢查清單逐項自查並跑 check-behaviors.sh、開 PR、依 deploy-verify.md 部署並用新的 CLI 行程驗證、用 wiki-repo SKILLSET 解出存取庫並依 templates/skillset-page.md 把異動報告附加到 SKILLSET_{HASH}、再取 wiki-url 的絕對網址、用 wiki-contents.sh upsert SKILLSET 2 把自己那一列寫進 CONTENTS 存取庫的 SKILLSET_CONTENTS 並依 0、1、2、3、4、7、8 各自分流 |
|
| 關鍵步驟 | 跑 sync-domains.sh 同步、跑 list-skills.sh 列出全部技能、讓使用者挑一支、用決策樹問出改動細節、以 sub agent 改 SKILL.md 與相關檔案、同步更新 references/behaviors.md 該技能那一節、跑 sync-skill-manifest.sh、對 guidelines 檢查清單逐項自查並跑 check-behaviors.sh、開 PR、依 deploy-verify.md 部署並用新的 CLI 行程驗證、用 wiki-repo SKILLSET 解出存取庫並依 templates/skillset-page.md 把異動報告附加到 SKILLSET_{HASH}、再取 wiki-url 的絕對網址、把頁上與列上的每個連結交給 link-check.sh 驗證、退出 0 才用 wiki-contents.sh upsert SKILLSET 2 把自己那一列寫進 CONTENTS 存取庫的 SKILLSET_CONTENTS 並依 0、1、2、3、4、7、8 各自分流 |
|
||||||
| 外部呼叫 | tools/sync-domains.sh、tools/list-skills.sh、tools/check-behaviors.sh、tools/sync-skill-manifest.sh、tools/deploy-route.sh、jsc-gitea/tools/gitea.sh 的 wiki-repo、hash-id 與 wiki-url、jsc-gitea/tools/wiki-contents.sh upsert(目錄頁那一列)、jsc-ask:ask、jsc-git:pr、jsc-gitea:wiki、templates/skillset-page.md、templates/skillset-contents.md |
|
| 外部呼叫 | tools/sync-domains.sh、tools/list-skills.sh、tools/check-behaviors.sh、tools/sync-skill-manifest.sh、tools/deploy-route.sh、jsc-gitea/tools/link-check.sh、jsc-gitea/tools/gitea.sh 的 wiki-repo、hash-id 與 wiki-url、jsc-gitea/tools/wiki-contents.sh upsert(目錄頁那一列)、jsc-ask:ask、jsc-git:pr、jsc-gitea:wiki、templates/skillset-page.md、templates/skillset-contents.md |
|
||||||
| 完成條件 | 每個提問都有紀錄、技能檔案帶著改動、行為清單那一節與新行為一致且 check-behaviors.sh 退出 0、三份 manifest 同版、檢查清單全過、PR 網址到手、deploy-verify.md 第 1 到第 5 節的完成條件全數成立、SKILLSET_{HASH} 附加一節且舊節原樣留著、wiki-contents.sh upsert 退出 0 |
|
| 完成條件 | 每個提問都有紀錄、技能檔案帶著改動、行為清單那一節與新行為一致且 check-behaviors.sh 退出 0、三份 manifest 同版、檢查清單全過、PR 網址到手、deploy-verify.md 第 1 到第 5 節的完成條件全數成立、寫進頁與列的每個連結都經 link-check.sh 退出 0、SKILLSET_{HASH} 附加一節且舊節原樣留著、wiki-contents.sh upsert 退出 0 |
|
||||||
| 可驗證跡象 | 該技能的 SKILL.md 與相關檔案改動、references/behaviors.md 對應節改寫、README 與三份 manifest 更新、一條 PR、wiki SKILLSET_{HASH} 附加一節,並在 CONTENTS 存取庫的 SKILLSET_CONTENTS 留下自己那一列、列裡以絕對網址指向該內容頁 |
|
| 可驗證跡象 | 該技能的 SKILL.md 與相關檔案改動、references/behaviors.md 對應節改寫、README 與三份 manifest 更新、一條 PR、wiki SKILLSET_{HASH} 附加一節,並在 CONTENTS 存取庫的 SKILLSET_CONTENTS 留下自己那一列、列裡以 `[SKILLSET_{HASH}]({連結})` 的絕對網址指向該內容頁 |
|
||||||
|
|
||||||
## skillset-update
|
## skillset-update
|
||||||
|
|
||||||
| 項目 | 內容 |
|
| 項目 | 內容 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 觸發時機 | 一個異動需求橫跨多支技能或多個 domain,要一次做完時用。只改一支走 skill-update、手上沒有異動需求的例行稽核走 skill-check |
|
| 觸發時機 | 一個異動需求橫跨多支技能或多個 domain,要一次做完時用。只改一支走 skill-update、手上沒有異動需求的例行稽核走 skill-check |
|
||||||
| 關鍵步驟 | 平行啟動 sync-domains.sh 與異動細節決策樹、問清楚改哪一條規則、影響哪些技能與 domain,並補問工具化、sub agent、環境變數三項塑形檢查、以每個 domain 一個 sub agent 平行套用改動、同步更新每個受影響 domain 的 references/behaviors.md、逐存取庫跑 sync-skill-manifest.sh、以平行 sub agent 重跑 guidelines 檢查清單與 check-behaviors.sh 直到全過、每個受影響存取庫各開一條 PR、依 deploy-verify.md 部署並用新的 CLI 行程驗證、以平行 sub agent 逐存取庫用 wiki-repo SKILLSET 解出存取庫並依 templates/skillset-page.md 把異動報告附加到 SKILLSET_{HASH}、再取 wiki-url 的絕對網址、用 wiki-contents.sh upsert SKILLSET 2 把自己那一列寫進 CONTENTS 存取庫的 SKILLSET_CONTENTS 並依 0、1、2、3、4、7、8 各自分流 |
|
| 關鍵步驟 | 平行啟動 sync-domains.sh 與異動細節決策樹、問清楚改哪一條規則、影響哪些技能與 domain,並補問工具化、sub agent、環境變數三項塑形檢查、以每個 domain 一個 sub agent 平行套用改動、同步更新每個受影響 domain 的 references/behaviors.md、逐存取庫跑 sync-skill-manifest.sh、以平行 sub agent 重跑 guidelines 檢查清單與 check-behaviors.sh 直到全過、每個受影響存取庫各開一條 PR、依 deploy-verify.md 部署並用新的 CLI 行程驗證、以平行 sub agent 逐存取庫用 wiki-repo SKILLSET 解出存取庫並依 templates/skillset-page.md 把異動報告附加到 SKILLSET_{HASH}、再取 wiki-url 的絕對網址、把頁上與列上的每個連結交給 link-check.sh 驗證、退出 0 才用 wiki-contents.sh upsert SKILLSET 2 把自己那一列寫進 CONTENTS 存取庫的 SKILLSET_CONTENTS 並依 0、1、2、3、4、7、8 各自分流 |
|
||||||
| 外部呼叫 | tools/sync-domains.sh、tools/check-behaviors.sh、tools/sync-skill-manifest.sh、tools/deploy-route.sh、tools/list-skills.sh、jsc-gitea/tools/gitea.sh 的 wiki-repo、hash-id 與 wiki-url、jsc-gitea/tools/wiki-contents.sh upsert(目錄頁那一列)、jsc-ask:ask、jsc-git:pr、jsc-gitea:wiki、templates/skillset-page.md、templates/skillset-contents.md |
|
| 外部呼叫 | tools/sync-domains.sh、tools/check-behaviors.sh、tools/sync-skill-manifest.sh、tools/deploy-route.sh、tools/list-skills.sh、jsc-gitea/tools/link-check.sh、jsc-gitea/tools/gitea.sh 的 wiki-repo、hash-id 與 wiki-url、jsc-gitea/tools/wiki-contents.sh upsert(目錄頁那一列)、jsc-ask:ask、jsc-git:pr、jsc-gitea:wiki、templates/skillset-page.md、templates/skillset-contents.md |
|
||||||
| 完成條件 | 受影響技能清單與三項塑形檢查都跟使用者談定、每個受影響存取庫都帶著改動、README 同步與 manifest 提升、每支動過的技能檢查清單全過且該 domain 的 check-behaviors.sh 退出 0、每個受影響存取庫都有 PR 網址、deploy-verify.md 第 1 到第 5 節對每個存取庫都成立、每個存取庫的 SKILLSET_{HASH} 都附加一節且舊節原樣留著、每個存取庫的 wiki-contents.sh upsert 都退出 0 |
|
| 完成條件 | 受影響技能清單與三項塑形檢查都跟使用者談定、每個受影響存取庫都帶著改動、README 同步與 manifest 提升、每支動過的技能檢查清單全過且該 domain 的 check-behaviors.sh 退出 0、每個受影響存取庫都有 PR 網址、deploy-verify.md 第 1 到第 5 節對每個存取庫都成立、每個存取庫寫進頁與列的每個連結都經 link-check.sh 退出 0、每個存取庫的 SKILLSET_{HASH} 都附加一節且舊節原樣留著、每個存取庫的 wiki-contents.sh upsert 都退出 0 |
|
||||||
| 可驗證跡象 | 每個受影響存取庫的技能檔案改動、各自的 references/behaviors.md 更新、README 與三份 manifest 更新、每個存取庫一條 PR、每個存取庫的 wiki SKILLSET_{HASH} 各附加一節,並在 CONTENTS 存取庫的 SKILLSET_CONTENTS 各留下自己那一列、列裡以絕對網址指向該內容頁 |
|
| 可驗證跡象 | 每個受影響存取庫的技能檔案改動、各自的 references/behaviors.md 更新、README 與三份 manifest 更新、每個存取庫一條 PR、每個存取庫的 wiki SKILLSET_{HASH} 各附加一節,並在 CONTENTS 存取庫的 SKILLSET_CONTENTS 各留下自己那一列、列裡以 `[SKILLSET_{HASH}]({連結})` 的絕對網址指向該內容頁 |
|
||||||
|
|
||||||
## ste100-sync
|
## ste100-sync
|
||||||
|
|
||||||
|
|||||||
@@ -377,11 +377,17 @@ kiro 是唯一真的擋不了的,verdict 據實寫 `degraded`,不寫 `wired`
|
|||||||
它只用來解存取庫,`gitea.sh wiki-repo CONTENTS` 是全部目錄頁的解析入口。
|
它只用來解存取庫,`gitea.sh wiki-repo CONTENTS` 是全部目錄頁的解析入口。
|
||||||
總表列的十四種是頁的分類,`CONTENTS` 是存取庫的分類,兩張清單長度不同是正常的。
|
總表列的十四種是頁的分類,`CONTENTS` 是存取庫的分類,兩張清單長度不同是正常的。
|
||||||
|
|
||||||
三條規則,寫入前逐條核對:
|
四條規則,寫入前逐條核對:
|
||||||
|
|
||||||
1. 任何 `*_CONTENTS` 頁都走 `gitea.sh wiki-repo CONTENTS`,十四種型別的目錄頁全部落在同一個存取庫。
|
1. 任何 `*_CONTENTS` 頁都走 `gitea.sh wiki-repo CONTENTS`,十四種型別的目錄頁全部落在同一個存取庫。
|
||||||
2. 目錄頁的解析鏈**不退回型別變數**。設了 `JSC_WIKI_REPO_LOG` 不會讓 `LOG_CONTENTS` 跟著搬過去。
|
2. 目錄頁的解析鏈**不退回型別變數**。設了 `JSC_WIKI_REPO_LOG` 不會讓 `LOG_CONTENTS` 跟著搬過去。
|
||||||
3. 目錄頁指向內容頁的連結**一律用絕對網址**(`{GITEA_HOST}/{owner}/{repo}/wiki/{頁名}`),不用 `[[頁名]]` 這種同 wiki 連結。兩頁跨存取庫,同 wiki 連結會指到目錄頁自己那個存取庫裡不存在的頁,點下去是 404,而且看起來像頁沒寫成功。
|
3. **文字加連結一律寫成 `[{文字}]({連結})`。** 不分目錄頁或內容頁,也不分同存取庫或跨存取庫,全部只有這一種寫法。`[[頁名]]` 與 `[[顯示文字|頁名]]` 兩種同 wiki 連結全面取消。網址取自 `jsc-gitea/tools/gitea.sh wiki-url`,不自行組路徑。
|
||||||
|
|
||||||
|
**為什麼只留一種寫法。** `[[...]]` 只在目前這個 wiki 內解析。寫錯不會報錯,畫面上看起來像正常文字或死連結,巡不到也修不了。兩種寫法並存就得逐處判斷兩端各自解到哪個存取庫;統一成一種,這個判斷消失。
|
||||||
|
|
||||||
|
4. **連結先驗證連得到,才可以寫進文件。** 寫入任何文件前,把要放進去的每一個連結交給 `jsc-gitea/tools/link-check.sh`,結束碼 0 才寫入。有任何一筆連不到就不寫入,把連不到的清單回報給呼叫端。結束碼分流以那支腳本的檔頭為準:0 才寫入,1 不得寫入並回報死連結那幾筆,2 與 3 補齊參數或 `GITEA_HOST` 再呼叫,7 停下來回報金鑰問題。
|
||||||
|
|
||||||
|
**為什麼驗證走 API,不看網頁狀態碼。** 私有存取庫的網頁網址對未登入請求一律回 404。拿網頁狀態碼判斷,會把還在的頁判成死連結,接著整批被刪掉或改寫。金鑰失效那一種也要與死連結分開回報,理由一樣:一次金鑰過期就會把整批好頁判成壞的。
|
||||||
|
|
||||||
**為什麼要分開。** 目錄頁是全部使用者共用的索引,內容頁按專案或機器分散在各自的存取庫。混在一起的話,換一個專案就換一份索引,「這台機器有哪些頁」永遠問不到完整答案。索引集中一處、內容各自落地,才查得到全貌。
|
**為什麼要分開。** 目錄頁是全部使用者共用的索引,內容頁按專案或機器分散在各自的存取庫。混在一起的話,換一個專案就換一份索引,「這台機器有哪些頁」永遠問不到完整答案。索引集中一處、內容各自落地,才查得到全貌。
|
||||||
|
|
||||||
@@ -442,7 +448,8 @@ kiro 是唯一真的擋不了的,verdict 據實寫 `degraded`,不寫 `wired`
|
|||||||
- [ ] 細節流程已標示 MUST run as a sub agent
|
- [ ] 細節流程已標示 MUST run as a sub agent
|
||||||
- [ ] gitea 操作透過 gitea.sh 或 tea
|
- [ ] gitea 操作透過 gitea.sh 或 tea
|
||||||
- [ ] wiki repo 與 Gitea 認證先讀目前 shell 繼承的環境變數;只有缺值或無法解析時才詢問;頁面類型不得跨用其他 `JSC_WIKI_REPO_{TYPE}`
|
- [ ] wiki repo 與 Gitea 認證先讀目前 shell 繼承的環境變數;只有缺值或無法解析時才詢問;頁面類型不得跨用其他 `JSC_WIKI_REPO_{TYPE}`
|
||||||
- [ ] 目錄頁一律解 `CONTENTS` 存取庫(`gitea.sh wiki-repo CONTENTS`),內容頁解自己的型別;目錄頁指向內容頁的連結用絕對網址
|
- [ ] 目錄頁一律解 `CONTENTS` 存取庫(`gitea.sh wiki-repo CONTENTS`),內容頁解自己的型別;所有連結一律寫成 `[{文字}]({連結})`,網址取自 `gitea.sh wiki-url`,不用 `[[頁名]]`
|
||||||
|
- [ ] 文件裡的連結都經過 `jsc-gitea/tools/link-check.sh` 驗證(結束碼 0 才寫入)且格式為 `[{文字}]({連結})`;`tools/check-link-format.sh {domain-path}` 對該 domain 退出 0,退出 3 是「什麼都沒掃」,不算通過
|
||||||
- [ ] 頁名樣式三處一致:`jsc-gitea/tools/page-name.sh`(正本)、`jsc-hooks/hooks/comment-scope.sh`、`jsc-log/tools/worklog-pending.sh`,`tools/check-page-name.sh {root}` 退出 0;退出 3 是「什麼都沒查」,不算通過。三處刻意不共用函式,因為 hook 必須自足,不得在執行期相依別的 plugin 路徑
|
- [ ] 頁名樣式三處一致:`jsc-gitea/tools/page-name.sh`(正本)、`jsc-hooks/hooks/comment-scope.sh`、`jsc-log/tools/worklog-pending.sh`,`tools/check-page-name.sh {root}` 退出 0;退出 3 是「什麼都沒查」,不算通過。三處刻意不共用函式,因為 hook 必須自足,不得在執行期相依別的 plugin 路徑
|
||||||
- [ ] 問詢透過 jsc-ask 決策樹規則
|
- [ ] 問詢透過 jsc-ask 決策樹規則
|
||||||
- [ ] `tools/` 與 `hooks/` 內的 shell 腳本都通過 `sh -n`;技能直接呼叫的腳本都存在、可執行,且退出碼有分流
|
- [ ] `tools/` 與 `hooks/` 內的 shell 腳本都通過 `sh -n`;技能直接呼叫的腳本都存在、可執行,且退出碼有分流
|
||||||
|
|||||||
+17
-10
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: skill-check
|
name: skill-check
|
||||||
description: Routine compliance, script, hook, flow-efficiency, and cost-efficiency audit of the whole jsc skill set with no change request in hand. Sync every domain repo from the Gitea canonical marketplace, then run three parallel groups - lint-scripts.sh plus lint-frontmatter.sh plus check-behaviors.sh plus ste100-lint.sh plus check-wiki-rules.sh plus check-page-name.sh plus hook smoke, the guidelines.md checklist audit, and an optimization review that first reads each domain's SKILLSET_{HASH} so suggestions already applied or deferred are never re-scanned or re-asked, then covers parallelism, tool extraction, repeated interaction, redundant checks, misplaced gates, and avoidable token, sub-agent, API, scan, or interaction cost. Confirm compliance fixes and optimization suggestions before applying them, recording each decision with its date, re-check until accepted fixes pass, then open a PR per affected repo via jsc-git pr. Close by appending the round's result to every changed domain's SKILLSET_{HASH} and its SKILLSET_CONTENTS row, or to the plugins/meta page when no domain was changed. Use for periodic or on-demand skill-set checks; not for applying a change request (use skillset-update) or editing one skill (use skill-update).
|
description: Routine compliance, script, hook, flow-efficiency, and cost-efficiency audit of the whole jsc skill set with no change request in hand. Sync every domain repo from the Gitea canonical marketplace, then run three parallel groups - lint-scripts.sh plus lint-frontmatter.sh plus check-behaviors.sh plus ste100-lint.sh plus check-link-format.sh plus check-wiki-rules.sh plus check-page-name.sh plus hook smoke, the guidelines.md checklist audit, and an optimization review that first reads each domain's SKILLSET_{HASH} so suggestions already applied or deferred are never re-scanned or re-asked, then covers parallelism, tool extraction, repeated interaction, redundant checks, misplaced gates, and avoidable token, sub-agent, API, scan, or interaction cost. Confirm compliance fixes and optimization suggestions before applying them, recording each decision with its date, re-check until accepted fixes pass, then open a PR per affected repo via jsc-git pr. Close by appending the round's result to every changed domain's SKILLSET_{HASH} and its SKILLSET_CONTENTS row, or to the plugins/meta page when no domain was changed. Use for periodic or on-demand skill-set checks; not for applying a change request (use skillset-update) or editing one skill (use skill-update).
|
||||||
---
|
---
|
||||||
|
|
||||||
# skill-check — audit compliance, flow efficiency, and cost efficiency
|
# skill-check — audit compliance, flow efficiency, and cost efficiency
|
||||||
@@ -19,12 +19,13 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
2. For every synced domain repo, run `tools/lint-frontmatter.sh {domain-path}`. One run per domain, and the runs go **in parallel** alongside the `lint-scripts.sh` runs. It parses the frontmatter of every `skills/*/SKILL.md` without a YAML library — paired `---` delimiters, the required `name` and `description` keys, unquoted scalars carrying a colon-space or ending in a colon, unquoted scalars opening with `&`, `*`, `!`, `|`, `>`, `%`, `@` or a backtick, and quoted scalars that never close. Route each exit code: 0 — every SKILL.md in that domain parses; 1 — the failures are printed on stderr as `{檔案}:{鍵}:{說明}`, so report every one as a compliance failure with the file and key it belongs to; 2 — usage error, the tool takes exactly one argument; 3 — nothing was scanned, because the domain path or `skills/` is missing, or `skills/` holds no `SKILL.md`. Record exit 3 as 「無 frontmatter 可掃」with the cause from stderr and carry it into the step 3 merge; exit 3 is **never** a pass. This check exists because a broken frontmatter makes Antigravity drop the whole skill with **no error message at all** — 34 skills on disk loaded as 28, and only a file-by-file comparison found it.
|
2. For every synced domain repo, run `tools/lint-frontmatter.sh {domain-path}`. One run per domain, and the runs go **in parallel** alongside the `lint-scripts.sh` runs. It parses the frontmatter of every `skills/*/SKILL.md` without a YAML library — paired `---` delimiters, the required `name` and `description` keys, unquoted scalars carrying a colon-space or ending in a colon, unquoted scalars opening with `&`, `*`, `!`, `|`, `>`, `%`, `@` or a backtick, and quoted scalars that never close. Route each exit code: 0 — every SKILL.md in that domain parses; 1 — the failures are printed on stderr as `{檔案}:{鍵}:{說明}`, so report every one as a compliance failure with the file and key it belongs to; 2 — usage error, the tool takes exactly one argument; 3 — nothing was scanned, because the domain path or `skills/` is missing, or `skills/` holds no `SKILL.md`. Record exit 3 as 「無 frontmatter 可掃」with the cause from stderr and carry it into the step 3 merge; exit 3 is **never** a pass. This check exists because a broken frontmatter makes Antigravity drop the whole skill with **no error message at all** — 34 skills on disk loaded as 28, and only a file-by-file comparison found it.
|
||||||
3. For every synced domain repo, run `tools/check-behaviors.sh {domain-path}`. One run per domain, and the runs go **in parallel** alongside the `lint-scripts.sh` runs — no domain's verdict depends on another's. It compares `references/behaviors.md` against `skills/`: section per skill, dictionary order, one table per section, five rows, no empty content cell. Route each exit code: 0 — that domain's behavior list matches; 1 — the mismatches are printed on stderr as `{檔案}:{技能名}:{說明}`, so report every one as a compliance failure with the skill it belongs to; 2 — usage error, the tool takes exactly one argument; 3 — nothing was checked, because `references/behaviors.md` is missing, `skills/` is missing, or no `SKILL.md` was found. Record exit 3 as 「無清單可查」with the cause from stderr and carry it into the step 3 merge; a domain with no behavior list is a compliance failure, and exit 3 is **never** a pass.
|
3. For every synced domain repo, run `tools/check-behaviors.sh {domain-path}`. One run per domain, and the runs go **in parallel** alongside the `lint-scripts.sh` runs — no domain's verdict depends on another's. It compares `references/behaviors.md` against `skills/`: section per skill, dictionary order, one table per section, five rows, no empty content cell. Route each exit code: 0 — that domain's behavior list matches; 1 — the mismatches are printed on stderr as `{檔案}:{技能名}:{說明}`, so report every one as a compliance failure with the skill it belongs to; 2 — usage error, the tool takes exactly one argument; 3 — nothing was checked, because `references/behaviors.md` is missing, `skills/` is missing, or no `SKILL.md` was found. Record exit 3 as 「無清單可查」with the cause from stderr and carry it into the step 3 merge; a domain with no behavior list is a compliance failure, and exit 3 is **never** a pass.
|
||||||
4. For every synced domain repo, run `tools/ste100-lint.sh {domain-path}`. One run per domain, and the runs go **in parallel** alongside the other group 1 runs. Route each exit code: 0 — every scanned file in that domain passes; 1 — the hits are printed on stdout as `{檔案}:{行號}:{類別}:{命中內容}`, so report every one as a compliance failure with the category it belongs to, after checking the two documented false-positive classes (a path or branch name holding a slash between Chinese characters, and English items listed with a slash); 2 — no scan target was given, which is a caller defect here, so fix the argument and rerun. The tool has no exit 3: an empty run returns 2 rather than a silent pass. This check lives in group 1 because the audit checklist demands 「`tools/ste100-lint.sh` 對該 domain 全綠」 for every domain — leaving it to the group 2 sub agents meant ten agents each ran it their own way, and the main agent never held one comparable verdict per domain.
|
4. For every synced domain repo, run `tools/ste100-lint.sh {domain-path}`. One run per domain, and the runs go **in parallel** alongside the other group 1 runs. Route each exit code: 0 — every scanned file in that domain passes; 1 — the hits are printed on stdout as `{檔案}:{行號}:{類別}:{命中內容}`, so report every one as a compliance failure with the category it belongs to, after checking the two documented false-positive classes (a path or branch name holding a slash between Chinese characters, and English items listed with a slash); 2 — no scan target was given, which is a caller defect here, so fix the argument and rerun. The tool has no exit 3: an empty run returns 2 rather than a silent pass. This check lives in group 1 because the audit checklist demands 「`tools/ste100-lint.sh` 對該 domain 全綠」 for every domain — leaving it to the group 2 sub agents meant ten agents each ran it their own way, and the main agent never held one comparable verdict per domain.
|
||||||
5. Run the two wiki-rule checkers once each, not per domain — both judge shared rules, so a second run adds nothing:
|
5. For every synced domain repo, run `tools/check-link-format.sh {domain-path}`. One run per domain, and the runs go **in parallel** alongside the other group 1 runs. It reads every `*.md` of that domain and reports any link still written in the double-bracket wiki-link form, which resolves only inside one wiki and dead-links everywhere else. Route each exit code: 0 — every link in that domain is written as `[{text}]({url})`; 1 — the hits are printed on stdout as `{檔案}:{行號}:{命中內容}`, so report every one as a compliance failure; 2 — usage error, the tool takes exactly one argument; 3 — nothing was scanned, because the domain path is missing or holds no `*.md`. Record exit 3 as 「無文件可掃」with the cause from stderr; it is **never** a pass. The tool strips inline code and fenced code blocks before judging, so a document that quotes the forbidden form while explaining it, and a shell test expression inside an example, both stay clean.
|
||||||
|
6. Run the two wiki-rule checkers once each, not per domain — both judge shared rules, so a second run adds nothing:
|
||||||
- `jsc-gitea/tools/check-wiki-rules.sh`, which verifies wiki repo resolution and the `hash-id` rule for every page type. It takes no argument. Route each exit code: 0 — printed `OK` on stdout, every item passed; 1 — the first mismatch is printed on stderr as `{項目}: want=… got=…` and the script stops there, so report that item and rerun after the fix, because the remaining items were never reached. Those are its only two codes. Until this audit, no flow in the whole repository ever called it.
|
- `jsc-gitea/tools/check-wiki-rules.sh`, which verifies wiki repo resolution and the `hash-id` rule for every page type. It takes no argument. Route each exit code: 0 — printed `OK` on stdout, every item passed; 1 — the first mismatch is printed on stderr as `{項目}: want=… got=…` and the script stops there, so report that item and rerun after the fix, because the remaining items were never reached. Those are its only two codes. Until this audit, no flow in the whole repository ever called it.
|
||||||
- `tools/check-page-name.sh {root}`, where `{root}` is the directory holding the domain repos — the parent directory of the paths `tools/sync-domains.sh` printed in step 1, so no extra derivation is needed. It compares the page-name pattern in its three copies: `jsc-gitea/tools/page-name.sh` (the canonical one), `jsc-hooks/hooks/comment-scope.sh` and `jsc-log/tools/worklog-pending.sh`. Route each exit code: 0 — the three agree; 1 — the mismatches are printed on stderr as `{檔案}:{說明}`, so report each one as a compliance failure, and a copy that could not be found is one of those lines; 2 — usage error, the tool takes exactly one argument; 3 — none of the three copies was found, so the root is wrong: fix it and rerun. Record exit 3 as 「什麼都沒查」; it is **never** a pass. The three copies stay separate on purpose — a hook must be self-contained and may not depend on another plugin's path at run time — so consistency is checked here instead of shared in a function.
|
- `tools/check-page-name.sh {root}`, where `{root}` is the directory holding the domain repos — the parent directory of the paths `tools/sync-domains.sh` printed in step 1, so no extra derivation is needed. It compares the page-name pattern in its three copies: `jsc-gitea/tools/page-name.sh` (the canonical one), `jsc-hooks/hooks/comment-scope.sh` and `jsc-log/tools/worklog-pending.sh`. Route each exit code: 0 — the three agree; 1 — the mismatches are printed on stderr as `{檔案}:{說明}`, so report each one as a compliance failure, and a copy that could not be found is one of those lines; 2 — usage error, the tool takes exactly one argument; 3 — none of the three copies was found, so the root is wrong: fix it and rerun. Record exit 3 as 「什麼都沒查」; it is **never** a pass. The three copies stay separate on purpose — a hook must be self-contained and may not depend on another plugin's path at run time — so consistency is checked here instead of shared in a function.
|
||||||
6. For every shell script directly named by a SKILL.md, confirm the skill routes every exit code the script's header declares. `lint-scripts.sh` proves the script exists and declares its codes; this check is the other half — that the caller branches on each of them. Report evidence as `skill file:line -> script path`.
|
7. For every shell script directly named by a SKILL.md, confirm the skill routes every exit code the script's header declares. `lint-scripts.sh` proves the script exists and declares its codes; this check is the other half — that the caller branches on each of them. Report evidence as `skill file:line -> script path`.
|
||||||
7. When the `jsc-hooks` domain is present, run `jsc-hooks/tools/wire-cli.sh smoke {cli}` for every CLI reported by `jsc-cli/tools/detect-clis.sh`; the per-CLI smokes run **in parallel**. When no CLI is detected, run `jsc-hooks/tools/wire-cli.sh smoke codex` as the minimum hook behavior check and label it 「預設 hook smoke」 in the report. Use `smoke`, not `purge` or rewiring actions, and set `JSC_READONLY=1` for the whole audit so a mistyped sub-command is refused in code (exit 6) instead of rewiring the machine; `status` and `smoke` are unaffected by that variable. Route each `smoke` exit code: 0 — the run passed its own assertions; 2 — usage error, so fix the CLI code and rerun; 4 — the smoke failed, which includes the script's own result-line count not matching what it expected. **Read the count from the script's `lines<TAB>{數量}` output line; never write the number into this skill.** The script counts its own result lines and asserts them, so a hardcoded number here goes stale the moment a hook or a decision path is added — an out-of-date count in a SKILL.md is exactly what misled the previous audit.
|
8. When the `jsc-hooks` domain is present, run `jsc-hooks/tools/wire-cli.sh smoke {cli}` for every CLI reported by `jsc-cli/tools/detect-clis.sh`; the per-CLI smokes run **in parallel**. When no CLI is detected, run `jsc-hooks/tools/wire-cli.sh smoke codex` as the minimum hook behavior check and label it 「預設 hook smoke」 in the report. Use `smoke`, not `purge` or rewiring actions, and set `JSC_READONLY=1` for the whole audit so a mistyped sub-command is refused in code (exit 6) instead of rewiring the machine; `status` and `smoke` are unaffected by that variable. Route each `smoke` exit code: 0 — the run passed its own assertions; 2 — usage error, so fix the CLI code and rerun; 4 — the smoke failed, which includes the script's own result-line count not matching what it expected. **Read the count from the script's `lines<TAB>{數量}` output line; never write the number into this skill.** The script counts its own result lines and asserts them, so a hardcoded number here goes stale the moment a hook or a decision path is added — an out-of-date count in a SKILL.md is exactly what misled the previous audit.
|
||||||
8. When a hook or script smoke fails, route it as a compliance failure with script name, exit code, output summary, and proposed fix. Do not continue to report the affected hook as compliant.
|
9. When a hook or script smoke fails, route it as a compliance failure with script name, exit code, output summary, and proposed fix. Do not continue to report the affected hook as compliant.
|
||||||
|
|
||||||
**Group 2 — audit every skill of every domain against the guidelines.md audit checklist.** This group MUST run as a sub agent, one sub agent per domain repo, and those sub agents run **in parallel**. Each sub agent reports its findings: skill, failed checklist item, evidence (file:line), proposed fix. Cover the checklist's four flow checks by name, not only the naming and language items:
|
**Group 2 — audit every skill of every domain against the guidelines.md audit checklist.** This group MUST run as a sub agent, one sub agent per domain repo, and those sub agents run **in parallel**. Each sub agent reports its findings: skill, failed checklist item, evidence (file:line), proposed fix. Cover the checklist's four flow checks by name, not only the naming and language items:
|
||||||
- Every step number, file path and section title the skill references — inside itself and in other files — really exists (the pointer points at something).
|
- Every step number, file path and section title the skill references — inside itself and in other files — really exists (the pointer points at something).
|
||||||
@@ -32,7 +33,7 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
- Every external call (script, API, other skill) states what to do on failure and routes every exit code.
|
- Every external call (script, API, other skill) states what to do on failure and routes every exit code.
|
||||||
- No gate the skill installs blocks the only path that lifts that gate.
|
- No gate the skill installs blocks the only path that lifts that gate.
|
||||||
|
|
||||||
Eight checklist items are **already decided by group 1** and must not be re-run here: `sh -n` on every `tools/` and `hooks/` script, script existence with the executable bit, the hook smoke, the `references/behaviors.md` match, the `lint-frontmatter.sh` verdict, the `ste100-lint.sh` verdict, the page-name-pattern verdict from `tools/check-page-name.sh`, and the wiki repo resolution plus `hash-id` verdict from `jsc-gitea/tools/check-wiki-rules.sh`. Tell each sub agent to skip those eight and leave them blank; the main agent fills them in from the group 1 verdicts when merging in step 3. The last two are **one verdict for the whole round**, not one per domain — group 1 runs each of those two checkers once, because both judge rules the domains share — so the merge writes that single verdict into every domain's checklist. Re-scanning the same files in every domain sub agent buys nothing — group 1 already scanned them all, with the same tools, on the same synced tree.
|
Nine checklist items are **already decided by group 1** and must not be re-run here: `sh -n` on every `tools/` and `hooks/` script, script existence with the executable bit, the hook smoke, the `references/behaviors.md` match, the `lint-frontmatter.sh` verdict, the `ste100-lint.sh` verdict, the link-format verdict from `tools/check-link-format.sh`, the page-name-pattern verdict from `tools/check-page-name.sh`, and the wiki repo resolution plus `hash-id` verdict from `jsc-gitea/tools/check-wiki-rules.sh`. Tell each sub agent to skip those nine and leave them blank; the main agent fills them in from the group 1 verdicts when merging in step 3. The link-checklist item has a second half no script can judge — that every link went through `jsc-gitea/tools/link-check.sh` before it was written — so each sub agent still audits that half from the skill text. The last two are **one verdict for the whole round**, not one per domain — group 1 runs each of those two checkers once, because both judge rules the domains share — so the merge writes that single verdict into every domain's checklist. Re-scanning the same files in every domain sub agent buys nothing — group 1 already scanned them all, with the same tools, on the same synced tree.
|
||||||
|
|
||||||
**Group 3 — a flow and cost optimization review**, kept separate from the compliance audit.
|
**Group 3 — a flow and cost optimization review**, kept separate from the compliance audit.
|
||||||
|
|
||||||
@@ -70,8 +71,8 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
|
|
||||||
Each optimization finding reports skill, aspect, evidence (file:line), current flow step count, proposed flow step count, what time or interaction it saves, what cost it saves, current cost driver, proposed cost driver, whether correctness decreases, which protection would be weakened if any, the **決議** (`套用`, `延後` or `自訂`) recorded in step 3, and the **決議日期** that decision was made. The last two fields start empty and are filled in by step 3; they are what step 8 writes to the wiki and what the next round reads back, so a finding that reaches step 8 with either field empty is unfinished, not optional. Cost savings may be token volume, sub-agent count, API calls, file scans, full-repo audits, or user prompts. Keep optimization findings separate from compliance failures.
|
Each optimization finding reports skill, aspect, evidence (file:line), current flow step count, proposed flow step count, what time or interaction it saves, what cost it saves, current cost driver, proposed cost driver, whether correctness decreases, which protection would be weakened if any, the **決議** (`套用`, `延後` or `自訂`) recorded in step 3, and the **決議日期** that decision was made. The last two fields start empty and are filled in by step 3; they are what step 8 writes to the wiki and what the next round reads back, so a finding that reaches step 8 with either field empty is unfinished, not optional. Cost savings may be token volume, sub-agent count, API calls, file scans, full-repo audits, or user prompts. Keep optimization findings separate from compliance failures.
|
||||||
|
|
||||||
Completion condition for all three groups: every domain has a `lint-scripts.sh` verdict, a `lint-frontmatter.sh` verdict, a `check-behaviors.sh` verdict and an `ste100-lint.sh` verdict, `check-wiki-rules.sh` and `check-page-name.sh` each have one verdict for the whole run, every script named by a SKILL.md has an exit-code-routing verdict, and every smoked CLI has a `smoke` exit code plus the `lines` value the script printed for it; every domain has a group 2 audit result that names a verdict for all checklist items — the four flow checks included, and the eight group 1 items left blank for the step 3 merge rather than re-scanned; and every one of the six aspects has returned a verdict for every domain whose settled list was read, 「無發現」 where an aspect found nothing and every settled entry of that domain excluded rather than re-reported — a domain whose pre-read failed carries 「本輪未取得已決議清單,優化建議暫不提出」 instead, and that sentence is a complete group 3 result for it.
|
Completion condition for all three groups: every domain has a `lint-scripts.sh` verdict, a `lint-frontmatter.sh` verdict, a `check-behaviors.sh` verdict, an `ste100-lint.sh` verdict and a `check-link-format.sh` verdict, `check-wiki-rules.sh` and `check-page-name.sh` each have one verdict for the whole run, every script named by a SKILL.md has an exit-code-routing verdict, and every smoked CLI has a `smoke` exit code plus the `lines` value the script printed for it; every domain has a group 2 audit result that names a verdict for all checklist items — the four flow checks included, and the nine group 1 items left blank for the step 3 merge rather than re-scanned; and every one of the six aspects has returned a verdict for every domain whose settled list was read, 「無發現」 where an aspect found nothing and every settled entry of that domain excluded rather than re-reported — a domain whose pre-read failed carries 「本輪未取得已決議清單,優化建議暫不提出」 instead, and that sentence is a complete group 3 result for it.
|
||||||
3. Merge the three groups, then present compliance failures and optimization findings separately via the `jsc-ask:ask` decision tree. Merging means one thing in code: fill the eight skipped checklist items of every group 2 sub agent report from the matching group 1 verdicts, so each domain ends with one complete checklist and no item counted twice. Six of the eight are per-domain verdicts, one domain to one item. The other two — `check-page-name.sh` and `check-wiki-rules.sh` — are judged **once for the whole round**, and that one verdict goes into that same item of **every** domain's checklist; re-judging a whole-round item per domain is precisely the double counting this merge exists to stop. A domain that group 3 marked 「本輪未取得已決議清單,優化建議暫不提出」 still gets its full compliance checklist here; only its optimization findings are missing, and the merge report says so.
|
3. Merge the three groups, then present compliance failures and optimization findings separately via the `jsc-ask:ask` decision tree. Merging means one thing in code: fill the nine skipped checklist items of every group 2 sub agent report from the matching group 1 verdicts, so each domain ends with one complete checklist and no item counted twice. Seven of the nine are per-domain verdicts, one domain to one item. The other two — `check-page-name.sh` and `check-wiki-rules.sh` — are judged **once for the whole round**, and that one verdict goes into that same item of **every** domain's checklist; re-judging a whole-round item per domain is precisely the double counting this merge exists to stop. A domain that group 3 marked 「本輪未取得已決議清單,優化建議暫不提出」 still gets its full compliance checklist here; only its optimization findings are missing, and the merge report says so.
|
||||||
- Compliance failure options: apply the proposed fix / skip / custom fix. Every option states its impact scope, for example skipping leaves the skill non-compliant until the next audit.
|
- Compliance failure options: apply the proposed fix / skip / custom fix. Every option states its impact scope, for example skipping leaves the skill non-compliant until the next audit.
|
||||||
- Optimization options: apply / defer / custom. Record the chosen option in the finding's 決議 field as `套用`, `延後` or `自訂`, and today's date in 決議日期. Any suggestion that weakens a protection must name the protection it removes and must not be applied unless the user explicitly accepts that tradeoff. Cost optimization may move, merge, cache, or narrow checks; it must not delete a compliance check only because it is expensive.
|
- Optimization options: apply / defer / custom. Record the chosen option in the finding's 決議 field as `套用`, `延後` or `自訂`, and today's date in 決議日期. Any suggestion that weakens a protection must name the protection it removes and must not be applied unless the user explicitly accepts that tradeoff. Cost optimization may move, merge, cache, or narrow checks; it must not delete a compliance check only because it is expensive.
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
- Exit 0 — every copy holds identical bytes; the script verifies that itself.
|
- Exit 0 — every copy holds identical bytes; the script verifies that itself.
|
||||||
|
|
||||||
Completion condition: the script exits 0 and prints the touched paths.
|
Completion condition: the script exits 0 and prints the touched paths.
|
||||||
6. Re-run the group 1 script, frontmatter, behavior-list, language, wiki-rule, page-name and hook validation, re-check the guidelines.md audit checklist for every touched skill, then re-run the optimization aspect that produced each accepted optimization. These three re-runs are as independent as the first pass, so run them **in parallel** and merge them the same way step 3 did. On any compliance failure, **return to step 3**: confirm and fix again, until all accepted compliance fixes pass. On an accepted optimization that does not produce the promised step reduction or cost reduction, or still weakens correctness beyond the recorded decision, return to step 3 for a new decision. Completion condition: `tools/lint-scripts.sh` exits 0 or 3 for every domain, `tools/lint-frontmatter.sh` exits 0 for every domain — exit 3 is 「什麼都沒掃」 and never counts as a pass — `tools/check-behaviors.sh` exits 0 for every domain, `tools/ste100-lint.sh` exits 0 for every domain, `jsc-gitea/tools/check-wiki-rules.sh` exits 0, `tools/check-page-name.sh` exits 0 — its exit 3 is 「什麼都沒查」 and never counts as a pass — every hook smoke exits 0 with the `lines` count the script itself asserted, every domain's checklist passes in full — the two whole-round verdicts filled into each domain from the one run that produced them — and every accepted optimization has a matching verification result.
|
6. Re-run the group 1 script, frontmatter, behavior-list, language, link-format, wiki-rule, page-name and hook validation, re-check the guidelines.md audit checklist for every touched skill, then re-run the optimization aspect that produced each accepted optimization. These three re-runs are as independent as the first pass, so run them **in parallel** and merge them the same way step 3 did. On any compliance failure, **return to step 3**: confirm and fix again, until all accepted compliance fixes pass. On an accepted optimization that does not produce the promised step reduction or cost reduction, or still weakens correctness beyond the recorded decision, return to step 3 for a new decision. Completion condition: `tools/lint-scripts.sh` exits 0 or 3 for every domain, `tools/lint-frontmatter.sh` exits 0 for every domain — exit 3 is 「什麼都沒掃」 and never counts as a pass — `tools/check-behaviors.sh` exits 0 for every domain, `tools/ste100-lint.sh` exits 0 for every domain, `tools/check-link-format.sh` exits 0 for every domain — its exit 3 is 「什麼都沒掃」 and never counts as a pass — `jsc-gitea/tools/check-wiki-rules.sh` exits 0, `tools/check-page-name.sh` exits 0 — its exit 3 is 「什麼都沒查」 and never counts as a pass — every hook smoke exits 0 with the `lines` count the script itself asserted, every domain's checklist passes in full — the two whole-round verdicts filled into each domain from the one run that produced them — and every accepted optimization has a matching verification result.
|
||||||
7. Call `jsc-git:pr` once per affected domain repo to open a Push Request. Completion condition: every affected repo has a PR URL, and all URLs are reported in one table with the format in [`../../references/pr-report.md`](../../references/pr-report.md).
|
7. Call `jsc-git:pr` once per affected domain repo to open a Push Request. Completion condition: every affected repo has a PR URL, and all URLs are reported in one table with the format in [`../../references/pr-report.md`](../../references/pr-report.md).
|
||||||
8. Write the round's result to the wiki. This step **MUST run as a sub agent**, one sub agent per affected domain repo, and those sub agents run **in parallel**: each domain writes its own page, and no page waits on another.
|
8. Write the round's result to the wiki. This step **MUST run as a sub agent**, one sub agent per affected domain repo, and those sub agents run **in parallel**: each domain writes its own page, and no page waits on another.
|
||||||
|
|
||||||
@@ -99,7 +100,8 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
|
|
||||||
The key column is `2`, the 存取庫 column, and the key is that domain repo's `{owner}/{repo}` written exactly as the row file writes it; the string is the same every round, so one domain keeps exactly one row. The script resolves the CONTENTS repo itself — the directory page lives there, never in the SKILLSET repo — reads the whole page, replaces the row whose key column matches, appends when none matches, and writes the page back, so every row owned by another domain stays as it was.
|
The key column is `2`, the 存取庫 column, and the key is that domain repo's `{owner}/{repo}` written exactly as the row file writes it; the string is the same every round, so one domain keeps exactly one row. The script resolves the CONTENTS repo itself — the directory page lives there, never in the SKILLSET repo — reads the whole page, replaces the row whose key column matches, appends when none matches, and writes the page back, so every row owned by another domain stays as it was.
|
||||||
|
|
||||||
The 異動頁 cell holds an **absolute** URL from `gitea.sh wiki-url {SKILLSET repo} SKILLSET_{HASH}`, because the two pages sit in different wikis and `[[SKILLSET_{HASH}]]` would resolve inside the directory page's own repo. Fetch that URL only after the content page is written: **write the content page first** — a directory row naming a page whose write failed is worse than a missing row.
|
The 異動頁 cell is written as `[SKILLSET_{HASH}]({url})`, the URL being the **absolute** one from `gitea.sh wiki-url {SKILLSET repo} SKILLSET_{HASH}`. Every link on both pages takes that `[{text}]({url})` form — the double-bracket wiki-link form is never used, because it resolves only inside one wiki. Fetch that URL only after the content page is written: **write the content page first** — a directory row naming a page whose write failed is worse than a missing row.
|
||||||
|
- **Check the links before writing.** Hand every URL going onto the content page and into the directory row to `jsc-gitea/tools/link-check.sh` and write only when it exits 0. It verifies through the Gitea API, never a web status code: a private repo answers 404 to an unauthenticated web request, so a status-code check would call a live page dead and rewrite pages that are fine.
|
||||||
- **Exit codes.** Route every one of them. None of these calls may be read as success by default.
|
- **Exit codes.** Route every one of them. None of these calls may be read as success by default.
|
||||||
|
|
||||||
| Call | Exit | Do |
|
| Call | Exit | Do |
|
||||||
@@ -113,6 +115,11 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
| | 7 or 8 | Stop and write nothing, because a page rebuilt on top of an unread read loses every section already on it |
|
| | 7 or 8 | Stop and write nothing, because a page rebuilt on top of an unread read loses every section already on it |
|
||||||
| `gitea.sh wiki-url` | 4 | The content page is not there, so the write above did **not** succeed. Go back and write it; put no directory row in until the page exists, because a row may not name a page that failed |
|
| `gitea.sh wiki-url` | 4 | The content page is not there, so the write above did **not** succeed. Go back and write it; put no directory row in until the page exists, because a row may not name a page that failed |
|
||||||
| | 5 | The API answered with no `html_url`. Stop and report it; never assemble the URL by hand from the host and the page name |
|
| | 5 | The API answered with no `html_url`. Stop and report it; never assemble the URL by hand from the host and the page name |
|
||||||
|
| `link-check.sh` | 0 | Every link is reachable. Write the page |
|
||||||
|
| | 1 | At least one link is dead. Write nothing, and report the `DEAD` lines it printed |
|
||||||
|
| | 2 | No URL was passed, which is a defect here. Pass the links and rerun |
|
||||||
|
| | 3 | `GITEA_HOST` is unset. Set it and rerun; never skip the check instead |
|
||||||
|
| | 7 | Gitea authentication failed. Stop and report the key problem, and never read it as a dead link |
|
||||||
| `wiki-contents.sh upsert` | 0 | The row is in place. Report the `updated` or `added` it printed, with the page it named |
|
| `wiki-contents.sh upsert` | 0 | The row is in place. Report the `updated` or `added` it printed, with the page it named |
|
||||||
| | 1 | The write failed, or the directory page holds no markdown table. Report `SKILLSET_CONTENTS` as not written, together with the row content |
|
| | 1 | The write failed, or the directory page holds no markdown table. Report `SKILLSET_CONTENTS` as not written, together with the row content |
|
||||||
| | 2 | An argument was rejected. Fix it and rerun; nothing was written |
|
| | 2 | An argument was rejected. Fix it and rerun; nothing was written |
|
||||||
|
|||||||
@@ -36,11 +36,12 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
On any mismatch — the deleted skill still listed, a leftover from exit 1, a fixed caller that now fails, a prompt failure, or unexpected stderr — fix the cause and rerun this step from 8.1. Completion condition: the skill is absent from the list, the verification script exits 0 or its exit 3 is reported as「無處可查」and carried into step 8.3, every fixed caller ran, every checkable CLI completed the prompt with the expected result, and every untestable CLI has a stated reason.
|
On any mismatch — the deleted skill still listed, a leftover from exit 1, a fixed caller that now fails, a prompt failure, or unexpected stderr — fix the cause and rerun this step from 8.1. Completion condition: the skill is absent from the list, the verification script exits 0 or its exit 3 is reported as「無處可查」and carried into step 8.3, every fixed caller ran, every checkable CLI completed the prompt with the expected result, and every untestable CLI has a stated reason.
|
||||||
3. Write the change report to the wiki — this part MUST run as a sub agent. It is two pages in two repos, and they must not be mixed up.
|
3. Write the change report to the wiki — this part MUST run as a sub agent. It is two pages in two repos, and they must not be mixed up.
|
||||||
- **Content page `SKILLSET_{HASH}`.** Resolve its repo with `jsc-gitea/tools/gitea.sh wiki-repo SKILLSET`, which reads `JSC_WIKI_REPO_SKILLSET` first, then `JSC_WIKI_REPO`. `{HASH}` is `gitea.sh hash-id "{owner}/{repo}"` of the domain repo that lost the skill, used at the full 40 characters it prints. Write it through `jsc-gitea:wiki` following [`../../templates/skillset-page.md`](../../templates/skillset-page.md): **append** a section for this change — date, 「刪除」, skill name, changed files (the step 5 inventory verdicts included), PR URL, the step 8.1 route verdict and the step 8.2 verification result per item, the deep-delete verdict「無處可查」included when it applies — and keep every earlier section.
|
- **Content page `SKILLSET_{HASH}`.** Resolve its repo with `jsc-gitea/tools/gitea.sh wiki-repo SKILLSET`, which reads `JSC_WIKI_REPO_SKILLSET` first, then `JSC_WIKI_REPO`. `{HASH}` is `gitea.sh hash-id "{owner}/{repo}"` of the domain repo that lost the skill, used at the full 40 characters it prints. Write it through `jsc-gitea:wiki` following [`../../templates/skillset-page.md`](../../templates/skillset-page.md): **append** a section for this change — date, 「刪除」, skill name, changed files (the step 5 inventory verdicts included), PR URL, the step 8.1 route verdict and the step 8.2 verification result per item, the deep-delete verdict「無處可查」included when it applies — and keep every earlier section.
|
||||||
- **Directory page `SKILLSET_CONTENTS`.** It lives in the CONTENTS repo, never in the SKILLSET one. `wiki-contents.sh` resolves it itself with `gitea.sh wiki-repo CONTENTS`, whose chain is `JSC_WIKI_REPO_CONTENTS` then `JSC_WIKI_REPO` and never falls back to `JSC_WIKI_REPO_SKILLSET`. Build one file holding the single row from [`../../templates/skillset-contents.md`](../../templates/skillset-contents.md), its 異動頁 cell carrying the **absolute** URL from `gitea.sh wiki-url {SKILLSET repo} SKILLSET_{HASH}` — `[[SKILLSET_{HASH}]]` resolves only inside the directory page's own wiki, so it would be a dead link. Then run:
|
- **Directory page `SKILLSET_CONTENTS`.** It lives in the CONTENTS repo, never in the SKILLSET one. `wiki-contents.sh` resolves it itself with `gitea.sh wiki-repo CONTENTS`, whose chain is `JSC_WIKI_REPO_CONTENTS` then `JSC_WIKI_REPO` and never falls back to `JSC_WIKI_REPO_SKILLSET`. Build one file holding the single row from [`../../templates/skillset-contents.md`](../../templates/skillset-contents.md), its 異動頁 cell written as `[SKILLSET_{HASH}]({url})` with the **absolute** URL from `gitea.sh wiki-url {SKILLSET repo} SKILLSET_{HASH}`. Every link on both pages takes that `[{text}]({url})` form; the double-bracket wiki-link form resolves only inside one wiki, so it is never used. Then run:
|
||||||
|
|
||||||
`jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}" {row file} templates/skillset-contents.md`
|
`jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}" {row file} templates/skillset-contents.md`
|
||||||
|
|
||||||
The key column is `2`, the 存取庫 column, holding that repo's `{owner}/{repo}` exactly as the row file writes it, so one domain keeps exactly one row and no other domain's row moves. Never hand-edit the directory page. Write the content page first and fetch the URL only after it exists.
|
The key column is `2`, the 存取庫 column, holding that repo's `{owner}/{repo}` exactly as the row file writes it, so one domain keeps exactly one row and no other domain's row moves. Never hand-edit the directory page. Write the content page first and fetch the URL only after it exists.
|
||||||
|
- **Check the links before writing.** Hand every URL going onto the content page and into the directory row to `jsc-gitea/tools/link-check.sh`, and write only when it exits 0. It verifies through the Gitea API, never a web status code: a private repo answers 404 to an unauthenticated web request, so a status-code check would call a live page dead.
|
||||||
- **Exit codes.** Route every one of them:
|
- **Exit codes.** Route every one of them:
|
||||||
|
|
||||||
| Call | Exit | Do |
|
| Call | Exit | Do |
|
||||||
@@ -54,6 +55,11 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
| | 7 or 8 | Stop and write nothing: a page rebuilt on top of an unread read loses every section already on it |
|
| | 7 or 8 | Stop and write nothing: a page rebuilt on top of an unread read loses every section already on it |
|
||||||
| `gitea.sh wiki-url` | 4 | The content page is not there, so the write above did **not** succeed. Go back and write it, and add no directory row until the page exists |
|
| `gitea.sh wiki-url` | 4 | The content page is not there, so the write above did **not** succeed. Go back and write it, and add no directory row until the page exists |
|
||||||
| | 5 | The API answered with no `html_url`. Stop and report it; never assemble the URL by hand from the host and the page name |
|
| | 5 | The API answered with no `html_url`. Stop and report it; never assemble the URL by hand from the host and the page name |
|
||||||
|
| `link-check.sh` | 0 | Every link is reachable. Write the page |
|
||||||
|
| | 1 | At least one link is dead. Write nothing, and report the `DEAD` lines it printed |
|
||||||
|
| | 2 | No URL was passed, which is a defect here. Pass the links and rerun |
|
||||||
|
| | 3 | `GITEA_HOST` is unset. Set it and rerun; never skip the check instead |
|
||||||
|
| | 7 | Gitea authentication failed. Stop and report the key problem, and never read it as a dead link |
|
||||||
| `wiki-contents.sh upsert` | 0 | The row is in place. Report the `updated` or `added` it printed |
|
| `wiki-contents.sh upsert` | 0 | The row is in place. Report the `updated` or `added` it printed |
|
||||||
| | 1 | The write failed. Report `SKILLSET_CONTENTS` as not written, together with the row content |
|
| | 1 | The write failed. Report `SKILLSET_CONTENTS` as not written, together with the row content |
|
||||||
| | 2 | An argument was rejected. Fix it and rerun; nothing was written |
|
| | 2 | An argument was rejected. Fix it and rerun; nothing was written |
|
||||||
|
|||||||
@@ -45,11 +45,12 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
1. Follow [`../../references/deploy-verify.md`](../../references/deploy-verify.md) from section 1 to section 5: `tools/deploy-route.sh {domain-path}` picks the route, the deploy route or the worktree route runs, and the verification then runs in a **fresh CLI process**, never in the session that ran the deploy. That session raised the restart gate itself and still holds the old skill body, so verifying inside it either gets blocked or passes on stale behavior. Verify the added skill's row in `tools/list-skills.sh`, every tool the skill added, and one minimal prompt per checkable CLI — the per-CLI prompts run in parallel. Completion condition: every completion condition in `deploy-verify.md` sections 1 to 5 holds for this domain repo.
|
1. Follow [`../../references/deploy-verify.md`](../../references/deploy-verify.md) from section 1 to section 5: `tools/deploy-route.sh {domain-path}` picks the route, the deploy route or the worktree route runs, and the verification then runs in a **fresh CLI process**, never in the session that ran the deploy. That session raised the restart gate itself and still holds the old skill body, so verifying inside it either gets blocked or passes on stale behavior. Verify the added skill's row in `tools/list-skills.sh`, every tool the skill added, and one minimal prompt per checkable CLI — the per-CLI prompts run in parallel. Completion condition: every completion condition in `deploy-verify.md` sections 1 to 5 holds for this domain repo.
|
||||||
2. Write the change report to the wiki — this part MUST run as a sub agent. It is two pages in two repos, and they must not be mixed up.
|
2. Write the change report to the wiki — this part MUST run as a sub agent. It is two pages in two repos, and they must not be mixed up.
|
||||||
- **Content page `SKILLSET_{HASH}`.** Resolve its repo with `jsc-gitea/tools/gitea.sh wiki-repo SKILLSET`, which reads `JSC_WIKI_REPO_SKILLSET` first, then `JSC_WIKI_REPO`. `{HASH}` is `gitea.sh hash-id "{owner}/{repo}"` of the domain repo that gained the skill, used at the full 40 characters it prints. Write it through `jsc-gitea:wiki` following [`../../templates/skillset-page.md`](../../templates/skillset-page.md): **append** a section for this change — date, 「新增」, skill name, changed files, PR URL, the step 6.1 route verdict and verification result per item — and keep every earlier section.
|
- **Content page `SKILLSET_{HASH}`.** Resolve its repo with `jsc-gitea/tools/gitea.sh wiki-repo SKILLSET`, which reads `JSC_WIKI_REPO_SKILLSET` first, then `JSC_WIKI_REPO`. `{HASH}` is `gitea.sh hash-id "{owner}/{repo}"` of the domain repo that gained the skill, used at the full 40 characters it prints. Write it through `jsc-gitea:wiki` following [`../../templates/skillset-page.md`](../../templates/skillset-page.md): **append** a section for this change — date, 「新增」, skill name, changed files, PR URL, the step 6.1 route verdict and verification result per item — and keep every earlier section.
|
||||||
- **Directory page `SKILLSET_CONTENTS`.** It lives in the CONTENTS repo, never in the SKILLSET one. `wiki-contents.sh` resolves it itself with `gitea.sh wiki-repo CONTENTS`, whose chain is `JSC_WIKI_REPO_CONTENTS` then `JSC_WIKI_REPO` and never falls back to `JSC_WIKI_REPO_SKILLSET`. Build one file holding the single row from [`../../templates/skillset-contents.md`](../../templates/skillset-contents.md), its 異動頁 cell carrying the **absolute** URL from `gitea.sh wiki-url {SKILLSET repo} SKILLSET_{HASH}` — `[[SKILLSET_{HASH}]]` resolves only inside the directory page's own wiki, so it would be a dead link. Then run:
|
- **Directory page `SKILLSET_CONTENTS`.** It lives in the CONTENTS repo, never in the SKILLSET one. `wiki-contents.sh` resolves it itself with `gitea.sh wiki-repo CONTENTS`, whose chain is `JSC_WIKI_REPO_CONTENTS` then `JSC_WIKI_REPO` and never falls back to `JSC_WIKI_REPO_SKILLSET`. Build one file holding the single row from [`../../templates/skillset-contents.md`](../../templates/skillset-contents.md), its 異動頁 cell written as `[SKILLSET_{HASH}]({url})` with the **absolute** URL from `gitea.sh wiki-url {SKILLSET repo} SKILLSET_{HASH}`. Every link on both pages takes that `[{text}]({url})` form; the double-bracket wiki-link form resolves only inside one wiki, so it is never used. Then run:
|
||||||
|
|
||||||
`jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}" {row file} templates/skillset-contents.md`
|
`jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}" {row file} templates/skillset-contents.md`
|
||||||
|
|
||||||
The key column is `2`, the 存取庫 column, holding that repo's `{owner}/{repo}` exactly as the row file writes it, so one domain keeps exactly one row and no other domain's row moves. Never hand-edit the directory page. Write the content page first and fetch the URL only after it exists.
|
The key column is `2`, the 存取庫 column, holding that repo's `{owner}/{repo}` exactly as the row file writes it, so one domain keeps exactly one row and no other domain's row moves. Never hand-edit the directory page. Write the content page first and fetch the URL only after it exists.
|
||||||
|
- **Check the links before writing.** Hand every URL going onto the content page and into the directory row to `jsc-gitea/tools/link-check.sh`, and write only when it exits 0. It verifies through the Gitea API, never a web status code: a private repo answers 404 to an unauthenticated web request, so a status-code check would call a live page dead.
|
||||||
- **Exit codes.** Route every one of them:
|
- **Exit codes.** Route every one of them:
|
||||||
|
|
||||||
| Call | Exit | Do |
|
| Call | Exit | Do |
|
||||||
@@ -63,6 +64,11 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
| | 7 or 8 | Stop and write nothing: a page rebuilt on top of an unread read loses every section already on it |
|
| | 7 or 8 | Stop and write nothing: a page rebuilt on top of an unread read loses every section already on it |
|
||||||
| `gitea.sh wiki-url` | 4 | The content page is not there, so the write above did **not** succeed. Go back and write it, and add no directory row until the page exists |
|
| `gitea.sh wiki-url` | 4 | The content page is not there, so the write above did **not** succeed. Go back and write it, and add no directory row until the page exists |
|
||||||
| | 5 | The API answered with no `html_url`. Stop and report it; never assemble the URL by hand from the host and the page name |
|
| | 5 | The API answered with no `html_url`. Stop and report it; never assemble the URL by hand from the host and the page name |
|
||||||
|
| `link-check.sh` | 0 | Every link is reachable. Write the page |
|
||||||
|
| | 1 | At least one link is dead. Write nothing, and report the `DEAD` lines it printed |
|
||||||
|
| | 2 | No URL was passed, which is a defect here. Pass the links and rerun |
|
||||||
|
| | 3 | `GITEA_HOST` is unset. Set it and rerun; never skip the check instead |
|
||||||
|
| | 7 | Gitea authentication failed. Stop and report the key problem, and never read it as a dead link |
|
||||||
| `wiki-contents.sh upsert` | 0 | The row is in place. Report the `updated` or `added` it printed |
|
| `wiki-contents.sh upsert` | 0 | The row is in place. Report the `updated` or `added` it printed |
|
||||||
| | 1 | The write failed. Report `SKILLSET_CONTENTS` as not written, together with the row content |
|
| | 1 | The write failed. Report `SKILLSET_CONTENTS` as not written, together with the row content |
|
||||||
| | 2 | An argument was rejected. Fix it and rerun; nothing was written |
|
| | 2 | An argument was rejected. Fix it and rerun; nothing was written |
|
||||||
|
|||||||
@@ -20,11 +20,12 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
1. Follow [`../../references/deploy-verify.md`](../../references/deploy-verify.md) from section 1 to section 5: `tools/deploy-route.sh {domain-path}` picks the route, the deploy route or the worktree route runs, and the verification then runs in a **fresh CLI process**, never in the session that ran the deploy. That session raised the restart gate itself and still holds the old skill body, so verifying inside it either gets blocked or passes on stale behavior. Verify the updated `description` in the skill's `tools/list-skills.sh` row, every tool this change touched, and one minimal prompt per checkable CLI — the per-CLI prompts run in parallel. Completion condition: every completion condition in `deploy-verify.md` sections 1 to 5 holds for this domain repo.
|
1. Follow [`../../references/deploy-verify.md`](../../references/deploy-verify.md) from section 1 to section 5: `tools/deploy-route.sh {domain-path}` picks the route, the deploy route or the worktree route runs, and the verification then runs in a **fresh CLI process**, never in the session that ran the deploy. That session raised the restart gate itself and still holds the old skill body, so verifying inside it either gets blocked or passes on stale behavior. Verify the updated `description` in the skill's `tools/list-skills.sh` row, every tool this change touched, and one minimal prompt per checkable CLI — the per-CLI prompts run in parallel. Completion condition: every completion condition in `deploy-verify.md` sections 1 to 5 holds for this domain repo.
|
||||||
2. Write the change report to the wiki — this part MUST run as a sub agent. It is two pages in two repos, and they must not be mixed up.
|
2. Write the change report to the wiki — this part MUST run as a sub agent. It is two pages in two repos, and they must not be mixed up.
|
||||||
- **Content page `SKILLSET_{HASH}`.** Resolve its repo with `jsc-gitea/tools/gitea.sh wiki-repo SKILLSET`, which reads `JSC_WIKI_REPO_SKILLSET` first, then `JSC_WIKI_REPO`. `{HASH}` is `gitea.sh hash-id "{owner}/{repo}"` of the changed domain repo, used at the full 40 characters it prints. Write it through `jsc-gitea:wiki` following [`../../templates/skillset-page.md`](../../templates/skillset-page.md): **append** a section for this change — date, 「更新」, skill name, changed files, PR URL, the step 8.1 route verdict and verification result per item — and keep every earlier section.
|
- **Content page `SKILLSET_{HASH}`.** Resolve its repo with `jsc-gitea/tools/gitea.sh wiki-repo SKILLSET`, which reads `JSC_WIKI_REPO_SKILLSET` first, then `JSC_WIKI_REPO`. `{HASH}` is `gitea.sh hash-id "{owner}/{repo}"` of the changed domain repo, used at the full 40 characters it prints. Write it through `jsc-gitea:wiki` following [`../../templates/skillset-page.md`](../../templates/skillset-page.md): **append** a section for this change — date, 「更新」, skill name, changed files, PR URL, the step 8.1 route verdict and verification result per item — and keep every earlier section.
|
||||||
- **Directory page `SKILLSET_CONTENTS`.** It lives in the CONTENTS repo, never in the SKILLSET one. `wiki-contents.sh` resolves it itself with `gitea.sh wiki-repo CONTENTS`, whose chain is `JSC_WIKI_REPO_CONTENTS` then `JSC_WIKI_REPO` and never falls back to `JSC_WIKI_REPO_SKILLSET`. Build one file holding the single row from [`../../templates/skillset-contents.md`](../../templates/skillset-contents.md), its 異動頁 cell carrying the **absolute** URL from `gitea.sh wiki-url {SKILLSET repo} SKILLSET_{HASH}` — `[[SKILLSET_{HASH}]]` resolves only inside the directory page's own wiki, so it would be a dead link. Then run:
|
- **Directory page `SKILLSET_CONTENTS`.** It lives in the CONTENTS repo, never in the SKILLSET one. `wiki-contents.sh` resolves it itself with `gitea.sh wiki-repo CONTENTS`, whose chain is `JSC_WIKI_REPO_CONTENTS` then `JSC_WIKI_REPO` and never falls back to `JSC_WIKI_REPO_SKILLSET`. Build one file holding the single row from [`../../templates/skillset-contents.md`](../../templates/skillset-contents.md), its 異動頁 cell written as `[SKILLSET_{HASH}]({url})` with the **absolute** URL from `gitea.sh wiki-url {SKILLSET repo} SKILLSET_{HASH}`. Every link on both pages takes that `[{text}]({url})` form; the double-bracket wiki-link form resolves only inside one wiki, so it is never used. Then run:
|
||||||
|
|
||||||
`jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}" {row file} templates/skillset-contents.md`
|
`jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}" {row file} templates/skillset-contents.md`
|
||||||
|
|
||||||
The key column is `2`, the 存取庫 column, holding that repo's `{owner}/{repo}` exactly as the row file writes it, so one domain keeps exactly one row and no other domain's row moves. Never hand-edit the directory page. Write the content page first and fetch the URL only after it exists.
|
The key column is `2`, the 存取庫 column, holding that repo's `{owner}/{repo}` exactly as the row file writes it, so one domain keeps exactly one row and no other domain's row moves. Never hand-edit the directory page. Write the content page first and fetch the URL only after it exists.
|
||||||
|
- **Check the links before writing.** Hand every URL going onto the content page and into the directory row to `jsc-gitea/tools/link-check.sh`, and write only when it exits 0. It verifies through the Gitea API, never a web status code: a private repo answers 404 to an unauthenticated web request, so a status-code check would call a live page dead.
|
||||||
- **Exit codes.** Route every one of them:
|
- **Exit codes.** Route every one of them:
|
||||||
|
|
||||||
| Call | Exit | Do |
|
| Call | Exit | Do |
|
||||||
@@ -38,6 +39,11 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
| | 7 or 8 | Stop and write nothing: a page rebuilt on top of an unread read loses every section already on it |
|
| | 7 or 8 | Stop and write nothing: a page rebuilt on top of an unread read loses every section already on it |
|
||||||
| `gitea.sh wiki-url` | 4 | The content page is not there, so the write above did **not** succeed. Go back and write it, and add no directory row until the page exists |
|
| `gitea.sh wiki-url` | 4 | The content page is not there, so the write above did **not** succeed. Go back and write it, and add no directory row until the page exists |
|
||||||
| | 5 | The API answered with no `html_url`. Stop and report it; never assemble the URL by hand from the host and the page name |
|
| | 5 | The API answered with no `html_url`. Stop and report it; never assemble the URL by hand from the host and the page name |
|
||||||
|
| `link-check.sh` | 0 | Every link is reachable. Write the page |
|
||||||
|
| | 1 | At least one link is dead. Write nothing, and report the `DEAD` lines it printed |
|
||||||
|
| | 2 | No URL was passed, which is a defect here. Pass the links and rerun |
|
||||||
|
| | 3 | `GITEA_HOST` is unset. Set it and rerun; never skip the check instead |
|
||||||
|
| | 7 | Gitea authentication failed. Stop and report the key problem, and never read it as a dead link |
|
||||||
| `wiki-contents.sh upsert` | 0 | The row is in place. Report the `updated` or `added` it printed |
|
| `wiki-contents.sh upsert` | 0 | The row is in place. Report the `updated` or `added` it printed |
|
||||||
| | 1 | The write failed. Report `SKILLSET_CONTENTS` as not written, together with the row content |
|
| | 1 | The write failed. Report `SKILLSET_CONTENTS` as not written, together with the row content |
|
||||||
| | 2 | An argument was rejected. Fix it and rerun; nothing was written |
|
| | 2 | An argument was rejected. Fix it and rerun; nothing was written |
|
||||||
|
|||||||
@@ -21,11 +21,12 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
1. Follow [`../../references/deploy-verify.md`](../../references/deploy-verify.md) from section 1 to section 5, once per affected domain repo — the route judgements run in parallel. The batch takes the deploy route only when **every** affected repo's `tools/deploy-route.sh` exits 0; a single exit 3 puts the whole batch on the worktree route, because the change reaches the CLIs only when the last repo merges, so name every outstanding release PR. The verification then runs in a **fresh CLI process**, never in the session that ran the deploy: that session raised the restart gate itself and still holds the old skill bodies. Verify every touched skill's row in `tools/list-skills.sh`, every tool this change touched, and one minimal prompt per affected domain per checkable CLI — the per-CLI and per-domain prompts run in parallel. Completion condition: every completion condition in `deploy-verify.md` sections 1 to 5 holds for every affected domain repo.
|
1. Follow [`../../references/deploy-verify.md`](../../references/deploy-verify.md) from section 1 to section 5, once per affected domain repo — the route judgements run in parallel. The batch takes the deploy route only when **every** affected repo's `tools/deploy-route.sh` exits 0; a single exit 3 puts the whole batch on the worktree route, because the change reaches the CLIs only when the last repo merges, so name every outstanding release PR. The verification then runs in a **fresh CLI process**, never in the session that ran the deploy: that session raised the restart gate itself and still holds the old skill bodies. Verify every touched skill's row in `tools/list-skills.sh`, every tool this change touched, and one minimal prompt per affected domain per checkable CLI — the per-CLI and per-domain prompts run in parallel. Completion condition: every completion condition in `deploy-verify.md` sections 1 to 5 holds for every affected domain repo.
|
||||||
2. Write the change report to the wiki — this part MUST run as a sub agent, one sub agent per affected domain repo, run in parallel. Each sub agent writes two pages in two repos, and they must not be mixed up.
|
2. Write the change report to the wiki — this part MUST run as a sub agent, one sub agent per affected domain repo, run in parallel. Each sub agent writes two pages in two repos, and they must not be mixed up.
|
||||||
- **Content page `SKILLSET_{HASH}`.** Resolve its repo with `jsc-gitea/tools/gitea.sh wiki-repo SKILLSET`, which reads `JSC_WIKI_REPO_SKILLSET` first, then `JSC_WIKI_REPO`. `{HASH}` is `gitea.sh hash-id "{owner}/{repo}"` of that repo, used at the full 40 characters it prints. Write it through `jsc-gitea:wiki` following [`../../templates/skillset-page.md`](../../templates/skillset-page.md): **append** a section for this change — date, 「批次更新」, the change request in one line, touched skills, changed files, PR URL, the step 5.1 route verdict and verification result per item — and keep every earlier section.
|
- **Content page `SKILLSET_{HASH}`.** Resolve its repo with `jsc-gitea/tools/gitea.sh wiki-repo SKILLSET`, which reads `JSC_WIKI_REPO_SKILLSET` first, then `JSC_WIKI_REPO`. `{HASH}` is `gitea.sh hash-id "{owner}/{repo}"` of that repo, used at the full 40 characters it prints. Write it through `jsc-gitea:wiki` following [`../../templates/skillset-page.md`](../../templates/skillset-page.md): **append** a section for this change — date, 「批次更新」, the change request in one line, touched skills, changed files, PR URL, the step 5.1 route verdict and verification result per item — and keep every earlier section.
|
||||||
- **Directory page `SKILLSET_CONTENTS`.** One shared page holds every domain's row, so each sub agent writes only its own. It lives in the CONTENTS repo, never in the SKILLSET one: `wiki-contents.sh` resolves it itself with `gitea.sh wiki-repo CONTENTS`, whose chain is `JSC_WIKI_REPO_CONTENTS` then `JSC_WIKI_REPO` and never falls back to `JSC_WIKI_REPO_SKILLSET`. Build one file holding the single row from [`../../templates/skillset-contents.md`](../../templates/skillset-contents.md), its 異動頁 cell carrying the **absolute** URL from `gitea.sh wiki-url {SKILLSET repo} SKILLSET_{HASH}` — `[[SKILLSET_{HASH}]]` resolves only inside the directory page's own wiki, so it would be a dead link. Then run:
|
- **Directory page `SKILLSET_CONTENTS`.** One shared page holds every domain's row, so each sub agent writes only its own. It lives in the CONTENTS repo, never in the SKILLSET one: `wiki-contents.sh` resolves it itself with `gitea.sh wiki-repo CONTENTS`, whose chain is `JSC_WIKI_REPO_CONTENTS` then `JSC_WIKI_REPO` and never falls back to `JSC_WIKI_REPO_SKILLSET`. Build one file holding the single row from [`../../templates/skillset-contents.md`](../../templates/skillset-contents.md), its 異動頁 cell written as `[SKILLSET_{HASH}]({url})` with the **absolute** URL from `gitea.sh wiki-url {SKILLSET repo} SKILLSET_{HASH}`. Every link on both pages takes that `[{text}]({url})` form; the double-bracket wiki-link form resolves only inside one wiki, so it is never used. Then run:
|
||||||
|
|
||||||
`jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}" {row file} templates/skillset-contents.md`
|
`jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}" {row file} templates/skillset-contents.md`
|
||||||
|
|
||||||
The key column is `2`, the 存取庫 column, holding that repo's `{owner}/{repo}` exactly as the row file writes it, so one domain keeps exactly one row and no sibling sub agent's row moves. Never hand-edit the directory page, and never overwrite it as a whole. Write the content page first and fetch the URL only after it exists.
|
The key column is `2`, the 存取庫 column, holding that repo's `{owner}/{repo}` exactly as the row file writes it, so one domain keeps exactly one row and no sibling sub agent's row moves. Never hand-edit the directory page, and never overwrite it as a whole. Write the content page first and fetch the URL only after it exists.
|
||||||
|
- **Check the links before writing.** Hand every URL going onto the content page and into the directory row to `jsc-gitea/tools/link-check.sh`, and write only when it exits 0. It verifies through the Gitea API, never a web status code: a private repo answers 404 to an unauthenticated web request, so a status-code check would call a live page dead.
|
||||||
- **Exit codes.** Route every one of them:
|
- **Exit codes.** Route every one of them:
|
||||||
|
|
||||||
| Call | Exit | Do |
|
| Call | Exit | Do |
|
||||||
@@ -39,6 +40,11 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
|||||||
| | 7 or 8 | Stop and write nothing: a page rebuilt on top of an unread read loses every section already on it |
|
| | 7 or 8 | Stop and write nothing: a page rebuilt on top of an unread read loses every section already on it |
|
||||||
| `gitea.sh wiki-url` | 4 | The content page is not there, so the write above did **not** succeed. Go back and write it, and add no directory row until the page exists |
|
| `gitea.sh wiki-url` | 4 | The content page is not there, so the write above did **not** succeed. Go back and write it, and add no directory row until the page exists |
|
||||||
| | 5 | The API answered with no `html_url`. Stop and report it; never assemble the URL by hand from the host and the page name |
|
| | 5 | The API answered with no `html_url`. Stop and report it; never assemble the URL by hand from the host and the page name |
|
||||||
|
| `link-check.sh` | 0 | Every link is reachable. Write the page |
|
||||||
|
| | 1 | At least one link is dead. Write nothing, and report the `DEAD` lines it printed |
|
||||||
|
| | 2 | No URL was passed, which is a defect here. Pass the links and rerun |
|
||||||
|
| | 3 | `GITEA_HOST` is unset. Set it and rerun; never skip the check instead |
|
||||||
|
| | 7 | Gitea authentication failed. Stop and report the key problem, and never read it as a dead link |
|
||||||
| `wiki-contents.sh upsert` | 0 | The row is in place. Report the `updated` or `added` it printed |
|
| `wiki-contents.sh upsert` | 0 | The row is in place. Report the `updated` or `added` it printed |
|
||||||
| | 1 | The write failed. Report `SKILLSET_CONTENTS` as not written, together with the row content |
|
| | 1 | The write failed. Report `SKILLSET_CONTENTS` as not written, together with the row content |
|
||||||
| | 2 | An argument was rejected. Fix it and rerun; nothing was written |
|
| | 2 | An argument was rejected. Fix it and rerun; nothing was written |
|
||||||
|
|||||||
@@ -6,26 +6,29 @@
|
|||||||
> 寫入一律用 `jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}" {列檔} templates/skillset-contents.md`:`<TYPE>` 填 `SKILLSET`,鍵欄填數字 `2`,也就是「存取庫」那一欄。
|
> 寫入一律用 `jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}" {列檔} templates/skillset-contents.md`:`<TYPE>` 填 `SKILLSET`,鍵欄填數字 `2`,也就是「存取庫」那一欄。
|
||||||
> 它讀回整頁、換掉鍵欄相符的那一列、找不到才附加,最後整頁寫回。不得手工改目錄頁。
|
> 它讀回整頁、換掉鍵欄相符的那一列、找不到才附加,最後整頁寫回。不得手工改目錄頁。
|
||||||
> `SKILLSET_{HASH}` 的 `{HASH}` 交給 `jsc-gitea/tools/hash-id` 產生,雜湊來源見 `jsc-meta/references/guidelines.md` 的「Wiki 頁命名總表」。
|
> `SKILLSET_{HASH}` 的 `{HASH}` 交給 `jsc-gitea/tools/hash-id` 產生,雜湊來源見 `jsc-meta/references/guidelines.md` 的「Wiki 頁命名總表」。
|
||||||
|
> 連結寫法:所有連結一律 `[{文字}]({連結})`,網址放 `jsc-gitea/tools/gitea.sh wiki-url` 印出的絕對網址,不用 `[[...]]`。寫入前先把每個連結交給 `jsc-gitea/tools/link-check.sh` 驗證,結束碼 0 才寫入;驗證走 API,不看網頁狀態碼。
|
||||||
|
|
||||||
| 異動頁 | 存取庫 | 最近異動 | 異動次數 | 最後更新 |
|
| 異動頁 | 存取庫 | 最近異動 | 異動次數 | 最後更新 |
|
||||||
| --- | --- | --- | ---: | --- |
|
| --- | --- | --- | ---: | --- |
|
||||||
| [SKILLSET_{HASH}]({GITEA_HOST}/{owner}/{repo}/wiki/SKILLSET_{HASH}) | {owner}/{repo} | {一句話寫這一次改了什麼} | {n} | {yyyy-MM-dd HH:mm} |
|
| [SKILLSET_{HASH}]({wiki-url 印出的絕對網址}) | {owner}/{repo} | {一句話寫這一次改了什麼} | {n} | {yyyy-MM-dd HH:mm} |
|
||||||
|
|
||||||
## 欄位說明
|
## 欄位說明
|
||||||
|
|
||||||
| 欄位 | 內容 |
|
| 欄位 | 內容 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 異動頁 | 指向 `SKILLSET_{HASH}` 的**絕對網址**,格式 `{GITEA_HOST}/{owner}/{repo}/wiki/SKILLSET_{HASH}`。`{owner}/{repo}` 是內容頁那一個存取庫 |
|
| 異動頁 | `[SKILLSET_{HASH}]({連結})`,連結是 `gitea.sh wiki-url` 印出的絕對網址。`{owner}/{repo}` 是內容頁那一個存取庫 |
|
||||||
| 存取庫 | 被改動的 domain 存取庫 `{owner}/{repo}`,也就是這一頁的雜湊來源 |
|
| 存取庫 | 被改動的 domain 存取庫 `{owner}/{repo}`,也就是這一頁的雜湊來源 |
|
||||||
| 最近異動 | 最後一次異動的一句話摘要,與內容頁最新一節的「異動需求」同一句 |
|
| 最近異動 | 最後一次異動的一句話摘要,與內容頁最新一節的「異動需求」同一句 |
|
||||||
| 異動次數 | 該內容頁累積的節數。內容頁只附加不覆蓋,所以這個數字只會往上加 |
|
| 異動次數 | 該內容頁累積的節數。內容頁只附加不覆蓋,所以這個數字只會往上加 |
|
||||||
| 最後更新 | 最後一次寫入內容頁的時間,與那一節的日期一致 |
|
| 最後更新 | 最後一次寫入內容頁的時間,與那一節的日期一致 |
|
||||||
|
|
||||||
## 為什麼連結要用絕對網址
|
## 為什麼連結要用絕對網址,還要先驗證
|
||||||
|
|
||||||
目錄頁與內容頁分屬不同存取庫。`[[SKILLSET_{HASH}]]` 這種同 wiki 連結解到的是目錄頁自己那個存取庫,那裡沒有這一頁,點下去是 404。
|
目錄頁與內容頁分屬不同存取庫。同 wiki 連結解到的是目錄頁自己那個存取庫,那裡沒有這一頁,點下去是 404。
|
||||||
更麻煩的是它看起來像「頁沒寫成功」,實際上頁好好的,只是連結指錯地方,查的人會回去重寫一次已經寫好的頁。
|
更麻煩的是它看起來像「頁沒寫成功」,實際上頁好好的,只是連結指錯地方,查的人會回去重寫一次已經寫好的頁。
|
||||||
|
|
||||||
|
驗證則走 API,不看網頁狀態碼。私有存取庫的網頁網址對未登入請求一律回 404,拿狀態碼判斷會把還在的頁判成死連結,接著被刪掉或改寫。
|
||||||
|
|
||||||
## 寫入規則
|
## 寫入規則
|
||||||
|
|
||||||
- 一律走 `jsc-gitea/tools/wiki-contents.sh upsert`,鍵欄是第 2 欄「存取庫」,鍵值是 `{owner}/{repo}`。
|
- 一律走 `jsc-gitea/tools/wiki-contents.sh upsert`,鍵欄是第 2 欄「存取庫」,鍵值是 `{owner}/{repo}`。
|
||||||
|
|||||||
@@ -3,16 +3,17 @@
|
|||||||
> 由 `jsc-meta:tooling-guide` 維護。這是目錄頁 `TOOLING_CONTENTS`。
|
> 由 `jsc-meta:tooling-guide` 維護。這是目錄頁 `TOOLING_CONTENTS`。
|
||||||
> 一列代表一組「機器、CLI、帳號」。同一台機器裝了幾支 CLI,就有幾列。
|
> 一列代表一組「機器、CLI、帳號」。同一台機器裝了幾支 CLI,就有幾列。
|
||||||
> `TOOLING_{HASH}` 的 `{HASH}` 交給 `jsc-gitea/tools/hash-id` 產生,雜湊來源見 `jsc-meta/references/guidelines.md` 的「Wiki 頁命名總表」。
|
> `TOOLING_{HASH}` 的 `{HASH}` 交給 `jsc-gitea/tools/hash-id` 產生,雜湊來源見 `jsc-meta/references/guidelines.md` 的「Wiki 頁命名總表」。
|
||||||
|
> 連結寫法:所有連結一律 `[{文字}]({連結})`,網址放 `jsc-gitea/tools/gitea.sh wiki-url` 印出的絕對網址,不用 `[[...]]`。寫入前先把每個連結交給 `jsc-gitea/tools/link-check.sh` 驗證,結束碼 0 才寫入;驗證走 API,不看網頁狀態碼,私有存取庫的網頁網址對未登入請求會回 404。
|
||||||
|
|
||||||
| 盤點頁 | 主機 | 工具 | 帳號 | plugin 數 | 技能數 | hook 接線 | 最後盤點 |
|
| 盤點頁 | 主機 | 工具 | 帳號 | plugin 數 | 技能數 | hook 接線 | 最後盤點 |
|
||||||
| --- | --- | --- | --- | ---: | ---: | --- | --- |
|
| --- | --- | --- | --- | ---: | ---: | --- | --- |
|
||||||
| [[TOOLING_{HASH}]] | {主機名} | {claude、codex、copilot、antigravity、kiro 五選一} | {登入帳號} | {n} | {n} | {wired、degraded、unwired、unknown 四選一} | {yyyy-MM-dd HH:mm} |
|
| [TOOLING_{HASH}]({wiki-url 印出的絕對網址}) | {主機名} | {claude、codex、copilot、antigravity、kiro 五選一} | {登入帳號} | {n} | {n} | {wired、degraded、unwired、unknown 四選一} | {yyyy-MM-dd HH:mm} |
|
||||||
|
|
||||||
## 欄位說明
|
## 欄位說明
|
||||||
|
|
||||||
| 欄位 | 內容 |
|
| 欄位 | 內容 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 盤點頁 | 指向 `TOOLING_{HASH}` 的同 wiki 連結 |
|
| 盤點頁 | `[TOOLING_{HASH}]({連結})`,連結是 `gitea.sh wiki-url` 印出的絕對網址 |
|
||||||
| 主機 | 這次盤點的機器名,與雜湊第一段相同 |
|
| 主機 | 這次盤點的機器名,與雜湊第一段相同 |
|
||||||
| 工具 | CLI 代號,與雜湊第二段相同 |
|
| 工具 | CLI 代號,與雜湊第二段相同 |
|
||||||
| 帳號 | 執行盤點的登入帳號,與雜湊第三段相同 |
|
| 帳號 | 執行盤點的登入帳號,與雜湊第三段相同 |
|
||||||
|
|||||||
Executable
+67
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# check-link-format.sh — 檢查一個 domain 存取庫的 markdown 連結寫法。
|
||||||
|
#
|
||||||
|
# 用法: check-link-format.sh <domain-path>
|
||||||
|
#
|
||||||
|
# 檢查一項(掃 {domain-path} 底下全部 *.md,跳過 .git):
|
||||||
|
# 連結一律 [{文字}]({連結})。雙括號那種同 wiki 連結一個都不留。
|
||||||
|
#
|
||||||
|
# 為什麼要有這支: 雙括號只在目前這個 wiki 內解析。指到別的存取庫時不會報錯,
|
||||||
|
# 畫面上看起來像正常文字或死連結,巡不到也修不了。人工比對每輪都會漏,交給程式判。
|
||||||
|
#
|
||||||
|
# 判定範圍與其極限: 只看**渲染得出來的正文**。行內程式碼(單引號反引號夾起來的那段)
|
||||||
|
# 與圍籬程式碼區塊都先剝掉再比,理由有二:
|
||||||
|
# 1. 文件解釋「不要用雙括號」時,本來就要把那個寫法原樣寫出來,那是說明不是連結。
|
||||||
|
# 2. shell 腳本的條件測試語法長得一模一樣,範例貼進 markdown 就會被誤判。
|
||||||
|
# 代價講白: 有人把真正的連結寫進程式碼區塊,這支抓不到;那種寫法本來也不會被渲染成連結。
|
||||||
|
#
|
||||||
|
# 輸出: 一行一個不合格項目,格式 {檔案}:{行號}:{命中內容}(stdout);統計摘要走 stderr。
|
||||||
|
# 結束碼: 0=掃到 markdown 且全部通過
|
||||||
|
# 1=有不合格項目(清單在 stdout)
|
||||||
|
# 2=用法錯誤(本腳本只吃一個參數)
|
||||||
|
# 3=domain 路徑不存在,或底下一個 *.md 都沒有——**什麼都沒掃**,不等於通過
|
||||||
|
set -u
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo 'usage: check-link-format.sh <domain-path>' >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
[ "$#" -eq 1 ] || usage
|
||||||
|
DOMAIN=${1%/}
|
||||||
|
[ -n "$DOMAIN" ] || usage
|
||||||
|
[ -d "$DOMAIN" ] || { echo "找不到 domain 路徑:$DOMAIN" >&2; exit 3; }
|
||||||
|
|
||||||
|
TMP=$(mktemp) || { echo "無法建立暫存檔" >&2; exit 3; }
|
||||||
|
trap 'rm -f "$TMP"' EXIT
|
||||||
|
|
||||||
|
find "$DOMAIN" -name .git -prune -o -type f -name '*.md' -print 2>/dev/null | sort > "$TMP"
|
||||||
|
[ -s "$TMP" ] || { echo "底下沒有 *.md,無文件可掃:$DOMAIN" >&2; exit 3; }
|
||||||
|
|
||||||
|
total=$(wc -l < "$TMP" | tr -d ' ')
|
||||||
|
|
||||||
|
hits=$(
|
||||||
|
# shellcheck disable=SC2046
|
||||||
|
awk '
|
||||||
|
FNR == 1 { fence = 0 }
|
||||||
|
# 圍籬起訖各自成行,起與訖用同一個判準,所以一個旗標開關就夠。
|
||||||
|
/^[[:space:]]*(```|~~~)/ { fence = !fence; next }
|
||||||
|
fence { next }
|
||||||
|
{
|
||||||
|
line = $0
|
||||||
|
gsub(/`[^`]*`/, "", line)
|
||||||
|
if (match(line, /\[\[[^]]*\]\]/)) {
|
||||||
|
printf "%s:%d:%s\n", FILENAME, FNR, substr(line, RSTART, RLENGTH)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' $(cat "$TMP")
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ -n "$hits" ]; then
|
||||||
|
printf '%s\n' "$hits"
|
||||||
|
echo "連結寫法檢查有不合格項目:共掃 $total 份文件,清單見 stdout" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "連結寫法檢查通過:$total 份文件,連結全部為 [{文字}]({連結})" >&2
|
||||||
|
exit 0
|
||||||
Reference in New Issue
Block a user