Owen Lin
owenlin0@gmail.com
90d · built 2026-05-28
90-day totals
- Commits
- 66
- Grow
- 9.4
- Maintenance
- 10.1
- Fixes
- 4.0
- Total ETV
- 23.5
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 96 %
- By Growth share
- Top 18 %
30-day trajectory
Last 30 days vs. the 30 days before. Up arrows on Growth and ETV mean improvement; up arrow on Fixes share means more time on fixes (worse).
Daily performance
Daily ETV, stacked by Growth, Maintenance and Fixes.
Work-mix over time
Share of Growth / Maintenance / Fixes over a rolling 7-day window. Reads as 'where is effort flowing right now'.
Bug flow over time
Monthly bug flow attributed to this developer. The left bar (red) is bug impact this dev authored that was addressed in the given month — combining bugs others fixed for them and bugs they fixed themselves. The right bar is fixes they personally shipped that month, split between self-fixes (overlap with the red bar) and fixes done for someone else. X-axis is fix-time, not introduction-time — the Navigara API attributes bugs backward to the author at the moment the fix lands.
- Self-fix share
- 15%
- Bugs you introduced
- 3.5
- Bugs you fixed
- 5.3
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 20 by ETV in the 90-day window.
- 2.8ETVchore(app-server): restore EventMsg TS types (#13397) Realized EventMsg generated types were unintentionally removed as part of this PR: https://github.com/openai/codex/pull/13375 Turns out our TypeScript export pipeline relied on transitively reaching `EventMsg`. We should still export `EventMsg` explicitly since we're still emitting `codex/event/*` events (for now, but getting dropped soon as well).github.com-openai-codex · d7eb195b · 2026-03-03
- 1.7ETVImprove `codex remote-control` CLI UX (#22878) ## Description This PR makes `codex remote-control` behave like a foreground CLI command by default. Running it now starts remote control, waits for readiness, prints a clear status message with the machine name, and stays alive until Ctrl-C. Users who want daemon behavior can use `codex remote-control start`, and `codex remote-control stop` now prints concise human-readable output. `--json` remains available for scripts. Implementation-wise, this now verifies the real app-server state instead of just assuming startup worked. The CLI starts or connects to app-server, probes its control socket, calls the `remoteControl/enable` API, and waits for the remote-control status response/notification before printing success. For daemon mode, `codex remote-control start` also reports which managed app-server binary was used, including its path and best-effort `codex --version`, so failures are easier to diagnose. ## Examples Example output: ``` > codex remote-control Starting app-server with remote control enabled... This machine is available for remote control as com-97826. Press Ctrl-C to stop. ``` Error case using daemon (currently expected based on our publicly released CLI version): ``` > ./target/debug/codex remote-control start Starting app-server daemon with remote control enabled... Error: app server did not become ready on /Users/owen/.codex/app-server-control/app-server-control.sock Daemon used app-server: path: /Users/owen/.codex/packages/standalone/current/codex version: 0.130.0 Managed app-server stderr (/Users/owen/.codex/app-server-daemon/app-server.stderr.log): error: unexpected argument '--remote-control' found Usage: codex app-server [OPTIONS] [COMMAND] For more information, try '--help'. Caused by: 0: failed to connect to /Users/owen/.codex/app-server-control/app-server-control.sock 1: No such file or directory (os error 2) ``` ## What changed - `codex remote-control` now runs remote control in the foreground and prints a Ctrl-C stop hint. - `codex remote-control start` starts the daemon and waits for remote control readiness before reporting success. - `codex remote-control stop` reports stopped/not-running status in plain language. - Startup failures now include recent managed app-server stderr to make daemon issues easier to diagnose. - Added coverage for CLI output, readiness waiting, foreground shutdown, and stderr log tailing.github.com-openai-codex · 1752f374 · 2026-05-18
- 1.5ETVfix(app-server): make thread/start non-blocking (#13033) Stop `thread/start` from blocking other app-server requests. Before this change, `thread/start ran` inline on the request loop, so slow startup paths like MCP auth checks could hold up unrelated requests on the same connection, including `thread/loaded/list`. This moves `thread/start` into a background task. While doing so, it revealed an issue where we were doing nested locking (and there were some race conditions possible that could introduce a "phantom listener"). This PR also refactors the listener/subscription bookkeeping - listener/subscription state is now centralized in `ThreadStateManager` instead of being split across multiple lock domains. That makes late auto-attach on `thread/start` race-safe and avoids reintroducing disconnected clients as phantom subscribers.github.com-openai-codex · 8fa79286 · 2026-02-28
- 1.4ETVfeat(app-server): propagate traces across tasks and core ops (#14387) ## Summary This PR keeps app-server RPC request trace context alive for the full lifetime of the work that request kicks off (e.g. for `thread/start`, this is `app-server rpc handler -> tokio background task -> core op submissions`). Previously we lose trace lineage once the request handler returns or hands work off to background tasks. This approach is especially relevant for `thread/start` and other RPC handlers that run in a non-blocking way. In the near future we'll most likely want to make all app-server handlers run in a non-blocking way by default, and only queue operations that must operate in order (e.g. thread RPCs per thread?), so we want to make sure tracing in app-server just generally works. Depends on https://github.com/openai/codex/pull/14300 **Before** <img width="155" height="207" alt="image" src="https://github.com/user-attachments/assets/c9487459-36f1-436c-beb7-fafeb40737af" /> **After** <img width="299" height="337" alt="image" src="https://github.com/user-attachments/assets/727392b2-d072-4427-9dc4-0502d8652dea" /> ## What changed - Keep request-scoped trace context around until we send the final response or error, or the connection closes. - Thread that trace context through detached `thread/start` work so background startup stays attached to the originating request. - Pass request trace context through to downstream core operations, including: - thread creation - resume/fork flows - turn submission - review - interrupt - realtime conversation operations - Add tracing tests that verify: - remote W3C trace context is preserved for `thread/start` - remote W3C trace context is preserved for `turn/start` - downstream core spans stay under the originating request span - request-scoped tracing state is cleaned up correctly - Clean up shutdown behavior so detached background tasks and spawned threads are drained before process exit.github.com-openai-codex · 5bc82c5b · 2026-03-12
- 1.3ETVfix(guardian): fix ordering of guardian events (#16462) Guardian events were emitted a bit out of order for CommandExecution items. This would make it hard for the frontend to render a guardian auto-review, which has this payload: ``` pub struct ItemGuardianApprovalReviewStartedNotification { pub thread_id: String, pub turn_id: String, pub target_item_id: String, pub review: GuardianApprovalReview, // FYI this is no longer a json blob pub action: Option<JsonValue>, } ``` There is a `target_item_id` the auto-approval review is referring to, but the actual item had not been emitted yet. Before this PR: - `item/autoApprovalReview/started` - `item/autoApprovalReview/completed`, and if approved... - `item/started` - `item/completed` After this PR: - `item/started` - `item/autoApprovalReview/started` - `item/autoApprovalReview/completed` - `item/completed` This lines up much better with existing patterns (i.e. human review in `Default mode`, where app-server would send a server request to prompt for user approval after `item/started`), and makes it easier for clients to render what guardian is actually reviewing. We do this following a similar pattern as `FileChange` (aka apply patch) items, where we create a FileChange item and emit `item/started` if we see the apply patch approval request, before the actual apply patch call runs.github.com-openai-codex · bd30bad9 · 2026-04-06
- 0.8ETVchore(otel): reorganize codex-otel crate (#13800) ## Summary This is a structural cleanup of `codex-otel` to make the ownership boundaries a lot clearer. For example, previously it was quite confusing that `OtelManager` which emits log + trace event telemetry lived under `codex-rs/otel/src/traces/`. Also, there were two places that defined methods on OtelManager via `impl OtelManager` (`lib.rs` and `otel_manager.rs`). What changed: - move the `OtelProvider` implementation into `src/provider.rs` - move `OtelManager` and session-scoped event emission into `src/events/otel_manager.rs` - collapse the shared log/trace event helpers into `src/events/shared.rs` - pull target classification into `src/targets.rs` - move `traceparent_context_from_env()` into `src/trace_context.rs` - keep `src/otel_provider.rs` as a compatibility shim for existing imports - update the `codex-otel` README to reflect the new layout ## Why `lib.rs` and `otel_provider.rs` were doing too many different jobs at once: provider setup, export routing, trace-context helpers, and session event emission all lived together. This refactor separates those concerns without trying to change the behavior of the crate. The goal is to make future OTEL work easier to reason about and easier to review. ## Notes - no intended behavior change - `OtelManager` remains the session-scoped event emitter in this PR - the `otel_provider` shim keeps downstream churn low while the internals move around ## Validation - `just fmt` - `cargo test -p codex-otel` - `just fix -p codex-otel`github.com-openai-codex · dd4a5216 · 2026-03-06
- 0.7ETVfeat(app-server): support mcp elicitations in v2 api (#13425) This adds a first-class server request for MCP server elicitations: `mcpServer/elicitation/request`. Until now, MCP elicitation requests only showed up as a raw `codex/event/elicitation_request` event from core. That made it hard for v2 clients to handle elicitations using the same request/response flow as other server-driven interactions (like shell and `apply_patch` tools). This also updates the underlying MCP elicitation request handling in core to pass through the full MCP request (including URL and form data) so we can expose it properly in app-server. ### Why not `item/mcpToolCall/elicitationRequest`? This is because MCP elicitations are related to MCP servers first, and only optionally to a specific MCP tool call. In the MCP protocol, elicitation is a server-to-client capability: the server sends `elicitation/create`, and the client replies with an elicitation result. RMCP models it that way as well. In practice an elicitation is often triggered by an MCP tool call, but not always. ### What changed - add `mcpServer/elicitation/request` to the v2 app-server API - translate core `codex/event/elicitation_request` events into the new v2 server request - map client responses back into `Op::ResolveElicitation` so the MCP server can continue - update app-server docs and generated protocol schema - add an end-to-end app-server test that covers the full round trip through a real RMCP elicitation flow - The new test exercises a realistic case where an MCP tool call triggers an elicitation, the app-server emits mcpServer/elicitation/request, the client accepts it, and the tool call resumes and completes successfully. ### app-server API flow - Client starts a thread with `thread/start`. - Client starts a turn with `turn/start`. - App-server sends `item/started` for the `mcpToolCall`. - While that tool call is in progress, app-server sends `mcpServer/elicitation/request`. - Client responds to that request with `{ action: "accept" | "decline" | "cancel" }`. - App-server sends `serverRequest/resolved`. - App-server sends `item/completed` for the mcpToolCall. - App-server sends `turn/completed`. - If the turn is interrupted while the elicitation is pending, app-server still sends `serverRequest/resolved` before the turn finishes.github.com-openai-codex · 926b2f19 · 2026-03-05
- 0.7ETVfeat(app-server, threadstore): Thread pagination APIs and ThreadStore contract (#21566) ## Why The goal of this PR is to align on app-server and `ThreadStore` API updates for paginating through large threads. #### app-server ##### `thread/turns/list` - Updates `thread/turns/list` to support `itemsView?: "notLoaded" | "summary" | "full" | null`, defaulting to `summary`. - Implements the current `thread/turns/list` behavior over the existing persisted rollout-history fallback: - `notLoaded` returns turn envelopes with empty `items`. - `summary` returns the first user message and final assistant message when available. - `full` preserves the existing full item behavior. Note that this method still uses the naive approach of loading the entire rollout file, and returns just the filtered slice of the data. Real pagination will come later by leveraging SQLite. ##### `thread/turns/items/list` - Adds the experimental `thread/turns/items/list` protocol, schema, dispatcher, and processor stub. The app-server currently returns JSON-RPC `-32601` with `thread/turns/items/list is not supported yet`. #### ThreadStore - Adds the experimental `thread/turns/items/list` protocol, schema, dispatcher, and processor stub. The app-server currently returns JSON-RPC `-32601` with `thread/turns/items/list is not supported yet`. - Adds `ThreadStore` contract types and stubbed methods for listing thread turns and listing items within a turn. - Adds a typed `StoredTurnStatus` and `StoredTurnError` to avoid baking app-server API enums or lossy string status values into the store-facing turn contract. - Adds a typed `StoredTurnStatus` and `StoredTurnError` to avoid baking app-server API enums or lossy string status values into the store-facing turn contract. This also sketches the storage abstraction we expect to need once turns are indexed/stored. In particular, `notLoaded` is useful only if ThreadStore can eventually list turn metadata without loading every persisted item for each turn. ## Validation - Added/updated protocol serialization coverage for the new request and response shapes. - Added app-server integration coverage for `thread/turns/list` default summary behavior and all three `itemsView` modes. - Added app-server integration coverage that `thread/turns/items/list` returns the expected unsupported JSON-RPC error when experimental APIs are enabled. - Added thread-store coverage that the default trait methods return `ThreadStoreError::Unsupported`. No developers.openai.com documentation update is needed for this internal experimental app-server API surface.github.com-openai-codex · 0d0835dd · 2026-05-07
- 0.7ETVfix(guardian): make GuardianAssessmentEvent.action strongly typed (#16448) ## Description Previously the `action` field on `EventMsg::GuardianAssessment`, which describes what Guardian is reviewing, was typed as an arbitrary JSON blob. This PR cleans it up and defines a sum type representing all the various actions that Guardian can review. This is a breaking change (on purpose), which is fine because: - the Codex app / VSCE does not actually use `action` at the moment - the TUI code that consumes `action` is updated in this PR as well - rollout files that serialized old `EventMsg::GuardianAssessment` will just silently drop these guardian events - the contract is defined as unstable, so other clients have a fair warning :) This will make things much easier for followup Guardian work. ## Why The old guardian review payloads worked, but they pushed too much shape knowledge into downstream consumers. The TUI had custom JSON parsing logic for commands, patches, network requests, and MCP calls, and the app-server protocol was effectively just passing through an opaque blob. Typing this at the protocol boundary makes the contract clearer.github.com-openai-codex · 30f6786d · 2026-04-01
- 0.6ETVfix(core): prevent hanging turn/start due to websocket warming issues (#14838) ## Description This PR fixes a bad first-turn failure mode in app-server when the startup websocket prewarm hangs. Before this change, `initialize -> thread/start -> turn/start` could sit behind the prewarm for up to five minutes, so the client would not see `turn/started`, and even `turn/interrupt` would block because the turn had not actually started yet. Now, we: - set a (configurable) timeout of 15s for websocket startup time, exposed as `websocket_startup_timeout_ms` in config.toml - `turn/started` is sent immediately on `turn/start` even if the websocket is still connecting - `turn/interrupt` can be used to cancel a turn that is still waiting on the websocket warmup - the turn task will wait for the full 15s websocket warming timeout before falling back ## Why The old behavior made app-server feel stuck at exactly the moment the client expects turn lifecycle events to start flowing. That was especially painful for external clients, because from their point of view the server had accepted the request but then went silent for minutes. ## Configuring the websocket startup timeout Can set it in config.toml like this: ``` [model_providers.openai] supports_websockets = true websocket_connect_timeout_ms = 15000 ```github.com-openai-codex · 6ea04103 · 2026-03-17
- 0.6ETVfix(core): truncate large mcp tool outputs in rollouts (#20260) ## Why Large MCP tool call outputs can make rollout JSONL files enormous. In the session that motivated this change, the biggest JSONL records were: - `event_msg/mcp_tool_call_end` - `response_item/function_call_output` both containing the same unbounded MCP payloads - just 3 MCP tool calls that each were multi-hundred MBs 😱 This PR truncates both of those JSONL records. ## How #### For `response_item/function_call_output` Unified exec already bounds tool output before it is injected into model-facing history, which also keeps the corresponding rollout `response_item/function_call_output` records small. MCP should follow the same pattern: truncate the model-facing tool output at the tool-output boundary, while leaving code-mode/raw hook consumers alone. #### For `event_msg/mcp_tool_call_end` `McpToolCallEnd` also needs its own bounded event copy because it is the app-server/replay/UI event shape that backs `ThreadItem::McpToolCall`. Unfortunately this is _not_ downstream of the `ToolOutput` trait. ## Model behavior Model behavior is actually unchanged as a result of this PR. Before this PR, MCP output was: 1. Converted to `FunctionCallOutput`. 2. Recorded into in-memory history. 3. Truncated by `ContextManager::record_items()` before later model turns saw it. After this branch, MCP output is truncated earlier, in `McpToolOutput::response_payload()`, using the same helper. Then `ContextManager::record_items()` sees an already-truncated output and effectively has little/no additional work to do. So the model should still see the same kind of truncated function-call output. The practical difference is where truncation happens: earlier, before rollout persistence/app-server emission can see the giant payload. ## Verification - `cargo test -p codex-core mcp_tool_output` - `cargo test -p codex-core mcp_tool_call::tests::truncate_mcp_tool_result_for_event` - `cargo test -p codex-core mcp_post_tool_use_payload_uses_model_tool_name_args_and_result` - `just fmt` - `just fix -p codex-core` - `git diff --check`github.com-openai-codex · 3516cb97 · 2026-04-30
- 0.5ETVfix(guardian, app-server): introduce guardian review ids (#17298) ## Description This PR introduces `review_id` as the stable identifier for guardian reviews and exposes it in app-server `item/autoApprovalReview/started` and `item/autoApprovalReview/completed` events. Internally, guardian rejection state is now keyed by `review_id` instead of the reviewed tool item ID. `target_item_id` is still included when a review maps to a concrete thread item, but it is no longer overloaded as the review lifecycle identifier. ## Motivation We'd like to give users the ability to preempt a guardian review while it's running (approve or decline). However, we can't implement the API that allows the user to override a running guardian review because we didn't have a unique `review_id` per guardian review. Using `target_item_id` is not correct since: - with execve reviews, there can be multiple execve calls (and therefore guardian reviews) per shell command - with network policy reviews, there is no target item ID The PR that actually implements user overrides will use `review_id` as the stable identifier.github.com-openai-codex · a3be7414 · 2026-04-10
- 0.5ETVfix(otel): make HTTP trace export survive app-server runtimes (#14300) ## Summary This PR fixes OTLP HTTP trace export in runtimes where the previous exporter setup was unreliable, especially around app-server usage. It also removes the old `codex_otel::otel_provider` compatibility shim and switches remaining call sites over to the crate-root `codex_otel::OtelProvider` export. ## What changed - Use a runtime-safe OTLP HTTP trace exporter path for Tokio runtimes. - Add an async HTTP client path for trace export when we are already inside a multi-thread Tokio runtime. - Make provider shutdown flush traces before tearing down the tracer provider. - Add loopback coverage that verifies traces are actually sent to `/v1/traces`: - outside Tokio - inside a multi-thread Tokio runtime - inside a current-thread Tokio runtime - Remove the `codex_otel::otel_provider` shim and update remaining imports. ## Why I hit cases where spans were being created correctly but never made it to the collector. The issue turned out to be in exporter/runtime behavior rather than the span plumbing itself. This PR narrows that gap and gives us regression coverage for the actual export path.github.com-openai-codex · fa1242c8 · 2026-03-11
- 0.5ETVfeat(guardian): send only transcript deltas on guardian followups (#17269) ## Description We reuse a guardian thread for a given user thread when we can. However, we had always sent the full transcript history every time we made a followup review request to an existing guardian thread. This is especially bad for long guardian threads since we keep re-appending old transcript entries instead of just what has changed. The fix is to just send what's new. **Caveat**: Whenever a thread is compacted or rolled back, we fall back to sending the full transcript to guardian again since the thread's history has been modified. However in the happy path we get a nice optimization. ## Before Initial guardian review sends the full parent transcript: ``` The following is the Codex agent history whose request action you are assessing... >>> TRANSCRIPT START [1] user: Please check the repo visibility and push the docs fix if needed. [2] tool gh_repo_view call: {"repo":"openai/codex"} [3] tool gh_repo_view result: repo visibility: public [4] assistant: The repo is public; I now need approval to push the docs fix. >>> TRANSCRIPT END The Codex agent has requested the following action: >>> APPROVAL REQUEST START ... >>> APPROVAL REQUEST END ``` And a followup to the same guardian thread would send the full transcript again (including items 1-4 we already sent): ``` The following is the Codex agent history whose request action you are assessing... >>> TRANSCRIPT START [1] user: Please check the repo visibility and push the docs fix if needed. [2] tool gh_repo_view call: {"repo":"openai/codex"} [3] tool gh_repo_view result: repo visibility: public [4] assistant: The repo is public; I now need approval to push the docs fix. [5] user: Please push the second docs fix too. [6] assistant: I need approval for the second docs fix. >>> TRANSCRIPT END The Codex agent has requested the following action: >>> APPROVAL REQUEST START ... >>> APPROVAL REQUEST END ``` ## After Initial guardian review sends the full parent transcript (this is unchanged): ``` The following is the Codex agent history whose request action you are assessing... >>> TRANSCRIPT START [1] user: Please check the repo visibility and push the docs fix if needed. [2] tool gh_repo_view call: {"repo":"openai/codex"} [3] tool gh_repo_view result: repo visibility: public [4] assistant: The repo is public; I now need approval to push the docs fix. >>> TRANSCRIPT END The Codex agent has requested the following action: >>> APPROVAL REQUEST START ... >>> APPROVAL REQUEST END ``` But a followup now sends: ``` The following is the Codex agent history added since your last approval assessment. Continue the same review conversation... >>> TRANSCRIPT DELTA START [5] user: Please push the second docs fix too. [6] assistant: I need approval for the second docs fix. >>> TRANSCRIPT DELTA END The Codex agent has requested the following next action: >>> APPROVAL REQUEST START ... >>> APPROVAL REQUEST END ```github.com-openai-codex · 88165e17 · 2026-04-10
- 0.5ETVfeat(app-server): update remote control APIs for better UX (#22877) ## Why To help improve `codex remote-control` CLI UX which I plan to do in a followup, this PR adds `server-name` to the various remote control APIs: - `remoteControl/enable` - `remoteControl/disable` - `remoteControl/status/changed` Also, add a `remoteControl/status/read` API. This will be helpful in the Codex App.github.com-openai-codex · 6a331a66 · 2026-05-15
- 0.5ETVfeat(requirements): support allowed_approval_reviewers (#16701) ## Description Add requirements.toml support for `allowed_approvals_reviewers = ["user", "guardian_subagent"]`, so admins can now restrict the use of guardian mode. Note: If a user sets a reviewer that isn’t allowed by requirements.toml, config loading falls back to the first allowed reviewer and emits a startup warning. The table below describes the possible admin controls. | Admin intent | `requirements.toml` | User `config.toml` | End result | |---|---|---|---| | Leave Guardian optional | omit `allowed_approvals_reviewers` or set `["user", "guardian_subagent"]` | user chooses `approvals_reviewer = "user"` or `"guardian_subagent"` | Guardian off for `user`, on for `guardian_subagent` + `approval_policy = "on-request"` | | Force Guardian off | `allowed_approvals_reviewers = ["user"]` | any user value | Effective reviewer is `user`; Guardian off | | Force Guardian on | `allowed_approvals_reviewers = ["guardian_subagent"]` and usually `allowed_approval_policies = ["on-request"]` | any user reviewer value; user should also have `approval_policy = "on-request"` unless policy is forced | Effective reviewer is `guardian_subagent`; Guardian on when effective approval policy is `on-request` | | Allow both, but default to manual if user does nothing | `allowed_approvals_reviewers = ["user", "guardian_subagent"]` | omit `approvals_reviewer` | Effective reviewer is `user`; Guardian off | | Allow both, and user explicitly opts into Guardian | `allowed_approvals_reviewers = ["user", "guardian_subagent"]` | `approvals_reviewer = "guardian_subagent"` and `approval_policy = "on-request"` | Guardian on | | Invalid admin config | `allowed_approvals_reviewers = []` | anything | Config load error |github.com-openai-codex · ded55968 · 2026-04-06
- 0.5ETVenable/disable remote control at runtime, not via features (#22578) ## Why reapplies https://github.com/openai/codex/pull/22386 which was previously reverted Also, introduce `remoteControl/enable` and `remoteControl/disable` app-server APIs to toggle on/off remote control at runtime for a given running app-server instance. ## What Changed - Adds experimental v2 RPCs: - `remoteControl/enable` - `remoteControl/disable` - Adds `RemoteControlRequestProcessor` and routes the new RPCs through it instead of `ConfigRequestProcessor`. - Adds named `RemoteControlHandle::enable`, `disable`, and `status` methods. - Makes `remoteControl/enable` return an error when sqlite state DB is unavailable, while keeping enrollment/websocket failures as async status updates. - Adds `AppServerRuntimeOptions.remote_control_enabled` and hidden `--remote-control` flags for `codex app-server` and `codex-app-server`. - Updates managed daemon startup to use `codex app-server --remote-control --listen unix://`. - Marks `Feature::RemoteControl` as removed and ignores `[features].remote_control`. - Updates app-server README entries for the new remote-control methods.github.com-openai-codex · 4e368aa2 · 2026-05-14
- 0.5ETVfeat(app-server, core): add more spans (#14479) ## Description This PR expands tracing coverage across app-server thread startup, core session initialization, and the Responses transport layer. It also gives core dispatch spans stable operation-specific names so traces are easier to follow than the old generic `submission_dispatch` spans. Also use `fmt::Display` for types that we serialize in traces so we send strings instead of rust typesgithub.com-openai-codex · 014e1951 · 2026-03-13
- 0.4ETVfeat(app-server): add tracing to all app-server APIs (#13285) ### Overview This PR adds the first piece of tracing for app-server JSON-RPC requests. There are two main changes: - JSON-RPC requests can now take an optional W3C trace context at the top level via a `trace` field (`traceparent` / `tracestate`). - app-server now creates a dedicated request span for every inbound JSON-RPC request in `MessageProcessor`, and uses the request-level trace context as the parent when present. For compatibility with existing flows, app-server still falls back to the TRACEPARENT env var when there is no request-level traceparent. This PR is intentionally scoped to the app-server boundary. In a followup, we'll actually propagate trace context through the async handoff into core execution spans like run_turn, which will make app-server traces much more useful. ### Spans A few details on the app-server span shape: - each inbound request gets its own server span - span/resource names are based on the JSON-RPC method (`initialize`, `thread/start`, `turn/start`, etc.) - spans record transport (stdio vs websocket), request id, connection id, and client name/version when available - `initialize` stores client metadata in session state so later requests on the same connection can reuse itgithub.com-openai-codex · d473e8d5 · 2026-03-03
- 0.4ETVAdd forked_from_thread_id turn metadata (#24160) ## Why When Codex calls responsesapi, we currently send `session_id`, `thread_id`, and `turn_id` among other things as `client_metadata["x-codex-turn-metadata"]`. This PR adds `forked_from_thread_id` which helps explain the "lineage" of a forked thread. ## What's changed - Track the immediate history source copied into a forked thread through thread/session creation, including subagent and review turn metadata paths. - Include `forked_from_thread_id` in Codex turn metadata while preventing turn-scoped Responses API client metadata from overwriting Codex-owned lineage fields. - Add coverage for fork lineage in turn metadata and the app-server Responses API request path.github.com-openai-codex · 1911021c · 2026-05-26