Skip to content

Fix Codex launch — deliver prompt + drop deprecated/async hook config (CROW-492)#499

Merged
dgershman merged 1 commit into
mainfrom
feature/crow-492-codex-launch-prompt-hooks
Jun 11, 2026
Merged

Fix Codex launch — deliver prompt + drop deprecated/async hook config (CROW-492)#499
dgershman merged 1 commit into
mainfrom
feature/crow-492-codex-launch-prompt-hooks

Conversation

@dgershman

Copy link
Copy Markdown
Collaborator

Closes #492

Summary

  • Bug 1 — Codex launched bare. launch_codex in the workspace skill (and its template copy) now passes \"\$(cat \$prompt_path)\" as Codex's positional argv so the TUI starts with the ticket prompt pre-filled, matching Codex 0.129+ behavior and mirroring launch_cursor. The stale "Codex has no prompt-argv form" log + comment go with it. OpenAICodexAgent.autoLaunchCommand keeps the bare codex\n for in-app re-launches (matches CursorAgent .work shape); the misleading comment is refreshed to point at the skill as the first-launch prompt path.
  • Bug 2 — deprecated TOML key. CodexHookConfigWriter.installGlobalTomlConfig now writes [features].hooks = true (renamed in Codex 0.129; the old codex_hooks alias emits a deprecation warning). Any legacy codex_hooks entry is migrated/removed via a new removeTomlSectionLine helper — idempotent on subsequent runs.
  • Bug 2 — unsupported async hooks. Dropped \"async\": true from PostToolUse and Stop hook entries. Codex 0.139 still silently skips async hooks at execution, which meant CodexSignalSource's state-signal pipeline (card-color updates, auto-respond, completion detection) was silently broken for those two events — not just noisy. All six hooks now run sync and reach Crow.

Test plan

  • arch -arm64 swift test --package-path Packages/CrowCodex — all 31 tests pass, including:
    • installGlobalTomlConfigCreatesFreshFile updated to expect hooks = true and reject codex_hooks.
    • installGlobalTomlConfigPreservesUserSettings updated the same way.
    • New installGlobalTomlConfigMigratesLegacyCodexHooksKey — pre-seeds codex_hooks = true, asserts it is replaced with hooks = true, and asserts idempotency on a second run.
    • New installGlobalConfigDoesNotDeclareAsyncHooks — walks every event in hooks.json and asserts no entry sets "async".
  • Manual: launch a Codex coding session via the workspace skill — TUI opens with the ticket prompt already in the composer, zero startup warnings.
  • Manual: pre-seed ~/.codex/config.toml with [features].codex_hooks = true, restart Crow, confirm migration to hooks = true.
  • Manual: trigger a tool call in a Codex session and watch the card color reflect PreToolUsePostToolUseStop. None of this worked before.

🐦‍⬛ Generated with Claude Code, orchestrated by Crow

@dgershman dgershman requested a review from dhilgaertner as a code owner June 11, 2026 23:31
@dgershman dgershman added the crow:merge Crow auto-merge on green label Jun 11, 2026

@dhilgaertner dhilgaertner 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.

Code & Security Review

Tight, well-scoped bug-fix PR. Both reported bugs are fixed correctly, comments are accurate, and the new behavior mirrors established patterns in the codebase.

Critical Issues

None.

Security Review

Strengths:

  • Bug 1 (prompt argv). launch_codex now passes "\$(cat $prompt_path)" exactly as launch_cursor (setup.sh:822) and launch_claude_code (setup.sh:797) already do. The $(cat …) is wrapped in double quotes and expanded by the target shell at paste time; command-substitution output is not re-parsed for quotes/$/backticks, so an arbitrary prompt body can't break out of the single argv. No new injection surface — it joins a well-trodden path.
  • Template (Resources/crow-workspace-setup.sh.template:721) and skill copy (skills/crow-workspace/setup.sh:844) are kept in sync — no drift introduced.
  • escapeTomlString still guards the notify path; no untrusted data flows into the new TOML helpers (section/key are compile-time literals).

Concerns: None.

Code Quality

  • Bug 2a (deprecated key). removeTomlSectionLine is correct and bounded: sectionEnd defaults to lines.count and is always > start, so the (start+1)..<sectionEnd range is always valid (no crash on an empty/last section). Exact-equality key matching (not prefix) means migrating codex_hooks can't accidentally clobber the new hooks key, and order-independence holds. Migration is idempotent — confirmed by the new test asserting second == toml.
  • Bug 2b (async hooks). Dropping async is the right call given Codex silently drops the field. Note the fix is self-healing for existing installs too: installGlobalConfig overwrites existingHooks[eventName] for all six events, so a stale hooks.json carrying "async": true on PostToolUse/Stop gets rewritten without the flag on next launch.
  • Tests are strong: the new installGlobalConfigDoesNotDeclareAsyncHooks walks every event/entry rather than spot-checking, and the migration test verifies user keys survive (memories = true) plus idempotency.
  • Verified locally: arch -arm64 swift test --package-path Packages/CrowCodex → all 31 tests pass.

Consider (non-blocking, Green):

  • removeTomlSectionLine only scans inside [features] and removes the first match. A theoretical legacy config with a top-level codex_hooks (outside any section) wouldn't be migrated — but Crow has only ever written it under [features], so this is purely hypothetical and fine as-is.

Summary Table

Color Meaning Verdict effect
Red Must fix Request changes
Yellow Should fix Request changes
Green Consider Approve allowed

Recommendation: Approve — driven by [0 Red, 0 Yellow, 1 Green] findings.


🐦‍⬛ Reviewed by Crow via Claude Code

… (CROW-492)

Two distinct bugs in Codex coding sessions surfaced on Codex CLI 0.139.0:

1. Crow launched Codex with a bare `codex` command, leaving the user staring
   at an empty TUI even though the prompt file was written to disk. Codex
   0.129+ accepts the initial prompt as a positional argv that pre-fills the
   composer; `launch_codex` in the workspace skill (and its template copy)
   now mirrors `launch_cursor` and passes `"$(cat $prompt_path)"`. The stale
   "Codex has no prompt-argv form" log + comment go with it. The Swift
   `OpenAICodexAgent.autoLaunchCommand` keeps the bare `codex\n` for in-app
   re-launches (matches `CursorAgent` `.work` shape); only the misleading
   comment is refreshed to point at the skill as the first-launch prompt
   path.

2. `CodexHookConfigWriter` wrote `[features].codex_hooks = true` and marked
   `PostToolUse`/`Stop` hooks with `"async": true`. Codex 0.129 renamed the
   feature flag to `hooks` (the old key still works but emits a deprecation
   warning), and as of 0.139 async hooks are still parsed-but-dropped. The
   two async events were the load-bearing ones for `CodexSignalSource`'s
   state-signal pipeline — card-color updates, auto-respond, completion
   detection were silently broken for Codex sessions, not just noisy. Now:
   `hooks = true` is written under `[features]`, any legacy `codex_hooks`
   entry is migrated/removed via a new `removeTomlSectionLine` helper, and
   `generateHooks` no longer emits the `async` field. All six hook events
   now run sync and reach `CodexSignalSource`.

Tests updated: TOML expectations swapped to `hooks = true`, added an
idempotent migration test that pre-seeds legacy `codex_hooks` and asserts it
is removed, added a test that walks every event in `hooks.json` and asserts
no entry declares `async`.

🐦‍⬛ Generated with Claude Code, orchestrated by Crow

Co-Authored-By: Claude <[email protected]>
Crow-Session: 8B58E578-FAD3-4C2D-8EBF-2E6DE8651170
@dgershman dgershman force-pushed the feature/crow-492-codex-launch-prompt-hooks branch from a5066bd to de817f5 Compare June 11, 2026 23:39
@dgershman dgershman merged commit d9e34c4 into main Jun 11, 2026
2 checks passed
@dgershman dgershman deleted the feature/crow-492-codex-launch-prompt-hooks branch June 11, 2026 23:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

crow:merge Crow auto-merge on green

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codex coding session launches bare (no prompt) and writes deprecated config keys + unsupported async hooks

2 participants