From ea9debffe9fa646d88970333e141737125bd2b2c Mon Sep 17 00:00:00 2001 From: bitkyc08-arch Date: Tue, 25 Aug 2026 12:48:27 +0900 Subject: [PATCH] fix(catalog): do not carry a retained compact limit onto a corrected window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #1905 taught catalog sync never to raise a compaction threshold retained from Codex. The rule is right, but the retained number was trusted even when sync corrected the row's context window in the same pass. An upstream entry arriving as 128k/115_200 whose window is then widened to 272k kept the stale 115_200 — 42% of the real window — so every long turn compacted early. CI caught it on macos and test 1/4 at 121c1fbe2. A retained threshold only describes the window it arrived with. Capture the incoming window before any override or cap rewrites the row, and trust the retained value only when the window is unchanged; lower-is-policy still holds there, which is what #1905 was protecting. --- src/codex/catalog/parsing.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/codex/catalog/parsing.ts b/src/codex/catalog/parsing.ts index 7fe07aca7f..7d150567d9 100644 --- a/src/codex/catalog/parsing.ts +++ b/src/codex/catalog/parsing.ts @@ -320,6 +320,9 @@ export function applyNativeOpenAiContextOverride(entry: RawEntry, limits?: Nativ ?? (isNativeOpenAiEntry(entry) ? entry.slug as string : undefined); if (!nativeSlug) return; const override = NATIVE_OPENAI_CONTEXT_OVERRIDES[nativeSlug]; + // Captured before any override/cap rewrites the row: a retained compaction threshold only + // describes the window it arrived with. + const incomingContextWindow = typeof entry.context_window === "number" ? entry.context_window : undefined; if (override) { // Read the effective values through the accessors rather than re-deriving them from the // static table: this function used to apply only the provider cap, so a per-model window @@ -352,7 +355,14 @@ export function applyNativeOpenAiContextOverride(entry: RawEntry, limits?: Nativ : undefined; if (effectiveContext !== undefined) { const derivedAutoCompactTokenLimit = nativeOpenAiAutoCompactTokenLimit(nativeSlug, limits); - const retainedAutoCompactTokenLimit = isNativeOpenAiEntry(entry) + // Only trust a retained threshold that still describes THIS window. When sync corrects the + // window, the old number is an artifact of the old one: a 115_200 limit retained from a + // 128k row would pin a corrected 272k model to 42% of its real window and compact every + // long turn early. Lower-is-policy still holds whenever the window is unchanged. + const retainedDescribesCurrentContext = incomingContextWindow === undefined + || incomingContextWindow === effectiveContext; + const retainedAutoCompactTokenLimit = retainedDescribesCurrentContext + && isNativeOpenAiEntry(entry) && typeof entry.auto_compact_token_limit === "number" && Number.isSafeInteger(entry.auto_compact_token_limit) && entry.auto_compact_token_limit > 0