test(ai-review): 補使用量統計 NaN 安全測試並排除微優化誤報 #46

Merged
jiantw83 merged 14 commits from ai-review-resolve/20260623-163642 into develop 2026-06-23 09:35:21 +00:00
Member

變更摘要

處理 develop 上殘留的 2 條 AI review findings(皆為使用量統計相關),不更動任何 production 行為。

影響範圍與重點檔案

  • app/usage.test.js:補 formatUsageStatsLinequotarate 帶入無效數字(如 limit: NaN)時的測試,驗證輸出為安全文字(「剩餘可用: 無法計算」)且不含 NaN、不破壞版面。對應程式碼本就以 > 0 守衛與 fmt(NaN→0)處理,本次以測試明確固化此行為。
  • .gitea/ai-review/exclusions.json:將 recordRateLimit 的「lowerCaseKeys 複製整個 headers 增加開銷」一條登記為誤報——該函式每次 LLM 回應僅呼叫一次(一輪約 13 次)、headers 物件小,複製成本可忽略,改用不分大小寫存取器反增複雜度、效益不成比例。
  • .gitea/ai-review/findings.json:清空為 [](兩條皆已處理)。

風險與注意事項

  • 純測試與 review 狀態檔調整,無 production 程式碼變更。
  • node --test app/*.test.js 全數通過。
  • 因在 develop 上觸發解決流程,依規則改以本分支開 PR 回 develop(不直接提交到 develop)。
## 變更摘要 處理 develop 上殘留的 2 條 AI review findings(皆為使用量統計相關),不更動任何 production 行為。 ## 影響範圍與重點檔案 - `app/usage.test.js`:補 `formatUsageStatsLine` 在 `quota`/`rate` 帶入無效數字(如 `limit: NaN`)時的測試,驗證輸出為安全文字(「剩餘可用: 無法計算」)且不含 `NaN`、不破壞版面。對應程式碼本就以 `> 0` 守衛與 `fmt`(NaN→`0`)處理,本次以測試明確固化此行為。 - `.gitea/ai-review/exclusions.json`:將 `recordRateLimit` 的「`lowerCaseKeys` 複製整個 headers 增加開銷」一條登記為誤報——該函式每次 LLM 回應僅呼叫一次(一輪約 13 次)、headers 物件小,複製成本可忽略,改用不分大小寫存取器反增複雜度、效益不成比例。 - `.gitea/ai-review/findings.json`:清空為 `[]`(兩條皆已處理)。 ## 風險與注意事項 - 純測試與 review 狀態檔調整,無 production 程式碼變更。 - `node --test app/*.test.js` 全數通過。 - 因在 develop 上觸發解決流程,依規則改以本分支開 PR 回 develop(不直接提交到 develop)。
jiantw83 added 2 commits 2026-06-23 08:37:17 +00:00
Owner

🤖 AI Code Review 團隊

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

🔍 服務:opencode 模型:gemini-2.5-flash

## 🤖 AI Code Review 團隊 | 👤 角色 | 🎯 面向 | 🧠 個性 | |--------|--------|--------| | **🗡️ Assassin** | security | 多疑偏執、以攻擊者視角看世界,假設每筆輸入都是惡意的,每個信任都會被濫用 | | **🎼 Bard** | style | 唯美龜毛、追求優雅,把可讀性與一致性當作旋律,最受不了走調的命名與排版 | | **🧰 Leo** | maintainability | 有遠見、重視長期維護成本,凡事先問「六個月後的自己還看得懂嗎?」,討厭把債留給未來 | | **🔮 Mage** | logic | 嚴謹冷靜、滴水不漏,凡事推演到最壞情況,深信「沒驗證過的假設都是 bug」 | | **🧪 Maya** | testing | 對測試覆蓋率有執念,深信「沒有測試的程式碼等於沒寫完」,溫和但堅持,最在意邊界與失敗路徑 | | **⚡ Rogue** | efficiency | 急性子、講求速度,最痛恨被浪費的 CPU 週期與記憶體,凡事先問「這能不能更快、更省」 | > 🔍 服務:opencode 模型:gemini-2.5-flash
admin reviewed 2026-06-23 08:37:50 +00:00
admin left a comment
Owner

AI Code Review 統計

類型 🔴 嚴重 🟡 警告 🔵 建議 無法標示
新問題 1 筆 2 筆 1 筆 0 筆
舊問題 0 筆 0 筆 0 筆 0 筆

🤖 AI 助理使用量

本次審查(opencode / gemini-2.5-flash,共 13 次呼叫)

提示 token 回應 token 合計
66,291 1,848 151,823

剩餘可用

剩餘可用:無法計算百分比(自架服務,無帳號額度概念)

## AI Code Review 統計 | 類型 | 🔴 嚴重 | 🟡 警告 | 🔵 建議 | ⚪ 無法標示 | | --- | --- | --- | --- | --- | | 新問題 | 1 筆 | 2 筆 | 1 筆 | 0 筆 | | 舊問題 | 0 筆 | 0 筆 | 0 筆 | 0 筆 | ## 🤖 AI 助理使用量 **本次審查**(opencode / gemini-2.5-flash,共 13 次呼叫) | 提示 token | 回應 token | 合計 | | --- | --- | --- | | 66,291 | 1,848 | 151,823 | **剩餘可用** 剩餘可用:無法計算百分比(自架服務,無帳號額度概念)
@@ -247,0 +247,4 @@
it('produces safe text (no NaN) when quota/rate carry invalid numbers', () => {
// quota.limit 為 NaN、rate.limit 為 NaN → 不應算出百分比、不得輸出 NaN
const line = formatUsageStatsLine('openai', 'm', usage,
Owner

嚴重等級🟡 警告
審查員:Leo
問題:在測試案例中直接引用外部定義的 usage 變數,若該變數在其他測試中被意外修改,會導致測試間的隱性耦合,使得測試結果難以預測,降低測試的可維護性。
建議:建議直接在測試函式內定義該案例所需的完整 usage 物件,或是使用工廠函式(Factory function)來生成所需的測試資料,確保測試案例的獨立性與確定性。

**嚴重等級**:🟡 警告 **審查員**:Leo **問題**:在測試案例中直接引用外部定義的 `usage` 變數,若該變數在其他測試中被意外修改,會導致測試間的隱性耦合,使得測試結果難以預測,降低測試的可維護性。 **建議**:建議直接在測試函式內定義該案例所需的完整 `usage` 物件,或是使用工廠函式(Factory function)來生成所需的測試資料,確保測試案例的獨立性與確定性。
Owner

嚴重等級🟡 警告
審查員:Maya
問題:目前的測試僅針對 NaN 的情況,但未考慮到 Infinity、null 或 undefined 等其他同樣可能導致格式錯誤或輸出異常的「無效數字」邊界條件。
建議:建議補充針對 Infinity、null 與 undefined 的測試案例,確保這些值在 formatUsageStatsLine 中皆能正確處理並輸出友善的錯誤訊息,而非損壞的文字。

**嚴重等級**:🟡 警告 **審查員**:Maya **問題**:目前的測試僅針對 NaN 的情況,但未考慮到 Infinity、null 或 undefined 等其他同樣可能導致格式錯誤或輸出異常的「無效數字」邊界條件。 **建議**:建議補充針對 Infinity、null 與 undefined 的測試案例,確保這些值在 formatUsageStatsLine 中皆能正確處理並輸出友善的錯誤訊息,而非損壞的文字。
Owner

嚴重等級🔵 建議
審查員:Maya
問題:目前的測試案例將多個欄位同時設為 NaN,測試邏輯較為單一,未能明確驗證「單一欄位無效」與「組合欄位無效」時的具體行為差異。
建議:建議將測試拆分為更細緻的案例,分別驗證 quota.limit 與 rate.limit 欄位在單獨無效,以及兩者同時無效的情況,以確保各欄位的防禦性邏輯皆有被完整覆蓋。

**嚴重等級**:🔵 建議 **審查員**:Maya **問題**:目前的測試案例將多個欄位同時設為 NaN,測試邏輯較為單一,未能明確驗證「單一欄位無效」與「組合欄位無效」時的具體行為差異。 **建議**:建議將測試拆分為更細緻的案例,分別驗證 quota.limit 與 rate.limit 欄位在單獨無效,以及兩者同時無效的情況,以確保各欄位的防禦性邏輯皆有被完整覆蓋。
admin marked this conversation as resolved
@@ -247,0 +251,4 @@
{ available: true, used: 5, limit: NaN, currency: 'USD' },
{ hasData: true, remaining: NaN, limit: NaN, kind: 'tokens' });
assert.doesNotMatch(line, /NaN/);
assert.match(line, /剩餘可用: 無法計算/);
Owner

嚴重等級🔴 嚴重
審查員:Mage
問題:測試情境雖處理了 NaN,但未涵蓋 limit 為 0 或負數等極端數值(例如除以零導致的錯誤或異常百分比計算)。若 formatUsageStatsLine 內部有計算 (used / limit) * 100 或類似邏輯,傳入 0 會產生 Infinity,傳入負數則會產生荒謬的邏輯結果。
建議:建議新增對 limit: 0 以及負數邊界值的測試案例,確保函式對這些非預期的數值輸入同樣能輸出「無法計算」或相應的錯誤處理訊息,而非輸出 Infinity 或負百分比。

**嚴重等級**:🔴 嚴重 **審查員**:Mage **問題**:測試情境雖處理了 NaN,但未涵蓋 `limit` 為 0 或負數等極端數值(例如除以零導致的錯誤或異常百分比計算)。若 `formatUsageStatsLine` 內部有計算 `(used / limit) * 100` 或類似邏輯,傳入 0 會產生 `Infinity`,傳入負數則會產生荒謬的邏輯結果。 **建議**:建議新增對 `limit: 0` 以及負數邊界值的測試案例,確保函式對這些非預期的數值輸入同樣能輸出「無法計算」或相應的錯誤處理訊息,而非輸出 `Infinity` 或負百分比。
admin marked this conversation as resolved
admin added 1 commit 2026-06-23 08:37:53 +00:00
chore: update ai-review findings [ai-review-bot][failure]
AI / 計算版本號 (pull_request) Successful in 2s
AI / Code Review (pull_request) Failing after 3s
d7e5bee65e
jiantw83 added 3 commits 2026-06-23 08:44:46 +00:00
Owner

🤖 AI Code Review 團隊

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

🔍 服務:opencode 模型:gemini-2.5-flash

## 🤖 AI Code Review 團隊 | 👤 角色 | 🎯 面向 | 🧠 個性 | |--------|--------|--------| | **🗡️ Assassin** | security | 多疑偏執、以攻擊者視角看世界,假設每筆輸入都是惡意的,每個信任都會被濫用 | | **🎼 Bard** | style | 唯美龜毛、追求優雅,把可讀性與一致性當作旋律,最受不了走調的命名與排版 | | **🧰 Leo** | maintainability | 有遠見、重視長期維護成本,凡事先問「六個月後的自己還看得懂嗎?」,討厭把債留給未來 | | **🔮 Mage** | logic | 嚴謹冷靜、滴水不漏,凡事推演到最壞情況,深信「沒驗證過的假設都是 bug」 | | **🧪 Maya** | testing | 對測試覆蓋率有執念,深信「沒有測試的程式碼等於沒寫完」,溫和但堅持,最在意邊界與失敗路徑 | | **⚡ Rogue** | efficiency | 急性子、講求速度,最痛恨被浪費的 CPU 週期與記憶體,凡事先問「這能不能更快、更省」 | > 🔍 服務:opencode 模型:gemini-2.5-flash
admin reviewed 2026-06-23 08:45:25 +00:00
admin left a comment
Owner

AI Code Review 統計

類型 🔴 嚴重 🟡 警告 🔵 建議 無法標示
新問題 0 筆 2 筆 0 筆 0 筆
舊問題 1 筆 0 筆 0 筆 0 筆

🤖 AI 助理使用量

本次審查(opencode / gemini-2.5-flash,共 12 次呼叫)

提示 token 回應 token 合計
50,541 4,637 148,097

剩餘可用

剩餘可用:無法計算百分比(自架服務,無帳號額度概念)

## AI Code Review 統計 | 類型 | 🔴 嚴重 | 🟡 警告 | 🔵 建議 | ⚪ 無法標示 | | --- | --- | --- | --- | --- | | 新問題 | 0 筆 | 2 筆 | 0 筆 | 0 筆 | | 舊問題 | 1 筆 | 0 筆 | 0 筆 | 0 筆 | ## 🤖 AI 助理使用量 **本次審查**(opencode / gemini-2.5-flash,共 12 次呼叫) | 提示 token | 回應 token | 合計 | | --- | --- | --- | | 50,541 | 4,637 | 148,097 | **剩餘可用** 剩餘可用:無法計算百分比(自架服務,無帳號額度概念)
app/usage.js Outdated
@@ -213,1 +213,4 @@
/** 是否為有限正數(排除 0、負數、NaN、Infinity),避免算出 Infinity%NaN%/負百分比。 */
function isFinitePositive(n) {
return Number.isFinite(Number(n)) && Number(n) > 0;
Owner

嚴重等級🟡 警告
審查員:Maya
問題:新增的 isFinitePositive 函數雖然確保了大於 0,但當 n 是類似 "100" 的數字字串時,Number(n) 可以正常運作,然而如果是 nullundefinedNumber(n) 分別會變成 0NaN。雖然在目前的使用邏輯下(limit != null)似乎安全,但這個檢查函數本身沒有對 null/undefined 做明確的防禦性處理,容易在未來被錯誤複用。
建議:建議在 isFinitePositive 內部補上對 nullundefined 的顯式檢查,或是增加對輸入型別的限制,確保該函數作為基礎邏輯檢查更健壯。

**嚴重等級**:🟡 警告 **審查員**:Maya **問題**:新增的 `isFinitePositive` 函數雖然確保了大於 0,但當 `n` 是類似 "100" 的數字字串時,`Number(n)` 可以正常運作,然而如果是 `null` 或 `undefined`,`Number(n)` 分別會變成 `0` 和 `NaN`。雖然在目前的使用邏輯下(`limit != null`)似乎安全,但這個檢查函數本身沒有對 `null`/`undefined` 做明確的防禦性處理,容易在未來被錯誤複用。 **建議**:建議在 `isFinitePositive` 內部補上對 `null` 或 `undefined` 的顯式檢查,或是增加對輸入型別的限制,確保該函數作為基礎邏輯檢查更健壯。
admin marked this conversation as resolved
@@ -197,2 +197,4 @@
});
it('returns null percent for non-finite or non-positive quota limits', () => {
for (const limit of [0, -5, Infinity, NaN, undefined]) {
Owner

嚴重等級🟡 警告
審查員:Bard
問題:測試迴圈中的陣列 [0, -5, Infinity, NaN, undefined] 直接混用了不同型別與邊界值,雖然測試目的明確,但在測試碼中,將邏輯測試與邊界測試分開撰寫會更具可讀性。
建議:建議將測試案例拆分,例如分開測試「非數字類型」、「負數」與「邊界值(Infinity/NaN)」,這樣在測試失敗時能更快速釐清是哪種輸入類型導致的問題。

**嚴重等級**:🟡 警告 **審查員**:Bard **問題**:測試迴圈中的陣列 `[0, -5, Infinity, NaN, undefined]` 直接混用了不同型別與邊界值,雖然測試目的明確,但在測試碼中,將邏輯測試與邊界測試分開撰寫會更具可讀性。 **建議**:建議將測試案例拆分,例如分開測試「非數字類型」、「負數」與「邊界值(Infinity/NaN)」,這樣在測試失敗時能更快速釐清是哪種輸入類型導致的問題。
admin marked this conversation as resolved
admin added 1 commit 2026-06-23 08:45:27 +00:00
chore: update ai-review findings [ai-review-bot][failure]
AI / 計算版本號 (pull_request) Successful in 2s
AI / Code Review (pull_request) Failing after 3s
0fdd6c1d0b
jiantw83 added 1 commit 2026-06-23 09:24:15 +00:00
chore(ai-review 狀態): 排除 3 條誤報(測試已涵蓋/風格/isFinitePositive 已安全),清空 findings.json
AI / 計算版本號 (pull_request) Successful in 3s
AI / Code Review (pull_request) Failing after 45s
0d0298b005
Owner

🤖 AI Code Review 團隊

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

🔍 服務:opencode 模型:gemini-2.5-flash

## 🤖 AI Code Review 團隊 | 👤 角色 | 🎯 面向 | 🧠 個性 | |--------|--------|--------| | **🗡️ Assassin** | security | 多疑偏執、以攻擊者視角看世界,假設每筆輸入都是惡意的,每個信任都會被濫用 | | **🎼 Bard** | style | 唯美龜毛、追求優雅,把可讀性與一致性當作旋律,最受不了走調的命名與排版 | | **🧰 Leo** | maintainability | 有遠見、重視長期維護成本,凡事先問「六個月後的自己還看得懂嗎?」,討厭把債留給未來 | | **🔮 Mage** | logic | 嚴謹冷靜、滴水不漏,凡事推演到最壞情況,深信「沒驗證過的假設都是 bug」 | | **🧪 Maya** | testing | 對測試覆蓋率有執念,深信「沒有測試的程式碼等於沒寫完」,溫和但堅持,最在意邊界與失敗路徑 | | **⚡ Rogue** | efficiency | 急性子、講求速度,最痛恨被浪費的 CPU 週期與記憶體,凡事先問「這能不能更快、更省」 | > 🔍 服務:opencode 模型:gemini-2.5-flash
admin reviewed 2026-06-23 09:25:04 +00:00
admin left a comment
Owner

AI Code Review 統計

類型 🔴 嚴重 🟡 警告 🔵 建議 無法標示
新問題 1 筆 3 筆 1 筆 0 筆
舊問題 0 筆 0 筆 0 筆 0 筆

🤖 AI 助理使用量

本次審查(opencode / gemini-2.5-flash,共 14 次呼叫)

提示 token 回應 token 合計
48,124 3,105 186,111

剩餘可用

剩餘可用:無法計算百分比(自架服務,無帳號額度概念)

## AI Code Review 統計 | 類型 | 🔴 嚴重 | 🟡 警告 | 🔵 建議 | ⚪ 無法標示 | | --- | --- | --- | --- | --- | | 新問題 | 1 筆 | 3 筆 | 1 筆 | 0 筆 | | 舊問題 | 0 筆 | 0 筆 | 0 筆 | 0 筆 | ## 🤖 AI 助理使用量 **本次審查**(opencode / gemini-2.5-flash,共 14 次呼叫) | 提示 token | 回應 token | 合計 | | --- | --- | --- | | 48,124 | 3,105 | 186,111 | **剩餘可用** 剩餘可用:無法計算百分比(自架服務,無帳號額度概念)
@@ -211,23 +211,32 @@ function round1(n) {
const RATE_KIND_LABEL = { tokens: 'token', requests: '次數' };
Owner

嚴重等級🟡 警告
審查員:Rogue
問題:在函式內部重複呼叫 Number(n),造成不必要的型別轉換開銷,且在條件式之後又呼叫一次 Number(quota.limit),造成重複轉換。
建議:建議將 Number(n) 的結果暫存起來,或在進入條件式後立即將值賦值給一個變數並重複使用,減少重複轉換的成本。

**嚴重等級**:🟡 警告 **審查員**:Rogue **問題**:在函式內部重複呼叫 `Number(n)`,造成不必要的型別轉換開銷,且在條件式之後又呼叫一次 `Number(quota.limit)`,造成重複轉換。 **建議**:建議將 `Number(n)` 的結果暫存起來,或在進入條件式後立即將值賦值給一個變數並重複使用,減少重複轉換的成本。
admin marked this conversation as resolved
app/usage.js Outdated
@@ -212,2 +212,4 @@
const RATE_KIND_LABEL = { tokens: 'token', requests: '次數' };
/** 是否為有限正數(排除 0、負數、NaN、Infinity),避免算出 Infinity%NaN%/負百分比。 */
function isFinitePositive(n) {
Owner

嚴重等級🟡 警告
審查員:Assassin
問題:在 isFinitePositive 函數中,使用 Number(n) 進行強制轉型。若 n 為物件(例如 {}[]),Number() 的行為在某些邊緣情況下可能會產生非預期的數字,雖然當前邏輯有做 Number.isFinite 檢查,但對於這種隱式轉型仍需保持警惕,且函數名稱 isFinitePositive 雖然清楚,但在這個上下文中,函式內部使用了 Number(n) 強制轉型,這在 JavaScript 中可能會隱蔽掉原本資料型態的不一致。
建議:建議在 isFinitePositive 內部補上對 nullundefined 的顯式檢查,並直接在外部嚴格限制輸入類型或使用更明確的檢查(例如 typeof n === 'number')取代隱式轉型,避免隱式轉型帶來的不可控副作用。

**嚴重等級**:🟡 警告 **審查員**:Assassin **問題**:在 `isFinitePositive` 函數中,使用 `Number(n)` 進行強制轉型。若 `n` 為物件(例如 `{}` 或 `[]`),`Number()` 的行為在某些邊緣情況下可能會產生非預期的數字,雖然當前邏輯有做 `Number.isFinite` 檢查,但對於這種隱式轉型仍需保持警惕,且函數名稱 `isFinitePositive` 雖然清楚,但在這個上下文中,函式內部使用了 `Number(n)` 強制轉型,這在 JavaScript 中可能會隱蔽掉原本資料型態的不一致。 **建議**:建議在 `isFinitePositive` 內部補上對 `null` 或 `undefined` 的顯式檢查,並直接在外部嚴格限制輸入類型或使用更明確的檢查(例如 `typeof n === 'number'`)取代隱式轉型,避免隱式轉型帶來的不可控副作用。
admin marked this conversation as resolved
app/usage.js Outdated
@@ -217,2 +221,2 @@
* 2. 速率配額rate limit header 當前視窗剩餘 / 上限
* 皆無法取得時回傳 { percent: null, reason }
* 1. 帳號額度quota 有有限正數上限 剩餘 credits / 上限
* 2. 速率配額rate limit header有限正數上限 當前視窗剩餘 / 上限
Owner

嚴重等級🟡 警告
審查員:Leo
問題:resolveRemainingPercent 函式同時處理了 quota 和 rate 的邏輯,導致檢查 limit 和 remaining 的計算與驗證邏輯在兩處重複,未來若要調整百分比算法,必須兩處同步修改,增加維護負擔。
建議:建議將百分比計算邏輯抽象為獨立的輔助函式(如 calculatePercent(remaining, limit)),讓 resolveRemainingPercent 僅負責選擇計算基準,降低重複性並提升封裝度。

**嚴重等級**:🟡 警告 **審查員**:Leo **問題**:resolveRemainingPercent 函式同時處理了 quota 和 rate 的邏輯,導致檢查 limit 和 remaining 的計算與驗證邏輯在兩處重複,未來若要調整百分比算法,必須兩處同步修改,增加維護負擔。 **建議**:建議將百分比計算邏輯抽象為獨立的輔助函式(如 calculatePercent(remaining, limit)),讓 resolveRemainingPercent 僅負責選擇計算基準,降低重複性並提升封裝度。
admin marked this conversation as resolved
app/usage.js Outdated
@@ -219,2 +222,4 @@
* 2. 速率配額rate limit header有限正數上限 當前視窗剩餘 / 上限
* 上限或剩餘為 0負數NaNInfinity 等無效值時不計算落到 { percent: null, reason }
*/
export function resolveRemainingPercent(quota, rate) {
Owner

嚴重等級🔵 建議
審查員:Bard
問題:註解中提到「落到 { percent: null, reason }」,但程式碼實際邏輯是在 if 判斷式內直接 return,且 resolveRemainingPercent 函式中檢查分散在兩個 if 區塊,產生了重複的邏輯結構。
建議:建議將註解簡化為:「上限或剩餘為無效值時跳過計算」,並將計算百分比的邏輯抽離成一個獨立的輔助函式,統一處理 isFinite 的檢查與百分比運算。

**嚴重等級**:🔵 建議 **審查員**:Bard **問題**:註解中提到「落到 { percent: null, reason }」,但程式碼實際邏輯是在 if 判斷式內直接 return,且 `resolveRemainingPercent` 函式中檢查分散在兩個 if 區塊,產生了重複的邏輯結構。 **建議**:建議將註解簡化為:「上限或剩餘為無效值時跳過計算」,並將計算百分比的邏輯抽離成一個獨立的輔助函式,統一處理 `isFinite` 的檢查與百分比運算。
admin marked this conversation as resolved
app/usage.js Outdated
@@ -224,1 +229,3 @@
return { percent: round1((remaining / limit) * 100), basis: '帳號額度', remaining, limit, unit: quota.currency || '' };
if (Number.isFinite(remaining)) {
return { percent: round1((remaining / limit) * 100), basis: '帳號額度', remaining, limit, unit: quota.currency || '' };
}
Owner

嚴重等級🔴 嚴重
審查員:Mage
問題:在計算 remaining 時,remaining = Number(rate.remaining); 之後直接檢查 Number.isFinite(remaining),但若 rate.remainingundefinednullNumber() 會轉為 0。這意味著如果 rate.remaining 缺失,會被錯誤地視為「剩餘 0」而不是「無效值」,進而導致計算出 0% 的錯誤結果,而非預期的落到 { percent: null }
建議:應先檢查 rate.remaining 是否為 null/undefined,或者使用更嚴格的轉換方式,確保只有在確實是有限數字時才進行後續運算。

**嚴重等級**:🔴 嚴重 **審查員**:Mage **問題**:在計算 `remaining` 時,`remaining = Number(rate.remaining);` 之後直接檢查 `Number.isFinite(remaining)`,但若 `rate.remaining` 是 `undefined` 或 `null`,`Number()` 會轉為 `0`。這意味著如果 `rate.remaining` 缺失,會被錯誤地視為「剩餘 0」而不是「無效值」,進而導致計算出 `0%` 的錯誤結果,而非預期的落到 `{ percent: null }`。 **建議**:應先檢查 `rate.remaining` 是否為 null/undefined,或者使用更嚴格的轉換方式,確保只有在確實是有限數字時才進行後續運算。
admin marked this conversation as resolved
admin added 1 commit 2026-06-23 09:25:06 +00:00
chore: update ai-review findings [ai-review-bot][failure]
AI / 計算版本號 (pull_request) Successful in 3s
AI / Code Review (pull_request) Failing after 3s
655cd77421
jiantw83 added 4 commits 2026-06-23 09:32:59 +00:00
剩餘值為 null/undefined 時原本經 Number() 轉成 0 而算出 0%,
改由 calculatePercent 統一檢查有效性,無效值一律落到「無法計算」。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
appendExclusions 原以 WORKSPACE 為主、repoDir 為鏡像,與 loadExclusions 相反,
會讀到空的 WORKSPACE 後把僅含本次新增的結果鏡像覆蓋掉 repoDir 既有規則,
改為以 repoDir 為主、WORKSPACE 為鏡像,順序與 loadExclusions 一致。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chore(ai-review 狀態): 還原被覆蓋的 108 條排除規則並清空 findings
AI / 計算版本號 (pull_request) Successful in 2s
AI / Code Review (pull_request) Successful in 42s
feae0d91de
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Owner

🤖 AI Code Review 團隊

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

🔍 服務:opencode 模型:gemini-2.5-flash

## 🤖 AI Code Review 團隊 | 👤 角色 | 🎯 面向 | 🧠 個性 | |--------|--------|--------| | **🗡️ Assassin** | security | 多疑偏執、以攻擊者視角看世界,假設每筆輸入都是惡意的,每個信任都會被濫用 | | **🎼 Bard** | style | 唯美龜毛、追求優雅,把可讀性與一致性當作旋律,最受不了走調的命名與排版 | | **🧰 Leo** | maintainability | 有遠見、重視長期維護成本,凡事先問「六個月後的自己還看得懂嗎?」,討厭把債留給未來 | | **🔮 Mage** | logic | 嚴謹冷靜、滴水不漏,凡事推演到最壞情況,深信「沒驗證過的假設都是 bug」 | | **🧪 Maya** | testing | 對測試覆蓋率有執念,深信「沒有測試的程式碼等於沒寫完」,溫和但堅持,最在意邊界與失敗路徑 | | **⚡ Rogue** | efficiency | 急性子、講求速度,最痛恨被浪費的 CPU 週期與記憶體,凡事先問「這能不能更快、更省」 | > 🔍 服務:opencode 模型:gemini-2.5-flash
admin reviewed 2026-06-23 09:33:43 +00:00
admin left a comment
Owner

AI Code Review 統計

類型 🔴 嚴重 🟡 警告 🔵 建議 無法標示
新問題 0 筆 0 筆 1 筆 0 筆
舊問題 0 筆 0 筆 0 筆 0 筆

🤖 AI 助理使用量

本次審查(opencode / gemini-2.5-flash,共 9 次呼叫)

提示 token 回應 token 合計
45,342 4,302 120,317

剩餘可用

剩餘可用:無法計算百分比(自架服務,無帳號額度概念)

## AI Code Review 統計 | 類型 | 🔴 嚴重 | 🟡 警告 | 🔵 建議 | ⚪ 無法標示 | | --- | --- | --- | --- | --- | | 新問題 | 0 筆 | 0 筆 | 1 筆 | 0 筆 | | 舊問題 | 0 筆 | 0 筆 | 0 筆 | 0 筆 | ## 🤖 AI 助理使用量 **本次審查**(opencode / gemini-2.5-flash,共 9 次呼叫) | 提示 token | 回應 token | 合計 | | --- | --- | --- | | 45,342 | 4,302 | 120,317 | **剩餘可用** 剩餘可用:無法計算百分比(自架服務,無帳號額度概念)
@@ -199,0 +214,4 @@
for (const remaining of [null, undefined]) {
const pct = resolveRemainingPercent({ available: false, reason: 'x' }, { hasData: true, remaining, limit: 200000, kind: 'tokens' });
assert.equal(pct.percent, null, `rate.remaining=${remaining} 應算不出百分比`);
}
Owner

嚴重等級🔵 建議
審查員:Maya
問題:測試案例 returns null percent when rate.remaining is null/undefined 僅驗證了 remaining 為 null/undefined,但未驗證當 rate.limit 為 null/undefined 時的情況。雖然這可能由 calculatePercent 內部處理,但針對 resolveRemainingPercent 這一層級的整合測試仍不完整。
建議:建議補上一個測試案例,明確測試當 rate.limit 為 null/undefined 時,resolveRemainingPercent 的行為是否符合預期。

**嚴重等級**:🔵 建議 **審查員**:Maya **問題**:測試案例 `returns null percent when rate.remaining is null/undefined` 僅驗證了 remaining 為 null/undefined,但未驗證當 rate.limit 為 null/undefined 時的情況。雖然這可能由 `calculatePercent` 內部處理,但針對 `resolveRemainingPercent` 這一層級的整合測試仍不完整。 **建議**:建議補上一個測試案例,明確測試當 `rate.limit` 為 null/undefined 時,`resolveRemainingPercent` 的行為是否符合預期。
admin added 1 commit 2026-06-23 09:33:45 +00:00
chore: update ai-review findings [ai-review-bot][success]
AI / 計算版本號 (pull_request) Successful in 2s
AI / Code Review (pull_request) Successful in 2s
78127cf51c
jiantw83 merged commit 3763908b39 into develop 2026-06-23 09:35:21 +00:00
jiantw83 deleted branch ai-review-resolve/20260623-163642 2026-06-23 09:35:21 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: old-actions/code-review#46