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

Closed
opened 2026-07-20 05:53:11 +00:00 by gitea-actions · 10 comments

變更摘要

本 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 的審查結果自動建立,問題明細見下方留言。

🤖 AI Code Review|審查工具

項目 內容
工具 codex
版本 codex-cli 0.144.6
模型 (工具預設)
審查 commit e37a96433df84cd542d6c93c3b407873e873fa14
Run Job #17
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` | | 模型 | (工具預設) | | 審查 commit | `e37a96433df84cd542d6c93c3b407873e873fa14` | | Run Job | [#17](https://gitea.jsc.idv.tw/node-actions/ai-code-review/actions/runs/1585) | ```mermaid flowchart LR A[整理 git diff] --> B[⚔️ 攻擊方找問題] B --> C[🛡️ 防守方裁決] C --> D[保存 findings] D --> E[留言到 PR] ```

📋 變更摘要(送審 git diff)

檔案 用途 git diff 長度 最後更新時間
action.yml 定義 Action 輸入與執行入口 84 行/3668 字元 2026/07/17 18:54:00
readme.md 說明專案功能、設定與審查流程 274 行/23780 字元(過長截斷送審) 2026/07/20 09:46:12
src/index.js 編排多角色程式碼審查主流程 277 行/12084 字元 2026/07/20 12:06:21
src/lib/agents.js 偵測並執行 AI CLI 代理 14 行/503 字元 2026/07/20 09:46:12
src/lib/gitea.js 封裝 Gitea API 操作 115 行/4988 字元 2026/07/20 11:24:48
src/lib/gitrepo.js 處理 Git 差異、歷史與提交 80 行/2875 字元 2026/07/17 19:02:42
src/lib/review.js 執行審查、裁決與結果整理 513 行/21596 字元(過長截斷送審) 2026/07/20 13:41:41
src/lib/roles.js 載入並分類審查角色 14 行/586 字元 2026/07/20 09:46:12
src/lib/templates.js 產生審查留言與表格模板 165 行/5949 字元 2026/07/20 12:06:21

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

<!-- ai-code-review --> ## 📋 變更摘要(送審 git diff) | 檔案 | 用途 | git diff 長度 | 最後更新時間 | | --- | --- | --- | --- | | `action.yml` | 定義 Action 輸入與執行入口 | 84 行/3668 字元 | 2026/07/17 18:54:00 | | `readme.md` | 說明專案功能、設定與審查流程 | 274 行/23780 字元(過長截斷送審) | 2026/07/20 09:46:12 | | `src/index.js` | 編排多角色程式碼審查主流程 | 277 行/12084 字元 | 2026/07/20 12:06:21 | | `src/lib/agents.js` | 偵測並執行 AI CLI 代理 | 14 行/503 字元 | 2026/07/20 09:46:12 | | `src/lib/gitea.js` | 封裝 Gitea API 操作 | 115 行/4988 字元 | 2026/07/20 11:24:48 | | `src/lib/gitrepo.js` | 處理 Git 差異、歷史與提交 | 80 行/2875 字元 | 2026/07/17 19:02:42 | | `src/lib/review.js` | 執行審查、裁決與結果整理 | 513 行/21596 字元(過長截斷送審) | 2026/07/20 13:41:41 | | `src/lib/roles.js` | 載入並分類審查角色 | 14 行/586 字元 | 2026/07/20 09:46:12 | | `src/lib/templates.js` | 產生審查留言與表格模板 | 165 行/5949 字元 | 2026/07/20 12:06:21 | > 共 9 個檔案納入審查;另有 4 個檔案依 `.reviewignore` 排除。

⚔️ 攻擊方登場

角色 面向 個性
🗡️ 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 週期與記憶體,凡事先問「這能不能更快、更省」 |

🛡️ 防守方登場

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

🔴 嚴重|🔮 Mage

位置src/index.js 第 221–223 行

問題描述

舊留言在本回合確認能完成審查前就被標記為過時。最小重現:PR 已有上一回合有效 findings,但 runner 未安裝任何 AI CLI;步驟 2 先清除舊留言,接著 detectTool() 回傳 null 並以失敗結束,PR 最後既沒有有效的舊結果,也沒有新的審查結果。後續任一 AI、檔案系統或 API 例外也會造成相同狀態。

修改建議

resolveOldComments 延後到新一輪審查結果已成功產生、且即將發布新結果時執行;至少也應在工具偵測、diff 整理及攻防裁決成功後才使舊結果失效。

<!-- ai-code-review --> ### 🔴 嚴重|🔮 Mage **位置**:`src/index.js` 第 221–223 行 **問題描述** 舊留言在本回合確認能完成審查前就被標記為過時。最小重現:PR 已有上一回合有效 findings,但 runner 未安裝任何 AI CLI;步驟 2 先清除舊留言,接著 `detectTool()` 回傳 null 並以失敗結束,PR 最後既沒有有效的舊結果,也沒有新的審查結果。後續任一 AI、檔案系統或 API 例外也會造成相同狀態。 **修改建議** 將 `resolveOldComments` 延後到新一輪審查結果已成功產生、且即將發布新結果時執行;至少也應在工具偵測、diff 整理及攻防裁決成功後才使舊結果失效。

🔴 嚴重|🗡️ Assassin

位置src/lib/review.js 第 39–42 行

問題描述

攻擊者可刻意讓 AI CLI 失敗,並誘使其在 stderr/stdout 回顯提示內容、環境資訊、權杖或 PR diff 中的機密;此處未經遮罩便擷取最多 500 字,後續直接寫入 CI log。即使截斷仍足以洩漏 token、PII 或原始碼祕密,而 CI 記錄通常會被長期保存並供多人讀取。

修改建議

不要將 AI CLI 的原始 stdout 寫入日誌;stderr 也只保留固定錯誤分類與 exit code。若確實需要診斷文字,應先移除換行與控制字元,套用 token、Authorization header、URL credential、常見金鑰格式及 PII 的遮罩,並以明確的除錯開關控制詳細輸出。

建議寫法

function agentFailureDetail(res) {
  const err = res && res.error;
  const parts = [];
  if (err && err.killed) parts.push('已逾時終止');
  if (err && typeof err.code === 'number') parts.push(`exit ${err.code}`);
  else if (err && err.signal) parts.push(`signal ${err.signal}`);
  return parts.join('|') || 'AI CLI 執行失敗(詳細輸出已隱藏)';
}
<!-- ai-code-review --> ### 🔴 嚴重|🗡️ Assassin **位置**:`src/lib/review.js` 第 39–42 行 **問題描述** 攻擊者可刻意讓 AI CLI 失敗,並誘使其在 stderr/stdout 回顯提示內容、環境資訊、權杖或 PR diff 中的機密;此處未經遮罩便擷取最多 500 字,後續直接寫入 CI log。即使截斷仍足以洩漏 token、PII 或原始碼祕密,而 CI 記錄通常會被長期保存並供多人讀取。 **修改建議** 不要將 AI CLI 的原始 stdout 寫入日誌;stderr 也只保留固定錯誤分類與 exit code。若確實需要診斷文字,應先移除換行與控制字元,套用 token、Authorization header、URL credential、常見金鑰格式及 PII 的遮罩,並以明確的除錯開關控制詳細輸出。 **建議寫法** ``` function agentFailureDetail(res) { const err = res && res.error; const parts = []; if (err && err.killed) parts.push('已逾時終止'); if (err && typeof err.code === 'number') parts.push(`exit ${err.code}`); else if (err && err.signal) parts.push(`signal ${err.signal}`); return parts.join('|') || 'AI CLI 執行失敗(詳細輸出已隱藏)'; } ```

🟠 其他問題(警告+建議,共 10 條)

等級 審查員 檔案名稱 問題起訖行數 問題描述 修改建議
🟠 警告 🧰 Leo src/index.js 210–224 ensureIssueCreated 同時建立 issue、修改外層 issue 狀態、逐筆清空 issueBuffer,但整段流程沒有可重入或冪等機制。若 issue 建立成功後,寫入其中一則暫存留言時失敗,主流程會中止;重跑後又會建立另一個 issue,留下內容不完整的孤兒 issue。這種依賴閉包可變狀態的半完成狀態,半年後要加入重試、續傳或測試失敗情境都會很痛苦。 把「建立追蹤 issue 並沖刷留言」抽成獨立、可注入 Gitea client 的服務函式,明確回傳 issue 與已寫入進度;建立前以 PR 編號或隱藏識別標記查找既有追蹤 issue,讓重跑能接續而非重複建立。至少也應保留已建立的 issue 編號並在錯誤訊息中回報,避免留下無法追蹤的半成品。
🟠 警告 🧪 Maya src/index.js 306–359 建問題模式的核心流程已大幅改變,但 diff 中沒有對應測試驗證各分支:有保留問題時才建立 issue、暫存留言依序送出、無問題時靜默通過、嚴重與非嚴重問題送往正確位置,以及標籤失敗後仍須回貼 PR 連結。這些分支牽涉多次外部 API 呼叫與狀態切換,未測試時很容易出現漏留言、留言送錯 PR/issue,或在 issue 尚未建立時解參考的回歸。 新增主流程測試並 mock Gitea、agent 與 git 操作,至少涵蓋:kept=[] 時不建立 issue 且不留言;僅嚴重問題;僅警告/建議;混合問題;建立 issue 或寫入暫存留言失敗;標籤查詢、AI 選標籤及補掛標籤失敗時仍回貼 issue 連結。除了呼叫次數,也應斷言 API 呼叫順序、目標 issue 編號及留言內容。
🟠 警告 🧪 Maya src/lib/gitea.js 188–191 新增的 addLabelsToIssue 沒有對應測試,尚未驗證空值捷徑與實際 API 請求格式。這個函式位於新建問題流程的收尾路徑;若 endpoint、HTTP method 或 { labels } payload 不符預期,追蹤 issue 將無法取得標籤,而空陣列是否真的不發出請求也未被保護。 新增單元測試,分別傳入 undefinednull、空陣列及多個 label id;斷言前三者回傳 null 且完全不呼叫 API,多個 id 時以 POST 呼叫正確的 owner/repo/issue endpoint 並傳送 { labels: [...] },另驗證 API 拋錯會原樣往上傳遞。
🟠 警告 🧪 Maya src/lib/gitrepo.js 100–122 resolveMergeBase 新增多階段 fetch 與淺層 checkout 修復邏輯,但沒有看到測試驗證成功、降級與最終失敗路徑。尤其初次 merge-base 失敗後,淺層與非淺層 repository 會走不同路徑,且多個 tryGit 失敗會被刻意吞掉;若參數、refspec 或重試順序有誤,只會在實際 CI checkout 深度不足時才暴露。 以 stub 的 git 執行器或暫存 repository 補齊案例:首次 merge-base 成功;淺層 repository 經 --unshallow 後成功;--unshallow 失敗但 --deepen=1000 後成功;非淺層首次失敗後重試成功;所有策略失敗時拋出含 baseRef 且保留原始 cause 的錯誤。並斷言 base/head fetch 的 refspec 與執行順序。
🟠 警告 🧰 Leo src/lib/gitrepo.js 101–123 resolveMergeBase 連續呼叫 tryGit,卻完全忽略每次 fetch 的成功與失敗資訊;tryGit 又吞掉原始例外,最後只把第一次 merge-base 失敗設為 cause。未來遇到權限、refspec、遠端或 Git 版本差異時,維護者只會看到籠統的「歷史不足」,無法判斷是哪個補抓策略失敗,也難以針對各分支編寫單元測試。 讓嘗試函式回傳包含 ok、策略名稱與原始錯誤的結果,並由 resolveMergeBase 以資料驅動方式依序執行補抓策略;最終失敗時彙整各次診斷資訊。如此新增或調整 fetch 策略時不必再複製控制流,也能在測試中驗證每個降級路徑。
🟠 警告 Rogue src/lib/gitrepo.js 110–111 --unshallow 成功後仍無條件再執行兩次 --deepen=1000 fetch;每次淺層 checkout 都可能多付 2 次遠端往返與重複物件協商,大型存取庫還會浪費明顯網路流量、CPU 與 CI 時間。 記錄 --unshallow 是否成功;成功後直接重試 merge-base,只有失敗時才進一步 deepen。若要補抓 base 與 HEAD,也應每次 fetch 後先嘗試 merge-base,成功就停止。
🔵 建議 🎼 Bard src/index.js 303–304 註解聲稱「無保留問題則不建 issue,改在 PR 留一則審查通過提示」,但緊接著的實作與內層註解皆寫明「PR 也不留言(靜默通過)」。同一段譜面出現兩種相反敘述,會誤導後續維護者。 將段落註解改成與實作一致,明確說明無保留問題時會靜默通過並捨棄暫存留言。
🔵 建議 Rogue src/index.js 332–348 最終 findings 已經確定後,流程仍先用空標籤建立 issue,再額外呼叫 addLabelsToIssue;每個有問題的 PR 固定浪費 1 次遠端 API 往返。 在建立 issue 前先完成 listLabelsselectLabels,再把選出的 labelIds 直接傳給既有的 gitea.createIssue。標籤挑選失敗時傳空陣列即可維持目前的降級行為,並可移除補掛標籤請求。
🔵 建議 🧪 Maya src/lib/review.js 17–45 新增的 agent 失敗診斷涵蓋逾時、數字或字串 exit code、signal、空輸出及 500 字截斷等多個邊界,但沒有測試鎖定輸出。這些資訊只在失敗路徑出現,正常審查不會自然覆蓋;日後修改時可能悄悄遺失真正的 CLI 錯誤內容,或破壞單行與截斷約束。 將摘要邏輯匯出供測試,或透過失敗的 runAttackersrunDefendersfillPurposes 測試間接斷言 log。至少覆蓋 killed、數字 exit code、字串 code、signal、stderr 與 stdout 同時存在、超過 500 字、完全無資訊,以及 res 為 null/undefined 的案例。
🔵 建議 🎼 Bard src/lib/templates.js 58–58 focusLabel 的使用情境仍標成「步驟 5/6」,但角色登場已調整為攻擊方步驟 5、防守方步驟 7;同檔 rolesComment 的文件也已採用「5/7」。步驟編號前後走調。 統一改為「步驟 5/7」,使共用函式與鄰近模板文件採用相同流程編號。
<!-- ai-code-review --> ## 🟠 其他問題(警告+建議,共 10 條) | 等級 | 審查員 | 檔案名稱 | 問題起訖行數 | 問題描述 | 修改建議 | | --- | --- | --- | --- | --- | --- | | 🟠 警告 | 🧰 Leo | `src/index.js` | 210–224 | `ensureIssueCreated` 同時建立 issue、修改外層 `issue` 狀態、逐筆清空 `issueBuffer`,但整段流程沒有可重入或冪等機制。若 issue 建立成功後,寫入其中一則暫存留言時失敗,主流程會中止;重跑後又會建立另一個 issue,留下內容不完整的孤兒 issue。這種依賴閉包可變狀態的半完成狀態,半年後要加入重試、續傳或測試失敗情境都會很痛苦。 | 把「建立追蹤 issue 並沖刷留言」抽成獨立、可注入 Gitea client 的服務函式,明確回傳 issue 與已寫入進度;建立前以 PR 編號或隱藏識別標記查找既有追蹤 issue,讓重跑能接續而非重複建立。至少也應保留已建立的 issue 編號並在錯誤訊息中回報,避免留下無法追蹤的半成品。 | | 🟠 警告 | 🧪 Maya | `src/index.js` | 306–359 | 建問題模式的核心流程已大幅改變,但 diff 中沒有對應測試驗證各分支:有保留問題時才建立 issue、暫存留言依序送出、無問題時靜默通過、嚴重與非嚴重問題送往正確位置,以及標籤失敗後仍須回貼 PR 連結。這些分支牽涉多次外部 API 呼叫與狀態切換,未測試時很容易出現漏留言、留言送錯 PR/issue,或在 `issue` 尚未建立時解參考的回歸。 | 新增主流程測試並 mock Gitea、agent 與 git 操作,至少涵蓋:`kept=[]` 時不建立 issue 且不留言;僅嚴重問題;僅警告/建議;混合問題;建立 issue 或寫入暫存留言失敗;標籤查詢、AI 選標籤及補掛標籤失敗時仍回貼 issue 連結。除了呼叫次數,也應斷言 API 呼叫順序、目標 issue 編號及留言內容。 | | 🟠 警告 | 🧪 Maya | `src/lib/gitea.js` | 188–191 | 新增的 `addLabelsToIssue` 沒有對應測試,尚未驗證空值捷徑與實際 API 請求格式。這個函式位於新建問題流程的收尾路徑;若 endpoint、HTTP method 或 `{ labels }` payload 不符預期,追蹤 issue 將無法取得標籤,而空陣列是否真的不發出請求也未被保護。 | 新增單元測試,分別傳入 `undefined`、`null`、空陣列及多個 label id;斷言前三者回傳 `null` 且完全不呼叫 API,多個 id 時以 POST 呼叫正確的 owner/repo/issue endpoint 並傳送 `{ labels: [...] }`,另驗證 API 拋錯會原樣往上傳遞。 | | 🟠 警告 | 🧪 Maya | `src/lib/gitrepo.js` | 100–122 | `resolveMergeBase` 新增多階段 fetch 與淺層 checkout 修復邏輯,但沒有看到測試驗證成功、降級與最終失敗路徑。尤其初次 merge-base 失敗後,淺層與非淺層 repository 會走不同路徑,且多個 `tryGit` 失敗會被刻意吞掉;若參數、refspec 或重試順序有誤,只會在實際 CI checkout 深度不足時才暴露。 | 以 stub 的 git 執行器或暫存 repository 補齊案例:首次 merge-base 成功;淺層 repository 經 `--unshallow` 後成功;`--unshallow` 失敗但 `--deepen=1000` 後成功;非淺層首次失敗後重試成功;所有策略失敗時拋出含 `baseRef` 且保留原始 `cause` 的錯誤。並斷言 base/head fetch 的 refspec 與執行順序。 | | 🟠 警告 | 🧰 Leo | `src/lib/gitrepo.js` | 101–123 | `resolveMergeBase` 連續呼叫 `tryGit`,卻完全忽略每次 fetch 的成功與失敗資訊;`tryGit` 又吞掉原始例外,最後只把第一次 `merge-base` 失敗設為 cause。未來遇到權限、refspec、遠端或 Git 版本差異時,維護者只會看到籠統的「歷史不足」,無法判斷是哪個補抓策略失敗,也難以針對各分支編寫單元測試。 | 讓嘗試函式回傳包含 `ok`、策略名稱與原始錯誤的結果,並由 `resolveMergeBase` 以資料驅動方式依序執行補抓策略;最終失敗時彙整各次診斷資訊。如此新增或調整 fetch 策略時不必再複製控制流,也能在測試中驗證每個降級路徑。 | | 🟠 警告 | ⚡ Rogue | `src/lib/gitrepo.js` | 110–111 | `--unshallow` 成功後仍無條件再執行兩次 `--deepen=1000` fetch;每次淺層 checkout 都可能多付 2 次遠端往返與重複物件協商,大型存取庫還會浪費明顯網路流量、CPU 與 CI 時間。 | 記錄 `--unshallow` 是否成功;成功後直接重試 `merge-base`,只有失敗時才進一步 deepen。若要補抓 base 與 HEAD,也應每次 fetch 後先嘗試 `merge-base`,成功就停止。 | | 🔵 建議 | 🎼 Bard | `src/index.js` | 303–304 | 註解聲稱「無保留問題則不建 issue,改在 PR 留一則審查通過提示」,但緊接著的實作與內層註解皆寫明「PR 也不留言(靜默通過)」。同一段譜面出現兩種相反敘述,會誤導後續維護者。 | 將段落註解改成與實作一致,明確說明無保留問題時會靜默通過並捨棄暫存留言。 | | 🔵 建議 | ⚡ Rogue | `src/index.js` | 332–348 | 最終 findings 已經確定後,流程仍先用空標籤建立 issue,再額外呼叫 `addLabelsToIssue`;每個有問題的 PR 固定浪費 1 次遠端 API 往返。 | 在建立 issue 前先完成 `listLabels` 與 `selectLabels`,再把選出的 `labelIds` 直接傳給既有的 `gitea.createIssue`。標籤挑選失敗時傳空陣列即可維持目前的降級行為,並可移除補掛標籤請求。 | | 🔵 建議 | 🧪 Maya | `src/lib/review.js` | 17–45 | 新增的 agent 失敗診斷涵蓋逾時、數字或字串 exit code、signal、空輸出及 500 字截斷等多個邊界,但沒有測試鎖定輸出。這些資訊只在失敗路徑出現,正常審查不會自然覆蓋;日後修改時可能悄悄遺失真正的 CLI 錯誤內容,或破壞單行與截斷約束。 | 將摘要邏輯匯出供測試,或透過失敗的 `runAttackers`/`runDefenders`/`fillPurposes` 測試間接斷言 log。至少覆蓋 killed、數字 exit code、字串 code、signal、stderr 與 stdout 同時存在、超過 500 字、完全無資訊,以及 `res` 為 null/undefined 的案例。 | | 🔵 建議 | 🎼 Bard | `src/lib/templates.js` | 58–58 | `focusLabel` 的使用情境仍標成「步驟 5/6」,但角色登場已調整為攻擊方步驟 5、防守方步驟 7;同檔 `rolesComment` 的文件也已採用「5/7」。步驟編號前後走調。 | 統一改為「步驟 5/7」,使共用函式與鄰近模板文件採用相同流程編號。 |
admin closed this issue 2026-07-20 05:57:21 +00:00
admin reopened this issue 2026-07-20 06:09:20 +00:00
Member

🔧 AI Code Review 問題處理進度

已依嚴重度逐條處理議題 #7 的審查問題,修復已提交並推送至分支 ai-review-resolve/develop-20260717-185330(納入既有的 PR #6develop,未另建重複 PR)。

統計: 已解決 7 條、⏭️ 待人工處理 5 條、🚫 誤報 0 條。 exclusions.json 無新增。

# 等級 審查員 位置 處理 說明
1 🔴 嚴重 🔮 Mage src/index.js 已解決 resolveOldComments 延後到審查成功產生結果、發布問題留言前才執行,並以 currentRunCommentIds 排除本回合新留言(commit e44a8ed
2 🔴 嚴重 🗡️ Assassin src/lib/review.js 已解決 agentFailureDetail 預設只輸出 exit code/signal;僅 ACTIONS_STEP_DEBUG=true 時輸出經遮罩+去控制字元的片段(commit 5c83329
7 🟠 警告 🧰 Leo src/lib/gitrepo.js 已解決 resolveMergeBase 改資料驅動策略、彙整各策略成敗診斷、保留首次錯誤 cause(commit 35887f1
8 🟠 警告 Rogue src/lib/gitrepo.js 已解決 每個補抓策略後立即重試 merge-base、成功即停,--unshallow 成功不再多做 deepen(commit 35887f1
9 🔵 建議 🎼 Bard src/index.js 已解決 修正「無保留問題」段落註解與實作(靜默通過、不留言)一致(commit e44a8ed
10 🔵 建議 Rogue src/index.js 已解決 標籤改為建立 issue 前先挑選、createIssue 一次帶入,移除事後補掛的多餘 API 往返(commit e44a8ed
12 🔵 建議 🎼 Bard src/lib/templates.js 已解決 角色登場步驟編號統一為 5/7(commit dbeb565
3 🟠 警告 🧰 Leo src/index.js ⏭️ 待人工處理 完整冪等(查找既有追蹤 issue 續建)需新增 issue 查詢 API 與標記機制,屬對未經 CI 驗證之核心流程的功能級改動與設計取捨,需人工確認匹配規則後再做
4 🟠 警告 🧪 Maya src/index.js ⏭️ 待人工處理 主流程測試需先建立測試架構與 Gitea/agent/git 的 mock 策略;專案目前無測試框架與 devDependencies,屬設計決策
5 🟠 警告 🧪 Maya src/lib/gitea.js ⏭️ 待人工處理 同測試架構決策;另註:空/空陣列不發出請求的防護已存在於現行 addLabelsToIssue
6 🟠 警告 🧪 Maya src/lib/gitrepo.js ⏭️ 待人工處理 resolveMergeBase 需可注入 git 執行器方能穩定測試各降級路徑,屬可測性重構+測試架構決策
11 🔵 建議 🧪 Maya src/lib/review.js ⏭️ 待人工處理 同測試架構決策;該函式已於本次重構為安全版本,待測試框架就緒後補上邊界案例

待人工處理共同原因

⏭️ 的 5 條皆繞不開「專案目前無測試框架/devDependencies/可測性結構」或「對未經 CI 驗證的核心流程做功能級改動」,屬架構決策,依規範不逕自硬加,避免對核心流程造成回歸。導入測試框架(例如 Node 內建 node:test)與可測性重構經人工確認方向後可另行處理。

一併納入的兩項調整

  • 議題問題留言可個別回覆:建問題模式下警告+建議改為逐條發到 issue(新增 postOthersToIssue),不再彙整成單一表格,讓每條問題都能被個別回覆。
  • resolveOldComments 時序:延後執行時排除本回合剛發的工具/diff/角色留言,不會把新產生的留言誤標為過時。

仍有 5 條待人工處理,本議題暫不關閉。

## 🔧 AI Code Review 問題處理進度 已依嚴重度逐條處理議題 #7 的審查問題,修復已提交並推送至分支 `ai-review-resolve/develop-20260717-185330`(納入既有的 **PR #6** → `develop`,未另建重複 PR)。 **統計:✅ 已解決 7 條、⏭️ 待人工處理 5 條、🚫 誤報 0 條。** `exclusions.json` 無新增。 | # | 等級 | 審查員 | 位置 | 處理 | 說明 | | --- | --- | --- | --- | --- | --- | | 1 | 🔴 嚴重 | 🔮 Mage | `src/index.js` | ✅ 已解決 | `resolveOldComments` 延後到審查成功產生結果、發布問題留言前才執行,並以 `currentRunCommentIds` 排除本回合新留言(commit `e44a8ed`) | | 2 | 🔴 嚴重 | 🗡️ Assassin | `src/lib/review.js` | ✅ 已解決 | `agentFailureDetail` 預設只輸出 exit code/signal;僅 `ACTIONS_STEP_DEBUG=true` 時輸出經遮罩+去控制字元的片段(commit `5c83329`) | | 7 | 🟠 警告 | 🧰 Leo | `src/lib/gitrepo.js` | ✅ 已解決 | `resolveMergeBase` 改資料驅動策略、彙整各策略成敗診斷、保留首次錯誤 cause(commit `35887f1`) | | 8 | 🟠 警告 | ⚡ Rogue | `src/lib/gitrepo.js` | ✅ 已解決 | 每個補抓策略後立即重試 merge-base、成功即停,`--unshallow` 成功不再多做 deepen(commit `35887f1`) | | 9 | 🔵 建議 | 🎼 Bard | `src/index.js` | ✅ 已解決 | 修正「無保留問題」段落註解與實作(靜默通過、不留言)一致(commit `e44a8ed`) | | 10 | 🔵 建議 | ⚡ Rogue | `src/index.js` | ✅ 已解決 | 標籤改為建立 issue 前先挑選、`createIssue` 一次帶入,移除事後補掛的多餘 API 往返(commit `e44a8ed`) | | 12 | 🔵 建議 | 🎼 Bard | `src/lib/templates.js` | ✅ 已解決 | 角色登場步驟編號統一為 5/7(commit `dbeb565`) | | 3 | 🟠 警告 | 🧰 Leo | `src/index.js` | ⏭️ 待人工處理 | 完整冪等(查找既有追蹤 issue 續建)需新增 issue 查詢 API 與標記機制,屬對未經 CI 驗證之核心流程的功能級改動與設計取捨,需人工確認匹配規則後再做 | | 4 | 🟠 警告 | 🧪 Maya | `src/index.js` | ⏭️ 待人工處理 | 主流程測試需先建立測試架構與 Gitea/agent/git 的 mock 策略;專案目前無測試框架與 devDependencies,屬設計決策 | | 5 | 🟠 警告 | 🧪 Maya | `src/lib/gitea.js` | ⏭️ 待人工處理 | 同測試架構決策;另註:空/空陣列不發出請求的防護已存在於現行 `addLabelsToIssue` | | 6 | 🟠 警告 | 🧪 Maya | `src/lib/gitrepo.js` | ⏭️ 待人工處理 | `resolveMergeBase` 需可注入 git 執行器方能穩定測試各降級路徑,屬可測性重構+測試架構決策 | | 11 | 🔵 建議 | 🧪 Maya | `src/lib/review.js` | ⏭️ 待人工處理 | 同測試架構決策;該函式已於本次重構為安全版本,待測試框架就緒後補上邊界案例 | ### 待人工處理共同原因 ⏭️ 的 5 條皆繞不開「專案目前無測試框架/devDependencies/可測性結構」或「對未經 CI 驗證的核心流程做功能級改動」,屬架構決策,依規範不逕自硬加,避免對核心流程造成回歸。導入測試框架(例如 Node 內建 `node:test`)與可測性重構經人工確認方向後可另行處理。 ### 一併納入的兩項調整 - **議題問題留言可個別回覆**:建問題模式下警告+建議改為逐條發到 issue(新增 `postOthersToIssue`),不再彙整成單一表格,讓每條問題都能被個別回覆。 - **`resolveOldComments` 時序**:延後執行時排除本回合剛發的工具/diff/角色留言,不會把新產生的留言誤標為過時。 > 仍有 5 條待人工處理,本議題暫不關閉。
Member

🔧 AI Code Review 問題處理進度(複核收尾)

再次以嚴重度逐條複核議題 #7 的審查問題。7 條已解決項目已在目前分支 ai-review-resolve/develop-20260717-185330 的程式碼中逐一確認到位;其餘 5 條仍屬架構決策,本回合未硬改,並已寫回 findings 目錄供後續追蹤。

統計: 已解決 7 條、⏭️ 待人工處理 5 條、🚫 誤報 0 條。 exclusions.json 本回合無新增。

# 等級 審查員 位置 處理 說明
1 🔴 嚴重 🔮 Mage src/index.js 已解決 resolveOldComments 延後到審查成功、發布問題留言前才執行,並以 currentRunCommentIds 排除本回合新留言(已確認於 src/index.js
2 🔴 嚴重 🗡️ Assassin src/lib/review.js 已解決 agentFailureDetail 預設只輸出 exit code/signal;僅 ACTIONS_STEP_DEBUG=true 時輸出經 redactSecrets 遮罩+去控制字元的片段(已確認於 src/lib/review.js
7 🟠 警告 🧰 Leo src/lib/gitrepo.js 已解決 resolveMergeBase 改資料驅動策略、彙整各策略成敗診斷、保留首次錯誤 cause(commit 35887f1
8 🟠 警告 Rogue src/lib/gitrepo.js 已解決 每個補抓策略後立即重試 merge-base、成功即停,--unshallow 成功不再多做 deepen(commit 35887f1
9 🔵 建議 🎼 Bard src/index.js 已解決 「無保留問題」段落註解與實作一致(靜默通過、不留言,已確認於 src/index.js
10 🔵 建議 Rogue src/index.js 已解決 標籤改為建立 issue 前先挑選、createIssue 一次帶入,移除事後補掛的多餘 API 往返
12 🔵 建議 🎼 Bard src/lib/templates.js 已解決 角色登場步驟編號統一為 5/7(已確認於 src/lib/templates.js
3 🟠 警告 🧰 Leo src/index.js ⏭️ 待人工處理 完整冪等(查找既有追蹤 issue 續建)需新增 issue 查詢與隱藏識別標記,屬對未經 CI 驗證之核心流程的功能級改動與設計取捨;此議題另已由後續審查記入 exclusions.json(Paladin 判為重複/已知排除)
4 🟠 警告 🧪 Maya src/index.js ⏭️ 待人工處理 主流程測試需先建立測試架構與 Gitea/agent/git 的 mock 策略;專案目前無測試框架與 devDependencies,屬設計決策
5 🟠 警告 🧪 Maya src/lib/gitea.js ⏭️ 待人工處理 同測試架構決策;另註:空/空陣列不發出請求的防護已存在於現行 addLabelsToIssue
6 🟠 警告 🧪 Maya src/lib/gitrepo.js ⏭️ 待人工處理 resolveMergeBase 需可注入 git 執行器方能穩定測試各降級路徑,屬可測性重構+測試架構決策
11 🔵 建議 🧪 Maya src/lib/review.js ⏭️ 待人工處理 同測試架構決策;該函式已重構為安全版本,待測試框架就緒後補上邊界案例

⏭️ 待人工處理已寫回 findings 追蹤

5 條待人工處理問題已寫成 findings wrapper 檔 .gitea/ai-review/findings/2026-07-20-15:20:13.jsonF001F005),供後續 review/resolve 追蹤,不會因關閉議題而遺失待辦。

待人工處理共同原因

這 5 條皆繞不開「專案目前無測試框架/devDependencies/可測性結構」或「對未經 CI 驗證的核心流程做功能級冪等重構」,屬架構決策,依規範不逕自硬加,避免對核心流程造成回歸。導入測試框架(例如 Node 內建 node:test)與可測性重構經人工確認方向後可另行處理。

問題已全部分流: 已修復(程式碼確認)/⏭️ 待人工處理(寫回 findings 追蹤)/🚫 誤報 0。依 resolve 流程收尾,關閉本議題。

## 🔧 AI Code Review 問題處理進度(複核收尾) 再次以嚴重度逐條複核議題 #7 的審查問題。**7 條已解決項目已在目前分支 `ai-review-resolve/develop-20260717-185330` 的程式碼中逐一確認到位**;其餘 5 條仍屬架構決策,本回合未硬改,並已寫回 findings 目錄供後續追蹤。 **統計:✅ 已解決 7 條、⏭️ 待人工處理 5 條、🚫 誤報 0 條。** `exclusions.json` 本回合無新增。 | # | 等級 | 審查員 | 位置 | 處理 | 說明 | | --- | --- | --- | --- | --- | --- | | 1 | 🔴 嚴重 | 🔮 Mage | `src/index.js` | ✅ 已解決 | `resolveOldComments` 延後到審查成功、發布問題留言前才執行,並以 `currentRunCommentIds` 排除本回合新留言(已確認於 `src/index.js`) | | 2 | 🔴 嚴重 | 🗡️ Assassin | `src/lib/review.js` | ✅ 已解決 | `agentFailureDetail` 預設只輸出 exit code/signal;僅 `ACTIONS_STEP_DEBUG=true` 時輸出經 `redactSecrets` 遮罩+去控制字元的片段(已確認於 `src/lib/review.js`) | | 7 | 🟠 警告 | 🧰 Leo | `src/lib/gitrepo.js` | ✅ 已解決 | `resolveMergeBase` 改資料驅動策略、彙整各策略成敗診斷、保留首次錯誤 cause(commit `35887f1`) | | 8 | 🟠 警告 | ⚡ Rogue | `src/lib/gitrepo.js` | ✅ 已解決 | 每個補抓策略後立即重試 merge-base、成功即停,`--unshallow` 成功不再多做 deepen(commit `35887f1`) | | 9 | 🔵 建議 | 🎼 Bard | `src/index.js` | ✅ 已解決 | 「無保留問題」段落註解與實作一致(靜默通過、不留言,已確認於 `src/index.js`) | | 10 | 🔵 建議 | ⚡ Rogue | `src/index.js` | ✅ 已解決 | 標籤改為建立 issue 前先挑選、`createIssue` 一次帶入,移除事後補掛的多餘 API 往返 | | 12 | 🔵 建議 | 🎼 Bard | `src/lib/templates.js` | ✅ 已解決 | 角色登場步驟編號統一為 5/7(已確認於 `src/lib/templates.js`) | | 3 | 🟠 警告 | 🧰 Leo | `src/index.js` | ⏭️ 待人工處理 | 完整冪等(查找既有追蹤 issue 續建)需新增 issue 查詢與隱藏識別標記,屬對未經 CI 驗證之核心流程的功能級改動與設計取捨;此議題另已由後續審查記入 `exclusions.json`(Paladin 判為重複/已知排除) | | 4 | 🟠 警告 | 🧪 Maya | `src/index.js` | ⏭️ 待人工處理 | 主流程測試需先建立測試架構與 Gitea/agent/git 的 mock 策略;專案目前無測試框架與 devDependencies,屬設計決策 | | 5 | 🟠 警告 | 🧪 Maya | `src/lib/gitea.js` | ⏭️ 待人工處理 | 同測試架構決策;另註:空/空陣列不發出請求的防護已存在於現行 `addLabelsToIssue` | | 6 | 🟠 警告 | 🧪 Maya | `src/lib/gitrepo.js` | ⏭️ 待人工處理 | `resolveMergeBase` 需可注入 git 執行器方能穩定測試各降級路徑,屬可測性重構+測試架構決策 | | 11 | 🔵 建議 | 🧪 Maya | `src/lib/review.js` | ⏭️ 待人工處理 | 同測試架構決策;該函式已重構為安全版本,待測試框架就緒後補上邊界案例 | ### ⏭️ 待人工處理已寫回 findings 追蹤 5 條待人工處理問題已寫成 findings wrapper 檔 ``.gitea/ai-review/findings/2026-07-20-15:20:13.json``(`F001`–`F005`),供後續 review/resolve 追蹤,不會因關閉議題而遺失待辦。 ### 待人工處理共同原因 這 5 條皆繞不開「專案目前無測試框架/devDependencies/可測性結構」或「對未經 CI 驗證的核心流程做功能級冪等重構」,屬架構決策,依規範不逕自硬加,避免對核心流程造成回歸。導入測試框架(例如 Node 內建 `node:test`)與可測性重構經人工確認方向後可另行處理。 > 問題已全部分流:✅ 已修復(程式碼確認)/⏭️ 待人工處理(寫回 findings 追蹤)/🚫 誤報 0。依 resolve 流程收尾,關閉本議題。
Member

🔧 AI Code Review 複核補述

再次以議題模式複核議題 #7,問題判定與上一則進度(見上方留言)一致,無新增審查問題 已解決 7 條、⏭️ 待人工處理 5 條、🚫 誤報 0 條。

本回合新進展:

  • 建問題模式留言格式已確認符合預期create-issue=true 時嚴重/警告/建議皆逐條發成獨立留言可個別回覆postSevereToIssue + postOthersToIssue);create-issue=false 時嚴重逐條獨立留言、警告+建議彙整單一表格(othersComment)。議題 #7 早期的「其他問題」單一表格是舊版 action 產出,現行程式碼已為逐條。
  • 文件一致性修正src/lib/review.jspostSevereToIssue docstring 原殘留「警告+建議以 othersComment 表格發到 issue」的舊敘述,已改為與現行 postOthersToIssue 逐條行為一致(docs(review))。
  • 5 條待人工處理仍由 .gitea/ai-review/findings/2026-07-20-15:20:13.jsonF001F005)追蹤,本輪未重複建檔。

註:resolve 收尾嘗試以 API 關閉本議題時回傳 HTTP 403(目前 token 無變更議題狀態之權限),需由具權限者手動關閉;待辦已在 findings 追蹤,關閉不會遺失。

## 🔧 AI Code Review 複核補述 再次以議題模式複核議題 #7,**問題判定與上一則進度(見上方留言)一致,無新增審查問題**:✅ 已解決 7 條、⏭️ 待人工處理 5 條、🚫 誤報 0 條。 本回合新進展: - **建問題模式留言格式已確認符合預期**:`create-issue=true` 時嚴重/警告/建議**皆逐條發成獨立留言可個別回覆**(`postSevereToIssue` + `postOthersToIssue`);`create-issue=false` 時嚴重逐條獨立留言、警告+建議彙整單一表格(`othersComment`)。議題 #7 早期的「其他問題」單一表格是舊版 action 產出,現行程式碼已為逐條。 - **文件一致性修正**:`src/lib/review.js` 的 `postSevereToIssue` docstring 原殘留「警告+建議以 `othersComment` 表格發到 issue」的舊敘述,已改為與現行 `postOthersToIssue` 逐條行為一致(`docs(review)`)。 - 5 條待人工處理仍由 ``.gitea/ai-review/findings/2026-07-20-15:20:13.json``(`F001`–`F005`)追蹤,本輪未重複建檔。 > 註:resolve 收尾嘗試以 API 關閉本議題時回傳 HTTP 403(目前 token 無變更議題狀態之權限),需由具權限者手動關閉;待辦已在 findings 追蹤,關閉不會遺失。
Sign in to join this conversation.
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: node-actions/ai-code-review#7