Skip to content

Fix app bind history repair - #460

Merged
ndycode merged 4 commits into
mainfrom
issue-459-app-bind-history-repair
Apr 30, 2026
Merged

ndycode merged 4 commits into
mainfrom
issue-459-app-bind-history-repair

Conversation

@ndycode

@ndycode ndycode commented Apr 30, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • warn app-bind users that Codex Desktop may hide prior history while the runtime proxy provider is active
  • document the unbind and disable workaround plus model_reasoning_effort control
  • repair missing local session_index.jsonl entries from rollout files after forwarded Codex runs
  • silence known upstream Codex rollout-store and rmcp DELETE 404 noise in captured CI forwarded sessions

Verification

  • npm.cmd run lint:scripts
  • npm.cmd run typecheck
  • npm.cmd test -- test/codex-bin-wrapper.test.ts (95 passed)
  • npm.cmd test -- test/codex-manager-rotation-command.test.ts test/app-bind.test.ts test/codex-bin-wrapper.test.ts (146 passed)
  • real installed smoke: codex exec --skip-git-repo-check --cd C:\Users\neil\DevTools\codex-multi-auth-issue-459 -c 'model_reasoning_effort="low"' -o <out> 'Reply exactly: ISSUE459_REAL_PASS_20260501-010008'
  • real smoke result: marker output present, session_index.jsonl entry present for 019ddf55-75e9-73c2-8fba-60d152a76353, no failed to record rollout items, no fail to delete session, no DELETE returned HTTP 404

Risk notes

  • the upstream Codex thread-store issue is not fixed here; the wrapper repairs local history index visibility and suppresses the known false-noise logger modules for captured forwarded sessions
  • CODEX_MULTI_AUTH_CAPTURE_FORWARD_OUTPUT=0 remains the opt-out for terminal-sensitive passthrough runs

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 pr repairs missing session_index.jsonl entries after forwarded codex runs, adds atomic+locked writes to handle concurrent wrapper processes on windows, gates repair to successful exits only, and suppresses known upstream codex_core::session and rmcp DELETE 404 noise in captured/CI runs via both a RUST_LOG ci-only silencer and a post-process line filter. docs and formatAppBindStatus are updated to warn app-bind users about the desktop history visibility limitation and model_reasoning_effort placement.

Confidence Score: 5/5

safe to merge; all findings are p2 style/quality concerns with no correctness impact on the hot path

the three prior p1 issues (concurrent overwrite, repair-before-exit-check, broad RUST_LOG silencing) are all addressed. remaining findings are p2: a misleading function name applied to stdout, a missing user_message type guard for thread naming, and an O(n) scan that grows with session history on windows. none block correctness.

scripts/codex.js — the new output buffering and index repair logic

Important Files Changed

Filename Overview
scripts/codex.js adds session index repair, output buffering/filtering, and CI RUST_LOG silencer; three P2 issues: stderr filter applied to stdout (silent drop risk), thread name picking non-user messages, and O(n) full scan per exit
lib/runtime/app-bind.ts formatAppBindStatus extended with multi-line history/reasoning-effort guidance; configPath is always non-null in this codepath, no issues found
test/codex-bin-wrapper.test.ts three new integration tests for index repair, failed-run guard, and concurrent serialization; covers the main new paths well
test/app-bind.test.ts adds test for resolved configPath in reasoning guidance text; no issues
test/codex-manager-rotation-command.test.ts adds two assertions for the new multi-line formatAppBindStatus output; no issues
docs/troubleshooting.md command references updated from codex-multi-auth to canonical codex auth; new rows for history visibility and model speed; no issues
docs/reference/commands.md added app-bind history-visibility warning and model_reasoning_effort guidance paragraph; no issues

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[forwardToRealCodex] --> B{captureOutput?}
    B -- yes --> C[withCiKnownForwardedCodexLogSilencers\nsets RUST_LOG=codex_core::session=off\nonly if CODEX_CI=1 and no existing RUST_LOG]
    B -- no --> D[spawn with stdio: inherit]
    C --> E[spawn with stdout/stderr piped]
    E --> F[buffer stdout + stderr]
    F --> G{exitCode}
    G -- 0 --> H[filterKnownForwardedCodexStderr stdout\nwrite to process.stdout]
    G -- 0 --> I[filterKnownForwardedCodexStderr stderr\nwrite to process.stderr]
    G -- 0 --> J[repairCodexSessionIndex\nacquire shadow lock\nread existing index\ncollectRolloutFiles scan\nwriteSessionIndexAtomicSync]
    G -- non-0 --> K[flush filtered output\nno index repair]
    J --> L[Return exitCode 0]
    K --> M[Return exitCode non-0 / retry]
Loading

Fix All in Codex

Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
scripts/codex.js:851-855
**stderr filter silently applied to stdout**

`filterKnownForwardedCodexStderr` (a stderr-noise filter) is applied to `stdout` at line 852. any valid codex stdout line that happens to be a two-line match — e.g., a UUID-only second line immediately following a line ending with `thread` — would be silently dropped from the caller's view. the function name gives future maintainers no signal that it's being applied to stdout, so new noise patterns added there will unknowingly affect structured stdout output too. applying the stderr noise filter to stdout is also asymmetric: `stderr` gets a `trim()` guard before writing (line 859), `stdout` does not, so a whitespace-only filtered stdout would still pass the `filteredStdout.length > 0` check and write blank content.

### Issue 2 of 3
scripts/codex.js:3394-3400
**thread name may capture agent reply, not user prompt**

`parseRolloutIndexEntry` picks the first `event_msg` record where `payload.message` is non-empty, with no restriction on `payload.type`. in continuation sessions or sessions where the agent produces an initial greeting before the user's first turn, the indexed `thread_name` will be the agent's message instead of the user's prompt. consider restricting to `record.payload?.type === "user_message"` to stay consistent with how codex desktop labels threads.

### Issue 3 of 3
scripts/codex.js:3475-3492
**O(n) full rollout scan on every successful exit**

`repairCodexSessionIndex` walks the entire `sessions/` tree on every successful `codex exec`. after a user accumulates hundreds or thousands of sessions on windows (where `readdirSync` on a large directory is slower and i/o is not cached as aggressively), the synchronous full-scan adds latency to every non-repair run. the `seen` set prevents duplicate writes but not the initial scan. consider short-circuiting if the rollout file for the current session is already present in the index (e.g., read only the last N lines of the index and skip the scan if the current session ID is already there).

Reviews (3): Last reviewed commit: "Narrow Codex log suppression" | Re-trigger Greptile

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai

coderabbitai Bot commented Apr 30, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

the pr documents behavior warnings and fixes for codex auth rotation bind-app. it updates docs about provider switching potentially hiding Codex Desktop history, implements session index repair after forwarding attempts, filters known error messages from output, and clarifies model configuration remains controlled by Codex settings.

Changes

Cohort / File(s) Summary
Documentation Updates
docs/reference/commands.md, docs/troubleshooting.md
Adds caveats about provider filtering hiding history after app bind and clarifies that model reasoning/speed config remains in Codex config or CLI flags, not surfaced by rotation command.
App Bind Status Formatting
lib/runtime/app-bind.ts
Extends formatAppBindStatus to output multi-line string with additional paragraphs warning about Codex Desktop history visibility after provider switch and documenting model config via model_reasoning_effort.
Session Index Repair & Output Filtering
scripts/codex.js
Introduces repairCodexSessionIndex function to scan rollout files, extract/deduplicate session metadata, and rebuild session_index.jsonl after each forward attempt. Augments child RUST_LOG, forces capture when CODEX_CI=1, and filters known stderr/stdout error sequences before output.
Test Coverage
test/codex-bin-wrapper.test.ts, test/codex-manager-rotation-command.test.ts
Adds new test exercising session index repair with rollout file injection and filtered error output. Extends rotation command test to validate "Codex Desktop may hide history" and model_reasoning_effort messages.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Concerns

  • scripts/codex.js:repairCodexSessionIndex — the function parses JSONL without explicit error handling for malformed records. if a rollout file is truncated or corrupted, parsing failures could silently skip entries or crash the deduplication logic. recommend adding try-catch around JSON.parse and logging skipped entries.
  • RUST_LOG modification — adding module silencers to child process RUST_LOG globally may mask legitimate debug output in CI (CODEX_CI=1). flag whether suppressing "failed to record rollout items" across all runs is the intended behavior or if filtering should be more selective.
  • Missing windows coverage — session path construction (CODExHome/sessions, rollout-*.jsonl) uses forward slashes. verify repairCodexSessionIndex handles path separators correctly on windows (likely needs path.join instead of string concatenation).
  • No concurrency guard — if multiple wrapper instances run simultaneously and both call repairCodexSessionIndex, they could race on session_index.jsonl reads/writes. consider fs locking or a single-writer pattern.
  • Test isolation — test/codex-bin-wrapper.test.ts injects a fake downstream bin. confirm the test properly cleans up fixture files and doesn't leak state between test runs.

Suggested labels

bug

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed the title 'fix app bind history repair' follows conventional commits format (fix type, lowercase imperative, 27 chars) and directly maps to the core changeset: session index repair in scripts/codex.js and app-bind documentation updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed PR description is comprehensive and well-structured, covering summary, verification steps with specific test counts, and risk notes addressing upstream issues and opt-out mechanisms.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 issue-459-app-bind-history-repair
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch issue-459-app-bind-history-repair

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 and usage tips.

Comment thread scripts/codex.js Outdated
Comment thread scripts/codex.js Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/troubleshooting.md`:
- Around line 77-78: The docs use the non-canonical alias "codex-multi-auth" in
troubleshooting entries; update those to the canonical "codex auth" command form
so the recovery steps match docs/reference/commands.md — replace
"codex-multi-auth rotation unbind-app" and "codex-multi-auth rotation disable"
with "codex auth rotation unbind-app" and "codex auth rotation disable" in the
history-recovery row, and change any other occurrences (e.g., examples or
mentions) to the "codex auth" form so README/SECURITY/docs remain consistent
with the primary CLI command family.

In `@lib/runtime/app-bind.ts`:
- Around line 795-808: The note currently hardcodes "~/.codex/config.toml" in
the message returned in lib/runtime/app-bind.ts; instead use the resolved config
path available as status.state.configPath (the same status used around the
return at app-bind.ts:788) when constructing that string, and remove the
hardcoded path. Update the message construction in the function that builds the
returned array (the block that currently includes "~/.codex/config.toml") to
interpolate status.state.configPath. Add a regression test that sets a
non-default Codex home (and a Windows-style path) and asserts the returned note
contains the resolved configPath so the message remains correct across
overridden homes and Windows.

In `@scripts/codex.js`:
- Around line 3426-3471: repairCodexSessionIndex currently reads, merges and
writes session_index.jsonl without acquiring the existing lock or using the
file-rename atomic-write pattern, so concurrent processes can clobber each
other; update repairCodexSessionIndex to acquire the same lock used elsewhere in
this file before reading/writing (use the same lock filename/mechanism already
in this module), perform the merge while holding the lock, and write the new
contents via the module’s atomic-write + rename routine rather than
writeFileSync directly; keep existing error swallowing semantics, ensure
seen/additions logic (collectRolloutFiles, parseRolloutIndexEntry) runs under
the lock, and add a regression test that simulates two concurrent exits writing
the index to verify no entries are lost.
🪄 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

Run ID: 060ad742-0ba5-447c-acb1-79b0ae4a1f35

📥 Commits

Reviewing files that changed from the base of the PR and between 64055fb and b3a305b.

📒 Files selected for processing (6)
  • docs/reference/commands.md
  • docs/troubleshooting.md
  • lib/runtime/app-bind.ts
  • scripts/codex.js
  • test/codex-bin-wrapper.test.ts
  • test/codex-manager-rotation-command.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (3)
lib/**

⚙️ CodeRabbit configuration file

focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails.

Files:

  • lib/runtime/app-bind.ts
docs/**

⚙️ CodeRabbit configuration file

keep README, SECURITY, and docs consistent with actual CLI flags and workflows. whenever behavior changes, require updated upgrade notes and mention new npm scripts.

Files:

  • docs/reference/commands.md
  • docs/troubleshooting.md
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-manager-rotation-command.test.ts
  • test/codex-bin-wrapper.test.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Use the canonical command family `codex auth ...` for primary operations; compatibility aliases `codex multi auth`, `codex multi-auth`, and `codex multiauth` are supported
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Use `codex auth login --device-auth` for remote/headless login flows instead of browser launch
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Use `codex auth login --manual` or `codex auth login --no-browser` to skip browser launch and use manual callback flow (mutually exclusive with `--device-auth`)
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: In non-TTY/manual shells, provide the full redirect URL on stdin when using `codex auth login --manual`, for example: `echo "http://127.0.0.1:1455/auth/callback?code=..." | codex auth login --manual`
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Use `--json` flag for machine-readable output when automating `codex auth` commands (verify-flagged, verify, why-selected, best, forecast, report, usage, budget, models, monitor, integrations, fix, doctor, config explain, debug bundle)
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: For usage analysis, use `--by <model|account|project|outcome|day>` to group summary output; default is `model`
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Use `codex auth budget limit` to set local budget guard limits with `--window <hour|day|week|month>` and optional `--max-requests`, `--max-tokens`, or `--max-cost-usd` constraints
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Use `codex auth bridge token create`, `rotate`, `revoke`, and `list` to manage local bearer tokens for the optional local bridge (tokens are printed only on `create` and `rotate`, persisting SHA-256 hashes plus prefixes and labels)
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Use `codex auth rotation enable` to activate the default-on runtime Responses proxy for live account rotation within Codex sessions; disable with `codex auth rotation disable`
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Set `CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY=0` to disable the proxy for the current process without changing persistent settings
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Set `CODEX_MULTI_AUTH_APP_BIND_INSTALL=0` to skip self-heal bind during package install/update, or `=1` to force it
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Set `CODEX_MULTI_AUTH_APP_LAUNCHER_INSTALL=0` to skip launcher routing during package install/update
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Set `CODEX_MULTI_AUTH_AUTO_UPDATE=0` to disable daily auto-update checks; auto-update startup wait is bounded by `CODEX_MULTI_AUTH_AUTO_UPDATE_STARTUP_BUDGET_MS`
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Set `CODEX_AUTH_NO_BROWSER=1` to suppress browser launch in automation/headless sessions; false-like values such as `0` and `false` do not disable browser launch by themselves
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: In non-TTY sessions (including `CODEX_TUI=1`, `CODEX_DESKTOP=1`, `TERM_PROGRAM=codex`, or `ELECTRON_RUN_AS_NODE=1`), auth flows degrade to deterministic text behavior with `codex auth login` defaulting to add-account mode
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Use dashboard hotkeys: `Up/Down` to move selection, `Enter` to select, `1-9` for quick account switch, `/` to search, `?` for help, `Q` to back/cancel
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: In account details dashboard, use `S` to set account, `R` to refresh/re-login, `E` to enable/disable, `D` to delete, `Q` to back
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Use workflow pack `codex auth check`, `codex auth forecast --live --explain --model gpt-5.3-codex`, and `codex auth report --live --json` for health and planning diagnostics
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:37.690Z
Learning: Use workflow pack `codex auth fix --dry-run`, `codex auth fix --live --model gpt-5.3-codex`, and `codex auth doctor --fix` for repair and recovery procedures
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:46.232Z
Learning: Run `codex-multi-auth doctor --fix` followed by `codex-multi-auth check` and `codex-multi-auth forecast --live` as the initial troubleshooting steps for account pool issues
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:46.232Z
Learning: Use `codex-multi-auth login --device-auth` for remote, SSH, container, or headless shell environments where browser-based OAuth is unavailable
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:46.232Z
Learning: Run `codex-multi-auth doctor --fix` when the entire account pool appears unhealthy or stale, then add at least one fresh account
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:46.232Z
Learning: Ensure `CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY` environment variable is set to `1` for rotation to function; the runtime proxy is loopback-only and default-on
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:46.232Z
Learning: Run `codex-multi-auth list` once in a worktree to trigger migration from legacy path keys to repo-shared storage
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:46.232Z
Learning: Review project storage rules in reference/storage-paths.md to ensure project-scoped storage is properly enabled and not sharing accounts across unrelated repos
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:46.232Z
Learning: When performing a soft reset, remove the account and settings JSON files (`openai-codex-accounts.json`, `openai-codex-flagged-accounts.json`, `settings.json`) from `~/.codex/multi-auth/` before re-logging in
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-04-30T17:04:46.232Z
Learning: When reporting issues, attach the output of `codex-multi-auth report --json`, `codex-multi-auth doctor --json`, version information from `codex --version`, `codex-multi-auth --version`, `npm ls -g codex-multi-auth`, and the full terminal output of the failing command
🔇 Additional comments (3)
test/codex-bin-wrapper.test.ts (1)

719-777: good regression coverage for session repair and noise suppression.

this fixture is deterministic and exercises the important wrapper path: repair of session_index.jsonl, stdout/stderr filtering, and the persisted index payload. good coverage for the reported upstream rollout noise.

test/codex-manager-rotation-command.test.ts (1)

443-445: good coverage for the added app-bind status text.

the new assertions pin the bind/unbind flow to the expanded status output, including the history warning and reasoning-controls note. this keeps the rotation regression tied to the actual user-facing strings.

docs/reference/commands.md (1)

295-297: docs match the new app-bind behavior.

this adds the right recovery note for provider-based history filtering and the model_reasoning_effort reminder, which aligns with the runtime behavior in lib/runtime/app-bind.ts.

Comment thread docs/troubleshooting.md Outdated
Comment thread lib/runtime/app-bind.ts
Comment thread scripts/codex.js
Comment thread scripts/codex.js Outdated
@ndycode
ndycode merged commit cccf16e into main Apr 30, 2026
2 checks passed
@ndycode
ndycode deleted the issue-459-app-bind-history-repair branch April 30, 2026 17:35
@coderabbitai coderabbitai Bot mentioned this pull request May 27, 2026
3 tasks done
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