diff --git a/src/usage-primer.test.ts b/src/usage-primer.test.ts index 7ccb686..18e649b 100644 --- a/src/usage-primer.test.ts +++ b/src/usage-primer.test.ts @@ -54,7 +54,7 @@ vi.mock('./codex-warmup.js', () => ({ })); describe('usage-primer', () => { - it('refreshes Codex usage before primer selection and allows 1% fresh usage', async () => { + it('refreshes Codex usage before primer selection and fires regardless of usage level', async () => { callOrder.length = 0; refreshAllCodexAccountUsage.mockClear(); refreshActiveCodexUsage.mockClear(); @@ -68,7 +68,7 @@ describe('usage-primer', () => { expect.objectContaining({ enabled: true, minIntervalMs: 18_000_000, - maxUsagePct: 1, + maxUsagePct: 100, maxD7UsagePct: 100, }), { ignoreZeroUsageWindow: true }, diff --git a/src/usage-primer.ts b/src/usage-primer.ts index 97e7a0c..fad904a 100644 --- a/src/usage-primer.ts +++ b/src/usage-primer.ts @@ -26,10 +26,13 @@ const PRIMER_HOURS_KST = [8, 13, 18, 23]; const KST_OFFSET_MS = 9 * 60 * 60 * 1000; const CLAUDE_PRIMER_TIMEOUT_MS = 60_000; const CODEX_PRIMER_MIN_INTERVAL_MS = 5 * 60 * 60 * 1000; -// Codex's rate-limit read can report a freshly reset, otherwise idle account -// as 1%. Treat that as still eligible so the real primer call can anchor the -// 5h inference window at the fixed slot. -const CODEX_PRIMER_MAX_USAGE_PCT = 1; +// Fire the Codex primer unconditionally at every slot, mirroring the Claude +// primer (which always fires unless the account is rate-limited). The 5h usage +// level no longer gates the call (maxUsagePct=100), so a slot is never skipped +// just because Codex happens to be partway through its window. The d7 gate +// stays at 100 so we still skip an account whose weekly quota is exhausted, +// which is the Codex analogue of Claude's rate-limit skip. +const CODEX_PRIMER_MAX_USAGE_PCT = 100; const CODEX_PRIMER_MAX_D7_USAGE_PCT = 100; function resolveClaudeBinary(): string {