Skip to content

[WRONG BRANCH] Merge dev into preview: Windows suite green - #1907

Merged
lidge-jun merged 23 commits into
previewfrom
promote-preview
Aug 17, 2026
Merged

[WRONG BRANCH] Merge dev into preview: Windows suite green#1907
lidge-jun merged 23 commits into
previewfrom
promote-preview

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Summary

Promotes dev to preview: the Windows suite work merged in #1881, plus the 21 commits already on dev.

Fast-forward-shaped merge of origin/dev with no conflicts. Highlights from #1881:

Verification

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Summary by CodeRabbit

  • New Features
    • GPT-5.6 native models now use a 272k-token default context window.
    • Eligible GPT-5.6 models can opt in to a context window of up to 922k tokens.
    • Model settings, catalog details, routing, and integrations consistently reflect configured native limits.
  • Bug Fixes
    • Improved Windows compatibility for identity resolution, file permissions, symlinks, and secure ACL operations.
    • Improved cleanup and reliability for background processes, database operations, and configuration updates.
  • Documentation
    • Updated GPT-5.6 context-window and opt-in behavior documentation.

lidge-jun and others added 23 commits August 17, 2026 17:49
Codex-login 5.6 rows advertised 922k with no user action. Follow the live
catalog default of 272k, and let the native switch or overlay raise to the
measured 922k ceiling. gpt-5.4 stays 1M; the API-key 1.05M path is unchanged.
…sktop writers

Pass full nativeContextLimits into model-info, catalog, and Desktop apply paths
so a 1M overlay is not dropped. Keep the combo fallback ceiling on the 5.6
family so a GPT-5.4 native alias does not inherit 922k.
Bare icacls.exe on PATH threw ENOENT under a bun-shim environment and was reported as missing NTFS ACL support, which blocked ocx service install. Use GetSystemDirectoryW like schtasks/powershell, and classify spawn failure as EICACLS.
The Windows coordinator namespace resolved LocalAppData through .NET
GetFolderPath(SpecialFolder.LocalApplicationData), which follows USERPROFILE and
returns an EMPTY STRING -- not an error -- when the profile it computes has no
AppData directory on disk. Any caller with a redirected USERPROFILE therefore
refused every coordinator lookup with "Windows effective-account lookup returned
an empty value", which is precisely the environment dependence this module exists
to eliminate. The suite hid it by handing each child the real profile back, so
the defect read as unrelated assertion failures across locking, transition-state,
catalog serialization and sync.

Use SHGetKnownFolderPath with a null token and KF_FLAG_DEFAULT_PATH instead: it
reads the known-folder registration for the effective token, returns the real
per-user path whether or not the directory exists, and is unaffected by
USERPROFILE, LOCALAPPDATA, HOMEDRIVE or HOMEPATH. A non-null token is NOT
equivalent: passing (HANDLE)-1 resolves the built-in Default profile, which would
key coordination to a namespace no real account writes to.

The write-lock contention child published its hold marker with Bun.write, whose
write only lands on a later event-loop turn. The callback that follows is a
synchronous busy wait by contract, so the marker appeared ~3s late, after the hold
had already ended, and the contender met an unheld lock and reported acquired
where the test demands busy. Write the marker synchronously.

The symlink spelling case needed Developer Mode to create a directory symlink;
an NTFS junction needs no privilege and exercises the same realpath
canonicalization, so the invariant stays proven on an unelevated machine.
…st isolation

Six failures on an unelevated Windows checkout, none of which were product bugs
in the code they pointed at:

The test sandbox moves HOME, and git resolves ~/.gitconfig from HOME, so the
developer's `safe.directory` became invisible to every git call a test made. On a
checkout whose directory owner differs from the running account -- ordinary on
Windows when a tool or installer created the tree -- git then refused with
"detected dubious ownership", the adapter read that as "not a git repository",
and command-code asserted against its empty fallback. Pin GIT_CONFIG_GLOBAL to
the real file before HOME moves; the sandbox is unchanged, since git writes
nothing there.

claude-management-api spoofed process.platform globally, which sent Windows
management-token initialization down the POSIX ACL path and answered 503 before
the assertion under test was ever reached. Project the capability through an
explicit management dependency instead, so the platform under test is named
rather than impersonated.

codex-sqlite-home asserted a POSIX-shaped literal for a relative-path resolution
whose point is anchoring, not spelling; every neighbouring case already spells it
through resolve/join. codex-history-reachability compared backslash paths against
a forward-slash inventory, so the named permitted module could not match itself.
codex-catalog-writer asserted chmod through stat mode bits that Windows only
synthesizes, while the recorded harden effect proves the same transition. cli
models and the catalog resync exceeded Bun's 5s default while doing real
multi-process CLI work, and now use the repository's existing spawn budget.

codex-config-generation created fixtures under tests/ and replaced its sandbox
root with a file, so a failed SQLite open kept a Windows handle and teardown left
the directory behind; it uses the OS temp dir and a directory at the database
path, keeping the typed-error coverage.

The catalog-sync workaround that handed children back the real USERPROFILE is
removed: the defect it described is fixed at the source in the parent commit, and
a workaround outliving its cause only hides the next regression.
…of the code

The bare-PATH resolution case builds its launcher with a file symlink, which needs
Developer Mode or admin on Windows and failed with EPERM before the probe under
test ever ran. No privilege-free substitute preserves what it proves: the resolver
follows the PATH entry through realpath into `@openai/codex/bin/` to reach the
sibling platform package, and a copy erases that association, a hard link reports
its own path as its realpath, and a .cmd wrapper is never matched for a bare
command. Report a visible skip where the OS withholds the privilege, in the shape
claude-agents-inject and codex-service-manager-probe already use.

The key-delegation case called codexFeaturesInvocation with no seams, so it read
the developer's own Codex install. Where that install is the npm codex.cmd, the
invocation is correctly wrapped in `cmd /d /s /c` and the raw-args assertion
failed -- describing the machine's install shape, not the delegation under test.
Name the platform and resolution seams, exactly as the invocation-shape case
further down the same file already does.
…values

rootTomlString and providerTableString returned the raw bytes between the quotes,
so a basic TOML string was never unescaped. On Windows that matters immediately:
a path is written as an escaped basic string, so reading it back yielded doubled
backslashes and a value that matches nothing on disk. The journal records
injectedCatalogPath through exactly this path, so restore after a Codex app
rewrite could not recognize the catalog it had written itself (#1798).

paths.ts already had the correct reader -- readRootTomlString captures the quoted
value and decodes it with parseTomlString. These two helpers are the same idea
spelled a second time without that step, which is why the divergence went unseen
on POSIX, where an escaped path and its raw bytes are usually identical. Capture
the value with its quotes and decode it through the same parser rather than
maintaining a second, subtly weaker interpretation of the format.
The effective token's SID and its known-folder local AppData were re-derived by a
fresh PowerShell on every call: about 150ms and 310ms respectively, and the
coordinator asks for both on every config write and lock acquisition. Neither can
change without a new logon token, and both lookups deliberately ignore the
environment, so the second spawn only re-establishes what the first already knew.

On Windows that overhead was not merely wasteful: it pushed real multi-process
injection tests past their budget, where they timed out at 5s while doing genuine
work. Memoize successful lookups for the process lifetime -- roughly 510ms to 1ms
for a coordinator path resolution. Refusals are not cached, so a transient failure
cannot pin a process into a permanently refusing state.
…und fixtures

The core/Lab boundary test never ran on Windows. It built its repository root from
`new URL(import.meta.url).pathname`, which yields "/C:/..." there, so resolving it
produced "C:\\C:\\..." and every case threw ENOENT while opening its own sources.
Two further spellings assumed POSIX separators: the walk matched the literal
"/src/lab/", which no backslash path can contain, and the reported chain kept the
native separator so the attack cases could not match it.

That combination matters more than a red test. This guard exists because the
original violation hid in a six-hop import chain and pulled ~69 Lab modules into
every install; with the path broken it would have reported clean for a real Lab
import exactly as it did for a missing file. Its own adversarial cases now fail
before the fix and pass after it, which is the evidence that it is live again.

config.ts dotfiles cases need a file symlink, which no privilege-free construct
substitutes for, so they take the visible skip this repository already uses for
the same constraint. The DSH settings case asserted 0o600 through stat, but
Windows synthesizes mode from the read-only attribute and always answers 0o666;
assert the file exists everywhere and the permission bits only where they mean
something.
… own file

rebuildLabProjection closed its database without finalizing the statements it had
prepared. Bun keeps a prepared statement alive until it is finalized or collected,
and on Windows an outstanding statement holds the file open: `close()` leaves the
handle behind and `close(true)` throws "database is locked". The next rebuild then
could not unlink the projection it was replacing, and the retry loop in wipeSqlite
could only convert that into a slower failure -- "failed to remove stale projection
file after retries". POSIX permits unlinking an open file, which is why a rebuild
that is deterministic by contract was only ever non-deterministic on Windows.

Collect the prepared statements and finalize them before the close. This is the
real defect behind ten Compatibility Lab failures across the ledger, fabric-task
and public-evidence suites, all of which called rebuild more than once.

Two server tests also exceeded Bun's 5s default while binding real proxies: the
Retry-After case runs two full pool-passthrough cycles and the #702 case binds one
proxy per route class to prove none of them reaches upstream. In both the servers
are the assertion, so they take the existing SERVER_BUDGET_MS rather than a new knob.
The contention test released its holder and dropped the exit promise on the floor,
so afterEach could remove the temp root while that child still had the coordinator
database open. Windows refuses to unlink a file another process holds, so teardown
threw EBUSY and the failure was attributed to a test that had already proved its
assertion. POSIX unlinks an open file regardless, which is why this only ever
appeared on Windows, and only under full-suite load where the child exits slower.

Await the holder, and let teardown retry briefly before giving the directory back
to the OS: `force` covers a missing path, not a locked one, and a temp directory
left behind is a smaller lie than a green test reported red.
Filling the affinity cap persists CODEX_THREAD_AFFINITY_MAX_ENTRIES real mappings, and that store work is the eviction proof rather than incidental setup. On Windows the pair sits right on Bun default of 5s -- one measured 5.7s and its neighbour 5.25s -- so the cap test failed on load while the test beside it passed by a quarter second. Both take the existing STORE_BUDGET_MS.
The isolated Codex home rethrew when its temp tree could not be removed. On
Windows a proxy or child that is still shutting down can hold a file there past
the 2.5s retry budget, and the throw landed in afterEach -- so a test that had
already asserted everything it claims was reported red, and the red pointed at
whatever happened to run in that slot rather than at an OS release race.

The env restore is the part other tests depend on and still runs unconditionally;
the directory is disposable. Leave it to the OS when the retries are exhausted. The
rate-limit E2E teardown had the same shape with a worse consequence: a failed
removal skipped the clearKeyCooldowns() call after it, leaking cooldown state into
the next test.
completeMockCodexOAuth waited between login-status polls with queueMicrotask. A
microtask only yields to work already queued, but the login flow awaits real I/O --
credential reads and the WHAM fetch -- so under load its continuation lands on the
macrotask queue and 500 microtask turns can pass without it running once. The flow
then reached its own 150-poll ceiling and reported "Login timed out before OAuth
completed" where the test asserts a specific commit-failure message, which reads as
a behavioural regression rather than a starved poller.

setImmediate yields past the microtask queue, so each poll observes the state the
flow actually reached.
The refusal is only proven by letting a connection attempt reach its own 2s socket timeout, on top of starting and stopping a real proxy and listener. On a loaded Windows box that measured 5.04s against Bun default of 5s, so the case failed for the wait that IS its assertion. Use the existing SERVER_BUDGET_MS.
discoverProjectCodexConfigPaths walks up to 12 parents, and on Windows the OS temp
directory lives under C:\Users\<user> -- so the fixture's walk climbed out of the
fixture and found the developer's real ~/.codex/config.toml. The identity check
cannot exclude it, because it genuinely is a different file from the fixture's
codexConfigPath. Bound the walk; the assertion is that a parent walk does not
rediscover the global config, not how far it may travel.

The claim-narrowing case asserted 0o644 before and 0o600 after, but Windows
synthesizes mode from the read-only attribute and answers 0o666 regardless, so
neither end of the transition is observable there. The call still runs on every
platform; only the POSIX-shaped observation is conditional.

The auth-temp residue case needs a real file symlink to prove it refuses to follow
one, and that needs Developer Mode or admin. Take the visible skip; the hard-link
case beside it still proves the scrubber will not truncate a shared target here.
…wn race

Four responses-state cases are irreducibly about symlink resolution -- following a
symlinked snapshot to its real directory, or refusing an oversized or non-regular
one -- and creating a file symlink needs Developer Mode or admin on Windows. They
failed in the fixture, before the behaviour under test ran. Detect the privilege
once and take the visible skip this repository already uses for the constraint.

The CL-06 boundary teardown removed its temp root unconditionally and threw EBUSY
when a shutting-down server still held a file there, failing a test that had
already asserted. The state that matters is reset before it; leave the directory
to the OS.
Starting two real servers, driving a policy job to idle, and stopping both IS the assertion that one stop leaves the other process-wide work alone. That sequence measured 5.4s against Bun default of 5s on Windows, so it failed for its own evidence. Use the existing SERVER_BUDGET_MS.
inspectNpmCacheDirectory judges accessibility from POSIX owner bits, and a Windows
directory reports 0o666 with no execute bit -- so the owner-rwx check can never
pass and every inspection answered cache_entry_inaccessible. That is not a defect
to fix: the module inspects a Unix npm cache, and runNpmCachePreflight already
returns windows_skip before reaching it. The worker round-trip case additionally
spawns the real npm while claiming a non-Windows platform, which is slow and
proves nothing here. Both are now explicitly non-Windows, and the windows_skip
case beside them still covers the branch this platform actually takes.

Three real-home guard cases and three npm-cache cases need genuine symlinks to
prove the guard resolves through one; that needs Developer Mode or admin. They
take the visible skip already used elsewhere for the same constraint.
Both failures are on origin/dev independently of this branch, and both come from
the same shape: a test that asserts on the TEXT of a source file, pinned to a
spelling the implementation has since changed.

8b67220 threaded nativeContextLimits through the remaining Codex and Desktop
writers, but sync-client-integrations still required the retired
providerContextCap spelling -- so the check failed against the very change it
exists to pin. The GUI cap-display check required a one-line expression that is now
wrapped and has grown a native branch, so it was pinning formatting rather than
behaviour. Match the current spellings, and match the GUI expression as fragments
so a reflow cannot fail it again.

Verified on origin/dev before this branch was rebased onto it: the sync case fails
there with the same message, and the GUI case fails there in a clean worktree.
fix(windows): make the suite pass on an unelevated Windows checkout
@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot changed the title Merge dev into preview: Windows suite green [WRONG BRANCH] Merge dev into preview: Windows suite green Aug 17, 2026
@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • wrong target branch (preview); retarget to dev. UI screenshot required.

What to do

  • Retarget this PR to dev — all contributions go to dev.
  • Add a screenshot of the UI change to the PR description.

Its title has been prefixed with [WRONG BRANCH].
Automatic draft conversion failed (token cannot change draft status). Please convert this pull request to a draft manually. The required enforce-target check will keep failing until every issue above is resolved.

@github-actions
github-actions Bot marked this pull request as draft August 17, 2026 09:55
@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1eb8acc2-969b-446a-8daf-0da267738470

📥 Commits

Reviewing files that changed from the base of the PR and between f32a2f5 and 6a23ea9.

📒 Files selected for processing (79)
  • devlog/_plan/260817_native_gpt56_1m_context/070_default_272k_opt_in.md
  • gui/src/pages/Models.tsx
  • gui/src/pages/models-shared.ts
  • gui/tests/models-native-group-controls.test.ts
  • scripts/test.ts
  • src/claude/context-windows.ts
  • src/claude/desktop-3p.ts
  • src/claude/model-info.ts
  • src/cli/claude-desktop.ts
  • src/codex/catalog.ts
  • src/codex/catalog/metadata.ts
  • src/codex/catalog/provider-fetch.ts
  • src/codex/injected-marker.ts
  • src/codex/user-identity.ts
  • src/grok/sync.ts
  • src/lab/projection/rebuild.ts
  • src/lib/windows-elevation.ts
  • src/lib/windows-secret-acl.ts
  • src/routing/capability.ts
  • src/server/index.ts
  • src/server/management-api.ts
  • src/server/management/agent-settings-routes.ts
  • src/server/management/config-routes.ts
  • src/server/management/context.ts
  • src/server/management/native-integration-routes.ts
  • src/server/management/shared.ts
  • src/server/responses/core.ts
  • src/server/responses/input-admission.ts
  • src/server/system-env.ts
  • structure/08_openai-provider-tiers.md
  • tests/claude-context-windows.test.ts
  • tests/claude-desktop-native-context.test.ts
  • tests/claude-management-api.test.ts
  • tests/claude-model-info.test.ts
  • tests/cli-models.test.ts
  • tests/codex-auth-api.test.ts
  • tests/codex-catalog-sync-hardening.test.ts
  • tests/codex-catalog-writer.test.ts
  • tests/codex-catalog.test.ts
  • tests/codex-composed-acceptance.test.ts
  • tests/codex-config-generation.test.ts
  • tests/codex-convergence-account-selectors.test.ts
  • tests/codex-history-reachability.test.ts
  • tests/codex-inject-integration.test.ts
  • tests/codex-inject-write-lock.test.ts
  • tests/codex-journal.test.ts
  • tests/codex-log-guard-coderabbit.test.ts
  • tests/codex-restore-app-rewrite.test.ts
  • tests/codex-retained-root-serialization.test.ts
  • tests/codex-routing.test.ts
  • tests/codex-sqlite-home.test.ts
  • tests/codex-sync-api.test.ts
  • tests/codex-transition-state.test.ts
  • tests/codex-v2-gate.test.ts
  • tests/codex-write-lock.test.ts
  • tests/config.test.ts
  • tests/core-lab-boundary.test.ts
  • tests/dsh-writer-lock.test.ts
  • tests/grok-sync.test.ts
  • tests/helpers/codex-write-lock-child.ts
  • tests/helpers/isolated-codex-home.ts
  • tests/input-admission.test.ts
  • tests/issue-452-empty-503.test.ts
  • tests/issue-702-expired-replay-state.test.ts
  • tests/loopback-listener-integration.test.ts
  • tests/native-main-auth-temp.test.ts
  • tests/native-main-claim.test.ts
  • tests/native-model-toggle.test.ts
  • tests/project-config-warnings.test.ts
  • tests/responses-state.test.ts
  • tests/route-explainability.test.ts
  • tests/routing-compatibility-boundaries.test.ts
  • tests/server-background-lifecycle.test.ts
  • tests/server-rate-limit-retry-e2e.test.ts
  • tests/sync-client-integrations.test.ts
  • tests/test-home-guard.test.ts
  • tests/update-npm-cache-preflight.test.ts
  • tests/windows-elevation.test.ts
  • tests/windows-secret-acl.test.ts

📝 Walkthrough

Walkthrough

GPT-5.6 native models now default to a 272k-token context window and support a clamped 922k opt-in. Native context limits replace the OpenAI provider cap across catalog, server, integrations, and GUI paths. Windows process resolution, SQLite cleanup, and cross-platform tests were also hardened.

Changes

Native GPT-5.6 context handling

Layer / File(s) Summary
Catalog limits and resolution
src/codex/catalog/*
GPT-5.6 models use a 272k default and a 922k opt-in ceiling. Native combo and custom aliases resolve limits through the catalog.
Server and integration propagation
src/server/..., src/claude/..., src/grok/sync.ts, src/routing/capability.ts
Native context-limit objects replace the OpenAI Codex provider cap across model discovery, Claude configuration, Grok synchronization, routing evidence, and input admission.
GUI, documentation, and tests
gui/src/pages/*, structure/08_openai-provider-tiers.md, tests/*context*, tests/native-model-toggle.test.ts
Native provider controls show the 272k default and send the 922k opt-in. Documentation and expectations reflect the new default and opt-in behavior.

Windows and test reliability

Layer / File(s) Summary
Windows identity and ACL execution
src/codex/user-identity.ts, src/lib/windows-*.ts
LocalAppData uses a known-folder lookup. ACL operations resolve trusted icacls.exe paths and convert launch failures into unsuccessful results.
SQLite and test portability
src/lab/projection/rebuild.ts, tests/*
SQLite statements are finalized before database closure. Tests add bounded timeouts, portable paths, platform-specific symlink handling, and defensive teardown cleanup.

Estimated code review effort: 4 (Complex) | ~60 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch promote-preview

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lidge-jun
lidge-jun marked this pull request as ready for review August 17, 2026 09:55
@lidge-jun
lidge-jun merged commit e25ec09 into preview Aug 17, 2026
25 of 28 checks passed
@lidge-jun
lidge-jun deleted the promote-preview branch August 17, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant