Skip to content

checkpoint: into wallentx/termux-target from release/0.138.0 @ 2ae55f9a4229 - #196

Merged
wallentx merged 18 commits into
wallentx/termux-targetfrom
checkpoint/wallentx_termux-target_from_release_0.138.0_2ae55f9a4229
Jun 8, 2026
Merged

checkpoint: into wallentx/termux-target from release/0.138.0 @ 2ae55f9a4229#196
wallentx merged 18 commits into
wallentx/termux-targetfrom
checkpoint/wallentx_termux-target_from_release_0.138.0_2ae55f9a4229

Conversation

@unemployabot

@unemployabot unemployabot Bot commented Jun 8, 2026

Copy link
Copy Markdown

Termux release checkpoint

  • Source branch: release/0.138.0
  • Source hash: 2ae55f9a4229b9a5d592625c0f05eb1b28a0583b
  • Destination branch: wallentx/termux-target
  • Remaining first-parent commits on source: 0

This PR carries release-train conflict fixes and follow-up changes back into the reusable Termux patch branch.

Release-only workflow files and metadata under .github were restored to the destination branch versions before opening this PR.

apanasenko-oai and others added 18 commits June 5, 2026 22:54
…penai#26741)

## Why

A remote-control WebSocket handshake can receive a generic HTTP 404 when
an intermediary routes the request without preserving the WebSocket
upgrade. Treating every 404 as proof that the remote app server is gone
clears valid enrollment and causes repeated re-enrollment, new
environment and server IDs, Habitat churn, and noisy `/server/enroll`
traffic.

## What Changed

- Clear enrollment only when a 404 JSON response explicitly contains
`{"detail":"Remote app server not found"}`.
- Preserve enrollment for empty, plain-text, malformed, or otherwise
unrecognized 404 responses, return the transport error, and retry with
the existing reconnect backoff.
- Log the status, correlation headers (`request-id` or
`x-oai-request-id`, plus `cf-ray`), and bounded/redacted response body
for unrecognized 404s.
- Cover both explicit missing-server re-enrollment and generic 404
enrollment preservation/reconnect behavior.

## Verification

`just test -p codex-app-server-transport` passes all 114 tests on the
rebased branch, including the targeted explicit and generic WebSocket
404 scenarios.

Related issue: N/A
## Why

`BUILDBUDDY_API_KEY` now lives in the `bazel` GitHub Actions environment
as an environment secret. Jobs that need BuildBuddy credentials must opt
into that environment so `${{ secrets.BUILDBUDDY_API_KEY }}` resolves
from the protected environment secret instead of relying on an unscoped
repository/organization secret.

This follows the same environment-secret migration pattern as openai#26466.

## What Changed

- Attach each workflow job that reads `BUILDBUDDY_API_KEY` to the
`bazel` environment.
- Set `deployment: false` on those job-level environment blocks.

`deployment: false` lets the job enter the `bazel` environment to access
its environment secrets without creating GitHub deployment records for
these CI jobs. That keeps the environment as a secret/access-control
boundary without making ordinary Bazel CI runs look like deploys.

## Validation

- Parsed the modified workflow YAML files with Ruby's YAML parser.
- Checked the modified workflow files for trailing whitespace.
## Why

This PR fixes approval sandbox semantics in the unified-exec path. The
zsh-fork runtime exposed the bug because the shell can do meaningful
work before any intercepted child `execv(2)` exists: redirections,
builtins, globbing, and pipeline setup all happen in the launch process.
If the model requested `sandbox_permissions=require_escalated`, or an
exec-policy `allow` rule explicitly bypassed the sandbox, that approved
sandbox decision needs to be preserved for the launch path and for
intercepted execs that use the same approval machinery.

The behavior is not only about zsh fork. The production changes are in
shared approval/escalation code, so they also affect non-zsh-fork
intercepted exec paths that go through the same sandbox decision logic.
The narrow intent is to preserve the approval decision while still
keeping denied-read profiles and bounded additional-permission requests
sandboxed.

## Production Changes

- `codex-rs/core/src/tools/runtimes/unified_exec.rs`: derives a
`launch_sandbox_permissions` value from the requested sandbox
permissions and the runtime filesystem policy, then uses that value for
managed-network/env setup and launch sandbox selection. This keeps full
approval or policy-bypass decisions visible to the first unified-exec
attempt, while still preventing a full sandbox override from discarding
denied-read restrictions. Direct unified exec keeps the same decision
surface; the important difference is that zsh-fork launch setup no
longer accidentally loses the approved parent sandbox decision.

- `codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs`: makes
intercepted-exec escalation selection explicit for the three sandbox
permission modes. `UseDefault` only escalates when an exec-policy
decision allows sandbox bypass, `RequireEscalated` escalates when
unsandboxed execution is allowed, and `WithAdditionalPermissions`
escalates through the bounded additional-permissions path instead of
being treated as a full unsandboxed override. Unsandboxed intercepted
execs now also rebuild the environment as `RequireEscalated`, which
strips managed-network proxy variables consistently with other
unsandboxed execution.

## Test Coverage

Most of the PR is tests. The new coverage verifies:

- unified exec preserves parent approval and exec-policy sandbox
decisions for zsh-fork launch selection;
- bounded `with_additional_permissions` remains sandboxed and
permission-profile based;
- denied-read profiles are not weakened by parent approval;
- explicit prompt rules still prompt for intercepted execs after the
parent command is approved;
- unsandboxed intercepted execs strip managed-network env vars.

No documentation update is needed; this is an internal approval/sandbox
correctness fix.





---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/24981).
* openai#24982
* __->__ openai#24981
## Why

Interactive `codex resume` and `codex fork` expose both a session ID
positional and an initial prompt positional. With `--last`, Clap still
assigns the first positional to the session ID, so a command such as
`codex fork --last "/compact focus on auth"` either fails parsing or
attempts to look up the prompt as a session ID instead of sending it to
the latest session.

This makes it impossible to select the latest session and immediately
provide a follow-up prompt, even though `codex exec resume --last`
already supports that workflow.

<img width="1746" height="1024" alt="CleanShot 2026-06-06 at 17 00
47@2x"
src="https://github.com/user-attachments/assets/86885c07-a23c-48ee-b0ee-47f2484f6eb7"
/>

## What Changed

- Reinterpret the first positional as the initial prompt when
interactive `resume --last` or `fork --last` is used and no explicit
second prompt was parsed.
- Preserve the existing `resume SESSION_ID PROMPT` and `fork SESSION_ID
PROMPT` behavior.
- Add parser-level regression coverage for latest-session and
explicit-session prompt forms.

## How to Test

1. Start an interactive session, exit it, then run `codex resume --last
"continue from the latest session"`.
2. Confirm Codex resumes the latest session and submits the supplied
prompt instead of treating it as a session ID.
3. Run `codex fork --last "take a different approach"`.
4. Confirm Codex forks the latest session and submits the supplied
prompt.
5. Also verify `codex resume SESSION_ID "continue here"` and `codex fork
SESSION_ID "branch here"` still target the explicit session and submit
the prompt.

Targeted tests:
- `just test -p codex-cli` (267 passed)
## Why

MCP startup failures from spawned subagents were rendered as global
notifications, so a child thread's failure could pollute the visible
parent transcript. Routing the notification to the child exposed two
related replay problems: session refresh could discard the buffered
event, and a newly created child `ChatWidget` did not know the expected
MCP server set, which could leave its startup spinner running after
every server had settled.

MCP startup diagnostics should remain visible in the thread that owns
the startup without affecting other transcripts. The protocol also needs
to support a future app-scoped MCP lifecycle where startup is not owned
by any thread.

## Reported Behavior

The [originating Slack
report](https://openai.slack.com/archives/C08JZTV654K/p1780604538859939)
called out that using subagents could turn MCP startup failures into a
wall of yellow CLI warnings because repeated failures were not
deduplicated. The intended behavior is for those diagnostics to remain
visible once in the thread that owns the startup, without polluting the
parent transcript.

## What Changed

- add nullable `threadId` ownership to `mcpServer/startupStatus/updated`
- populate it from the app-server conversation ID for the current
thread-scoped lifecycle and regenerate the protocol schema and
TypeScript artifacts
- treat a missing or null `threadId` as app-scoped without injecting it
into the active chat transcript
- route and buffer thread-owned MCP startup notifications by thread in
the TUI
- preserve buffered MCP startup events across child session refresh
- seed expected MCP servers before replaying a thread snapshot so
startup reaches its terminal state
- suppress an identical repeated failure warning for the same server
within one startup round

The owning thread still renders the detailed failure and final `MCP
startup incomplete (...)` summary.

## How to Test

1. Configure an optional MCP server named `smoke` that exits during
initialization.
2. Launch the TUI with multi-agent support enabled.
3. Confirm the main thread's own startup failure renders one detailed
`smoke` warning and one incomplete-startup summary.
4. Spawn exactly one subagent.
5. Confirm the parent transcript does not receive the subagent's MCP
startup failure.
6. Switch to the subagent thread and confirm it contains exactly one
detailed `smoke` failure and one incomplete-startup summary.
7. Confirm the subagent's MCP startup spinner disappears and the thread
remains usable.
8. Switch between the parent and subagent and confirm the warnings
neither move nor duplicate.

Targeted tests:

- `just test -p codex-app-server-protocol`
- `just test -p codex-app-server
thread_start_emits_mcp_server_status_updated_notifications`
- `just test -p codex-tui mcp_startup`

The parent/child behavior and spinner completion were also exercised
manually in tmux. `just argument-comment-lint` was attempted but blocked
by an unrelated local Bazel LLVM empty-glob failure; touched Rust
callsites were inspected manually.
## What

- Consume plaintext `output` from standalone search while retaining
optional `encrypted_output` parsing.
- Expose `web.run` to code mode and return search output to nested
JavaScript calls.
- Cover direct and code-mode standalone search paths with integration
tests.

## Why

`/v1/alpha/search` now returns plaintext output, which code mode needs
to consume standalone search results.

## Test plan

- `just test -p codex-api`
- `just test -p codex-web-search-extension`
- `just test -p codex-core code_mode_can_call_standalone_web_search`
- `just test -p codex-app-server
standalone_web_search_round_trips_output`
## Why

Multi-agent v2 treats agents as durable logical agents, not just live
entries in `ThreadManager`. After the reload-on-delivery change, a v2
agent can be addressed even if its thread is not currently loaded.

This PR adds the next layer: loaded v2 subagents can be paged out of
`ThreadManager` when the session has too many resident agents. That
keeps residency separate from logical identity and prepares the stack
for making v2 concurrency count active execution instead of existing
agents.

## What Changed

- Add an `AgentControl`-scoped LRU for resident v2 subagents.
- Reserve residency before spawning or reloading a v2 subagent.
- If resident capacity is full, unload the least-recently-used idle v2
subagent from `ThreadManager`.
- Keep `ThreadManager` as a primitive loaded-thread store; it does not
own the LRU policy.
- Keep unloaded agents registered and durable so they can be reloaded by
the delivery path.
- Preserve the existing v2 cap semantics by using the derived non-root
v2 cap for residency.

Eviction is intentionally conservative. A thread is unloadable only when
it is a v2 subagent, has completed or errored, has no active turn, and
has no pending mailbox work. Before removal, the rollout is materialized
and flushed.

## Assumptions And Non-Goals

- PR openai#26623 provides the reload-on-delivery path for unloaded v2 agents.
- `ThreadManager` membership means loaded/resident, not logical agent
existence.
- `AgentRegistry` remains the logical identity/metadata source for v2
agents that may be unloaded.
- `list_agents` remains a recent/resident view for now.
- This does not change active execution concurrency; that is the next
PR.
- This does not change `close_agent` semantics.
- This does not change or remove `resume_agent`.
- This does not add a new residency config knob.

## Stack

1. V2 durable lookup and reload on delivery (openai#26623) - reload unloaded
v2 agents before delivering follow-up/input.
2. V2 residency LRU (this PR) - unload idle resident v2 agents from
`ThreadManager` when resident capacity is full.
3. V2 active-execution concurrency - count running non-root v2 turns
instead of logical agents.
4. V2 close/interrupt semantics - make v2 close interrupt the current
turn without deleting durable identity.
5. V2 resume cleanup - remove the manual resume surface for v2 while
keeping internal reload support.

## Validation

- Added focused coverage for the residency LRU eviction path.
- Local clippy/check/tests were not run; CI will cover them.
## Summary
- ignore RUSTSEC-2026-0173 in cargo-deny and cargo-audit config
- document that proc-macro-error2 is pulled in transitively via
i18n-embed-fl/age/codex-secrets
- leave the ignore temporary until codex-secrets moves off age or age
drops i18n-embed-fl

## Validation
- just fmt
- cargo deny check --hide-inclusion-graph
## Why

Multi-Agent V2 concurrency should count active non-root turns, not
resident or durable agent threads. The limit is intentionally best
effort: admission checks are synchronous, but concurrent successful
checks may overshoot slightly.

## What changed

- Keep one root-derived execution limit on the shared `AgentControl`.
- Count active V2 subagent turns with an RAII guard owned by
`RunningTask`.
- Check capacity before spawning or starting an idle agent, including
direct app-server `turn/start` submissions.
- Preserve queued delivery for agents that are already running.
- Exempt automatic idle continuations so `/goal` work is not dropped
when capacity is temporarily full.
- Keep root and V1 turns outside this limiter.

## Test coverage

- `execution_guards_count_active_v2_subagent_turns`
- `execution_guards_ignore_root_and_v1_turns`
- `v2_nested_spawn_checks_shared_active_execution_capacity`
## Why

`close_agent` is the wrong model-facing name for the v2 operation after
the residency changes. V2 agents remain reusable by task name, and
residency/unloading owns capacity management; the exposed tool should
describe the action it actually performs: interrupt the target agent's
current turn without making the agent unavailable for future messages or
follow-up tasks.

## What changed

- Rename the multi-agent v2 tool from `close_agent` to
`interrupt_agent`.
- Keep the v1 `close_agent` surface unchanged.
- Update the v2 handler to send `Op::Interrupt`, keep interrupted agents
registered, and reject root/self targets with interrupt-specific errors.
- Route interrupt delivery through the existing dead-thread cleanup path
so stale resident entries do not keep consuming capacity.
- Update tool planning and handler tests for the new v2 surface and
semantics.

## Verification

Added focused coverage in:

- `core/src/tools/spec_plan_tests.rs`
- `core/src/tools/handlers/multi_agents_tests.rs`
…nt/wallentx_termux-target_from_release_0.138.0_2ae55f9a4229
@unemployabot
unemployabot Bot requested a review from wallentx June 8, 2026 17:42
@unemployabot unemployabot Bot added checkpoint Checkpoint merge termux-release Termux release automation labels Jun 8, 2026
@wallentx
wallentx merged commit 8c9fb9e into wallentx/termux-target Jun 8, 2026
1 check passed
@wallentx
wallentx deleted the checkpoint/wallentx_termux-target_from_release_0.138.0_2ae55f9a4229 branch June 8, 2026 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

checkpoint Checkpoint merge termux-release Termux release automation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants