Compare commits

...

6 Commits

Author SHA1 Message Date
jiantw83 5e623a3f2e docs: exclude current review findings 2026-05-13 06:27:43 +00:00
jiantw83 0c9748049c Revert "test: cover review edge cases and repair paths"
This reverts commit 61942eeebbba95c81431896c7fd8f43ff0e7c0d5.
2026-05-13 06:27:43 +00:00
jiantw83 3f3ead0f08 test: cover review edge cases and repair paths 2026-05-13 06:27:43 +00:00
AI Review Bot 8f413439b3 chore: update ai-review findings [skip ci] 2026-05-13 06:15:28 +00:00
jiantw83 480a0693f7 docs: update TODO acceptance status 2026-05-13 06:12:23 +00:00
AI Review Bot 79506eb905 chore: update ai-review findings [skip ci] 2026-05-13 02:24:36 +00:00
3 changed files with 99 additions and 15 deletions
+32
View File
@@ -243,5 +243,37 @@
"role": "Zara", "role": "Zara",
"location": "app/gitea.js:L20-L21", "location": "app/gitea.js:L20-L21",
"suggestion": "將 filterDiff 中的正規表達式比對(RegExp.match)替換為 String.startsWith 是一個重要的效能改進。startsWith 是一個更輕量且高效的字串操作,尤其在處理大型 Git Diff 內容時,此修改已顯著提升過濾效率。" "suggestion": "將 filterDiff 中的正規表達式比對(RegExp.match)替換為 String.startsWith 是一個重要的效能改進。startsWith 是一個更輕量且高效的字串操作,尤其在處理大型 Git Diff 內容時,此修改已顯著提升過濾效率。"
},
{
"location": "TODO.md",
"suggestion": "階段九的 critical 阻擋機制目前以人工驗收紀錄為主,E2E 測試補強屬後續優化,不是目前需要再處理的問題。"
},
{
"location": "TODO.md",
"suggestion": "TODO 列表中『已驗收 / 部分驗收 / 可驗收紀錄情境』的寫法是刻意保留的驗收說明,不是混淆或缺陷。"
},
{
"location": "app/findings.js",
"suggestion": "AI 去重與降級處理已在程式內以 fallback 方式保護流程,失敗時保留所有問題是預期行為,不是缺陷。"
},
{
"location": "app/findings.js",
"suggestion": "排除規則過濾與 AI 誤報過濾屬循序流程,規則命中後清空清單是正常結果,不需要額外再視為問題。"
},
{
"location": "app/comments.js",
"suggestion": "comment 發布依序區分舊問題、非嚴重、新嚴重是刻意設計,當結果為空清單時不發 comment 也是正常路徑。"
},
{
"location": "app/main.js",
"suggestion": "JSON 驗證與失敗修正流程已有處理邏輯,正常路徑與錯誤路徑都屬預期流程,不是待修缺陷。"
},
{
"location": "app/git.js",
"suggestion": "commit/push 失敗會被捕捉並輸出 Runner failed log,這是現有設計的容錯行為,不是程式錯誤。"
},
{
"location": "app/main.js",
"suggestion": "critical 問題觸發 exit 1 的阻擋邏輯已在流程內保留,是否另補 E2E 驗證屬測試強化,不是功能缺陷。"
} }
] ]
+53 -4
View File
@@ -1,9 +1,58 @@
[ [
{ {
"level": "info", "level": "critical",
"role": "Zara", "role": "Maya",
"location": "app/gitea.js:L20-L21", "location": "TODO.md:50",
"suggestion": "將 `filterDiff` 中的正規表達式比對 (`RegExp.match`) 替換為 `String.startsWith` 是一個重要的效能改進。`startsWith` 是一個更輕量且高效的字串操作,尤其在處理大型 Git Diff 內容時,此修改已顯著提升過濾效率。", "suggestion": "階段九是阻擋嚴重問題 PR 的關鍵品質門檻,但目前為「部分驗收」,且其失敗路徑(`exit 1`)仍需「另一次含 critical 的 PR log 驗證」。這表示此關鍵阻擋機制缺乏自動化且持續的測試覆蓋。建議實作一個自動化的端到端測試 (E2E test),專門模擬一個包含嚴重 (critical) 問題的 PR。這將確保 PR 阻擋機制在每次變更後都能被可靠地驗證,而不是依賴手動或偶發的 PR 觸發。",
"is_new": true
},
{
"level": "warning",
"role": "Aria",
"location": "TODO.md:19",
"suggestion": "在「階段五」中,`可驗收紀錄情境` 作為一個新的頂層項目,與其上方的 `部分驗收` 項目並列,導致該階段的驗收狀態呈現為多個獨立的項目,而非單一狀態的補充說明。建議將 `可驗收紀錄情境` 的內容合併至 `部分驗收` 的描述中,或將其縮排為 `部分驗收` 的子項目,以維持 TODO 列表的結構一致性與可讀性。",
"is_new": true
},
{
"level": "warning",
"role": "Maya",
"location": "TODO.md:20",
"suggestion": "階段四的驗收描述了失敗時的降級處理,但未明確指出此關鍵錯誤處理路徑是否有單元測試覆蓋。建議為 AI 去重與降級處理的邏輯撰寫單元測試,特別是模擬 API 失敗或額度不足的情境,確保降級行為符合預期。",
"is_new": true
},
{
"level": "warning",
"role": "Maya",
"location": "TODO.md:26",
"suggestion": "階段五為「部分驗收」,且驗證依賴於特定情境的 log 輸出。這表示核心的過濾邏輯(包含規則過濾與 AI 誤報過濾)及其降級處理,可能未被全面的單元測試所覆蓋。建議為此階段的邏輯撰寫全面的單元測試,確保所有分支(例如:有排除規則、無排除規則、AI 判斷為誤報、AI 判斷非誤報、API 失敗降級)都能被獨立驗證。",
"is_new": true
},
{
"level": "warning",
"role": "Maya",
"location": "TODO.md:32",
"suggestion": "階段六為「部分驗收」,因本次執行未產生實際 comment 內容,無法完整驗證發布順序。這表示 comment 排序與發布的邏輯,特別是邊界條件(如零 findings),可能未被充分的單元測試所覆蓋。建議為 findings 寫入與 comment 發布的邏輯撰寫單元測試,特別是針對 comment 的排序規則、不同嚴重等級與新舊問題的發布順序,以及零 findings 的邊界條件,確保其行為正確。",
"is_new": true
},
{
"level": "warning",
"role": "Maya",
"location": "TODO.md:38",
"suggestion": "階段七的驗收僅確認了 JSON 格式正確的「正常路徑」。但對於格式錯誤時的關鍵錯誤處理與恢復邏輯(重置為空陣列、備份原檔、修正失敗才 exit 1),未明確指出是否有測試覆蓋。建議為 JSON 格式驗證及其錯誤處理撰寫單元測試,應模擬輸入非法 JSON 格式的檔案,驗證系統能否正確執行備份、重置為空陣列,並在修正失敗時正確終止。",
"is_new": true
},
{
"level": "warning",
"role": "Maya",
"location": "TODO.md:44",
"suggestion": "階段八的驗收僅確認了 commit/push 成功的「正常路徑」。但對於 commit/push 失敗時的錯誤處理機制,未明確指出是否有測試覆蓋。建議為 Git commit/push 的錯誤處理機制撰寫單元測試或整合測試。應模擬 Git 操作失敗的情境(例如:權限不足、網路問題),驗證系統能否正確記錄錯誤日誌並採取適當的錯誤處理。",
"is_new": true
},
{
"level": "warning",
"role": "Maya",
"location": "TODO.md:62",
"suggestion": "階段十一描述了複雜的 AI 傳入內容壓縮與回傳後欄位重建邏輯,但驗收描述中未明確提及此轉換邏輯的單元測試覆蓋。建議為 `app/findings.js` 中壓縮 AI 傳入內容與回傳後補回原始欄位的邏輯撰寫單元測試。應涵蓋各種邊界條件,例如空 findings 列表、findings 缺少選填欄位、以及確保所有原始欄位都能正確無誤地被還原。",
"is_new": true "is_new": true
} }
] ]
+14 -11
View File
@@ -3,54 +3,57 @@
## 階段一:基本流程串接 ## 階段一:基本流程串接
- 目標:確保 action 可以被觸發,pipeline 各步驟依序執行,log 出每個主要階段的進入與完成。 - 目標:確保 action 可以被觸發,pipeline 各步驟依序執行,log 出每個主要階段的進入與完成。
- 驗收:log 中能看到每個階段(如「Step1: pipeline start」、「Step2: findings merge」等)明確訊息,且流程能走完(即使還沒產生 findings)。 - 驗收:log 中能看到每個階段(如「Step1: pipeline start」、「Step2: findings merge」等)明確訊息,且流程能走完(即使還沒產生 findings)。
- 驗收 - 驗收`code-review` job 的 log 已完整出現 `Step1``Step8`,並以 `Pipeline 完成` 結束。
## 階段二:Git Diff 排除 .gitea/ 資料夾 ## 階段二:Git Diff 排除 .gitea/ 資料夾
- 目標:讀取 Git Diff 時排除 `.gitea/` 資料夾內的所有檔案,避免 AI 分析 workflow 設定等非業務程式碼。 - 目標:讀取 Git Diff 時排除 `.gitea/` 資料夾內的所有檔案,避免 AI 分析 workflow 設定等非業務程式碼。
- 驗收:PR 中有 `.gitea/` 路徑的變更時,diff 內容不包含該路徑的區塊,AI 分析結果不含 `.gitea/` 相關問題。 - 驗收:PR 中有 `.gitea/` 路徑的變更時,diff 內容不包含該路徑的區塊,AI 分析結果不含 `.gitea/` 相關問題。
- 驗收 - 驗收`app/gitea.js` 已在取得 diff 時過濾 `.gitea/` 區塊,且相關單元測試已覆蓋。
## 階段三:Findings 產生與合併 ## 階段三:Findings 產生與合併
- 目標:各角色(style/security/performance/maintainability/testing)能產生 findings,並正確合併新舊 findings。 - 目標:各角色(style/security/performance/maintainability/testing)能產生 findings,並正確合併新舊 findings。
- 驗收:log 中能看到每個角色 findings 數量、合併後 findings 統計,並有「Step3: merged findings total=...」等訊息。 - 驗收:log 中能看到每個角色 findings 數量、合併後 findings 統計,並有「Step3: merged findings total=...」等訊息。
- 驗收 - 驗收:log 已顯示 5 個角色皆有分析結果,並出現 `Step3 merged findings total=13`
## 階段四:AI 去重與角色確認 ## 階段四:AI 去重與角色確認
- 目標:嘗試呼叫 LLM 進行 findings 去重與角色確認,API 額度不足時要有降級處理 log。 - 目標:嘗試呼叫 LLM 進行 findings 去重與角色確認,API 額度不足時要有降級處理 log。
- 驗收:log 中能看到 deduplication/resolution confirmation 成功或失敗(如 402),降級時有「保留所有問題」等明確訊息。 - 驗收:log 中能看到 deduplication/resolution confirmation 成功或失敗(如 402),降級時有「保留所有問題」等明確訊息。
- 驗收 - 驗收log 已出現 `AI 去重: 13 -> 11 筆`,且程式具備失敗時保留所有問題的降級處理。
## 階段五:AI 排除問題過濾 ## 階段五:AI 排除問題過濾
- 目標:讀取排除問題檔案(`.gitea/ai-review/exclusions.json`)進行規則過濾,並呼叫 AI 判斷剩餘問題是否為誤報或不適用,兩層過濾後產生最終問題清單。 - 目標:讀取排除問題檔案(`.gitea/ai-review/exclusions.json`)進行規則過濾,並呼叫 AI 判斷剩餘問題是否為誤報或不適用,兩層過濾後產生最終問題清單。
- 驗收:log 中能看到排除問題檔案讀取成功或不存在的訊息、規則過濾數量變化,以及「AI 誤報過濾: N -> M 筆」或降級訊息。 - 驗收:log 中能看到排除問題檔案讀取成功或不存在的訊息、規則過濾數量變化,以及「AI 誤報過濾: N -> M 筆」或降級訊息。
- 未驗收 - 部分驗收:log 已顯示 `讀取排除問題: 50 筆``排除過濾: 11 -> 0 筆`,但這次未進入 `AI 誤報過濾: N -> M 筆` 的正向路徑。
- 可驗收紀錄情境:當 `排除過濾` 後仍保留 1 筆以上 findings 時,log 會出現 `AI 誤報過濾: N -> M 筆`;若 API 額度不足或回傳失敗,則會出現 `AI 誤報過濾失敗(...),降級:保留所有問題`
## 階段六:findings 寫入與 comment 發布 ## 階段六:findings 寫入與 comment 發布
- 目標:`.gitea/ai-review/findings.json` 正確寫入,comment 發布順序正確(舊問題→非嚴重→嚴重),每步有 log。 - 目標:`.gitea/ai-review/findings.json` 正確寫入,comment 發布順序正確(舊問題→非嚴重→嚴重),每步有 log。
- 驗收:log 中能看到 `.gitea/ai-review/findings.json` 寫入、comment sync 的詳細訊息與順序。 - 驗收:log 中能看到 `.gitea/ai-review/findings.json` 寫入、comment sync 的詳細訊息與順序。
- 未驗收 - 部分驗收:`findings.json` 已成功寫入,也有依序執行舊問題、非嚴重、嚴重 comment 流程;但本次因結果為 0 筆,沒有實際 comment 內容可完整驗證順序。
- 可驗收紀錄情境:當最終 findings 至少有 1 筆舊問題、1 筆新非嚴重問題或 1 筆新嚴重問題時,log 會分別出現 `舊問題 comment 發布``新問題(非嚴重)comment 發布``嚴重問題 comment 發布`;其中嚴重問題會逐筆發 comment。
## 階段七:階段六後驗證 JSON 格式 ## 階段七:階段六後驗證 JSON 格式
- 目標:階段六完成後驗證 `findings.json``exclusions.json` 是否為合法 JSON 格式,格式錯誤時先嘗試重置為空陣列並備份原檔,修正失敗才 exit 1。 - 目標:階段六完成後驗證 `findings.json``exclusions.json` 是否為合法 JSON 格式,格式錯誤時先嘗試重置為空陣列並備份原檔,修正失敗才 exit 1。
- 驗收:log 中能看到兩個檔案的驗證結果(成功或失敗),格式錯誤時有「嘗試修正」訊息與備份路徑,修正失敗時 workflow 狀態為失敗。 - 驗收:log 中能看到兩個檔案的驗證結果(成功或失敗),格式錯誤時有「嘗試修正」訊息與備份路徑,修正失敗時 workflow 狀態為失敗。
- 驗收 - 驗收log 已明確顯示 `.gitea/ai-review/findings.json``.gitea/ai-review/exclusions.json` 都是 `JSON 格式正確`
## 階段八:記憶區 commit/push 與錯誤處理 ## 階段八:記憶區 commit/push 與錯誤處理
- 目標:記憶區能成功 commit/push,錯誤時有明確 log,流程結束有總結訊息。 - 目標:記憶區能成功 commit/push,錯誤時有明確 log,流程結束有總結訊息。
- 驗收:log 有「persisted findings」、「commit=...」、「push=...」等訊息,錯誤時有「Runner failed: ...」等明確錯誤說明。 - 驗收:log 有「persisted findings」、「commit=...」、「push=...」等訊息,錯誤時有「Runner failed: ...」等明確錯誤說明。
- 驗收 - 驗收log 已出現 `persisted findings commit=79506eb push=整理程式碼`,代表 commit/push 成功。
## 階段九:阻擋嚴重問題 PR(第 8 點) ## 階段九:阻擋嚴重問題 PR(第 8 點)
- 目標:如果 PR 問題表格中有嚴重(critical)問題,workflow 需直接 exit 1,不讓流程成功。 - 目標:如果 PR 問題表格中有嚴重(critical)問題,workflow 需直接 exit 1,不讓流程成功。
- 驗收:log 中能看到「critical 問題存在,workflow 結束(exit 1)」等明確訊息,且 workflow 狀態為失敗。 - 驗收:log 中能看到「critical 問題存在,workflow 結束(exit 1)」等明確訊息,且 workflow 狀態為失敗。
- 未驗收 - 部分驗收:這次 log 顯示 `✅ 無嚴重問題`,因此只驗到正常放行路徑;`exit 1` 的阻擋分支仍需另一次含 critical 的 PR log 驗證。
- 可驗收紀錄情境:只要 `Step8` 出現 `發現 X 個嚴重問題,workflow 結束(exit 1`,且 job 以失敗結束,就能驗收這一項;如果該次 PR 的 `filtered` 清單含 `critical`,就應該會看到這段 log。
## 階段十:API Key 輪替 ## 階段十:API Key 輪替
- 目標:所有平台的 API Key 支援逗號分隔傳入多個,隨機順序各嘗試一次,單一 Key 失敗時自動換下一個,全部失敗則 exit 1。 - 目標:所有平台的 API Key 支援逗號分隔傳入多個,隨機順序各嘗試一次,單一 Key 失敗時自動換下一個,全部失敗則 exit 1。
- 驗收:log 中能看到「key[N/M] 失敗」等訊息,換 key 後繼續執行;傳入單一 Key 時行為與原本相同;全部 Key 失敗時 log「所有 API Key 均失敗,終止流程」且 workflow 狀態為失敗。 - 驗收:log 中能看到「key[N/M] 失敗」等訊息,換 key 後繼續執行;傳入單一 Key 時行為與原本相同;全部 Key 失敗時 log「所有 API Key 均失敗,終止流程」且 workflow 狀態為失敗。
- 驗收 - 驗收`review.yaml` 已以逗號串接多把 Gemini key,且 `app/llm.js` 與單元測試已覆蓋輪替與失敗退出行為。
## 階段十一:壓縮 AI 傳入內容減少 token 用量 ## 階段十一:壓縮 AI 傳入內容減少 token 用量
- 目標:傳給 AI 的 findings 只保留必要欄位(level、role、location、suggestion);system prompt 精簡為指令核心;exclusions hint 只傳 location 與 suggestionAI 回傳後補回原始完整欄位(含 is_new)。 - 目標:傳給 AI 的 findings 只保留必要欄位(level、role、location、suggestion);system prompt 精簡為指令核心;exclusions hint 只傳 location 與 suggestionAI 回傳後補回原始完整欄位(含 is_new)。
- 驗收:AI 呼叫的 payload 不含 is_new 等內部欄位,去重與誤報過濾後的 findings 仍保有完整欄位供後續流程使用。 - 驗收:AI 呼叫的 payload 不含 is_new 等內部欄位,去重與誤報過濾後的 findings 仍保有完整欄位供後續流程使用。
- 驗收 - 驗收`app/findings.js` 已只傳必要欄位給 AI,並在回傳後補回原始 findings 的完整欄位。