Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
45a99a3
fix(codex): default native GPT-5.6 to Codex 272k until 1M is opted in
lidge-jun Aug 17, 2026
8b67220
fix(codex): thread native 5.6 overlays through remaining Codex and De…
lidge-jun Aug 17, 2026
627eecf
fix(windows): resolve icacls from trusted System32 path
lidge-jun Aug 17, 2026
1828cb1
fix(windows): keep icacls spawn stdio types inferred
lidge-jun Aug 17, 2026
9122d5e
fix(windows): resolve LocalAppData independently of USERPROFILE
lidge-jun Aug 17, 2026
5a4d968
fix(windows): keep git, platform and path assumptions honest under te…
lidge-jun Aug 17, 2026
dad5348
fix(windows): stop three v2-gate cases reporting the machine instead …
lidge-jun Aug 17, 2026
1b8c399
fix(codex): decode TOML string escapes when reading injected routing …
lidge-jun Aug 17, 2026
960c7a9
perf(windows): memoize the per-process identity lookups
lidge-jun Aug 17, 2026
c388221
fix(windows): restore the core/Lab boundary guard and two platform-bo…
lidge-jun Aug 17, 2026
5c6be04
fix(lab): finalize projection statements so a rebuild can replace its…
lidge-jun Aug 17, 2026
7563d35
fix(tests): await the lock holder before removing its temp root
lidge-jun Aug 17, 2026
079f417
test(windows): budget the thread-affinity LRU cases
lidge-jun Aug 17, 2026
e2f9670
fix(tests): never fail a finished test on a Windows teardown race
lidge-jun Aug 17, 2026
54c5a8f
fix(tests): let the OAuth poller yield to real work, not just microtasks
lidge-jun Aug 17, 2026
71f69ed
test(windows): budget the non-loopback refusal case
lidge-jun Aug 17, 2026
51857c9
fix(windows): three more cases that described the machine, not the code
lidge-jun Aug 17, 2026
a6de95a
fix(windows): skip the file-symlink cases and survive one more teardo…
lidge-jun Aug 17, 2026
0f4b95b
test(windows): budget the two-server lifecycle case
lidge-jun Aug 17, 2026
f3a6120
fix(windows): mark the Unix-only and symlink-only preflight cases
lidge-jun Aug 17, 2026
e7a71c1
fix(tests): update two source-shape checks the dev tip left behind
lidge-jun Aug 17, 2026
bb984ad
Merge pull request #1881 from lidge-jun/fix/windows-icacls-trusted-path
lidge-jun Aug 17, 2026
d8bf2bc
Merge dev into main: Windows suite green
lidge-jun Aug 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# 070 — Native GPT-5.6 default follows Codex 272k

## Change

- `NATIVE_GPT56_CONTEXT_WINDOW` is 272,000 (Codex live advertised default).
- Measured ceiling / 1M opt-in stays `NATIVE_GPT56_MAX_INPUT_TOKENS` = 922,000.
- For the GPT-5.6 family only, `providerContextCaps.openai` and per-model overlays may RAISE the default up to 922k. Values above 922k clamp. Other native slugs still only lower.
- Native group switch ON without a value sends 922,000. Switch OFF displays 272k.
- API-key 1,050,000 / 922,000 path is unchanged. gpt-5.4 stays 1M. gpt-5.5 stays 272k.

## Files

- `src/codex/catalog/metadata.ts`
- `gui/src/pages/Models.tsx`
- `gui/src/pages/models-shared.ts`
- `structure/08_openai-provider-tiers.md`
- focused tests listed in the same commit

## Accept

- `nativeOpenAiContextWindow("gpt-5.6-sol") === 272000`
- `nativeOpenAiContextWindow("gpt-5.6-sol", 922000) === 922000`
- `nativeOpenAiContextWindow("gpt-5.6-sol", 2000000) === 922000`
- `nativeOpenAiContextWindow("gpt-5.5", 922000) === 272000`
- Claude default sol is unmarked; opted-in 922k marks `[1m]`
14 changes: 10 additions & 4 deletions gui/src/pages/Models.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ import {
fmtK,
NATIVE_CAP_OPTIONS,
NATIVE_CAP_OPTION_SET,
NATIVE_GPT56_DEFAULT_WINDOW,
NATIVE_GPT56_OPT_IN_WINDOW,
PAGE,
readCollapsedProviders,
THREAD_OPTION_SET,
Expand Down Expand Up @@ -629,7 +631,7 @@ export default function Models({ apiBase, restartEpoch = 0 }: { apiBase: string;
}
};

const toggleProviderCap = async (provider: string) => {
const toggleProviderCap = async (provider: string, nativeGroup = false) => {
setBusy(true);
busyRef.current = true;
setStatus("");
Expand All @@ -640,7 +642,9 @@ export default function Models({ apiBase, restartEpoch = 0 }: { apiBase: string;
const r = await fetch(`${apiBase}/api/provider-context-caps`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ provider, enabled }),
body: JSON.stringify(enabled && nativeGroup
? { provider, enabled, value: NATIVE_GPT56_OPT_IN_WINDOW }
: { provider, enabled }),
});
try {
const data = await readJsonOrThrow<ProviderContextCapsResponse>(r, t("models.capSaveFailed"));
Expand Down Expand Up @@ -1025,7 +1029,9 @@ export default function Models({ apiBase, restartEpoch = 0 }: { apiBase: string;
if (window === undefined) return widest;
return widest === undefined || window > widest ? window : widest;
}, undefined);
const capDisplayValue = capOn ? providerCap : (widestRowWindow ?? providerCap);
const capDisplayValue = capOn
? providerCap
: (nativeProviderGroup ? NATIVE_GPT56_DEFAULT_WINDOW : (widestRowWindow ?? providerCap));
// The native group offers only the three windows GPT-5.6 actually has contracts for
// (272k live, 372k legacy, 1.05M measured); routed providers keep the generic ladder.
// The set has to follow the list, or a saved value outside it loses its option.
Expand Down Expand Up @@ -1118,7 +1124,7 @@ export default function Models({ apiBase, restartEpoch = 0 }: { apiBase: string;
<button type="button" className="btn btn-ghost btn-sm text-caption" disabled={busy || allOn} onClick={() => bulkToggle(true)}>{t("models.allOn")}</button>
<button type="button" className="btn btn-ghost btn-sm text-caption" disabled={busy || allOff} onClick={() => bulkToggle(false)}>{t("models.allOff")}</button>
<>
<Switch on={capOn} onClick={() => toggleProviderCap(provider)} disabled={busy} label={t("models.capValue", { value: fmtK(capDisplayValue) })} />
<Switch on={capOn} onClick={() => toggleProviderCap(provider, nativeProviderGroup)} disabled={busy} label={t("models.capValue", { value: fmtK(capDisplayValue) })} />
{/* The native group keeps the value visible with the cap off: its rows always
advertise SOME window, so hiding the number leaves the card saying nothing
about the context Codex will actually see. Routed providers keep the old
Expand Down
4 changes: 3 additions & 1 deletion gui/src/pages/models-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ export const CAP_OPTION_SET = new Set(CAP_OPTIONS);
* window, so listing a value above the advertised one would be an inert choice.
* Anything else goes through "Custom".
*/
export const NATIVE_CAP_OPTIONS = [272_000, 372_000, 922_000];
export const NATIVE_GPT56_DEFAULT_WINDOW = 272_000;
export const NATIVE_GPT56_OPT_IN_WINDOW = 922_000;
export const NATIVE_CAP_OPTIONS = [NATIVE_GPT56_DEFAULT_WINDOW, 372_000, NATIVE_GPT56_OPT_IN_WINDOW];
export const NATIVE_CAP_OPTION_SET = new Set(NATIVE_CAP_OPTIONS);
export const CUSTOM_OPTION = "custom";
export const THREAD_OPTIONS = [4, 8, 16, 32, 64, 128, 256, 500, 1000];
Expand Down
7 changes: 6 additions & 1 deletion gui/tests/models-native-group-controls.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,12 @@ test("the native group keeps its window readable with the cap switched off", asy
expect(src).toContain("{(capOn || nativeProviderGroup) && (");
// With the cap off the stored value is only what a future toggle would apply — the 350k
// default — so the display falls back to the widest window the rows actually advertise.
expect(src).toContain("const capDisplayValue = capOn ? providerCap : (widestRowWindow ?? providerCap);");
// Matched as separate fragments because the expression is wrapped across lines now, and
// it grew a native branch: with the cap off the native group shows its default window
// rather than the widest advertised row. A single-line literal pinned the formatting
// instead of the behaviour and broke on the reflow that introduced that branch.
expect(src).toContain("const capDisplayValue = capOn");
expect(src).toContain("nativeProviderGroup ? NATIVE_GPT56_DEFAULT_WINDOW : (widestRowWindow ?? providerCap)");
// The select is inert until the cap is actually on: showing a number is not the same as
// offering to change one.
expect(src).toContain("disabled={busy || !capOn}");
Expand Down
11 changes: 11 additions & 0 deletions scripts/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ export function createIsolatedTestEnvironment(
// real-home write guard can still know which path to protect.
// (devlog 260730_codex_rs_upstream_v2_live_handoff/070.)
OCX_REAL_HOME: baseEnv.OCX_REAL_HOME ?? homedir(),
// Pin git's global config to the developer's real one before HOME moves.
//
// git resolves ~/.gitconfig from HOME, so a sandboxed HOME makes it invisible.
// That silently drops `safe.directory`, and on a checkout whose directory owner
// differs from the running account -- ordinary on Windows when a tool or
// installer created the tree -- every `git` call a test makes then fails with
// "detected dubious ownership". The test reads that as "this is not a git
// repository" and asserts against a fallback, which looks like a product bug in
// whichever adapter collected the metadata. Naming the file keeps the sandbox
// (git still writes nothing here) while leaving git's own trust decisions intact.
GIT_CONFIG_GLOBAL: baseEnv.GIT_CONFIG_GLOBAL ?? join(homedir(), ".gitconfig"),
HOME: root,
USERPROFILE: root,
OPENCODEX_HOME: opencodexHome,
Expand Down
4 changes: 2 additions & 2 deletions src/claude/context-windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/
import { aliasForNative, aliasForRoute } from "./alias";
import { desktop3pAlias } from "./desktop-3p";
import { nativeOpenAiContextWindow, type CatalogModel } from "../codex/catalog";
import { nativeOpenAiContextWindow, type CatalogModel, type NativeContextLimitsInput } from "../codex/catalog";

const ONE_MILLION = 1_000_000;

Expand Down Expand Up @@ -104,7 +104,7 @@ export function buildClaudeContextWindows(
// A configured providerContextCaps.openai has to reach the native rows here too. Without
// it the Claude surface keeps advertising the uncapped authoritative window while the
// Codex catalog advertises the capped one, and the two disagree about the same model.
nativeContextCap?: number,
nativeContextCap?: NativeContextLimitsInput,
): Record<string, number> {
const out: Record<string, number> = {};
const put = (key: string | null, value: number) => {
Expand Down
12 changes: 6 additions & 6 deletions src/claude/desktop-3p.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
renderDesktopProfile,
type DesktopProfileModel,
} from "./desktop-profile";
import { nativeOpenAiContextWindow } from "../codex/catalog";
import { nativeOpenAiContextWindow, type NativeContextLimitsInput } from "../codex/catalog";
import { assertDesktop3pModelsValid } from "./desktop-3p-guard";

export interface Desktop3pModelEntry {
Expand Down Expand Up @@ -191,7 +191,7 @@ function collectDesktop3pModels(
nativeSlugs: string[],
routedModels: Array<Desktop3pRoutedModel>,
profile?: OcxClaudeDesktopProfile,
nativeContextCap?: number,
nativeContextCap?: NativeContextLimitsInput,
): { models: Desktop3pModelEntry[]; registry: Map<string, string> } {
const registry = new Map<string, string>();
const models: Desktop3pModelEntry[] = [];
Expand Down Expand Up @@ -293,7 +293,7 @@ export function buildDesktop3pRegistry(
nativeSlugs: string[],
routedModels: Array<Desktop3pRoutedModel>,
profile?: OcxClaudeDesktopProfile,
nativeContextCap?: number,
nativeContextCap?: NativeContextLimitsInput,
): Map<string, string> {
const { registry } = collectDesktop3pModels(nativeSlugs, routedModels, profile, nativeContextCap);
desktop3pRegistry = registry;
Expand All @@ -305,7 +305,7 @@ export function generateDesktop3pModels(
nativeSlugs: string[],
routedModels: Array<Desktop3pRoutedModel>,
profile?: OcxClaudeDesktopProfile,
nativeContextCap?: number,
nativeContextCap?: NativeContextLimitsInput,
): Desktop3pModelEntry[] {
const { models, registry } = collectDesktop3pModels(nativeSlugs, routedModels, profile, nativeContextCap);
desktop3pRegistry = registry;
Expand Down Expand Up @@ -337,7 +337,7 @@ export function generateDesktop3pConfig(
apiKey = "ocx",
mode: Desktop3pConfigMode = "static",
profile?: OcxClaudeDesktopProfile,
nativeContextCap?: number,
nativeContextCap?: NativeContextLimitsInput,
): object {
const base = {
inferenceProvider: "gateway",
Expand Down Expand Up @@ -558,7 +558,7 @@ export function writeDesktop3pConfig(
apiKey?: string,
mode: Desktop3pConfigMode = "static",
profile?: OcxClaudeDesktopProfile,
nativeContextCap?: number,
nativeContextCap?: NativeContextLimitsInput,
): { written: boolean; path: string; reason?: string; fingerprint?: string } {
const libraryPath = resolveDesktop3pConfigLibraryPath();
const metadataPath = join(libraryPath, "_meta.json");
Expand Down
4 changes: 2 additions & 2 deletions src/claude/model-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* - created_at is a fixed constant; max_input_tokens is authoritative-or-null;
* max_tokens is always null (no authoritative output limit exists proxy-side).
*/
import { catalogModelEfforts, nativeEffortClamp, nativeOpenAiContextWindow, nativeOpenAiMaxInputTokens, type CatalogModel } from "../codex/catalog";
import { catalogModelEfforts, nativeEffortClamp, nativeOpenAiContextWindow, nativeOpenAiMaxInputTokens, type CatalogModel, type NativeContextLimitsInput } from "../codex/catalog";
import { claudeCodeAlias, claudeCodeNativeAlias } from "./alias";
import { desktop3pAlias } from "./desktop-3p";
import { AUTO_CONTEXT_OFF, type AutoContextMode } from "./context-windows";
Expand Down Expand Up @@ -108,7 +108,7 @@ export function buildAnthropicModelInfos(
auto: AutoContextMode = AUTO_CONTEXT_OFF,
idStyle: AnthropicIdStyle = "desktop3p",
aliasForRoute: (provider: string, modelId: string) => string = desktop3pAlias,
nativeContextCap?: number,
nativeContextCap?: NativeContextLimitsInput,
): AnthropicModelInfo[] {
const out: AnthropicModelInfo[] = [];
const seen = new Set<string>();
Expand Down
5 changes: 2 additions & 3 deletions src/cli/claude-desktop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ import {
type DesktopProfile,
} from "../claude/desktop-profile";
import { writeDesktop3pConfig, type Desktop3pConfigMode, parseDesktop3pModeArgs } from "../claude/desktop-3p";
import { filterCatalogVisibleModels, desktopVisibleNativeSlugs } from "../codex/catalog";
import { filterCatalogVisibleModels, desktopVisibleNativeSlugs, nativeContextLimits } from "../codex/catalog";
import { buildClaudeDesktopState, fetchAllModels } from "../server/management-api";
import { findLiveProxy } from "../server/proxy-liveness";
import { runtimeRequest } from "./runtime-api";
import { providerContextCap } from "../providers/context-cap";
import { OPENAI_CODEX_PROVIDER_ID } from "../providers/openai-tiers";

function isFamily(value: string | undefined): value is DesktopFamily {
Expand Down Expand Up @@ -100,7 +99,7 @@ export async function applyProfile(
config.apiKeys?.[0]?.key,
mode,
state.profile,
providerContextCap(config, OPENAI_CODEX_PROVIDER_ID),
nativeContextLimits(config),
);
return { ok: result.written, path: result.path, reason: result.reason };
}
Expand Down
2 changes: 1 addition & 1 deletion src/codex/catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Public surface preserved exactly; importers keep using "src/codex/catalog".
export { isMediaGenerationModelId, shouldExposeRoutedModel, readCodexCatalogPath, readCatalog, normalizeRoutedCatalogEntry, catalogModelSlug, filterSupportedNativeSlugs, catalogModelSupportsReasoningSummaries } from "./catalog/parsing";
export type { CatalogModel, MultiAgentMode } from "./catalog/parsing";
export { accountBoundNativeOpenAiSlugs, accountBoundNativeOpenAiSlugsBySelector, CODEX_NATIVE_ALIAS_CATALOG_KIND, NATIVE_DAYBREAK_BLUE_MODEL, NATIVE_GPT56_MAX_INPUT_TOKENS, NATIVE_OPENAI_CAPABILITY_ALIAS_MODELS, NATIVE_OPENAI_MODELS, configuredNativeAliasSlugs, desktopAllowlistSuppressedNativeSlugs, isNativeAliasCatalogEntry, isNativeOpenAiCapabilityAliasModel, nativeContextLimits, nativeOpenAiCapabilitySourceSlug, nativeOpenAiContextWindow, nativeOpenAiMaxInputTokens, disabledNativeSlugs, visibleNativeSlugs, desktopVisibleNativeSlugs, nativeModelRows, applyNativeVisibility, observedAccountBoundNativeEntries, observedAccountBoundNativeOpenAiSlugs, upstreamNativeEntry, nativeOpenAiSlugs, listCatalogNativeSlugs, nativeInputModalities, nativeReasoningEfforts, nativeDefaultReasoningEffort, shouldIncludeAccountBoundNativeOpenAi, shouldIncludeNativeOpenAi, type NativeContextLimits, type NativeContextLimitsInput } from "./catalog/metadata";
export { accountBoundNativeOpenAiSlugs, accountBoundNativeOpenAiSlugsBySelector, CODEX_NATIVE_ALIAS_CATALOG_KIND, NATIVE_DAYBREAK_BLUE_MODEL, NATIVE_GPT56_CONTEXT_WINDOW, NATIVE_GPT56_MAX_INPUT_TOKENS, NATIVE_GPT56_OPT_IN_CONTEXT_WINDOW, NATIVE_OPENAI_CAPABILITY_ALIAS_MODELS, NATIVE_OPENAI_MODELS, configuredNativeAliasSlugs, desktopAllowlistSuppressedNativeSlugs, isNativeAliasCatalogEntry, isNativeOpenAiCapabilityAliasModel, nativeContextLimits, nativeOpenAiCapabilitySourceSlug, nativeOpenAiContextWindow, nativeOpenAiMaxInputTokens, disabledNativeSlugs, visibleNativeSlugs, desktopVisibleNativeSlugs, nativeModelRows, applyNativeVisibility, observedAccountBoundNativeEntries, observedAccountBoundNativeOpenAiSlugs, upstreamNativeEntry, nativeOpenAiSlugs, listCatalogNativeSlugs, nativeInputModalities, nativeReasoningEfforts, nativeDefaultReasoningEffort, shouldIncludeAccountBoundNativeOpenAi, shouldIncludeNativeOpenAi, type NativeContextLimits, type NativeContextLimitsInput } from "./catalog/metadata";
export { isSpawnableCodexCandidate, codexExecInvocation, loadBundledCodexCatalog, materializeBundledCodexCatalog, loadCatalogTemplate } from "./catalog/bundled";
export { nativeEffortClamp, shouldApplyNativeEffortClamp, catalogModelEfforts, codexSupportedReasoningEfforts, clampedDefaultEffort, clampEntryToCodexSupportedEfforts, clampCatalogModelsToCodexSupport } from "./catalog/effort";
export { applyProviderConfigHints, isDatedVariantId, filterCatalogVisibleModels, gatherRoutedModels, clearGatherRoutedModelsInflight, augmentRoutedModelsWithRegistryOpenAiApiRows, augmentRoutedModelsWithMetadata, resolveComboCatalogMember, configuredComboTargetModelsByProvider } from "./catalog/provider-fetch";
Expand Down
Loading
Loading