feat(primer): hold off-slot Codex turns so the fixed-slot primer anchors the reset

The usage primer fires at 08/13/18/23 KST but could not pin the Codex 5h
reset because reviewer/arbiter turns on the same shared account ran off-slot
and anchored the window first. Add a time-based hold
(shouldHoldCodexForPrimerAlignment) that keeps non-primer Codex turns quiet
during the 04-08 KST dawn gap and for a few minutes after each slot, so the
scheduled primer wins the first-request race. Applied at the reviewer/arbiter
dispatch site (the actual off-slot consumer here) and for codex-owner rooms;
urgent @-mention turns bypass it. Time-based by design — the usage/reset
figures are exactly the unreliable data, so a blunt clock rule is predictable
and testable.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-06-09 14:31:01 +09:00
parent efc8c00380
commit e324a1baa1
5 changed files with 175 additions and 11 deletions

View File

@@ -18,17 +18,19 @@ import { getAllTokens } from './token-rotation.js';
* provider account is kept warm and any usage-window issues surface in the
* logs at predictable times.
*
* IMPORTANT — what this does NOT do: it does not pin the reset to a fixed
* clock time. Empirically the Codex 5h limit is a *trailing rolling* window:
* the reported reset slides forward with continued usage (observed reset
* moving 18:00 → 18:33 over ~33 min of activity). A single timed message can
* therefore not anchor the reset to a fixed time while Codex keeps being used
* (e.g. by a paired-room reviewer on the same account). The slots are a
* best-effort warm-up + a success/failure record, not a reset-alignment lever.
* Reset alignment: the primer alone cannot pin the reset — empirically the
* Codex 5h limit slides forward with continued usage (observed reset moving
* 18:00 → 18:33 over ~33 min of activity), so any off-slot Codex call by a
* paired-room reviewer/arbiter on the same account would anchor the window
* early. To make the slot the *anchor*, the primer is paired with a hold gate
* (`shouldHoldCodexForPrimerAlignment` in message-runtime-gating.ts) that
* keeps non-primer Codex turns quiet during the dawn gap (0408 KST) and for a
* few minutes after each slot, so the primer wins the first-request race. The
* primer is also a best-effort warm-up + success/failure record.
*/
const PRIMER_HOURS_KST = [8, 13, 18, 23];
const KST_OFFSET_MS = 9 * 60 * 60 * 1000;
export const PRIMER_HOURS_KST = [8, 13, 18, 23];
export 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;
// Fire the Codex primer unconditionally at every slot, mirroring the Claude