Files
gitea/README.md
T
jiantw83 9ec18b8a94 feat(link): 連結一律寫成 [文字](絕對網址),寫入前先驗證連得到
取消 [[頁名]] 與 [[顯示文字|頁名]] 兩種同 wiki 寫法,不再分「同存取庫」與
「跨存取庫」兩條規則。那種寫法只在自己那個 wiki 內解析,寫錯不報錯,畫面上
看起來像普通文字或死連結,巡不到也修不了。

連結寫進頁面前先過 jsc-gitea 的 link-check.sh,結束碼 0 才寫。驗證一律走 API,
不看網頁狀態碼:私有存取庫的網頁網址對未登入請求一律回 404,拿狀態碼判會把
好連結判成壞的。認證失敗回 7,與死連結的 1 分開,免得金鑰一過期就把還在的頁
整批判死。
2026-09-02 14:27:18 +08:00

196 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# jsc-gitea — Gitea 操作
jsc 技能組的 gitea domain:Gitea API 的統一入口。所有 jsc 技能需要操作 gitea(wiki、repo、PR)時,一律經由本 domain 的工具或技能,不可自行拼 API 呼叫。
## 安裝、更新、移除
Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安裝 token 為 `jsc-gitea@jsc`。每個指令一行:
| CLI | 安裝 | 更新 | 移除 |
| --- | --- | --- | --- |
| claude | `claude plugin marketplace add https://gitea.jsc.idv.tw/plugins/meta.git && claude plugin install jsc-gitea@jsc` | `claude plugin marketplace update jsc && claude plugin update jsc-gitea@jsc` | `claude plugin uninstall jsc-gitea@jsc` |
| codex | `codex plugin marketplace add https://gitea.jsc.idv.tw/plugins/meta.git && codex plugin add jsc-gitea@jsc` | `codex plugin marketplace upgrade jsc` | `codex plugin remove jsc-gitea@jsc` |
| copilot | `copilot plugin marketplace add https://gitea.jsc.idv.tw/plugins/meta.git && copilot plugin install jsc-gitea@jsc` | `copilot plugin marketplace update jsc && copilot plugin update jsc-gitea@jsc` | `copilot plugin uninstall jsc-gitea@jsc` |
| antigravity | `git clone https://gitea.jsc.idv.tw/plugins/gitea.git ~/plugins/gitea && agy plugin install ~/plugins/gitea` | `git -C ~/plugins/gitea pull && agy plugin uninstall jsc-gitea && agy plugin install ~/plugins/gitea` | `agy plugin uninstall jsc-gitea` |
| kiro | `kiro-cli plugin marketplace add https://gitea.jsc.idv.tw/plugins/meta.git && kiro-cli plugin install jsc-gitea@jsc` | `kiro-cli plugin marketplace update jsc && kiro-cli plugin update jsc-gitea@jsc` | `kiro-cli plugin uninstall jsc-gitea@jsc` |
> antigravity 不支援 gitea URL 安裝,改用本地 clone 路徑。批次操作五個 CLI:使用 `/jsc-cli:deploy`。
> 舊入口 `plugins/jsc` 已移除,marketplace 正本移到 `plugins/meta`。marketplace 名稱仍是 `jsc`(取自 marketplace.json 的 `name` 欄位,與存取庫名無關),安裝 token 不變;已從舊入口安裝過的人先執行 `claude plugin marketplace remove jsc`,再依上表重新 add。
## 工具
`tools/gitea.sh`(POSIX shell + curl):
```
gitea.sh owners # 列出可讀取的 owner
gitea.sh repos <owner> # 列出 owner 的 repo 全名
gitea.sh default-branch <owner>/<repo>
gitea.sh clone-url <owner>/<repo>
gitea.sh hash-id <text> # 產生完整 40 碼大寫 SHA-1
gitea.sh wiki-repo <TYPE> # 解析頁面類型的 wiki 位置(TYPE = QUESTION / PLAN / ANALYZE / DELIVER / MAINTAIN / REPO / LOG / LEARN / ERROR / CHECK / REPORT / SKILLSET / TOOLING / MONITOR / CONTENTS)
# 所有 *_CONTENTS 頁一律走 CONTENTS,內容頁走自己的型別
gitea.sh wiki-list <owner>/<repo>
gitea.sh wiki-get <owner>/<repo> <page> # 不存在 exit 4
gitea.sh wiki-put <owner>/<repo> <page> <file> # 自動判斷新建或更新;會先要求確認
gitea.sh wiki-delete <owner>/<repo> <page> # 刪除 wiki 頁;與 wiki-put 走同一道確認,頁不存在 exit 4
gitea.sh wiki-url <owner>/<repo> <page> # 印出 wiki 頁絕對網址(取自 API 的 html_url)
# 連結一律寫成 [文字](絕對網址),網址就取自這裡
gitea.sh pr-create <owner>/<repo> <head> <base> <title> <body-file> # 會先要求確認
gitea.sh pr-status <owner>/<repo> <pr-index> # 印出 {state} {merged} {mergeable}
gitea.sh pr-get <owner>/<repo> <pr-index> # 印出 PR 的標題、base 分支與描述,供呼叫端比對有沒有差
# 前三行固定 title、base、body 三個標記,第 4 行起是描述原文
gitea.sh pr-of-branch <owner>/<repo> <branch> # 印出該分支目前開啟中的 PR(比對 head.ref)
# 第 1 行 number,接著 title、base、body 三個標記,第 5 行起是描述原文
# 結束碼 0=找到、2=用法錯誤、3=該分支沒有開啟中的 PR、4=API 失敗
# 「沒有 PR」用 3 不用 4:混用會把金鑰失效讀成沒開過 PR,接著開出重複的 PR
gitea.sh pr-edit <owner>/<repo> <pr-index> <title> <body-file> # 會先要求確認
# 更新 PR 的標題與描述;描述從檔案讀,裝得下多行
gitea.sh pr-comments <owner>/<repo> <pr-index> # 印出所有留言(issue 留言、審查評語、行內留言),第三欄帶 #id,依時間排序
gitea.sh comment-reply <owner>/<repo> <pr-index> <issue|review|inline> <comment-id> <body-file> # 會先要求確認
# 回覆本輪處理過的 PR 留言;inline 走 review comment reply,其餘補一則 PR 留言
gitea.sh pr-depend <owner>/<repo> <pr-index> <dep-owner>/<dep-repo> <dep-index> # 會先要求確認
# 把 PR 掛上前置 PR 依賴;依賴未關閉前 Gitea 會阻擋合併
gitea.sh repo-set <owner>/<repo> <description> [website] # 會先要求確認
gitea.sh markdown <file> # markdown 檔渲染成 HTML 片段(走 /markdown/raw)
gitea.sh api <METHOD> <path> [json-file]
# 全腳本共用結束碼: 0=成功、1=api 子命令請求失敗、2=用法錯誤
# 3=wiki-repo 沒設定或 pr-of-branch 查無 PR、4=找不到(404)與 PR 系列 API 失敗
# 5=wiki 頁沒有 html_url、7=金鑰失效或權限不足(401/403)、8=其他 API 失敗
# 7 與 8 一定要跟 4 分開:認證失敗若被讀成「頁面不存在」,
# 附加寫入就會變成整頁覆蓋,舊紀錄直接消失
hash-id <text> # 與 gitea.sh hash-id 相同
# 結束碼 0=成功、1=沒有 sha1sum 也沒有 shasum、2=沒給文字或給了空字串
page-name.sh regex | check <page> # 頁名樣式的唯一正本
# 合法頁名 {型別}_(CONTENTS|8 碼|H 加 7 碼|40 碼大寫十六進位)
# 8 碼與 H 加 7 碼留給尚未遷移的舊頁;舊演算法多數情況會加 H,兩種都要收
# 前綴只收十四種內容型別。CONTENTS 只解存取庫,沒有 CONTENTS_CONTENTS 這一頁
# 結束碼 0=合法、1=不合法、2=用法錯誤
wiki-contents.sh upsert <TYPE> <key-col> <key> <row-file> [template-file]
# 目錄頁的整列 upsert:解 CONTENTS 存取庫、讀舊頁、換掉鍵相同那一列或附加到表尾、整頁寫回
# key-col 是 1 起算的欄位序號,不是欄位名稱
# 用範本建新頁時剝掉分隔列之後的示範列,正式頁上不留佔位的死連結
# 結束碼 0=已更新或已新增、1=寫入失敗、2=用法錯誤、3=CONTENTS 存取庫未設定
# 4=頁不存在且沒給範本、7=金鑰失效或權限不足、8=其他 API 失敗
# 只有 4 才准建新頁;7 與 8 一律中止,不得當成「頁面不存在」
migrate-wiki.sh [--apply] [--key <候選鍵>]... # 把舊頁搬到新規則:目錄頁換存取庫、內容頁換頁名
# 只做正推配對,配不上的一律列成孤兒,不猜;不帶 --apply 只印對照表
# 寫目的地之前先讀:只有 4 才准寫,0 列成需人工確認且不覆蓋,7 與 8 中止
# 連結改寫只動被搬的頁;沒被搬的引用方另列一節,交給人改
# 結束碼 0=全部搬完、1=有頁搬移失敗、2=用法錯誤、3=有需人工處理的項目
repo-sync.sh <owner>/<repo> [target-dir] # 同步單一存取庫;印出 cloned、updated、dirty {分支} 或 failed {原因}
# 基準分支的優先序只在這支腳本裡;dirty 會把解析好的分支帶出來當 PR 的 base
check-wiki-rules.sh # 驗證 wiki repo 解析、hash-id 與頁名樣式規則
link-check.sh <網址>... # 連結寫進文件之前先驗證連得到;也吃標準輸入,一行一個
# 每個網址一行「{OK|DEAD|SKIP}<TAB>{網址}<TAB>{說明}」
# wiki 頁與議題轉成 API 查,其他 Gitea 網址帶金鑰 HEAD,外部網址不帶金鑰 HEAD
# Gitea 一律走 API:私有存取庫的網頁網址對未登入請求一律回 404
# 結束碼 0=全部連得到、1=有連不到、2=沒給網址、3=有 Gitea 網址但 GITEA_HOST 未設定
# 7=Gitea 認證失敗(401/403)
# 7 一定要與 1 分開:金鑰失效與「頁不存在」難分辨,混用會把還在的頁整批判成死連結
pr-watch.sh <owner>/<repo> <pr-index> [state-file]
# 盯著一支 PR,直到它合併或關閉,不自動逾時退場
# 退出碼 0 = 已合併或關閉、10 = 有新留言要接手、2 = 參數錯誤、3 = 查不到該 PR
# 已回報過的留言記在狀態檔,預設 $JSC_HOME/pr-watch/{owner}-{repo}-{index}.seen
```
`pr-watch.sh` 的退出碼 10 是設計重點:腳本只負責偵測,決策交回呼叫端。收到 10 就把印出來的留言丟進決策樹,處理完再重新盯一次。
議題與 HTML 產出:
```
gitea-link.sh parse <url> # 解析 wiki 或議題連結;不是這兩種就 exit 3(呼叫端據此中止)
issue.sh labels|label-ids|projects <owner>/<repo>
issue.sh title|body|labels-of <owner>/<repo> <index>
issue.sh show <owner>/<repo> <index> # 一次拿齊標題、標籤與正文,只打一次 API
# 四段固定格式:title、labels、body 標記,第 4 行起是正文
issue.sh create <owner>/<repo> <title> <body-file> [--labels <ids>] [--milestone <id>] # 會先要求確認
html-style.sh get|set|unset|list|layouts|styles # 種類對版型與風格的設定
html-style.sh key wiki <頁名> # 推導種類:取第一個底線前的字首
html-style.sh key issue <owner>/<repo> <編號> [--labels <名稱>[,<名稱>]]
# 推導種類:依序試每個標籤,第一個設定過的勝出,都沒有就回 ISSUE:DEFAULT
# 輸出一行「{種類}<TAB>{依據}」;結束碼 1=取不到標籤
html-render.sh --markdown <檔案> --title <標題> --out <輸出檔> [--layout] [--style] [--subtitle] [--source-url]
```
## 參考資料
- `references/wiki-links.md`:連結規則。規則 A:一律寫成 `[文字](絕對網址)`,網址取自 `wiki-url`,只有這一種寫法。規則 B:連結寫進文件之前先過 `link-check.sh`,結束碼 0 才寫入。
## HTML 範本
版型(`templates/html/layout/*.html`)決定內容怎麼排,風格(`templates/html/style/*.css`)決定看起來長怎樣。兩者自由搭配,六乘五共三十種。
| 版型 | 內容排法 |
| --- | --- |
| `report` | 左側目錄加章節內文,長文件用 |
| `slide` | 一個 `##` 一張投影片,鍵盤左右鍵翻頁 |
| `dashboard` | 每個 `##` 一張卡片並排 |
| `spec` | 表格表頭固定、程式碼區塊放大,API 文件用 |
| `timeline` | 每個 `##` 一個節點串成一條線 |
| `onepager` | 窄欄單頁,印出來剛好一頁 |
| 風格 | 視覺 |
| --- | --- |
| `minimal` | 白底細線、無襯線,資訊密度優先 |
| `corporate` | 深藍主色、表頭反白,正式對外 |
| `dark` | 深底亮字 |
| `print` | 襯線字、A4 邊界,列印或轉 PDF |
| `vivid` | 高彩度、圓角卡片、漸層標題 |
哪一種頁面套哪一組,由 `html-style.sh` 的設定決定:專案的 `./.jsc/html-styles` 優先,其次 `$JSC_HOME/html-styles.conf`,種類對不到就退 `DEFAULT`,再對不到才用內建的 `report`/`minimal`。設定的 key 是 `WIKI:{頁名前綴}`、`ISSUE:{標籤名}` 或 `DEFAULT`。
自訂範本:版型放進 `templates/html/layout/`,風格放進 `templates/html/style/`,檔案第一行寫一句繁中說明——那句話就是技能問使用者時顯示的選項說明。版型檔可用的佔位有 `{{TITLE}}`、`{{SUBTITLE}}`、`{{CONTENT}}`、`{{BASE}}`、`{{BASE_JS}}`、`{{STYLE}}`、`{{SOURCE}}`、`{{GENERATED}}`、`{{LAYOUT}}`、`{{STYLE_NAME}}`。
## Skills 目錄
呼叫方式:Claude / Antigravity `/jsc-gitea:{name}`;Codex `${name}`;Copilot / Kiro 描述需求自動觸發。
<!-- JSC-SKILLS:START -->
### `wiki`
Gitea wiki 頁讀寫的統一入口:依頁面類型(QUESTION / PLAN / ANALYZE / DELIVER / MAINTAIN / REPO / LOG / LEARN / ERROR / CHECK / REPORT / SKILLSET / TOOLING / MONITOR / CONTENTS)解析 wiki 所在的 `{owner}/{repo}`,先讀對應的 `JSC_WIKI_REPO_{TYPE}`,再退回 `JSC_WIKI_REPO`,不同類型不可互相代用。所有 `*_CONTENTS` 頁一律走 `CONTENTS` 這個型別,內容頁走自己的型別;目錄頁的整列 upsert 交給 `tools/wiki-contents.sh`。頁面內容以圖表優先(mermaid 圖、markdown 表格),純文字每節最多三句。
### `repo-sync`
存取庫批次同步:列出 owner → 使用者選擇 → 各存取庫併行(一個 repo 一個 sub agent)呼叫 `tools/repo-sync.sh` clone 或更新;回報 `dirty {分支}` 的存取庫交給 `jsc-git:pr`,base 直接用腳本帶出來的那個分支;PR 依 `jsc-meta/references/pr-report.md` 集中成表。
### `html-export`
把一頁 wiki 或一筆議題輸出成單一 HTML 檔:解析連結 → 判斷種類 → 查該種類的版型與風格 → 用 Gitea 自己的 markdown 渲染出圖。CSS 與腳本全部內嵌,檔案拿到哪裡都打得開。**沒有連結就直接中止**,不猜存取庫、不猜頁名、不猜議題編號。
### `html-style`
設定「哪一種 wiki 頁或議題,出 HTML 時用哪一種版型與風格」:六種版型與五種風格全部列給使用者選,再寫進專案的 `.jsc/html-styles` 或全域的 `$JSC_HOME/html-styles.conf`。`html-export` 讀的就是這份設定。
### `wiki-to-issue`
把一頁 wiki 轉成同一個存取庫的議題:讀頁面 → sub agent 起草標題與正文(開頭附來源連結)→ 從既有標籤挑合適的 → 關聯專案看板 → 建立議題。標籤只從存取庫既有的挑,不自己發明;站台沒有看板 API 時據實回報請使用者手動拖,不假裝關聯成功。**沒有連結就直接中止**。
<!-- JSC-SKILLS:END -->
## 環境變數
| 變數 | 用途 | 未設定時 |
| --- | --- | --- |
| `GITEA_HOST` | Gitea 站台(可省略 scheme,預設 https) | 詢問使用者 |
| `GITEA_TOKEN` | Gitea API token;缺少或遇 401/403 時自動退回 tea CLI 登入 token | 詢問使用者 |
| `JSC_WIKI_REPO_{TYPE}` | 各類型內容頁的 `{owner}/{repo}`;TYPE = QUESTION / PLAN / ANALYZE / DELIVER / MAINTAIN / REPO / LOG / LEARN / ERROR / CHECK / REPORT | 退回 `JSC_WIKI_REPO`,不做跨類型代用 |
| `JSC_WIKI_REPO_SKILLSET` | `SKILLSET_{HASH}`(技能組異動報告)的 `{owner}/{repo}` | 退回 `JSC_WIKI_REPO`,不做跨類型代用 |
| `JSC_WIKI_REPO_TOOLING` | `TOOLING_{HASH}`(技能盤點)的 `{owner}/{repo}` | 退回 `JSC_WIKI_REPO`,不做跨類型代用 |
| `JSC_WIKI_REPO_MONITOR` | `MONITOR_{HASH}`(助理巡檢監控)的 `{owner}/{repo}` | 退回 `JSC_WIKI_REPO`,不做跨類型代用 |
| `JSC_WIKI_REPO_CONTENTS` | 全部目錄頁(各型別的 `*_CONTENTS`)共用的 `{owner}/{repo}` | 退回 `JSC_WIKI_REPO`,不退回各型別的變數 |
| `JSC_WIKI_REPO` | 共用預設的 wiki `{owner}/{repo}` | 詢問使用者 |
| `JSC_HOME` | `pr-watch.sh` 狀態檔的根目錄 | 預設 `~/.jsc` |
| `JSC_PR_WATCH_INTERVAL` | `pr-watch.sh` 的輪詢間隔秒數(正整數) | 預設 60 |
## Hash 規則
`{HASH}` 一律由 `tools/hash-id` 產生:完整 40 碼大寫十六進位,不截短、不加前綴。頁名合不合規則交給 `tools/page-name.sh check` 判,不要另外寫一份樣式。各頁型的雜湊來源,唯一來源是 `jsc-meta` 的 [`references/guidelines.md`](https://gitea.jsc.idv.tw/plugins/meta/src/branch/master/references/guidelines.md)「Wiki 頁命名總表」,這裡不再複述一份。
## 相關 domain
- [`jsc-ask`](https://gitea.jsc.idv.tw/plugins/ask):wiki 位置未設定時的決策樹詢問
- [`jsc-git`](https://gitea.jsc.idv.tw/plugins/git):repo-sync 的 commit 與 PR