# T861 — sweep checkpoint resume budget > Status: `done`(2026-08-11) > Milestone: `M6` > Est. change: `~190 lines` ## Goal 完成後 Sweep 會逐筆 checkpoint,在中斷、重跑或點數耗盡時只處理未完成候選,並準確回報 partial/blocked budget。 ## Depends on - T842、T853、T860 ## Inputs - `apps/backend/internal/module/radar/domain/sweep.go` - `apps/backend/internal/module/radar/usecase/sweep_run.go` - `apps/backend/internal/module/job/**` - Spec §5.3–§5.4、驗收 #18–#20 ## Outputs ### 程式變更(預期路徑) | 路徑 | 動作 | 說明 | |------|------|------| | `apps/backend/internal/module/radar/domain/sweep.go` | edit | checkpoint、budget state、deferred count | | `apps/backend/internal/module/radar/usecase/sweep_progress.go` | add | guarded per-candidate progress | | `apps/backend/internal/module/radar/usecase/sweep_resume_test.go` | add | interruption/quota/race tests | ### 行為變更 - CreditCeiling/方案額度用完停止新 provider 呼叫,已完成保留,剩餘為 deferred。 - Redis lock value 保持 workerID;晚到 worker 不覆寫終態。 ### API / 契約(若有) - status 為 complete/partial_budget/blocked_budget/failed;不以成功空資料表示 budget stop。 ## Out of scope - 不改 usage meter cost 定義、不做 live page mapper。 ## Acceptance - [x] 第五筆中斷重跑不重扣前五筆。 - [x] 多 worker race 不突破 owner ceiling。 - [ ] 指令: ```bash cd apps/backend && go test ./internal/module/radar/... ./internal/module/job/... -run 'Sweep|Budget|Progress' -race -count=1 ``` ## Notes job status 更新必須 guarded;只由 lock owner 續期/釋放。