From 003593c73a42c7d7b3b99f1ba3e2129cceee3690 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Fri, 4 Sep 2026 10:51:31 +0800 Subject: [PATCH] =?UTF-8?q?fix(pr):=20=E8=A1=8C=E7=82=BA=E6=B8=85=E5=96=AE?= =?UTF-8?q?=E9=82=A3=E4=B8=89=E6=94=AF=E8=85=B3=E6=9C=AC=E7=9A=84=E8=B7=AF?= =?UTF-8?q?=E5=BE=91=E4=B9=9F=E8=A3=9C=E4=B8=8A=E5=A4=96=E6=8E=9B=E7=9B=AE?= =?UTF-8?q?=E9=8C=84=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 上一筆只改了技能本文,行為清單漏掉。新的路徑檢核腳本一跑就指出來——關鍵 步驟與外部呼叫兩欄還留著八處不帶前綴的寫法,而那兩欄正是別人拿來確認這支 技能會呼叫誰的地方。 順手改掉技能本文開頭那一句的舉例方式。原本把不帶前綴的錯誤寫法原樣寫出來 當例子,那一行自己就會被路徑檢核當成一處待改。改成描述後果、不照抄那個 寫法,順便講得更準:省掉外掛目錄名之後,路徑會相對於當下的工作目錄解, 可能解到自己這個存取庫裡對的那一支、可能解到別的 domain 底下另一支,也可能 什麼都解不到。中間那一種最糟,它會跑起來,跑的是另一支腳本。 Co-Authored-By: Claude Opus 5 --- references/behaviors.md | 6 +++--- skills/pr/SKILL.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/references/behaviors.md b/references/behaviors.md index b4a5645..437b44a 100644 --- a/references/behaviors.md +++ b/references/behaviors.md @@ -17,7 +17,7 @@ | 項目 | 內容 | | --- | --- | | 觸發時機 | 工作做完要送審時叫用。既有 PR 在新 commit 之後要重新同步時也叫用。只想提交不想推送時不叫用這一支,改叫 `jsc-git:commit`。 | -| 關鍵步驟 | 先用 `tools/base-branch.sh {呼叫方基底}` 驗證呼叫方傳進來的基底、叫 `jsc-git:commit` 提交全部變更、用 `tools/pick-type.sh` 從 commit 標題選出型別、用 `tools/slugify.sh` 組出階梯狀目標分支名、用 `tools/base-branch.sh --derive {目標分支}` 推導基底並和呼叫方基底比對、以 `git checkout -b {目標分支} origin/{基底分支}` 建分支並 `git push -u origin` 推上去、用 `gitea.sh pr-of-branch` 查一次開啟中的 PR、沒有就用 `gitea.sh pr-create` 開新 PR 並用 `gitea.sh pr-depend` 掛前置依賴、已經有就只更新標題、描述、前置依賴三項裡不同的那幾項、回覆已處理的 PR 意見、回報,最後跑 `jsc-hooks/tools/report-status.sh skill-end jsc-git:pr {status} {結束碼} {detail}` 記下本輪結果,腳本不在這台機器上就安靜跳過。PR 標題寫一句繁體中文摘要,說明這條 PR 做了什麼,不套用分支名;校準既有 PR 時只問標題還描述不描述得了目前的內容,不拿分支名比對。 | -| 外部呼叫 | `tools/base-branch.sh`、`tools/pick-type.sh`、`tools/slugify.sh`、`templates/pr-description.md`、`jsc-git:commit`、`jsc-gitea/tools/gitea.sh` 的 `pr-of-branch`、`pr-create`、`pr-edit`、`pr-depend`、`comment-reply`、`jsc-gitea:wiki`(讀 PLAN 頁與 ANALYZE 頁)、`jsc-ask:ask`(基底衝突與分支不存在時發問)、`jsc-meta/references/guidelines.md` 的「PR 分支階梯」、`jsc-meta/references/pr-report.md`、`git checkout`、`git cherry-pick`、`git push`、`git ls-remote`。分支標題摘要與描述草稿交給 sub agent 處理。 | +| 關鍵步驟 | 先用 `jsc-git/tools/base-branch.sh {呼叫方基底}` 驗證呼叫方傳進來的基底、叫 `jsc-git:commit` 提交全部變更、用 `jsc-git/tools/pick-type.sh` 從 commit 標題選出型別、用 `jsc-git/tools/slugify.sh` 組出階梯狀目標分支名、用 `jsc-git/tools/base-branch.sh --derive {目標分支}` 推導基底並和呼叫方基底比對、以 `git checkout -b {目標分支} origin/{基底分支}` 建分支並 `git push -u origin` 推上去、用 `gitea.sh pr-of-branch` 查一次開啟中的 PR、沒有就用 `gitea.sh pr-create` 開新 PR 並用 `gitea.sh pr-depend` 掛前置依賴、已經有就只更新標題、描述、前置依賴三項裡不同的那幾項、回覆已處理的 PR 意見、回報,最後跑 `jsc-hooks/tools/report-status.sh skill-end jsc-git:pr {status} {結束碼} {detail}` 記下本輪結果,腳本不在這台機器上就安靜跳過。PR 標題寫一句繁體中文摘要,說明這條 PR 做了什麼,不套用分支名;校準既有 PR 時只問標題還描述不描述得了目前的內容,不拿分支名比對。 | +| 外部呼叫 | `jsc-git/tools/base-branch.sh`、`jsc-git/tools/pick-type.sh`、`jsc-git/tools/slugify.sh`、`templates/pr-description.md`、`jsc-git:commit`、`jsc-gitea/tools/gitea.sh` 的 `pr-of-branch`、`pr-create`、`pr-edit`、`pr-depend`、`comment-reply`、`jsc-gitea:wiki`(讀 PLAN 頁與 ANALYZE 頁)、`jsc-ask:ask`(基底衝突與分支不存在時發問)、`jsc-meta/references/guidelines.md` 的「PR 分支階梯」、`jsc-meta/references/pr-report.md`、`git checkout`、`git cherry-pick`、`git push`、`git ls-remote`。分支標題摘要與描述草稿交給 sub agent 處理。 | | 完成條件 | 握有一個 PR 網址,送出的標題是一句繁體中文摘要,不是分支名。前置依賴已經處理完:`pr-depend` 印出 `OK` 行,或 PR 標題冠上 `WIP:` 且描述指名前置 PR,或描述寫「無」前置 PR 並在回報裡說明。既有 PR 的三個校準項目各自回報為相符或已更新,標題那一項說明拿什麼內容去判定,送出的 API 呼叫數等於不同的項目數。每一則已處理的意見握有回覆連結或記下失敗理由。回報含 `{owner}/{repo}`、PR 編號、PR 網址、PR 摘要四欄,並指名基底分支、目標分支、更新過的校準項目、自動建立的功能主幹、沒回覆到的意見。收尾一定要寫一筆 `skill-end` 狀態事件:拿到 PR 網址且前置依賴處理完是 `ok`,`base-branch.sh` 回 3、4、7、8、9 讓分支還沒推上去就停住是 `blocked`,`pr-depend` 回 4 退成 `WIP:` 或有意見沒回覆到是 `degraded`,`pick-type.sh` 回 3、推送失敗、`pr-create` 回 4、`pr-edit` 回非零是 `failed`,`pick-type.sh` 回 2 代表沒有可提交的變更、沒有 PR 好開,是 `aborted` 不是 `failed`,使用者在確認關卡喊停也是 `aborted`。 | -| 可驗證跡象 | origin 上多出目標分支的 ref,`git ls-remote --heads origin` 查得到。Gitea 上多出一條 PR,標題是一句繁體中文摘要、分支名仍是 ASCII,兩者不一樣。既有 PR 的標題與描述只在內容變了才被 `pr-edit` 改過,依賴被 `pr-depend` 掛上。PR 描述照 `templates/pr-description.md` 生成,各節不留空。功能主幹不在 origin 上時,`tools/base-branch.sh --derive` 會自動從 develop 建出 `{類型}/{功能}/main` 並推上 origin。本地 git 歷史含 `jsc-git:commit` 建立的 commit,目前分支切到目標分支。PR 意見的回覆留在 Gitea 那幾則意見底下。描述檔草稿寫在暫存檔。這一支不寫 wiki 頁,只讀 PLAN 頁與 ANALYZE 頁。跑完 `$JSC_HOME/usage/events.jsonl` 會多一筆 `{kind:skill,phase:end}` 事件,`name` 欄是 `jsc-git:pr`,`status` 與 `exit` 兩欄對得上上一列講的判準;沒有可提交的變更那一輪,事件上是 `aborted` 加結束碼 2,和開出 PR 的那一輪一眼分得開;`jsc-hooks` 不在這台機器上時沒有這一筆,技能本身照樣跑完。 | +| 可驗證跡象 | origin 上多出目標分支的 ref,`git ls-remote --heads origin` 查得到。Gitea 上多出一條 PR,標題是一句繁體中文摘要、分支名仍是 ASCII,兩者不一樣。既有 PR 的標題與描述只在內容變了才被 `pr-edit` 改過,依賴被 `pr-depend` 掛上。PR 描述照 `templates/pr-description.md` 生成,各節不留空。功能主幹不在 origin 上時,`jsc-git/tools/base-branch.sh --derive` 會自動從 develop 建出 `{類型}/{功能}/main` 並推上 origin。本地 git 歷史含 `jsc-git:commit` 建立的 commit,目前分支切到目標分支。PR 意見的回覆留在 Gitea 那幾則意見底下。描述檔草稿寫在暫存檔。這一支不寫 wiki 頁,只讀 PLAN 頁與 ANALYZE 頁。跑完 `$JSC_HOME/usage/events.jsonl` 會多一筆 `{kind:skill,phase:end}` 事件,`name` 欄是 `jsc-git:pr`,`status` 與 `exit` 兩欄對得上上一列講的判準;沒有可提交的變更那一輪,事件上是 `aborted` 加結束碼 2,和開出 PR 的那一輪一眼分得開;`jsc-hooks` 不在這台機器上時沒有這一筆,技能本身照樣跑完。 | diff --git a/skills/pr/SKILL.md b/skills/pr/SKILL.md index ed01738..e1871f8 100644 --- a/skills/pr/SKILL.md +++ b/skills/pr/SKILL.md @@ -7,7 +7,7 @@ description: Commit all changes via jsc-git:commit, name a ladder-shaped target The ladder rules live in one place only: section 「PR 分支階梯」 of `jsc-meta/references/guidelines.md`. `jsc-git/tools/base-branch.sh --derive` is the running implementation of that section. Read the rung a branch belongs to there; never hand-pick a base, and never restate the ladder table in this file. -Every script path in this file starts with its plugin's own directory name — `jsc-git/tools/…` for this plugin's, `jsc-gitea/tools/…` and `jsc-hooks/tools/…` for the others — and is resolved against the tool root the caller supplies, never against this skill's own directory. These three scripts sit at the plugin root, not under `skills/pr/`, so a bare `tools/base-branch.sh` resolves to a path that does not exist and exits 127. That failure is worse than it looks: step 4 says never hand-pick a base, and an agent that cannot run the deriver is one step away from picking one anyway, which turns a wrong path into a PR opened against the wrong rung. +Every script path in this file starts with its plugin's own directory name — `jsc-git/tools/…` for this plugin's, `jsc-gitea/tools/…` and `jsc-hooks/tools/…` for the others — and is resolved against the tool root the caller supplies, never against this skill's own directory. These three scripts sit at the plugin root, not under `skills/pr/`, so dropping the plugin directory name leaves a path that resolves against whatever the current directory happens to be — the right script inside this repo, a different domain's script outside it, or nothing at all and exit 127. That failure is worse than it looks: step 4 says never hand-pick a base, and an agent that cannot run the deriver is one step away from picking one anyway, which turns a wrong path into a PR opened against the wrong rung. ## Steps