feat(ask): 問詢目錄頁改條列式並修正 key-col 參數

What:
把問詢目錄頁 `QUESTION_CONTENTS` 的呈現格式從 markdown 表格改成條列式——每個存取庫一個 H2 區塊,H2 標題就是該存取庫問詢紀錄頁的頁名 `QUESTION_{HASH}`,欄位改成標題底下一層條列 `- {欄位名}:{值}`,順序維持存取庫名稱、問詢紀錄、最後更新,整頁不再留任何 markdown 表格。同一輪把 `wiki-contents.sh upsert QUESTION` 的呼叫參數從 `1 {owner}/{repo}` 改成 `2 QUESTION_{HASH}`。改動落在 `templates/question-contents.md` 的版面與參數語意、`skills/ask/SKILL.md` 與 `references/behaviors.md` 的步驟敘述與可驗證跡象,以及 `README.md` 的技能描述。

Why:
表格版面一列塞滿所有欄位,欄位一長就難讀,每一筆的鍵也埋在儲存格裡;改成一筆一個 H2 區塊之後,鍵就是標題文字,人與工具都直接看得出哪一筆對應哪一個內容頁。`key-col` 原本填 `1`,指到的是純文字的存取庫名稱欄:舊表格自動轉條列時,工具會拿那一欄的連結產生 H2 標題,填 `1` 只會做出 `## plugins/meta` 這種標題,比不到鍵 `QUESTION_{HASH}`,既有那一筆會被當成新的附加上去,同一個存取庫在頁面上出現兩個區塊,舊區塊從此再也更新不到。

How:
`templates/question-contents.md` 的範本主體從表頭加資料列換成 `## QUESTION_{HASH}` 加三條 bullet,引言補上版面段與參數語意段,寫明 `{key}` 是 H2 標題文字、第四個參數帶的是整個區塊的 markdown 而不是單列。`skills/ask/SKILL.md` 把目錄頁那幾條的 row 敘述全部改成 block,呼叫式改為 `upsert QUESTION 2 QUESTION_{HASH} {block-file} templates/question-contents.md`,並說明 `key-col` 為什麼固定是 `2`、填 `1` 會壞成什麼樣,另外在 `wiki-contents.sh` 退 1 的分支補上「頁面上還沒有自己那個區塊不算失敗,那是附加的情形」。`references/behaviors.md` 的關鍵步驟補上區塊檔的組法與參數語意,外部呼叫改成單一 H2 區塊的讀取、合併、寫回,可驗證跡象改成檢查該區塊三條 bullet 的齊全度、順序、全形冒號與整頁不留表格,並補上舊表格轉條列後 H1 與 `>` 引言原樣保留、原有資料一筆不少。`README.md` 的技能描述同步改成條列式的說法。實際的轉檔與 upsert 邏輯在另一個存取庫的 `gitea/tools/wiki-contents.sh`,本存取庫只調整敘述與範本。

Who:
屬於 wiki 目錄頁一律改條列式呈現的需求,`ask` 這一支負責 `QUESTION_CONTENTS` 的範本與敘述。`key-col` 修正是同一個需求能正確落地的必要條件,且與版面敘述改在同一段文字上,無法拆成獨立提交。
This commit is contained in:
2026-09-02 17:24:49 +08:00
parent fd690aa46e
commit e8294f3891
4 changed files with 24 additions and 18 deletions
+4 -4
View File
@@ -7,7 +7,7 @@
| 項目 | 內容 |
| --- | --- |
| 觸發時機 | 任何 jsc 技能需要使用者做決定時叫用。答案已經寫在 `QUESTION_{HASH}` 且意圖相符時不叫用,直接採用舊答案。答案查得到程式碼、設定檔或環境變數時不叫用,自己去查。 |
| 關鍵步驟 | 確認目前工作的 `{owner}/{repo}`、執行 `jsc-gitea/tools/hash-id {owner}/{repo}` 取得完整 40 碼大寫 `HASH`、每個工作階段各解析一次 `QUESTION` 與 `CONTENTS` 兩個 wiki 存取庫、讀入 `QUESTION_CONTENTS`(`CONTENTS` 庫)與 `QUESTION_{HASH}`(`QUESTION` 庫)並留成階段副本、把這一輪每一題標成「照紀錄回答」或「要問」、以決策樹選單一次問一個決策點且每個選項標明影響範圍、依答案決定下一題直到沒有疑慮、交一個 sub agent 做兩次寫入:先把新一節要放進 `QUESTION_{HASH}` 的每個連結交給 `jsc-gitea/tools/link-check.sh` 驗證,退 0 才用 `jsc-gitea:wiki` 寫那一節;再用 `jsc-gitea/tools/gitea.sh wiki-url` 取紀錄頁的絕對網址並依結束碼分流(4 是紀錄頁還沒寫上去要重寫、5 是沒有 `html_url`、7 金鑰失效、8 重試一次,其餘非 0 一律停下並註明那一列沒有被索引,網址取不到就不寫那一列)、把該列的連結再交給 `link-check.sh` 驗證,退 0 才用 `jsc-gitea/tools/wiki-contents.sh upsert` 把單列寫進 `QUESTION_CONTENTS` 並依結束碼分流、寫入後同步更新階段副本、把答案交回叫用的技能、收尾呼叫 `jsc-hooks/tools/report-status.sh skill-end jsc-ask:ask {status} {結束碼} {detail}` 記下這一輪怎麼結束(腳本路徑比照 `jsc-gitea/tools/hash-id` 的解析方式,檔案不在就安靜跳過,不得讓回報失敗變成問詢失敗)。頁面裡的連結一律寫成 `[{文字}]({連結})`,wiki 連結取自 `wiki-url` 印出的絕對網址,不自行組路徑。 |
| 外部呼叫 | `jsc-gitea/tools/hash-id`、`jsc-gitea:wiki`(`wiki-repo QUESTION`、`wiki-repo CONTENTS`、`wiki-get`、寫入)、`jsc-gitea/tools/wiki-contents.sh upsert`、`jsc-gitea/tools/gitea.sh wiki-url`(目錄頁連到紀錄頁的絕對網址)、`jsc-gitea/tools/link-check.sh`(兩頁寫入前各驗證一次連結)、AskUserQuestion 或等效選單、一個負責兩次 wiki 寫入的 sub agent;範本 `templates/question-record.md`、`templates/question-contents.md` |
| 完成條件 | 這一輪每一題都有答案,來源是紀錄或使用者;答案交回叫用的技能;有存取庫名稱時,sub agent 回報兩頁都寫成功(`wiki-contents.sh` 退 0),主代理接受那一次回報。沒有存取庫名稱時,問完直接交回答案,不寫任何頁。目錄頁寫不成的另一種完成條件:`wiki-contents.sh` 退 2、退 3、退 7,或 `wiki-url` 取不到網址,四種都算這一步走完——紀錄頁記成「已寫、未被索引」,回報講明結束碼與沒寫成的那一頁,答案照樣交回叫用的技能。退 3 特別要交回答案:`JSC_WIKI_REPO_CONTENTS` 在 `jsc-cli/tools/config-spec.tsv` 是 `fix=ask`,`/jsc-cli:setup` 只能靠這一支問到值,答案在這裡被吞掉,變數就永遠設不起來。退 4 代表範本參數被漏掉了,本技能的呼叫一律帶第五個參數,所以不會出現;範本路徑不存在回的是 2。`link-check.sh` 非 0 也算這一步走完:退 1 就那一頁不寫並回報 DEAD 清單,退 2 補參數重跑,退 3 先設定 `GITEA_HOST` 再驗證,退 7 停下來回報金鑰,四種都不得跳過驗證直接寫入。停止執行並回報的情況:`hash-id` 找不到 SHA-1 工具、wiki 讀取非 exit 4 的失敗、重試後仍寫不進去(`wiki-contents.sh` 退 1 或 8)。寫入失敗一律把答案交回並註明沒有記錄。以上每一條路線都要走完最後一步:呼叫 `report-status.sh skill-end`,狀態五選一——答案齊全且該寫的兩頁都寫成是 `ok`;問詢做完但記錄少了一塊是 `degraded`,涵蓋沒有 `{owner}/{repo}` 因而完全不記錄,以及紀錄頁寫成、目錄頁沒寫成;使用者中止那一輪是 `aborted`;停手而且答案沒交回去是 `failed`。閘門擋下的情形不在這裡出現,被擋的技能根本走不到這一步,所以不用 `blocked`。腳本不在磁碟上就跳過,這一步照樣算走完。 |
| 可驗證跡象 | `QUESTION` 存取庫的 wiki `QUESTION_{HASH}` 頁尾多一節,頁名是完整 40 碼大寫十六進位,開頭是使用者意圖,底下每題一張選項與影響範圍的表,附答案與時間;`CONTENTS` 存取庫的 wiki `QUESTION_CONTENTS` 該存取庫那一列的「最後更新」變成這次執行的時間戳,沒有該列就新增一列,該列的問詢紀錄欄是 `[QUESTION_{HASH}]({絕對網址})`,網址與 `wiki-url` 印出的一字不差,別的存取庫那幾列一字不動;兩頁寫進去的每個連結都通得過 `link-check.sh`,驗不過那一輪頁面停在舊內容,回報裡有 DEAD 清單或結束碼。沒有 `{owner}/{repo}` 時無 wiki 寫入跡象,只有回報內容。不論走哪一條路線,`$JSC_HOME/usage/events.jsonl` 尾端都會多一筆 `{kind:skill,phase:end}` 事件,`name` 是 `jsc-ask:ask`,`status` 與這一輪的結局相符,`exit` 是決定結局的那支工具的結束碼;`report-status.sh` 不在那台機器上就沒有這一筆,而問詢結果一字不變。 |
| 關鍵步驟 | 確認目前工作的 `{owner}/{repo}`、執行 `jsc-gitea/tools/hash-id {owner}/{repo}` 取得完整 40 碼大寫 `HASH`、每個工作階段各解析一次 `QUESTION` 與 `CONTENTS` 兩個 wiki 存取庫、讀入 `QUESTION_CONTENTS`(`CONTENTS` 庫)與 `QUESTION_{HASH}`(`QUESTION` 庫)並留成階段副本、把這一輪每一題標成「照紀錄回答」或「要問」、以決策樹選單一次問一個決策點且每個選項標明影響範圍、依答案決定下一題直到沒有疑慮、交一個 sub agent 做兩次寫入:先把新一節要放進 `QUESTION_{HASH}` 的每個連結交給 `jsc-gitea/tools/link-check.sh` 驗證,退 0 才用 `jsc-gitea:wiki` 寫那一節;再用 `jsc-gitea/tools/gitea.sh wiki-url` 取紀錄頁的絕對網址並依結束碼分流(4 是紀錄頁還沒寫上去要重寫、5 是沒有 `html_url`、7 金鑰失效、8 重試一次,其餘非 0 一律停下並註明那個區塊沒有被索引,網址取不到就不寫那個區塊)、備妥自己那個 H2 區塊的區塊檔(`## QUESTION_{HASH}` 那一行、空行,接存取庫名稱、問詢紀錄、最後更新三條 bullet,格式 `- {欄位名}:{值}`)、把區塊裡的連結再交給 `link-check.sh` 驗證,退 0 才執行 `jsc-gitea/tools/wiki-contents.sh upsert QUESTION 2 QUESTION_{HASH} {區塊檔} templates/question-contents.md` 把單一區塊寫進 `QUESTION_CONTENTS` 並依結束碼分流、寫入後同步更新階段副本、把答案交回叫用的技能、收尾呼叫 `jsc-hooks/tools/report-status.sh skill-end jsc-ask:ask {status} {結束碼} {detail}` 記下這一輪怎麼結束(腳本路徑比照 `jsc-gitea/tools/hash-id` 的解析方式,檔案不在就安靜跳過,不得讓回報失敗變成問詢失敗)。目錄頁的鍵是 H2 標題文字,也就是內容頁頁名 `QUESTION_{HASH}`,標題不放連結、不放網址、不加前後綴;第三個參數帶的就是這個頁名,第二個參數是 `2`,指舊表格裡持有內容頁連結那一欄的欄位序號(1 起算)——`QUESTION_CONTENTS` 的舊表格欄序是存取庫名稱、問詢紀錄、最後更新,帶連結的是第 2 欄「問詢紀錄」。這個參數只在舊頁還是 markdown 表格、要自動轉成條列時才有作用,但不是死參數也不能隨便填:轉檔時工具會拿那一欄的連結產生 H2 標題,填成 `1` 就取到純文字的 `{owner}/{repo}`,標題變成 `## plugins/meta`,比不到鍵 `QUESTION_{HASH}`,既有那一筆會被當成新的附加上去,同一個存取庫在頁面上出現兩次,舊區塊從此再也更新不到。頁面裡的連結一律寫成 `[{文字}]({連結})`,wiki 連結取自 `wiki-url` 印出的絕對網址,不自行組路徑。 |
| 外部呼叫 | `jsc-gitea/tools/hash-id`、`jsc-gitea:wiki`(`wiki-repo QUESTION`、`wiki-repo CONTENTS`、`wiki-get`、寫入)、`jsc-gitea/tools/wiki-contents.sh upsert`(單一 H2 區塊的讀取、合併、寫回)、`jsc-gitea/tools/gitea.sh wiki-url`(目錄頁連到紀錄頁的絕對網址)、`jsc-gitea/tools/link-check.sh`(兩頁寫入前各驗證一次連結)、AskUserQuestion 或等效選單、一個負責兩次 wiki 寫入的 sub agent;範本 `templates/question-record.md`、`templates/question-contents.md` |
| 完成條件 | 這一輪每一題都有答案,來源是紀錄或使用者;答案交回叫用的技能;有存取庫名稱時,sub agent 回報兩頁都寫成功(`wiki-contents.sh` 退 0,代表該區塊被換掉或附加上去),主代理接受那一次回報,不再重讀頁面確認。沒有存取庫名稱時,問完直接交回答案,不寫任何頁。目錄頁寫不成的另一種完成條件:`wiki-contents.sh` 退 2、退 3、退 7,或 `wiki-url` 取不到網址,四種都算這一步走完——紀錄頁記成「已寫、未被索引」,回報講明結束碼與沒寫成的那一頁,答案照樣交回叫用的技能。退 3 特別要交回答案:`JSC_WIKI_REPO_CONTENTS` 在 `jsc-cli/tools/config-spec.tsv` 是 `fix=ask`,`/jsc-cli:setup` 只能靠這一支問到值,答案在這裡被吞掉,變數就永遠設不起來。退 1 是組不出頁面內容或寫入失敗,重試一次;頁面上沒有自己那個區塊不算失敗,那是附加的情形。退 4 代表範本參數被漏掉了,本技能的呼叫一律帶第五個參數,所以不會出現;範本路徑不存在回的是 2。`link-check.sh` 非 0 也算這一步走完:退 1 就那一頁不寫並回報 DEAD 清單,退 2 補參數重跑,退 3 先設定 `GITEA_HOST` 再驗證,退 7 停下來回報金鑰,四種都不得跳過驗證直接寫入。停止執行並回報的情況:`hash-id` 找不到 SHA-1 工具、wiki 讀取非 exit 4 的失敗、重試後仍寫不進去(`wiki-contents.sh` 退 1 或 8)。寫入失敗一律把答案交回並註明沒有記錄。以上每一條路線都要走完最後一步:呼叫 `report-status.sh skill-end`,狀態五選一——答案齊全且該寫的兩頁都寫成是 `ok`;問詢做完但記錄少了一塊是 `degraded`,涵蓋沒有 `{owner}/{repo}` 因而完全不記錄,以及紀錄頁寫成、目錄頁沒寫成;使用者中止那一輪是 `aborted`;停手而且答案沒交回去是 `failed`。閘門擋下的情形不在這裡出現,被擋的技能根本走不到這一步,所以不用 `blocked`。腳本不在磁碟上就跳過,這一步照樣算走完。 |
| 可驗證跡象 | `QUESTION` 存取庫的 wiki `QUESTION_{HASH}` 頁尾多一節,頁名是完整 40 碼大寫十六進位,開頭是使用者意圖,底下每題一張選項與影響範圍的表,附答案與時間;`CONTENTS` 存取庫的 wiki `QUESTION_CONTENTS` 上,標題為 `QUESTION_{HASH}` 的那個 H2 區塊的「最後更新」那一條變成這次執行的時間戳,沒有該區塊就在頁尾新增一個,區塊裡三條 bullet 齊全且順序是存取庫名稱、問詢紀錄、最後更新,格式 `- {欄位名}:{值}` 用全形冒號,問詢紀錄那一條是 `[QUESTION_{HASH}]({絕對網址})`,網址與 `wiki-url` 印出的一字不差,別的存取庫那幾個區塊一字不動,整頁不留 markdown 表格;舊頁本來是表格時,這一次寫入後整頁已轉成條列,H1 與 `>` 引言原樣保留,原有資料一筆不少、順序不變。兩頁寫進去的每個連結都通得過 `link-check.sh`,驗不過那一輪頁面停在舊內容,回報裡有 DEAD 清單或結束碼。沒有 `{owner}/{repo}` 時無 wiki 寫入跡象,只有回報內容。不論走哪一條路線,`$JSC_HOME/usage/events.jsonl` 尾端都會多一筆 `{kind:skill,phase:end}` 事件,`name` 是 `jsc-ask:ask`,`status` 與這一輪的結局相符,`exit` 是決定結局的那支工具的結束碼;`report-status.sh` 不在那台機器上就沒有這一筆,而問詢結果一字不變。 |