Priority: P3(backlog — 探索性,非本週;先讓 v1.7.0 的 Phase 1 觀測資料累積後再評估)
Problem
rate-limit-proxy.py(v1.5.0 交付)目前是 Phase 1 純觀測:透明轉發 + 擷取真實 anthropic-ratelimit-* header、token usage、請求 model 寫進 rate-state.jsonl,但不做任何主動干預。所有 guard 仍是風險降低(pacing-guard 的 deny/sleep 只看 launch 次數 heuristic、nudge 只提醒)——沒有任何機制依真實 budget 在請求送出前主動 delay / 佇列 / 擋下。
本 issue 是 #1(Phase 1,已交付 v1.5.0)明確 defer 的 Phase 2:把 proxy 從被動觀測升級成主動排程,讓「保證不撞牆」從 heuristic 逼近真正可達成。
Type
feature(大型、探索性)。很可能是 Spectra 級——新增主動排程是對外行為改變、有死鎖/公平性/正確性的長期維護意涵,diagnose 階段應據此評估 Complexity,並可能拆成多個子問題。
Expected
proxy 在轉發請求「之前」讀最近一筆同桶的 rate-state.jsonl 快照,依真實 remaining/reset 做主動排程,理想能力(diagnose 階段再定案優先序):
- Budget-aware delay:某桶 remaining 逼近 0 且 reset 還有 N 秒 → 主動延遲送出到 budget 回填,而非讓請求撞 429 再由 Claude Code retry。
- 佇列/序列化:同桶並發請求(尤其一個 Workflow 內部 fan-out 的數十個 subagent)排隊而非同時打,攤平 burst。
- Hard block(最後手段):budget 真的乾了 → 擋下並回一個明確錯誤/等待,而非讓它撞牆。
Actual(現狀 — Phase 1 邊界)
Impact / 待 diagnose 釐清的關鍵風險
- 死鎖:proxy 若在請求路徑上同步等待 budget 回填,可能卡住整個 Claude Code 主迴圈(proxy 是所有 API 流量的必經點)。需要 timeout / 逃生閥設計。
- 不公平排程:多個並發 session 共用同一 account bucket(使用者本機常 3-4 並發),proxy 如何在它們之間公平分配 budget?先到先服務 vs. 加權?
- 正確性 vs. fail-open:Phase 1 的鐵律是 fail-open(proxy 掛掉不影響轉發)。Phase 2 主動 delay/block 與 fail-open 天生張力——排程邏輯出錯不能把使用者鎖死。預設應可一鍵退回純觀測(如 env flag
RATE_LIMIT_PROXY_SCHEDULE=0)。
- 前提驗證(gating precondition):Phase 1 defer Phase 2 的理由是「先靠 Phase 1 資料驗證『真實 header 可見度』本身有沒有用」。diagnose 第一步應先看 v1.7.0 累積的
rate-state.jsonl——真實 header 是否夠即時/準確到足以支撐主動排程決策;若 header 落後現實太多,Phase 2 的前提就不成立。
- 範疇:只涵蓋「經過 proxy 的流量」——claude.ai 網頁版等其他管道仍在視野外,Phase 2 一樣不保證帳號級絕對不撞牆(誠實邊界不變)。
References
Current Status
Phase: needs-fix(v1 hold 條件經 31 天 live 證據證偽;disposition 待定)
Last updated: 2026-08-17 by idd-comment → idd-update
Key Decisions
- 2026-08-17:v1 rejected-aware hold 已證偽。31 天 / 410,716 筆 record,
sched_held_ms > 0 為 0 筆;同期 1,194 筆 rejected 快照(68 個窗)全部落在 90s cap 之外(reset − now 最小值 3.9 min)。非樣本不足,是結構上不可達。
- 2026-08-17:根因為「兩個時鐘」——
rl_unified_reset 是 5h/7d 配額窗邊界、不是 retry-after;rejected 窗靠 utilization 衰退解除,不靠 reset 到達。窗長的原始經驗判斷(1–10 min)是對的,錯的是 hold 綁的欄位。
- 2026-08-17:
retry-after 從未被 proxy 擷取,且尚未證實 Anthropic 429 會回傳它 —— 不得當成已知替代方案。
- 2026-07-16:live gating 啟用(daemon 帶
RATE_LIMIT_PROXY_SCHEDULE=1 + settings.json env 持久化)。
- 2026-07-12:re-diagnosis —— 舊 blocker 全解除、gating precondition PASS 帶範疇轉折(帳號級訊號非桶級);Complexity=Spectra。spectra change
rejected-aware-admission-hold 已 apply 並歸檔。
Scope Changes
- v1 的「有界 hold」機制不再是可行的交付路徑;
resolve_sched_hold_cap() 的 240s 設計上限與實測 reset − now 分佈(p5 = 42.8 min)差距數量級,調參無法補救。
Blocking
Commits
Problem
rate-limit-proxy.py(v1.5.0 交付)目前是 Phase 1 純觀測:透明轉發 + 擷取真實anthropic-ratelimit-*header、token usage、請求 model 寫進rate-state.jsonl,但不做任何主動干預。所有 guard 仍是風險降低(pacing-guard 的 deny/sleep 只看 launch 次數 heuristic、nudge 只提醒)——沒有任何機制依真實 budget 在請求送出前主動 delay / 佇列 / 擋下。本 issue 是 #1(Phase 1,已交付 v1.5.0)明確 defer 的 Phase 2:把 proxy 從被動觀測升級成主動排程,讓「保證不撞牆」從 heuristic 逼近真正可達成。
Type
feature(大型、探索性)。很可能是 Spectra 級——新增主動排程是對外行為改變、有死鎖/公平性/正確性的長期維護意涵,diagnose 階段應據此評估 Complexity,並可能拆成多個子問題。
Expected
proxy 在轉發請求「之前」讀最近一筆同桶的
rate-state.jsonl快照,依真實 remaining/reset 做主動排程,理想能力(diagnose 階段再定案優先序):Actual(現狀 — Phase 1 邊界)
rate-state.jsonl資料寫了但只被 pacing-guard 的 heat-nudge 讀來「提醒」,沒有任何主動排程消費它。rate-state.jsonl帶model、rate_state_heat()依家族桶(model_bucket())過濾(rate-limit-proxy 的 rate-state.jsonl 也缺 model 欄位(sister concern from #2) #4 per-model 分桶用 exact model-id 相等,非 rate-limit bucket 相等(同族變體互不計入) #6)——Phase 2 排程可直接複用這套分桶,per-bucket 各自排程。Impact / 待 diagnose 釐清的關鍵風險
RATE_LIMIT_PROXY_SCHEDULE=0)。rate-state.jsonl——真實 header 是否夠即時/準確到足以支撐主動排程決策;若 header 落後現實太多,Phase 2 的前提就不成立。References
model_bucket()、rate-limit-proxy 的 rate-state.jsonl 也缺 model 欄位(sister concern from #2) #4 rate-state 帶 model(已交付 v1.7.0)plugins/claude-hot-limit/CLAUDE.md→「Proxy 誠實邊界(Phase 1)」段落「明確排除 Phase 2 主動排程」Current Status
Phase: needs-fix(v1 hold 條件經 31 天 live 證據證偽;disposition 待定)
Last updated: 2026-08-17 by idd-comment → idd-update
Key Decisions
sched_held_ms > 0為 0 筆;同期 1,194 筆 rejected 快照(68 個窗)全部落在 90s cap 之外(reset − now最小值 3.9 min)。非樣本不足,是結構上不可達。rl_unified_reset是 5h/7d 配額窗邊界、不是 retry-after;rejected 窗靠 utilization 衰退解除,不靠 reset 到達。窗長的原始經驗判斷(1–10 min)是對的,錯的是 hold 綁的欄位。retry-after從未被 proxy 擷取,且尚未證實 Anthropic 429 會回傳它 —— 不得當成已知替代方案。RATE_LIMIT_PROXY_SCHEDULE=1+ settings.json env 持久化)。rejected-aware-admission-hold已 apply 並歸檔。Scope Changes
resolve_sched_hold_cap()的 240s 設計上限與實測reset − now分佈(p5 = 42.8 min)差距數量級,調參無法補救。Blocking
retry-after擷取的前置調查 (2) 保留 gate 但更換觸發訊號 (3) 移除 v1 hold、把 rate-limit-proxy Phase 2:依真實 budget 主動排程(delay / 佇列 / block) #7 收斂到已交付的觀測面。無外部依賴。Commits
5a5b437docs: archive spectra change rejected-aware-admission-hold + spec sync2b2df37docs: daily changelog append rate-limit-proxy Phase 2:依真實 budget 主動排程(delay / 佇列 / block) #7 Phase 2 v146e7e46feat: rejected-aware admission hold — Phase 2 v1 opt-in scheduling