refactor(code): 接上 shared 共用規範,去除重抄段落並補模型檢查串接

依 todo.md 執行的規範治理專案:action-composite/action-docker/action-node/
image/issues/nuget/review-resolve/sync/target 九個 skill 改為引用
shared 新增的共用 spec(conventional-commit、pull-request、git-push、
git-safety 分支選擇、issue-read、todo-list、ask-user、action-scaffold、
node-src-layout、skill-invocation),移除大量重抄內容(review-resolve/
target 光是 commit/PR/push 三塊就精簡約 175 行);target/issues 補上讀到
帶 model: frontmatter 清單檔時依 /jsc-shared:spec-model 做模型檢查的規則。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 06:04:18 +00:00
co-authored by Claude Sonnet 5
parent 9d8ac26a3b
commit 85a4128f5e
14 changed files with 215 additions and 671 deletions
+30 -79
View File
@@ -19,15 +19,11 @@ argument-hint: "[--schedule on|off] [--run] [--project-dir <專案根目錄>] [-
---
## 共用規範(shared plugin,必要前置)
## 共用規範(必要前置)
執行本 skill 前,先以 Skill 工具載入下列共用規範並全程遵守;**任一載入不到(shared plugin 未安裝)時,先詢問使用者是否安裝 shared plugin(`https://gitea.jsc.idv.tw/plugins/shared.git`),使用者不安裝則直接中斷本 skill**,不得只憑下方一行摘要繼續執行:
- `/jsc-shared:spec-output`:繁體中文(台灣用語)、UTF-8(不含 BOM)無亂碼(含 `TARGET.md` 回寫、commit 訊息、PR 標題/描述)、表格呈現。
- `/jsc-shared:spec-execution`:自動執行原則(必要決策才中斷)、不臆測/需人工確認。
- `/jsc-shared:spec-git-safety`:不破壞既有工作(絕不 `reset --hard`/`clean`)、`pull --ff-only`、保守解衝突、新分支不覆蓋既有分支。
- `/jsc-shared:spec-gitea`:`GITEA_TOKEN` 機密保護(不 echo、遮蔽 `***`)、API body 以 UTF-8 JSON 檔帶入。
- `/jsc-shared:spec-time-log`:Asia/Taipei `yyyy/MM/dd HH:mm:ss` 時間格式、`[時間][階段][等級]: 訊息` log 格式。
先載入 `/jsc-shared:spec-preflight` 並依其流程處理;載入不到即代表 shared plugin 未安裝,
依該 spec 詢問使用者是否安裝 `https://gitea.jsc.idv.tw/plugins/shared.git`,不安裝則中斷本 skill。
本 skill 需要的規範:`spec-output`、`spec-execution`、`spec-git-safety`、`spec-gitea`、`spec-time-log`、`spec-todo-list`、`spec-conventional-commit`、`spec-git-push`、`spec-pull-request`、`spec-skill-invocation`、`spec-model`
本 skill 特有補充:
@@ -45,7 +41,7 @@ argument-hint: "[--schedule on|off] [--run] [--project-dir <專案根目錄>] [-
- `--run`:立即執行一次 `TARGET.md`(排程條目帶的就是這個)。
- `--project-dir <專案根目錄>`:目標專案根目錄,**省略時取目前工作目錄**(會先 `git rev-parse --show-toplevel` 正規化成 repo 根)。`TARGET.md` 固定讀**專案根目錄**的那一份。
- `--cli <claude|codex|agy|opencode|copilot>`:排程條目要用哪個助理的 headless 指令。省略時用**目前正在執行本 skill 的助理**;判斷不出來且未帶此參數 → 詢問,不猜測。
- `--base <PR 目標分支>`:PR 的目標分支。**省略時自動取遠端預設分支**(見 F1),取不到才詢問。
- `--base <PR 目標分支>`:PR 的目標分支。**省略時自動取遠端預設分支**(見階段 F),取不到才詢問。
- `--no-pr`:執行到 push 為止,不開 PR。
- `--yes`:全自動,不做確認式詢問(必要決策仍會中斷)。
@@ -66,15 +62,16 @@ argument-hint: "[--schedule on|off] [--run] [--project-dir <專案根目錄>] [-
- [x] 移除已停用的舊設定檔(2026/08/02 23:41:07 完成)
```
checklist 語法、已完成略過不重做、子項目連動、標題/說明文字原樣保留、禁止憑空編造等格式規則依 `/jsc-shared:spec-todo-list` 執行。
本 skill 特有:
| 規則 | 說明 |
| --- | --- |
| 待辦 | `- [ ]` 未勾選的項目,**由上而下**依序處理 |
| 已完成 | `- [x]` 直接略過,不重做 |
| 子項目 | 縮排的 `- [ ]` 視為上層項目的子步驟,隨上層一起處理;子項目全部完成才勾選上層 |
| 標題/說明文字 | 原樣保留,只當作項目的背景脈絡,不改寫 |
| 待辦 | `- [ ]` 未勾選的項目,**由上而下**依檔案既有順序處理(與 `spec-todo-list` 建立議題 TODO 時「依影響範圍排序」的情境不同,此處沿用 `TARGET.md` 本身的行順序) |
| 檔案不存在 | `--run` 視為「無待辦」正常結束(不建檔、不報錯);`--schedule on` 則提醒尚無 `TARGET.md`,非 `--yes` 時詢問是否仍要建立排程 |
完成一項後就地改成 `- [x]`,並在該行**行尾**補上 `(<yyyy/MM/dd HH:mm:ss> 完成)`(Asia/Taipei)。無法安全完成的項目**保持未勾選**,並在該行下方以縮排補一行 `> ⏭️ 待人工處理:<原因>`(已有同樣註記則更新而非重複新增)。
完成一項後就地改成 `- [x]`,並在該行**行尾**補上 `(<yyyy/MM/dd HH:mm:ss> 完成)`(Asia/Taipei,時間格式依 `/jsc-shared:spec-time-log`)。無法安全完成的項目**保持未勾選**,並在該行下方以縮排補一行 `> ⏭️ 待人工處理:<原因>`(已有同樣註記則更新而非重複新增)。
---
@@ -189,32 +186,22 @@ git status --porcelain
git rev-parse --abbrev-ref HEAD
```
- **工作區有未提交變更** → **停止**並回報(排程情境寫入 log)。理由:本 skill 結尾會分類提交所有變更,混入使用者未完成的工作會把它一起提交上去。依 `/jsc-shared:spec-git-safety`,**不得** stash、`reset --hard` 或 `clean` 來清場。
- **工作區有未提交變更** → **停止**並回報(排程情境寫入 log)。理由:本 skill 結尾會分類提交所有變更,混入使用者未完成的工作會把它一起提交上去。依 `/jsc-shared:spec-git-safety`「不破壞既有工作」,不得 stash、`reset --hard` 或 `clean` 來清場。
- **detached HEAD** → 停止並回報。
### A2. Fetch 與判定遠端預設分支
```bash
git fetch --all --prune
git symbolic-ref --quiet refs/remotes/origin/HEAD # → refs/remotes/origin/<預設分支>
```
取不到時退而用 `git remote show origin`(找 `HEAD branch:` 那行);`--base` 有帶則直接採用。兩者都不成立 → 停止並詢問,不臆測 `master`/`main`。
依 `/jsc-shared:spec-git-safety`「工作分支選擇」判定遠端預設分支(`git symbolic-ref refs/remotes/origin/HEAD` → 取不到退而 `git remote show origin` → 兩者皆無則停止詢問,不臆測 `master`/`main`)。**本 skill 特有**:帶 `--base` 時直接採用 `--base` 的值,不再另行判定。
### A3. 切到 `develop`(不存在就從預設分支建立)
```bash
if git rev-parse --verify --quiet origin/develop >/dev/null; then
git switch develop 2>/dev/null || git switch -c develop --track origin/develop
git pull --ff-only
else
git switch -c develop "origin/<預設分支>" # 遠端沒有 develop → 從預設分支開一條新的
fi
```
依 `/jsc-shared:spec-git-safety`「develop → master 後備分支」與「工作分支選擇」處理:`origin/develop` 存在則切換並 `git pull --ff-only`(分岔失敗 → 停止並回報,不做 merge/rebase 猜測);不存在則從 A2 判定出的遠端預設分支建立 `develop`。
- `pull --ff-only` 失敗(分岔)→ 停止並回報,交由使用者處理,不做 merge/rebase 猜測。
- 本地已有 `develop` 但遠端沒有 → 沿用本地那條,**不覆蓋、不重建**;並在回報中說明它還沒推上遠端。
- 新建 develop 屬不可忽略的狀態變更,必須在回報與 log 中明講「遠端沒有 develop,已從 `<預設分支>` 建立」。
本 skill 特有:**本地已有 `develop` 但遠端沒有** → 沿用本地那條,**不覆蓋、不重建**,並在回報中說明它還沒推上遠端(`git switch develop 2>/dev/null || git switch -c develop --track origin/develop` 的寫法即可自然落在此情形)。新建 `develop` 屬不可忽略的狀態變更,必須在回報與 log 中明講「遠端沒有 develop,已從 `<預設分支>` 建立」。
---
@@ -228,6 +215,8 @@ fi
| # | 項目 | 子項目數 | 備註 |
| --- | --- | --- | --- |
若 `TARGET.md` 帶有 `model:` frontmatter,依 `/jsc-shared:spec-model` 的『讀到帶 `model:` frontmatter 的清單檔時的檢查義務』先做模型檢查。
---
## 階段 C:逐項實作並回寫 `TARGET.md`
@@ -246,77 +235,37 @@ fi
## 階段 D:分類提交
1. 盤點**所有**變更(含未追蹤檔):
依 `/jsc-shared:spec-conventional-commit` 執行:以 `git status --porcelain=v1 -uall` 完整盤點所有變更(含未追蹤檔)、依實際異動內容歸入 9 種 commit 類型(每個 type 各一個 commit,訊息格式 `type(範圍): 一句總結`,範圍不得重述 type 本身)、逐組精準 `git add -- <該組檔案...>` 後分別 commit(不用 `git add -A`)。
```bash
git status --porcelain=v1 -uall
```
本 skill 特有:
2. 依實際異動內容歸入 conventional commit 類型(`feat`/`fix`/`docs`/`style`/`refactor`/`perf`/`test`/`chore`/`revert`),**每個 type 各一個 commit**。
3. commit 訊息格式 `type(範圍): 一句總結`,**括號內是實際異動的功能/模組名**,不是重述 type:
- ✅ `feat(使用者服務): 補上帳號建立與停用的單元測試`、`docs(README): 更新安裝章節的 CLI 指令`
- ❌ `feat(新增功能)`、`docs(文件)`
- `TARGET.md` 本身的勾選更新歸 `chore`,訊息用 `chore(TARGET): 更新每日待辦完成狀態`。
4. 逐組精準 `git add -- <該組檔案...>` 後 commit,不用 `git add -A` 一次混提。
5. 無任何變更(例如所有項目都待人工處理,只有 `TARGET.md` 的註記異動)→ 仍照常提交 `TARGET.md` 的異動;連 `TARGET.md` 都沒變則跳過 D、E、F,直接進入總結。
> 分類與訊息規則與 `/jsc-code:review-resolve` 階段 C 一致,細節可參照該 skill。
- `TARGET.md` 本身的勾選更新歸 `chore`,訊息固定用 `chore(TARGET): 更新每日待辦完成狀態`。
- 無任何變更(例如所有項目都待人工處理,只有 `TARGET.md` 的註記異動)→ 仍照常提交 `TARGET.md` 的異動;連 `TARGET.md` 都沒變則跳過 D、E、F,直接進入總結。
---
## 階段 E:Push `develop`
依 `/jsc-shared:spec-git-push` 的三段式流程(認證管理器 → token push → 詢問使用者,前者失敗才換下一個,token 全程遮蔽且不寫進 remote 設定)推送 `develop`。推送前先確認是否有領先遠端的 commit:
```bash
git log --oneline "origin/develop..develop" 2>/dev/null # 領先遠端的 commit;遠端無 develop 時視為全部要推
```
無 commit 可推 → 跳過 push,直接進入階段 F(既有遠端分支仍可開 PR)。否則依序嘗試,前者失敗才換下一個:
1. **認證管理器**:`git push -u origin develop`
2. **token**:從環境變數帶入,指令與輸出**全程遮蔽 token、不寫進 remote 設定**:
```bash
git push "https://oauth2:${GITEA_TOKEN}@<host>/<owner>/<repo>.git" develop
```
3. **都失敗** → 停止並回報失敗原因(先遮蔽 token)。排程情境寫入 log,等使用者處理,不猜測其他憑證。
本 skill 特有:無 commit 可推 → 跳過 push,直接進入階段 F(既有遠端分支仍可開 PR);三段皆失敗 → 停止並回報失敗原因(先遮蔽 token),排程情境寫入 log,等使用者處理,不猜測其他憑證。
---
## 階段 F:對預設分支發 PR(`--no-pr` 時略過)
### F1. 目標分支
依 `/jsc-shared:spec-pull-request` 執行:目標分支不臆測 → 解析 origin 座標(host/owner/repo)→ 先查有沒有相同 head=`develop` → base=`<目標分支>` 的 open PR,有則沿用不重開(今天新推的 commit 會自動出現在該 PR,可視情況補一則今日進度留言)→ 沒有才以 UTF-8 JSON 檔帶入 body 建立新 PR(換行用實際換行,不可送出字面 `\n`)→ 失敗回報 API 錯誤訊息(先依 `/jsc-shared:spec-gitea` 遮蔽 token)→ 完成後提醒清除對話內文。
`--base` 有帶則用它,否則用 A2 判定出的**遠端預設分支**。若預設分支就是 `develop`(等於 head=base)→ 不開 PR,回報原因即可。
### F2. 先查有沒有現成的 open PR(每天跑,不可重複開)
```bash
curl -sS -H "Authorization: token ${GITEA_TOKEN}" \
"https://<host>/api/v1/repos/<owner>/<repo>/pulls?state=open&base=<預設分支>"
```
已存在 `head=develop` → `base=<預設分支>` 的 open PR → **沿用它**(今天新推的 commit 會自動出現在該 PR),回報既有 PR 連結,並視情況在該 PR 補一則今日進度留言;**不重複建立**。
### F3. 建立 PR
repo 座標由 `git remote get-url origin` 解析(host/owner/repo)。body 以 UTF-8 JSON 檔帶入,換行用實際換行、不可送出字面 `\n`:
```bash
curl -sS -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"https://<host>/api/v1/repos/<owner>/<repo>/pulls" \
--data @body.json
```
本 skill 特有:
- **目標分支**:`--base` 有帶則用它,否則用 A2 判定出的遠端預設分支;若該目標分支就是 `develop`(等於 head=base)→ 不開 PR,回報原因即可。
- **標題**:`chore(TARGET): <yyyy/MM/dd> 每日待辦`(有明確主軸時可改成該主軸的一句總結)。
- **描述**:本次完成的項目清單(✅/⏭️ 各自列出+待人工處理原因)、變更摘要與影響範圍、本次的 commit 一覽。
- 失敗 → 回報 API 錯誤訊息(先遮蔽 token)。常見原因:目標分支不存在、已有相同 head→base 的 PR(回到 F2 沿用)、token 權限不足。
### F4. 收尾
push/API 過程可能讓 token 殘留在對話內文;**互動情境**完成後提醒使用者清除對話(Claude Code 用 `/clear`)。排程情境只寫 log,不輸出 token。
- **收尾**:push/API 過程可能讓 token 殘留在對話內文;**互動情境**完成後提醒使用者清除對話(Claude Code 用 `/clear`)。**排程情境**沒有互動對話,只寫 log,不輸出 token。
---
@@ -335,6 +284,8 @@ push/API 過程可能讓 token 殘留在對話內文;**互動情境**完成
## 呼叫方式
依 `/jsc-shared:spec-skill-invocation` 的統一呼叫方式,本 skill 的實際參數格式與範例:
| 助理 | 呼叫 |
| --- | --- |
| Claude Code / Antigravity | `/jsc-code:target --schedule on`、`/jsc-code:target --schedule off`、`/jsc-code:target --run --yes`、`/jsc-code:target --schedule on --run --project-dir ~/work/app` |