From 11082f648eebd9599a1cfe774944e98156565278 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Fri, 21 Aug 2026 16:53:17 +0000 Subject: [PATCH] =?UTF-8?q?fix(wiki):=20=E4=BE=9D=E9=A0=81=E9=9D=A2?= =?UTF-8?q?=E9=A1=9E=E5=9E=8B=E8=A7=A3=E6=9E=90=20wiki=20repo=20=E4=B8=A6?= =?UTF-8?q?=E7=B5=B1=E4=B8=80=20hash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude-plugin/plugin.json | 2 +- .codex-plugin/plugin.json | 2 +- README.md | 13 ++++++-- plugin.json | 2 +- skills/wiki/SKILL.md | 18 ++++++----- tools/check-wiki-rules.sh | 64 ++++++++++++++++++++++++++++++++++++++ tools/gitea.sh | 37 ++++++++++++++++------ tools/hash-id | 34 ++++++++++++++++++++ 8 files changed, 148 insertions(+), 24 deletions(-) create mode 100755 tools/check-wiki-rules.sh create mode 100755 tools/hash-id diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 0de1c44..10e058d 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-gitea", - "version": "0.0.2", + "version": "0.0.3", "description": "Gitea API 工具、Wiki 讀寫與存取庫批次同步", "skills": "./skills", "author": { diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 5c7f23e..84aa3b1 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-gitea", - "version": "0.0.2", + "version": "0.0.3", "description": "Gitea API 工具、Wiki 讀寫與存取庫批次同步", "skills": "./skills" } diff --git a/README.md b/README.md index 65baa07..d4ae00c 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,15 @@ gitea.sh owners # 列出可讀取的 owner gitea.sh repos # 列出 owner 的 repo 全名 gitea.sh default-branch / gitea.sh clone-url / -gitea.sh wiki-repo # 解析頁面類型的 wiki 位置(見環境變數) +gitea.sh hash-id # 產生 8 碼大寫 SHA-1;首碼 0-9/A/B/C 時改成 Hxxxxxxx +gitea.sh wiki-repo # 解析頁面類型的 wiki 位置(TYPE = QUESTION / PLAN / ANALYZE / MAINTAIN / REPO / LOG / ERROR) gitea.sh wiki-list / gitea.sh wiki-get / # 不存在 exit 4 gitea.sh wiki-put / # 自動判斷新建或更新 gitea.sh pr-create / <body-file> gitea.sh api <METHOD> <path> [json-file] +hash-id <text> # 與 gitea.sh hash-id 相同 +check-wiki-rules.sh # 驗證 wiki repo 解析與 hash fallback 規則 ``` ## Skills 目錄 @@ -41,7 +44,7 @@ gitea.sh api <METHOD> <path> [json-file] ### `wiki` -Gitea wiki 頁讀寫的統一入口:依頁面類型(QUESTION / PLAN / ANALYZE / MAINTAIN / REPO / LOG)解析 wiki 所在的 `{owner}/{repo}`,未設定環境變數時以決策樹詢問。頁面內容以圖表優先(mermaid 圖、markdown 表格),純文字為最後手段。 +Gitea wiki 頁讀寫的統一入口:依頁面類型(QUESTION / PLAN / ANALYZE / MAINTAIN / REPO / LOG / ERROR)解析 wiki 所在的 `{owner}/{repo}`,先讀對應的 `JSC_WIKI_REPO_{TYPE}`,再退回 `JSC_WIKI_REPO`,不同類型不可互相代用。頁面內容以圖表優先(mermaid 圖、markdown 表格),純文字為最後手段。 ### `repo-sync` @@ -55,9 +58,13 @@ Gitea wiki 頁讀寫的統一入口:依頁面類型(QUESTION / PLAN / ANALYZ | --- | --- | --- | | `GITEA_HOST` | Gitea 站台(可省略 scheme,預設 https) | 詢問使用者 | | `GITEA_TOKEN` | Gitea API token;缺少或遇 401/403 時自動退回 tea CLI 登入 token | 詢問使用者 | -| `JSC_WIKI_REPO_{TYPE}` | 各類型 wiki 頁的 `{owner}/{repo}`;TYPE = QUESTION / PLAN / ANALYZE / MAINTAIN / REPO / LOG | 退回 `JSC_WIKI_REPO` | +| `JSC_WIKI_REPO_{TYPE}` | 各類型 wiki 頁的 `{owner}/{repo}`;TYPE = QUESTION / PLAN / ANALYZE / MAINTAIN / REPO / LOG / ERROR | 退回 `JSC_WIKI_REPO`,不做跨類型代用 | | `JSC_WIKI_REPO` | 共用預設的 wiki `{owner}/{repo}` | 詢問使用者 | +## Hash 規則 + +`{HASH}` 由 `tools/hash-id` 產生。先算 `SHA-1` 前 8 碼並轉大寫。若首碼是數字或 `A`、`B`、`C`,就改成 `H` 加上原本的前 7 碼,維持 8 碼長度。 + ## 相關 domain - [`jsc-ask`](https://gitea.jsc.idv.tw/plugins/ask):wiki 位置未設定時的決策樹詢問 diff --git a/plugin.json b/plugin.json index add943c..fc74cf7 100644 --- a/plugin.json +++ b/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-gitea", - "version": "0.0.2", + "version": "0.0.3", "description": "Gitea API 工具、Wiki 讀寫與存取庫批次同步", "skills": "./skills/" } diff --git a/skills/wiki/SKILL.md b/skills/wiki/SKILL.md index efab159..4f0b935 100644 --- a/skills/wiki/SKILL.md +++ b/skills/wiki/SKILL.md @@ -1,6 +1,6 @@ --- name: wiki -description: Read or write a Gitea wiki page through tools/gitea.sh with GITEA_TOKEN. Resolve the wiki repo per page type (QUESTION/PLAN/ANALYZE/MAINTAIN/REPO/LOG) via gitea.sh wiki-repo, falling back to JSC_WIKI_REPO or a decision-tree question. Page content is chart-first - prefer mermaid diagrams and markdown tables over plain prose. Used by jsc-ask, jsc-sdlc, and jsc-log for all wiki pages; not for repo code files. +description: Read or write a Gitea wiki page through tools/gitea.sh and tools/hash-id. Resolve the wiki repo per page type with JSC_WIKI_REPO_{TYPE} first, then JSC_WIKI_REPO, and ask only when neither is set. Page content is chart-first - prefer mermaid diagrams and markdown tables over plain prose. Used by jsc-ask, jsc-sdlc, and jsc-log for wiki pages, including ERROR pages, not for repo code files. --- # wiki — read and write Gitea wiki pages @@ -9,10 +9,11 @@ Every wiki operation in the jsc skill set goes through this skill. One entry poi ## Resolve the wiki location -Different page types can live in different `{owner}/{repo}` repos, classified by page-name prefix: `QUESTION`, `PLAN`, `ANALYZE`, `MAINTAIN`, `REPO`, `LOG`. +Different page types can live in different `{owner}/{repo}` repos, classified by page-name prefix: `QUESTION`, `PLAN`, `ANALYZE`, `MAINTAIN`, `REPO`, `LOG`, `ERROR`. -1. Run `tools/gitea.sh wiki-repo {TYPE}` (TYPE = the page-name prefix). Resolution order: `JSC_WIKI_REPO_{TYPE}` > `JSC_WIKI_REPO`. When either is set, use it and skip the question. -2. On exit 3 (neither is set), ask the user for that page type's `{owner}/{repo}` per the `jsc-ask:ask` rules, and suggest setting `JSC_WIKI_REPO_{TYPE}` (can differ per type) or `JSC_WIKI_REPO` (shared default). +1. Before asking the user, inspect the current shell environment for the needed repo variables and Gitea connection variables: `JSC_WIKI_REPO_{TYPE}`, `JSC_WIKI_REPO`, `GITEA_HOST`, and `GITEA_TOKEN`. Use inherited shell values first; only ask when the needed repo cannot be resolved after that check. +2. Run `tools/gitea.sh wiki-repo {TYPE}` (TYPE = the page-name prefix). Allowed types are `QUESTION`, `PLAN`, `ANALYZE`, `MAINTAIN`, `REPO`, `LOG`, and `ERROR`. Resolution order is `JSC_WIKI_REPO_{TYPE}` first, then `JSC_WIKI_REPO`. Never borrow another type's repo. +3. On exit 3 (neither is set after env inspection), ask the user for that page type's `{owner}/{repo}` per the `jsc-ask:ask` rules, and suggest setting `JSC_WIKI_REPO_{TYPE}` (can differ per type) or `JSC_WIKI_REPO` (shared default). ## Operations @@ -25,7 +26,8 @@ Different page types can live in different `{owner}/{repo}` repos, classified by ## Rules 1. Page names must follow the wiki naming table in the skill guidelines (see `jsc-meta/references/guidelines.md`). -2. To update a contents page (`*_CONTENTS`): `wiki-get` it first, apply the template to append or modify, then `wiki-put` the whole page back. Never overwrite entries owned by others. -3. Write all wiki content in UTF-8 Traditional Chinese, per the STE100 output rule. -4. Prefer visual forms for page content: use mermaid diagrams (flowchart, sequence, gantt, pie) and markdown tables wherever the information allows. Plain running text is the last resort, kept short. -5. Authentication fallback is built into `tools/gitea.sh`: on a missing GITEA_TOKEN or a 401/403 response it retries with the tea CLI login token automatically, so only report an auth failure when both paths fail. +2. Use `tools/hash-id` for `{HASH}` values. It returns the first 8 uppercase SHA-1 hex chars, or `H` plus the first 7 chars when the raw hash starts with `0-9`, `A`, `B`, or `C`. +3. To update a contents page (`*_CONTENTS`): `wiki-get` it first, apply the template to append or modify, then `wiki-put` the whole page back. Never overwrite entries owned by others. +4. Write all wiki content in UTF-8 Traditional Chinese, per the STE100 output rule. +5. Prefer visual forms for page content: use mermaid diagrams (flowchart, sequence, gantt, pie) and markdown tables wherever the information allows. Plain running text is the last resort, kept short. +6. Authentication fallback is built into `tools/gitea.sh`: on a missing GITEA_TOKEN or a 401/403 response it retries with the tea CLI login token automatically, so only report an auth failure when both paths fail. diff --git a/tools/check-wiki-rules.sh b/tools/check-wiki-rules.sh new file mode 100755 index 0000000..7f0301e --- /dev/null +++ b/tools/check-wiki-rules.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env sh +# check-wiki-rules — 驗證 wiki repo 解析與 hash-id 規則。 +set -eu + +dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +gitea="$dir/gitea.sh" +hash_id="$dir/hash-id" + +fail() { + printf '%s\n' "$1" >&2 + exit 1 +} + +expect_eq() { + got=$1 + want=$2 + label=$3 + [ "$got" = "$want" ] || fail "$label: want=$want got=$got" +} + +check_repo() { + type=$1 + label=$2 + want=$3 + shift 3 + got=$(env -i PATH="${PATH:-/usr/bin:/bin}" "$@" "$gitea" wiki-repo "$type") + expect_eq "$got" "$want" "$label" +} + +check_hash() { + input=$1 + want=$2 + got=$("$hash_id" "$input") + expect_eq "$got" "$want" "hash-id $input" +} + +check_repo REPO 'REPO specific wins' 'records/REPO' \ + JSC_WIKI_REPO_REPO='records/REPO' \ + JSC_WIKI_REPO_ANALYZE='knowledges/ANALYZE' \ + JSC_WIKI_REPO='shared/wiki' + +check_repo REPO 'REPO falls back to shared only' 'shared/wiki' \ + JSC_WIKI_REPO_ANALYZE='knowledges/ANALYZE' \ + JSC_WIKI_REPO='shared/wiki' + +check_repo ANALYZE 'ANALYZE specific wins' 'knowledges/ANALYZE' \ + JSC_WIKI_REPO_REPO='records/REPO' \ + JSC_WIKI_REPO_ANALYZE='knowledges/ANALYZE' \ + JSC_WIKI_REPO='shared/wiki' + +check_repo ANALYZE 'ANALYZE falls back to shared only' 'shared/wiki' \ + JSC_WIKI_REPO_REPO='records/REPO' \ + JSC_WIKI_REPO='shared/wiki' + +check_repo ERROR 'ERROR uses its own repo' 'errors/wiki' \ + JSC_WIKI_REPO_ERROR='errors/wiki' \ + JSC_WIKI_REPO='shared/wiki' + +check_hash 'case-2' 'H5172CB7' +check_hash 'case-11' 'HA9A6662' +check_hash 'case-1' 'HB6EC7FD' +check_hash 'case-12' 'HCCA8D42' + +printf '%s\n' 'OK' diff --git a/tools/gitea.sh b/tools/gitea.sh index 7b73169..66cbaf8 100755 --- a/tools/gitea.sh +++ b/tools/gitea.sh @@ -5,9 +5,10 @@ # gitea.sh repos <owner> # 列出 owner 底下可讀取的 repo(全名) # gitea.sh default-branch <owner>/<repo> # 印出預設分支 # gitea.sh clone-url <owner>/<repo> # 印出 clone URL +# gitea.sh hash-id <text> # 產生 8 碼大寫 SHA-1 hash;首碼為 0-9/A/B/C 時改成 Hxxxxxxx # gitea.sh wiki-repo <TYPE> # 解析頁面類型的 wiki 位置: -# TYPE = QUESTION|PLAN|ANALYZE|MAINTAIN|REPO|LOG(即頁名前綴) -# 依序取 JSC_WIKI_REPO_{TYPE} > JSC_WIKI_REPO;都未設定 exit 3(呼叫端須詢問使用者) +# TYPE = QUESTION|PLAN|ANALYZE|MAINTAIN|REPO|LOG|ERROR(即頁名前綴) +# 依序取 JSC_WIKI_REPO_{TYPE} > JSC_WIKI_REPO;不得跨類型代用;都未設定 exit 3 # gitea.sh wiki-list <owner>/<repo> # 列出 wiki 頁名 # gitea.sh wiki-get <owner>/<repo> <page> # 印出 wiki 頁 markdown;不存在時 exit 4 # gitea.sh wiki-put <owner>/<repo> <page> <file> # 建立或更新 wiki 頁(內容取自檔案) @@ -21,6 +22,30 @@ # (~/.config/tea/config.yml,優先取 default: true 的登入);兩者皆無才失敗。 set -eu +script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) + +resolve_wiki_repo() { # TYPE -> JSC_WIKI_REPO_{TYPE} -> JSC_WIKI_REPO + type=$(printf '%s' "${1:?TYPE required}" | tr a-z A-Z) + case "$type" in + QUESTION|PLAN|ANALYZE|MAINTAIN|REPO|LOG|ERROR) ;; + *) echo "unknown wiki type: $type" >&2; exit 2 ;; + esac + eval "v=\${JSC_WIKI_REPO_${type}:-}" + [ -n "$v" ] || v="${JSC_WIKI_REPO:-}" + if [ -n "$v" ]; then printf '%s\n' "$v"; else + echo "no wiki repo configured for $type (set JSC_WIKI_REPO_$type or JSC_WIKI_REPO)" >&2; exit 3 + fi +} + +cmd="${1:?usage: gitea.sh <command> ...}"; shift +case "$cmd" in + hash-id) + exec "$script_dir/hash-id" "$@" ;; + wiki-repo) + resolve_wiki_repo "${1-}" + exit 0 ;; +esac + tea_token() { # 取 tea CLI 設定檔的 token(優先 default: true 的登入,否則第一個) cfg="${HOME}/.config/tea/config.yml" [ -f "$cfg" ] || return 1 @@ -78,7 +103,6 @@ for i in items: ' "$1" } -cmd="${1:?usage: gitea.sh <command> ...}"; shift case "$cmd" in owners) { req GET "/user" | json_field login @@ -101,13 +125,6 @@ case "$cmd" in clone-url) or="${1:?owner/repo required}" req GET "/repos/$or" | json_field clone_url ;; - wiki-repo) - type=$(printf '%s' "${1:?TYPE required}" | tr a-z A-Z) - eval "v=\${JSC_WIKI_REPO_$type:-}" - [ -n "$v" ] || v="${JSC_WIKI_REPO:-}" - if [ -n "$v" ]; then printf '%s\n' "$v"; else - echo "no wiki repo configured for $type (set JSC_WIKI_REPO_$type or JSC_WIKI_REPO)" >&2; exit 3 - fi ;; wiki-list) or="${1:?owner/repo required}" req GET "/repos/$or/wiki/pages?limit=200" | json_field title ;; diff --git a/tools/hash-id b/tools/hash-id new file mode 100755 index 0000000..1c7f256 --- /dev/null +++ b/tools/hash-id @@ -0,0 +1,34 @@ +#!/usr/bin/env sh +# hash-id — 產生 8 碼大寫 SHA-1 hash。 +# 用法: +# hash-id <text> +# printf '%s' <text> | hash-id +# 規則: +# 先取 SHA-1 前 8 碼大寫。 +# 若首碼為 0-9、A、B、C,改成 H 加上原 SHA-1 前 7 碼。 +set -eu + +input='' +if [ "$#" -gt 0 ]; then + input=$* +elif [ -t 0 ]; then + input='' +else + input=$(cat) +fi + +if command -v sha1sum >/dev/null 2>&1; then + raw=$(printf '%s' "$input" | sha1sum | awk '{print $1}') +elif command -v shasum >/dev/null 2>&1; then + raw=$(printf '%s' "$input" | shasum -a 1 | awk '{print $1}') +else + echo 'no SHA-1 helper found' >&2 + exit 1 +fi + +hash=$(printf '%s' "$raw" | cut -c1-8 | tr a-f A-F) +case "$hash" in + [0-9ABC]*) hash="H$(printf '%s' "$hash" | cut -c1-7)" ;; +esac + +printf '%s\n' "$hash" -- 2.53.0