程式碼審查報告 — stats-snapshot per-agent write + additive merge

Agent: reviewer (reviewer)
Confidence: 71%
Cost: $0.7301
Duration: 2m 51s
Task ID: f4b3824b-088c-48f2-a14b-3cd498bb41e0


All checks pass. Let me write the review report.

程式碼審查報告 — stats-snapshot per-agent write + additive merge

概述

Programmer 修復了 stats-snapshot.ts 的 race condition(並行 agent 重置 costResetDate 導致資料遺失),將架構從「一次性批次寫入」改為「per-agent 增量合併」模式,並同步更新了所有測試。改動邏輯清晰、測試完整,品質通過。

分析詳情

1. 核心架構變更(stats-snapshot.ts)— 正確

問題:舊版 snapshotDailyStats()access() 做 idempotent 檢查,且一次批量寫入所有 agent。但在並行執行場景下,先完成的 agent 會重置 costResetDate,導致後續批次查詢時看不到這些 agent。

解法:新增 addAgentToSnapshot() 函式,每次記錄單一 agent 的資料(read-modify-write),在 recordAgentRun() 中 cost reset 前逐一呼叫。snapshotDailyStats() 退化為 fallback,處理尚未在新日執行的殘留 agent。

評估

  • Read-modify-write 模式在低併發場景(agent 啟動通常有秒級間隔)足夠安全
  • writer.writeNow() 保持 atomic write 慣例
  • systemTotals 每次從 snapshot.agents 重算,避免增量計算的漂移問題 — 良好設計

2. agent-config.ts 變更 — 正確

  • 新增 avgDurationMs / totalDurationMs 欄位至 schema 和 interface(:69-70, :188-192)
  • recordAgentRun() 新增 durationMs 參數(:302),更新 duration tracking(:341-345)
  • 呼叫從 snapshotDailyStats(cfg.costResetDate) 改為 addAgentToSnapshot(cfg.costResetDate, cfg.name, {...})(:311-323)
  • 錯誤處理加入 warn log 而非靜默 catch — 改善可觀測性

3. worker-scheduler.ts 變更 — 正確

  • 單行改動:傳遞 result.value.durationrecordAgentRun()(:1057)
  • 最小侵入性修改

4. 測試變更 — 正確且完整

修復的 3 個測試

  • Test 1:toHaveBeenCalledOnce()toHaveBeenCalledTimes(2),因為 per-agent 模式下 2 個 agent = 2 次 writeNow 呼叫。檢查最後一次呼叫的 merged data — 正確。
  • Test 2(zero agent):不再檢查 mock.calls[0],改為 not.toHaveBeenCalled() — 因為 inactive agent 直接 return。
  • Test 3(idempotent → additive):完全改寫為測試合併行為。pre-populate fileContents 模擬既存 snapshot,驗證新 agent 正確 merge 進去。

新增的 4 個 addAgentToSnapshot() 測試

  • create from scratch — 驗證檔案不存在時的行為
  • merge into existing — 驗證 read-modify-write
  • skip inactive — 驗證 0 runs + 0 cost 的 guard
  • overwrite same agent — 驗證重複 snapshot 同一 agent 時覆蓋(而非堆疊)

Mock 策略mockWriteNow 改為寫回 fileContents,讓 sequential addAgentToSnapshot 呼叫能讀到前一次的寫入結果。這是正確的做法,確保 mock 反映真實 I/O 的 read-after-write 語意。

5. 潛在風險點(非阻擋性)

  • Read-modify-write 無鎖:若兩個 agent 真正同時觸發 addAgentToSnapshot(毫秒級併發),理論上存在 lost update 風險。但在實際場景中,agent task 完成時間有足夠間隔,且 writeNow 本身是 atomic,此風險極低。屬「建議未來注意」而非「必須修」。

測試結果

  • 編譯檢查:✅ tsc --noEmit 通過
  • 測試套件:✅ 1235 passed / 0 failed(共 97 test files)
  • 回歸測試:✅ 無新 regression

風險評估

  • 🟢 低風險:所有改動語意正確,測試覆蓋充分
  • 🟡 建議注意:read-modify-write 無鎖,但實際並發風險極低

結論

審查通過。改動修復了一個真實的 race condition,架構從批次改為增量,並同步新增 duration tracking。測試全面且正確反映新行為。

—HANDOFF—
TO: secretary
INTENT: handoff
ARTIFACT_TYPE: review
SUMMARY: fix: sync stats-snapshot tests with per-agent write + additive merge behavior — 修復 3 個失敗測試、新增 4 個 addAgentToSnapshot 單元測試、全部 1235 tests 通過