fix(codex): avoid runtime shadow reindex on TUI startup#639
Conversation
Run interactive TUI sessions against the canonical Codex home so its state database and thread index remain reusable. Route both the TUI and its app-server through ephemeral non-secret proxy overrides, preserving account rotation without mutating config or exposing credentials.
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
📝 WalkthroughMinor-risk performance and startup architecture update: the interactive Codex TUI now reuses the canonical Codex home, preserving its state database and thread index instead of rebuilding a shadow home, reducing repeat startup from ~40s to ~9.5s on macOS. Runtime proxy configuration is injected through ephemeral environment-backed CLI overrides without persisting Walkthroughthe runtime rotation helper now supports canonical-home execution, forwards dynamic app-server config arguments through its shim, and propagates helper-provided arguments into the final runtime process. interactive tui routing enables this mode and adds regression coverage. Changescanonical runtime rotation
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
test/codex-bin-wrapper.test.tsOops! Something went wrong! :( ESLint: 10.0.0 Error: The 'jiti' library is required for loading TypeScript configuration files. Make sure to install it. 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/codex.js`:
- Around line 3497-3528: Prevent interactive TUI and app-helper modes from
concurrently using the real Codex home without protection: update
createRuntimeRotationProxyCanonicalCodexHome to restore isolated shadow-home
behavior with safe sync-back, or enforce an equivalent single-instance
lock/flock with backoff around canonical sessions. In
test/codex-bin-wrapper.test.ts lines 2763-2857, add a regression that launches
two canonical sessions concurrently and verifies session/SQLite state is
preserved without corruption or loss.
In `@test/codex-bin-wrapper.test.ts`:
- Around line 2763-2857: The canonical Codex home test covers only one
interactive session and does not reproduce concurrent access. Extend the test
around “uses the canonical Codex home for interactive TUI runtime routing” to
launch overlapping TUI processes sharing the same canonical home, coordinate
their execution, and assert both complete without state/config corruption.
Preserve the existing routing and persistence assertions while adding the
concurrency regression coverage.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 839395a9-0370-4212-92c1-84143c42999d
📒 Files selected for processing (2)
scripts/codex.jstest/codex-bin-wrapper.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (10)
test/**/*.test.ts
📄 CodeRabbit inference engine (test/AGENTS.md)
test/**/*.test.ts: Write Vitest test suites with globals enabled (describe, it, expect)
Maintain 80%+ coverage threshold across statements, branches, functions, and lines
Use removeWithRetry() for Windows filesystem cleanup instead of bare fs.rm to handle EBUSY, EPERM, and ENOTEMPTY errors
Do not rely on dist/ in tests; use source files instead
Do not skip tests without justification
Relax lint rules for test files as configured in eslint.config.js
Files:
test/codex-bin-wrapper.test.ts
test/**/codex-bin-wrapper.test.ts
📄 CodeRabbit inference engine (test/AGENTS.md)
Test bin wrapper lazy-load and missing dist handling with concurrent invocations in codex-bin-wrapper.test.ts
Files:
test/codex-bin-wrapper.test.ts
**/*.{ts,js}
📄 CodeRabbit inference engine (AGENTS.md)
Use ESM only ("type": "module"), Node >= 18.17
Files:
test/codex-bin-wrapper.test.tsscripts/codex.js
**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Do not use
as any,@ts-ignore, or@ts-expect-errorin TypeScript files
Files:
test/codex-bin-wrapper.test.ts
{scripts/**/*.js,test/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Do not use bare recursive delete logic in Windows-sensitive scripts/tests without retry handling
Files:
test/codex-bin-wrapper.test.tsscripts/codex.js
**/*.{js,ts,mjs,cjs}
📄 CodeRabbit inference engine (README.md)
**/*.{js,ts,mjs,cjs}: Keep npm installation scripts side-effect-free; postinstall may print a short notice but must not modify runtime state or perform setup, especially in CI or non-interactive installs.
Never run npm install or update commands automatically; only display a manual upgrade notice when appropriate.
Do not publish or take ownership of a globalcodexbinary; preserve the official OpenAI installation as the owner of thecodexcommand.
Keep runtime rotation and local bridge services loopback-only, and protect local bridge access with hashed client tokens.
Keep OAuth credentials and account state local; do not send them to external services as part of normal account management.
Treat Responses background mode as opt-in: requests withbackground: truemust use statefulstore=true, while default stateless routing usesstore=false.
Use bounded outbound request budgets, avoid whole-pool replay when every account is rate-limited, and enter cooldown after repeated cross-account 5xx bursts.
Make experimental synchronization and backup flows non-destructive by default: preview before applying sync, preserve destination-only accounts, and fail safely on backup filename collisions.
Files:
test/codex-bin-wrapper.test.tsscripts/codex.js
test/**
⚙️ CodeRabbit configuration file
tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.
Files:
test/codex-bin-wrapper.test.ts
scripts/codex*.js
📄 CodeRabbit inference engine (AGENTS.md)
Do not bypass the official Codex CLI by reimplementing general Codex commands in the wrapper
Files:
scripts/codex.js
{scripts/*.js,lib/codex-manager/**/*.ts}
📄 CodeRabbit inference engine (AGENTS.md)
Canonical package name is
codex-multi-auth; canonical command family iscodex-multi-auth ...
Files:
scripts/codex.js
{lib,scripts}/**/*.{ts,js}
📄 CodeRabbit inference engine (AGENTS.md)
Windows filesystem safety: retry transient
EBUSY/EPERM/ENOTEMPTYcleanup and write failures where tests cover Windows locks
Files:
scripts/codex.js
🧠 Learnings (2)
📚 Learning: 2026-06-04T06:14:18.093Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/scheduling-strategy-config.test.ts:1-1
Timestamp: 2026-06-04T06:14:18.093Z
Learning: In ndycode/codex-multi-auth, do not flag explicit imports from "vitest" (e.g., describe, it, expect, beforeEach/afterEach, etc.) in test files as issues—even if the Vitest config sets `globals: true`. The repo’s established convention is to keep these imports for consistency with neighboring tests; removing them would make files outliers.
Applied to files:
test/codex-bin-wrapper.test.ts
📚 Learning: 2026-06-04T06:14:24.975Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/runtime-rotation-proxy.test.ts:2478-2491
Timestamp: 2026-06-04T06:14:24.975Z
Learning: In ndycode/codex-multi-auth test files (e.g. `test/*.test.ts`), when creating V3 storage fixtures for accounts, it’s an intentional convention to use `as never` for deliberately minimal stored-account objects that only include `refreshToken`, `addedAt`, and `lastUsed`. Do not treat `as never` here as a type-safety problem: optional/other fields are expected to be populated by the runtime during execution, and the cast is used solely to keep the fixture minimal and consistent across existing tests.
Applied to files:
test/codex-bin-wrapper.test.ts
🪛 ast-grep (0.44.1)
test/codex-bin-wrapper.test.ts
[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { type SpawnSyncReturns, spawn, spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(detect-child-process-typescript)
🔇 Additional comments (9)
scripts/codex.js (9)
77-80: LGTM!
3543-3562: LGTM!
3608-3608: LGTM!Also applies to: 3665-3669
3770-3770: LGTM!
3832-3832: LGTM!Also applies to: 3869-3869, 3900-3926, 3935-3936
3997-3997: LGTM!Also applies to: 4017-4018
4084-4091: LGTM!Also applies to: 4108-4108
4143-4151: LGTM!
3506-3506: 🎯 Functional Correctness
APP_SERVER_ACCOUNT_DISPLAY_NAMEis declared atscripts/codex.js:66, so this reference is safe.
| function createRuntimeRotationProxyCanonicalCodexHome( | ||
| baseEnv, | ||
| proxyBaseUrl, | ||
| clientApiKey, | ||
| configTomlModule, | ||
| ) { | ||
| const originalCodexHome = resolveRuntimeRotationProxyOriginalCodexHome(baseEnv); | ||
| const providerTable = `model_providers.${RUNTIME_ROTATION_PROXY_PROVIDER_ID}`; | ||
| const configArgs = [ | ||
| `${providerTable}.name=${configTomlModule.tomlStringLiteral(APP_SERVER_ACCOUNT_DISPLAY_NAME)}`, | ||
| `${providerTable}.base_url=${configTomlModule.tomlStringLiteral(proxyBaseUrl)}`, | ||
| `${providerTable}.env_key=${configTomlModule.tomlStringLiteral("OPENAI_API_KEY")}`, | ||
| `${providerTable}.requires_openai_auth=false`, | ||
| `${providerTable}.wire_api=${configTomlModule.tomlStringLiteral("responses")}`, | ||
| "disable_response_storage=false", | ||
| ].flatMap((assignment) => ["-c", assignment]); | ||
|
|
||
| return { | ||
| args: configArgs, | ||
| env: { | ||
| ...baseEnv, | ||
| CODEX_HOME: originalCodexHome, | ||
| OPENAI_API_KEY: clientApiKey, | ||
| CODEX_MULTI_AUTH_DIR: resolveRuntimeRotationOriginalMultiAuthDir( | ||
| originalCodexHome, | ||
| baseEnv, | ||
| ), | ||
| }, | ||
| cleanup: () => {}, | ||
| }; | ||
| } | ||
|
|
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'repo files matching codex.js/codex-bin-wrapper.test.ts:\n'
fd -a 'codex\.js$|codex-bin-wrapper\.test\.ts$' . | sed 's#^\./##'
printf '\noutline scripts/codex.js around target functions:\n'
ast-grep outline scripts/codex.js --match createRuntimeRotationProxyCanonicalCodexHome --view expanded || true
ast-grep outline scripts/codex.js --match createRuntimeRotationProxyCodexHome --view expanded || true
printf '\nrelevant scripts/codex.js lines:\n'
nl -ba scripts/codex.js | sed -n '3360,3560p'
printf '\nlock/guard terms in scripts/codex.js:\n'
rg -n "lock|single|instance|FILE_LOCK|tryLock|flock|lockfile|fs\\.lock|fs\\.open|mkdtemp|tmpdir|ORIGINAL_CODEX_HOME|CODEX_HOME=|CODEX_MULTI_AUTH_REAL_CODEX_BIN|createRuntimeRotation" scripts/codex.js || true
printf '\ntest lines:\n'
nl -ba test/codex-bin-wrapper.test.ts | sed -n '2700,2875p'Repository: ndycode/codex-multi-auth
Length of output: 614
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'scripts/codex.js relevant lines:\n'
awk 'NR>=3360 && NR<=3560 {printf "%6d\t%s\n", NR, $0}' scripts/codex.js
printf '\nlock/guard terms in scripts/codex.js:\n'
rg -n "lock|single|instance|FILE_LOCK|tryLock|flock|lockfile|fs\\.lock|fs\\.open|mkdtemp|tmpdir|ORIGINAL_CODEX_HOME|CODEX_HOME=|CODEX_MULTI_AUTH_REAL_CODEX_BIN|createRuntimeRotation" scripts/codex.js || true
printf '\ncreateRuntimeRotationProxyCanonicalCodexHome call sites in scripts/codex.js:\n'
rg -n "createRuntimeRotationProxyCanonicalCodexHome|createRuntimeRotationProxyCodexHome|app-bridge|app-server|--canonical-shim" scripts/codex.js || true
printf '\ntest/codex-bin-wrapper.test.ts relevant lines:\n'
awk 'NR>=2700 && NR<=2875 {printf "%6d\t%s\n", NR, $0}' test/codex-bin-wrapper.test.ts
printf '\nconcurrency-related terms in test/codex-bin-wrapper.test.ts:\n'
rg -n "concurrent|concurren|Promise\\s*<|all\\(|race\\(|spawnSync|fork\\(|parallel|simultan|same fixture home|same home" test/codex-bin-wrapper.test.ts || trueRepository: ndycode/codex-multi-auth
Length of output: 28523
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'codex.js lines around canonical context creation and app helper startup:\n'
awk 'NR>=3870 && NR<=3940 {printf "%6d\t%s\n", NR, $0}' scripts/codex.js
awk 'NR>=4010 && NR<=4155 {printf "%6d\t%s\n", NR, $0}' scripts/codex.js
awk 'NR>=4210 && NR'=4295' {printf "%6d\t%s\n", NR, $0}' scripts/codex.js
printf '\nsearch canonical home tests near usages:\n'
rg -n "canonical Codex home|canonical-shim|canonical.*home|app-server --canonical-shim|createRuntimeRotationProxyCanonicalCodexHome" test/codex-bin-wrapper.test.ts scripts/codex.js || true
printf '\nPython source scan for lock/single-instance around canonical home env:\n'
python3 - <<'PY'
from pathlib import Path
p=Path('scripts/codex.js')
s=p.read_text()
for name in ['createRuntimeRotationProxyCanonicalCodexHome','createRuntimeRotationProxyContextIfEnabled','createRuntimeRotationAppHelperContext']:
idx=s.find(f'function {name}')
print(f'{name}: found={idx!=-1}')
print()
for needle in [
'FILE_LOCK', 'single-instance', 'tryLock', 'flock', 'lockfile', 'mkdtempSync(join(shadowRoot',
'CODEX_HOME: originalCodexHome', 'cleanup: () => {}',
]:
print(needle, '=>', s.find(needle))
PYRepository: ndycode/codex-multi-auth
Length of output: 41998
don’t give interactive TUI/app-helper modes unguarded access to the real codex home.
scripts/codex.js:3903-3938 selects createRuntimeRotationProxyCanonicalCodexHome for TUI and scripts/codex.js:4078-4124 gives the helper the same env; it sets CODEX_HOME to originalCodexHome with cleanup: () => {}, while scripts/codex.js:3419-3495 previously used a shadow home and sync-back. no lock/single-instance guard is in play, so two concurrent canonical codex-multi-auth sessions using the same Codex home can race on session/sqlite state. add a regression in test/codex-bin-wrapper.test.ts:2763-2857 that launches two canonical sessions concurrently and asserts no state corruption/loss, or enforce a single-instance/flock/backoff design.
📍 Affects 2 files
scripts/codex.js#L3497-L3528(this comment)test/codex-bin-wrapper.test.ts#L2763-L2857
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/codex.js` around lines 3497 - 3528, Prevent interactive TUI and
app-helper modes from concurrently using the real Codex home without protection:
update createRuntimeRotationProxyCanonicalCodexHome to restore isolated
shadow-home behavior with safe sync-back, or enforce an equivalent
single-instance lock/flock with backoff around canonical sessions. In
test/codex-bin-wrapper.test.ts lines 2763-2857, add a regression that launches
two canonical sessions concurrently and verifies session/SQLite state is
preserved without corruption or loss.
Source: Path instructions
| it("uses the canonical Codex home for interactive TUI runtime routing", async () => { | ||
| const fixtureRoot = createWrapperFixture(); | ||
| createRuntimeRotationProxyFixtureModule(fixtureRoot); | ||
| const fakeBin = createCustomFakeCodexBin(fixtureRoot, [ | ||
| "#!/usr/bin/env node", | ||
| 'const { spawnSync } = require("node:child_process");', | ||
| 'const fs = require("node:fs");', | ||
| 'const path = require("node:path");', | ||
| 'const args = process.argv.slice(2);', | ||
| 'if (args[0] === "app-server") {', | ||
| ' console.log(`APP_SERVER_FORWARDED:${args.join(" ")}`);', | ||
| " process.exit(0);", | ||
| "}", | ||
| 'const statePath = path.join(process.env.CODEX_HOME ?? "", "state_5.sqlite");', | ||
| 'const originalState = path.join(process.env.ORIGINAL_CODEX_HOME ?? "", "state_5.sqlite");', | ||
| 'console.log(`TUI_HOME_IS_ORIGINAL:${process.env.CODEX_HOME === process.env.ORIGINAL_CODEX_HOME}`);', | ||
| 'console.log(`TUI_STATE_EXISTED:${fs.existsSync(statePath)}`);', | ||
| 'fs.writeFileSync(statePath, "first-run-state\\n", "utf8");', | ||
| 'console.log(`TUI_STATE_PERSISTED:${fs.readFileSync(originalState, "utf8").includes("first-run-state")}`);', | ||
| 'console.log(`TUI_HAS_BASE_URL_OVERRIDE:${args.some((arg) => arg.includes("model_providers.codex-multi-auth-runtime-proxy.base_url="))}`);', | ||
| 'console.log(`TUI_HAS_ENV_KEY_OVERRIDE:${args.includes(\'model_providers.codex-multi-auth-runtime-proxy.env_key="OPENAI_API_KEY"\')}`);', | ||
| 'console.log(`TUI_HAS_AUTH_OVERRIDE:${args.includes("model_providers.codex-multi-auth-runtime-proxy.requires_openai_auth=false")}`);', | ||
| 'console.log(`TUI_HAS_WIRE_OVERRIDE:${args.includes(\'model_providers.codex-multi-auth-runtime-proxy.wire_api="responses"\')}`);', | ||
| 'console.log(`TUI_HAS_STORAGE_OVERRIDE:${args.includes("disable_response_storage=false")}`);', | ||
| 'console.log(`TUI_KEY_IN_ARGS:${args.includes(process.env.OPENAI_API_KEY ?? "__missing__")}`);', | ||
| 'const shimExe = path.join(process.env.CODEX_CLI_PATH ?? "", process.platform === "win32" ? "codex.exe" : "codex");', | ||
| 'const shimResult = spawnSync(shimExe, ["app-server", "--canonical-shim"], { encoding: "utf8", env: process.env });', | ||
| 'console.log(`TUI_SHIM_STATUS:${shimResult.status}`);', | ||
| 'console.log(`TUI_SHIM_STDOUT:${(shimResult.stdout ?? "").trim()}`);', | ||
| "process.exit(0);", | ||
| ]); | ||
| const originalHome = join(fixtureRoot, "codex-home"); | ||
| const markerPath = join(fixtureRoot, "proxy-marker.txt"); | ||
| mkdirSync(originalHome, { recursive: true }); | ||
| writeFileSync( | ||
| join(originalHome, "config.toml"), | ||
| 'model_provider = "openai"\n', | ||
| "utf8", | ||
| ); | ||
|
|
||
| const result = runWrapper(fixtureRoot, [], { | ||
| CODEX_MULTI_AUTH_REAL_CODEX_BIN: fakeBin, | ||
| CODEX_HOME: originalHome, | ||
| ORIGINAL_CODEX_HOME: originalHome, | ||
| CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY: "1", | ||
| CODEX_MULTI_AUTH_APP_ROTATION_IDLE_MS: "200", | ||
| CODEX_MULTI_AUTH_TEST_PROXY_MARKER: markerPath, | ||
| OPENAI_API_KEY: undefined, | ||
| }); | ||
|
|
||
| const output = combinedOutput(result); | ||
| if (result.status !== 0) { | ||
| throw new Error(output); | ||
| } | ||
| expect(output).toContain("TUI_HOME_IS_ORIGINAL:true"); | ||
| expect(output).toContain("TUI_STATE_EXISTED:false"); | ||
| expect(output).toContain("TUI_STATE_PERSISTED:true"); | ||
| expect(output).toContain("TUI_HAS_BASE_URL_OVERRIDE:true"); | ||
| expect(output).toContain("TUI_HAS_ENV_KEY_OVERRIDE:true"); | ||
| expect(output).toContain("TUI_HAS_AUTH_OVERRIDE:true"); | ||
| expect(output).toContain("TUI_HAS_WIRE_OVERRIDE:true"); | ||
| expect(output).toContain("TUI_HAS_STORAGE_OVERRIDE:true"); | ||
| expect(output).toContain("TUI_KEY_IN_ARGS:false"); | ||
| expect(output).toContain("TUI_SHIM_STATUS:0"); | ||
| expect(output).toContain( | ||
| "APP_SERVER_FORWARDED:app-server --canonical-shim", | ||
| ); | ||
| expect(output).toContain( | ||
| "model_providers.codex-multi-auth-runtime-proxy.base_url=", | ||
| ); | ||
| expect(output).toContain( | ||
| 'model_providers.codex-multi-auth-runtime-proxy.env_key="OPENAI_API_KEY"', | ||
| ); | ||
| expect(output).toContain( | ||
| "model_providers.codex-multi-auth-runtime-proxy.requires_openai_auth=false", | ||
| ); | ||
| expect(output).toContain( | ||
| 'model_providers.codex-multi-auth-runtime-proxy.wire_api="responses"', | ||
| ); | ||
| expect(output).toContain("disable_response_storage=false"); | ||
| expect(output).toContain( | ||
| 'model_provider="codex-multi-auth-runtime-proxy"', | ||
| ); | ||
| expect(readFileSync(join(originalHome, "state_5.sqlite"), "utf8")).toBe( | ||
| "first-run-state\n", | ||
| ); | ||
| expect(readFileSync(join(originalHome, "config.toml"), "utf8")).toBe( | ||
| 'model_provider = "openai"\n', | ||
| ); | ||
| await waitForFileText( | ||
| markerPath, | ||
| "start:http://127.0.0.1:4567\nclose\n", | ||
| ); | ||
| }); | ||
|
|
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
solid single-session coverage, but missing a concurrency regression case for canonical-home sharing.
see scripts/codex.js:3497-3528 for the root cause — canonical mode now shares the live codex home across processes with no isolation. as per path instructions, test/** should "demand regression cases that reproduce concurrency bugs" and this new test only exercises one TUI session at a time.
🧰 Tools
🪛 ast-grep (0.44.1)
[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { type SpawnSyncReturns, spawn, spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(detect-child-process-typescript)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@test/codex-bin-wrapper.test.ts` around lines 2763 - 2857, The canonical Codex
home test covers only one interactive session and does not reproduce concurrent
access. Extend the test around “uses the canonical Codex home for interactive
TUI runtime routing” to launch overlapping TUI processes sharing the same
canonical home, coordinate their execution, and assert both complete without
state/config corruption. Preserve the existing routing and persistence
assertions while adding the concurrency regression coverage.
Source: Path instructions
Summary
Why
Runtime rotation created a fresh shadow CODEX_HOME that omitted Codex state SQLite files. With a large sessions directory, every TUI launch rebuilt the thread index and could remain blank for tens of seconds.
Validation
note: greptile review for oc-chatgpt-multi-auth. cite files like
lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.Greptile Summary
this change moves interactive tui rotation from a shadow home to the canonical codex home.
-coverrides.config.toml.Confidence Score: 4/5
the change appears safe to merge, with non-blocking missing vitest coverage for concurrent canonical-home launches.
the provider overrides and token handling are internally consistent, but the test suite does not exercise multiple detached helpers sharing canonical filesystem state.
Files Needing Attention: test/codex-bin-wrapper.test.ts
Important Files Changed
Sequence Diagram
Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "fix(codex): avoid runtime shadow reindex..." | Re-trigger Greptile
Context used (3)