feat(ai-code-review): 建問題模式導向 issue,並整併流程調整、文件與 CI #25

Closed
opened 2026-07-20 10:45:35 +00:00 by admin · 8 comments
Owner

變更摘要

本 PR 將 ai-code-review action 分支的完整成果併入 develop,主要含四塊:

  1. 建問題模式重構(feat)create-issue: 'true' 時,審查留言(工具/diff/角色/嚴重問題/警告+建議)全部改發到追蹤 issue、不再張貼到 PR;不執行「舊留言標過時/resolve」;issue 延後到「確定有保留問題」才建立;無保留問題或無可審查變更則不建 issue、PR 也完全不留言(靜默通過);有問題時最後在 PR 回貼一則 issue 連結並補掛標籤,形成雙向關聯。
  2. 審查流程步驟調整(refactor):將「標記舊留言過時/resolve」提前到偵測 AI 工具之前,並依新順序重編所有步驟編號與說明。
  3. 修正(gitrepo):補抓淺層 checkout 的 base 歷史,避免 merge-base 計算失敗。
  4. 文件與 CI:補齊 action.ymlsrc 各模組文件、重建 readme.md,新增 .gitea/workflows/ci.yaml(多工具 code review 驗證)並啟用建問題模式。

影響範圍

範圍 說明
action 執行流程 src/index.js main() 依模式分流:留言去向、跳過 resolveOldComments、issue 延後建立、severe/others 導向 issue、有問題才在 PR 回貼連結
Gitea API src/lib/gitea.js 新增 addLabelsToIssue
留言模板 src/lib/templates.js 新增 issueLinkComment
審查核心 src/lib/review.js 新增 postSevereToIssue,移除 createIssueWithFindingssortFindingsForIssue
git base 解析 src/lib/gitrepo.js 補抓淺層 checkout 的 base 歷史
文件與 CI readme.mdaction.yml.gitea/workflows/ci.yaml.gitea/workflows/readme.md

風險與注意事項

  • 建問題模式行為明顯改變:啟用後 PR 上不再有審查留言(有問題時改為 issue + 一則連結留言;無問題時完全不留言),請確認團隊流程可接受。
  • 端對端行為需靠 CI 實測:本地僅完成語法與模組載入驗證,實際 issue/PR 互動需一次 CI 觸發確認。
  • readme.md 尚未反映「建問題模式導向 issue」的最新行為與新/移除的函式,建議後續以 doc-funcs 重建文件。
  • 各檔頭部「更新時間」時間戳仍為 2026/07/17 18:49:58,未刷新。

本問題由 AI Code Review 依 PR #6 的審查結果自動建立,問題明細見下方留言。

<!-- ai-code-review --> ## 變更摘要 本 PR 將 ai-code-review action 分支的完整成果併入 `develop`,主要含四塊: 1. **建問題模式重構(feat)**:`create-issue: 'true'` 時,審查留言(工具/diff/角色/嚴重問題/警告+建議)全部改發到追蹤 issue、不再張貼到 PR;不執行「舊留言標過時/resolve」;issue 延後到「確定有保留問題」才建立;**無保留問題或無可審查變更則不建 issue、PR 也完全不留言(靜默通過)**;有問題時最後在 PR 回貼一則 issue 連結並補掛標籤,形成雙向關聯。 2. **審查流程步驟調整(refactor)**:將「標記舊留言過時/resolve」提前到偵測 AI 工具之前,並依新順序重編所有步驟編號與說明。 3. **修正(gitrepo)**:補抓淺層 checkout 的 base 歷史,避免 merge-base 計算失敗。 4. **文件與 CI**:補齊 `action.yml`/`src` 各模組文件、重建 `readme.md`,新增 `.gitea/workflows/ci.yaml`(多工具 code review 驗證)並啟用建問題模式。 ## 影響範圍 | 範圍 | 說明 | | --- | --- | | action 執行流程 | `src/index.js` `main()` 依模式分流:留言去向、跳過 resolveOldComments、issue 延後建立、severe/others 導向 issue、有問題才在 PR 回貼連結 | | Gitea API | `src/lib/gitea.js` 新增 `addLabelsToIssue` | | 留言模板 | `src/lib/templates.js` 新增 `issueLinkComment` | | 審查核心 | `src/lib/review.js` 新增 `postSevereToIssue`,移除 `createIssueWithFindings`、`sortFindingsForIssue` | | git base 解析 | `src/lib/gitrepo.js` 補抓淺層 checkout 的 base 歷史 | | 文件與 CI | `readme.md`、`action.yml`、`.gitea/workflows/ci.yaml`、`.gitea/workflows/readme.md` | ## 風險與注意事項 - **建問題模式行為明顯改變**:啟用後 PR 上不再有審查留言(有問題時改為 issue + 一則連結留言;無問題時完全不留言),請確認團隊流程可接受。 - **端對端行為需靠 CI 實測**:本地僅完成語法與模組載入驗證,實際 issue/PR 互動需一次 CI 觸發確認。 - `readme.md` 尚未反映「建問題模式導向 issue」的最新行為與新/移除的函式,建議後續以 doc-funcs 重建文件。 - 各檔頭部「更新時間」時間戳仍為 `2026/07/17 18:49:58`,未刷新。 --- > 本問題由 AI Code Review 依 PR #6 的審查結果自動建立,問題明細見下方留言。
Author
Owner

🤖 AI Code Review|審查工具

項目 內容
工具 codex
版本 codex-cli 0.144.6
模型 gpt-5.5
審查 commit 5ac73f290e31cc6bf36fff047829ef251a51468c
Run Job #55
flowchart LR
    A[整理 git diff] --> B[⚔️ 攻擊方找問題]
    B --> C[🛡️ 防守方裁決]
    C --> D[保存 findings]
    D --> E[留言到 PR]
<!-- ai-code-review --> ## 🤖 AI Code Review|審查工具 | 項目 | 內容 | | --- | --- | | 工具 | `codex` | | 版本 | `codex-cli 0.144.6` | | 模型 | `gpt-5.5` | | 審查 commit | `5ac73f290e31cc6bf36fff047829ef251a51468c` | | Run Job | [#55](https://gitea.jsc.idv.tw/node-actions/ai-code-review/actions/runs/1624) | ```mermaid flowchart LR A[整理 git diff] --> B[⚔️ 攻擊方找問題] B --> C[🛡️ 防守方裁決] C --> D[保存 findings] D --> E[留言到 PR] ```
Author
Owner

📋 變更摘要(送審 git diff)

檔案 用途 git diff 長度 最後更新時間
action.yml 定義 Action 參數與執行入口 88 行/4025 字元 2026/07/20 17:24:18
readme.md 說明專案用途、流程與用法 276 行/23829 字元(過長截斷送審) 2026/07/20 16:01:05
src/index.js 編排 AI code review 主流程 360 行/16212 字元(過長截斷送審) 2026/07/20 18:04:23
src/lib/agents.js 偵測並執行可用 AI CLI 工具 14 行/503 字元 2026/07/20 09:46:12
src/lib/context.js 載入 workflow 與 PR 執行脈絡 15 行/769 字元 2026/07/20 17:24:18
src/lib/gitea.js 封裝 Gitea API 操作 130 行/5744 字元 2026/07/20 18:04:23
src/lib/gitrepo.js 封裝 git diff 與提交操作 224 行/9542 字元 2026/07/20 18:04:23
src/lib/review.js 處理審查結果與診斷邏輯 586 行/25250 字元(過長截斷送審) 2026/07/20 18:43:06
src/lib/roles.js 載入並分類審查角色設定 14 行/586 字元 2026/07/20 09:46:12
src/lib/templates.js 產生 PR 留言 Markdown 模板 165 行/5966 字元 2026/07/20 18:04:23

共 10 個檔案納入審查;另有 10 個檔案依 .reviewignore 排除。

<!-- ai-code-review --> ## 📋 變更摘要(送審 git diff) | 檔案 | 用途 | git diff 長度 | 最後更新時間 | | --- | --- | --- | --- | | `action.yml` | 定義 Action 參數與執行入口 | 88 行/4025 字元 | 2026/07/20 17:24:18 | | `readme.md` | 說明專案用途、流程與用法 | 276 行/23829 字元(過長截斷送審) | 2026/07/20 16:01:05 | | `src/index.js` | 編排 AI code review 主流程 | 360 行/16212 字元(過長截斷送審) | 2026/07/20 18:04:23 | | `src/lib/agents.js` | 偵測並執行可用 AI CLI 工具 | 14 行/503 字元 | 2026/07/20 09:46:12 | | `src/lib/context.js` | 載入 workflow 與 PR 執行脈絡 | 15 行/769 字元 | 2026/07/20 17:24:18 | | `src/lib/gitea.js` | 封裝 Gitea API 操作 | 130 行/5744 字元 | 2026/07/20 18:04:23 | | `src/lib/gitrepo.js` | 封裝 git diff 與提交操作 | 224 行/9542 字元 | 2026/07/20 18:04:23 | | `src/lib/review.js` | 處理審查結果與診斷邏輯 | 586 行/25250 字元(過長截斷送審) | 2026/07/20 18:43:06 | | `src/lib/roles.js` | 載入並分類審查角色設定 | 14 行/586 字元 | 2026/07/20 09:46:12 | | `src/lib/templates.js` | 產生 PR 留言 Markdown 模板 | 165 行/5966 字元 | 2026/07/20 18:04:23 | > 共 10 個檔案納入審查;另有 10 個檔案依 `.reviewignore` 排除。
Author
Owner

⚔️ 攻擊方登場

角色 面向 個性
🗡️ Assassin 安全性(security) 多疑偏執、以攻擊者視角看世界,假設每筆輸入都是惡意的,每個信任都會被濫用
🎼 Bard 風格(style) 唯美龜毛、追求優雅,把可讀性與一致性當作旋律,最受不了走調的命名與排版
🧰 Leo 可維護性(maintainability) 有遠見、重視長期維護成本,凡事先問「六個月後的自己還看得懂嗎?」,討厭把債留給未來
🔮 Mage 邏輯(logic) 嚴謹冷靜、滴水不漏,凡事推演到最壞情況,深信「沒驗證過的假設都是 bug」
🧪 Maya 測試(testing) 對測試覆蓋率有執念,深信「沒有測試的程式碼等於沒寫完」,溫和但堅持,最在意邊界與失敗路徑
Rogue 效率(efficiency) 急性子、講求速度,最痛恨被浪費的 CPU 週期與記憶體,凡事先問「這能不能更快、更省」
<!-- ai-code-review --> ## ⚔️ 攻擊方登場 | 角色 | 面向 | 個性 | | --- | --- | --- | | 🗡️ **Assassin** | 安全性(security) | 多疑偏執、以攻擊者視角看世界,假設每筆輸入都是惡意的,每個信任都會被濫用 | | 🎼 **Bard** | 風格(style) | 唯美龜毛、追求優雅,把可讀性與一致性當作旋律,最受不了走調的命名與排版 | | 🧰 **Leo** | 可維護性(maintainability) | 有遠見、重視長期維護成本,凡事先問「六個月後的自己還看得懂嗎?」,討厭把債留給未來 | | 🔮 **Mage** | 邏輯(logic) | 嚴謹冷靜、滴水不漏,凡事推演到最壞情況,深信「沒驗證過的假設都是 bug」 | | 🧪 **Maya** | 測試(testing) | 對測試覆蓋率有執念,深信「沒有測試的程式碼等於沒寫完」,溫和但堅持,最在意邊界與失敗路徑 | | ⚡ **Rogue** | 效率(efficiency) | 急性子、講求速度,最痛恨被浪費的 CPU 週期與記憶體,凡事先問「這能不能更快、更省」 |
Author
Owner

🛡️ 防守方登場

角色 面向 個性
🛡️ Paladin 裁決(verdict) 沉穩公正、就事論事,不護短也不冤枉,只依排除事項與原始碼脈絡裁定問題成立與否
<!-- ai-code-review --> ## 🛡️ 防守方登場 | 角色 | 面向 | 個性 | | --- | --- | --- | | 🛡️ **Paladin** | 裁決(verdict) | 沉穩公正、就事論事,不護短也不冤枉,只依排除事項與原始碼脈絡裁定問題成立與否 |
Author
Owner

🔴 嚴重|🔮 Mage

位置src/index.js 第 398–415 行

問題描述

建問題模式在「有嚴重問題、但 exclusions.json 沒有變更」時不會產生任何 [failure] 結果 commit,最後仍回傳 0。最小重現:create-issue=true、攻擊/防守後 kept 含 1 條 severity === '嚴重'excluded 為空,所以 exclusionsChanged === false。流程會建立 issue、嘗試掛 dependency,接著進入 建問題模式且 exclusions.json 無變更,略過 commit/push,最後 return 0。此時既沒有本輪 exit 1,也沒有下一輪可讀取的 failure commit;若 issue dependency 未啟用或設定失敗又被 catch 降級,PR 檢查會顯示通過。

修改建議

不要讓嚴重問題的失敗狀態只依賴可選的 exclusions commit。建問題模式只要 severe.length > 0,應至少保證一個可被下一輪讀到的 failure marker commit,或在無法產生 marker 時直接 return 1。若設計上 dependency 是阻擋合併的來源,則 dependency 建立失敗時不能降級為通過。

<!-- ai-code-review --> ### 🔴 嚴重|🔮 Mage **位置**:`src/index.js` 第 398–415 行 **問題描述** 建問題模式在「有嚴重問題、但 exclusions.json 沒有變更」時不會產生任何 `[failure]` 結果 commit,最後仍回傳 0。最小重現:`create-issue=true`、攻擊/防守後 `kept` 含 1 條 `severity === '嚴重'`、`excluded` 為空,所以 `exclusionsChanged === false`。流程會建立 issue、嘗試掛 dependency,接著進入 `建問題模式且 exclusions.json 無變更,略過 commit/push`,最後 `return 0`。此時既沒有本輪 exit 1,也沒有下一輪可讀取的 failure commit;若 issue dependency 未啟用或設定失敗又被 catch 降級,PR 檢查會顯示通過。 **修改建議** 不要讓嚴重問題的失敗狀態只依賴可選的 exclusions commit。建問題模式只要 `severe.length > 0`,應至少保證一個可被下一輪讀到的 failure marker commit,或在無法產生 marker 時直接 `return 1`。若設計上 dependency 是阻擋合併的來源,則 dependency 建立失敗時不能降級為通過。
Author
Owner

🟠 警告|🔮 Mage

位置src/index.js 第 409–415 行

問題描述

本輪審查一律 return 0 的前提是「結果 commit 一定會觸發下一輪」。但 action.yml 只建議使用 PAT,沒有驗證 ctx.token 真的能觸發 CI。最小重現:一般模式發現嚴重問題,result === 'failure',使用者仍傳入自動 token;程式成功 push failure commit,但該 push 不觸發 workflow,於是沒有下一輪步驟 1 回報 exit 1,本輪又固定回傳 0,檢查結果會錯誤地通過。

修改建議

失敗狀態不能建立在未驗證的 token 行為上。建議在 severe.length > 0 時,若無法確認已用可觸發 CI 的 PAT 產生下一輪檢查,就維持本輪 return 1;或新增明確 input(例如 deferred-failure=true)並在未啟用時直接失敗。

<!-- ai-code-review --> ### 🟠 警告|🔮 Mage **位置**:`src/index.js` 第 409–415 行 **問題描述** 本輪審查一律 `return 0` 的前提是「結果 commit 一定會觸發下一輪」。但 `action.yml` 只建議使用 PAT,沒有驗證 `ctx.token` 真的能觸發 CI。最小重現:一般模式發現嚴重問題,`result === 'failure'`,使用者仍傳入自動 token;程式成功 push failure commit,但該 push 不觸發 workflow,於是沒有下一輪步驟 1 回報 exit 1,本輪又固定回傳 0,檢查結果會錯誤地通過。 **修改建議** 失敗狀態不能建立在未驗證的 token 行為上。建議在 `severe.length > 0` 時,若無法確認已用可觸發 CI 的 PAT 產生下一輪檢查,就維持本輪 `return 1`;或新增明確 input(例如 `deferred-failure=true`)並在未啟用時直接失敗。
Author
Owner

🔵 建議|🧰 Leo

位置src/index.js 第 194–232 行

問題描述

queueOrPostComment() 會依閉包狀態回傳 Commentnull,同時還會修改 issueBuffer / currentRunCommentIds。這種「同一個方法但回傳型別和副作用隨模式變」的介面,現在呼叫端剛好不使用回傳值所以看似無害;未來有人若要在留言後讀 created.id 或做錯誤補償,很容易踩到建問題模式尚未建立 issue 時回傳 null 的隱藏分支。

修改建議

讓介面語意更窄:若呼叫端不需要留言物件,就讓函式固定回傳 Promise<void>;若需要留言結果,則拆成 postPrCommentAndTrack()bufferOrPostIssueComment()。避免一個 helper 同時承載兩種模式與兩種回傳契約。

<!-- ai-code-review --> ### 🔵 建議|🧰 Leo **位置**:`src/index.js` 第 194–232 行 **問題描述** `queueOrPostComment()` 會依閉包狀態回傳 `Comment` 或 `null`,同時還會修改 `issueBuffer` / `currentRunCommentIds`。這種「同一個方法但回傳型別和副作用隨模式變」的介面,現在呼叫端剛好不使用回傳值所以看似無害;未來有人若要在留言後讀 `created.id` 或做錯誤補償,很容易踩到建問題模式尚未建立 issue 時回傳 `null` 的隱藏分支。 **修改建議** 讓介面語意更窄:若呼叫端不需要留言物件,就讓函式固定回傳 `Promise<void>`;若需要留言結果,則拆成 `postPrCommentAndTrack()` 與 `bufferOrPostIssueComment()`。避免一個 helper 同時承載兩種模式與兩種回傳契約。
Member

🧩 code-review-resolve 處理進度

本議題為 AI Code Review 建問題模式的追蹤議題。以 --issue all 併同 .gitea/ai-review/findings/ 逐條處理後結果如下(對照目前程式碼與 exclusions.json):

# 等級 審查員 位置 處理結果 說明
1 🔴 嚴重 Mage src/index.js 第 398–415 行 🚫誤報 建問題模式「有嚴重問題但 exclusions.json 無變更時不推 [failure] commit」為刻意的兩階段失敗設計,exclusions.json 已有多筆等價 Mage 嚴重裁決。
2 🟠 警告 Mage src/index.js 第 409–415 行 🚫誤報 「一律 return 0、依賴結果 commit 觸發下一輪」屬同一兩階段失敗設計,已列入 exclusions。
3 🔵 建議 Leo src/index.js 第 194–232 行 🚫誤報 queueOrPostComment(前身 postComment)依模式回傳型別/副作用不同、main() 閉包應抽出 publisher,屬既有可維護性設計取捨,已列入 exclusions。

小計 已解決 0 條、🚫 誤報(已列入 exclusions)3 條、⏭️ 待人工處理 0 條。

本議題三條問題皆與 .gitea/ai-review/exclusions.json 既有裁決等價(兩階段失敗設計、留言路由多形介面),屬需維護者拍板的設計取捨,非可自動修復之缺陷;本輪不重複新增排除、不改動程式碼。

處理完成,依 code-review-resolve 流程關閉本議題。

<!-- code-review-resolve --> ## 🧩 code-review-resolve 處理進度 本議題為 AI Code Review 建問題模式的追蹤議題。以 `--issue all` 併同 `.gitea/ai-review/findings/` 逐條處理後結果如下(對照目前程式碼與 `exclusions.json`): | # | 等級 | 審查員 | 位置 | 處理結果 | 說明 | | --- | --- | --- | --- | --- | --- | | 1 | 🔴 嚴重 | Mage | `src/index.js` 第 398–415 行 | 🚫誤報 | 建問題模式「有嚴重問題但 exclusions.json 無變更時不推 `[failure]` commit」為刻意的兩階段失敗設計,`exclusions.json` 已有多筆等價 Mage 嚴重裁決。 | | 2 | 🟠 警告 | Mage | `src/index.js` 第 409–415 行 | 🚫誤報 | 「一律 return 0、依賴結果 commit 觸發下一輪」屬同一兩階段失敗設計,已列入 exclusions。 | | 3 | 🔵 建議 | Leo | `src/index.js` 第 194–232 行 | 🚫誤報 | `queueOrPostComment`(前身 postComment)依模式回傳型別/副作用不同、main() 閉包應抽出 publisher,屬既有可維護性設計取捨,已列入 exclusions。 | **小計**:✅ 已解決 0 條、🚫 誤報(已列入 exclusions)3 條、⏭️ 待人工處理 0 條。 > 本議題三條問題皆與 `.gitea/ai-review/exclusions.json` 既有裁決等價(兩階段失敗設計、留言路由多形介面),屬需維護者拍板的設計取捨,非可自動修復之缺陷;本輪不重複新增排除、不改動程式碼。 處理完成,依 code-review-resolve 流程關閉本議題。
Sign in to join this conversation.
No labels
2 Participants
Notifications
Due Date
No due date set.
Reference: node-actions/ai-code-review#25