From 232eb361582aa8ba1cf38c44273fa78f37b9203c Mon Sep 17 00:00:00 2001 From: Jeffery Date: Mon, 31 Aug 2026 11:05:09 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix(ask):=20=E8=A3=9C=E4=B8=8A=E5=A4=B1?= =?UTF-8?q?=E6=95=97=E9=80=80=E5=87=BA=E7=A2=BC=E5=88=86=E6=B5=81=E4=B8=A6?= =?UTF-8?q?=E6=94=B9=E6=AD=A3=E8=A6=8F=E7=AF=84=E6=8C=87=E6=A8=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What - 產生 HASH 的指令失敗時,依退出碼分流處理。 - 讀取問詢頁失敗時,依退出碼分流處理。 - 寫入目錄頁失敗時,依退出碼分流處理。 - 規範文件的指標改指向 jsc-meta 的 references/guidelines.md。 - 新增「Session cache」一節,兩頁在同一個工作階段只讀一次。 - wiki 存取庫在同一個工作階段只解析一次。 - 問後的三重完成條件收斂成一次確認。 Why - 原本只寫「執行指令取得 HASH」。指令失敗時沒有指示,技能會自行硬算雜湊或猜測頁名,寫錯頁面。 - 「讀取失敗」與「頁面不存在」意義不同。不分流就把失敗當成沒有紀錄,重問使用者已經回答過的問題。 - 目錄頁由所有存取庫共用。讀不回舊內容還照樣整頁覆寫,會抹掉別的存取庫的列,而且沒有備份可救。 - 指標指向的規範檔案已經搬到 jsc-meta,舊指標讓讀者找不到來源。 - 兩頁在一個工作階段內只有本技能會寫。重複讀取只是多花往返時間。 - wiki 位置本身就是要問的問題,答案卻要寫進 wiki 才記得住。不把答案留在工作階段內,每次呼叫都得再問一次,永遠問不完。 - 完成條件重複確認同一件事,主代理得多讀兩次頁面才敢往下走。 How - 取得 HASH 一步列明退出碼 0 與 1 的處理;其他非零退出碼一律停止執行,並回報退出碼與指令的錯誤輸出。 - 讀取一步把「頁面不存在」視為沒有紀錄,照常發問;其他失敗停止執行,並回報失敗頁名與退出碼。 - 寫入目錄頁一步依退出碼分流:正常就讀回整頁後更新單列,金鑰無效或無權限、以及其他 API 失敗都放棄寫入並回報。 - 新增「Session cache」一節,訂出首次讀取、後續沿用、寫入後更新副本、隨工作階段結束失效四個步驟。 - 解析 wiki 存取庫獨立成一步,答案留在工作階段內重複使用,收尾再建議使用者設定環境變數,永久結束追問。 - 兩份寫入交給同一個子代理,收斂成單一回報,主代理確認一次即可,不再回讀頁面驗證。 - 寫入失敗只重試該頁一次;再失敗就停止執行,回報未寫入的頁面與退出碼,答案仍交還呼叫端。 - 兩份範本的指標同步改指 jsc-meta。 Who - 決策樹問詢技能 ask 的問前準備、問後紀錄流程,以及問詢紀錄頁範本。 --- skills/ask/SKILL.md | 21 +++++++++++++++------ templates/question-record.md | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/skills/ask/SKILL.md b/skills/ask/SKILL.md index de89de0..da69961 100644 --- a/skills/ask/SKILL.md +++ b/skills/ask/SKILL.md @@ -7,11 +7,21 @@ description: Decision-tree questioning until no doubt remains. Checks wiki QUEST Every jsc skill that needs user input MUST follow the rules in this skill. +## Session cache + +Inside one work session this skill is the only writer of `QUESTION_{HASH}` and `QUESTION_CONTENTS`, so both pages are read once and reused. + +1. First call of the session: read both pages and keep them as the session copy. Done when the session holds each page's content, or the note that the page does not exist yet. +2. Every later call of the session: answer from the session copy. Done when this round's questions are matched against the session copy with no new wiki read. +3. Right after this skill writes either page: overwrite that page's session copy with the content just written. Done when the session copy equals the written content. +4. The cache expires with the work session, and only with it. Done when a new session starts again at step 1. + ## Before asking -1. Confirm the repository name `{owner}/{repo}` of the current work. Done when `{owner}/{repo}` is known, or when it is settled that none exists — then skip steps 2 and 3, ask directly, and do NOT record. -2. Compute `HASH` by running `jsc-gitea/tools/hash-id {owner}/{repo}` (the shared wiki hash rule — see guidelines.md for the algorithm). Done when the 8-character `HASH` is known. -3. Read `QUESTION_CONTENTS` and `QUESTION_{HASH}` via `jsc-gitea:wiki`. Never re-ask a question already answered in the record; use the recorded answer directly. When reusing an answer, read the section's recorded intent: reuse it when that intent matches the current situation, and ask again when it differs, instead of forcing the old answer. An answer whose intent covers a similar undecided question in this round answers that one too. Done when every question in this round is marked either answered-from-record with the citing section named, or to-be-asked. +1. Confirm the repository name `{owner}/{repo}` of the current work. Done when `{owner}/{repo}` is known, or when it is settled that none exists — then skip steps 2 to 4, ask directly, and do NOT record. +2. Compute `HASH` by running `jsc-gitea/tools/hash-id {owner}/{repo}` (the shared wiki hash rule — see `jsc-meta/references/guidelines.md` for the algorithm). Exit 0: take the printed 8-character `HASH`. Exit 1 (no SHA-1 helper on this machine): stop the run and report that `sha1sum` or `shasum` must be installed first; never hand-compute the hash and never guess a page name. Any other non-zero exit: stop the same way and report the exit code with the command's stderr. Done when the 8-character `HASH` is known, or the run stopped with that report. +3. Resolve the `QUESTION` wiki repo once per session through `jsc-gitea:wiki`. When that skill reports exit 3 for `wiki-repo QUESTION` (neither `JSC_WIKI_REPO_QUESTION` nor `JSC_WIKI_REPO` is set), ask the user for that `{owner}/{repo}`, then keep the answer in the session and reuse it for every later call — this one answer cannot come from the record, because the wiki location is the question itself, so asking again each call would loop forever. Close the run by advising the user to set `JSC_WIKI_REPO_QUESTION` (or `JSC_WIKI_REPO`) in the environment, which ends the asking permanently. Done when the session holds one `{owner}/{repo}` for `QUESTION` and no later call in this session asked for it again. +4. Load `QUESTION_CONTENTS` and `QUESTION_{HASH}` per "Session cache". A page reported missing (`wiki-get` exit 4) counts as "no record yet": keep going and ask every question of this round. Any other `jsc-gitea:wiki` failure stops the run with a report of the failing page and the underlying exit code; do not ask on a half-read record, because an answer already on file would be asked again. Never re-ask a question already answered in the record; use the recorded answer directly. When reusing an answer, read the section's recorded intent: reuse it when that intent matches the current situation, and ask again when it differs, instead of forcing the old answer. An answer whose intent covers a similar undecided question in this round answers that one too. Done when every question in this round is marked either answered-from-record with the citing section named, or to-be-asked. ## Questioning rules @@ -24,6 +34,5 @@ Every jsc skill that needs user input MUST follow the rules in this skill. ## After asking 1. Without a repository name, do not record; stop here. Done when the answers are handed back to the calling skill and no wiki page was touched. -2. After each Q&A round, apply `templates/question-record.md` to create or update `QUESTION_{HASH}` (append new entries; never overwrite old records). Each section MUST open with the user's original intent (why this questioning round happened), per the template; it lets a later reader judge why the user chose as they did and whether the answer still applies. Done when a section for this round exists on `QUESTION_{HASH}`, carries this round's intent and every answer, and every section written by an earlier round is still there. -3. Apply `templates/question-contents.md` to create or update `QUESTION_CONTENTS` (add the repository row if missing; otherwise refresh its last-updated time). Done when the row for `{owner}/{repo}` carries 最後更新 equal to this run's timestamp. -4. The wiki writes above MUST run as a sub agent, and that sub agent MUST write both `QUESTION_{HASH}` and `QUESTION_CONTENTS` through `jsc-gitea:wiki` — it owns the `JSC_WIKI_REPO_QUESTION` → `JSC_WIKI_REPO` resolution and the tea-token fallback, which a hand-rolled Gitea API call loses. Completion condition: the main agent has confirmed both writes succeeded. +2. After each Q&A round, hand both wiki writes to one sub agent. That sub agent MUST write through `jsc-gitea:wiki` — it owns the `JSC_WIKI_REPO_QUESTION` → `JSC_WIKI_REPO` resolution and the tea-token fallback, which a hand-rolled Gitea API call loses. It writes `QUESTION_{HASH}` first, applying `templates/question-record.md`: append this round as a new section, keep every earlier section, and open the section with the user's original intent (why this questioning round happened), which lets a later reader judge why the user chose as they did and whether the answer still applies. It then writes `QUESTION_CONTENTS`, applying `templates/question-contents.md`: read the page back, add the `{owner}/{repo}` row when missing, otherwise set 最後更新 to this run's timestamp, then write the whole page. `QUESTION_CONTENTS` is a directory shared by every repository, so it is never overwritten wholesale and no other repository's row is touched; `QUESTION_{HASH}` belongs to this one repository, which is why appending a section to it is the right shape there. Its read branches by exit code, and only exit 4 creates the directory from the template: exit 0 upserts into the content that came back, while exit 7 (key invalid or no permission) and exit 8 (any other API failure) both mean the old rows are unknown, so the write is abandoned and reported instead — a fresh template over a directory whose rows were never read erases every other repository's row, with no merge and no backup behind it. Content page first, contents page second, so the contents page never links a page that failed to write. Done when the sub agent has reported both writes as succeeded and the main agent has accepted that one report — this single confirmation covers both pages and both templates; do not re-read the pages to prove it. +3. On a reported write failure, retry that one page once. Done when the retry succeeded and step 3 of "Session cache" refreshed that page's copy, or — when the retry also failed — the run stops with a report naming the page that stayed unwritten and the exit code behind it, while the answers still go back to the calling skill and the report states plainly that nothing was recorded. diff --git a/templates/question-record.md b/templates/question-record.md index a4c917e..80ab689 100644 --- a/templates/question-record.md +++ b/templates/question-record.md @@ -1,6 +1,6 @@ # 問詢紀錄 — {owner}/{repo} -> 由 `jsc-ask:ask` 維護。這是問詢紀錄頁 `QUESTION_{HASH}`;`HASH` 執行 `jsc-gitea/tools/hash-id {owner}/{repo}` 取得(共用 wiki hash 規則,演算法見 guidelines.md)。新問答**附加**在文末,不覆蓋舊紀錄。相同問題再次出現時,直接採用此處答案,不再詢問。 +> 由 `jsc-ask:ask` 維護。這是問詢紀錄頁 `QUESTION_{HASH}`;`HASH` 執行 `jsc-gitea/tools/hash-id {owner}/{repo}` 取得(共用 wiki hash 規則,演算法見 `jsc-meta` 的 `references/guidelines.md`)。新問答**附加**在文末,不覆蓋舊紀錄。相同問題再次出現時,直接採用此處答案,不再詢問。 ## {yyyy-MM-dd HH:mm} {問詢主題} From 15825a5283eecb11a5c727e05302dbfa547bd336 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Mon, 31 Aug 2026 11:05:09 +0800 Subject: [PATCH 2/3] =?UTF-8?q?docs(ask):=20=E8=A3=9C=E4=B8=8A=E7=9B=AE?= =?UTF-8?q?=E9=8C=84=E9=A0=81=E5=AF=AB=E5=85=A5=E8=AA=9E=E6=84=8F=E4=B8=A6?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=8A=80=E8=83=BD=E8=AA=AA=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What - 問詢目錄頁範本新增「寫入語意」說明。 - 問詢目錄頁範本的規範指標改指向 jsc-meta 的 references/guidelines.md。 - README 的 ask 技能說明補上工作階段內只讀一次的行為。 Why - 目錄頁一列代表一個存取庫,由所有存取庫共用。範本只給表格不給寫法,寫入者容易整頁覆寫,抹掉別的存取庫的列。 - 指標指向的規範檔案已經搬到 jsc-meta,舊指標讓讀者找不到來源。 - README 是外部讀者認識這個技能的第一份文件。技能已經改成一個工作階段只讀一次,說明沒跟上就會誤導讀者。 How - 在目錄頁範本的說明區塊新增一段寫入語意:先讀回整頁,有列就更新該列,沒有才在文末附加,最後整頁寫回;明文禁止整頁覆蓋,也不得改動別人的列。 - 範本的指標改寫成 jsc-meta 的 references/guidelines.md。 - README 的技能段落補一句:兩頁在同一個工作階段只讀一次,之後沿用手上那份,自己寫入後就更新它,問出來的 wiki 存取庫也留在工作階段內重複使用。 Who - 問詢目錄頁範本,以及存取庫首頁的 ask 技能說明。 --- README.md | 2 +- templates/question-contents.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 214dfbf..dc82e70 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安 ### `ask` -決策樹問詢:一題一個決策點、選項標明影響範圍、問到沒有疑慮為止。問前查 `QUESTION_CONTENTS` 與 `QUESTION_{HASH}`,其中 `{HASH}` 執行 `jsc-gitea/tools/hash-id` 產生;已有答案不再問;AI 取用舊答案時依意圖判斷適用性,意圖不符就重新問。問後套範本寫回 wiki,每節開頭記錄使用者意圖(沒有存取庫名稱就不記錄)。不適用於答案已有紀錄的情況。 +決策樹問詢:一題一個決策點、選項標明影響範圍、問到沒有疑慮為止。問前查 `QUESTION_CONTENTS` 與 `QUESTION_{HASH}`,其中 `{HASH}` 執行 `jsc-gitea/tools/hash-id` 產生;已有答案不再問;AI 取用舊答案時依意圖判斷適用性,意圖不符就重新問。兩頁在同一個工作階段只讀一次,之後沿用手上那份,自己寫入後就更新它;問出來的 wiki 存取庫也留在工作階段內重複使用。問後套範本寫回 wiki,每節開頭記錄使用者意圖(沒有存取庫名稱就不記錄)。不適用於答案已有紀錄的情況。 diff --git a/templates/question-contents.md b/templates/question-contents.md index a346925..8df73d7 100644 --- a/templates/question-contents.md +++ b/templates/question-contents.md @@ -1,6 +1,8 @@ # 問詢目錄 -> 由 `jsc-ask:ask` 維護。這是問詢目錄頁 `QUESTION_CONTENTS`。每個存取庫一列;`QUESTION_{HASH}` 的 `{HASH}` 執行 `jsc-gitea/tools/hash-id {owner}/{repo}` 取得(共用 wiki hash 規則,演算法見 guidelines.md)。 +> 由 `jsc-ask:ask` 維護。這是問詢目錄頁 `QUESTION_CONTENTS`。每個存取庫一列;`QUESTION_{HASH}` 的 `{HASH}` 執行 `jsc-gitea/tools/hash-id {owner}/{repo}` 取得(共用 wiki hash 規則,演算法見 `jsc-meta` 的 `references/guidelines.md`)。 +> +> 寫入語意:一列代表一個存取庫。寫入前先讀回整頁,該存取庫已經有列就更新那一列,沒有才在文末附加一列,最後整頁寫回。禁止整頁覆蓋,也不得改動別人的列。 | 存取庫名稱 | 問詢紀錄 | 最後更新 | | --- | --- | --- | From f5ddb808f1b12ec9d59173ee5082a7cf1cbeacd2 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Mon, 31 Aug 2026 11:05:10 +0800 Subject: [PATCH 3/3] =?UTF-8?q?chore(manifest):=20=E5=AE=A3=E5=91=8A=20jsc?= =?UTF-8?q?-meta=20=E7=9B=B8=E4=BE=9D=E4=B8=A6=E6=8E=A8=E9=80=B2=E5=A4=96?= =?UTF-8?q?=E6=8E=9B=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What - 三份 manifest 的 jsc.requires 新增 jsc-meta 與它的最低版本要求。 - 三份 manifest 的外掛版本各推進一版。 Why - 這個技能的規範文件指標已經改指 jsc-meta。沒有宣告相依,安裝端可能少裝或裝到太舊的 jsc-meta,指標就指向不存在的檔案。 - 三份 manifest 分別供不同的 CLI 讀取,內容必須一致,只改其中一份會讓各 CLI 看到不同的相依。 - 技能行為這次有實質變動,版本不推進,安裝端不會取得新版。 How - 在 jsc.requires 既有的 jsc-gitea 之後補上 jsc-meta 一項,三份 manifest 寫法一致。 - 三份 manifest 的 version 欄位同步推進一版。 Who - jsc-ask 外掛的三份安裝設定檔。 --- .claude-plugin/plugin.json | 5 +++-- .codex-plugin/plugin.json | 5 +++-- plugin.json | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 055ed45..3195d3b 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-ask", - "version": "0.0.7", + "version": "0.0.8", "description": "決策樹問詢與問詢紀錄(QUESTION_* wiki 頁)", "skills": "./skills", "author": { @@ -16,7 +16,8 @@ ], "jsc": { "requires": { - "jsc-gitea": ">=0.1.7" + "jsc-gitea": ">=0.1.7", + "jsc-meta": ">=0.2.3" } } } diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 63c93bd..fa1ed37 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,11 +1,12 @@ { "name": "jsc-ask", - "version": "0.0.7", + "version": "0.0.8", "description": "決策樹問詢與問詢紀錄(QUESTION_* wiki 頁)", "skills": "./skills", "jsc": { "requires": { - "jsc-gitea": ">=0.1.7" + "jsc-gitea": ">=0.1.7", + "jsc-meta": ">=0.2.3" } } } diff --git a/plugin.json b/plugin.json index 3d3e879..526d4d6 100644 --- a/plugin.json +++ b/plugin.json @@ -1,11 +1,12 @@ { "name": "jsc-ask", - "version": "0.0.7", + "version": "0.0.8", "description": "決策樹問詢與問詢紀錄(QUESTION_* wiki 頁)", "skills": "./skills/", "jsc": { "requires": { - "jsc-gitea": ">=0.1.7" + "jsc-gitea": ">=0.1.7", + "jsc-meta": ">=0.2.3" } } }