Skip to content

fix(codex): resolve control socket symlinks before daemon restart - #4018

Merged
steipete merged 3 commits into
steipete:mainfrom
massdo:fix/codex-daemon-socket-symlink
Sep 26, 2026
Merged

steipete merged 3 commits into
steipete:mainfrom
massdo:fix/codex-daemon-socket-symlink

Conversation

@massdo

@massdo massdo commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

After a System Account switch, CodexBar can silently skip the daemon restart added in #4006 because it resolves the reported socket path but not the expected socket path. Codex's Unix app-server publishes that expected path as a symbolic link, so the two URLs compare unequal even though they identify the same socket.

This PR resolves both paths before comparing them and extends the existing promotion tests with real filesystem symlinks. It is a follow-up to #3990 and #4006.

Cause and fix

The current guard compares the resolved destination against the unresolved alias:

Expected alias:    ~/.codex/app-server-control/app-server-control.sock
Actual target:     /private/tmp/codex-daemon-<uid>/<socket-hash>

The mismatch returns nil before the restart command. That branch also produces no recovery note. The fix applies the same symlink resolution and path standardization to the expected URL; PID/process, running-state, backend, and home checks remain in place.

Source references:

Diagnostic history and anonymized evidence

All account labels and local paths below are anonymized.

  1. Original controlled account-switch test: with Codex CLI/daemon 0.157.0, closing and reopening the CLI retained Account A's limits after selecting B. Restarting the daemon loaded B's account state. CODEX_HOME was unset in the checked CodexBar, CLI, and daemon processes, and all resolved to the same home. Published observations.
  2. Follow-up after fix(codex): restart daemon after system account promotion #4006: on CodexBar 0.67.0, Codex CLI/daemon 0.157.1, macOS 26.6.2, Apple Silicon, a real System Account A → B switch changed the live auth file's modification time, but the daemon PID remained unchanged and no recovery note appeared. These are the recorded post-update observations; the timestamp alone is not used as proof of the account stored in the file.
  3. Read-only verification: codex app-server daemon version reported status: running, backend: pid, and CLI/app-server/managed versions 0.157.1. The reported socket path was the alias under the same Codex home. Evaluating the original Foundation URL comparison against that existing link returned false; resolving both URLs returned true. This check did not restart the daemon or read authentication contents.

Regression coverage

The existing promotion test now covers both PID filenames with a plain path, a symlink alias, and the resolved symlink target. It still verifies that the selected credentials are published before exactly one restart and that the command receives the destination CODEX_HOME.

The existing rejection test also runs with symlinked paths: a different home with a different target, an unmanaged server, and a stopped server must not restart. CLI responses and process matching remain injected; the filesystem symlinks are real, with fixture files as targets.

Validation

Check Result
Existing live socket, read-only Foundation comparison Original false; symmetric resolution true
Local harness with real temporary Unix sockets, 8 cases per revision Original: 4 expected symlink failures; fixed: 8/8 pass
Repository promotion regression tests on Xcode 26.6 Original: 4 expected failures; fixed: all 5 tests pass (17 test cases)
Full repository make test, two macOS shards 188/188 groups pass on the first attempt across 1,420 selections; no failures or timeouts
Repository make check and git diff --check Pass locally and on macOS CI; SwiftLint: 0 violations in 2,675 files

Reproducible local socket harness and anonymized before/after output are preserved on a separate proof branch.

Validation workflow and retained logs. The fork-only workflow restores the original implementation for the red test, reinstates the fix for the green test, then runs the repository checks. It is not part of the proposed source changes.

Commands and environment
export CODEXBAR_SUPPRESS_TEST_KEYCHAIN_ACCESS=1
export CODEXBAR_TEST_CODEX_FILE_ISOLATION=1
export CODEXBAR_TEST_SESSION_FILE_ISOLATION=1

# Run against the original implementation, then the corrected implementation.
swift test --jobs 4 --filter CodexAppServerDaemonTests

# CI runs these two shards as separate jobs.
for shard in 0 1; do
  CODEXBAR_TEST_SHARD_INDEX="$shard" CODEXBAR_TEST_SHARD_COUNT=2 \
    CODEXBAR_TEST_GROUP_SIZE=8 CODEXBAR_TEST_SUITE_TIMEOUT=120 \
    CODEXBAR_TEST_RETRY_NON_TIMEOUT_FAILURES=0 make test
done
make check
git diff --check

The local Command Line Tools installation lacks Swift's Testing module, so the package test results come from the Xcode 26.6 GitHub runners. Local make check passed with XCODE_DEFAULT_TOOLCHAIN_OVERRIDE=/Library/Developer/CommandLineTools so SwiftLint could locate SourceKit. Local runtime proof uses Foundation and temporary sockets only.

The automated promotion tests use isolated homes and synthetic credentials with Keychain and real Codex/session file access suppressed. The additional local harness used real temporary Unix sockets, copied restartIfRunning unchanged from each revision, and injected the CLI/process dependencies. A post-fix UI A → B test against a live authenticated daemon has not been performed; the live evidence above establishes the failure, and the automated tests exercise the corrected promotion path.

@clawsweeper

clawsweeper Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P1 Urgent regression or broken agent/channel workflow affecting real users now. merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Sep 26, 2026
@clawsweeper

clawsweeper Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed September 26, 2026, 6:40 AM ET / 10:40 UTC (Revision 2).

ClawSweeper review

What this changes

The branch resolves both Codex control-socket paths before deciding whether to restart the background server after a System Account switch, and adds symlink tests and documentation.

Regression provenance

Possible regression — probable (reviewed change; failure trace). No predecessor PR is attributed.

Merge readiness

⛔ Blocked before merge - 2 items remain

The latest release and current main retain the asymmetric socket comparison, and this PR addresses that gap with focused regression coverage. The earlier review’s proof gap remains: the new before-and-after trace exercises a copied daemon check with an injected CLI, while the contributor reports no after-fix account switch against a live daemon.

Priority: P1
Reviewed head: a13046ba9be23a1e9eec60f73f60d99f17afbf47

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) The focused patch and regression coverage are convincing, while the after-fix trace stops short of the installed account-switch path.
Proof confidence 🦐 gold shrimp (3/6) Needs stronger real behavior proof before merge: The linked terminal trace shows the revised daemon-check method succeeding with real temporary Unix sockets, but the harness injects CLI responses and the restart call. The PR also reports a live pre-fix account-switch failure; it does not yet show an after-fix switch through installed CodexBar restarting a real daemon and the CLI reflecting the selected account. Redact account identifiers, paths, keys, and other private details from that evidence. No stored-data contract changes. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Needs proof Needs stronger real behavior proof before merge: The linked terminal trace shows the revised daemon-check method succeeding with real temporary Unix sockets, but the harness injects CLI responses and the restart call. The PR also reports a live pre-fix account-switch failure; it does not yet show an after-fix switch through installed CodexBar restarting a real daemon and the CLI reflecting the selected account. Redact account identifiers, paths, keys, and other private details from that evidence. No stored-data contract changes. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 8 items Changed guard: The introduced hunk resolves the expected socket alias before comparing it with the already resolved CLI-reported path; the PID, backend, running-state, and scoped restart checks remain.
Production call path: Promotion publishes the selected credentials before calling the daemon restart check. That check invokes the installed Codex CLI for its version probe and restart.
Regression coverage: Promotion and rejection tests use real filesystem symlinks, including a symlinked home and a dangling socket alias, while injecting process detection and CLI responses.
Findings None None.
Security None None.

How this fits together

CodexBar copies the selected managed account’s credentials into the system Codex home. Its daemon check then reads that home’s PID record, asks the Codex CLI about the running server, and may restart the server so it reloads the selected account.

flowchart LR
A[System Account selection] --> B[Publish selected credentials]
B --> C[Check daemon PID and process]
C --> D[Ask Codex CLI for server status]
D --> E[Compare resolved socket paths]
E --> F[Restart matching daemon]
F --> G[CLI uses reloaded account]
Loading

Before merge

  • Add real behavior proof - Needs stronger real behavior proof before merge: The linked terminal trace shows the revised daemon-check method succeeding with real temporary Unix sockets, but the harness injects CLI responses and the restart call. The PR also reports a live pre-fix account-switch failure; it does not yet show an after-fix switch through installed CodexBar restarting a real daemon and the CLI reflecting the selected account. Redact account identifiers, paths, keys, and other private details from that evidence. No stored-data contract changes. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Complete next step (P2) - Add redacted after-fix proof from an installed CodexBar System Account switch showing a real daemon restart and the CLI using the selected account. Updating the PR body should trigger a fresh review; if it does not, ask a maintainer to comment @clawsweeper re-review.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production and test lines production +3/−3, tests +74/−7 The behavior change is small while the added coverage exercises several socket and home shapes.

Technical review

Best possible solution:

Keep the symmetric socket check and focused tests, then demonstrate an after-fix System Account switch through the installed CodexBar and Codex CLI, showing the daemon restart and the CLI reflecting the selected account.

Do we have a high-confidence way to reproduce the issue?

Yes. The released guard compares a resolved socket target with an unresolved alias, and the reporter’s live pre-fix account-switch observations and linked socket harness exercise that mismatch. I did not execute the app in this read-only review.

Is this the best way to solve the issue?

Yes. Resolving both sides of the existing guard is a narrow repair that preserves its other checks; the remaining question is whether the installed app completes the intended restart after the fix.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 3c97aa79eea7.

Labels

Label changes:

No label changes.

Label justifications:

  • P1: A System Account switch can leave the Codex daemon serving the previous account’s limits on the released path.
  • merge-risk: 🚨 availability: The corrected guard can now reach the already approved daemon restart, which may interrupt active Codex work as the product documentation states.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The linked terminal trace shows the revised daemon-check method succeeding with real temporary Unix sockets, but the harness injects CLI responses and the restart call. The PR also reports a live pre-fix account-switch failure; it does not yet show an after-fix switch through installed CodexBar restarting a real daemon and the CLI reflecting the selected account. Redact account identifiers, paths, keys, and other private details from that evidence. No stored-data contract changes. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

What I checked:

Likely related people:

  • unknown: The claimed source-line change could not be verified from bounded local history. (role: source history unknown; confidence: low)
  • Ratul Sarna: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Add redacted after-fix terminal output or a recording of a real System Account switch showing the daemon restart and the CLI reflecting the selected account.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (1 earlier review cycle)
  • reviewed 2026-09-26T09:52:20.492Z sha 89775a6 :: needs real behavior proof before merge. :: none

steipete and others added 2 commits September 26, 2026 03:34
Preserve symmetric socket resolution with an inline PID guard, keeping the
production change neutral in line count. Cover symlinked homes and failed
probes through dangling socket aliases, and document the home/socket boundary.

Refs steipete#3990, steipete#4018.

Co-authored-by: massdo <46751454+massdo@users.noreply.github.com>
@steipete
steipete merged commit 90f6d0a into steipete:main Sep 26, 2026
9 checks passed
@steipete

Copy link
Copy Markdown
Owner

Merged as yours, @massdo, with your commit intact; the maintainer commit on your branch only added the symlinked-home and dangling-link coverage plus the doc and changelog lines. Good catch: the #4006 guard canonicalized the reported socket but compared it against the unresolved expected path, and since Codex publishes the home socket as a symlink into its protected per-user directory, the restart was being skipped silently. Ships in 0.67.1. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. P1 Urgent regression or broken agent/channel workflow affecting real users now. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants