Skip to content

Restore automatic names for new Codex sessions - #213

Merged
webdevcody merged 2 commits into
mainfrom
fix/codex-session-auto-renaming-stuck-at-agent-n
Nov 10, 2026
Merged

webdevcody merged 2 commits into
mainfrom
fix/codex-session-auto-renaming-stuck-at-agent-n

Conversation

@webdevcody

Copy link
Copy Markdown
Contributor

Contents: 🐛 Symptom · 🔍 Cause · ✅ Fix · 📸 Before / After · 🔁 State · 🧪 Proof · ⚠️ Risk · 🔧 Technical overview · 📝 Notes

New Codex sessions can now receive Nebula's first-prompt naming instruction when a Codex background server already exists. This keeps their hooks and tool commands attached to the session that launched them.

🐛 Symptom

New Codex sessions kept names such as agent-1 after receiving a task. Two recent affected local rows still had a pending automatic title and had never recorded a Codex session ID or prompt history, pointing to the hook delivery path before the rename operation.

🔍 Cause

Codex can attach its TUI to an existing shared background server. Nebula supplied the session identity, callback URL and per-boot token to the new TUI process, while hooks ran in the shared server's older environment. With those variables absent, Nebula's hook guard exits before contacting the DAEMON, so the model never receives the naming instruction. A server inherited from another session can instead carry stale identity or authentication.

The installed home hooks still matched their persisted trust hashes when checked in an isolated copy. A live Codex 0.166.0 reproduction with a prestarted private server then confirmed the missing environment, and the same reproduction received all three variables with the fix.

✅ Fix

  • Keep the session's identity —
    • Built-in Codex sessions launch with --no-daemon for both new conversations and resumes.
    • Restarts and worktree relocations use the same launch path.
  • Preserve existing naming rules —
    • The first-prompt instruction and one-shot nebula rename flow stay in place.
    • User titles, title sanitization, hook trust review and other harness defaults keep their existing behavior.
  • Respect configured harnesses —
    • Launch options come from the registry, with an explicit empty-array override for older Codex CLIs.
    • Custom wrappers opt in; speaking Codex's hook dialect alone adds no CLI flags.

📸 Before / After

This changes DAEMON launch behavior, with no TUI layout change. Terminal output from an isolated live Codex probe provides the evidence instead of a PNG. It used a disposable Codex home, a synthetic trusted hook, a private tmux server, a prestarted private Codex server with no Nebula variables, and an invalid test key with the model endpoint directed to localhost. No real user session was resumed or changed.

codex-cli 0.166.0
Shared server socket ready: True

Before: codex --no-alt-screen --yolo <test prompt>
Hook environment present:
  NEBULA_AGENT_ID  false
  NEBULA_API_URL   false
  NEBULA_API_TOKEN false

After: codex --no-daemon --no-alt-screen --yolo <test prompt>
Hook environment present:
  NEBULA_AGENT_ID  true
  NEBULA_API_URL   true
  NEBULA_API_TOKEN true

The probe verified real CLI hook execution and environment inheritance, without a successful model completion. The final model-chosen title is covered by the manual checks below, not claimed as part of this probe.

🔁 State

flowchart TD
    A["TUI creates agent-N with automatic title pending"] --> B["DAEMON launches Codex with session environment"]
    B --> C["Before: TUI reuses shared Codex server"]
    C --> D["Hooks inherit older server environment"]
    D --> E["Hook guard exits; title stays pending"]
    B --> F["After: --no-daemon selects embedded server"]
    F --> G["UserPromptSubmit reaches HOOK RECEIVER"]
    G --> H["Reply injects nebula rename instruction"]
    H --> I["Model runs nebula rename"]
    I --> J["DAEMON persists title and broadcasts row"]
Loading

🧪 Proof

  • Regression first —
    • The new launch regression failed against the original code: first argument was --yolo, expected --no-daemon.
    • It covers cold launch and resume, each with and without an initial task, using default model/effort settings and checking command overrides remain verbatim.
  • Registry and existing pipeline checks —
    • Added coverage for preserving, replacing, serializing and clearing launch options, plus custom-wrapper isolation.
    • Updated existing command-shape checks for model/effort, trailing prompts and worktree relocation; existing hook-response and one-shot rename tests also pass.
  • Rust validation —
    • cargo fmt --all -- --check passed.
    • cargo clippy --workspace --all-targets --locked -- -D warnings passed.
    • cargo test --workspace --locked -- --test-threads=1 passed: 1,932 tests, 8 ignored. All 36 branch-switch tests also passed in isolation with one test thread.
    • cargo build --workspace --locked passed.

⚠️ Risk

Verdict: 🟡 Merge with care — Codex now runs a server per Nebula session and needs a CLI supporting --no-daemon.

Level Why
🔒 Security & production Low No new process-execution or network endpoint; the existing CLI receives an additional registry-controlled argument. Hook trust remains enforced, and session identity/token inheritance becomes local to the correct process. Older Codex versions may reject the flag.
⚡ Performance Medium Per-session embedded Codex servers add startup and memory cost compared with reusing one shared server; no TUI draw or PTY parsing hot path changes.
🧩 Fit with the codebase Low The registry supplies launch options to the existing command builder; overrides remain authoritative and other harness defaults stay empty.

Rollback: Revert these commits to restore shared-server launch behavior and remove the launch-options field. There is no database migration or protocol-version change; titles already saved remain saved, and existing processes need a restart to change behavior.

🔧 Technical overview

  • Creation through rename. crates/nebula-tui/src/event_loop/selection.rs assigns the temporary name and auto_title: true for an unnamed session. crates/nebula-daemon/src/registry/spawn.rs persists that state before launching the PTY and sets NEBULA_AGENT_ID, NEBULA_API_URL and NEBULA_API_TOKEN. The managed UserPromptSubmit curl forwards the HOOK RECEIVER's hookSpecificOutput.additionalContext; the model's nebula rename sends AutoRenameAgent, which conditionally saves the sanitized title and broadcasts it. This flow remains unchanged.
  • The launch fix. crates/nebula-core/src/harness.rs adds a defaulted launch_args list, with ["--no-daemon"] on built-in Codex and a replaceable override. crates/nebula-daemon/src/registry.rs places those arguments before resume subcommands and per-session flags. The command-override early return still bypasses them.
  • Why it was missed. Existing tests exercised argv shapes, injectable HTTP replies and rename persistence separately, without a live Codex shared server started under a different environment. Some CLI configuration overrides can also independently select embedded operation and mask the missing-environment path.
  • Why not bypass hook trust or embed session credentials in hook files. Trust was valid in the inspected configuration, and changing it would not repair process inheritance. Dynamic credentials in home-level hooks would introduce cross-session races and persisted secrets. The fixed launch preserves the existing stable, environment-guarded hook definitions.
  • Configuration. docs/configuration.md documents harnesses.codex.launch_args, the compatibility override, and the missing/misdirected-hook risk if isolation is removed.

📝 Notes

The first default-parallel cargo test --workspace --locked run passed all core/daemon/CLI/e2e tests, but failed two unmodified TUI branch-switch tests (discard_needs_a_second_press and the_cursor_opens_on_the_newest_branch_it_can_switch_to_and_the_filter_narrows). One could not spawn git (ENOENT); another test in the same process temporarily replaces PATH. PATH interference is the suspected cause. All 36 branch-switch tests and the full workspace passed with one test thread. Those unrelated files are unchanged; this was reported to the Captain for separate follow-up.

To test locally:

  1. Build this branch and run its TUI in a fresh isolated instance (make dev SEED=0). Add a test checkout there. Existing live sessions keep their old process environment until relaunched.
  2. Leave an ordinary Codex session/background server running outside that instance. In Nebula, create a Codex session with no explicit name and leave model/effort on default. Review/trust the installed hooks if Codex requests it.
  3. Submit a small request such as “Explain the README.” Expect the temporary agent-N name to become a short descriptive title; session ID and prompt history should also be captured.
  4. Submit another request and confirm the title stays stable. Rename it manually and confirm later prompts preserve that title.
  5. Create a second unnamed Codex session and confirm only its row is renamed. Restart/resume the test session and repeat a prompt; a worktree relocation should also retain the correct session identity.

Prepared using the repository's PR description skill, bug-fix template. Not merged; ready for Cody's review.

🤖 Generated with Codex

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