feat(primer): narrow pre-08:00 Codex hold to anchor 5h reset at 13:00 KST

The Codex 5h usage limit is a FIXED window (verified live: usedPercent climbs
while resetsAt stays put), so it can be anchored — but only if the 08:00 KST
primer is the first Codex request of a fresh window. Codex is otherwise used
near-continuously (reviewers/arbiters every paired room, codex-owner rooms,
warm-up), so 08:00 lands mid-window and the reset drifts (observed 15:47).

Restore the alignment hold from backup/primer-hold-work, but narrowed to a
single dawn window (03:00-08:00 KST) per user direction — the broad all-slots
version was previously reverted. One Codex window is at most 5h, so anything
opened before 03:00 has expired by 08:00, leaving the primer to anchor cleanly
=> 13:00 reset. Other slots (13/18/23) and all daytime hours are untouched.

- codex-primer-alignment.ts: narrow shouldHoldCodexForPrimerAlignment (03-08 KST)
- codex-warmup.ts: skip non-primer (non-forceAttempt) warm-ups during the hold
- message-runtime-queue.ts: defer Codex reviewer/arbiter turns during the hold
- message-runtime-gating.ts: defer fresh Codex-owner room turns during the hold

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-06-10 11:40:17 +09:00
parent 728a8c2ec9
commit 1a85ebf7eb
5 changed files with 153 additions and 1 deletions

View File

@@ -7,6 +7,7 @@ import { fileURLToPath } from 'url';
import { DATA_DIR } from './config.js';
import type { AppConfig } from './config/schema.js';
import { shouldHoldCodexForPrimerAlignment } from './codex-primer-alignment.js';
import {
getAllCodexAccounts,
getCodexAuthPath,
@@ -341,6 +342,13 @@ export async function runCodexWarmupCycle(
return { status: 'skipped', reason: 'runtime_busy' };
const nowMs = runtime.nowMs ?? Date.now();
// Hold every non-primer warm-up during the pre-08:00 dawn window so it can't
// anchor the shared Codex 5h window ahead of the scheduled primer (which
// passes forceAttempt). Skipping is safe — an opportunistic warm-up is
// best-effort. The fixed-slot primer itself (forceAttempt) is never held.
if (!runtime.forceAttempt && shouldHoldCodexForPrimerAlignment(nowMs)) {
return { status: 'skipped', reason: 'primer_alignment_hold' };
}
const nowIso = new Date(nowMs).toISOString();
const statePath = runtime.statePath ?? DEFAULT_STATE_FILE;
const state = readWarmupState(statePath);