Skip to content

refactor: hide shell override for zsh fork unified exec#24980

Merged
bolinfest merged 1 commit into
mainfrom
pr24980
Jun 1, 2026
Merged

refactor: hide shell override for zsh fork unified exec#24980
bolinfest merged 1 commit into
mainfrom
pr24980

Conversation

@bolinfest
Copy link
Copy Markdown
Collaborator

@bolinfest bolinfest commented May 28, 2026

Why

When unified exec is configured to launch through the zsh fork, local commands should not let the model override the shell binary with the shell parameter. The configured zsh fork is the mechanism that makes execv(2) interception reliable, so exposing shell for local zsh-fork execution would create a confusing API surface and undermine the composition.

Remote environments are different: zsh-fork interception is local-only, so remote unified-exec calls must keep direct unified-exec behavior and still expose shell when a remote environment can be selected.

What Changed

  • Taught the exec_command schema builder to omit the shell parameter when requested.
  • Hid shell from the unified-exec tool schema only when zsh-fork unified exec applies to all selectable environments.
  • Kept shell visible when any remote environment can be targeted, because those calls run through direct unified exec.
  • Made unified exec choose the effective shell mode per selected environment: local environments keep zsh-fork mode, remote environments use direct mode.
  • Left direct unified-exec behavior unchanged, including support for model-specified shells there.

Verification

  • Added schema coverage showing exec_command can hide shell.
  • Added planner coverage showing zsh-fork unified exec hides shell for local-only execution while direct unified exec still exposes it.
  • Added planner coverage showing shell remains visible when a remote environment is available.
  • Added handler coverage showing remote environments use direct unified-exec shell mode instead of zsh-fork mode.
  • Ran the focused codex-core shell-parameter and zsh-fork tests.

Stack created with Sapling. Best reviewed with ReviewStack.

}
}

fn unified_exec_should_include_shell_parameter(turn_context: &TurnContext) -> bool {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think this still leaves shell as a silent no-op in mixed-env sessions: once any remote env exists we expose it, but local execs still ignore it under zsh-for k

Should we reject shell for local targets instead of silently dropping it?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

[codex] Agreed. This is now changed on #24980: local zsh-fork unified exec rejects an explicit shell instead of silently ignoring it, with an error telling the model to omit shell or target a remote environment. Remote targets still map to direct unified exec via shell_mode_for_environment(), so their shell parameter remains supported.

@bolinfest bolinfest force-pushed the pr24980 branch 2 times, most recently from 9bc8a51 to 79a708f Compare June 1, 2026 18:33
bolinfest added a commit that referenced this pull request Jun 1, 2026
## Why

`shell_zsh_fork` and unified exec need to remain independently
controllable for enterprise rollouts, but we also need a third mode that
composes them. That composed mode is intended to preserve unified exec
command lifecycle support while letting the zsh fork provide more
accurate `execv(2)` interception.

Enabling `unified_exec_zsh_fork` by itself is intentionally not
sufficient. It is a composition gate, not a dependency-enabling
shortcut:

- `unified_exec` selects the PTY-backed unified exec tool.
- `shell_zsh_fork` opts into the zsh fork backend.
- `unified_exec_zsh_fork` only allows those two already-enabled modes to
be composed so local zsh unified exec commands can launch through the
zsh fork.

This separation is deliberate. Enterprises and staged rollouts must be
able to enable or disable unified exec and zsh-fork independently. If
`unified_exec_zsh_fork` implied either dependency, then enabling one
under-development composition flag would silently activate a shell
backend that the configured feature set left disabled.

This PR introduces only the configuration and planning gate for that
composition. Existing `shell_zsh_fork` behavior continues to use the
standalone shell tool unless the new composition feature is explicitly
enabled alongside both dependencies.

## What Changed

- Added the under-development feature flag `unified_exec_zsh_fork`.
- Added `UnifiedExecFeatureMode` so the three input feature flags
collapse into `Disabled`, `Direct`, or `ZshFork` mode before tool
planning.
- Updated tool selection so zsh-fork composition requires
`unified_exec`, `shell_zsh_fork`, and `unified_exec_zsh_fork`.
- Kept the existing standalone zsh-fork shell tool behavior when only
`shell_zsh_fork` is enabled.
- Updated config schema output for the new feature flag.

## Verification

- Added feature and tool-config coverage for the new gate.
- Added planner coverage proving `shell_zsh_fork` remains standalone
until composition is explicitly enabled.
- Ran focused tests for `codex-features`, `codex-tools`, and the
affected `codex-core` planner case.





---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/24979).
* #24982
* #24981
* #24980
* __->__ #24979
Base automatically changed from pr24979 to main June 1, 2026 20:01
@bolinfest bolinfest enabled auto-merge (squash) June 1, 2026 20:06
@bolinfest bolinfest merged commit feb9edd into main Jun 1, 2026
47 of 62 checks passed
@bolinfest bolinfest deleted the pr24980 branch June 1, 2026 20:22
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 1, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants