diff --git a/artifacts/github/bundles/openai-codex-pr-22879.json b/artifacts/github/bundles/openai-codex-pr-22879.json new file mode 100644 index 000000000..3328af474 --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-22879.json @@ -0,0 +1,131 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "canvrno-oai", + "committed_at": "2026-05-15T18:09:02Z", + "message": "reject Esc steer submission during /review", + "sha": "900347bbffae41f08467ae2ff7552ea3564847fe", + "url": "https://github.com/openai/codex/commit/900347bbffae41f08467ae2ff7552ea3564847fe" + }, + { + "author": "canvrno-oai", + "committed_at": "2026-05-15T18:15:31Z", + "message": "snapshot", + "sha": "80f3514fe4fa2d0c811797571ac8e813ed28c10d", + "url": "https://github.com/openai/codex/commit/80f3514fe4fa2d0c811797571ac8e813ed28c10d" + }, + { + "author": "canvrno-oai", + "committed_at": "2026-05-15T18:46:58Z", + "message": "Updated snapshot with new text", + "sha": "95d77fadad869b547af91f67bebdfc40d9927675", + "url": "https://github.com/openai/codex/commit/95d77fadad869b547af91f67bebdfc40d9927675" + }, + { + "author": "canvrno-oai", + "committed_at": "2026-05-15T19:11:44Z", + "message": "snap metadata", + "sha": "7f8f4e5d1a414d102075fa0fe87acdfff7f12f46", + "url": "https://github.com/openai/codex/commit/7f8f4e5d1a414d102075fa0fe87acdfff7f12f46" + }, + { + "author": "canvrno-oai", + "committed_at": "2026-05-16T02:00:27Z", + "message": "retry turn interrupts after active-turn mismatch - Ctrl + C case", + "sha": "375aab3440badf14d4f94ce5bb672fa800fea228", + "url": "https://github.com/openai/codex/commit/375aab3440badf14d4f94ce5bb672fa800fea228" + }, + { + "author": "canvrno-oai", + "committed_at": "2026-05-26T20:00:33Z", + "message": "Set active turn for review threads", + "sha": "061e1ad76c24a244534a5f27f70ae713b7d610b2", + "url": "https://github.com/openai/codex/commit/061e1ad76c24a244534a5f27f70ae713b7d610b2" + }, + { + "author": "canvrno-oai", + "committed_at": "2026-05-26T22:08:05Z", + "message": "Let lifecycle notifications update active turn cache", + "sha": "bbdb159af09fb5fbf4c672c7e9679a41725f6e7c", + "url": "https://github.com/openai/codex/commit/bbdb159af09fb5fbf4c672c7e9679a41725f6e7c" + } + ], + "default_branch": "main", + "docs_refs": [], + "examples_refs": [], + "extracted_flags": [ + "TUI", + "JSONRPCE", + "REVIEW_STEER_UNAVAILABLE_MESSAGE", + "NONE" + ], + "files": [ + { + "additions": 19, + "deletions": 0, + "patch_excerpt": "@@ -680,6 +680,25 @@ fn archived_session_guidance(err: &color_eyre::eyre::Report) -> Option {\n Some(message.to_string())\n }\n \n+fn active_turn_interrupt_race(error: &TypedRequestError) -> Option {\n+ let TypedRequestError::Server { method, source } = error else {\n+ return None;\n+ };\n+ if method != \"turn/interrupt\" {\n+ return None;\n+ }\n+ let mismatch_prefix = \"expected active turn id \";\n+ let mismatch_separator = \" but found \";\n+ Some(\n+ source\n+ .message\n+ .strip_prefix(mismatch_prefix)?\n+ .split_once(mismatch_separator)?\n+ .1\n+ .to_string(),\n+ )\n+}\n+\n impl App {\n pub fn chatwidget_init_for_forked_or_resumed_thread(\n &self,", + "path": "codex-rs/tui/src/app.rs", + "status": "modified" + }, + { + "additions": 17, + "deletions": 0, + "patch_excerpt": "@@ -4614,6 +4614,23 @@ fn active_turn_steer_race_extracts_actual_turn_id_from_mismatch() {\n );\n }\n \n+#[test]\n+fn active_turn_interrupt_race_extracts_actual_turn_id_from_mismatch() {\n+ let error = TypedRequestError::Server {\n+ method: \"turn/interrupt\".to_string(),\n+ source: JSONRPCErrorError {\n+ code: -32602,\n+ message: \"expected active turn id turn-expected but found turn-actual\".to_string(),\n+ data: None,\n+ },\n+ };\n+\n+ assert_eq!(\n+ active_turn_interrupt_race(&error),\n+ Some(\"turn-actual\".to_string())\n+ );\n+}\n+\n #[tokio::test]\n async fn fresh_session_config_uses_current_service_tier() {\n let mut app = make_test_app().await;", + "path": "codex-rs/tui/src/app/tests.rs", + "status": "modified" + }, + { + "additions": 38, + "deletions": 3, + "patch_excerpt": "@@ -500,9 +500,39 @@ impl App {\n match op {\n AppCommand::Interrupt { .. } => {\n if let Some(turn_id) = self.active_turn_id_for_thread(thread_id).await {\n- app_server.turn_interrupt(thread_id, turn_id).await?;\n+ let mut interrupt_turn_id = turn_id;\n+ for retried_after_turn_mismatch in [false, true] {\n+ match app_server\n+ .turn_interrupt(thread_id, interrupt_turn_id.clone())\n+ .await\n+ {\n+ Ok(()) => return Ok(true),\n+ Err(error) if !retried_after_turn_mismatch => {\n+ let Some(actual_turn_id) = active_turn_interrupt_race(&error)\n+ else {\n+ return Err(er...", + "path": "codex-rs/tui/src/app/thread_routing.rs", + "status": "modified" + }, + { + "additions": 6, + "deletions": 4, + "patch_excerpt": "@@ -736,7 +736,7 @@ impl AppServerSession {\n &mut self,\n thread_id: ThreadId,\n turn_id: String,\n- ) -> Result<()> {\n+ ) -> std::result::Result<(), TypedRequestError> {\n let request_id = self.next_request_id();\n let _: TurnInterruptResponse = self\n .client\n@@ -747,12 +747,14 @@ impl AppServerSession {\n turn_id,\n },\n })\n- .await\n- .wrap_err(\"turn/interrupt failed in TUI\")?;\n+ .await?;\n Ok(())\n }\n \n- pub(crate) async fn startup_interrupt(&mut self, thread_id: ThreadId) -> Result<()> {\n+ pub(crate) async fn startup_interrupt(\n+ &mut self,\n+ thread_id: ThreadId,\n+ ) -> std::result::Result<(), TypedRequestError> {\n self.turn_interrupt(thread_id, String::new()).await\n }", + "path": "codex-rs/tui/src/app_server_session.rs", + "status": "modified" + }, + { + "additions": 14, + "deletions": 0, + "patch_excerpt": "@@ -112,6 +112,20 @@ impl ChatWidget {\n return;\n }\n \n+ const REVIEW_STEER_UNAVAILABLE_MESSAGE: &str = \"Steer messages aren't supported during /review. Press Ctrl+C now to cancel the review.\";\n+\n+ if self.chat_keymap.interrupt_turn.is_pressed(key_event)\n+ && self.review.is_review_mode\n+ && (!self.input_queue.pending_steers.is_empty()\n+ || !self.input_queue.rejected_steers_queue.is_empty())\n+ && self.bottom_pane.is_task_running()\n+ && self.bottom_pane.no_modal_or_popup_active()\n+ && !self.should_handle_vim_insert_escape(key_event)\n+ {\n+ self.add_warning_message(REVIEW_STEER_UNAVAILABLE_MESSAGE.to_string());\n+ return;\n+ }\n+\n if self.chat_keymap.interrupt_turn.is_pressed(key_event)\n && !self.input_queue.pending_steers.is_empty()\n ...", + "path": "codex-rs/tui/src/chatwidget/interaction.rs", + "status": "modified" + }, + { + "additions": 4, + "deletions": 4, + "patch_excerpt": "@@ -1,7 +1,7 @@\n ---\n source: tui/src/chatwidget/tests/review_mode.rs\n-expression: lines_to_single_string(last)\n+assertion_line: 307\n+expression: last\n ---\n-⚠ Steer messages aren't supported during /review. Send your message after the\n- review finishes, or press Ctrl+C now to cancel the review.\n-\n+⚠ Steer messages aren't supported during /review. Press Ctrl+C now to cancel the\n+ review.", + "path": "codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__review_submission_warning_snapshot.snap", + "status": "modified" + }, + { + "additions": 23, + "deletions": 0, + "patch_excerpt": "@@ -285,6 +285,29 @@ async fn steer_rejection_queues_review_follow_up_before_existing_queued_messages\n }\n }\n \n+#[tokio::test]\n+async fn esc_with_review_queued_steers_shows_warning_and_does_not_interrupt() {\n+ let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await;\n+ chat.thread_id = Some(ThreadId::new());\n+ handle_turn_started(&mut chat, \"turn-1\");\n+ handle_entered_review_mode(&mut chat, \"feature branch\");\n+ let _ = drain_insert_history(&mut rx);\n+ chat.input_queue\n+ .pending_steers\n+ .push_back(pending_steer(\"review follow-up\"));\n+ chat.refresh_pending_input_preview();\n+\n+ chat.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE));\n+\n+ assert!(!chat.input_queue.submit_pending_steers_after_interrupt);\n+ assert_eq!(chat.input_queue.pending_steers.len(), 1);\n+ assert_no_submit_op(&mut op_rx);\n...", + "path": "codex-rs/tui/src/chatwidget/tests/review_mode.rs", + "status": "modified" + } + ], + "linked_issues": [ + "#22815" + ], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "This changes the `/review` escape path so `Esc` no longer behaves like the normal queued-follow-up interrupt flow while a review is running. Steering is not currently supported in `/review` mode, without this change users are able to attempt a steer but it leads to a crash (see #22815). If the user has already tried to send additional guidance during `/review`, the TUI now keeps the review running and shows a warning that steer messages are not supported in that mode, while still pointing users to `Ctrl+C` if they actually want to cancel. It also adds regression coverage for the review-specific warning behavior. When users do cancel with Ctrl+C during /review, the TUI now tolerates the active-turn race that can happen during review handoff, and any queued steer messages are restored to the composer instead of being discarded.\r\n\r\n- Special-case `Esc` during an active `/review` when follow-up steer input is pending or has already been deferred.\r\n- Show a clear warning instead of interrupting the running review.\r\n- Make the Ctrl+C cancel path during /review resilient to active-turn races, while preserving any queued steer text by restoring it to the composer.\r\n- Add review-mode test coverage for the warning path.\r\n\r\n## Testing\r\n\r\n1. Start a `/review` with a diff large enough that the review stays active for more than a few seconds. \r\n\r\n2. While the review is still running, type a follow-up / steer message, submit it, and then press `Esc`. \r\n Before: `Esc` causes the TUI to close abruptly. \r\n After: the review keeps running and the transcript shows a warning that steer messages are not supported during `/review`, with guidance to use `Ctrl+C` if you want to cancel.\r\n\r\n3. Press `Ctrl+C` if you actually want to stop the review. \r\n Before: (after restarting the test since Pt. 2 crashed) this is the intentional cancellation path. \r\n After: this remains the intentional cancellation path, and any queued follow-up steer text is restored to the composer instead of being lost.\r\n \r\n## Note:\r\n`/review` mode explicitly does not support steering at this time (as noted in `turn_processer.rs`, if we want to explore that in the future this code will need to be modified). This change keeps unsupported steer attempts from crashing the TUI and preserves queued follow-up text if the user cancels with Ctrl+C.", + "labels": [], + "merged_at": "2026-06-09T16:41:58Z", + "number": 22879, + "state": "merged", + "title": "fix: Prevent /review crash when entering Esc on steer message", + "url": "https://github.com/openai/codex/pull/22879" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/bundles/openai-codex-pr-25177.json b/artifacts/github/bundles/openai-codex-pr-25177.json new file mode 100644 index 000000000..f9e1c4161 --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-25177.json @@ -0,0 +1,119 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "canvrno-oai", + "committed_at": "2026-05-29T23:04:19Z", + "message": "Ensure cloud_requirements persist after /new, /clear, /side, etc.", + "sha": "074c237d6b2f061e02273af5b8ba2d7869020e10", + "url": "https://github.com/openai/codex/commit/074c237d6b2f061e02273af5b8ba2d7869020e10" + }, + { + "author": "canvrno-oai", + "committed_at": "2026-05-30T00:15:25Z", + "message": "fix type mismatch in new test", + "sha": "eb22256674028348ce7cb5ff6ed3b5365c11091e", + "url": "https://github.com/openai/codex/commit/eb22256674028348ce7cb5ff6ed3b5365c11091e" + }, + { + "author": "canvrno-oai", + "committed_at": "2026-05-30T00:19:24Z", + "message": "Make cloud requirements reload regression fail on refresh errors", + "sha": "dfcc2221c8b46a2390a982d48ef1426aadcc4a2b", + "url": "https://github.com/openai/codex/commit/dfcc2221c8b46a2390a982d48ef1426aadcc4a2b" + }, + { + "author": "canvrno-oai", + "committed_at": "2026-06-08T17:48:21Z", + "message": "Use cloud config bundle for TUI reloads", + "sha": "c25d9987b95c0f55aeac3fc963a4d4087bf173d2", + "url": "https://github.com/openai/codex/commit/c25d9987b95c0f55aeac3fc963a4d4087bf173d2" + }, + { + "author": "canvrno-oai", + "committed_at": "2026-06-08T17:56:27Z", + "message": "Merge branch 'main' into canvrno/ensure_cloud_config_load", + "sha": "666fae92fc838030f95254738138e047298f718e", + "url": "https://github.com/openai/codex/commit/666fae92fc838030f95254738138e047298f718e" + }, + { + "author": "canvrno-oai", + "committed_at": "2026-06-09T00:57:05Z", + "message": "Restore config build cancellation semantics", + "sha": "95e0f15865134edec8b6cc97f9983631b2607d0f", + "url": "https://github.com/openai/codex/commit/95e0f15865134edec8b6cc97f9983631b2607d0f" + }, + { + "author": "canvrno-oai", + "committed_at": "2026-06-09T00:58:19Z", + "message": "Merge branch 'main' into canvrno/ensure_cloud_config_load", + "sha": "12556519e8796dc575eedbac190b42e779e608e2", + "url": "https://github.com/openai/codex/commit/12556519e8796dc575eedbac190b42e779e608e2" + } + ], + "default_branch": "main", + "docs_refs": [], + "examples_refs": [], + "extracted_flags": [ + "TUI" + ], + "files": [ + { + "additions": 5, + "deletions": 0, + "patch_excerpt": "@@ -130,6 +130,7 @@ use codex_app_server_protocol::Turn;\n use codex_app_server_protocol::TurnError as AppServerTurnError;\n use codex_app_server_protocol::TurnStatus;\n use codex_app_server_protocol::WriteStatus;\n+use codex_config::CloudConfigBundleLoader;\n use codex_config::ConfigLayerStackOrdering;\n use codex_config::LoaderOverrides;\n use codex_config::types::ApprovalsReviewer;\n@@ -490,6 +491,7 @@ pub(crate) struct App {\n cli_kv_overrides: Vec<(String, TomlValue)>,\n harness_overrides: ConfigOverrides,\n loader_overrides: LoaderOverrides,\n+ cloud_config_bundle: CloudConfigBundleLoader,\n runtime_approval_policy_override: Option,\n runtime_permission_profile_override: Option,\n \n@@ -720,6 +722,7 @@ impl App {\n cli_kv_overrides: Vec<(String, TomlValue)>,\n harness_overrides: ConfigOverrides,\n loader_...", + "path": "codex-rs/tui/src/app.rs", + "status": "modified" + }, + { + "additions": 64, + "deletions": 2, + "patch_excerpt": "@@ -34,7 +34,8 @@ impl App {\n .codex_home(self.config.codex_home.to_path_buf())\n .cli_overrides(self.cli_kv_overrides.clone())\n .harness_overrides(overrides)\n- .loader_overrides(self.loader_overrides.clone());\n+ .loader_overrides(self.loader_overrides.clone())\n+ .cloud_config_bundle(self.cloud_config_bundle.clone());\n build_config_on_runtime_worker(\n builder,\n format!(\"Failed to rebuild config for cwd {cwd_display}\"),\n@@ -55,7 +56,8 @@ impl App {\n .codex_home(self.config.codex_home.to_path_buf())\n .cli_overrides(self.cli_kv_overrides.clone())\n .harness_overrides(overrides)\n- .loader_overrides(self.loader_overrides.clone());\n+ .loader_overrides(self.loader_overrides.clone())\n+ .cloud_config_bundle(self.cloud_config_bundle...", + "path": "codex-rs/tui/src/app/config_persistence.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -25,6 +25,7 @@ pub(super) async fn make_test_app() -> App {\n cli_kv_overrides: Vec::new(),\n harness_overrides: ConfigOverrides::default(),\n loader_overrides: LoaderOverrides::without_managed_config_for_tests(),\n+ cloud_config_bundle: CloudConfigBundleLoader::default(),\n runtime_approval_policy_override: None,\n runtime_permission_profile_override: None,\n file_search,", + "path": "codex-rs/tui/src/app/test_support.rs", + "status": "modified" + }, + { + "additions": 2, + "deletions": 0, + "patch_excerpt": "@@ -3945,6 +3945,7 @@ async fn make_test_app() -> App {\n cli_kv_overrides: Vec::new(),\n harness_overrides: ConfigOverrides::default(),\n loader_overrides: LoaderOverrides::without_managed_config_for_tests(),\n+ cloud_config_bundle: CloudConfigBundleLoader::default(),\n runtime_approval_policy_override: None,\n runtime_permission_profile_override: None,\n file_search,\n@@ -4009,6 +4010,7 @@ async fn make_test_app_with_channels() -> (\n cli_kv_overrides: Vec::new(),\n harness_overrides: ConfigOverrides::default(),\n loader_overrides: LoaderOverrides::without_managed_config_for_tests(),\n+ cloud_config_bundle: CloudConfigBundleLoader::default(),\n runtime_approval_policy_override: None,\n runtime_permission_profile_override: None,\n file_search,", + "path": "codex-rs/tui/src/app/tests.rs", + "status": "modified" + }, + { + "additions": 3, + "deletions": 0, + "patch_excerpt": "@@ -9,6 +9,7 @@ use crate::legacy_core::config::edit::ConfigEditsBuilder;\n use crate::tui;\n use codex_app_server_protocol::ExternalAgentConfigDetectParams;\n use codex_app_server_protocol::ExternalAgentConfigMigrationItem;\n+use codex_config::CloudConfigBundleLoader;\n use codex_features::Feature;\n use color_eyre::eyre::Result;\n use color_eyre::eyre::WrapErr;\n@@ -248,6 +249,7 @@ pub(crate) async fn handle_external_agent_config_migration_prompt_if_needed(\n config: &mut Config,\n cli_kv_overrides: &[(String, TomlValue)],\n harness_overrides: &ConfigOverrides,\n+ cloud_config_bundle: &CloudConfigBundleLoader,\n entered_trust_nux: bool,\n ) -> Result {\n if !should_show_external_agent_config_migration_prompt(config, entered_trust_nux) {\n@@ -321,6 +323,7 @@ pub(crate) async fn handle_external_agent_config_migration_prompt_if_needed(\n ...", + "path": "codex-rs/tui/src/external_agent_config_migration_startup.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -1849,6 +1849,7 @@ async fn run_ratatui_app(\n cli_kv_overrides.clone(),\n overrides.clone(),\n loader_overrides.clone(),\n+ cloud_config_bundle,\n prompt,\n images,\n session_selection,", + "path": "codex-rs/tui/src/lib.rs", + "status": "modified" + } + ], + "linked_issues": [], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "Fixes a TUI regression where thread transitions such as `/new` and `/clear` could rebuild config without the cloud requirements loader, allowing users to fall back to non-cloud-managed settings. The config refresh path now preserves cloud requirements during thread reinitialization, and config loading is moved off the deep TUI event stack to avoid stack-overflow crashes during those reloads.\r\n\r\n - Passes the cloud requirements loader through TUI config rebuild paths.\r\n - Keeps cloud requirements applied for `/new`, `/clear`, `/fork`, side conversations, and session picker transitions.\r\n - Runs config building on a Tokio task so reloads do not occur on the deep TUI caller stack.\r\n - Adds regression coverage that cloud requirements survive thread-transition config refreshes.\r\n\r\n## Test/Repro:\r\n - Start Codex with a cloud requirement applied.\r\n - Use `/new` or `/clear`.\r\n - The refreshed/fresh-session config should still include the cloud requirements\r\n \r\nThis can be tested with any config item, at this moment for oai staff the easiest item to test is the `mentions_v2` feature. This is currently enabled in cloud requirements, but is not enabled by default. As a result, prior to these changes that feature is disabled after `/new` or `/clear`. Testing the same steps with a binary from this branch should not drop the feature enablement.", + "labels": [], + "merged_at": "2026-06-09T01:08:48Z", + "number": 25177, + "state": "merged", + "title": "Preserve cloud requirements across TUI thread resets", + "url": "https://github.com/openai/codex/pull/25177" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/bundles/openai-codex-pr-27184.json b/artifacts/github/bundles/openai-codex-pr-27184.json new file mode 100644 index 000000000..7a140f33f --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-27184.json @@ -0,0 +1,433 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "jif-oai", + "committed_at": "2026-06-09T12:58:40Z", + "message": "skills: load selected executor capability roots", + "sha": "5d7823925c88f09568bafda637fccd92b56a9b6a", + "url": "https://github.com/openai/codex/commit/5d7823925c88f09568bafda637fccd92b56a9b6a" + }, + { + "author": "jif-oai", + "committed_at": "2026-06-09T13:21:19Z", + "message": "fix CI", + "sha": "0f384f1b4d7e7542f1202fc966b8c6475fa27d0f", + "url": "https://github.com/openai/codex/commit/0f384f1b4d7e7542f1202fc966b8c6475fa27d0f" + }, + { + "author": "jif-oai", + "committed_at": "2026-06-09T13:39:35Z", + "message": "some small fixes", + "sha": "f0df7cb06b999489e989767092ecc767fa7c30cc", + "url": "https://github.com/openai/codex/commit/f0df7cb06b999489e989767092ecc767fa7c30cc" + }, + { + "author": "jif-oai", + "committed_at": "2026-06-09T13:48:25Z", + "message": "Fix executor skills Clippy violations", + "sha": "fec64281b4558807c592629485958b02f0869d55", + "url": "https://github.com/openai/codex/commit/fec64281b4558807c592629485958b02f0869d55" + }, + { + "author": "jif-oai", + "committed_at": "2026-06-09T14:01:43Z", + "message": "Fix executor skill locator test setup", + "sha": "f607c8696bc512aefbcf3fc038d6c53d77d4663c", + "url": "https://github.com/openai/codex/commit/f607c8696bc512aefbcf3fc038d6c53d77d4663c" + }, + { + "author": "jif-oai", + "committed_at": "2026-06-09T14:24:22Z", + "message": "Normalize Windows executor skill test paths", + "sha": "2400fd9198b798764a5090410c8761a69fd61734", + "url": "https://github.com/openai/codex/commit/2400fd9198b798764a5090410c8761a69fd61734" + }, + { + "author": "jif-oai", + "committed_at": "2026-06-09T16:50:46Z", + "message": "process comments", + "sha": "ed85bf407760a9dcc0ebb6971dc0505c1d4f3a1a", + "url": "https://github.com/openai/codex/commit/ed85bf407760a9dcc0ebb6971dc0505c1d4f3a1a" + } + ], + "default_branch": "main", + "docs_refs": [ + "codex-rs/app-server/README.md" + ], + "examples_refs": [], + "extracted_flags": [ + "CCA", + "MCP", + "HTTP", + "SKILL", + "API", + "GENERATED", + "CODE", + "NOT", + "MODIFY", + "HAND", + "BUILT_IN_PERMISSION_PROFILE_DANGER_FULL_ACCESS", + "BUILT_IN_PERMISSION_PROFILE_WORKSPACE", + "JSONRPCR", + "READ_TIMEOUT", + "SKILL_NAME", + "SKILL_MARKER", + "EXECUTOR_SKILL_BODY_MARKER", + "LOCAL_SKILL_MARKER", + "LOCAL_SKILL_BODY_MARKER", + "FEATURES", + "SERVICE_TIER_DEFAULT_REQUEST_VALUE", + "TEST_INSTALLATION_ID", + "MAX_SKILL_NAME_BYTES", + "MAX_SKILL_PATH_BYTES", + "HOST_AUTHORITY_ID", + "SKILLS_INSTRUCTIONS_CLOSE_TAG", + "SKILLS_INSTRUCTIONS_OPEN_TAG", + "MAX_AVAILABLE_SKILLS_CHARS", + "MAX_MAIN_PROMPT_CHARS", + "MAX_AVAILABLE_SKILLS_BYTES", + "MAX_MAIN_PROMPT_BYTES", + "SKILL_CONTENTS", + "NEXT_TEST_ROOT_ID" + ], + "files": [ + { + "additions": 4, + "deletions": 0, + "patch_excerpt": "@@ -1994,6 +1994,7 @@ dependencies = [\n \"codex-rollout\",\n \"codex-sandboxing\",\n \"codex-shell-command\",\n+ \"codex-skills-extension\",\n \"codex-state\",\n \"codex-thread-store\",\n \"codex-tools\",\n@@ -3796,8 +3797,11 @@ dependencies = [\n \"async-trait\",\n \"codex-core\",\n \"codex-core-skills\",\n+ \"codex-exec-server\",\n \"codex-extension-api\",\n \"codex-protocol\",\n+ \"codex-utils-absolute-path\",\n+ \"codex-utils-string\",\n \"pretty_assertions\",\n \"tokio\",\n ]", + "path": "codex-rs/Cargo.lock", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -212,6 +212,7 @@ codex-sandboxing = { path = \"sandboxing\" }\n codex-secrets = { path = \"secrets\" }\n codex-shell-command = { path = \"shell-command\" }\n codex-shell-escalation = { path = \"shell-escalation\" }\n+codex-skills-extension = { path = \"ext/skills\" }\n codex-skills = { path = \"skills\" }\n codex-state = { path = \"state\" }\n codex-stdio-to-uds = { path = \"stdio-to-uds\" }", + "path": "codex-rs/Cargo.toml", + "status": "modified" + }, + { + "additions": 52, + "deletions": 0, + "patch_excerpt": "@@ -180,6 +180,36 @@\n ],\n \"type\": \"object\"\n },\n+ \"CapabilityRootLocation\": {\n+ \"description\": \"Location used to resolve a selected capability root.\",\n+ \"oneOf\": [\n+ {\n+ \"description\": \"A path owned by an execution environment.\",\n+ \"properties\": {\n+ \"environmentId\": {\n+ \"type\": \"string\"\n+ },\n+ \"path\": {\n+ \"type\": \"string\"\n+ },\n+ \"type\": {\n+ \"enum\": [\n+ \"environment\"\n+ ],\n+ \"title\": \"EnvironmentCapabilityRootLocationType\",\n+ \"type\": \"string\"\n+ }\n+ },\n+ \"required\": [\n+ \"environmentId\",\n+ \"path\",\n+ \"type\"\n+ ],\n+ \"title\": \"EnvironmentCapabilityRootLocation\",\n+ \"type\": \"object\"\n+ }\n+ ]\n+ },\n ...", + "path": "codex-rs/app-server-protocol/schema/json/ClientRequest.json", + "status": "modified" + }, + { + "additions": 52, + "deletions": 0, + "patch_excerpt": "@@ -6765,6 +6765,36 @@\n ],\n \"type\": \"string\"\n },\n+ \"CapabilityRootLocation\": {\n+ \"description\": \"Location used to resolve a selected capability root.\",\n+ \"oneOf\": [\n+ {\n+ \"description\": \"A path owned by an execution environment.\",\n+ \"properties\": {\n+ \"environmentId\": {\n+ \"type\": \"string\"\n+ },\n+ \"path\": {\n+ \"type\": \"string\"\n+ },\n+ \"type\": {\n+ \"enum\": [\n+ \"environment\"\n+ ],\n+ \"title\": \"EnvironmentCapabilityRootLocationType\",\n+ \"type\": \"string\"\n+ }\n+ },\n+ \"required\": [\n+ \"environmentId\",\n+ \"path\",\n+ \"type\"\n+ ],\n+ \"title\": \"EnvironmentCapabilityRootLocation\"...", + "path": "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json", + "status": "modified" + }, + { + "additions": 52, + "deletions": 0, + "patch_excerpt": "@@ -1087,6 +1087,36 @@\n ],\n \"type\": \"string\"\n },\n+ \"CapabilityRootLocation\": {\n+ \"description\": \"Location used to resolve a selected capability root.\",\n+ \"oneOf\": [\n+ {\n+ \"description\": \"A path owned by an execution environment.\",\n+ \"properties\": {\n+ \"environmentId\": {\n+ \"type\": \"string\"\n+ },\n+ \"path\": {\n+ \"type\": \"string\"\n+ },\n+ \"type\": {\n+ \"enum\": [\n+ \"environment\"\n+ ],\n+ \"title\": \"EnvironmentCapabilityRootLocationType\",\n+ \"type\": \"string\"\n+ }\n+ },\n+ \"required\": [\n+ \"environmentId\",\n+ \"path\",\n+ \"type\"\n+ ],\n+ \"title\": \"EnvironmentCapabilityRootLocation\",\n+ \"type\": \"object\"\n+ }\n+ ]\n+ },\n...", + "path": "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json", + "status": "modified" + }, + { + "additions": 52, + "deletions": 0, + "patch_excerpt": "@@ -64,6 +64,36 @@\n }\n ]\n },\n+ \"CapabilityRootLocation\": {\n+ \"description\": \"Location used to resolve a selected capability root.\",\n+ \"oneOf\": [\n+ {\n+ \"description\": \"A path owned by an execution environment.\",\n+ \"properties\": {\n+ \"environmentId\": {\n+ \"type\": \"string\"\n+ },\n+ \"path\": {\n+ \"type\": \"string\"\n+ },\n+ \"type\": {\n+ \"enum\": [\n+ \"environment\"\n+ ],\n+ \"title\": \"EnvironmentCapabilityRootLocationType\",\n+ \"type\": \"string\"\n+ }\n+ },\n+ \"required\": [\n+ \"environmentId\",\n+ \"path\",\n+ \"type\"\n+ ],\n+ \"title\": \"EnvironmentCapabilityRootLocation\",\n+ \"type\": \"object\"\n+ }\n+ ]\n+ },\n \"DynamicToolS...", + "path": "codex-rs/app-server-protocol/schema/json/v2/ThreadStartParams.json", + "status": "modified" + }, + { + "additions": 8, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,8 @@\n+// GENERATED CODE! DO NOT MODIFY BY HAND!\n+\n+// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.\n+\n+/**\n+ * Location used to resolve a selected capability root.\n+ */\n+export type CapabilityRootLocation = { \"type\": \"environment\", environmentId: string, path: string, };", + "path": "codex-rs/app-server-protocol/schema/typescript/v2/CapabilityRootLocation.ts", + "status": "added" + }, + { + "additions": 17, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,17 @@\n+// GENERATED CODE! DO NOT MODIFY BY HAND!\n+\n+// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.\n+import type { CapabilityRootLocation } from \"./CapabilityRootLocation\";\n+\n+/**\n+ * A user-selected root that can expose one or more runtime capabilities.\n+ */\n+export type SelectedCapabilityRoot = {\n+/**\n+ * Stable identifier supplied by the capability selection platform.\n+ */\n+id: string,\n+/**\n+ * Where the selected root can be resolved.\n+ */\n+location: CapabilityRootLocation, };", + "path": "codex-rs/app-server-protocol/schema/typescript/v2/SelectedCapabilityRoot.ts", + "status": "added" + }, + { + "additions": 2, + "deletions": 0, + "patch_excerpt": "@@ -40,6 +40,7 @@ export type { ByteRange } from \"./ByteRange\";\n export type { CancelLoginAccountParams } from \"./CancelLoginAccountParams\";\n export type { CancelLoginAccountResponse } from \"./CancelLoginAccountResponse\";\n export type { CancelLoginAccountStatus } from \"./CancelLoginAccountStatus\";\n+export type { CapabilityRootLocation } from \"./CapabilityRootLocation\";\n export type { ChatgptAuthTokensRefreshParams } from \"./ChatgptAuthTokensRefreshParams\";\n export type { ChatgptAuthTokensRefreshReason } from \"./ChatgptAuthTokensRefreshReason\";\n export type { ChatgptAuthTokensRefreshResponse } from \"./ChatgptAuthTokensRefreshResponse\";\n@@ -334,6 +335,7 @@ export type { ReviewTarget } from \"./ReviewTarget\";\n export type { SandboxMode } from \"./SandboxMode\";\n export type { SandboxPolicy } from \"./SandboxPolicy\";\n export type { SandboxWorkspaceWrite } from \"./SandboxWorkspaceWrite\";\n+export ...", + "path": "codex-rs/app-server-protocol/schema/typescript/v2/index.ts", + "status": "modified" + }, + { + "additions": 6, + "deletions": 0, + "patch_excerpt": "@@ -11,6 +11,8 @@ use super::TurnEnvironmentParams;\n use super::TurnItemsView;\n use super::shared::v2_enum_from_core;\n use codex_experimental_api_macros::ExperimentalApi;\n+pub use codex_protocol::capabilities::CapabilityRootLocation;\n+pub use codex_protocol::capabilities::SelectedCapabilityRoot;\n use codex_protocol::config_types::CollaborationMode;\n use codex_protocol::config_types::Personality;\n use codex_protocol::config_types::ReasoningSummary;\n@@ -153,6 +155,10 @@ pub struct ThreadStartParams {\n #[experimental(\"thread/start.dynamicTools\")]\n #[ts(optional = nullable)]\n pub dynamic_tools: Option>,\n+ /// Capability roots selected for this thread by the hosting platform.\n+ #[experimental(\"thread/start.selectedCapabilityRoots\")]\n+ #[ts(optional = nullable)]\n+ pub selected_capability_roots: Option>,\n /// Test-only...", + "path": "codex-rs/app-server-protocol/src/protocol/v2/thread.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -49,6 +49,7 @@ codex-hooks = { workspace = true }\n codex-otel = { workspace = true }\n codex-plugin = { workspace = true }\n codex-shell-command = { workspace = true }\n+codex-skills-extension = { workspace = true }\n codex-utils-cli = { workspace = true }\n codex-utils-pty = { workspace = true }\n codex-backend-client = { workspace = true }", + "path": "codex-rs/app-server/Cargo.toml", + "status": "modified" + }, + { + "additions": 13, + "deletions": 1, + "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`; paths must be absolute. For permissions, prefer experimental `permissions` profile selection by id; the legacy `sandbox` shorthand is still accepted but cannot be combined...", + "path": "codex-rs/app-server/README.md", + "status": "modified" + }, + { + "additions": 6, + "deletions": 0, + "patch_excerpt": "@@ -32,6 +32,7 @@ pub(crate) fn thread_extensions(\n state_db: Option,\n thread_manager: Weak,\n goal_service: Arc,\n+ executor_skill_provider: Arc,\n ) -> Arc>\n where\n S: AgentSpawner + 'static,\n@@ -51,6 +52,11 @@ where\n codex_memories_extension::install(&mut builder, codex_otel::global());\n codex_web_search_extension::install(&mut builder, auth_manager.clone());\n codex_image_generation_extension::install(&mut builder, auth_manager);\n+ codex_skills_extension::install_with_providers(\n+ &mut builder,\n+ codex_skills_extension::SkillProviders::new()\n+ .with_executor_provider(executor_skill_provider),\n+ );\n Arc::new(builder.build())\n }", + "path": "codex-rs/app-server/src/extensions.rs", + "status": "modified" + }, + { + "additions": 9, + "deletions": 1, + "patch_excerpt": "@@ -181,19 +181,27 @@ mod tests {\n .await\n .expect(\"refresh tests require state db\");\n let thread_store = thread_store_from_config(&good_config, Some(state_db.clone()));\n+ let environment_manager = Arc::new(EnvironmentManager::default_for_tests());\n+ let executor_skill_provider: Arc = Arc::new(\n+ codex_skills_extension::ExecutorSkillProvider::new_with_restriction_product(\n+ Arc::clone(&environment_manager),\n+ SessionSource::Exec.restriction_product(),\n+ ),\n+ );\n let thread_manager = Arc::new_cyclic(|thread_manager| {\n ThreadManager::new(\n &good_config,\n auth_manager.clone(),\n SessionSource::Exec,\n- Arc::new(EnvironmentManager::default_for_tests()),\n+ ...", + "path": "codex-rs/app-server/src/mcp_refresh.rs", + "status": "modified" + }, + { + "additions": 9, + "deletions": 0, + "patch_excerpt": "@@ -307,6 +307,14 @@ impl MessageProcessor {\n // resumed, or forked threads to a different persistence backend/root.\n let thread_store = codex_core::thread_store_from_config(config.as_ref(), state_db.clone());\n let environment_manager_for_requests = Arc::clone(&environment_manager);\n+ let environment_manager_for_extensions = Arc::clone(&environment_manager);\n+ let restriction_product = session_source.restriction_product();\n+ let executor_skill_provider: Arc = Arc::new(\n+ codex_skills_extension::ExecutorSkillProvider::new_with_restriction_product(\n+ environment_manager_for_extensions,\n+ restriction_product,\n+ ),\n+ );\n let goal_service = Arc::new(GoalService::new());\n let thread_manager = Arc::new_cyclic(|thread_manager| {\n ...", + "path": "codex-rs/app-server/src/message_processor.rs", + "status": "modified" + }, + { + "additions": 10, + "deletions": 0, + "patch_excerpt": "@@ -1,5 +1,7 @@\n use super::*;\n use crate::error_code::method_not_found;\n+use codex_app_server_protocol::SelectedCapabilityRoot;\n+use codex_extension_api::ExtensionDataInit;\n use codex_protocol::models::BUILT_IN_PERMISSION_PROFILE_DANGER_FULL_ACCESS;\n use codex_protocol::models::BUILT_IN_PERMISSION_PROFILE_WORKSPACE;\n \n@@ -822,6 +824,7 @@ impl ThreadRequestProcessor {\n base_instructions,\n developer_instructions,\n dynamic_tools,\n+ selected_capability_roots,\n mock_experimental_field: _mock_experimental_field,\n experimental_raw_events,\n personality,\n@@ -877,6 +880,7 @@ impl ThreadRequestProcessor {\n config,\n typesafe_overrides,\n dynamic_tools,\n+ selected_capability_roots.unwrap_or_default(),\n session_start_source,\n ...", + "path": "codex-rs/app-server/src/request_processors/thread_processor.rs", + "status": "modified" + }, + { + "additions": 148, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,148 @@\n+use std::time::Duration;\n+\n+use anyhow::Result;\n+use app_test_support::TestAppServer;\n+use app_test_support::to_response;\n+use codex_app_server_protocol::CapabilityRootLocation;\n+use codex_app_server_protocol::JSONRPCResponse;\n+use codex_app_server_protocol::RequestId;\n+use codex_app_server_protocol::SelectedCapabilityRoot;\n+use codex_app_server_protocol::ThreadStartParams;\n+use codex_app_server_protocol::ThreadStartResponse;\n+use codex_app_server_protocol::TurnStartParams;\n+use codex_app_server_protocol::UserInput;\n+use core_test_support::responses;\n+use tempfile::TempDir;\n+use tokio::time::timeout;\n+\n+const READ_TIMEOUT: Duration = Duration::from_secs(10);\n+const SKILL_NAME: &str = \"demo-plugin:deploy\";\n+const SKILL_MARKER: &str = \"EXECUTOR_SKILL_BODY_MARKER\";\n+const LOCAL_SKILL_MARKER: &str = \"LOCAL_SKILL_BODY_MARKER\";\n+\n+#[tokio::test]\n+async fn selected_executor_r...", + "path": "codex-rs/app-server/tests/suite/v2/executor_skills.rs", + "status": "added" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -12,6 +12,7 @@ mod connection_handling_websocket;\n #[cfg(unix)]\n mod connection_handling_websocket_unix;\n mod dynamic_tools;\n+mod executor_skills;\n mod experimental_api;\n mod experimental_feature_list;\n mod external_agent_config;", + "path": "codex-rs/app-server/tests/suite/v2/mod.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -793,6 +793,7 @@ async fn skills_changed_notification_is_emitted_after_skill_change() -> Result<(\n thread_source: None,\n dynamic_tools: None,\n environments: None,\n+ selected_capability_roots: None,\n mock_experimental_field: None,\n experimental_raw_events: false,\n })", + "path": "codex-rs/app-server/tests/suite/v2/skills_list.rs", + "status": "modified" + }, + { + "additions": 16, + "deletions": 8, + "patch_excerpt": "@@ -169,8 +169,8 @@ where\n let mut file_systems_by_skill_path: HashMap> =\n HashMap::new();\n for root in roots {\n- let root_path = canonicalize_for_skill_identity(&root.path);\n let fs = root.file_system;\n+ let root_path = canonicalize_for_skill_identity(fs.as_ref(), &root.path).await;\n let skills_before_root = outcome.skills.len();\n discover_skills_under_root(\n fs.as_ref(),\n@@ -471,8 +471,13 @@ fn dedupe_skill_roots_by_path(roots: &mut Vec) {\n roots.retain(|root| seen.insert(root.path.clone()));\n }\n \n-fn canonicalize_for_skill_identity(path: &AbsolutePathBuf) -> AbsolutePathBuf {\n- path.canonicalize().unwrap_or_else(|_| path.clone())\n+async fn canonicalize_for_skill_identity(\n+ fs: &dyn ExecutorFileSystem,\n+ path: &AbsolutePathBuf,\n+) -> AbsolutePathBuf {\n...", + "path": "codex-rs/core-skills/src/loader.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -103,6 +103,7 @@ pub(crate) async fn run_codex_thread_interactive(\n parent_rollout_thread_trace: codex_rollout_trace::ThreadTraceContext::disabled(),\n parent_trace: None,\n environment_selections: parent_ctx.environments.clone(),\n+ thread_extension_init: codex_extension_api::ExtensionDataInit::default(),\n analytics_events_client: Some(parent_session.services.analytics_events_client.clone()),\n thread_store: Arc::clone(&parent_session.services.thread_store),\n attestation_provider: parent_session.services.attestation_provider.clone(),", + "path": "codex-rs/core/src/codex_delegate.rs", + "status": "modified" + }, + { + "additions": 4, + "deletions": 0, + "patch_excerpt": "@@ -51,6 +51,7 @@ use codex_config::types::OAuthCredentialsStoreMode;\n use codex_exec_server::Environment;\n use codex_exec_server::EnvironmentManager;\n use codex_exec_server::FileSystemSandboxContext;\n+use codex_extension_api::ExtensionDataInit;\n use codex_extension_api::PromptSlot;\n use codex_features::FEATURES;\n use codex_features::Feature;\n@@ -417,6 +418,7 @@ pub(crate) struct CodexSpawnArgs {\n pub(crate) user_shell_override: Option,\n pub(crate) parent_trace: Option,\n pub(crate) environment_selections: ResolvedTurnEnvironments,\n+ pub(crate) thread_extension_init: ExtensionDataInit,\n pub(crate) analytics_events_client: Option,\n pub(crate) thread_store: Arc,\n pub(crate) attestation_provider: Option>,\n@@ -497,6 +499,7 @@ impl Codex {\n parent_rollout_t...", + "path": "codex-rs/core/src/session/mod.rs", + "status": "modified" + }, + { + "additions": 6, + "deletions": 2, + "patch_excerpt": "@@ -4,6 +4,7 @@ use crate::agents_md::LoadedAgentsMd;\n use crate::config::ConstraintError;\n use crate::skills::SkillError;\n use crate::state::ActiveTurn;\n+use codex_extension_api::ExtensionDataInit;\n use codex_protocol::SessionId;\n use codex_protocol::config_types::SERVICE_TIER_DEFAULT_REQUEST_VALUE;\n use codex_protocol::config_types::ServiceTier;\n@@ -487,6 +488,7 @@ impl Session {\n plugins_manager: Arc,\n mcp_manager: Arc,\n extensions: Arc>,\n+ thread_extension_init: ExtensionDataInit,\n agent_control: AgentControl,\n environment_manager: Arc,\n analytics_events_client: Option,\n@@ -961,8 +963,10 @@ impl Session {\n );\n let session_extension_data =\n codex_extension_api:...", + "path": "codex-rs/core/src/session/session.rs", + "status": "modified" + }, + { + "additions": 3, + "deletions": 0, + "patch_excerpt": "@@ -4690,6 +4690,7 @@ async fn session_new_fails_when_zsh_fork_enabled_without_packaged_zsh() {\n plugins_manager,\n mcp_manager,\n Arc::new(codex_extension_api::ExtensionRegistryBuilder::new().build()),\n+ codex_extension_api::ExtensionDataInit::default(),\n AgentControl::default(),\n Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()),\n /*analytics_events_client*/ None,\n@@ -5030,6 +5031,7 @@ async fn make_session_with_config_and_rx(\n plugins_manager,\n mcp_manager,\n Arc::new(codex_extension_api::ExtensionRegistryBuilder::new().build()),\n+ codex_extension_api::ExtensionDataInit::default(),\n AgentControl::default(),\n Arc::new(codex_exec_server::EnvironmentManager::default_for_tests()),\n /*analytics_events_client*/ None,\n@@ -5131,6 +5133,7 @@ async fn make_session_with_h...", + "path": "codex-rs/core/src/session/tests.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -731,6 +731,7 @@ async fn guardian_subagent_does_not_inherit_parent_exec_policy_rules() {\n environment_selections: ResolvedTurnEnvironments {\n turn_environments: Vec::new(),\n },\n+ thread_extension_init: codex_extension_api::ExtensionDataInit::default(),\n analytics_events_client: None,\n thread_store,\n attestation_provider: None,", + "path": "codex-rs/core/src/session/tests/guardian_tests.rs", + "status": "modified" + }, + { + "additions": 15, + "deletions": 0, + "patch_excerpt": "@@ -21,6 +21,7 @@ use codex_app_server_protocol::ThreadHistoryBuilder;\n use codex_app_server_protocol::TurnStatus;\n use codex_core_plugins::PluginsManager;\n use codex_exec_server::EnvironmentManager;\n+use codex_extension_api::ExtensionDataInit;\n use codex_extension_api::ExtensionRegistry;\n use codex_extension_api::empty_extension_registry;\n use codex_features::Feature;\n@@ -182,6 +183,7 @@ pub struct StartThreadOptions {\n pub metrics_service_name: Option,\n pub parent_trace: Option,\n pub environments: Vec,\n+ pub thread_extension_init: ExtensionDataInit,\n }\n \n pub(crate) struct ResumeThreadWithHistoryOptions {\n@@ -576,6 +578,7 @@ impl ThreadManager {\n metrics_service_name: None,\n parent_trace: None,\n environments,\n+ thread_extension_init: ExtensionDataInit::default(),\n })...", + "path": "codex-rs/core/src/thread_manager.rs", + "status": "modified" + }, + { + "additions": 79, + "deletions": 0, + "patch_excerpt": "@@ -331,6 +331,7 @@ async fn start_thread_rejects_explicit_local_environment_when_default_provider_i\n environment_id: \"local\".to_string(),\n cwd: config.cwd.clone(),\n }],\n+ thread_extension_init: Default::default(),\n })\n .await;\n let err = match result {\n@@ -368,6 +369,7 @@ async fn start_thread_keeps_internal_threads_hidden_from_normal_lookups() {\n metrics_service_name: None,\n parent_trace: None,\n environments: Vec::new(),\n+ thread_extension_init: Default::default(),\n })\n .await\n .expect(\"internal thread should start\");\n@@ -384,6 +386,81 @@ async fn start_thread_keeps_internal_threads_hidden_from_normal_lookups() {\n assert!(manager.list_thread_ids().await.is_empty());\n }\n \n+#[tokio::test]\n+async fn start_thread_seeds_extension_data_before_l...", + "path": "codex-rs/core/src/thread_manager_tests.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -757,6 +757,7 @@ async fn subagent_stop_replaces_stop_and_skips_internal_subagents() -> Result<()\n metrics_service_name: None,\n parent_trace: None,\n environments: Vec::new(),\n+ thread_extension_init: Default::default(),\n })\n .await?;", + "path": "codex-rs/core/tests/suite/subagent_notifications.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -59,3 +59,4 @@ pub use registry::ExtensionRegistry;\n pub use registry::ExtensionRegistryBuilder;\n pub use registry::empty_extension_registry;\n pub use state::ExtensionData;\n+pub use state::ExtensionDataInit;", + "path": "codex-rs/ext/extension-api/src/lib.rs", + "status": "modified" + }, + { + "additions": 32, + "deletions": 1, + "patch_excerpt": "@@ -7,6 +7,32 @@ use std::sync::PoisonError;\n \n type ErasedData = Arc;\n \n+/// Typed values supplied before an [`ExtensionData`] scope is created.\n+///\n+/// Hosts consume this value once to seed a scope before lifecycle contributors\n+/// run. It does not install extensions or provide persistence.\n+#[derive(Debug, Default)]\n+pub struct ExtensionDataInit {\n+ entries: HashMap,\n+}\n+\n+impl ExtensionDataInit {\n+ /// Creates an empty extension data initializer.\n+ pub fn new() -> Self {\n+ Self::default()\n+ }\n+\n+ /// Stores `value` as the initial attachment of type `T`.\n+ pub fn insert(&mut self, value: T) -> Option>\n+ where\n+ T: Any + Send + Sync,\n+ {\n+ self.entries\n+ .insert(TypeId::of::(), Arc::new(value))\n+ .map(downcast_data)\n+ }\n+}\n+\n /// Typed extension-owned data at...", + "path": "codex-rs/ext/extension-api/src/state.rs", + "status": "modified" + }, + { + "additions": 3, + "deletions": 0, + "patch_excerpt": "@@ -17,8 +17,11 @@ workspace = true\n async-trait = { workspace = true }\n codex-core = { workspace = true }\n codex-core-skills = { workspace = true }\n+codex-exec-server = { workspace = true }\n codex-extension-api = { workspace = true }\n codex-protocol = { workspace = true }\n+codex-utils-absolute-path = { workspace = true }\n+codex-utils-string = { workspace = true }\n \n [dev-dependencies]\n pretty_assertions = { workspace = true }", + "path": "codex-rs/ext/skills/Cargo.toml", + "status": "modified" + }, + { + "additions": 32, + "deletions": 3, + "patch_excerpt": "@@ -1,4 +1,5 @@\n use codex_core_skills::model::SkillDependencies;\n+use codex_exec_server::EnvironmentPathRef;\n \n /// Source authority that owns a skill package and must be used to read it.\n #[derive(Clone, Debug, PartialEq, Eq, Hash)]\n@@ -56,9 +57,37 @@ impl SkillAuthority {\n #[derive(Clone, Debug, PartialEq, Eq, Hash)]\n pub struct SkillPackageId(pub String);\n \n-/// Opaque resource id inside a skill package.\n+/// Opaque resource id inside a skill package, optionally bound to the\n+/// environment path that owns its contents.\n #[derive(Clone, Debug, PartialEq, Eq, Hash)]\n-pub struct SkillResourceId(pub String);\n+pub struct SkillResourceId {\n+ id: String,\n+ environment_path: Option,\n+}\n+\n+impl SkillResourceId {\n+ pub fn new(id: impl Into) -> Self {\n+ Self {\n+ id: id.into(),\n+ environment_path: None,\n+ }\n+ }\n+\n+ p...", + "path": "codex-rs/ext/skills/src/catalog.rs", + "status": "modified" + }, + { + "additions": 81, + "deletions": 23, + "patch_excerpt": "@@ -6,27 +6,32 @@ use codex_core_skills::SkillInstructions;\n use codex_core_skills::injection::InjectedHostSkillPrompts;\n use codex_core_skills::injection::SkillInjection;\n use codex_extension_api::ConfigContributor;\n+use codex_extension_api::ContextContributor;\n use codex_extension_api::ContextualUserFragment;\n use codex_extension_api::ExtensionData;\n use codex_extension_api::ExtensionEventSink;\n use codex_extension_api::ExtensionRegistryBuilder;\n+use codex_extension_api::PromptFragment;\n use codex_extension_api::ThreadLifecycleContributor;\n use codex_extension_api::ThreadStartInput;\n use codex_extension_api::TurnInputContext;\n use codex_extension_api::TurnInputContributor;\n+use codex_protocol::capabilities::SelectedCapabilityRoot;\n use codex_protocol::protocol::Event;\n use codex_protocol::protocol::EventMsg;\n use codex_protocol::protocol::WarningEvent;\n \n-use crate::catalog::SkillAutho...", + "path": "codex-rs/ext/skills/src/extension.rs", + "status": "modified" + }, + { + "additions": 2, + "deletions": 0, + "patch_excerpt": "@@ -8,6 +8,8 @@ mod state;\n \n pub use extension::install;\n pub use extension::install_with_providers;\n+pub use provider::ExecutorSkillProvider;\n pub use provider::HostSkillProvider;\n+pub use provider::SkillProvider;\n pub use sources::SkillProviderSource;\n pub use sources::SkillProviders;", + "path": "codex-rs/ext/skills/src/lib.rs", + "status": "modified" + }, + { + "additions": 4, + "deletions": 1, + "patch_excerpt": "@@ -2,9 +2,11 @@ use std::future::Future;\n use std::pin::Pin;\n use std::sync::Arc;\n \n+mod executor;\n mod host;\n \n use codex_core_skills::HostLoadedSkills;\n+use codex_protocol::capabilities::SelectedCapabilityRoot;\n \n use crate::catalog::SkillAuthority;\n use crate::catalog::SkillCatalog;\n@@ -14,12 +16,13 @@ use crate::catalog::SkillReadResult;\n use crate::catalog::SkillResourceId;\n use crate::catalog::SkillSearchResult;\n \n+pub use executor::ExecutorSkillProvider;\n pub use host::HostSkillProvider;\n \n #[derive(Clone, Debug)]\n pub struct SkillListQuery {\n pub turn_id: String,\n- pub executor_authorities: Vec,\n+ pub executor_roots: Vec,\n pub host: Option>,\n pub include_host_skills: bool,\n pub include_bundled_skills: bool,", + "path": "codex-rs/ext/skills/src/provider.rs", + "status": "modified" + }, + { + "additions": 197, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,197 @@\n+use std::path::PathBuf;\n+use std::sync::Arc;\n+\n+use codex_core_skills::SkillMetadata;\n+use codex_core_skills::filter_skill_load_outcome_for_product;\n+use codex_core_skills::loader::SkillRoot;\n+use codex_core_skills::loader::load_skills_from_roots;\n+use codex_exec_server::EnvironmentManager;\n+use codex_exec_server::EnvironmentPathRef;\n+use codex_protocol::capabilities::CapabilityRootLocation;\n+use codex_protocol::protocol::Product;\n+use codex_protocol::protocol::SkillScope;\n+use codex_utils_absolute_path::AbsolutePathBuf;\n+\n+use crate::catalog::SkillAuthority;\n+use crate::catalog::SkillCatalog;\n+use crate::catalog::SkillCatalogEntry;\n+use crate::catalog::SkillPackageId;\n+use crate::catalog::SkillProviderError;\n+use crate::catalog::SkillReadResult;\n+use crate::catalog::SkillResourceId;\n+use crate::catalog::SkillSearchResult;\n+use crate::catalog::SkillSourceKind;\n+use cra...", + "path": "codex-rs/ext/skills/src/provider/executor.rs", + "status": "added" + }, + { + "additions": 5, + "deletions": 5, + "patch_excerpt": "@@ -55,12 +55,12 @@ impl SkillProvider for HostSkillProvider {\n };\n let Some(skill) = host_loaded_skills.outcome().skills.iter().find(|skill| {\n let skill_path = skill.path_to_skills_md.to_string_lossy();\n- skill_path == request.resource.0.as_str()\n- || skill_path.replace('\\\\', \"/\") == request.resource.0\n+ skill_path == request.resource.as_str()\n+ || skill_path.replace('\\\\', \"/\") == request.resource.as_str()\n }) else {\n return Err(SkillProviderError::new(format!(\n \"host skill resource is not loaded: {}\",\n- request.resource.0\n+ request.resource.as_str()\n )));\n };\n \n@@ -70,7 +70,7 @@ impl SkillProvider for HostSkillProvider {\n .map_err(|err| {\n ...", + "path": "codex-rs/ext/skills/src/provider/host.rs", + "status": "modified" + }, + { + "additions": 15, + "deletions": 14, + "patch_excerpt": "@@ -2,11 +2,14 @@ use codex_core_skills::render_available_skills_body;\n use codex_extension_api::ContextualUserFragment;\n use codex_protocol::protocol::SKILLS_INSTRUCTIONS_CLOSE_TAG;\n use codex_protocol::protocol::SKILLS_INSTRUCTIONS_OPEN_TAG;\n+use codex_utils_string::take_bytes_at_char_boundary;\n \n use crate::catalog::SkillCatalog;\n \n-const MAX_AVAILABLE_SKILLS_CHARS: usize = 8_000;\n-const MAX_MAIN_PROMPT_CHARS: usize = 40_000;\n+const MAX_AVAILABLE_SKILLS_BYTES: usize = 8_000;\n+const MAX_MAIN_PROMPT_BYTES: usize = 8_000;\n+pub(crate) const MAX_SKILL_NAME_BYTES: usize = 256;\n+pub(crate) const MAX_SKILL_PATH_BYTES: usize = 1_024;\n \n #[derive(Debug, Clone, PartialEq, Eq)]\n pub(crate) struct AvailableSkillsFragment {\n@@ -32,7 +35,7 @@ impl ContextualUserFragment for AvailableSkillsFragment {\n }\n \n pub(crate) fn available_skills_fragment(catalog: &SkillCatalog) -> Option bool {\n- entry.main_prompt.0 == path\n+ entry.main_prompt.as_str() == path\n || entry.id.0 == path\n || entry\n .display_path\n .as_deref()\n- .is_some_and(|display_path| display_path == path)\n+ .is_some_and(|display_path| normalize_skill_path(display_path) == path)\n }\n \n fn path_is_skill(path: &str) -> bool {", + "path": "codex-rs/ext/skills/src/selection.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 1, + "patch_excerpt": "@@ -46,7 +46,7 @@ impl SkillProviderSource {\n fn should_list(&self, query: &SkillListQuery) -> bool {\n match &self.kind {\n SkillSourceKind::Host => query.include_host_skills,\n- SkillSourceKind::Executor => !query.executor_authorities.is_empty(),\n+ SkillSourceKind::Executor => !query.executor_roots.is_empty(),\n SkillSourceKind::Remote => query.include_remote_skills,\n SkillSourceKind::Custom(_) => true,\n }", + "path": "codex-rs/ext/skills/src/sources.rs", + "status": "modified" + }, + { + "additions": 11, + "deletions": 1, + "patch_excerpt": "@@ -1,4 +1,5 @@\n use codex_core::config::Config;\n+use codex_protocol::capabilities::SelectedCapabilityRoot;\n use std::sync::Mutex;\n \n use crate::catalog::SkillCatalog;\n@@ -22,12 +23,17 @@ impl SkillsExtensionConfig {\n #[derive(Debug)]\n pub(crate) struct SkillsThreadState {\n config: Mutex,\n+ selected_roots: Vec,\n }\n \n impl SkillsThreadState {\n- pub(crate) fn new(config: SkillsExtensionConfig) -> Self {\n+ pub(crate) fn new(\n+ config: SkillsExtensionConfig,\n+ selected_roots: Vec,\n+ ) -> Self {\n Self {\n config: Mutex::new(config),\n+ selected_roots,\n }\n }\n \n@@ -44,6 +50,10 @@ impl SkillsThreadState {\n .lock()\n .unwrap_or_else(std::sync::PoisonError::into_inner) = config;\n }\n+\n+ pub(crate) fn selected_roots(&self) -> &[Se...", + "path": "codex-rs/ext/skills/src/state.rs", + "status": "modified" + }, + { + "additions": 337, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,337 @@\n+use std::io;\n+use std::path::Path;\n+use std::sync::Arc;\n+use std::sync::atomic::AtomicUsize;\n+use std::sync::atomic::Ordering;\n+\n+use async_trait::async_trait;\n+use codex_core_skills::HostLoadedSkills;\n+use codex_core_skills::loader::SkillRoot;\n+use codex_core_skills::loader::load_skills_from_roots;\n+use codex_exec_server::CopyOptions;\n+use codex_exec_server::CreateDirectoryOptions;\n+use codex_exec_server::EnvironmentManager;\n+use codex_exec_server::ExecutorFileSystem;\n+use codex_exec_server::FileMetadata;\n+use codex_exec_server::FileSystemResult;\n+use codex_exec_server::FileSystemSandboxContext;\n+use codex_exec_server::ReadDirectoryEntry;\n+use codex_exec_server::RemoveOptions;\n+use codex_protocol::capabilities::CapabilityRootLocation;\n+use codex_protocol::capabilities::SelectedCapabilityRoot;\n+use codex_protocol::protocol::SkillScope;\n+use codex_skills_extension::Exec...", + "path": "codex-rs/ext/skills/tests/executor_file_system_authority.rs", + "status": "added" + }, + { + "additions": 135, + "deletions": 64, + "patch_excerpt": "@@ -14,7 +14,8 @@ use codex_extension_api::ExtensionData;\n use codex_extension_api::ExtensionRegistryBuilder;\n use codex_extension_api::ThreadStartInput;\n use codex_extension_api::TurnInputContext;\n-use codex_extension_api::TurnInputEnvironment;\n+use codex_protocol::capabilities::CapabilityRootLocation;\n+use codex_protocol::capabilities::SelectedCapabilityRoot;\n use codex_protocol::protocol::SKILLS_INSTRUCTIONS_OPEN_TAG;\n use codex_protocol::protocol::SessionSource;\n use codex_protocol::user_input::UserInput;\n@@ -112,6 +113,7 @@ async fn installed_extension_loads_host_skills_from_legacy_roots() -> TestResult\n .await;\n \n assert_eq!(2, fragments.len());\n+ assert_eq!(\"developer\", fragments[0].role());\n assert!(fragments[0].render().contains(\"demo\"));\n assert!(fragments[0].render().contains(&skill_prompt_path));\n assert_eq!(\"user\", fragments[1].role());\n@@ -128,42 ...", + "path": "codex-rs/ext/skills/tests/skills_extension.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -251,6 +251,7 @@ impl MemoryStartupContext {\n metrics_service_name: None,\n parent_trace: None,\n environments,\n+ thread_extension_init: Default::default(),\n })\n .await?;", + "path": "codex-rs/memories/write/src/runtime.rs", + "status": "modified" + }, + { + "additions": 30, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,30 @@\n+use schemars::JsonSchema;\n+use serde::Deserialize;\n+use serde::Serialize;\n+use ts_rs::TS;\n+\n+/// A user-selected root that can expose one or more runtime capabilities.\n+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]\n+#[serde(rename_all = \"camelCase\")]\n+#[ts(export_to = \"v2/\")]\n+pub struct SelectedCapabilityRoot {\n+ /// Stable identifier supplied by the capability selection platform.\n+ pub id: String,\n+ /// Where the selected root can be resolved.\n+ pub location: CapabilityRootLocation,\n+}\n+\n+/// Location used to resolve a selected capability root.\n+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]\n+#[serde(tag = \"type\", rename_all = \"camelCase\")]\n+#[ts(tag = \"type\")]\n+#[ts(export_to = \"v2/\")]\n+pub enum CapabilityRootLocation {\n+ /// A path owned by an execution environment.\n+ Environment {\n+ ...", + "path": "codex-rs/protocol/src/capabilities.rs", + "status": "added" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -9,6 +9,7 @@ pub use session_id::SessionId;\n pub use thread_id::ThreadId;\n pub use tool_name::ToolName;\n pub mod approvals;\n+pub mod capabilities;\n pub mod config_types;\n pub mod dynamic_tools;\n pub mod error;", + "path": "codex-rs/protocol/src/lib.rs", + "status": "modified" + } + ], + "linked_issues": [], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "## Why\r\n\r\nCCA is moving toward a split runtime where the orchestrator may not have a filesystem, while executors can expose preinstalled plugins and skills. A thread therefore needs to select capabilities without asking app-server or core to interpret executor-owned paths through the orchestrator's filesystem.\r\n\r\nThe longer-term model is broader than executor skills:\r\n\r\n- A plugin is a bundle of skills, MCP servers, connectors/apps, and hooks.\r\n- A plugin root can be local, executor-owned, or hosted by a backend.\r\n- Components inside one plugin can use different access and execution mechanisms. A skill may be read from a filesystem or through backend tools; an HTTP MCP server can run without an executor; a stdio MCP server or hook needs an execution environment.\r\n- Core should carry generic extension initialization data. The extension that owns a component should discover it, expose it to the model, and invoke it through the appropriate runtime.\r\n\r\nThis PR establishes that architecture through one complete vertical: selecting a root on an executor, discovering the skills beneath it, exposing those skills to the model, and reading an explicitly invoked `SKILL.md` through the same executor.\r\n\r\n## Contract\r\n\r\n`thread/start` gains an experimental `selectedCapabilityRoots` field:\r\n\r\n```json\r\n{\r\n \"selectedCapabilityRoots\": [\r\n {\r\n \"id\": \"deploy-plugin@1\",\r\n \"location\": {\r\n \"type\": \"environment\",\r\n \"environmentId\": \"workspace\",\r\n \"path\": \"/opt/codex/plugins/deploy\"\r\n }\r\n }\r\n ]\r\n}\r\n```\r\n\r\nThe root is intentionally not classified as a \"plugin\" or \"skill\" in the API. It can point at a standalone skill, a directory containing several skills, or a plugin containing skills and other components. This PR only teaches the skills extension how to consume it; later extensions can resolve MCP, connector, and hook components from the same selection.\r\n\r\nThe platform-supplied `id` is stable selection identity. The location says which runtime owns the root and gives that runtime an opaque path. App-server does not inspect or canonicalize the path.\r\n\r\n## What changed\r\n\r\n### Generic thread extension initialization\r\n\r\nApp-server converts selected roots into `ExtensionDataInit`. Core carries that generic initialization value until the final thread ID is known, then creates thread-scoped `ExtensionData` before lifecycle contributors run.\r\n\r\nThis keeps `Session` and core independent of the capability-selection contract. The initialization value is consumed during construction; it is not retained as another long-lived `Session` field.\r\n\r\n### Executor-backed skills\r\n\r\nThe skills extension now owns an `ExecutorSkillProvider` that:\r\n\r\n- resolves the selected environment through `EnvironmentManager`\r\n- discovers, canonicalizes, and reads skills through that environment's `ExecutorFileSystem`\r\n- contributes the bounded selected-skill catalog as stable developer context\r\n- reads an explicitly invoked skill body through the authority that listed it\r\n- warns when an environment or root is unavailable\r\n- never falls back to the orchestrator filesystem for an executor-owned root\r\n\r\nSkill catalog and instruction fragments have hard byte bounds, which also bound them below the 10K-token per-item context limit. If a selected executor skill has the same name as a legacy local skill, the executor selection owns that invocation and the local body is not injected a second time.\r\n\r\nExisting local and bundled skill loading remains in place. Omitting `selectedCapabilityRoots` therefore preserves current local-only behavior.\r\n\r\n## Current semantics\r\n\r\n- Only environment-owned locations are represented in this first contract.\r\n- Roots are resolved by the destination extension, not by app-server or core.\r\n- An unavailable executor or invalid root produces a warning and no capabilities from that root; it does not trigger a local-filesystem fallback.\r\n- Selection applies to a newly started active thread.\r\n- MCP servers, connectors, and hooks beneath a selected plugin root are not activated yet.\r\n- Selection is not yet persisted or inherited across resume, fork, or subagent creation. Existing local capabilities continue to behave as they do today in those flows.\r\n\r\n## Planned vertical follow-ups\r\n\r\n1. **Hosted HTTP MCP:** add an extension-backed HTTP MCP source that works without an executor, then replace the special-purpose MCP plugins loader with that implementation.\r\n2. **Executor MCP:** register and execute stdio MCP servers through the environment that owns the selected plugin root.\r\n3. **Backend skills:** add a hosted skill source whose catalog and bodies are accessed through extension tools rather than a filesystem.\r\n4. **Connectors and hooks:** activate those components through their owning extensions, using the same selected-root boundary and component-specific runtime.\r\n5. **Durable selection:** define the desired-selection lifecycle, persist it, and make resume, fork, and subagent inheritance explicit rather than accidental.\r\n6. **Local convergence:** incrementally route existing local plugin, skill, and MCP loading through the same extension model while preserving current local behavior.\r\n\r\nEach follow-up remains reviewable as an end-to-end capability. The platform selects roots, generic thread extension data carries the selection, and the owning extension resolves and operates its component.\r\n\r\n## Verification\r\n\r\nCoverage added for:\r\n\r\n- app-server end-to-end discovery and explicit invocation of a skill inside an executor-selected plugin root\r\n- exclusive invocation when a selected executor skill collides with a local skill name\r\n- executor filesystem authority for discovery, canonicalization, and reads\r\n- thread extension initialization before lifecycle contributors run\r\n- stable executor catalog context, explicit invocation, context rebuilding, hidden skills, and preserved host/remote catalog behavior\r\n\r\nTargeted protocol, core-skills, skills-extension, core lifecycle, and app-server executor-skill tests were run during development.\r\n", + "labels": [], + "merged_at": "2026-06-09T17:51:55Z", + "number": 27184, + "state": "merged", + "title": "Load selected executor skills through extensions", + "url": "https://github.com/openai/codex/pull/27184" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/impact/openai-codex-pr-22879.json b/artifacts/github/impact/openai-codex-pr-22879.json new file mode 100644 index 000000000..7d63cd57e --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-22879.json @@ -0,0 +1,44 @@ +{ + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-22879", + "repo": "openai/codex", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "fix: Prevent /review crash when entering Esc on steer message", + "url": "https://github.com/openai/codex/pull/22879", + "meta": "Merged 2026-06-09T16:41:58Z" + }, + { + "kind": "pull_request", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/22879", + "meta": "artifacts/github/reviews/openai-codex-pr-22879.review.json" + } + ] + }, + "observed_change": "Codex `/review` now rejects Esc-based queued steer attempts with a warning instead of crashing, while Ctrl+C cancellation retries once after an active-turn mismatch.", + "public_signal_decision": "publish", + "control_plane_impact": "watch", + "publisher_angle": "practical_explainer", + "confidence": "confirmed", + "evidence": [ + "The upstream review records the review-mode Esc guard and exact warning path.", + "The TUI interrupt path retries once when the server reports a different active turn during review cancellation.", + "Regression coverage asserts Esc does not submit an interrupt op while pending review steers remain queued.", + "The PR states `/review` steering remains unsupported." + ], + "candidate_followups": [ + "Keep Decodex review guidance explicit that `/review` steering is unsupported and Ctrl+C is the cancellation path.", + "Watch Decodex review tooling for assumptions that Esc during review should interrupt or steer." + ], + "social_notes": [ + "Public copy should frame this as a `/review` stability and guidance fix, not as new steering support.", + "Mention Ctrl+C as the intended cancellation path." + ], + "caveats": [ + "The change does not add `/review` steering.", + "The compatibility implication is primarily operator workflow behavior, not a protocol schema change." + ] +} diff --git a/artifacts/github/impact/openai-codex-pr-25177.json b/artifacts/github/impact/openai-codex-pr-25177.json new file mode 100644 index 000000000..55c8aa407 --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-25177.json @@ -0,0 +1,43 @@ +{ + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-25177", + "repo": "openai/codex", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "Preserve cloud requirements across TUI thread resets", + "url": "https://github.com/openai/codex/pull/25177", + "meta": "Merged 2026-06-09T01:08:48Z" + }, + { + "kind": "pull_request", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/25177", + "meta": "artifacts/github/reviews/openai-codex-pr-25177.review.json" + } + ] + }, + "observed_change": "Codex TUI config rebuilds for thread transitions now preserve the cloud config bundle loader so cloud requirements survive fresh-session and thread-reset paths.", + "public_signal_decision": "skip", + "control_plane_impact": "watch", + "publisher_angle": "none", + "confidence": "confirmed", + "evidence": [ + "The upstream review records the cloud config bundle being threaded through TUI config rebuild paths.", + "Regression coverage asserts cloud requirements survive the refresh used by `/new`, `/clear`, `/fork`, side conversations, and session picker paths.", + "No app-server protocol schema or public command contract changed.", + "The PR's easiest repro depends on cloud requirements and an internal feature example." + ], + "candidate_followups": [ + "Watch future Codex managed-config changes before Decodex assumes thread reset clears cloud-managed requirements.", + "Keep any Decodex TUI interop or reset guidance aligned with cloud requirements persisting across TUI transitions." + ], + "social_notes": [ + "Skip standalone public posting for now because the clearest repro is cloud-managed and partly internal." + ], + "caveats": [ + "The behavior is most relevant to cloud-managed Codex sessions.", + "No Decodex implementation surface changes immediately." + ] +} diff --git a/artifacts/github/impact/openai-codex-pr-27184.json b/artifacts/github/impact/openai-codex-pr-27184.json new file mode 100644 index 000000000..6fce14db2 --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-27184.json @@ -0,0 +1,46 @@ +{ + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-27184", + "repo": "openai/codex", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "Load selected executor skills through extensions", + "url": "https://github.com/openai/codex/pull/27184", + "meta": "Merged 2026-06-09T17:51:55Z" + }, + { + "kind": "pull_request", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/27184", + "meta": "artifacts/github/reviews/openai-codex-pr-27184.review.json" + } + ] + }, + "observed_change": "Codex app-server `thread/start` now accepts experimental `selectedCapabilityRoots` and uses extension initialization to load explicitly selected executor-owned skills without falling back to the orchestrator filesystem.", + "public_signal_decision": "publish", + "control_plane_impact": "candidate", + "publisher_angle": "operator_impact", + "confidence": "confirmed", + "evidence": [ + "The upstream review records the new `selectedCapabilityRoots` thread/start field and `CapabilityRootLocation::Environment` protocol shape.", + "App-server converts selected roots into `ExtensionDataInit` before thread creation.", + "The executor skill provider resolves selected environments and reads skill bodies through the environment filesystem.", + "App-server and skills-extension tests prove selected executor skills are model-visible and colliding local skill bodies are not injected." + ], + "candidate_followups": [ + "Create a Decodex Control Plane issue to evaluate `selectedCapabilityRoots` as the handoff format for executor-owned plugins and skills.", + "Audit current plugin, skill, and MCP selection paths for assumptions that app-server or the orchestrator can canonicalize selected plugin roots.", + "Track upstream follow-ups for MCP, connectors, hooks, durable selection, resume, fork, and subagent inheritance before treating the model as complete." + ], + "social_notes": [ + "Public copy should call the field experimental and scoped to executor-owned skills in this PR.", + "Avoid implying MCP servers, connectors, hooks, persistence, resume, fork, or subagent inheritance are already implemented." + ], + "caveats": [ + "Only environment-owned selected roots are represented in this first contract.", + "Unavailable environments or invalid roots warn rather than falling back to local filesystem reads.", + "Existing local and bundled skill loading remains when no selected roots are supplied." + ] +} diff --git a/artifacts/github/review-queue/openai-codex-latest.json b/artifacts/github/review-queue/openai-codex-latest.json index b8b00b649..ec1f398f7 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": 17, - "high": 9, - "low": 2, - "normal": 12, + "critical": 19, + "high": 10, + "low": 0, + "normal": 11, "published_subjects_seen": 0, "recent_commits_scanned": 40, "subjects_queued": 40 }, - "generated_at": "2026-06-09T20:05:04.380793Z", + "generated_at": "2026-06-10T02:06:16.841927Z", "repo": "openai/codex", "schema": "upstream_review_queue/v1", "source": { @@ -17,267 +17,6 @@ "signals_dir": "site/src/content/signals" }, "subjects": [ - { - "attention_flags": [ - "breaking_change", - "new_feature", - "protocol_change", - "release_packaging" - ], - "changed_file_count": 10, - "commit_shas": [ - "3a77fbcc7217e2a49e7447017ac4932625e55912", - "cbb1d21dfa72d84973bcc8b58a6deaca53808e0f", - "2a416e92a12e43d044e4a39096f1825a29b11d3f", - "1188ee05a5b82e99bc653820a27c8830d66ab7bf", - "fd0f44bb07220d2ae600bca3c38b2af596ae21e1", - "583174aca7660c1a872ac7aead5abb335dec1f65" - ], - "committed_at": "2026-06-08T18:16:32Z", - "next_step": "ai_review_required", - "pr_number": 26637, - "pr_url": "https://github.com/openai/codex/pull/26637", - "review_priority": "critical", - "review_reason": "Needs AI review for breaking_change, new_feature, protocol_change, release_packaging.", - "sample_paths": [ - "codex-rs/app-server/src/message_processor.rs", - "codex-rs/app-server/src/request_processors.rs", - "codex-rs/app-server/src/request_processors/external_agent_config_processor.rs", - "codex-rs/app-server/src/request_processors/external_agent_session_import.rs", - "codex-rs/app-server/tests/suite/v2/external_agent_config.rs", - "codex-rs/external-agent-sessions/src/export.rs", - "codex-rs/external-agent-sessions/src/ledger.rs", - "codex-rs/external-agent-sessions/src/ledger_tests.rs", - "codex-rs/external-agent-sessions/src/lib.rs", - "codex-rs/external-agent-sessions/src/records.rs" - ], - "source_state": "merged", - "subject_id": "26637", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "config_hooks", - "tests_ci" - ], - "title": "[codex] Speed up external agent session imports", - "url": "https://github.com/openai/codex/pull/26637" - }, - { - "attention_flags": [ - "breaking_change", - "deprecated_removed", - "new_feature", - "protocol_change" - ], - "changed_file_count": 3, - "commit_shas": [ - "a4520a312a6ac3509088827dc96bc5c20ec96ef6" - ], - "committed_at": "2026-06-08T18:37:55Z", - "next_step": "ai_review_required", - "pr_number": 27009, - "pr_url": "https://github.com/openai/codex/pull/27009", - "review_priority": "critical", - "review_reason": "Needs AI review for breaking_change, deprecated_removed, new_feature, protocol_change.", - "sample_paths": [ - "codex-rs/cli/src/marketplace_cmd.rs", - "codex-rs/cli/src/plugin_cmd.rs", - "codex-rs/cli/tests/plugin_cli.rs" - ], - "source_state": "merged", - "subject_id": "27009", - "subject_kind": "pr", - "surface_hints": [ - "cli_tui", - "mcp_plugins", - "tests_ci" - ], - "title": "[plugins] Expose marketplace source in marketplace list JSON", - "url": "https://github.com/openai/codex/pull/27009" - }, - { - "attention_flags": [ - "breaking_change", - "deprecated_removed", - "new_feature", - "protocol_change", - "security_policy" - ], - "changed_file_count": 8, - "commit_shas": [ - "d6528ccc954f1768a3d7d080bba8162b59d982a1", - "bf84a984d0233936cf29c72dd60d704b9182d569", - "8e14f2d413ef8a826d45a0602573148c6c7ac358" - ], - "committed_at": "2026-06-08T18:59:50Z", - "next_step": "ai_review_required", - "pr_number": 26230, - "pr_url": "https://github.com/openai/codex/pull/26230", - "review_priority": "critical", - "review_reason": "Needs AI review for breaking_change, deprecated_removed, new_feature, protocol_change, security_policy.", - "sample_paths": [ - "codex-rs/app-server-protocol/src/protocol/v2/shared.rs", - "codex-rs/app-server-protocol/src/protocol/v2/tests.rs", - "codex-rs/config/src/loader/mod.rs", - "codex-rs/core/src/tools/handlers/multi_agents_common.rs", - "codex-rs/core/src/tools/handlers/multi_agents_tests.rs", - "codex-rs/protocol/src/config_types.rs", - "codex-rs/tui/src/app/tests.rs", - "codex-rs/tui/src/debug_config.rs" - ], - "source_state": "merged", - "subject_id": "26230", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "cli_tui", - "config_hooks", - "tests_ci" - ], - "title": "fix: preserve auto review across config and delegation", - "url": "https://github.com/openai/codex/pull/26230" - }, - { - "attention_flags": [ - "auth_account", - "deprecated_removed", - "new_feature", - "protocol_change", - "rate_limit", - "release_packaging", - "security_policy" - ], - "changed_file_count": 90, - "commit_shas": [ - "534befc48bc2eec3bd002a31f5ac2c3e23a1f29a", - "bf26b031e535e3fb925bfacf41daf44ef87231ee", - "e0f10fa7e41d0cbfe3504b38c735e1de866cab27", - "09dccdf652b9c4c4995517a0191679836d69b026", - "4e459c4fcc4b6c10438e8e5e12430e64f3dd43ba", - "68060899b6a45f5d67c84938ffc906545c5e3b41", - "e239da0a36a20367e88e0f9d7d71b5cfb6cb5ca0", - "505dbae2c71a5886d6e12ff1082279fef26d94fd", - "d63b1a125f6e97fd1d4f26232455343207521b89", - "d98e9b984c0325d31fb1b58969e279fbedd09aca", - "fc6f77e19b0b41235d88a4879609a28eed97bb2b", - "6046b245a3f0efe30ca4012dec10c06c6fa32445", - "6a420d41ac70f172bb6deb9b75b6c2f5c93cdfa8", - "4923381143d028955a8542cd8c390f1505e83851", - "d10fb7bc65892d496a9e9ae0e0eed585ddd21d5f", - "acb9e264576e9d76f8438129f3eb321ff9ac2fd5", - "1c883fdb9219aff8ed78464669480a58f7745ce6", - "12e18e679d1dc46c712b87fc8f21c04ff95a8310", - "c1205d9c1a9d6fd80f6d4cea7198805c243fb9f6", - "f6e390602e97aa867a228c399846440d54d93cb3" - ], - "committed_at": "2026-06-08T20:55:15Z", - "next_step": "ai_review_required", - "pr_number": 26687, - "pr_url": "https://github.com/openai/codex/pull/26687", - "review_priority": "critical", - "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, rate_limit, release_packaging, security_policy.", - "sample_paths": [ - "codex-rs/app-server-protocol/src/protocol/v2/turn.rs", - "codex-rs/app-server/src/bespoke_event_handling.rs", - "codex-rs/app-server/src/request_processors.rs", - "codex-rs/app-server/src/request_processors/apps_processor.rs", - "codex-rs/app-server/src/request_processors/thread_lifecycle.rs", - "codex-rs/app-server/src/request_processors/thread_processor.rs", - "codex-rs/app-server/src/request_processors/thread_processor_tests.rs", - "codex-rs/app-server/src/request_processors/thread_summary.rs", - "codex-rs/app-server/src/request_processors/turn_processor.rs", - "codex-rs/core/src/agent/control_tests.rs", - "codex-rs/core/src/codex_delegate.rs", - "codex-rs/core/src/codex_thread.rs" - ], - "source_state": "merged", - "subject_id": "26687", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "cli_tui", - "config_hooks", - "mcp_plugins", - "model_provider", - "sandbox_permissions", - "tests_ci" - ], - "title": "Pair thread environment settings", - "url": "https://github.com/openai/codex/pull/26687" - }, - { - "attention_flags": [ - "breaking_change", - "deprecated_removed", - "new_feature", - "protocol_change" - ], - "changed_file_count": 6, - "commit_shas": [ - "6ca9ccf9cd12de3a88ffa2a001eb78a0b2f97c10", - "0165dbf6eda0ccb61187df6752a4e08de93f520c", - "9457965868264ba8838440a6d9ff539d830ee0af", - "2ff147fc6a4721000547e8b0d6b8ea8d97d58f24", - "c5a021feb1b677c105f0f51044311b62b18925af", - "034835589958076a97792994e22e724ad6d9a496" - ], - "committed_at": "2026-06-08T21:23:55Z", - "next_step": "ai_review_required", - "pr_number": 26486, - "pr_url": "https://github.com/openai/codex/pull/26486", - "review_priority": "critical", - "review_reason": "Needs AI review for breaking_change, deprecated_removed, new_feature, protocol_change.", - "sample_paths": [ - "codex-rs/Cargo.lock", - "codex-rs/app-server/tests/suite/v2/imagegen_extension.rs", - "codex-rs/ext/image-generation/Cargo.toml", - "codex-rs/ext/image-generation/imagegen_description.md", - "codex-rs/ext/image-generation/src/tests.rs", - "codex-rs/ext/image-generation/src/tool.rs" - ], - "source_state": "merged", - "subject_id": "26486", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "config_hooks", - "tests_ci" - ], - "title": "Route image edits through referenced file paths", - "url": "https://github.com/openai/codex/pull/26486" - }, - { - "attention_flags": [ - "breaking_change", - "deprecated_removed", - "protocol_change", - "release_packaging" - ], - "changed_file_count": 3, - "commit_shas": [ - "a65d2d5a2bc1987b53a3afab765f1240da867060" - ], - "committed_at": "2026-06-08T21:46:59Z", - "next_step": "ai_review_required", - "pr_number": 26934, - "pr_url": "https://github.com/openai/codex/pull/26934", - "review_priority": "critical", - "review_reason": "Needs AI review for breaking_change, deprecated_removed, protocol_change, release_packaging.", - "sample_paths": [ - "codex-rs/core-plugins/src/loader.rs", - "codex-rs/core-plugins/src/manager_tests.rs", - "codex-rs/core-plugins/src/marketplace.rs" - ], - "source_state": "merged", - "subject_id": "26934", - "subject_kind": "pr", - "surface_hints": [ - "mcp_plugins", - "tests_ci" - ], - "title": "[codex] Prune stale curated plugin caches", - "url": "https://github.com/openai/codex/pull/26934" - }, { "attention_flags": [ "auth_account", @@ -747,141 +486,368 @@ }, { "attention_flags": [ + "deprecated_removed", "new_feature", - "protocol_change" + "protocol_change", + "security_policy" ], - "changed_file_count": 2, + "changed_file_count": 7, "commit_shas": [ - "bd9e2cc47530cf4268e47aa2086bd969b7714503", - "5aad1bd45b793a734aed3032e4c6651310dae56a" + "766c4d531e27de9b8ec273e21f5062682fe032d5", + "08811b5e35e7d71eba040fde91d99a613bd3ba5a" ], - "committed_at": "2026-06-08T20:32:10Z", + "committed_at": "2026-06-09T20:26:00Z", "next_step": "ai_review_required", - "pr_number": 27037, - "pr_url": "https://github.com/openai/codex/pull/27037", - "review_priority": "high", - "review_reason": "Needs AI review for new_feature, protocol_change.", + "pr_number": 26711, + "pr_url": "https://github.com/openai/codex/pull/26711", + "review_priority": "critical", + "review_reason": "Needs AI review for deprecated_removed, new_feature, protocol_change, security_policy.", "sample_paths": [ - "codex-rs/core/src/config/mod.rs", - "codex-rs/core/src/tools/handlers/multi_agents_spec.rs" + "codex-rs/app-server-client/src/lib.rs", + "codex-rs/tui/prompt_for_init_command.md", + "codex-rs/tui/src/chatwidget.rs", + "codex-rs/tui/src/chatwidget/interaction.rs", + "codex-rs/tui/src/chatwidget/slash_dispatch.rs", + "codex-rs/tui/src/chatwidget/tests/slash_commands.rs", + "codex-rs/tui/src/status/helpers.rs" + ], + "source_state": "merged", + "subject_id": "26711", + "subject_kind": "pr", + "surface_hints": [ + "app_server_protocol", + "cli_tui", + "tests_ci" + ], + "title": "Reduce TUI legacy core dependencies", + "url": "https://github.com/openai/codex/pull/26711" + }, + { + "attention_flags": [ + "auth_account", + "deprecated_removed", + "new_feature", + "protocol_change", + "release_packaging" + ], + "changed_file_count": 6, + "commit_shas": [ + "a9941f5173d16907a710e49e2b083650ad78b3e3", + "e2477c12533a1f2f8865744a6341e8a939c9adc1" + ], + "committed_at": "2026-06-09T20:35:29Z", + "next_step": "ai_review_required", + "pr_number": 27110, + "pr_url": "https://github.com/openai/codex/pull/27110", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, release_packaging.", + "sample_paths": [ + "sdk/python/src/openai_codex/_goal.py", + "sdk/python/src/openai_codex/_message_router.py", + "sdk/python/src/openai_codex/async_client.py", + "sdk/python/src/openai_codex/client.py", + "sdk/python/src/openai_codex/models.py", + "sdk/python/tests/test_client_rpc_methods.py" ], "source_state": "merged", - "subject_id": "27037", + "subject_id": "27110", "subject_kind": "pr", "surface_hints": [ - "config_hooks" + "cli_tui", + "model_provider", + "tests_ci" ], - "title": "[codex] Calm multi-agent v2 usage prompts", - "url": "https://github.com/openai/codex/pull/27037" + "title": "[1/6] Add Python goal routing foundation", + "url": "https://github.com/openai/codex/pull/27110" }, { "attention_flags": [ + "auth_account", + "breaking_change", + "deprecated_removed", "new_feature", "protocol_change", + "release_packaging", "security_policy" ], - "changed_file_count": 7, + "changed_file_count": 28, "commit_shas": [ - "d783face3686a981e14453bc228913eac1d74059", - "2a15fb7d4eadc623a70b44db8aec1c9243418279", - "965e080940e4aeea1d3549c1c4f651bd16af1819", - "3928dc19b1a780206384dd5e0a1427c25188c6f0", - "6d445696505735e1cc41ef38ee20979282ed4d1f" + "04552f5663aa09b2363f8245b8d814d8bdfdc557", + "20b507e3783731f6ecda1ea1ed8197e286891158", + "648f66285f4ce14fd12e11c53386f19476b0d44b" ], - "committed_at": "2026-06-08T21:03:37Z", + "committed_at": "2026-06-09T20:44:16Z", "next_step": "ai_review_required", - "pr_number": 27035, - "pr_url": "https://github.com/openai/codex/pull/27035", - "review_priority": "high", - "review_reason": "Needs AI review for new_feature, protocol_change, security_policy.", + "pr_number": 27191, + "pr_url": "https://github.com/openai/codex/pull/27191", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, breaking_change, deprecated_removed, new_feature, protocol_change, release_packaging, security_policy.", "sample_paths": [ - "codex-rs/cli/BUILD.bazel", - "codex-rs/cli/src/debug_sandbox.rs", - "codex-rs/cli/tests/sandbox_network_proxy.rs", - "codex-rs/sandboxing/src/landlock.rs", - "codex-rs/sandboxing/src/landlock_tests.rs", - "codex-rs/sandboxing/src/manager.rs", - "codex-rs/sandboxing/src/manager_tests.rs" + "codex-rs/Cargo.lock", + "codex-rs/Cargo.toml", + "codex-rs/app-server/Cargo.toml", + "codex-rs/app-server/src/extensions.rs", + "codex-rs/app-server/src/mcp_refresh.rs", + "codex-rs/app-server/src/request_processors.rs", + "codex-rs/app-server/src/request_processors/apps_processor.rs", + "codex-rs/app-server/src/request_processors/mcp_processor.rs", + "codex-rs/app-server/src/request_processors/plugins.rs", + "codex-rs/chatgpt/src/connectors.rs", + "codex-rs/codex-mcp/src/lib.rs", + "codex-rs/codex-mcp/src/mcp/mod.rs" ], "source_state": "merged", - "subject_id": "27035", + "subject_id": "27191", "subject_kind": "pr", "surface_hints": [ + "app_server_protocol", + "config_hooks", + "mcp_plugins", + "tests_ci" + ], + "title": "Route hosted Apps MCP through extensions", + "url": "https://github.com/openai/codex/pull/27191" + }, + { + "attention_flags": [ + "auth_account", + "breaking_change", + "deprecated_removed", + "new_feature", + "protocol_change", + "security_policy" + ], + "changed_file_count": 19, + "commit_shas": [ + "b564da44fb798e9e8e5c89ff912ab72a70a2ba9c", + "5b5caa9431c818837eadc6d01cdd64e3b597ce9d", + "83c0b87e952501c98f96957c3df2b2efa45352f7", + "9ff7581214ba17137fd351893766e6be3612ff05", + "e605b381502ef535c95f6e57798cc78a08703912", + "eb4878b26439e36e1446fc72da6a8b25b495bfd1" + ], + "committed_at": "2026-06-09T22:10:17Z", + "next_step": "ai_review_required", + "pr_number": 26734, + "pr_url": "https://github.com/openai/codex/pull/26734", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, breaking_change, deprecated_removed, new_feature, protocol_change, security_policy.", + "sample_paths": [ + "codex-rs/core/src/unified_exec/process.rs", + "codex-rs/core/src/unified_exec/process_manager.rs", + "codex-rs/core/src/unified_exec/process_tests.rs", + "codex-rs/core/tests/suite/unified_exec.rs", + "codex-rs/exec-server/src/client.rs", + "codex-rs/exec-server/src/lib.rs", + "codex-rs/exec-server/src/local_process.rs", + "codex-rs/exec-server/src/process.rs", + "codex-rs/exec-server/src/protocol.rs", + "codex-rs/exec-server/src/remote_process.rs", + "codex-rs/exec-server/src/server/handler.rs", + "codex-rs/exec-server/src/server/process_handler.rs" + ], + "source_state": "merged", + "subject_id": "26734", + "subject_kind": "pr", + "surface_hints": [ + "app_server_protocol", "cli_tui", - "sandbox_permissions", "tests_ci" ], - "title": "Enforce configured network proxy in codex sandbox", - "url": "https://github.com/openai/codex/pull/27035" + "title": "[codex] Handle Ctrl-C for non-TTY unified exec", + "url": "https://github.com/openai/codex/pull/26734" }, { "attention_flags": [ "auth_account", + "deprecated_removed", "new_feature", "protocol_change" ], - "changed_file_count": 3, + "changed_file_count": 7, "commit_shas": [ - "cfff3511d3fb2330b9a6f72a04ea4652726305bf", - "b8d174254b6de10b231de936a6d85f3781ace8c5", - "2a0eef2528e481834d67fae9ed6bd41b00119a53", - "8886e8585481c63bed088c3c8e70ea23d2ad0503", - "6c65c2740bee5661c4d5b5632746b141efb399ad" + "09ce7e176bb3e35108cce7c74f9fe566125b6c87", + "821b679505e5021c4fc20a3c79070d96ff0aaa24", + "e992bdf9805440b068ffa2c031dbf3be0e244107", + "7c54723762ae9ebb3d2bbb95e71ac5000771c9c9", + "e4dca2440722489eb1d774ba0b273a4260f8d0e8", + "5f2b14e092e169c3f4c9f4b93c40e2560f95e2ca", + "d4b826175776c26f977b2e10a9dc9bc4a3030e41", + "daf24cccd232bb9cc3035eb9985d2bf3ee24cab5", + "b0a300fb9b9d8ee73be8d40f718eb7b9464a28be", + "6e4c8dfa31a5fbb6216e8465337d737b7327fb6a", + "dee789ab91d6883ca16fbc86aeadbf524d95c1ef", + "08503d6d13e7b7efc817299c30bcf34bd7b5b076", + "75e3421f94a530314154b3ff9dd51a1064f861f6", + "d1596f4595d17a2e2a94a8fc45c7ceb116079868", + "2e23b88414a393e9800c328bded2e6f2bd7ba7a7", + "b8760d31e0e00e07aa8db22afae4ab3fb9797af4", + "1f6a75d2ac149df0a0d8f99a531aeb65243c5d1b", + "9dfb4be0ec69162ea9b1b10008c160a333a99df1", + "ce34025915ff7df1c060ff0343c5b42c4f3453f9", + "7a381f591d4bd26aabb5312d89b5c5b3d47d5a9d", + "4f29a9e89e8f39e784336e83bc71dffc270f632d" + ], + "committed_at": "2026-06-09T22:49:48Z", + "next_step": "ai_review_required", + "pr_number": 25147, + "pr_url": "https://github.com/openai/codex/pull/25147", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change.", + "sample_paths": [ + "codex-rs/rmcp-client/src/bin/test_streamable_http_server.rs", + "codex-rs/rmcp-client/src/http_client_adapter.rs", + "codex-rs/rmcp-client/src/rmcp_client.rs", + "codex-rs/rmcp-client/src/streamable_http_retry.rs", + "codex-rs/rmcp-client/src/streamable_http_retry_tests.rs", + "codex-rs/rmcp-client/tests/streamable_http_recovery.rs", + "codex-rs/rmcp-client/tests/streamable_http_test_support.rs" + ], + "source_state": "merged", + "subject_id": "25147", + "subject_kind": "pr", + "surface_hints": [ + "cli_tui", + "mcp_plugins", + "tests_ci" + ], + "title": "[codex] Retry streamable HTTP initialize failures", + "url": "https://github.com/openai/codex/pull/25147" + }, + { + "attention_flags": [ + "auth_account", + "deprecated_removed", + "new_feature", + "protocol_change", + "rate_limit", + "release_packaging", + "security_policy" ], - "committed_at": "2026-06-08T21:41:05Z", + "changed_file_count": 7, + "commit_shas": [ + "52f9ec871bedbd53a0c0741d0b7bc47e3dae3da9", + "4d32a96c7580b022e5d906bcbb2eb283b80338f7", + "ddd48cab1b5d617e8a01737c0665f4025b351421", + "44448048dcad4a75a1d7056f23cc87691438268c", + "ccf0f0d9892fd9b253401466d6dee7a1886ac407", + "9da50461f3d23990d484b3ba29b5cb293269d23f" + ], + "committed_at": "2026-06-09T23:34:38Z", "next_step": "ai_review_required", - "pr_number": 24118, - "pr_url": "https://github.com/openai/codex/pull/24118", - "review_priority": "high", - "review_reason": "Needs AI review for auth_account, new_feature, protocol_change.", + "pr_number": 26701, + "pr_url": "https://github.com/openai/codex/pull/26701", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, rate_limit, release_packaging, security_policy.", "sample_paths": [ - "codex-rs/tools/src/json_schema.rs", - "codex-rs/tools/src/json_schema_tests.rs", - "codex-rs/tools/tests/fixtures/json_schema_policy/google_drive.json" + "codex-rs/tui/src/app.rs", + "codex-rs/tui/src/app/background_requests.rs", + "codex-rs/tui/src/app/event_dispatch.rs", + "codex-rs/tui/src/app_event.rs", + "codex-rs/tui/src/chatwidget/plugins.rs", + "codex-rs/tui/src/chatwidget/tests/helpers.rs", + "codex-rs/tui/src/chatwidget/tests/popups_and_settings.rs" ], "source_state": "merged", - "subject_id": "24118", + "subject_id": "26701", "subject_kind": "pr", "surface_hints": [ - "sandbox_permissions", + "cli_tui", + "config_hooks", + "mcp_plugins", + "tests_ci" + ], + "title": "TUI Plugin Sharing 1 - add remote plugin identity", + "url": "https://github.com/openai/codex/pull/26701" + }, + { + "attention_flags": [ + "auth_account", + "deprecated_removed", + "new_feature", + "protocol_change", + "security_policy" + ], + "changed_file_count": 9, + "commit_shas": [ + "00f1e544854c67163899cd0c6c3091c6d4a7694e", + "38b487f2a4eb2291eab6ccea41d24455acfbe9c0", + "b3dce407ff660c49d616be8920bc50a74ced8ac1", + "717e4b299bf0815a2fd1bd77d61ed5f3fbc7ae40" + ], + "committed_at": "2026-06-09T23:49:09Z", + "next_step": "ai_review_required", + "pr_number": 27129, + "pr_url": "https://github.com/openai/codex/pull/27129", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, security_policy.", + "sample_paths": [ + "codex-rs/Cargo.lock", + "codex-rs/memories/write/Cargo.toml", + "codex-rs/memories/write/src/lib.rs", + "codex-rs/memories/write/src/phase1.rs", + "codex-rs/memories/write/src/phase2.rs", + "codex-rs/memories/write/src/runtime.rs", + "codex-rs/memories/write/src/startup_tests.rs", + "codex-rs/model-provider/src/amazon_bedrock/mod.rs", + "codex-rs/model-provider/src/provider.rs" + ], + "source_state": "merged", + "subject_id": "27129", + "subject_kind": "pr", + "surface_hints": [ + "config_hooks", + "model_provider", "tests_ci" ], - "title": "feat: support oneOf and allOf in tool input schemas", - "url": "https://github.com/openai/codex/pull/24118" + "title": "feat: use provider defaults for memory models", + "url": "https://github.com/openai/codex/pull/27129" }, { "attention_flags": [ "auth_account", + "breaking_change", + "deprecated_removed", "new_feature", "protocol_change" ], - "changed_file_count": 5, + "changed_file_count": 23, "commit_shas": [ - "17ef6829fd77e3a084391f9fb40c48e730a2d81a" + "2d1ffe5d740f39a4288dfa09be7c6a5f5f00ec3c" ], - "committed_at": "2026-06-08T21:47:09Z", + "committed_at": "2026-06-10T01:45:54Z", "next_step": "ai_review_required", - "pr_number": 26932, - "pr_url": "https://github.com/openai/codex/pull/26932", - "review_priority": "high", - "review_reason": "Needs AI review for auth_account, new_feature, protocol_change.", + "pr_number": 27078, + "pr_url": "https://github.com/openai/codex/pull/27078", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, breaking_change, deprecated_removed, new_feature, protocol_change.", "sample_paths": [ - "codex-rs/app-server/src/request_processors/plugins.rs", - "codex-rs/app-server/tests/suite/v2/plugin_list.rs", - "codex-rs/core-plugins/src/lib.rs", - "codex-rs/core-plugins/src/manager.rs", - "codex-rs/core-plugins/src/remote.rs" + "codex-rs/Cargo.lock", + "codex-rs/analytics/Cargo.toml", + "codex-rs/analytics/src/client.rs", + "codex-rs/analytics/src/events.rs", + "codex-rs/analytics/src/facts.rs", + "codex-rs/analytics/src/lib.rs", + "codex-rs/analytics/src/reducer.rs", + "codex-rs/app-server/src/extensions.rs", + "codex-rs/app-server/src/mcp_refresh.rs", + "codex-rs/app-server/src/message_processor.rs", + "codex-rs/app-server/tests/suite/v2/analytics.rs", + "codex-rs/app-server/tests/suite/v2/thread_resume.rs" ], "source_state": "merged", - "subject_id": "26932", + "subject_id": "27078", "subject_kind": "pr", "surface_hints": [ "app_server_protocol", + "cli_tui", + "config_hooks", "mcp_plugins", + "model_provider", "tests_ci" ], - "title": "Use cached remote plugin catalog for plugin list", - "url": "https://github.com/openai/codex/pull/26932" + "title": "[codex-analytics] emit goal lifecycle analytics", + "url": "https://github.com/openai/codex/pull/27078" }, { "attention_flags": [ @@ -1053,161 +1019,177 @@ }, { "attention_flags": [ - "breaking_change", + "new_feature", "protocol_change", - "release_packaging" + "security_policy" ], - "changed_file_count": 7, + "changed_file_count": 4, "commit_shas": [ - "fe72ccd18a05ea467d8baf65286ca4e6c4156bd1" + "7d11ccc1219ef6027533969ce67ff5ac77d3efc6", + "d042443be940d05b1700260baac565bfe20836b1", + "457430a033c5beceb085b5e6ac94841ecc7e8a07", + "8812af506c639905875c3c94ef5544e0787d6f4f", + "afd2f66864982ad90369bd7ccb084fe2a6630fe8" ], - "committed_at": "2026-06-08T18:47:23Z", + "committed_at": "2026-06-09T20:08:01Z", "next_step": "ai_review_required", - "pr_number": 27024, - "pr_url": "https://github.com/openai/codex/pull/27024", - "review_priority": "normal", - "review_reason": "Needs AI review for breaking_change, protocol_change, release_packaging.", + "pr_number": 22685, + "pr_url": "https://github.com/openai/codex/pull/22685", + "review_priority": "high", + "review_reason": "Needs AI review for new_feature, protocol_change, security_policy.", "sample_paths": [ - ".github/workflows/bazel.yml", - ".github/workflows/rust-ci-full.yml", - ".github/workflows/rust-ci.yml", - ".github/workflows/rust-release-argument-comment-lint.yml", - ".github/workflows/rust-release-windows.yml", - ".github/workflows/rust-release.yml", - ".github/workflows/sdk.yml" + "codex-rs/network-proxy/README.md", + "codex-rs/network-proxy/src/config.rs", + "codex-rs/network-proxy/src/mitm.rs", + "codex-rs/network-proxy/src/socks5.rs" ], "source_state": "merged", - "subject_id": "27024", + "subject_id": "22685", "subject_kind": "pr", "surface_hints": [ - "release_packaging", - "tests_ci" + "config_hooks", + "docs_examples" ], - "title": "ci: template custom runner names by repo", - "url": "https://github.com/openai/codex/pull/27024" + "title": "Add SOCKS5 TCP MITM coverage", + "url": "https://github.com/openai/codex/pull/22685" }, { "attention_flags": [ "auth_account", "new_feature", - "security_policy" + "protocol_change" ], - "changed_file_count": 2, + "changed_file_count": 3, "commit_shas": [ - "6d9f9c5cdcaa0a156aa2dabbde259ae5e9e8bc0b" + "9ffed3cafd48244f2927e48fe05b82b9476b8378", + "f5101b8ff6b4c57d4a56b3c1c27487c8ae9bec2a" ], - "committed_at": "2026-06-08T20:59:23Z", + "committed_at": "2026-06-09T21:18:24Z", "next_step": "ai_review_required", - "pr_number": 27054, - "pr_url": "https://github.com/openai/codex/pull/27054", - "review_priority": "normal", - "review_reason": "Needs AI review for auth_account, new_feature, security_policy.", + "pr_number": 26713, + "pr_url": "https://github.com/openai/codex/pull/26713", + "review_priority": "high", + "review_reason": "Needs AI review for auth_account, new_feature, protocol_change.", "sample_paths": [ - "codex-rs/cli/src/lib.rs", - "codex-rs/cli/src/main.rs" + "codex-rs/rmcp-client/src/auth_status.rs", + "codex-rs/rmcp-client/src/oauth.rs", + "codex-rs/rmcp-client/tests/streamable_http_oauth_startup.rs" ], "source_state": "merged", - "subject_id": "27054", + "subject_id": "26713", "subject_kind": "pr", "surface_hints": [ - "cli_tui" + "auth_accounts", + "cli_tui", + "mcp_plugins", + "tests_ci" ], - "title": "cli: add -P sandbox permissions profile alias", - "url": "https://github.com/openai/codex/pull/27054" + "title": "[codex] Report unusable MCP OAuth credentials as logged out", + "url": "https://github.com/openai/codex/pull/26713" }, { "attention_flags": [ - "deprecated_removed", + "auth_account", + "new_feature", "protocol_change", - "security_policy" + "release_packaging" ], - "changed_file_count": 4, + "changed_file_count": 5, "commit_shas": [ - "42816a7efba43e1cf37b505419e8fdd52beafa06" + "ad5d6c462554bc75fdf458dbd9c4a9cec6b6e9d1" ], - "committed_at": "2026-06-08T21:29:06Z", + "committed_at": "2026-06-09T22:32:15Z", "next_step": "ai_review_required", - "pr_number": 27060, - "pr_url": "https://github.com/openai/codex/pull/27060", - "review_priority": "normal", - "review_reason": "Needs AI review for deprecated_removed, protocol_change, security_policy.", + "pr_number": 27111, + "pr_url": "https://github.com/openai/codex/pull/27111", + "review_priority": "high", + "review_reason": "Needs AI review for auth_account, new_feature, protocol_change, release_packaging.", "sample_paths": [ - "codex-rs/analytics/src/analytics_client_tests.rs", - "codex-rs/analytics/src/events.rs", - "codex-rs/analytics/src/facts.rs", - "codex-rs/analytics/src/reducer.rs" + "sdk/python/src/openai_codex/_goal.py", + "sdk/python/src/openai_codex/_message_router.py", + "sdk/python/src/openai_codex/async_client.py", + "sdk/python/src/openai_codex/client.py", + "sdk/python/tests/test_app_server_goal_operations.py" ], "source_state": "merged", - "subject_id": "27060", + "subject_id": "27111", "subject_kind": "pr", "surface_hints": [ + "app_server_protocol", "cli_tui", "tests_ci" ], - "title": "[codex-analytics] stop sending codex error subreason", - "url": "https://github.com/openai/codex/pull/27060" + "title": "[2/6] Add private Python goal operations", + "url": "https://github.com/openai/codex/pull/27111" }, { "attention_flags": [ "new_feature", - "protocol_change" + "protocol_change", + "security_policy" ], - "changed_file_count": 2, + "changed_file_count": 1, "commit_shas": [ - "a107f7b29619b363df4d2471890d9b53ed616c7b", - "203556719522157fa00a758a2e31fceff2f7ea9e" + "78e5f38713bfb1575127c7aa5a6ea6b11337fd6e" ], - "committed_at": "2026-06-08T22:29:51Z", + "committed_at": "2026-06-09T23:07:34Z", "next_step": "ai_review_required", - "pr_number": 26091, - "pr_url": "https://github.com/openai/codex/pull/26091", - "review_priority": "normal", - "review_reason": "Needs AI review for new_feature, protocol_change.", + "pr_number": 27257, + "pr_url": "https://github.com/openai/codex/pull/27257", + "review_priority": "high", + "review_reason": "Needs AI review for new_feature, protocol_change, security_policy.", "sample_paths": [ - "codex-rs/otel/src/metrics/client.rs", - "codex-rs/otel/tests/suite/send.rs" + "codex-rs/codex-mcp/src/connection_manager.rs" ], "source_state": "merged", - "subject_id": "26091", + "subject_id": "27257", "subject_kind": "pr", "surface_hints": [ - "cli_tui", - "tests_ci" + "mcp_plugins" ], - "title": "[codex] Add OTEL counter descriptions", - "url": "https://github.com/openai/codex/pull/26091" + "title": "[codex] Tighten MCP connection manager API visibility and order", + "url": "https://github.com/openai/codex/pull/27257" }, { "attention_flags": [ "new_feature", + "protocol_change", "release_packaging" ], - "changed_file_count": 5, + "changed_file_count": 11, "commit_shas": [ - "1aa5b250f28857330a5257b89dc036144d17b32c" + "6e4cd755e5195f95dfbff628f55d6c9ed592bb11" ], - "committed_at": "2026-06-08T22:43:08Z", + "committed_at": "2026-06-10T00:54:32Z", "next_step": "ai_review_required", - "pr_number": 27081, - "pr_url": "https://github.com/openai/codex/pull/27081", - "review_priority": "normal", - "review_reason": "Needs AI review for new_feature, release_packaging.", + "pr_number": 24999, + "pr_url": "https://github.com/openai/codex/pull/24999", + "review_priority": "high", + "review_reason": "Needs AI review for new_feature, protocol_change, release_packaging.", "sample_paths": [ - "codex-rs/cli/src/doctor.rs", - "codex-rs/cli/src/doctor/output.rs", - "codex-rs/cli/src/doctor/output/detail.rs", - "codex-rs/cli/src/doctor/snapshots/codex__doctor__output__tests__doctor_human_report_environment_rows.snap", - "codex-rs/cli/src/doctor/system.rs" + "codex-rs/app-server-protocol/schema/json/ClientRequest.json", + "codex-rs/app-server-protocol/src/protocol/common.rs", + "codex-rs/app-server-protocol/src/protocol/v2/realtime.rs", + "codex-rs/app-server/README.md", + "codex-rs/app-server/src/request_processors/turn_processor.rs", + "codex-rs/app-server/tests/suite/v2/experimental_api.rs", + "codex-rs/app-server/tests/suite/v2/realtime_conversation.rs", + "codex-rs/core/src/realtime_conversation.rs", + "codex-rs/core/tests/suite/compact_remote.rs", + "codex-rs/core/tests/suite/realtime_conversation.rs", + "codex-rs/protocol/src/protocol.rs" ], "source_state": "merged", - "subject_id": "27081", + "subject_id": "24999", "subject_kind": "pr", "surface_hints": [ + "app_server_protocol", "cli_tui", + "docs_examples", "tests_ci" ], - "title": "feat(doctor): report editor and pager environment", - "url": "https://github.com/openai/codex/pull/27081" + "title": "Add per-session realtime model and version overrides", + "url": "https://github.com/openai/codex/pull/24999" }, { "attention_flags": [ @@ -1440,53 +1422,141 @@ }, { "attention_flags": [ - "auth_account" + "auth_account", + "deprecated_removed", + "protocol_change" + ], + "changed_file_count": 4, + "commit_shas": [ + "e334749c069de53b53319622dd9519005812cd4c", + "b7b8195697fd4e367bf9bce3d2c9864f51276f8a" + ], + "committed_at": "2026-06-09T20:23:31Z", + "next_step": "ai_review_required", + "pr_number": 26681, + "pr_url": "https://github.com/openai/codex/pull/26681", + "review_priority": "normal", + "review_reason": "Needs AI review for auth_account, deprecated_removed, protocol_change.", + "sample_paths": [ + "codex-rs/ext/goal/src/spec.rs", + "codex-rs/ext/goal/src/tool.rs", + "codex-rs/ext/goal/tests/goal_extension_backend.rs", + "codex-rs/state/src/runtime/goals.rs" + ], + "source_state": "merged", + "subject_id": "26681", + "subject_kind": "pr", + "surface_hints": [ + "tests_ci" + ], + "title": "Allow creating a new goal after completion", + "url": "https://github.com/openai/codex/pull/26681" + }, + { + "attention_flags": [ + "breaking_change", + "new_feature", + "protocol_change", + "security_policy" ], - "changed_file_count": 1, + "changed_file_count": 2, + "commit_shas": [ + "f5aceef813187034818cd820bc6dc88eda61a2e0", + "31be4bfd9e18c79a72a46bd60414e1ff6d421855", + "370ee0584b72143fc47337d21933a41d1b4da7ef", + "fc5b45bfc2212b4c34e03ab6e4f826feb09edd90", + "4ce0812b02ebf0973901ed19f58bb7852237163a", + "98a6caf6a105156a0741c5952bd3350c03333556", + "4e2a69b9a3e0cf97209eeab7551a7bb11d5bec01", + "01f4a200d4e6eb53d086ec44ebddff9f25b1f8b6", + "6c6bc03418b575dba5af860025449bca73ecf1be", + "51dd8b35382f6ca994a4bf2e0dbc3ee86f38e413", + "42f3de1f1526af2e9f14538a4e63f01789141166", + "d2f5bddc9c6f8b8646af0a906e09115b78f28b66", + "5111a85c16c9ac17dc3adc5e7b0e1cadfafae93c", + "11babeb0901576cdd8f27e9864e1f20cfe22cfd1" + ], + "committed_at": "2026-06-09T20:51:57Z", + "next_step": "ai_review_required", + "pr_number": 26830, + "pr_url": "https://github.com/openai/codex/pull/26830", + "review_priority": "normal", + "review_reason": "Needs AI review for breaking_change, new_feature, protocol_change, security_policy.", + "sample_paths": [ + "codex-rs/core/tests/suite/agents_md.rs", + "codex-rs/core/tests/suite/compact.rs" + ], + "source_state": "merged", + "subject_id": "26830", + "subject_kind": "pr", + "surface_hints": [ + "tests_ci" + ], + "title": "[codex] Characterize global instruction lifecycle", + "url": "https://github.com/openai/codex/pull/26830" + }, + { + "attention_flags": [ + "auth_account", + "deprecated_removed", + "new_feature", + "protocol_change", + "release_packaging", + "security_policy" + ], + "changed_file_count": 6, "commit_shas": [ - "ea91ecc6afb743f7a37aabd4def5adfdba6cc73e" + "3c85d78cc93fa9f77fb57704cfe009c9c98324eb" ], - "committed_at": "2026-06-08T20:09:06Z", + "committed_at": "2026-06-09T22:20:01Z", "next_step": "ai_review_required", - "pr_number": 27038, - "pr_url": "https://github.com/openai/codex/pull/27038", - "review_priority": "low", - "review_reason": "Needs AI review for auth_account.", + "pr_number": 27116, + "pr_url": "https://github.com/openai/codex/pull/27116", + "review_priority": "normal", + "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, release_packaging, security_policy.", "sample_paths": [ - ".codex/skills/babysit-pr/SKILL.md" + "codex-rs/core/src/realtime_conversation.rs", + "codex-rs/core/src/session/handlers.rs", + "codex-rs/core/src/session/mod.rs", + "codex-rs/core/tests/suite/realtime_conversation.rs", + "codex-rs/core/tests/suite/snapshots/all__suite__realtime_conversation__conversation_user_text_turn_is_capped_when_mirrored_to_realtime.snap", + "codex-rs/core/tests/suite/snapshots/all__suite__realtime_conversation__conversation_user_text_turn_is_sent_to_realtime_when_active.snap" ], "source_state": "merged", - "subject_id": "27038", + "subject_id": "27116", "subject_kind": "pr", "surface_hints": [ - "internal_churn" + "tests_ci" ], - "title": "[codex] Clarify PR babysitter state mutations", - "url": "https://github.com/openai/codex/pull/27038" + "title": "Stop mirroring Codex user input into realtime", + "url": "https://github.com/openai/codex/pull/27116" }, { - "attention_flags": [], + "attention_flags": [ + "new_feature" + ], "changed_file_count": 1, "commit_shas": [ - "fad5259746920f25b73e32846f0854ca355333b1" + "e4b0f97aa21f7b723bceec78f76b64f9131b0435", + "affbd8bb42cc7501060fb05c0f0bedd4cc55d2f3" ], - "committed_at": "2026-06-08T21:33:57Z", + "committed_at": "2026-06-10T00:49:59Z", "next_step": "ai_review_required", - "pr_number": 27044, - "pr_url": "https://github.com/openai/codex/pull/27044", - "review_priority": "low", - "review_reason": "Needs AI review because every recent upstream commit is tracked, but deterministic hints found only internal churn.", + "pr_number": 27094, + "pr_url": "https://github.com/openai/codex/pull/27094", + "review_priority": "normal", + "review_reason": "Needs AI review for new_feature.", "sample_paths": [ - "codex-rs/core-skills/src/render.rs" + "codex-rs/core/src/tools/spec_plan.rs" ], "source_state": "merged", - "subject_id": "27044", + "subject_id": "27094", "subject_kind": "pr", "surface_hints": [ "internal_churn" ], - "title": "[codex] Require complete main-agent skill reads", - "url": "https://github.com/openai/codex/pull/27044" + "title": "Add spans to build_tool_router", + "url": "https://github.com/openai/codex/pull/27094" } ] } diff --git a/artifacts/github/reviews/openai-codex-pr-22879.review.json b/artifacts/github/reviews/openai-codex-pr-22879.review.json new file mode 100644 index 000000000..62ef422e9 --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-22879.review.json @@ -0,0 +1,72 @@ +{ + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-22879", + "repo": "openai/codex", + "subject": { + "subject_kind": "pr", + "subject_id": "22879", + "commit_shas": [ + "900347bbffae41f08467ae2ff7552ea3564847fe", + "80f3514fe4fa2d0c811797571ac8e813ed28c10d", + "95d77fadad869b547af91f67bebdfc40d9927675", + "7f8f4e5d1a414d102075fa0fe87acdfff7f12f46", + "375aab3440badf14d4f94ce5bb672fa800fea228", + "061e1ad76c24a244534a5f27f70ae713b7d610b2", + "bbdb159af09fb5fbf4c672c7e9679a41725f6e7c" + ] + }, + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "fix: Prevent /review crash when entering Esc on steer message", + "url": "https://github.com/openai/codex/pull/22879", + "meta": "Merged 2026-06-09T16:41:58Z" + }, + { + "kind": "commit", + "title": "reject Esc steer submission during /review", + "url": "https://github.com/openai/codex/commit/900347bbffae41f08467ae2ff7552ea3564847fe" + }, + { + "kind": "commit", + "title": "retry turn interrupts after active-turn mismatch - Ctrl + C case", + "url": "https://github.com/openai/codex/commit/375aab3440badf14d4f94ce5bb672fa800fea228" + } + ] + }, + "reviewed_at": "2026-06-10T02:09:14Z", + "observed_change": "Codex `/review` now rejects Esc-based queued steer attempts with a warning instead of crashing, while Ctrl+C cancellation retries once after an active-turn mismatch.", + "changed_surfaces": [ + "TUI `/review` chat widget interaction", + "TUI app-server turn interrupt error handling", + "review-start active turn cache updates", + "review mode regression tests and snapshots" + ], + "user_visible_path": "During an active `/review`, users who type follow-up guidance and press Esc now see a warning that steering is unsupported and should use Ctrl+C to cancel; queued text is preserved when cancellation is used.", + "control_plane_relevance": "Decodex review operators should preserve the upstream distinction: `/review` still does not support steering, and cancellation remains Ctrl+C/interrupt rather than an Esc steer path.", + "compatibility_risk": "Low to moderate for tooling that models `/review` as a normal steerable active turn; the PR explicitly keeps `/review` steering unsupported and hardens only the unsupported path.", + "adoption_opportunity": "Use the upstream warning semantics in Decodex review guidance and tolerate active-turn mismatch retries around review cancellation.", + "community_value": "Useful for Codex users who run `/review` on long diffs because it turns a crash-prone unsupported steer attempt into recoverable guidance.", + "deprecated_or_breaking_notes": "`/review` steering remains unsupported; Esc no longer routes queued review follow-up text through the normal interrupt/steer flow.", + "confidence": "confirmed", + "evidence": [ + "PR #22879 says Esc during `/review` with queued follow-up steer text previously caused a TUI crash and now shows an unsupported-steer warning.", + "codex-rs/tui/src/chatwidget/interaction.rs adds a review-mode guard that emits `Steer messages aren't supported during /review. Press Ctrl+C now to cancel the review.` and returns without interrupting.", + "codex-rs/tui/src/app/thread_routing.rs retries `turn_interrupt` once with the server-reported active turn id when a review race reports a different active turn.", + "codex-rs/tui/src/app/thread_routing.rs now stores the review thread active turn returned by `review_start`.", + "codex-rs/tui/src/chatwidget/tests/review_mode.rs asserts Esc keeps pending steers, submits no op, and shows the review warning.", + "The normalized bundle artifacts/github/bundles/openai-codex-pr-22879.json records 7 changed files for the merged PR." + ], + "caveats": "The change fixes unsupported steer handling during `/review`; it does not add steer support to review mode.", + "next_actions": [ + { + "type": "upstream_impact", + "reason": "Review-mode interrupt semantics can affect Decodex operator guidance and review tooling assumptions." + }, + { + "type": "social_candidate", + "reason": "The fixed `/review` user path is concrete and source-backed enough for a practical Publisher handoff." + } + ] +} diff --git a/artifacts/github/reviews/openai-codex-pr-25177.review.json b/artifacts/github/reviews/openai-codex-pr-25177.review.json new file mode 100644 index 000000000..424882bf1 --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-25177.review.json @@ -0,0 +1,68 @@ +{ + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-25177", + "repo": "openai/codex", + "subject": { + "subject_kind": "pr", + "subject_id": "25177", + "commit_shas": [ + "074c237d6b2f061e02273af5b8ba2d7869020e10", + "eb22256674028348ce7cb5ff6ed3b5365c11091e", + "dfcc2221c8b46a2390a982d48ef1426aadcc4a2b", + "c25d9987b95c0f55aeac3fc963a4d4087bf173d2", + "666fae92fc838030f95254738138e047298f718e", + "95e0f15865134edec8b6cc97f9983631b2607d0f", + "12556519e8796dc575eedbac190b42e779e608e2" + ] + }, + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "Preserve cloud requirements across TUI thread resets", + "url": "https://github.com/openai/codex/pull/25177", + "meta": "Merged 2026-06-09T01:08:48Z" + }, + { + "kind": "commit", + "title": "Ensure cloud_requirements persist after /new, /clear, /side, etc.", + "url": "https://github.com/openai/codex/commit/074c237d6b2f061e02273af5b8ba2d7869020e10" + }, + { + "kind": "commit", + "title": "Use cloud config bundle for TUI reloads", + "url": "https://github.com/openai/codex/commit/c25d9987b95c0f55aeac3fc963a4d4087bf173d2" + } + ] + }, + "reviewed_at": "2026-06-10T02:09:14Z", + "observed_change": "Codex TUI config rebuilds for thread transitions now preserve the cloud config bundle loader so cloud requirements survive fresh-session and thread-reset paths.", + "changed_surfaces": [ + "TUI config persistence and fresh-session config rebuilds", + "cloud managed-config bundle loading", + "external-agent config migration startup", + "TUI regression tests for config refresh" + ], + "user_visible_path": "Users with cloud requirements applied can use `/new`, `/clear`, `/fork`, side conversations, or session-picker transitions without dropping cloud-managed settings such as feature requirements.", + "control_plane_relevance": "Decodex should treat this as a watch item for managed Codex config behavior: TUI thread transitions no longer imply that cloud requirements were shed.", + "compatibility_risk": "Low for app-server clients because no protocol field is removed, but operators who expected thread resets to clear cloud requirements should adjust that assumption.", + "adoption_opportunity": "No immediate Decodex implementation is required; keep future config-refresh or TUI-interop code aligned with Codex preserving cloud bundles across thread transitions.", + "community_value": "Limited outside cloud-managed Codex users because the easiest public repro depends on cloud requirements and an internal feature example.", + "deprecated_or_breaking_notes": "No deprecated field or removed user command was identified; the behavior change is preservation of managed config across resets.", + "confidence": "confirmed", + "evidence": [ + "PR #25177 says `/new`, `/clear`, `/fork`, side conversations, and session picker transitions previously rebuilt config without the cloud requirements loader.", + "codex-rs/tui/src/app/config_persistence.rs now passes `cloud_config_bundle(self.cloud_config_bundle.clone())` into both config refresh builders.", + "codex-rs/tui/src/app.rs stores `CloudConfigBundleLoader` on the App and passes it through TUI initialization.", + "codex-rs/tui/src/external_agent_config_migration_startup.rs accepts the cloud config bundle during migration prompt handling.", + "The regression test `refresh_in_memory_config_from_disk_keeps_cloud_requirements_for_thread_transitions` asserts cloud approval-policy requirements still apply after config refresh.", + "The normalized bundle artifacts/github/bundles/openai-codex-pr-25177.json records 6 changed files for the merged PR." + ], + "caveats": "The PR body names an internal staff-friendly feature example, so public messaging should avoid implying a broadly available feature toggle.", + "next_actions": [ + { + "type": "upstream_impact", + "reason": "Managed config preservation is worth tracking as a Decodex Control Plane watch item." + } + ] +} diff --git a/artifacts/github/reviews/openai-codex-pr-27184.review.json b/artifacts/github/reviews/openai-codex-pr-27184.review.json new file mode 100644 index 000000000..2030aaa43 --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-27184.review.json @@ -0,0 +1,79 @@ +{ + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-27184", + "repo": "openai/codex", + "subject": { + "subject_kind": "pr", + "subject_id": "27184", + "commit_shas": [ + "5d7823925c88f09568bafda637fccd92b56a9b6a", + "0f384f1b4d7e7542f1202fc966b8c6475fa27d0f", + "f0df7cb06b999489e989767092ecc767fa7c30cc", + "fec64281b4558807c592629485958b02f0869d55", + "f607c8696bc512aefbcf3fc038d6c53d77d4663c", + "2400fd9198b798764a5090410c8761a69fd61734", + "ed85bf407760a9dcc0ebb6971dc0505c1d4f3a1a" + ] + }, + "source_refs": { + "items": [ + { + "kind": "pull_request", + "title": "Load selected executor skills through extensions", + "url": "https://github.com/openai/codex/pull/27184", + "meta": "Merged 2026-06-09T17:51:55Z" + }, + { + "kind": "commit", + "title": "Add selected root protocol", + "url": "https://github.com/openai/codex/commit/5d7823925c88f09568bafda637fccd92b56a9b6a" + }, + { + "kind": "commit", + "title": "Load executor skills from selected roots", + "url": "https://github.com/openai/codex/commit/fec64281b4558807c592629485958b02f0869d55" + } + ] + }, + "reviewed_at": "2026-06-10T02:09:14Z", + "observed_change": "Codex app-server `thread/start` now accepts experimental `selectedCapabilityRoots` and uses extension initialization to load explicitly selected executor-owned skills without falling back to the orchestrator filesystem.", + "changed_surfaces": [ + "app-server v2 `thread/start` protocol schemas and TypeScript exports", + "app-server thread start request processing", + "core thread/session extension initialization", + "skills extension catalog, prompt contribution, and read path", + "executor filesystem authority tests" + ], + "user_visible_path": "An app-server client can start a thread with an environment-owned selected capability root, then invoke a skill from that root; omitting `selectedCapabilityRoots` preserves existing local and bundled skill behavior.", + "control_plane_relevance": "High for Decodex Control Plane: capability selection can move from orchestrator-local plugin paths toward executor-owned roots while preserving the extension that owns discovery and invocation.", + "compatibility_risk": "Moderate for strict app-server clients and Control Plane adapters because the new field is experimental and optional, but selected roots require environment-owned absolute paths, unavailable roots only warn, and no orchestrator filesystem fallback occurs.", + "adoption_opportunity": "Create a Decodex follow-up to evaluate selected capability roots for executor-side plugins and skills, while accounting for the PR caveats that MCP, connectors, hooks, persistence, resume, fork, and subagent inheritance are not yet active.", + "community_value": "High for Codex operators because it is the first end-to-end app-server vertical for executor-owned capability roots and split-runtime skill loading.", + "deprecated_or_breaking_notes": "The PR does not remove local skill loading; current semantics are additive and experimental, but selected executor roots deliberately override colliding local skills and avoid local fallback.", + "confidence": "confirmed", + "evidence": [ + "PR #27184 states `thread/start` gains experimental `selectedCapabilityRoots` and that app-server does not inspect or canonicalize the selected path.", + "codex-rs/protocol/src/capabilities.rs adds `SelectedCapabilityRoot` with stable `id` plus `CapabilityRootLocation::Environment { environmentId, path }`.", + "codex-rs/app-server-protocol/src/protocol/v2/thread.rs exposes `selected_capability_roots: Option>` on `ThreadStartParams`.", + "codex-rs/app-server/src/request_processors/thread_processor.rs converts selected roots into `ExtensionDataInit` before creating the thread.", + "codex-rs/ext/skills/src/provider/executor.rs resolves the selected environment, loads skills through that environment's filesystem, warns on unavailable environments or invalid paths, and reads the invoked skill through the bound environment resource.", + "codex-rs/app-server/tests/suite/v2/executor_skills.rs starts a thread with a selected executor plugin root and asserts the executor skill body is injected while the colliding local skill body is not.", + "codex-rs/ext/skills/tests/executor_file_system_authority.rs verifies skill loading and reads use the supplied executor filesystem and selected-root identity.", + "The normalized bundle artifacts/github/bundles/openai-codex-pr-27184.json records 46 changed files for the merged PR." + ], + "caveats": "The PR states only environment-owned locations are represented; MCP, connectors, hooks, durable selection, resume, fork, and subagent inheritance remain follow-ups.", + "next_actions": [ + { + "type": "upstream_impact", + "reason": "This is an app-server protocol and extension-loading change with direct Decodex Control Plane implications." + }, + { + "type": "social_candidate", + "reason": "The selected executor-root vertical has a clear operator-facing public angle." + }, + { + "type": "linear_followup", + "reason": "Decodex should evaluate selected capability roots for executor-side plugin and skill loading." + } + ] +} diff --git a/artifacts/github/social-candidates/openai-codex-pr-22879.json b/artifacts/github/social-candidates/openai-codex-pr-22879.json new file mode 100644 index 000000000..4928078b0 --- /dev/null +++ b/artifacts/github/social-candidates/openai-codex-pr-22879.json @@ -0,0 +1,54 @@ +{ + "schema": "social_candidate/v1", + "slug": "openai-codex-pr-22879", + "repo": "openai/codex", + "channel": "x", + "target_account": "decodexspace", + "mode": "practical_explainer", + "priority": "high", + "audience": "Codex users running `/review` on active diffs", + "candidate_text": [ + "Codex `/review` no longer treats Esc on queued steer text as an interrupt path: it warns that steering is unsupported during review and keeps Ctrl+C as cancellation. PR: https://github.com/openai/codex/pull/22879" + ], + "source_refs": { + "upstream_reviews": [ + "artifacts/github/reviews/openai-codex-pr-22879.review.json" + ], + "upstream_impacts": [ + "artifacts/github/impact/openai-codex-pr-22879.json" + ], + "urls": [ + "https://github.com/openai/codex/pull/22879" + ] + }, + "evidence_notes": [ + "The review records the review-mode Esc guard and warning text.", + "The PR says `/review` steering remains unsupported.", + "Ctrl+C cancellation is hardened against an active-turn mismatch race.", + "Review-mode tests assert Esc keeps queued steer text and submits no interrupt op." + ], + "claims": [ + { + "text": "Esc during `/review` with queued steer text now shows an unsupported-steer warning instead of interrupting.", + "evidence": "artifacts/github/reviews/openai-codex-pr-22879.review.json", + "confidence": "confirmed" + }, + { + "text": "Ctrl+C remains the intended cancellation path during `/review`.", + "evidence": "artifacts/github/impact/openai-codex-pr-22879.json", + "confidence": "confirmed" + } + ], + "decision": { + "worthiness": "publish", + "reason": "The PR fixes a concrete `/review` crash-prone path with clear user guidance.", + "idempotency_key": "x:decodexspace:openai-codex-pr-22879:practical_explainer" + }, + "caveats": [ + "This is not new `/review` steering support.", + "Publisher should avoid implying the queued guidance is sent during review." + ], + "next_steps": [ + "Let Publisher automation decide whether to reserve or post this candidate." + ] +} diff --git a/artifacts/github/social-candidates/openai-codex-pr-27184.json b/artifacts/github/social-candidates/openai-codex-pr-27184.json new file mode 100644 index 000000000..93e964df1 --- /dev/null +++ b/artifacts/github/social-candidates/openai-codex-pr-27184.json @@ -0,0 +1,56 @@ +{ + "schema": "social_candidate/v1", + "slug": "openai-codex-pr-27184", + "repo": "openai/codex", + "channel": "x", + "target_account": "decodexspace", + "mode": "operator_impact", + "priority": "critical", + "audience": "Codex app-server, plugin, and executor-runtime operators", + "candidate_text": [ + "Codex `thread/start` now has experimental `selectedCapabilityRoots` so an executor-owned plugin root can expose skills without app-server reading the orchestrator filesystem. PR: https://github.com/openai/codex/pull/27184" + ], + "source_refs": { + "upstream_reviews": [ + "artifacts/github/reviews/openai-codex-pr-27184.review.json" + ], + "upstream_impacts": [ + "artifacts/github/impact/openai-codex-pr-27184.json" + ], + "urls": [ + "https://github.com/openai/codex/pull/27184" + ] + }, + "evidence_notes": [ + "`thread/start` adds experimental `selectedCapabilityRoots` with environment-owned root locations.", + "Selected roots are converted into extension initialization before thread creation.", + "Executor skills are discovered and read through the environment filesystem.", + "Tests assert executor-selected skills override colliding local skill bodies." + ], + "claims": [ + { + "text": "`thread/start` now accepts experimental selected capability roots.", + "evidence": "artifacts/github/reviews/openai-codex-pr-27184.review.json", + "confidence": "confirmed" + }, + { + "text": "Executor-owned skill roots are loaded through the selected environment rather than the orchestrator filesystem.", + "evidence": "artifacts/github/impact/openai-codex-pr-27184.json", + "confidence": "confirmed" + } + ], + "decision": { + "worthiness": "publish", + "reason": "The PR creates a concrete split-runtime app-server capability-selection path for executor-owned skills.", + "idempotency_key": "x:decodexspace:openai-codex-pr-27184:operator_impact" + }, + "caveats": [ + "The field is experimental.", + "This PR covers executor-owned skills; MCP, connectors, hooks, persistence, resume, fork, and subagent inheritance remain follow-ups.", + "Unavailable environments or invalid roots warn rather than falling back to local filesystem reads." + ], + "next_steps": [ + "Let Publisher automation decide whether to reserve or post this candidate.", + "Create a Decodex follow-up if selected executor skill roots should enter the Control Plane roadmap." + ] +}