From 33b9ecbcf200fe791f802fdccdb55a7f9f210fba Mon Sep 17 00:00:00 2001 From: Yvette Carlisle Date: Mon, 8 Jun 2026 16:11:48 +0800 Subject: [PATCH] {"schema":"decodex/commit/1","summary":"Persist upstream Radar review artifacts","authority":"manual"} --- .../github/bundles/openai-codex-pr-26449.json | 87 ++++++++ .../github/bundles/openai-codex-pr-26450.json | 106 ++++++++++ .../github/bundles/openai-codex-pr-26552.json | 192 ++++++++++++++++++ .../github/bundles/openai-codex-pr-26631.json | 90 ++++++++ .../github/impact/openai-codex-pr-26449.json | 44 ++++ .../github/impact/openai-codex-pr-26450.json | 46 +++++ .../github/impact/openai-codex-pr-26552.json | 46 +++++ .../github/impact/openai-codex-pr-26631.json | 46 +++++ .../review-queue/openai-codex-latest.json | 120 ++++++----- .../reviews/openai-codex-pr-26449.review.json | 57 ++++++ .../reviews/openai-codex-pr-26450.review.json | 68 +++++++ .../reviews/openai-codex-pr-26552.review.json | 80 ++++++++ .../reviews/openai-codex-pr-26631.review.json | 61 ++++++ .../openai-codex-pr-26450.json | 54 +++++ .../openai-codex-pr-26552.json | 54 +++++ .../openai-codex-pr-26631.json | 53 +++++ 16 files changed, 1155 insertions(+), 49 deletions(-) create mode 100644 artifacts/github/bundles/openai-codex-pr-26449.json create mode 100644 artifacts/github/bundles/openai-codex-pr-26450.json create mode 100644 artifacts/github/bundles/openai-codex-pr-26552.json create mode 100644 artifacts/github/bundles/openai-codex-pr-26631.json create mode 100644 artifacts/github/impact/openai-codex-pr-26449.json create mode 100644 artifacts/github/impact/openai-codex-pr-26450.json create mode 100644 artifacts/github/impact/openai-codex-pr-26552.json create mode 100644 artifacts/github/impact/openai-codex-pr-26631.json create mode 100644 artifacts/github/reviews/openai-codex-pr-26449.review.json create mode 100644 artifacts/github/reviews/openai-codex-pr-26450.review.json create mode 100644 artifacts/github/reviews/openai-codex-pr-26552.review.json create mode 100644 artifacts/github/reviews/openai-codex-pr-26631.review.json create mode 100644 artifacts/github/social-candidates/openai-codex-pr-26450.json create mode 100644 artifacts/github/social-candidates/openai-codex-pr-26552.json create mode 100644 artifacts/github/social-candidates/openai-codex-pr-26631.json diff --git a/artifacts/github/bundles/openai-codex-pr-26449.json b/artifacts/github/bundles/openai-codex-pr-26449.json new file mode 100644 index 000000000..e7c112739 --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-26449.json @@ -0,0 +1,87 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "hefuc-oai", + "committed_at": "2026-06-04T19:16:00Z", + "message": "feat(remote-control): add pairing status transport", + "sha": "acf4f7a893034a677d89703bc6236842b923ee23", + "url": "https://github.com/openai/codex/commit/acf4f7a893034a677d89703bc6236842b923ee23" + } + ], + "default_branch": "main", + "docs_refs": [], + "examples_refs": [], + "extracted_flags": [ + "URL", + "--manifest-path", + "--all", + "--check", + "REMOTE_CONTROL_PAIRING_TIMEOUT", + "HTTP", + "JSONRPCM", + "POST", + "ABCD", + "TEST_REMOTE_CONTROL_SERVER_TOKEN", + "TEST_REFRESHED_REMOTE_CONTROL_SERVER_TOKEN" + ], + "files": [ + { + "additions": 17, + "deletions": 0, + "patch_excerpt": "@@ -62,6 +62,23 @@ pub struct RemoteControlPairingStartResponse {\n pub expires_at: i64,\n }\n \n+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]\n+#[serde(rename_all = \"camelCase\")]\n+#[ts(export_to = \"v2/\")]\n+pub struct RemoteControlPairingStatusParams {\n+ #[ts(optional = nullable)]\n+ pub pairing_code: Option,\n+ #[ts(optional = nullable)]\n+ pub manual_pairing_code: Option,\n+}\n+\n+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]\n+#[serde(rename_all = \"camelCase\")]\n+#[ts(export_to = \"v2/\")]\n+pub struct RemoteControlPairingStatusResponse {\n+ pub claimed: bool,\n+}\n+\n #[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema, TS)]\n #[serde(rename_all = \"camelCase\")]\n #[ts(export_to = \"v2/\")]", + "path": "codex-rs/app-server-protocol/src/protocol/v2/remote_control.rs", + "status": "modified" + }, + { + "additions": 66, + "deletions": 0, + "patch_excerpt": "@@ -3,11 +3,14 @@ use super::pairing_unavailable_error;\n use super::protocol::EnrollRemoteServerRequest;\n use super::protocol::EnrollRemoteServerResponse;\n use super::protocol::RefreshRemoteServerRequest;\n+use super::protocol::RemoteControlPairingStatusRequest;\n+use super::protocol::RemoteControlPairingStatusResponse as BackendRemoteControlPairingStatusResponse;\n use super::protocol::RemoteControlTarget;\n use super::protocol::StartRemoteControlPairingRequest;\n use super::protocol::StartRemoteControlPairingResponse;\n use axum::http::HeaderMap;\n use codex_app_server_protocol::RemoteControlPairingStartResponse;\n+use codex_app_server_protocol::RemoteControlPairingStatusResponse;\n use codex_login::default_client::build_reqwest_client;\n use codex_state::RemoteControlEnrollmentRecord;\n use codex_state::StateRuntime;\n@@ -136,6 +139,69 @@ impl RemoteControlEnrollment {\n })\n }\n \n+ p...", + "path": "codex-rs/app-server-transport/src/transport/remote_control/enroll.rs", + "status": "modified" + }, + { + "additions": 114, + "deletions": 0, + "patch_excerpt": "@@ -18,6 +18,7 @@ use crate::transport::remote_control::websocket::RemoteControlStatusPublisher;\n use crate::transport::remote_control::websocket::RemoteControlWebsocket;\n \n pub use self::protocol::ClientId;\n+use self::protocol::RemoteControlPairingStatusCode;\n use self::protocol::ServerEvent;\n use self::protocol::StreamId;\n use self::protocol::normalize_remote_control_url;\n@@ -31,6 +32,8 @@ use codex_app_server_protocol::RemoteControlClientsRevokeResponse;\n use codex_app_server_protocol::RemoteControlConnectionStatus;\n use codex_app_server_protocol::RemoteControlPairingStartParams;\n use codex_app_server_protocol::RemoteControlPairingStartResponse;\n+use codex_app_server_protocol::RemoteControlPairingStatusParams;\n+use codex_app_server_protocol::RemoteControlPairingStatusResponse;\n use codex_app_server_protocol::RemoteControlStatusChangedNotification;\n use codex_login::AuthManager;\n use c...", + "path": "codex-rs/app-server-transport/src/transport/remote_control/mod.rs", + "status": "modified" + }, + { + "additions": 51, + "deletions": 0, + "patch_excerpt": "@@ -13,6 +13,7 @@ pub(super) struct RemoteControlTarget {\n pub(super) enroll_url: String,\n pub(super) refresh_url: String,\n pub(super) pair_url: String,\n+ pub(super) pair_status_url: String,\n }\n \n #[derive(Debug, Serialize)]\n@@ -52,6 +53,40 @@ pub(super) struct StartRemoteControlPairingResponse {\n pub(super) expires_at: String,\n }\n \n+#[derive(Debug, Serialize)]\n+pub(super) struct RemoteControlPairingStatusRequest {\n+ #[serde(skip_serializing_if = \"Option::is_none\")]\n+ pub(super) pairing_code: Option,\n+ #[serde(skip_serializing_if = \"Option::is_none\")]\n+ pub(super) manual_pairing_code: Option,\n+}\n+\n+#[derive(Clone)]\n+pub(super) enum RemoteControlPairingStatusCode {\n+ PairingCode(String),\n+ ManualPairingCode(String),\n+}\n+\n+impl From for RemoteControlPairingStatusRequest {\n+ fn from(code: RemoteControlPa...", + "path": "codex-rs/app-server-transport/src/transport/remote_control/protocol.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -21,6 +21,7 @@ use codex_app_server_protocol::ConfigWarningNotification;\n use codex_app_server_protocol::JSONRPCMessage;\n use codex_app_server_protocol::RemoteControlConnectionStatus;\n use codex_app_server_protocol::RemoteControlPairingStartParams;\n+use codex_app_server_protocol::RemoteControlPairingStatusParams;\n use codex_app_server_protocol::RemoteControlStatusChangedNotification;\n use codex_app_server_protocol::ServerNotification;\n use codex_config::types::AuthCredentialsStoreMode;", + "path": "codex-rs/app-server-transport/src/transport/remote_control/tests.rs", + "status": "modified" + }, + { + "additions": 216, + "deletions": 0, + "patch_excerpt": "@@ -1,6 +1,8 @@\n+use super::super::protocol::RemoteControlPairingStatusRequest;\n use super::super::protocol::StartRemoteControlPairingRequest;\n use super::*;\n use pretty_assertions::assert_eq;\n+use std::io;\n \n fn remote_control_enrollment(\n remote_control_url: &str,\n@@ -66,6 +68,36 @@ async fn pairing_response_error(body: serde_json::Value) -> String {\n err.to_string()\n }\n \n+async fn pairing_status_error(status: &'static str, body: &'static str) -> (io::Error, String) {\n+ let listener = TcpListener::bind(\"127.0.0.1:0\")\n+ .await\n+ .expect(\"listener should bind\");\n+ let remote_control_url = remote_control_url_for_listener(&listener);\n+ let expected_status_url = normalize_remote_control_url(&remote_control_url)\n+ .expect(\"target should normalize\")\n+ .pair_status_url;\n+ let server_task = tokio::spawn(async move {\n+ let status_request = a...", + "path": "codex-rs/app-server-transport/src/transport/remote_control/tests/pairing_tests.rs", + "status": "modified" + } + ], + "linked_issues": [], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "## What\n\nAdds transport support for checking remote-control pairing status against the backend.\n\n- Adds the normalized `server/pair/status` backend URL.\n- Adds backend request/response structs for exactly one lookup key: `pairing_code` or `manual_pairing_code`, returning `{ claimed }`.\n- Adds `RemoteControlEnrollment::pairing_status` and `RemoteControlHandle::pairing_status`.\n- Preserves auth refresh/retry behavior and backend error mapping.\n- Adds transport coverage for pending, claimed, manual-code payloads, token refresh, mapped backend errors, malformed responses, and URL normalization.\n\n## Why\n\nDesktop needs a host-authenticated way to poll whether a QR or manual pairing code has been claimed.\n\nRelated backend change: https://github.com/openai/openai/pull/990244\n\n## Verification\n\n- `cargo test --manifest-path app-server-transport/Cargo.toml remote_control::tests::pairing_tests`\n- `cargo fmt --all --check`\n- `git diff --check`", + "labels": [], + "merged_at": "2026-06-05T17:07:25Z", + "number": 26449, + "state": "merged", + "title": "feat(remote-control): add pairing status transport", + "url": "https://github.com/openai/codex/pull/26449" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/bundles/openai-codex-pr-26450.json b/artifacts/github/bundles/openai-codex-pr-26450.json new file mode 100644 index 000000000..c99bce6a1 --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-26450.json @@ -0,0 +1,106 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "hefuc-oai", + "committed_at": "2026-06-04T19:20:55Z", + "message": "feat(app-server): add remote control pairing status RPC", + "sha": "7d3240b290464a9102fd68f4438c1bd7ecb2431d", + "url": "https://github.com/openai/codex/commit/7d3240b290464a9102fd68f4438c1bd7ecb2431d" + } + ], + "default_branch": "main", + "docs_refs": [ + "codex-rs/app-server/README.md" + ], + "examples_refs": [], + "extracted_flags": [ + "RPC", + "README", + "JSON", + "--manifest-path", + "--all", + "--check", + "JSONRPCE", + "INTERNAL_ERROR_CODE", + "INVALID_REQUEST_ERROR_CODE", + "ABCD", + "JSONRPCR", + "DEFAULT_TIMEOUT", + "POST", + "HTTP" + ], + "files": [ + { + "additions": 3, + "deletions": 0, + "patch_excerpt": "@@ -2963,11 +2963,14 @@ permissionProfile?: string | null};\n \n let client_request_json = fs::read_to_string(output_dir.join(\"ClientRequest.json\"))?;\n assert!(client_request_json.contains(\"remoteControl/pairing/start\"));\n+ assert!(client_request_json.contains(\"remoteControl/pairing/status\"));\n assert!(client_request_json.contains(\"remoteControl/client/list\"));\n assert!(client_request_json.contains(\"remoteControl/client/revoke\"));\n for schema in [\n \"RemoteControlPairingStartParams.json\",\n \"RemoteControlPairingStartResponse.json\",\n+ \"RemoteControlPairingStatusParams.json\",\n+ \"RemoteControlPairingStatusResponse.json\",\n \"RemoteControlClientsListParams.json\",\n \"RemoteControlClientsListResponse.json\",\n \"RemoteControlClientsRevokeParams.json\",", + "path": "codex-rs/app-server-protocol/src/export.rs", + "status": "modified" + }, + { + "additions": 19, + "deletions": 0, + "patch_excerpt": "@@ -849,6 +849,12 @@ client_request_definitions! {\n serialization: global(\"remote-control-pairing\"),\n response: v2::RemoteControlPairingStartResponse,\n },\n+ #[experimental(\"remoteControl/pairing/status\")]\n+ RemoteControlPairingStatus => \"remoteControl/pairing/status\" {\n+ params: v2::RemoteControlPairingStatusParams,\n+ serialization: global_shared_read(\"remote-control-pairing\"),\n+ response: v2::RemoteControlPairingStatusResponse,\n+ },\n #[experimental(\"remoteControl/client/list\")]\n RemoteControlClientsList => \"remoteControl/client/list\" {\n params: v2::RemoteControlClientsListParams,\n@@ -2014,6 +2020,19 @@ mod tests {\n \"remote-control-pairing\"\n ))\n );\n+ let remote_control_pairing_status = ClientRequest::RemoteControlPairingStatus {\n+ request_id: request_id(),\n+ ...", + "path": "codex-rs/app-server-protocol/src/protocol/common.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -211,6 +211,7 @@ Example with notification opt-out:\n - `remoteControl/disable` — experimental; disable remote control for the current app-server process and return the current remote-control status snapshot. This does not revoke already enrolled controller devices.\n - `remoteControl/status/read` — experimental; read the current remote-control status snapshot. `status` is one of `disabled`, `connecting`, `connected`, or `errored`; `serverName` is the local machine name used by this app-server process; `environmentId` is a string when the app-server has a current enrollment and `null` when that enrollment is cleared, invalidated, or remote control is disabled.\n - `remoteControl/pairing/start` — experimental; start a short-lived remote-control pairing artifact for the current app-server process. Pass `manualCode: true` to also request a manual pairing code. Returns `pairingCode`, `manual...", + "path": "codex-rs/app-server/README.md", + "status": "modified" + }, + { + "additions": 5, + "deletions": 0, + "patch_excerpt": "@@ -921,6 +921,11 @@ impl MessageProcessor {\n .pairing_start(params, app_server_client_name.as_deref())\n .await\n .map(|response| Some(response.into())),\n+ ClientRequest::RemoteControlPairingStatus { params, .. } => self\n+ .remote_control_processor\n+ .pairing_status(params)\n+ .await\n+ .map(|response| Some(response.into())),\n ClientRequest::RemoteControlClientsList { params, .. } => self\n .remote_control_processor\n .clients_list(params)", + "path": "codex-rs/app-server/src/message_processor.rs", + "status": "modified" + }, + { + "additions": 27, + "deletions": 0, + "patch_excerpt": "@@ -11,6 +11,8 @@ use codex_app_server_protocol::RemoteControlDisableResponse;\n use codex_app_server_protocol::RemoteControlEnableResponse;\n use codex_app_server_protocol::RemoteControlPairingStartParams;\n use codex_app_server_protocol::RemoteControlPairingStartResponse;\n+use codex_app_server_protocol::RemoteControlPairingStatusParams;\n+use codex_app_server_protocol::RemoteControlPairingStatusResponse;\n use codex_app_server_protocol::RemoteControlStatusReadResponse;\n use std::io;\n \n@@ -60,6 +62,17 @@ impl RemoteControlRequestProcessor {\n .map_err(map_pairing_start_error)\n }\n \n+ pub(crate) async fn pairing_status(\n+ &self,\n+ params: RemoteControlPairingStatusParams,\n+ ) -> Result {\n+ validate_pairing_status_params(¶ms)?;\n+ self.handle()?\n+ .pairing_status(params)\n+ ...", + "path": "codex-rs/app-server/src/request_processors/remote_control_processor.rs", + "status": "modified" + }, + { + "additions": 53, + "deletions": 0, + "patch_excerpt": "@@ -23,6 +23,59 @@ async fn pairing_start_returns_internal_error_when_remote_control_is_unavailable\n );\n }\n \n+#[tokio::test]\n+async fn pairing_status_returns_internal_error_when_remote_control_is_unavailable() {\n+ let err = RemoteControlRequestProcessor::new(/*remote_control_handle*/ None)\n+ .pairing_status(RemoteControlPairingStatusParams {\n+ pairing_code: Some(\"pairing-code\".to_string()),\n+ manual_pairing_code: None,\n+ })\n+ .await\n+ .expect_err(\"missing remote control should fail pairing status\");\n+\n+ assert_eq!(\n+ err,\n+ JSONRPCErrorError {\n+ code: INTERNAL_ERROR_CODE,\n+ data: None,\n+ message: \"remote control is unavailable for this app-server\".to_string(),\n+ }\n+ );\n+}\n+\n+#[test]\n+fn pairing_status_rejects_missing_pairing_codes() {\n+ assert_eq!(\n+ validate_pai...", + "path": "codex-rs/app-server/src/request_processors/remote_control_processor/remote_control_processor_tests.rs", + "status": "modified" + }, + { + "additions": 11, + "deletions": 0, + "patch_excerpt": "@@ -70,6 +70,7 @@ use codex_app_server_protocol::ProcessWriteStdinParams;\n use codex_app_server_protocol::RemoteControlClientsListParams;\n use codex_app_server_protocol::RemoteControlClientsRevokeParams;\n use codex_app_server_protocol::RemoteControlPairingStartParams;\n+use codex_app_server_protocol::RemoteControlPairingStatusParams;\n use codex_app_server_protocol::RequestId;\n use codex_app_server_protocol::ReviewStartParams;\n use codex_app_server_protocol::SendAddCreditsNudgeEmailParams;\n@@ -656,6 +657,16 @@ impl TestAppServer {\n .await\n }\n \n+ /// Send a `remoteControl/pairing/status` JSON-RPC request.\n+ pub async fn send_remote_control_pairing_status_request(\n+ &mut self,\n+ params: RemoteControlPairingStatusParams,\n+ ) -> anyhow::Result {\n+ let params = Some(serde_json::to_value(params)?);\n+ self.send_request(\"remoteControl/pairi...", + "path": "codex-rs/app-server/tests/common/test_app_server.rs", + "status": "modified" + }, + { + "additions": 74, + "deletions": 0, + "patch_excerpt": "@@ -19,12 +19,15 @@ use codex_app_server_protocol::RemoteControlDisableResponse;\n use codex_app_server_protocol::RemoteControlEnableResponse;\n use codex_app_server_protocol::RemoteControlPairingStartParams;\n use codex_app_server_protocol::RemoteControlPairingStartResponse;\n+use codex_app_server_protocol::RemoteControlPairingStatusParams;\n+use codex_app_server_protocol::RemoteControlPairingStatusResponse;\n use codex_app_server_protocol::RemoteControlStatusReadResponse;\n use codex_app_server_protocol::RequestId;\n use codex_config::types::AuthCredentialsStoreMode;\n use pretty_assertions::assert_eq;\n use tempfile::TempDir;\n use tokio::io::AsyncBufReadExt;\n+use tokio::io::AsyncReadExt;\n use tokio::io::AsyncWriteExt;\n use tokio::io::BufReader;\n use tokio::net::TcpListener;\n@@ -190,6 +193,44 @@ async fn remote_control_pairing_start_returns_pairing_artifacts() -> Result<()>\n expires_...", + "path": "codex-rs/app-server/tests/suite/v2/remote_control.rs", + "status": "modified" + } + ], + "linked_issues": [], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "## What\n\nExposes the pairing status transport as experimental app-server v2 RPC `remoteControl/pairing/status`.\n\n- Adds request/response protocol types for exactly one lookup key: `pairingCode` or `manualPairingCode`, returning `{ claimed }`.\n- Registers the RPC with `global_shared_read(\"remote-control-pairing\")`.\n- Wires the method through `MessageProcessor` and `RemoteControlRequestProcessor`.\n- Validates missing/conflicting pairing-code params as invalid requests.\n- Documents the RPC in `app-server/README.md`.\n- Adds processor, protocol export, and JSON-RPC integration coverage for both code paths.\n\n## Why\n\nThis is the app-server surface the desktop app can poll while the QR/manual pairing modal is active.\n\nDepends on https://github.com/openai/codex/pull/26449\nRelated backend change: https://github.com/openai/openai/pull/990244\n\n## Verification\n\n- `cargo test --manifest-path app-server-protocol/Cargo.toml remote_control`\n- `cargo test --manifest-path app-server/Cargo.toml remote_control`\n- `cargo fmt --all --check`\n- `git diff --check`", + "labels": [], + "merged_at": "2026-06-05T17:33:57Z", + "number": 26450, + "state": "merged", + "title": "feat(app-server): add remote control pairing status RPC", + "url": "https://github.com/openai/codex/pull/26450" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/bundles/openai-codex-pr-26552.json b/artifacts/github/bundles/openai-codex-pr-26552.json new file mode 100644 index 000000000..71d715e96 --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-26552.json @@ -0,0 +1,192 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "pakrym-oai", + "committed_at": "2026-06-05T04:33:24Z", + "message": "Require absolute cwd in thread settings", + "sha": "7b0e744c2817f02dfb2be7741654b3163cf63640", + "url": "https://github.com/openai/codex/commit/7b0e744c2817f02dfb2be7741654b3163cf63640" + }, + { + "author": "pakrym-oai", + "committed_at": "2026-06-05T05:16:01Z", + "message": "Resolve thread settings cwd in app-server", + "sha": "581088c7d4effa5370dbfffdd73075c28f0a69a3", + "url": "https://github.com/openai/codex/commit/581088c7d4effa5370dbfffdd73075c28f0a69a3" + }, + { + "author": "pakrym-oai", + "committed_at": "2026-06-05T05:43:17Z", + "message": "Remove stale thread environment test overrides", + "sha": "763ee1c0f8a5c0874acb23b2b139b1ef0c65d40b", + "url": "https://github.com/openai/codex/commit/763ee1c0f8a5c0874acb23b2b139b1ef0c65d40b" + }, + { + "author": "pakrym-oai", + "committed_at": "2026-06-05T06:04:49Z", + "message": "Use cross-platform cwd fixtures in compact tests", + "sha": "69c63117537ebd06a9e553bd78a8224ef472b619", + "url": "https://github.com/openai/codex/commit/69c63117537ebd06a9e553bd78a8224ef472b619" + }, + { + "author": "pakrym-oai", + "committed_at": "2026-06-05T06:47:38Z", + "message": "Make runtime workspace roots absolute in app-server API", + "sha": "51cba6a6237ebe8a9f9c5b6c97c2e1016521c14a", + "url": "https://github.com/openai/codex/commit/51cba6a6237ebe8a9f9c5b6c97c2e1016521c14a" + }, + { + "author": "pakrym-oai", + "committed_at": "2026-06-05T07:06:01Z", + "message": "codex: fix CI failure on PR #26552", + "sha": "16b2de73300f6b30c4e891fca718ee52025d70cb", + "url": "https://github.com/openai/codex/commit/16b2de73300f6b30c4e891fca718ee52025d70cb" + }, + { + "author": "pakrym-oai", + "committed_at": "2026-06-05T07:18:56Z", + "message": "app-server: fix windows clippy import", + "sha": "386bced1067c66ff1573f437b03a38199a3b4f3b", + "url": "https://github.com/openai/codex/commit/386bced1067c66ff1573f437b03a38199a3b4f3b" + }, + { + "author": "pakrym-oai", + "committed_at": "2026-06-05T16:39:50Z", + "message": "Merge remote-tracking branch 'origin/main' into pakrym/full-ci-app-server-workspace-roots", + "sha": "8662abac5d2a62bd4e676912be23f85b361209f4", + "url": "https://github.com/openai/codex/commit/8662abac5d2a62bd4e676912be23f85b361209f4" + } + ], + "default_branch": "main", + "docs_refs": [ + "codex-rs/app-server/README.md" + ], + "examples_refs": [], + "extracted_flags": [ + "TUI", + "API", + "MCP", + "ARC", + "JSONRPCE", + "DEFAULT_READ_TIMEOUT" + ], + "files": [ + { + "additions": 4, + "deletions": 0, + "patch_excerpt": "@@ -1,6 +1,10 @@\n {\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"definitions\": {\n+ \"AbsolutePathBuf\": {\n+ \"description\": \"A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\\n\\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.\",\n+ \"type\": \"string\"\n+ },\n \"ApprovalsReviewer\": {\n \"description\": \"Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approv...", + "path": "codex-rs/app-server-protocol/schema/json/v2/ThreadForkParams.json", + "status": "modified" + }, + { + "additions": 4, + "deletions": 0, + "patch_excerpt": "@@ -1,6 +1,10 @@\n {\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"definitions\": {\n+ \"AbsolutePathBuf\": {\n+ \"description\": \"A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\\n\\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.\",\n+ \"type\": \"string\"\n+ },\n \"AgentMessageInputContent\": {\n \"oneOf\": [\n {", + "path": "codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json", + "status": "modified" + }, + { + "additions": 6, + "deletions": 9, + "patch_excerpt": "@@ -107,11 +107,10 @@ pub struct ThreadStartParams {\n pub service_tier: Option>,\n #[ts(optional = nullable)]\n pub cwd: Option,\n- /// Replace the thread's runtime workspace roots. Relative paths are\n- /// resolved against the effective cwd for the thread.\n+ /// Replace the thread's runtime workspace roots. Paths must be absolute.\n #[experimental(\"thread/start.runtimeWorkspaceRoots\")]\n #[ts(optional = nullable)]\n- pub runtime_workspace_roots: Option>,\n+ pub runtime_workspace_roots: Option>,\n #[experimental(nested)]\n #[ts(optional = nullable)]\n pub approval_policy: Option,\n@@ -358,11 +357,10 @@ pub struct ThreadResumeParams {\n pub service_tier: Option>,\n #[ts(optional = nullable)]\n pub cwd: Option,\n- /// Replace the thread's runtime wo...", + "path": "codex-rs/app-server-protocol/src/protocol/v2/thread.rs", + "status": "modified" + }, + { + "additions": 2, + "deletions": 3, + "patch_excerpt": "@@ -88,11 +88,10 @@ pub struct TurnStartParams {\n #[ts(optional = nullable)]\n pub cwd: Option,\n /// Replace the thread's runtime workspace roots for this turn and\n- /// subsequent turns. Relative paths are resolved against the effective\n- /// cwd for the turn.\n+ /// subsequent turns. Paths must be absolute.\n #[experimental(\"turn/start.runtimeWorkspaceRoots\")]\n #[ts(optional = nullable)]\n- pub runtime_workspace_roots: Option>,\n+ pub runtime_workspace_roots: Option>,\n /// Override the approval policy for this turn and subsequent turns.\n #[experimental(nested)]\n #[ts(optional = nullable)]", + "path": "codex-rs/app-server-protocol/src/protocol/v2/turn.rs", + "status": "modified" + }, + { + "additions": 2, + "deletions": 2, + "patch_excerpt": "@@ -130,7 +130,7 @@ Example with notification opt-out:\n \n ## API Overview\n \n-- `thread/start` — create a new thread; emits `thread/started` (including the current `thread.status`) and auto-subscribes you to turn/item events for that thread. When the request includes a `cwd` and the resolved sandbox is `workspace-write` or full access, app-server also marks that project as trusted in the user `config.toml`. Pass `sessionStartSource: \"clear\"` when starting a replacement thread after clearing the current session so `SessionStart` hooks receive `source: \"clear\"` instead of the default `\"startup\"`. Experimental `runtimeWorkspaceRoots` replaces the thread-scoped runtime workspace roots used to materialize `:workspace_roots`; relative paths resolve against the effective thread cwd. For permissions, prefer experimental `permissions` profile selection by id; the legacy `sandbox` shorthand is stil...", + "path": "codex-rs/app-server/README.md", + "status": "modified" + }, + { + "additions": 18, + "deletions": 0, + "patch_excerpt": "@@ -513,6 +513,24 @@ use crate::thread_state::ThreadStateManager;\n use token_usage_replay::latest_token_usage_turn_id_from_rollout_items;\n use token_usage_replay::send_thread_token_usage_update_to_connection;\n \n+fn resolve_request_cwd(cwd: Option) -> Result, JSONRPCErrorError> {\n+ cwd.map(|cwd| {\n+ AbsolutePathBuf::relative_to_current_dir(path_utils::normalize_for_native_workdir(cwd))\n+ .map_err(|err| invalid_request(format!(\"invalid cwd: {err}\")))\n+ })\n+ .transpose()\n+}\n+\n+fn resolve_runtime_workspace_roots(workspace_roots: Vec) -> Vec {\n+ let mut resolved_roots = Vec::new();\n+ for root in workspace_roots {\n+ if !resolved_roots.iter().any(|existing| existing == &root) {\n+ resolved_roots.push(root);\n+ }\n+ }\n+ resolved_roots\n+}\n+\n mod config_errors;\n mod reque...", + "path": "codex-rs/app-server/src/request_processors.rs", + "status": "modified" + }, + { + "additions": 5, + "deletions": 12, + "patch_excerpt": "@@ -56,17 +56,7 @@ fn collect_resume_override_mismatches(\n }\n }\n if let Some(requested_runtime_workspace_roots) = request.runtime_workspace_roots.as_ref() {\n- let base_cwd = request\n- .cwd\n- .as_deref()\n- .map(|cwd| {\n- AbsolutePathBuf::resolve_path_against_base(cwd, config_snapshot.cwd.as_path())\n- })\n- .unwrap_or_else(|| config_snapshot.cwd.clone());\n- let requested_runtime_workspace_roots = requested_runtime_workspace_roots\n- .iter()\n- .map(|path| AbsolutePathBuf::resolve_path_against_base(path, base_cwd.as_path()))\n- .collect::>();\n+ let requested_runtime_workspace_roots = requested_runtime_workspace_roots.to_vec();\n if requested_runtime_workspace_roots != config_snapshot.workspace_roots {\n mismatch_details.push(format!...", + "path": "codex-rs/app-server/src/request_processors/thread_processor.rs", + "status": "modified" + }, + { + "additions": 9, + "deletions": 49, + "patch_excerpt": "@@ -18,28 +18,6 @@ pub(crate) struct TurnRequestProcessor {\n skills_watcher: Arc,\n }\n \n-fn resolve_runtime_workspace_roots(\n- workspace_roots: Vec,\n- base_cwd: &AbsolutePathBuf,\n-) -> Vec {\n- let mut resolved_roots = Vec::new();\n- for path in workspace_roots {\n- let root = AbsolutePathBuf::resolve_path_against_base(path, base_cwd.as_path());\n- if !resolved_roots.iter().any(|existing| existing == &root) {\n- resolved_roots.push(root);\n- }\n- }\n- resolved_roots\n-}\n-\n-fn resolve_request_cwd(cwd: Option) -> Result, JSONRPCErrorError> {\n- cwd.map(|cwd| {\n- AbsolutePathBuf::relative_to_current_dir(path_utils::normalize_for_native_workdir(cwd))\n- .map_err(|err| invalid_request(format!(\"invalid cwd: {err}\")))\n- })\n- .transpose()\n-}\n-\n fn map_add...", + "path": "codex-rs/app-server/src/request_processors/turn_processor.rs", + "status": "modified" + }, + { + "additions": 4, + "deletions": 1, + "patch_excerpt": "@@ -366,7 +366,10 @@ async fn turn_start_updates_runtime_workspace_roots_for_loaded_thread() -> Resul\n text: \"Hello\".to_string(),\n text_elements: Vec::new(),\n }],\n- runtime_workspace_roots: Some(vec![extra_root.clone(), extra_root.join(\".\")]),\n+ runtime_workspace_roots: Some(vec![\n+ AbsolutePathBuf::from_absolute_path(&extra_root)?,\n+ AbsolutePathBuf::from_absolute_path(extra_root.join(\".\"))?,\n+ ]),\n ..Default::default()\n })\n .await?;", + "path": "codex-rs/app-server/tests/suite/v2/thread_resume.rs", + "status": "modified" + }, + { + "additions": 5, + "deletions": 8, + "patch_excerpt": "@@ -197,23 +197,23 @@ async fn thread_start_creates_thread_and_emits_started() -> Result<()> {\n }\n \n #[tokio::test]\n-async fn thread_start_resolves_runtime_workspace_roots_against_cwd() -> Result<()> {\n+async fn thread_start_accepts_absolute_runtime_workspace_roots() -> Result<()> {\n let server = create_mock_responses_server_repeating_assistant(\"Done\").await;\n let codex_home = TempDir::new()?;\n create_config_toml_without_approval_policy(codex_home.path(), &server.uri())?;\n \n let cwd_tmp = TempDir::new()?;\n let cwd = cwd_tmp.path().to_path_buf();\n- let relative_root = PathBuf::from(\"extra-root\");\n- std::fs::create_dir_all(cwd.join(&relative_root))?;\n+ let extra_root = cwd.join(\"extra-root\");\n+ std::fs::create_dir_all(&extra_root)?;\n \n let mut mcp = TestAppServer::new(codex_home.path()).await?;\n timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??...", + "path": "codex-rs/app-server/tests/suite/v2/thread_start.rs", + "status": "modified" + }, + { + "additions": 2, + "deletions": 0, + "patch_excerpt": "@@ -2301,6 +2301,8 @@ async fn turn_start_permission_profile_rebinds_runtime_workspace_roots_between_t\n std::fs::create_dir(&new_root)?;\n let old_root_text = old_root.to_string_lossy().into_owned();\n let new_root_text = new_root.to_string_lossy().into_owned();\n+ let old_root = codex_utils_absolute_path::AbsolutePathBuf::from_absolute_path(old_root)?;\n+ let new_root = codex_utils_absolute_path::AbsolutePathBuf::from_absolute_path(new_root)?;\n \n let server = responses::start_mock_server().await;\n let response_mock = responses::mount_sse_sequence(", + "path": "codex-rs/app-server/tests/suite/v2/turn_start.rs", + "status": "modified" + }, + { + "additions": 4, + "deletions": 9, + "patch_excerpt": "@@ -2245,9 +2245,9 @@ pub struct ConfigOverrides {\n pub bypass_hook_trust: Option,\n /// Additional directories that should be treated as writable roots for this session.\n pub additional_writable_roots: Vec,\n- /// Explicit runtime workspace roots for this session. When set, this is\n- /// the full runtime root list rather than an additive override.\n- pub workspace_roots: Option>,\n+ /// Explicit absolute runtime workspace roots for this session. When set,\n+ /// this is the full runtime root list rather than an additive override.\n+ pub workspace_roots: Option>,\n }\n \n fn dedupe_absolute_paths(paths: &mut Vec) {\n@@ -2821,12 +2821,7 @@ impl Config {\n || !requested_additional_writable_roots.is_empty()\n || legacy_workspace_roots_explicit;\n let mut workspace_roots = match...", + "path": "codex-rs/core/src/config/mod.rs", + "status": "modified" + }, + { + "additions": 2, + "deletions": 14, + "patch_excerpt": "@@ -1044,13 +1044,7 @@ fn thread_start_params_from_config(config: &Config) -> ThreadStartParams {\n model: config.model.clone(),\n model_provider: Some(config.model_provider_id.clone()),\n cwd: Some(config.cwd.to_string_lossy().to_string()),\n- runtime_workspace_roots: Some(\n- config\n- .workspace_roots\n- .iter()\n- .map(AbsolutePathBuf::to_path_buf)\n- .collect(),\n- ),\n+ runtime_workspace_roots: Some(config.workspace_roots.clone()),\n approval_policy: Some(config.permissions.approval_policy.value().into()),\n approvals_reviewer: approvals_reviewer_override_from_config(config),\n sandbox: sandbox.flatten(),\n@@ -1075,13 +1069,7 @@ fn thread_resume_params_from_config(config: &Config, thread_id: String) -> Threa\n model: config.model.clone(),\n mode...", + "path": "codex-rs/exec/src/lib.rs", + "status": "modified" + }, + { + "additions": 6, + "deletions": 41, + "patch_excerpt": "@@ -708,12 +708,7 @@ impl AppServerSession {\n additional_context: None,\n environments: None,\n cwd: Some(cwd),\n- runtime_workspace_roots: Some(\n- workspace_roots\n- .iter()\n- .map(AbsolutePathBuf::to_path_buf)\n- .collect(),\n- ),\n+ runtime_workspace_roots: Some(workspace_roots.to_vec()),\n approval_policy: Some(approval_policy),\n approvals_reviewer: Some(approvals_reviewer.into()),\n sandbox_policy,\n@@ -1403,13 +1398,7 @@ fn thread_start_params_from_config(\n model_provider: thread_params_mode.model_provider_from_config(config),\n service_tier: service_tier_override_from_config(config),\n cwd: th...", + "path": "codex-rs/tui/src/app_server_session.rs", + "status": "modified" + } + ], + "linked_issues": [ + "#26532", + "#26552" + ], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "Stacked on #26532.\n\n## Why\n\n#26532 moves cwd normalization to the app-server/core boundary. `runtimeWorkspaceRoots` still accepted raw paths in v2 requests and in `ConfigOverrides`, which left core responsible for interpreting those roots later. This makes runtime workspace roots follow the same absolute-path boundary as cwd.\n\n## What\n\n- Change v2 `runtimeWorkspaceRoots` request fields for `thread/start`, `thread/resume`, `thread/fork`, and `turn/start` to `AbsolutePathBuf`.\n- Deduplicate already-absolute runtime roots in app-server handlers and pass them through `ConfigOverrides.workspace_roots` as `AbsolutePathBuf`.\n- Update TUI and exec client request builders to pass absolute runtime roots directly.\n- Update app-server docs, schema fixtures, and focused tests for absolute runtime roots.\n\n## Testing\n\n- `just test -p codex-app-server-protocol`\n- `just test -p codex-app-server runtime_workspace_roots`\n- `just test -p codex-core session_permission_profile_rebinds_runtime_workspace_roots`\n- `just test -p codex-tui app_server_session`\n- `just test -p codex-exec`", + "labels": [], + "merged_at": "2026-06-05T18:36:54Z", + "number": 26552, + "state": "merged", + "title": "Make runtime workspace roots absolute in app-server API", + "url": "https://github.com/openai/codex/pull/26552" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/bundles/openai-codex-pr-26631.json b/artifacts/github/bundles/openai-codex-pr-26631.json new file mode 100644 index 000000000..0fc04a5a7 --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-26631.json @@ -0,0 +1,90 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "mpc-oai", + "committed_at": "2026-06-05T15:21:30Z", + "message": "Add JSON output for plugin subcommands", + "sha": "25dbc5f55c696a58a0e58a55e0649240c909e3ab", + "url": "https://github.com/openai/codex/commit/25dbc5f55c696a58a0e58a55e0649240c909e3ab" + } + ], + "default_branch": "main", + "docs_refs": [], + "examples_refs": [], + "extracted_flags": [ + "--json", + "JSON", + "CLI", + "MARKETPLACE_NAME", + "CODEX_HOME", + "OPENAI_BUNDLED_MARKETPLACE_NAME", + "PLUGIN", + "MARKETPLACE", + "CONFIG_TOML_FILE", + "ON_INSTALL", + "--marketplace" + ], + "files": [ + { + "additions": 180, + "deletions": 6, + "patch_excerpt": "@@ -7,11 +7,14 @@ use codex_core::config::find_codex_home;\n use codex_core_plugins::PluginMarketplaceUpgradeOutcome;\n use codex_core_plugins::PluginsManager;\n use codex_core_plugins::marketplace::marketplace_root_dir;\n+use codex_core_plugins::marketplace_add::MarketplaceAddOutcome;\n use codex_core_plugins::marketplace_add::MarketplaceAddRequest;\n use codex_core_plugins::marketplace_add::add_marketplace;\n+use codex_core_plugins::marketplace_remove::MarketplaceRemoveOutcome;\n use codex_core_plugins::marketplace_remove::MarketplaceRemoveRequest;\n use codex_core_plugins::marketplace_remove::remove_marketplace;\n use codex_utils_cli::CliConfigOverrides;\n+use serde::Serialize;\n use std::collections::HashSet;\n \n use crate::plugin_cmd::configured_marketplace_snapshot_issues;\n@@ -32,7 +35,7 @@ enum MarketplaceSubcommand {\n Add(AddMarketplaceArgs),\n \n /// List plugin marketplaces Codex is c...", + "path": "codex-rs/cli/src/marketplace_cmd.rs", + "status": "modified" + }, + { + "additions": 78, + "deletions": 3, + "patch_excerpt": "@@ -6,6 +6,7 @@ use codex_core::config::Config;\n use codex_core::config::find_codex_home;\n use codex_core_plugins::ConfiguredMarketplace;\n use codex_core_plugins::OPENAI_BUNDLED_MARKETPLACE_NAME;\n+use codex_core_plugins::PluginInstallOutcome;\n use codex_core_plugins::PluginInstallRequest;\n use codex_core_plugins::PluginsConfigInput;\n use codex_core_plugins::PluginsManager;\n@@ -73,6 +74,10 @@ pub struct AddPluginArgs {\n /// Configured marketplace name to use when PLUGIN does not include @MARKETPLACE.\n #[arg(long = \"marketplace\", short = 'm', value_name = \"MARKETPLACE\")]\n marketplace_name: Option,\n+\n+ /// Output install result as JSON.\n+ #[arg(long = \"json\")]\n+ json: bool,\n }\n \n #[derive(Debug, Parser)]\n@@ -107,6 +112,10 @@ pub struct RemovePluginArgs {\n /// Marketplace name to use when PLUGIN does not include @MARKETPLACE.\n #[arg(long = \"marketplace\", ...", + "path": "codex-rs/cli/src/plugin_cmd.rs", + "status": "modified" + }, + { + "additions": 37, + "deletions": 0, + "patch_excerpt": "@@ -1,8 +1,10 @@\n use anyhow::Result;\n use codex_config::CONFIG_TOML_FILE;\n use codex_core_plugins::installed_marketplaces::marketplace_install_root;\n+use codex_utils_absolute_path::AbsolutePathBuf;\n use predicates::str::contains;\n use pretty_assertions::assert_eq;\n+use serde_json::json;\n use std::path::Path;\n use tempfile::TempDir;\n \n@@ -70,6 +72,41 @@ async fn marketplace_add_local_directory_source() -> Result<()> {\n Ok(())\n }\n \n+#[tokio::test]\n+async fn marketplace_add_json_prints_add_outcome() -> Result<()> {\n+ let codex_home = TempDir::new()?;\n+ let source = TempDir::new()?;\n+ write_marketplace_source(source.path(), \"local ref\")?;\n+ let source_parent = source.path().parent().unwrap();\n+ let source_arg = format!(\"./{}\", source.path().file_name().unwrap().to_string_lossy());\n+\n+ let assert = codex_command(codex_home.path())?\n+ .current_dir(source_parent)\n+...", + "path": "codex-rs/cli/tests/marketplace_add.rs", + "status": "modified" + }, + { + "additions": 29, + "deletions": 0, + "patch_excerpt": "@@ -2,7 +2,10 @@ use anyhow::Result;\n use codex_config::MarketplaceConfigUpdate;\n use codex_config::record_user_marketplace;\n use codex_core_plugins::installed_marketplaces::marketplace_install_root;\n+use codex_utils_absolute_path::canonicalize_existing_preserving_symlinks;\n use predicates::str::contains;\n+use pretty_assertions::assert_eq;\n+use serde_json::json;\n use std::path::Path;\n use tempfile::TempDir;\n \n@@ -54,6 +57,32 @@ async fn marketplace_remove_deletes_config_and_installed_root() -> Result<()> {\n Ok(())\n }\n \n+#[tokio::test]\n+async fn marketplace_remove_json_prints_remove_outcome() -> Result<()> {\n+ let codex_home = TempDir::new()?;\n+ record_user_marketplace(codex_home.path(), \"debug\", &configured_marketplace_update())?;\n+ write_installed_marketplace(codex_home.path(), \"debug\")?;\n+ let installed_root = marketplace_install_root(codex_home.path()).join(\"debug\");\n+...", + "path": "codex-rs/cli/tests/marketplace_remove.rs", + "status": "modified" + }, + { + "additions": 25, + "deletions": 0, + "patch_excerpt": "@@ -1,5 +1,7 @@\n use anyhow::Result;\n use predicates::str::contains;\n+use pretty_assertions::assert_eq;\n+use serde_json::json;\n use std::path::Path;\n use tempfile::TempDir;\n \n@@ -22,6 +24,29 @@ async fn marketplace_upgrade_runs_under_plugin() -> Result<()> {\n Ok(())\n }\n \n+#[tokio::test]\n+async fn marketplace_upgrade_json_prints_upgrade_outcome() -> Result<()> {\n+ let codex_home = TempDir::new()?;\n+\n+ let assert = codex_command(codex_home.path())?\n+ .args([\"plugin\", \"marketplace\", \"upgrade\", \"--json\"])\n+ .assert()\n+ .success();\n+ let stdout = assert.get_output().stdout.as_slice();\n+ let actual: serde_json::Value = serde_json::from_slice(stdout)?;\n+\n+ assert_eq!(\n+ actual,\n+ json!({\n+ \"selectedMarketplaces\": [],\n+ \"upgradedRoots\": [],\n+ \"errors\": [],\n+ })\n+ );\n+\n+ Ok(())\n+}\n+\n #[tokio::test]...", + "path": "codex-rs/cli/tests/marketplace_upgrade.rs", + "status": "modified" + }, + { + "additions": 89, + "deletions": 0, + "patch_excerpt": "@@ -338,6 +338,32 @@ async fn marketplace_list_shows_configured_marketplace_names() -> Result<()> {\n Ok(())\n }\n \n+#[tokio::test]\n+async fn marketplace_list_json_prints_configured_marketplaces() -> Result<()> {\n+ let (codex_home, source) = setup_local_marketplace()?;\n+\n+ let assert = codex_command(codex_home.path())?\n+ .args([\"plugin\", \"marketplace\", \"list\", \"--json\"])\n+ .assert()\n+ .success();\n+ let stdout = assert.get_output().stdout.as_slice();\n+ let actual: serde_json::Value = serde_json::from_slice(stdout)?;\n+\n+ assert_eq!(\n+ actual,\n+ json!({\n+ \"marketplaces\": [\n+ {\n+ \"name\": \"debug\",\n+ \"root\": source.path().display().to_string(),\n+ },\n+ ],\n+ })\n+ );\n+\n+ Ok(())\n+}\n+\n #[tokio::test]\n async fn marketplace_list_includes_home_market...", + "path": "codex-rs/cli/tests/plugin_cli.rs", + "status": "modified" + } + ], + "linked_issues": [ + "#25330", + "#26417" + ], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "## Summary\r\n- Follow-up to #25330 and #26417\r\n- Add `--json` output for `codex plugin add` and `codex plugin remove`\r\n- Add `--json` output for `codex plugin marketplace add/list/upgrade/remove`\r\n- Keep existing human-readable output unchanged\r\n- Keep existing error handling/stderr behavior unchanged; `--json` changes successful stdout output only\r\n- Align marketplace add/remove JSON field names with the existing app-server protocol shape\r\n- Add CLI coverage for plugin and marketplace JSON outputs\r\n\r\n## Validation\r\n- `just fmt`\r\n- `just fix -p codex-cli`\r\n- `just test -p codex-cli`", + "labels": [], + "merged_at": "2026-06-05T19:40:31Z", + "number": 26631, + "state": "merged", + "title": "Add JSON output for plugin subcommands", + "url": "https://github.com/openai/codex/pull/26631" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/impact/openai-codex-pr-26449.json b/artifacts/github/impact/openai-codex-pr-26449.json new file mode 100644 index 000000000..7dd2b30fe --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-26449.json @@ -0,0 +1,44 @@ +{ + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-26449", + "repo": "openai/codex", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "feat(remote-control): add pairing status transport", + "url": "https://github.com/openai/codex/pull/26449", + "meta": "Merged 2026-06-05T17:07:25Z" + }, + { + "kind": "pull_request", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/26449", + "meta": "artifacts/github/reviews/openai-codex-pr-26449.review.json" + } + ] + }, + "observed_change": "Codex added host-authenticated remote-control transport support for polling whether a QR or manual pairing code has been claimed.", + "public_signal_decision": "skip", + "control_plane_impact": "watch", + "publisher_angle": "none", + "confidence": "confirmed", + "evidence": [ + "The PR adds the server/pair/status backend URL, request and response structs, and RemoteControlEnrollment/RemoteControlHandle pairing_status methods.", + "The status request accepts exactly one code field and returns claimed: bool.", + "Transport tests cover pending, claimed, manual-code, token refresh, backend error mapping, malformed responses, and URL normalization.", + "The user-callable app-server RPC lands in dependent PR #26450 rather than this transport-only PR." + ], + "candidate_followups": [ + "Track this as supporting evidence for any Decodex remote-control enrollment adoption work.", + "Use PR #26450 rather than this PR for public app-server RPC messaging." + ], + "social_notes": [ + "Do not publish this transport PR as a standalone signal.", + "If mentioned publicly, use it only as dependency evidence for PR #26450." + ], + "caveats": [ + "No direct Decodex remote-control adoption was implemented in this run.", + "Backend behavior is inferred through the merged openai/codex transport integration and tests, not a live backend probe." + ] +} diff --git a/artifacts/github/impact/openai-codex-pr-26450.json b/artifacts/github/impact/openai-codex-pr-26450.json new file mode 100644 index 000000000..ae01ac42f --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-26450.json @@ -0,0 +1,46 @@ +{ + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-26450", + "repo": "openai/codex", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "feat(app-server): add remote control pairing status RPC", + "url": "https://github.com/openai/codex/pull/26450", + "meta": "Merged 2026-06-05T17:33:57Z" + }, + { + "kind": "pull_request", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/26450", + "meta": "artifacts/github/reviews/openai-codex-pr-26450.review.json" + } + ] + }, + "observed_change": "Codex exposed the remote-control pairing status transport as experimental app-server v2 JSON-RPC method remoteControl/pairing/status.", + "public_signal_decision": "publish", + "control_plane_impact": "candidate", + "publisher_angle": "operator_impact", + "confidence": "confirmed", + "evidence": [ + "The app-server protocol registers experimental method remoteControl/pairing/status with shared-read serialization.", + "MessageProcessor and RemoteControlRequestProcessor route the method to the remote-control handle.", + "The request processor rejects missing or conflicting pairing-code params before calling the transport.", + "The app-server README documents the new pairing status API beside pairing/start.", + "JSON-RPC integration tests exercise both pairingCode and manualPairingCode request paths." + ], + "candidate_followups": [ + "Evaluate whether Decodex Control Plane needs a pairing-status read helper when remote-control enrollment is surfaced.", + "Keep request construction strict: exactly one of pairingCode or manualPairingCode.", + "Do not treat the method as stable; preserve the upstream experimental label in public and implementation notes." + ], + "social_notes": [ + "Frame as a new experimental app-server RPC for Desktop remote-control pairing UX.", + "Mention the dependency on lower-level transport support from PR #26449 only if extra context is needed." + ], + "caveats": [ + "The method is experimental.", + "This review did not probe a live remote-control backend." + ] +} diff --git a/artifacts/github/impact/openai-codex-pr-26552.json b/artifacts/github/impact/openai-codex-pr-26552.json new file mode 100644 index 000000000..6dddd2be9 --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-26552.json @@ -0,0 +1,46 @@ +{ + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-26552", + "repo": "openai/codex", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "Make runtime workspace roots absolute in app-server API", + "url": "https://github.com/openai/codex/pull/26552", + "meta": "Merged 2026-06-05T18:36:54Z" + }, + { + "kind": "pull_request", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/26552", + "meta": "artifacts/github/reviews/openai-codex-pr-26552.review.json" + } + ] + }, + "observed_change": "Codex changed app-server runtimeWorkspaceRoots request fields and ConfigOverrides.workspace_roots to require absolute runtime workspace roots.", + "public_signal_decision": "publish", + "control_plane_impact": "compat_risk", + "publisher_angle": "operator_impact", + "confidence": "confirmed", + "evidence": [ + "PR #26552 explicitly says runtimeWorkspaceRoots now follows the same absolute-path boundary as cwd.", + "Protocol thread and turn request fields move runtime_workspace_roots from Vec to Vec.", + "The app-server README changes runtimeWorkspaceRoots documentation from relative-path resolution to paths-must-be-absolute wording.", + "Core ConfigOverrides.workspace_roots changes to Option>.", + "TUI and exec request builders pass existing absolute workspace roots directly instead of converting them to PathBuf." + ], + "candidate_followups": [ + "Audit Decodex app-server clients and tests that send runtimeWorkspaceRoots.", + "Resolve or reject relative runtime roots at the Decodex request boundary before calling upstream Codex app-server APIs.", + "Pair this with the existing PR #26532 absolute-cwd review when planning compatibility work." + ], + "social_notes": [ + "Frame as an app-server protocol migration note for integrators.", + "Avoid claiming a broad end-user workflow change; the observable path is app-server request construction." + ], + "caveats": [ + "The PR is stacked on #26532.", + "No direct Decodex breakage was reproduced in this run." + ] +} diff --git a/artifacts/github/impact/openai-codex-pr-26631.json b/artifacts/github/impact/openai-codex-pr-26631.json new file mode 100644 index 000000000..1fda2ab1e --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-26631.json @@ -0,0 +1,46 @@ +{ + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-26631", + "repo": "openai/codex", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "Add JSON output for plugin subcommands", + "url": "https://github.com/openai/codex/pull/26631", + "meta": "Merged 2026-06-05T19:40:31Z" + }, + { + "kind": "pull_request", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/26631", + "meta": "artifacts/github/reviews/openai-codex-pr-26631.review.json" + } + ] + }, + "observed_change": "Codex added successful stdout JSON output for plugin add/remove and plugin marketplace add/list/upgrade/remove commands while preserving existing human-readable output.", + "public_signal_decision": "publish", + "control_plane_impact": "candidate", + "publisher_angle": "practical_explainer", + "confidence": "confirmed", + "evidence": [ + "PR #26631 says --json changes successful stdout only and keeps existing human-readable and error/stderr behavior unchanged.", + "codex-rs/cli/src/plugin_cmd.rs adds --json flags to plugin add and plugin remove.", + "codex-rs/cli/src/marketplace_cmd.rs adds JSON handling for marketplace add, list, upgrade, and remove.", + "CLI tests parse JSON stdout for plugin and marketplace command success cases.", + "The JSON field names align marketplace add/remove results with the existing app-server protocol shape according to the PR body." + ], + "candidate_followups": [ + "Use --json for Decodex plugin-management probes where successful stdout is currently parsed as text.", + "Keep failure handling unchanged because stderr and errors are explicitly outside the new JSON success-output contract.", + "Consider a small operator note or issue if Decodex has plugin install/remove automation that can consume this immediately." + ], + "social_notes": [ + "Give readers concrete commands: codex plugin add --json, codex plugin remove --json, and codex plugin marketplace list --json.", + "State that human-readable output remains unchanged unless --json is used." + ], + "caveats": [ + "The PR adds JSON only for successful stdout output.", + "This does not by itself change plugin discovery or plugin runtime behavior." + ] +} diff --git a/artifacts/github/review-queue/openai-codex-latest.json b/artifacts/github/review-queue/openai-codex-latest.json index 55009e1a2..379c65fc8 100644 --- a/artifacts/github/review-queue/openai-codex-latest.json +++ b/artifacts/github/review-queue/openai-codex-latest.json @@ -1,14 +1,14 @@ { "counts": { - "critical": 18, - "high": 4, + "critical": 19, + "high": 5, "low": 2, - "normal": 16, + "normal": 14, "published_subjects_seen": 0, "recent_commits_scanned": 40, "subjects_queued": 40 }, - "generated_at": "2026-06-08T02:19:37.943725Z", + "generated_at": "2026-06-08T08:04:47.078688Z", "repo": "openai/codex", "schema": "upstream_review_queue/v1", "source": { @@ -818,6 +818,53 @@ "title": "deps: update starlark to 0.14.2", "url": "https://github.com/openai/codex/pull/24820" }, + { + "attention_flags": [ + "auth_account", + "breaking_change", + "new_feature", + "protocol_change", + "rate_limit" + ], + "changed_file_count": 18, + "commit_shas": [ + "b5eae7326947ad4e7e7003a3f6925f370fb85407", + "84b8997c6c294c8e63ea1e85c53e9ef01ed022de", + "1b50304606151d6071fb68c7dbb09597b6d8c100" + ], + "committed_at": "2026-06-08T03:12:05Z", + "next_step": "ai_review_required", + "pr_number": 26639, + "pr_url": "https://github.com/openai/codex/pull/26639", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, breaking_change, new_feature, protocol_change, rate_limit.", + "sample_paths": [ + "codex-rs/app-server-protocol/schema/json/ServerNotification.json", + "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json", + "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json", + "codex-rs/app-server-protocol/schema/json/v2/McpServerStatusUpdatedNotification.json", + "codex-rs/app-server-protocol/schema/typescript/v2/McpServerStatusUpdatedNotification.ts", + "codex-rs/app-server-protocol/src/protocol/v2/mcp.rs", + "codex-rs/app-server-protocol/src/protocol/v2/tests.rs", + "codex-rs/app-server/README.md", + "codex-rs/app-server/src/bespoke_event_handling.rs", + "codex-rs/app-server/tests/suite/v2/thread_start.rs", + "codex-rs/tui/src/app/app_server_event_targets.rs", + "codex-rs/tui/src/app/app_server_events.rs" + ], + "source_state": "merged", + "subject_id": "26639", + "subject_kind": "pr", + "surface_hints": [ + "app_server_protocol", + "cli_tui", + "docs_examples", + "mcp_plugins", + "tests_ci" + ], + "title": "fix(tui): scope MCP startup status by thread", + "url": "https://github.com/openai/codex/pull/26639" + }, { "attention_flags": [ "protocol_change", @@ -939,66 +986,41 @@ "title": "fix(core-plugins): send Codex product SKU to plugin-service", "url": "https://github.com/openai/codex/pull/26804" }, - { - "attention_flags": [ - "new_feature", - "protocol_change" - ], - "changed_file_count": 1, - "commit_shas": [ - "acc0252dd2ef5f84af46d5acae80a065baa84aab", - "faa67b521be5f4cb32c416423e8a6c4e33d9e905", - "e3051c46b831615f34c922c2a7e84317613ef1ec" - ], - "committed_at": "2026-06-05T15:32:42Z", - "next_step": "ai_review_required", - "pr_number": 26500, - "pr_url": "https://github.com/openai/codex/pull/26500", - "review_priority": "normal", - "review_reason": "Needs AI review for new_feature, protocol_change.", - "sample_paths": [ - "codex-rs/cli/src/desktop_app/windows.rs" - ], - "source_state": "merged", - "subject_id": "26500", - "subject_kind": "pr", - "surface_hints": [ - "cli_tui" - ], - "title": "Open Windows app workspaces via deep link", - "url": "https://github.com/openai/codex/pull/26500" - }, { "attention_flags": [ "auth_account", "new_feature", - "protocol_change" + "protocol_change", + "security_policy" ], - "changed_file_count": 4, + "changed_file_count": 6, "commit_shas": [ - "99f0fff78b39b88b2a0f3b2f17aa7a1d3a1b0bd5" + "e28d2a19b431e3507482c05c2e292aeb9c68bf8c", + "02724b98d36c0285a4ded52dd8eeb5cae7dba445" ], - "committed_at": "2026-06-05T15:32:53Z", + "committed_at": "2026-06-08T06:18:23Z", "next_step": "ai_review_required", - "pr_number": 26551, - "pr_url": "https://github.com/openai/codex/pull/26551", - "review_priority": "normal", - "review_reason": "Needs AI review for auth_account, new_feature, protocol_change.", + "pr_number": 26719, + "pr_url": "https://github.com/openai/codex/pull/26719", + "review_priority": "high", + "review_reason": "Needs AI review for auth_account, new_feature, protocol_change, security_policy.", "sample_paths": [ - "codex-rs/tui/src/app/thread_goal_actions.rs", - "codex-rs/tui/src/chatwidget/slash_dispatch.rs", - "codex-rs/tui/src/chatwidget/tests/slash_commands.rs", - "codex-rs/tui/src/goal_display.rs" + "codex-rs/app-server/tests/suite/v2/web_search.rs", + "codex-rs/codex-api/src/endpoint/search.rs", + "codex-rs/codex-api/src/search.rs", + "codex-rs/core/tests/suite/code_mode.rs", + "codex-rs/ext/web-search/src/output.rs", + "codex-rs/ext/web-search/src/tool.rs" ], "source_state": "merged", - "subject_id": "26551", + "subject_id": "26719", "subject_kind": "pr", "surface_hints": [ - "cli_tui", + "app_server_protocol", "tests_ci" ], - "title": "Fix `/goal` usage text for control commands", - "url": "https://github.com/openai/codex/pull/26551" + "title": "[codex] Enable standalone web search in code mode", + "url": "https://github.com/openai/codex/pull/26719" }, { "attention_flags": [ diff --git a/artifacts/github/reviews/openai-codex-pr-26449.review.json b/artifacts/github/reviews/openai-codex-pr-26449.review.json new file mode 100644 index 000000000..2f8730315 --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-26449.review.json @@ -0,0 +1,57 @@ +{ + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-26449", + "repo": "openai/codex", + "subject": { + "subject_kind": "pr", + "subject_id": "26449", + "commit_shas": [ + "acf4f7a893034a677d89703bc6236842b923ee23" + ] + }, + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "feat(remote-control): add pairing status transport", + "url": "https://github.com/openai/codex/pull/26449", + "meta": "Merged 2026-06-05T17:07:25Z" + }, + { + "kind": "commit", + "title": "feat(remote-control): add pairing status transport", + "url": "https://github.com/openai/codex/commit/acf4f7a893034a677d89703bc6236842b923ee23" + } + ] + }, + "reviewed_at": "2026-06-08T08:07:33Z", + "observed_change": "Codex added host-authenticated remote-control transport support for polling whether a QR or manual pairing code has been claimed.", + "changed_surfaces": [ + "app-server protocol remote-control pairing status request and response types", + "remote-control transport backend URL normalization and request payloads", + "RemoteControlEnrollment and RemoteControlHandle pairing status methods", + "remote-control transport tests for pending, claimed, manual-code, auth refresh, backend error, and malformed response cases" + ], + "user_visible_path": "Desktop can use the transport layer to poll the backend while a remote-control pairing modal is open, but this PR is the transport half and does not by itself expose the app-server JSON-RPC method to clients.", + "control_plane_relevance": "Decodex should treat pairing-status polling as a new remote-control transport capability that may matter if Control Plane starts mirroring Codex remote-control enrollment flows.", + "compatibility_risk": "The backend lookup accepts exactly one lookup key, pairing_code or manual_pairing_code, and callers that send neither or both should expect request validation or backend rejection once routed through the app-server surface.", + "adoption_opportunity": "If Decodex adopts remote-control enrollment UX, it can preserve host-authenticated polling and backend error mapping instead of implementing a separate status channel.", + "community_value": "Useful as supporting evidence for the app-server pairing-status RPC in PR #26450, but too low-level for a standalone public post.", + "deprecated_or_breaking_notes": "No removed public method is shown; the contract narrows the status lookup shape to one code field per request.", + "confidence": "confirmed", + "evidence": [ + "PR #26449 states that it adds the normalized server/pair/status backend URL and pairing status request/response structs for exactly one lookup key.", + "codex-rs/app-server-protocol/src/protocol/v2/remote_control.rs adds RemoteControlPairingStatusParams and RemoteControlPairingStatusResponse with claimed: bool.", + "codex-rs/app-server-transport/src/transport/remote_control/protocol.rs adds pair_status_url plus backend pairing status request and response types.", + "codex-rs/app-server-transport/src/transport/remote_control/enroll.rs and mod.rs wire RemoteControlEnrollment and RemoteControlHandle pairing_status methods.", + "codex-rs/app-server-transport/src/transport/remote_control/tests/pairing_tests.rs adds coverage for pending, claimed, manual-code, token refresh, mapped backend errors, malformed responses, and URL normalization.", + "The normalized bundle artifacts/github/bundles/openai-codex-pr-26449.json records 6 changed files for the merged PR." + ], + "caveats": "The public app-server JSON-RPC entrypoint lands in the dependent PR #26450, so downstream copy should not present this transport PR alone as a user-callable RPC.", + "next_actions": [ + { + "type": "upstream_impact", + "reason": "The new remote-control transport capability is relevant to Decodex Control Plane remote-enrollment compatibility tracking." + } + ] +} diff --git a/artifacts/github/reviews/openai-codex-pr-26450.review.json b/artifacts/github/reviews/openai-codex-pr-26450.review.json new file mode 100644 index 000000000..3db4f84ed --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-26450.review.json @@ -0,0 +1,68 @@ +{ + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-26450", + "repo": "openai/codex", + "subject": { + "subject_kind": "pr", + "subject_id": "26450", + "commit_shas": [ + "7d3240b290464a9102fd68f4438c1bd7ecb2431d" + ] + }, + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "feat(app-server): add remote control pairing status RPC", + "url": "https://github.com/openai/codex/pull/26450", + "meta": "Merged 2026-06-05T17:33:57Z" + }, + { + "kind": "commit", + "title": "feat(app-server): add remote control pairing status RPC", + "url": "https://github.com/openai/codex/commit/7d3240b290464a9102fd68f4438c1bd7ecb2431d" + }, + { + "kind": "pull_request", + "title": "feat(remote-control): add pairing status transport", + "url": "https://github.com/openai/codex/pull/26449", + "meta": "Dependency noted by PR #26450" + } + ] + }, + "reviewed_at": "2026-06-08T08:07:33Z", + "observed_change": "Codex exposed the remote-control pairing status transport as experimental app-server v2 JSON-RPC method remoteControl/pairing/status.", + "changed_surfaces": [ + "app-server protocol ClientRequest definitions and generated schema export checks", + "app-server MessageProcessor and RemoteControlRequestProcessor routing", + "remote-control app-server README API documentation", + "JSON-RPC integration tests for pairing-code and manual-code status requests" + ], + "user_visible_path": "Desktop and app-server clients can call remoteControl/pairing/status with exactly one of pairingCode or manualPairingCode and receive claimed: true or false while QR/manual pairing is pending.", + "control_plane_relevance": "Decodex Control Plane integrations that track Codex remote-control enrollment can poll a first-party app-server RPC instead of inferring pairing state out of band.", + "compatibility_risk": "Clients must send exactly one lookup key and should serialize calls under the remote-control-pairing shared-read scope; missing or conflicting params are invalid requests.", + "adoption_opportunity": "Add a bounded Decodex remote-control pairing-status read path if Control Plane adopts or tests Codex remote enrollment.", + "community_value": "The PR creates a concrete app-server API worth a public Publisher handoff for Desktop pairing UX and integrator migration awareness.", + "deprecated_or_breaking_notes": "No prior RPC is removed, but the new request shape is strict: one of pairingCode or manualPairingCode, not both.", + "confidence": "confirmed", + "evidence": [ + "PR #26450 states that it exposes pairing status as experimental app-server v2 RPC remoteControl/pairing/status.", + "codex-rs/app-server-protocol/src/protocol/common.rs registers RemoteControlPairingStatus with serialization global_shared_read(\"remote-control-pairing\").", + "codex-rs/app-server/src/message_processor.rs routes ClientRequest::RemoteControlPairingStatus to the remote control processor.", + "codex-rs/app-server/src/request_processors/remote_control_processor.rs validates pairing status params before calling the transport handle.", + "codex-rs/app-server/README.md documents the new remoteControl/pairing/status API beside pairing/start.", + "codex-rs/app-server/tests/suite/v2/remote_control.rs adds JSON-RPC coverage for the pairing status path.", + "The normalized bundle artifacts/github/bundles/openai-codex-pr-26450.json records 8 changed files for the merged PR." + ], + "caveats": "This RPC depends on the transport support from PR #26449 and remains marked experimental in the app-server protocol.", + "next_actions": [ + { + "type": "upstream_impact", + "reason": "The new app-server method affects Decodex Control Plane remote-control integration planning." + }, + { + "type": "social_candidate", + "reason": "The source-backed API addition has a clear public explainer angle for app-server and Desktop integrators." + } + ] +} diff --git a/artifacts/github/reviews/openai-codex-pr-26552.review.json b/artifacts/github/reviews/openai-codex-pr-26552.review.json new file mode 100644 index 000000000..8ac79ca22 --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-26552.review.json @@ -0,0 +1,80 @@ +{ + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-26552", + "repo": "openai/codex", + "subject": { + "subject_kind": "pr", + "subject_id": "26552", + "commit_shas": [ + "7b0e744c2817f02dfb2be7741654b3163cf63640", + "581088c7d4effa5370dbfffdd73075c28f0a69a3", + "763ee1c0f8a5c0874acb23b2b139b1ef0c65d40b", + "69c63117537ebd06a9e553bd78a8224ef472b619", + "51cba6a6237ebe8a9f9c5b6c97c2e1016521c14a", + "16b2de73300f6b30c4e891fca718ee52025d70cb", + "386bced1067c66ff1573f437b03a38199a3b4f3b", + "8662abac5d2a62bd4e676912be23f85b361209f4" + ] + }, + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "Make runtime workspace roots absolute in app-server API", + "url": "https://github.com/openai/codex/pull/26552", + "meta": "Merged 2026-06-05T18:36:54Z" + }, + { + "kind": "commit", + "title": "Make runtime workspace roots absolute in app-server API", + "url": "https://github.com/openai/codex/commit/51cba6a6237ebe8a9f9c5b6c97c2e1016521c14a" + }, + { + "kind": "pull_request", + "title": "Require absolute cwd in thread settings", + "url": "https://github.com/openai/codex/pull/26532", + "meta": "Stack dependency noted by PR #26552" + } + ] + }, + "reviewed_at": "2026-06-08T08:07:33Z", + "observed_change": "Codex changed app-server runtimeWorkspaceRoots request fields and ConfigOverrides.workspace_roots to require absolute runtime workspace roots.", + "changed_surfaces": [ + "app-server protocol schemas for thread and turn request runtimeWorkspaceRoots", + "app-server thread, resume, fork, and turn request processors", + "core ConfigOverrides workspace root type", + "TUI and exec app-server request builders", + "app-server README and focused runtime workspace roots tests" + ], + "user_visible_path": "App-server v2 callers that send runtimeWorkspaceRoots on thread/start, thread/resume, thread/fork, or turn/start now need to resolve those roots to absolute paths before submitting requests.", + "control_plane_relevance": "Decodex Control Plane should audit any app-server request builders that materialize :workspace_roots or pass runtimeWorkspaceRoots so relative roots are normalized at the Decodex boundary.", + "compatibility_risk": "Adapters that still rely on Codex core to resolve relative runtime workspace roots may fail or send invalid requests after this protocol narrowing.", + "adoption_opportunity": "Share the same absolute-path preparation used for cwd with runtime workspace root construction in Decodex app-server clients and tests.", + "community_value": "The change is a migration watch note for app-server integrators because it changes a protocol-facing path contract.", + "deprecated_or_breaking_notes": "Relative runtimeWorkspaceRoots are no longer described as accepted; the protocol types move from PathBuf to AbsolutePathBuf and docs now say paths must be absolute.", + "confidence": "confirmed", + "evidence": [ + "PR #26552 states that runtimeWorkspaceRoots request fields for thread/start, thread/resume, thread/fork, and turn/start change to AbsolutePathBuf.", + "codex-rs/app-server-protocol/src/protocol/v2/thread.rs changes runtime_workspace_roots from Vec to Vec and updates comments from relative resolution to absolute-only.", + "codex-rs/app-server-protocol/src/protocol/v2/turn.rs applies the same absolute-only runtimeWorkspaceRoots type and docs.", + "codex-rs/app-server/src/request_processors.rs adds resolve_runtime_workspace_roots for already-absolute roots and deduplication.", + "codex-rs/core/src/config/mod.rs changes ConfigOverrides.workspace_roots to Option>.", + "codex-rs/exec/src/lib.rs and codex-rs/tui/src/app_server_session.rs stop converting workspace_roots back to PathBuf before sending app-server requests.", + "The normalized bundle artifacts/github/bundles/openai-codex-pr-26552.json records 14 changed files for the merged PR." + ], + "caveats": "This PR is stacked on #26532, so public or implementation follow-up should discuss the broader absolute-path boundary rather than treating runtimeWorkspaceRoots in isolation.", + "next_actions": [ + { + "type": "upstream_impact", + "reason": "The protocol-facing absolute workspace-roots contract is a Decodex Control Plane compatibility risk." + }, + { + "type": "social_candidate", + "reason": "The migration requirement is useful for app-server integrators if framed as a cautious operator-impact note." + }, + { + "type": "linear_followup", + "reason": "Decodex should audit runtimeWorkspaceRoots construction across app-server request paths." + } + ] +} diff --git a/artifacts/github/reviews/openai-codex-pr-26631.review.json b/artifacts/github/reviews/openai-codex-pr-26631.review.json new file mode 100644 index 000000000..b5070a955 --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-26631.review.json @@ -0,0 +1,61 @@ +{ + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-26631", + "repo": "openai/codex", + "subject": { + "subject_kind": "pr", + "subject_id": "26631", + "commit_shas": [ + "25dbc5f55c696a58a0e58a55e0649240c909e3ab" + ] + }, + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "Add JSON output for plugin subcommands", + "url": "https://github.com/openai/codex/pull/26631", + "meta": "Merged 2026-06-05T19:40:31Z" + }, + { + "kind": "commit", + "title": "Add JSON output for plugin subcommands", + "url": "https://github.com/openai/codex/commit/25dbc5f55c696a58a0e58a55e0649240c909e3ab" + } + ] + }, + "reviewed_at": "2026-06-08T08:07:33Z", + "observed_change": "Codex added successful stdout JSON output for plugin add/remove and plugin marketplace add/list/upgrade/remove commands while preserving existing human-readable output.", + "changed_surfaces": [ + "codex plugin add and remove CLI flags and stdout formatting", + "codex plugin marketplace add/list/upgrade/remove CLI flags and stdout formatting", + "plugin and marketplace outcome serialization", + "CLI integration tests for JSON outputs" + ], + "user_visible_path": "Users and automation can pass --json to supported plugin and marketplace subcommands to receive structured success output instead of parsing human-readable text.", + "control_plane_relevance": "Decodex and plugin-management automation can consume Codex plugin command results as JSON when installing, listing, upgrading, or removing plugin marketplaces.", + "compatibility_risk": "The PR says --json changes successful stdout only and keeps existing error/stderr behavior unchanged, so callers still need existing error handling for failures.", + "adoption_opportunity": "Replace any Decodex parsing of plugin command prose with --json calls for supported successful plugin and marketplace operations.", + "community_value": "This is a practical public explainer candidate because it gives plugin operators a concrete machine-readable CLI path.", + "deprecated_or_breaking_notes": "No existing human-readable output is removed; --json is additive for successful stdout.", + "confidence": "confirmed", + "evidence": [ + "PR #26631 says it adds --json output for codex plugin add/remove and plugin marketplace add/list/upgrade/remove while keeping human-readable output and error behavior unchanged.", + "codex-rs/cli/src/plugin_cmd.rs adds --json flags to AddPluginArgs and RemovePluginArgs and serializes PluginInstallOutcome on success.", + "codex-rs/cli/src/marketplace_cmd.rs adds --json handling for marketplace add, list, upgrade, and remove commands.", + "codex-rs/cli/tests/plugin_cli.rs adds JSON tests for plugin add/remove and marketplace list paths.", + "codex-rs/cli/tests/marketplace_add.rs, marketplace_remove.rs, and marketplace_upgrade.rs add JSON stdout assertions for marketplace operations.", + "The normalized bundle artifacts/github/bundles/openai-codex-pr-26631.json records 6 changed files for the merged PR." + ], + "caveats": "The JSON mode covers successful stdout; failure handling and stderr behavior remain the same per the PR body.", + "next_actions": [ + { + "type": "upstream_impact", + "reason": "Machine-readable plugin command output is a Decodex plugin automation adoption candidate." + }, + { + "type": "social_candidate", + "reason": "The change has a concrete try path and clear value for plugin operators." + } + ] +} diff --git a/artifacts/github/social-candidates/openai-codex-pr-26450.json b/artifacts/github/social-candidates/openai-codex-pr-26450.json new file mode 100644 index 000000000..d967e0393 --- /dev/null +++ b/artifacts/github/social-candidates/openai-codex-pr-26450.json @@ -0,0 +1,54 @@ +{ + "schema": "social_candidate/v1", + "slug": "openai-codex-pr-26450", + "repo": "openai/codex", + "channel": "x", + "target_account": "decodexspace", + "mode": "operator_impact", + "priority": "high", + "audience": "Codex app-server and Desktop integrators", + "candidate_text": [ + "Codex added experimental app-server RPC remoteControl/pairing/status so Desktop can poll whether a QR or manual pairing code was claimed. PR: https://github.com/openai/codex/pull/26450" + ], + "source_refs": { + "upstream_reviews": [ + "artifacts/github/reviews/openai-codex-pr-26450.review.json" + ], + "upstream_impacts": [ + "artifacts/github/impact/openai-codex-pr-26450.json" + ], + "urls": [ + "https://github.com/openai/codex/pull/26450", + "https://github.com/openai/codex/pull/26449" + ] + }, + "evidence_notes": [ + "PR #26450 registers experimental remoteControl/pairing/status in app-server v2.", + "The request accepts exactly one of pairingCode or manualPairingCode and returns claimed.", + "The app-server README and JSON-RPC tests cover the new method." + ], + "claims": [ + { + "text": "Codex added an experimental app-server RPC for remote-control pairing status.", + "evidence": "artifacts/github/reviews/openai-codex-pr-26450.review.json", + "confidence": "confirmed" + }, + { + "text": "The method lets clients check whether a QR or manual pairing code has been claimed.", + "evidence": "artifacts/github/impact/openai-codex-pr-26450.json", + "confidence": "confirmed" + } + ], + "decision": { + "worthiness": "publish", + "reason": "The PR adds a concrete experimental app-server method with a clear Desktop pairing UX path.", + "idempotency_key": "x:decodexspace:openai-codex-pr-26450:operator_impact" + }, + "caveats": [ + "Preserve the experimental app-server label.", + "Do not imply Decodex has already adopted the RPC." + ], + "next_steps": [ + "Let Publisher automation decide whether to reserve or post this after repository checks pass." + ] +} diff --git a/artifacts/github/social-candidates/openai-codex-pr-26552.json b/artifacts/github/social-candidates/openai-codex-pr-26552.json new file mode 100644 index 000000000..d5980a9c5 --- /dev/null +++ b/artifacts/github/social-candidates/openai-codex-pr-26552.json @@ -0,0 +1,54 @@ +{ + "schema": "social_candidate/v1", + "slug": "openai-codex-pr-26552", + "repo": "openai/codex", + "channel": "x", + "target_account": "decodexspace", + "mode": "operator_impact", + "priority": "high", + "audience": "Codex app-server integrators", + "candidate_text": [ + "Codex now requires app-server runtimeWorkspaceRoots to be absolute in thread/turn requests. If you mirror v2 calls, resolve roots before sending them: https://github.com/openai/codex/pull/26552" + ], + "source_refs": { + "upstream_reviews": [ + "artifacts/github/reviews/openai-codex-pr-26552.review.json" + ], + "upstream_impacts": [ + "artifacts/github/impact/openai-codex-pr-26552.json" + ], + "urls": [ + "https://github.com/openai/codex/pull/26552", + "https://github.com/openai/codex/pull/26532" + ] + }, + "evidence_notes": [ + "PR #26552 changes runtimeWorkspaceRoots request fields to AbsolutePathBuf.", + "The app-server README now says runtimeWorkspaceRoots paths must be absolute.", + "TUI and exec request builders pass absolute workspace roots directly." + ], + "claims": [ + { + "text": "runtimeWorkspaceRoots in app-server thread and turn requests now require absolute roots.", + "evidence": "artifacts/github/reviews/openai-codex-pr-26552.review.json", + "confidence": "confirmed" + }, + { + "text": "Integrators should resolve runtime workspace roots before sending app-server v2 calls.", + "evidence": "artifacts/github/impact/openai-codex-pr-26552.json", + "confidence": "confirmed" + } + ], + "decision": { + "worthiness": "publish", + "reason": "The PR changes a protocol-facing app-server path contract with clear integrator migration value.", + "idempotency_key": "x:decodexspace:openai-codex-pr-26552:operator_impact" + }, + "caveats": [ + "Mention that the PR is stacked on #26532 when longer context is available.", + "Do not present this as a general end-user UI change." + ], + "next_steps": [ + "Let Publisher automation decide whether to reserve or post this after repository checks pass." + ] +} diff --git a/artifacts/github/social-candidates/openai-codex-pr-26631.json b/artifacts/github/social-candidates/openai-codex-pr-26631.json new file mode 100644 index 000000000..b539930bd --- /dev/null +++ b/artifacts/github/social-candidates/openai-codex-pr-26631.json @@ -0,0 +1,53 @@ +{ + "schema": "social_candidate/v1", + "slug": "openai-codex-pr-26631", + "repo": "openai/codex", + "channel": "x", + "target_account": "decodexspace", + "mode": "practical_explainer", + "priority": "high", + "audience": "Codex plugin operators and automation authors", + "candidate_text": [ + "Codex plugin commands now have --json for successful stdout on add/remove and marketplace add/list/upgrade/remove. Human output stays unchanged. PR: https://github.com/openai/codex/pull/26631" + ], + "source_refs": { + "upstream_reviews": [ + "artifacts/github/reviews/openai-codex-pr-26631.review.json" + ], + "upstream_impacts": [ + "artifacts/github/impact/openai-codex-pr-26631.json" + ], + "urls": [ + "https://github.com/openai/codex/pull/26631" + ] + }, + "evidence_notes": [ + "PR #26631 adds --json to plugin add/remove and marketplace add/list/upgrade/remove.", + "The PR states successful stdout changes only when --json is used.", + "CLI tests parse JSON stdout for the new plugin and marketplace paths." + ], + "claims": [ + { + "text": "Supported Codex plugin and marketplace commands now have successful stdout JSON output.", + "evidence": "artifacts/github/reviews/openai-codex-pr-26631.review.json", + "confidence": "confirmed" + }, + { + "text": "Human-readable output and failure stderr behavior are unchanged unless --json is used for a success path.", + "evidence": "artifacts/github/impact/openai-codex-pr-26631.json", + "confidence": "confirmed" + } + ], + "decision": { + "worthiness": "publish", + "reason": "The PR gives plugin operators a concrete machine-readable CLI workflow.", + "idempotency_key": "x:decodexspace:openai-codex-pr-26631:practical_explainer" + }, + "caveats": [ + "Keep the claim scoped to successful stdout output.", + "Do not imply plugin runtime behavior changed." + ], + "next_steps": [ + "Let Publisher automation decide whether to reserve or post this after repository checks pass." + ] +}