feat(git): PR 分支階梯推導與既有 PR 校準 #11

Merged
admin merged 4 commits from feat/sdlc-flow-rules/pr-ladder-and-sync into feat/sdlc-flow-rules/main 2026-08-27 03:26:23 +00:00
Member

摘要

  • 需求描述:落實「SDLC 執行流程」規則群裡由 jsc-git 負責的兩條。其一,PR 分支階梯禁止越級:{類型}/{子功能} → {類型}/{功能}/main → develop → master,fix 走 fix/{修改} → develop → master。其二,分支已有 PR 時,每次認可後比對標題、描述、上層 PR 依賴三項,有差才更新,不重開第二支 PR。決策紀錄在 wiki 存取庫 knowledges/QUESTION 的 QUESTION_FB8DF0B5,2026-08-27 那一節。
  • 計畫名稱:無
  • 計畫頁:無
  • 分析頁:無

變更內容

檔案 為什麼改
tools/base-branch.sh base 原本靠呼叫端自己挑,挑錯就把一個子功能直接併進 develop。新增 --derive 把階梯推導寫進程式,並新增退出碼 7、8、9 分辨「推不出」「基底不在遠端」「自動建立失敗」三種收場
skills/pr/SKILL.md 目標分支改成階梯形狀命名,base 改由 --derive 推導;新增「查有沒有開啟中的 PR」與「校準既有 PR」兩步,把重開 PR 改成只更新有差的項目
skills/commit/SKILL.md 認可完成後,目前分支若已有開啟中的 PR,就把 PR 編號交給 pr 校準,讓 PR 標題與描述跟著新認可走
README.md 新增「PR 階梯」一節,工具表與兩段技能說明同步改寫
plugin.json、.claude-plugin/plugin.json、.codex-plugin/plugin.json 行為變更要 bump 版本;三份同步升到 0.0.8

設計重點

  • 推導只認分支名,不猜。{子功能} 可以多層,推導一律把最後一段換成 main;推不出唯一合法基底就回 7 中止,由呼叫端問使用者。不退回 develop——退回 develop 正是階梯要擋的那件事。
  • 呼叫方傳入的 base 仍然照收,但要與推導結果一致。不一致就當成越級擋下,說明正確階梯再問使用者,不會悄悄改 PR 目標。
  • 功能主幹不在 origin 時自動補一條:直接把 origin/develop 推成新分支,不動本機工作區,省下切分支再切回來的來回,並把建立了哪一條分支印到 stderr,讓收尾回報講得出來。
  • 分支名只收 ASCII 小寫、數字、連字號與斜線。多層分支名用 slugify.sh 連叫兩次組出來,第一次的結果當第二次的型別參數。
  • 校準三項各自獨立:標題或描述有差走 pr-edit(一次帶兩項),依賴有差走 pr-depend,三項都相同就什麼都不做。每一次多餘的編修都會通知所有審查者,安靜才是對的結果。
  • 既有的呼叫方模式(不帶旗標)一字未改:傳入空字串仍然回 6,不會被當成「沒傳」而退回 develop。

測試結果

  • sh -n tools/base-branch.sh:語法檢查通過。
  • 在一個隔離的暫存存取庫(本機 bare 存取庫當 origin,只有 develop)跑過 --derive 的八種情境,結果全部符合預期:
    • feat/order-export/report-filter → 自動建立 feat/order-export/main 並推上 origin,印出該基底,退出碼 0;
    • feat/order-export/main → develop,fix/order-crash → develop,兩者退出碼 0;
    • feat/order-export(少了功能層)、foo/a/b(型別不在階梯表)、master(已在頂端)、feat/訂單(含非 ASCII)四種都回 7 並印繁中原因;
    • develop 在沒有 master 的存取庫回 8,訊息指出基底不在 origin 且不是可自動建立的功能主幹。
  • 參數護欄:--derive a b c 回 2 並印用法,空字串回 6。
  • tools/slugify.sh feat "order export" → feat/order-export,再以它當型別跑 tools/slugify.sh feat/order-export "report filter" → feat/order-export/report-filter,多層分支名組得出來。
  • ste100-lint.sh .:全庫零命中。
  • 三份 manifest 以 JSON 解析器讀過,格式正確且版本一致為 0.0.8。
  • 未測:pr 與 commit 兩支技能對真實 Gitea 的校準往返,需要可連線的主機與一支開啟中的 PR,本次在沒有 Gitea 存取的環境進行。

前置 Push Request

## 摘要 - 需求描述:落實「SDLC 執行流程」規則群裡由 `jsc-git` 負責的兩條。其一,PR 分支階梯禁止越級:`{類型}/{子功能}` → `{類型}/{功能}/main` → `develop` → `master`,`fix` 走 `fix/{修改}` → `develop` → `master`。其二,分支已有 PR 時,每次認可後比對標題、描述、上層 PR 依賴三項,有差才更新,不重開第二支 PR。決策紀錄在 wiki 存取庫 `knowledges/QUESTION` 的 `QUESTION_FB8DF0B5`,2026-08-27 那一節。 - 計畫名稱:無 - 計畫頁:無 - 分析頁:無 ## 變更內容 | 檔案 | 為什麼改 | | --- | --- | | `tools/base-branch.sh` | base 原本靠呼叫端自己挑,挑錯就把一個子功能直接併進 `develop`。新增 `--derive` 把階梯推導寫進程式,並新增退出碼 `7`、`8`、`9` 分辨「推不出」「基底不在遠端」「自動建立失敗」三種收場 | | `skills/pr/SKILL.md` | 目標分支改成階梯形狀命名,base 改由 `--derive` 推導;新增「查有沒有開啟中的 PR」與「校準既有 PR」兩步,把重開 PR 改成只更新有差的項目 | | `skills/commit/SKILL.md` | 認可完成後,目前分支若已有開啟中的 PR,就把 PR 編號交給 `pr` 校準,讓 PR 標題與描述跟著新認可走 | | `README.md` | 新增「PR 階梯」一節,工具表與兩段技能說明同步改寫 | | `plugin.json`、`.claude-plugin/plugin.json`、`.codex-plugin/plugin.json` | 行為變更要 bump 版本;三份同步升到 0.0.8 | ## 設計重點 - 推導只認分支名,不猜。`{子功能}` 可以多層,推導一律把最後一段換成 `main`;推不出唯一合法基底就回 `7` 中止,由呼叫端問使用者。**不退回 `develop`**——退回 `develop` 正是階梯要擋的那件事。 - 呼叫方傳入的 base 仍然照收,但要與推導結果一致。不一致就當成越級擋下,說明正確階梯再問使用者,不會悄悄改 PR 目標。 - 功能主幹不在 origin 時自動補一條:直接把 `origin/develop` 推成新分支,不動本機工作區,省下切分支再切回來的來回,並把建立了哪一條分支印到 stderr,讓收尾回報講得出來。 - 分支名只收 ASCII 小寫、數字、連字號與斜線。多層分支名用 `slugify.sh` 連叫兩次組出來,第一次的結果當第二次的型別參數。 - 校準三項各自獨立:標題或描述有差走 `pr-edit`(一次帶兩項),依賴有差走 `pr-depend`,三項都相同就什麼都不做。每一次多餘的編修都會通知所有審查者,安靜才是對的結果。 - 既有的呼叫方模式(不帶旗標)一字未改:傳入空字串仍然回 `6`,不會被當成「沒傳」而退回 `develop`。 ## 測試結果 - `sh -n tools/base-branch.sh`:語法檢查通過。 - 在一個隔離的暫存存取庫(本機 bare 存取庫當 origin,只有 `develop`)跑過 `--derive` 的八種情境,結果全部符合預期: - `feat/order-export/report-filter` → 自動建立 `feat/order-export/main` 並推上 origin,印出該基底,退出碼 `0`; - `feat/order-export/main` → `develop`,`fix/order-crash` → `develop`,兩者退出碼 `0`; - `feat/order-export`(少了功能層)、`foo/a/b`(型別不在階梯表)、`master`(已在頂端)、`feat/訂單`(含非 ASCII)四種都回 `7` 並印繁中原因; - `develop` 在沒有 `master` 的存取庫回 `8`,訊息指出基底不在 origin 且不是可自動建立的功能主幹。 - 參數護欄:`--derive a b c` 回 `2` 並印用法,空字串回 `6`。 - `tools/slugify.sh feat "order export"` → `feat/order-export`,再以它當型別跑 `tools/slugify.sh feat/order-export "report filter"` → `feat/order-export/report-filter`,多層分支名組得出來。 - `ste100-lint.sh .`:全庫零命中。 - 三份 manifest 以 JSON 解析器讀過,格式正確且版本一致為 0.0.8。 - 未測:`pr` 與 `commit` 兩支技能對真實 Gitea 的校準往返,需要可連線的主機與一支開啟中的 PR,本次在沒有 Gitea 存取的環境進行。 ## 前置 Push Request - plugins/gitea#22 https://gitea.jsc.idv.tw/plugins/gitea/pulls/22(本 PR 用到的 `pr-get`、`pr-edit` 在那支)
jiantw83 added 4 commits 2026-08-27 03:21:23 +00:00
What:`tools/base-branch.sh` 新增 `--derive [分支]` 模式,從分支名推出唯一合法的上一階基底。`feat` 這一類走 `{類型}/{功能}/{子功能}` → `{類型}/{功能}/main` → `develop` → `master`,`fix` 走 `fix/{修改}` → `develop` → `master`。新增退出碼 `7`(推不出唯一合法基底)、`8`(推導出的基底不在遠端又不能自動建立)、`9`(自動建立功能主幹失敗)。既有的呼叫方模式一字未改。

Why:PR 階梯禁止越級,但基底原本靠呼叫端自己挑,挑錯就是把一個子功能直接併進 `develop`,中間那層功能主幹整個被跳過。判斷寫進程式,越級就不會發生在「這次剛好沒注意」的時候。

How:`{子功能}` 可以多層,推導一律把最後一段換成 `main`。推不出唯一合法基底就中止並回 `7`,由呼叫端問使用者,不猜、也不退回 `develop`——退回 `develop` 正是這支腳本要擋的那件事。功能主幹不在 origin 時,直接把 `origin/develop` 推成新分支自動補一條,不動本機工作區,再把建立了哪一條分支印到 stderr。分支名只收 ASCII 小寫、數字、連字號與斜線,中文簡述請先過 `tools/slugify.sh`。

Who:`jsc-git:pr` 決定 PR base 的那一步,以及所有經由它開 PR 的技能。
What:`pr` 技能新增「PR ladder」一節與階梯形狀的分支命名(`fix` 叫一次 `slugify.sh`,其餘型別叫兩次組出 `{類型}/{功能}/{子功能}`),base 一律由 `base-branch.sh --derive` 推導;新增步驟 6 查目標分支有沒有開啟中的 PR,有就跳到新的步驟 9 比對標題、描述、前置 PR 依賴三項,只有不一樣的那幾項才送 API。`commit` 技能新增步驟 5:認可完成後,目前分支已有 PR 就交給 `pr` 校準。

Why:越級開 PR 與「同一條分支重開第二支 PR」是同一個病灶的兩面——base 與 PR 現況都靠人記。改成先推導、先比對之後,base 由腳本決定,PR 只在真的有差時才更新。

How:呼叫方傳入的 base 仍然照收,但要與推導結果一致;不一致就當成越級擋下,說明正確階梯再問使用者,不會悄悄改目標。校準走 `jsc-gitea` 的 `pr-get` 讀現況、`pr-edit` 一次帶標題與描述、`pr-depend` 補依賴;三項都相同就什麼都不做——每一次多餘的編修都會通知所有審查者,安靜才是對的結果。

Who:`jsc-git:pr` 與 `jsc-git:commit` 兩支技能,以及呼叫它們的 `jsc-sdlc:implement`、`jsc-sdlc:maintain` 與 `jsc-meta` 各技能。
What:README 新增「PR 階梯」一節(兩種型別的階梯表、多層子功能的推導方式、推不出就回 `7` 中止、功能主幹自動建立),工具表補上 `base-branch.sh --derive` 與 `slugify.sh` 連叫兩次組多層分支名,`commit` 與 `pr` 兩段說明改寫成新行為。

Why:階梯與校準是這次的行為變更,README 是對外說明。說明沒跟上,使用者會照舊以為 base 可以自己挑、PR 要重開一支。

How:階梯表在 README 只寫一份摘要,唯一來源仍是 `jsc-meta` 的 `references/guidelines.md`。技能說明兩段各補上推導與校準兩件事,用詞與 SKILL.md 一致。

Who:讀 `jsc-git` 說明的人,以及要接 `base-branch.sh` 的其他 domain。
What:`plugin.json`、`.claude-plugin/plugin.json`、`.codex-plugin/plugin.json` 的 `version` 由 0.0.7 改為 0.0.8。

Why:本次改了 `base-branch.sh` 的介面與 `commit`、`pr` 兩支技能的步驟,屬於行為變更,版本要跟著往上走,各 CLI 才知道要更新。

How:三份只改 `version` 一個欄位,其餘內容不動,三份保持同一版號。

Who:`jsc-git` 外掛的套件描述檔。
admin merged commit 8e42050718 into feat/sdlc-flow-rules/main 2026-08-27 03:26:23 +00:00
admin deleted branch feat/sdlc-flow-rules/pr-ladder-and-sync 2026-08-27 03:26:23 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Reference: plugins/git#11