From 1e479ee48335b4dbe8f2e8a3c5aae2018e3a3039 Mon Sep 17 00:00:00 2001 From: Yvette Carlisle Date: Fri, 12 Jun 2026 22:14:14 +0800 Subject: [PATCH 1/2] {"schema":"decodex/commit/1","summary":"Persist upstream Radar review artifacts","authority":"manual"} --- .../github/bundles/openai-codex-pr-27420.json | 153 ++++ .../github/bundles/openai-codex-pr-27424.json | 435 +++++++++ .../github/bundles/openai-codex-pr-27433.json | 78 ++ .../github/bundles/openai-codex-pr-27646.json | 50 ++ .../github/impact/openai-codex-pr-27420.json | 45 + .../github/impact/openai-codex-pr-27424.json | 45 + .../github/impact/openai-codex-pr-27433.json | 44 + .../github/impact/openai-codex-pr-27646.json | 45 + .../review-queue/openai-codex-latest.json | 836 ++++++++++-------- .../reviews/openai-codex-pr-27420.review.json | 63 ++ .../reviews/openai-codex-pr-27424.review.json | 64 ++ .../reviews/openai-codex-pr-27433.review.json | 57 ++ .../reviews/openai-codex-pr-27646.review.json | 59 ++ .../openai-codex-pr-27420.json | 53 ++ .../openai-codex-pr-27424.json | 54 ++ .../openai-codex-pr-27646.json | 54 ++ 16 files changed, 1771 insertions(+), 364 deletions(-) create mode 100644 artifacts/github/bundles/openai-codex-pr-27420.json create mode 100644 artifacts/github/bundles/openai-codex-pr-27424.json create mode 100644 artifacts/github/bundles/openai-codex-pr-27433.json create mode 100644 artifacts/github/bundles/openai-codex-pr-27646.json create mode 100644 artifacts/github/impact/openai-codex-pr-27420.json create mode 100644 artifacts/github/impact/openai-codex-pr-27424.json create mode 100644 artifacts/github/impact/openai-codex-pr-27433.json create mode 100644 artifacts/github/impact/openai-codex-pr-27646.json create mode 100644 artifacts/github/reviews/openai-codex-pr-27420.review.json create mode 100644 artifacts/github/reviews/openai-codex-pr-27424.review.json create mode 100644 artifacts/github/reviews/openai-codex-pr-27433.review.json create mode 100644 artifacts/github/reviews/openai-codex-pr-27646.review.json create mode 100644 artifacts/github/social-candidates/openai-codex-pr-27420.json create mode 100644 artifacts/github/social-candidates/openai-codex-pr-27424.json create mode 100644 artifacts/github/social-candidates/openai-codex-pr-27646.json diff --git a/artifacts/github/bundles/openai-codex-pr-27420.json b/artifacts/github/bundles/openai-codex-pr-27420.json new file mode 100644 index 000000000..4701b082a --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-27420.json @@ -0,0 +1,153 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "charlesgong-openai", + "committed_at": "2026-06-10T17:27:52Z", + "message": "Propagate plugin app categories", + "sha": "2f6191ea633cd0a58580c484cc37d88191787385", + "url": "https://github.com/openai/codex/commit/2f6191ea633cd0a58580c484cc37d88191787385" + } + ], + "default_branch": "main", + "docs_refs": [], + "examples_refs": [], + "extracted_flags": [ + "EXPERIMENTAL", + "REMOTE_PLUGIN_ID", + "AUTHORIZATION", + "DEFAULT_TIMEOUT", + "JSONRPCR", + "UNAUTHORIZED", + "BAD_REQUEST" + ], + "files": [ + { + "additions": 12, + "deletions": 0, + "patch_excerpt": "@@ -6416,6 +6416,12 @@\n \"AppSummary\": {\n \"description\": \"EXPERIMENTAL - app metadata summary for plugin responses.\",\n \"properties\": {\n+ \"category\": {\n+ \"type\": [\n+ \"string\",\n+ \"null\"\n+ ]\n+ },\n \"description\": {\n \"type\": [\n \"string\",\n@@ -6449,6 +6455,12 @@\n \"null\"\n ]\n },\n+ \"category\": {\n+ \"type\": [\n+ \"string\",\n+ \"null\"\n+ ]\n+ },\n \"description\": {\n \"type\": [\n \"string\",", + "path": "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json", + "status": "modified" + }, + { + "additions": 12, + "deletions": 0, + "patch_excerpt": "@@ -694,6 +694,12 @@\n \"AppSummary\": {\n \"description\": \"EXPERIMENTAL - app metadata summary for plugin responses.\",\n \"properties\": {\n+ \"category\": {\n+ \"type\": [\n+ \"string\",\n+ \"null\"\n+ ]\n+ },\n \"description\": {\n \"type\": [\n \"string\",\n@@ -727,6 +733,12 @@\n \"null\"\n ]\n },\n+ \"category\": {\n+ \"type\": [\n+ \"string\",\n+ \"null\"\n+ ]\n+ },\n \"description\": {\n \"type\": [\n \"string\",", + "path": "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json", + "status": "modified" + }, + { + "additions": 6, + "deletions": 0, + "patch_excerpt": "@@ -4,6 +4,12 @@\n \"AppSummary\": {\n \"description\": \"EXPERIMENTAL - app metadata summary for plugin responses.\",\n \"properties\": {\n+ \"category\": {\n+ \"type\": [\n+ \"string\",\n+ \"null\"\n+ ]\n+ },\n \"description\": {\n \"type\": [\n \"string\",", + "path": "codex-rs/app-server-protocol/schema/json/v2/PluginInstallResponse.json", + "status": "modified" + }, + { + "additions": 12, + "deletions": 0, + "patch_excerpt": "@@ -8,6 +8,12 @@\n \"AppSummary\": {\n \"description\": \"EXPERIMENTAL - app metadata summary for plugin responses.\",\n \"properties\": {\n+ \"category\": {\n+ \"type\": [\n+ \"string\",\n+ \"null\"\n+ ]\n+ },\n \"description\": {\n \"type\": [\n \"string\",\n@@ -41,6 +47,12 @@\n \"null\"\n ]\n },\n+ \"category\": {\n+ \"type\": [\n+ \"string\",\n+ \"null\"\n+ ]\n+ },\n \"description\": {\n \"type\": [\n \"string\",", + "path": "codex-rs/app-server-protocol/schema/json/v2/PluginReadResponse.json", + "status": "modified" + }, + { + "additions": 1, + "deletions": 1, + "patch_excerpt": "@@ -5,4 +5,4 @@\n /**\n * EXPERIMENTAL - app metadata summary for plugin responses.\n */\n-export type AppSummary = { id: string, name: string, description: string | null, installUrl: string | null, };\n+export type AppSummary = { id: string, name: string, description: string | null, installUrl: string | null, category: string | null, };", + "path": "codex-rs/app-server-protocol/schema/typescript/v2/AppSummary.ts", + "status": "modified" + }, + { + "additions": 1, + "deletions": 1, + "patch_excerpt": "@@ -3,4 +3,4 @@\n // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.\n import type { AppTemplateUnavailableReason } from \"./AppTemplateUnavailableReason\";\n \n-export type AppTemplateSummary = { templateId: string, name: string, description: string | null, canonicalConnectorId: string | null, logoUrl: string | null, logoUrlDark: string | null, materializedAppIds: Array, reason: AppTemplateUnavailableReason | null, };\n+export type AppTemplateSummary = { templateId: string, name: string, description: string | null, category: string | null, canonicalConnectorId: string | null, logoUrl: string | null, logoUrlDark: string | null, materializedAppIds: Array, reason: AppTemplateUnavailableReason | null, };", + "path": "codex-rs/app-server-protocol/schema/typescript/v2/AppTemplateSummary.ts", + "status": "modified" + }, + { + "additions": 30, + "deletions": 0, + "patch_excerpt": "@@ -102,6 +102,33 @@ pub struct AppInfo {\n pub plugin_display_names: Vec,\n }\n \n+impl AppInfo {\n+ pub fn category(&self) -> Option {\n+ self.branding\n+ .as_ref()\n+ .and_then(|branding| non_empty_category(branding.category.as_deref()))\n+ .or_else(|| {\n+ self.app_metadata\n+ .as_ref()\n+ .and_then(|metadata| metadata.categories.as_ref())\n+ .and_then(|categories| {\n+ categories\n+ .iter()\n+ .find_map(|category| non_empty_category(Some(category.as_str())))\n+ })\n+ })\n+ }\n+}\n+\n+fn non_empty_category(category: Option<&str>) -> Option {\n+ let category = category?.trim();\n+ if category.is_empty() {\n+ None\n+ } else {\n+ Some(categor...", + "path": "codex-rs/app-server-protocol/src/protocol/v2/apps.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -661,6 +661,7 @@ pub struct AppTemplateSummary {\n pub template_id: String,\n pub name: String,\n pub description: Option,\n+ pub category: Option,\n pub canonical_connector_id: Option,\n pub logo_url: Option,\n pub logo_url_dark: Option,", + "path": "codex-rs/app-server-protocol/src/protocol/v2/plugin.rs", + "status": "modified" + }, + { + "additions": 62, + "deletions": 13, + "patch_excerpt": "@@ -1035,7 +1035,12 @@ impl PluginRequestProcessor {\n }\n None => None,\n };\n- let app_summaries = load_plugin_app_summaries(&config, &outcome.plugin.apps).await;\n+ let app_summaries = load_plugin_app_summaries(\n+ &config,\n+ &outcome.plugin.apps,\n+ &outcome.plugin.app_category_by_id,\n+ )\n+ .await;\n let visible_skills = outcome\n .plugin\n .skills\n@@ -1111,7 +1116,13 @@ impl PluginRequestProcessor {\n .cloned()\n .map(codex_plugin::AppConnectorId)\n .collect::>();\n- let app_summaries = load_plugin_app_summaries(&config, &plugin_apps).await;\n+ let app_category_by_id = remote_d...", + "path": "codex-rs/app-server/src/request_processors/plugins.rs", + "status": "modified" + }, + { + "additions": 19, + "deletions": 1, + "patch_excerpt": "@@ -292,14 +292,29 @@ async fn plugin_install_writes_remote_plugin_to_cloud_and_cache() -> Result<()>\n async fn plugin_install_uses_remote_apps_needing_auth_response() -> Result<()> {\n let codex_home = TempDir::new()?;\n let server = MockServer::start().await;\n+ let remote_app_manifest = json!({\n+ \"apps\": {\n+ \"alpha\": {\n+ \"id\": \"alpha\",\n+ \"category\": \"Developer Tools\"\n+ }\n+ }\n+ });\n let bundle_url = mount_remote_plugin_bundle(\n &server,\n /*status_code*/ 200,\n remote_plugin_bundle_tar_gz_bytes(\"linear\")?,\n )\n .await;\n configure_remote_plugin_with_apps_test(codex_home.path(), &server)?;\n- mount_remote_plugin_detail(&server, REMOTE_PLUGIN_ID, \"1.2.3\", Some(&bundle_url)).await;\n+ mount_remote_plugin_detail_with_app_manifest(\n+ &server,\n+ REMOTE_PLUGIN_ID,...", + "path": "codex-rs/app-server/tests/suite/v2/plugin_install.rs", + "status": "modified" + }, + { + "additions": 203, + "deletions": 1, + "patch_excerpt": "@@ -1,10 +1,22 @@\n+use std::sync::Arc;\n+use std::sync::Mutex as StdMutex;\n use std::time::Duration;\n \n use anyhow::Result;\n use app_test_support::ChatGptAuthFixture;\n use app_test_support::TestAppServer;\n use app_test_support::to_response;\n use app_test_support::write_chatgpt_auth;\n+use axum::Json;\n+use axum::Router;\n+use axum::extract::State;\n+use axum::http::HeaderMap;\n+use axum::http::StatusCode;\n+use axum::http::Uri;\n+use axum::http::header::AUTHORIZATION;\n+use axum::routing::get;\n+use codex_app_server_protocol::AppInfo;\n+use codex_app_server_protocol::AppMetadata;\n use codex_app_server_protocol::AppTemplateSummary;\n use codex_app_server_protocol::AppTemplateUnavailableReason;\n use codex_app_server_protocol::HookEventName;\n@@ -27,6 +39,8 @@ use codex_utils_absolute_path::AbsolutePathBuf;\n use pretty_assertions::assert_eq;\n use serde_json::json;\n use tempfile::TempDir;\n+use tokio::net...", + "path": "codex-rs/app-server/tests/suite/v2/plugin_read.rs", + "status": "modified" + }, + { + "additions": 61, + "deletions": 14, + "patch_excerpt": "@@ -61,6 +61,12 @@ pub struct PluginHookLoadOutcome {\n pub hook_load_warnings: Vec,\n }\n \n+#[derive(Debug, Clone, PartialEq, Eq)]\n+pub struct PluginAppMetadata {\n+ pub id: AppConnectorId,\n+ pub category: Option,\n+}\n+\n enum PluginLoadScope<'a> {\n AllCapabilities {\n restriction_product: Option,\n@@ -123,6 +129,7 @@ struct PluginAppFile {\n #[derive(Debug, Default, Deserialize)]\n struct PluginAppConfig {\n id: String,\n+ category: Option,\n }\n \n pub async fn load_plugins_from_layer_stack(\n@@ -848,6 +855,14 @@ fn default_mcp_config_paths(plugin_root: &Path) -> Vec {\n }\n \n pub async fn load_plugin_apps(plugin_root: &Path) -> Vec {\n+ load_plugin_app_metadata(plugin_root)\n+ .await\n+ .into_iter()\n+ .map(|app| app.id)\n+ .collect()\n+}\n+\n+pub async fn load_plugin_app_metadata(plug...", + "path": "codex-rs/core-plugins/src/loader.rs", + "status": "modified" + }, + { + "additions": 10, + "deletions": 2, + "patch_excerpt": "@@ -5,7 +5,7 @@ use crate::loader::PluginHookLoadOutcome;\n use crate::loader::configured_curated_plugin_ids_from_codex_home;\n use crate::loader::curated_plugin_cache_version;\n use crate::loader::installed_plugin_telemetry_metadata;\n-use crate::loader::load_plugin_apps;\n+use crate::loader::load_plugin_app_metadata;\n use crate::loader::load_plugin_hooks;\n use crate::loader::load_plugin_hooks_from_layer_stack;\n use crate::loader::load_plugin_mcp_servers;\n@@ -254,6 +254,7 @@ pub struct PluginDetail {\n pub disabled_skill_paths: HashSet,\n pub hooks: Vec,\n pub apps: Vec,\n+ pub app_category_by_id: HashMap,\n pub mcp_server_names: Vec,\n pub details_unavailable_reason: Option,\n }\n@@ -1224,6 +1225,7 @@ impl PluginsManager {\n disabled_skill_paths: HashSet:...", + "path": "codex-rs/core-plugins/src/manager.rs", + "status": "modified" + }, + { + "additions": 4, + "deletions": 0, + "patch_excerpt": "@@ -178,6 +178,7 @@ pub struct RemoteAppTemplate {\n pub template_id: String,\n pub name: String,\n pub description: Option,\n+ pub category: Option,\n pub canonical_connector_id: Option,\n pub logo_url: Option,\n pub logo_url_dark: Option,\n@@ -458,6 +459,8 @@ struct RemoteAppTemplateResponse {\n #[serde(default)]\n description: Option,\n #[serde(default)]\n+ category: Option,\n+ #[serde(default)]\n canonical_connector_id: Option,\n #[serde(default)]\n logo_url: Option,\n@@ -1059,6 +1062,7 @@ async fn build_remote_plugin_detail(\n template_id: template.template_id,\n name: template.name,\n description: template.description,\n+ category: template.category,\n canonical_connector_id: template.canonical_conn...", + "path": "codex-rs/core-plugins/src/remote.rs", + "status": "modified" + }, + { + "additions": 8, + "deletions": 1, + "patch_excerpt": "@@ -307,10 +307,17 @@ def validate_app_manifest(path: Path, errors: list[str]) -> None:\n if not isinstance(value, dict):\n errors.append(f\"`.app.json` app `{key}` must be an object\")\n continue\n- reject_companion_unknown_fields(value, {\"id\"}, f\"`.app.json` app `{key}`\", errors)\n+ reject_companion_unknown_fields(\n+ value, {\"id\", \"category\"}, f\"`.app.json` app `{key}`\", errors\n+ )\n app_id = value.get(\"id\")\n if not isinstance(app_id, str) or not app_id.strip():\n errors.append(f\"`.app.json` app `{key}` field `id` must be a non-empty string\")\n+ category = value.get(\"category\")\n+ if category is not None and (not isinstance(category, str) or not category.strip()):\n+ errors.append(\n+ f\"`.app.json` app `{key}` field `category` must be a non-empty string\"\n+ )...", + "path": "codex-rs/skills/src/assets/samples/plugin-creator/scripts/validate_plugin.py", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -1455,6 +1455,7 @@ pub(super) fn plugins_test_detail(\n name: (*name).to_string(),\n description: Some(format!(\"{name} app\")),\n install_url: Some(format!(\"https://example.test/{name}\")),\n+ category: None,\n })\n .collect(),\n app_templates: Vec::new(),", + "path": "codex-rs/tui/src/chatwidget/tests/helpers.rs", + "status": "modified" + } + ], + "linked_issues": [], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "## What\r\n- Parse optional `.app.json` `category` overrides for plugin apps.\r\n- Add nullable `category` to `AppSummary` and `AppTemplateSummary` in the app-server protocol.\r\n- Fall back from `branding.category` to the first non-empty `app_metadata.categories` value when building app/template summaries.\r\n- Regenerate schema/type fixtures and update plugin read/install tests.\r\n\r\n## Why\r\nThe plugin details UI needs a normalized per-app category. Some apps only provide their default category in metadata, while others need a local `.app.json` override.\r\n", + "labels": [], + "merged_at": "2026-06-11T17:34:41Z", + "number": 27420, + "state": "merged", + "title": "[codex] Propagate plugin app categories", + "url": "https://github.com/openai/codex/pull/27420" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/bundles/openai-codex-pr-27424.json b/artifacts/github/bundles/openai-codex-pr-27424.json new file mode 100644 index 000000000..748178e7b --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-27424.json @@ -0,0 +1,435 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "anp-oai", + "committed_at": "2026-06-11T17:37:42Z", + "message": "Migrate ExecutorFileSystem paths to PathUri", + "sha": "32d2f04abebfd51a0062e3b68710bd60b5a51c98", + "url": "https://github.com/openai/codex/commit/32d2f04abebfd51a0062e3b68710bd60b5a51c98" + } + ], + "default_branch": "main", + "docs_refs": [], + "examples_refs": [], + "extracted_flags": [ + "API", + "JSON", + "JSONRPCE", + "CONFIG_TOML_FILE", + "LOCAL_FS", + "TOOL_MENTION_SIGIL", + "AGENTS_DIR_NAME", + "SKILLS_DIR_NAME", + "URI", + "SKILLS_METADATA_DIR", + "SKILLS_METADATA_FILENAME", + "HIERARCHICAL_AGENTS_MESSAGE", + "LOCAL_AGENTS_MD_FILENAME", + "DEFAULT_AGENTS_MD_FILENAME", + "AGENTS", + "WORKFLOW", + "PROJECT_INSTRUCTIONS", + "NEW_PROJECT_INSTRUCTIONS", + "CODEX_LINUX_SANDBOX_ARG0", + "UNIX_EPOCH", + "SKILL", + "REMOTE_ENVIRONMENT_ID", + "STANDARD", + "FS_WRITE_FILE_METHOD", + "UNC", + "FS_CANONICALIZE_METHOD", + "MAX_READ_FILE_BYTES", + "JSONRPCM", + "JSONRPCR", + "FS_READ_FILE_METHOD", + "INITIALIZE_METHOD", + "INITIALIZED_METHOD", + "URL", + "TODO", + "SKILL_CONTENTS", + "UTF", + "DISCOVERABLE_PLUGIN_MANIFEST_PATHS" + ], + "files": [ + { + "additions": 11, + "deletions": 0, + "patch_excerpt": "@@ -2004,6 +2004,7 @@ dependencies = [\n \"codex-utils-cargo-bin\",\n \"codex-utils-cli\",\n \"codex-utils-json-to-toml\",\n+ \"codex-utils-path-uri\",\n \"codex-utils-pty\",\n \"codex-web-search-extension\",\n \"codex-windows-sandbox\",\n@@ -2183,6 +2184,7 @@ dependencies = [\n \"codex-exec-server\",\n \"codex-utils-absolute-path\",\n \"codex-utils-cargo-bin\",\n+ \"codex-utils-path-uri\",\n \"pretty_assertions\",\n \"similar\",\n \"tempfile\",\n@@ -2515,6 +2517,7 @@ dependencies = [\n \"codex-protocol\",\n \"codex-utils-absolute-path\",\n \"codex-utils-path\",\n+ \"codex-utils-path-uri\",\n \"core-foundation 0.9.4\",\n \"dns-lookup\",\n \"dunce\",\n@@ -2634,6 +2637,7 @@ dependencies = [\n \"codex-utils-image\",\n \"codex-utils-output-truncation\",\n \"codex-utils-path\",\n+ \"codex-utils-path-uri\",\n \"codex-utils-plugins\",\n \"codex-utils-pty\",\n \"codex-utils-stream-parser\",\n@@ -2768,6 +2772,7 @@ dependencies = [\n \"codex-skills\",\n \"codex-u...", + "path": "codex-rs/Cargo.lock", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -237,6 +237,7 @@ codex-utils-json-to-toml = { path = \"utils/json-to-toml\" }\n codex-utils-oss = { path = \"utils/oss\" }\n codex-utils-output-truncation = { path = \"utils/output-truncation\" }\n codex-utils-path = { path = \"utils/path-utils\" }\n+codex-utils-path-uri = { path = \"utils/path-uri\" }\n codex-utils-plugins = { path = \"utils/plugins\" }\n codex-utils-pty = { path = \"utils/pty\" }\n codex-utils-rustls-provider = { path = \"utils/rustls-provider\" }", + "path": "codex-rs/Cargo.toml", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -76,6 +76,7 @@ codex-thread-store = { workspace = true }\n codex-tools = { workspace = true }\n codex-utils-absolute-path = { workspace = true }\n codex-utils-json-to-toml = { workspace = true }\n+codex-utils-path-uri = { workspace = true }\n chrono = { workspace = true }\n clap = { workspace = true, features = [\"derive\"] }\n futures = { workspace = true }", + "path": "codex-rs/app-server/Cargo.toml", + "status": "modified" + }, + { + "additions": 18, + "deletions": 8, + "patch_excerpt": "@@ -29,6 +29,7 @@ use codex_exec_server::CreateDirectoryOptions;\n use codex_exec_server::EnvironmentManager;\n use codex_exec_server::ExecutorFileSystem;\n use codex_exec_server::RemoveOptions;\n+use codex_utils_path_uri::PathUri;\n use std::io;\n use std::sync::Arc;\n \n@@ -64,9 +65,10 @@ impl FsRequestProcessor {\n &self,\n params: FsReadFileParams,\n ) -> Result {\n+ let path = PathUri::from_abs_path(¶ms.path).map_err(map_fs_error)?;\n let bytes = self\n .file_system()?\n- .read_file(¶ms.path, /*sandbox*/ None)\n+ .read_file(&path, /*sandbox*/ None)\n .await\n .map_err(map_fs_error)?;\n Ok(FsReadFileResponse {\n@@ -83,8 +85,9 @@ impl FsRequestProcessor {\n \"fs/writeFile requires valid base64 dataBase64: {err}\"\n ))\n })?;\n+ ...", + "path": "codex-rs/app-server/src/request_processors/fs_processor.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -20,6 +20,7 @@ workspace = true\n anyhow = { workspace = true }\n codex-exec-server = { workspace = true }\n codex-utils-absolute-path = { workspace = true }\n+codex-utils-path-uri = { workspace = true }\n similar = { workspace = true }\n thiserror = { workspace = true }\n tokio = { workspace = true, features = [\"macros\", \"rt\"] }", + "path": "codex-rs/apply-patch/Cargo.toml", + "status": "modified" + }, + { + "additions": 13, + "deletions": 1, + "patch_excerpt": "@@ -21,6 +21,7 @@ use crate::parser::Hunk;\n use crate::parser::ParseError;\n use crate::parser::parse_patch;\n use crate::unified_diff_from_chunks;\n+use codex_utils_path_uri::PathUri;\n use std::str::Utf8Error;\n use tree_sitter::LanguageError;\n \n@@ -185,7 +186,18 @@ pub async fn verify_apply_patch_args(\n );\n }\n Hunk::DeleteFile { .. } => {\n- let content = match fs.read_file_text(&path, sandbox).await {\n+ let path_uri = match PathUri::from_abs_path(&path) {\n+ Ok(path_uri) => path_uri,\n+ Err(e) => {\n+ return MaybeApplyPatchVerified::CorrectnessError(\n+ ApplyPatchError::IoError(IoError {\n+ context: format!(\"Failed to read {}\", path.display()),\n+ source: e,\n+ ...", + "path": "codex-rs/apply-patch/src/invocation.rs", + "status": "modified" + }, + { + "additions": 32, + "deletions": 12, + "patch_excerpt": "@@ -16,6 +16,7 @@ use codex_exec_server::ExecutorFileSystem;\n use codex_exec_server::FileSystemSandboxContext;\n use codex_exec_server::RemoveOptions;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n pub use parser::Hunk;\n pub use parser::ParseError;\n use parser::ParseError::*;\n@@ -390,6 +391,7 @@ async fn apply_hunks_to_files(\n for hunk in hunks {\n let affected_path = hunk.path().to_path_buf();\n let path_abs = hunk.resolve_path(cwd);\n+ let path_uri = PathUri::from_abs_path(&path_abs)?;\n match hunk {\n Hunk::AddFile { contents, .. } => {\n let overwritten_content =\n@@ -415,7 +417,7 @@ async fn apply_hunks_to_files(\n }\n Hunk::DeleteFile { .. } => {\n note_existing_path_delta_support(&path_abs, fs, sandbox, &mut delta.exact).await;\n- let del...", + "path": "codex-rs/apply-patch/src/lib.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -25,6 +25,7 @@ codex-network-proxy = { workspace = true }\n codex-protocol = { workspace = true }\n codex-utils-absolute-path = { workspace = true }\n codex-utils-path = { workspace = true }\n+codex-utils-path-uri = { workspace = true }\n dunce = { workspace = true }\n futures = { workspace = true, features = [\"alloc\", \"std\"] }\n gethostname = { workspace = true }", + "path": "codex-rs/config/Cargo.toml", + "status": "modified" + }, + { + "additions": 3, + "deletions": 1, + "patch_excerpt": "@@ -10,6 +10,7 @@ use crate::strict_config::config_error_from_ignored_toml_value_fields;\n use codex_file_system::ExecutorFileSystem;\n use codex_utils_absolute_path::AbsolutePathBuf;\n use codex_utils_absolute_path::AbsolutePathBufGuard;\n+use codex_utils_path_uri::PathUri;\n use std::io;\n use std::path::Path;\n use std::path::PathBuf;\n@@ -106,7 +107,8 @@ pub(super) async fn read_config_from_path(\n log_missing_as_info: bool,\n strict_config: bool,\n ) -> io::Result> {\n- match fs.read_file_text(path, /*sandbox*/ None).await {\n+ let path_uri = PathUri::from_abs_path(path)?;\n+ match fs.read_file_text(&path_uri, /*sandbox*/ None).await {\n Ok(contents) => match toml::from_str::(&contents) {\n Ok(value) => {\n if strict_config {", + "path": "codex-rs/config/src/loader/layer_io.rs", + "status": "modified" + }, + { + "additions": 21, + "deletions": 8, + "patch_excerpt": "@@ -40,6 +40,7 @@ use codex_protocol::config_types::TrustLevel;\n use codex_protocol::protocol::AskForApproval;\n use codex_utils_absolute_path::AbsolutePathBuf;\n use codex_utils_absolute_path::AbsolutePathBufGuard;\n+use codex_utils_path_uri::PathUri;\n use dunce::canonicalize as normalize_path;\n use serde::Deserialize;\n use std::io;\n@@ -471,7 +472,8 @@ async fn load_config_toml_for_required_layer(\n strict_config: bool,\n create_entry: impl FnOnce(TomlValue) -> ConfigLayerEntry,\n ) -> io::Result {\n- let toml_value = match fs.read_file_text(toml_file, /*sandbox*/ None).await {\n+ let toml_file_uri = PathUri::from_abs_path(toml_file)?;\n+ let toml_value = match fs.read_file_text(&toml_file_uri, /*sandbox*/ None).await {\n Ok(contents) => {\n let config_parent = toml_file.as_path().parent().ok_or_else(|| {\n io::Error::new(\n@@ -5...", + "path": "codex-rs/config/src/loader/mod.rs", + "status": "modified" + }, + { + "additions": 15, + "deletions": 24, + "patch_excerpt": "@@ -7,8 +7,8 @@ use codex_file_system::FileSystemResult;\n use codex_file_system::FileSystemSandboxContext;\n use codex_file_system::ReadDirectoryEntry;\n use codex_file_system::RemoveOptions;\n+use codex_utils_path_uri::PathUri;\n use pretty_assertions::assert_eq;\n-use std::path::Path;\n use tempfile::tempdir;\n \n struct TestFileSystem;\n@@ -17,35 +17,26 @@ struct TestFileSystem;\n impl ExecutorFileSystem for TestFileSystem {\n async fn canonicalize(\n &self,\n- path: &AbsolutePathBuf,\n+ path: &PathUri,\n _sandbox: Option<&FileSystemSandboxContext>,\n- ) -> FileSystemResult {\n- path.canonicalize()\n- }\n-\n- async fn join(\n- &self,\n- base_path: &AbsolutePathBuf,\n- path: &Path,\n- ) -> FileSystemResult {\n- Ok(base_path.join(path))\n- }\n-\n- async fn parent(&self, path: &AbsolutePathBuf) -...", + "path": "codex-rs/config/src/loader/tests.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -26,6 +26,7 @@ codex-protocol = { workspace = true }\n codex-skills = { workspace = true }\n codex-utils-absolute-path = { workspace = true }\n codex-utils-output-truncation = { workspace = true }\n+codex-utils-path-uri = { workspace = true }\n codex-utils-plugins = { workspace = true }\n dirs = { workspace = true }\n dunce = { workspace = true }", + "path": "codex-rs/core-skills/Cargo.toml", + "status": "modified" + }, + { + "additions": 16, + "deletions": 4, + "patch_excerpt": "@@ -13,6 +13,7 @@ use codex_exec_server::LOCAL_FS;\n use codex_otel::SessionTelemetry;\n use codex_protocol::user_input::UserInput;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n use codex_utils_plugins::mention_syntax::TOOL_MENTION_SIGIL;\n \n #[derive(Debug, Default)]\n@@ -75,10 +76,21 @@ pub async fn build_skill_injections(\n let fs = loaded_skills\n .and_then(|outcome| outcome.file_system_for_skill(skill))\n .unwrap_or_else(|| Arc::clone(&LOCAL_FS));\n- match fs\n- .read_file_text(&skill.path_to_skills_md, /*sandbox*/ None)\n- .await\n- {\n+ // Skill metadata may point at a file that is absent, but a path the host\n+ // cannot represent means the configured skill cannot be loaded correctly.\n+ let path = match PathUri::from_abs_path(&skill.path_to_skills_md) {\n+ ...", + "path": "codex-rs/core-skills/src/injection.rs", + "status": "modified" + }, + { + "additions": 80, + "deletions": 10, + "patch_excerpt": "@@ -19,6 +19,7 @@ use codex_protocol::protocol::Product;\n use codex_protocol::protocol::SkillScope;\n use codex_utils_absolute_path::AbsolutePathBuf;\n use codex_utils_absolute_path::AbsolutePathBufGuard;\n+use codex_utils_path_uri::PathUri;\n use codex_utils_plugins::PluginSkillRoot;\n use codex_utils_plugins::plugin_namespace_for_skill_path;\n use dirs::home_dir;\n@@ -374,7 +375,17 @@ async fn repo_agents_skill_roots(\n let mut roots = Vec::new();\n for dir in dirs {\n let agents_skills = dir.join(AGENTS_DIR_NAME).join(SKILLS_DIR_NAME);\n- match fs.get_metadata(&agents_skills, /*sandbox*/ None).await {\n+ let agents_skills_uri = match PathUri::from_abs_path(&agents_skills) {\n+ Ok(path) => path,\n+ Err(err) => {\n+ tracing::warn!(\n+ \"failed to convert repo skills root {} to URI: {err:#}\",\n+ agents...", + "path": "codex-rs/core-skills/src/loader.rs", + "status": "modified" + }, + { + "additions": 3, + "deletions": 2, + "patch_excerpt": "@@ -9,6 +9,7 @@ use codex_exec_server::LOCAL_FS;\n use codex_protocol::protocol::Product;\n use codex_protocol::protocol::SkillScope;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n \n #[derive(Debug, Clone, PartialEq)]\n pub struct SkillMetadata {\n@@ -152,8 +153,8 @@ impl HostLoadedSkills {\n .outcome\n .file_system_for_skill(skill)\n .unwrap_or_else(|| Arc::clone(&LOCAL_FS));\n- fs.read_file_text(&skill.path_to_skills_md, /*sandbox*/ None)\n- .await\n+ let path = PathUri::from_abs_path(&skill.path_to_skills_md)?;\n+ fs.read_file_text(&path, /*sandbox*/ None).await\n }\n }", + "path": "codex-rs/core-skills/src/model.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -70,6 +70,7 @@ codex-utils-image = { workspace = true }\n codex-utils-home-dir = { workspace = true }\n codex-utils-output-truncation = { workspace = true }\n codex-utils-path = { workspace = true }\n+codex-utils-path-uri = { workspace = true }\n codex-utils-plugins = { workspace = true }\n codex-utils-pty = { workspace = true }\n codex-utils-string = { workspace = true }", + "path": "codex-rs/core/Cargo.toml", + "status": "modified" + }, + { + "additions": 26, + "deletions": 10, + "patch_excerpt": "@@ -26,6 +26,7 @@ use codex_exec_server::ExecutorFileSystem;\n use codex_features::Feature;\n use codex_prompts::HIERARCHICAL_AGENTS_MESSAGE;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n use std::io;\n use toml::Value as TomlValue;\n use tracing::error;\n@@ -58,7 +59,19 @@ impl<'a> AgentsMdManager<'a> {\n let base = codex_dir?;\n for candidate in [LOCAL_AGENTS_MD_FILENAME, DEFAULT_AGENTS_MD_FILENAME] {\n let path = base.join(candidate);\n- let data = match fs.read_file(&path, /*sandbox*/ None).await {\n+ // A missing global instructions file is normal, but an unrepresentable\n+ // configured path means Codex cannot honor the workspace configuration.\n+ let path_uri = match PathUri::from_abs_path(&path) {\n+ Ok(path_uri) => path_uri,\n+ Err(err) => {\n+ ...", + "path": "codex-rs/core/src/agents_md.rs", + "status": "modified" + }, + { + "additions": 7, + "deletions": 3, + "patch_excerpt": "@@ -7,6 +7,7 @@ use codex_config::config_toml::ConfigToml;\n use codex_exec_server::ExecutorFileSystem;\n use codex_utils_absolute_path::AbsolutePathBuf;\n use codex_utils_absolute_path::AbsolutePathBufGuard;\n+use codex_utils_path_uri::PathUri;\n use serde::Deserialize;\n use std::collections::BTreeMap;\n use std::collections::BTreeSet;\n@@ -319,7 +320,8 @@ async fn read_resolved_agent_role_file(\n path: &AbsolutePathBuf,\n role_name_hint: Option<&str>,\n ) -> std::io::Result {\n- let contents = fs.read_file_text(path, /*sandbox*/ None).await?;\n+ let path_uri = PathUri::from_abs_path(path)?;\n+ let contents = fs.read_file_text(&path_uri, /*sandbox*/ None).await?;\n let config_base_dir = path.parent().unwrap_or_else(|| path.clone());\n parse_agent_role_file_contents(\n &contents,\n@@ -391,8 +393,9 @@ async fn validate_agent_role_config_file(\n ...", + "path": "codex-rs/core/src/config/agent_roles.rs", + "status": "modified" + }, + { + "additions": 3, + "deletions": 1, + "patch_excerpt": "@@ -105,6 +105,7 @@ use codex_protocol::protocol::SandboxPolicy;\n pub use codex_thread_store::ExtraConfig;\n use codex_utils_absolute_path::AbsolutePathBuf;\n use codex_utils_absolute_path::AbsolutePathBufGuard;\n+use codex_utils_path_uri::PathUri;\n use rmcp::model::ElicitationCapability;\n use rmcp::model::FormElicitationCapability;\n use rmcp::model::UrlElicitationCapability;\n@@ -3667,8 +3668,9 @@ impl Config {\n return Ok(None);\n };\n \n+ let path_uri = PathUri::from_abs_path(path)?;\n let contents = fs\n- .read_file_text(path, /*sandbox*/ None)\n+ .read_file_text(&path_uri, /*sandbox*/ None)\n .await\n .map_err(|e| {\n std::io::Error::new(", + "path": "codex-rs/core/src/config/mod.rs", + "status": "modified" + }, + { + "additions": 9, + "deletions": 2, + "patch_excerpt": "@@ -27,6 +27,7 @@ use crate::tools::registry::CoreToolRuntime;\n use crate::tools::registry::ToolExecutor;\n use codex_tools::ToolName;\n use codex_tools::ToolSpec;\n+use codex_utils_path_uri::PathUri;\n \n pub struct ViewImageHandler {\n options: ViewImageToolOptions,\n@@ -146,9 +147,15 @@ impl ViewImageHandler {\n let abs_path = cwd.join(path);\n let sandbox = turn.file_system_sandbox_context(/*additional_permissions*/ None, &cwd);\n let fs = turn_environment.environment.get_filesystem();\n+ let path_uri = PathUri::from_abs_path(&abs_path).map_err(|error| {\n+ FunctionCallError::RespondToModel(format!(\n+ \"unable to locate image at `{}`: {error}\",\n+ abs_path.display()\n+ ))\n+ })?;\n \n let metadata = fs\n- .get_metadata(&abs_path, Some(&sandbox))\n+ .get_metadata(&path_uri, Some(&sa...", + "path": "codex-rs/core/src/tools/handlers/view_image.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -28,6 +28,7 @@ codex-models-manager = { workspace = true }\n codex-protocol = { workspace = true }\n codex-utils-absolute-path = { workspace = true }\n codex-utils-cargo-bin = { workspace = true }\n+codex-utils-path-uri = { workspace = true }\n ctor = { workspace = true }\n futures = { workspace = true }\n notify = { workspace = true }", + "path": "codex-rs/core/tests/common/Cargo.toml", + "status": "modified" + }, + { + "additions": 26, + "deletions": 7, + "patch_excerpt": "@@ -43,6 +43,7 @@ use codex_protocol::protocol::TurnEnvironmentSelection;\n use codex_protocol::protocol::TurnEnvironmentSelections;\n use codex_protocol::user_input::UserInput;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n use futures::future::BoxFuture;\n use serde_json::Value;\n use tempfile::TempDir;\n@@ -135,10 +136,11 @@ pub async fn test_env() -> Result {\n let environment =\n codex_exec_server::Environment::create_for_tests(Some(websocket_url.clone()))?;\n let cwd = remote_aware_cwd_path();\n+ let cwd_uri = PathUri::from_path(&cwd)?;\n environment\n .get_filesystem()\n .create_directory(\n- &cwd,\n+ &cwd_uri,\n CreateDirectoryOptions { recursive: true },\n /*sandbox*/ None,\n ...", + "path": "codex-rs/core/tests/common/test_codex.rs", + "status": "modified" + }, + { + "additions": 37, + "deletions": 14, + "patch_excerpt": "@@ -7,6 +7,7 @@ use codex_protocol::protocol::EventMsg;\n use codex_protocol::protocol::Op;\n use codex_protocol::user_input::UserInput;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n use core_test_support::PathBufExt;\n use core_test_support::create_directory_symlink;\n use core_test_support::load_default_config_for_test;\n@@ -112,10 +113,12 @@ async fn agents_override_is_preferred_over_agents_md() -> Result<()> {\n agents_instructions(test_codex().with_workspace_setup(|cwd, fs| async move {\n let agents_md = cwd.join(\"AGENTS.md\");\n let override_md = cwd.join(\"AGENTS.override.md\");\n- fs.write_file(&agents_md, b\"base doc\".to_vec(), /*sandbox*/ None)\n+ let agents_md_uri = PathUri::from_path(&agents_md)?;\n+ let override_md_uri = PathUri::from_path(&override_md)?;\n+ fs.write_file(&age...", + "path": "codex-rs/core/tests/suite/agents_md.rs", + "status": "modified" + }, + { + "additions": 18, + "deletions": 13, + "patch_excerpt": "@@ -38,6 +38,7 @@ use codex_protocol::user_input::UserInput;\n #[cfg(target_os = \"linux\")]\n use codex_sandboxing::landlock::CODEX_LINUX_SANDBOX_ARG0;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n use core_test_support::PathBufExt;\n use core_test_support::assert_regex_match;\n use core_test_support::get_remote_test_env;\n@@ -1329,25 +1330,24 @@ async fn apply_patch_turn_diff_paths_stay_repo_relative_when_session_cwd_is_nest\n config.cwd = config.cwd.join(\"subdir\");\n })\n .with_workspace_setup(|cwd, fs| async move {\n+ let cwd_uri = PathUri::from_path(&cwd)?;\n fs.create_directory(\n- &cwd,\n+ &cwd_uri,\n CreateDirectoryOptions { recursive: true },\n /*sandbox*/ None,\n )\n .await?;\n ...", + "path": "codex-rs/core/tests/suite/apply_patch_cli.rs", + "status": "modified" + }, + { + "additions": 3, + "deletions": 1, + "patch_excerpt": "@@ -1,4 +1,5 @@\n use codex_features::Feature;\n+use codex_utils_path_uri::PathUri;\n use core_test_support::responses::ev_completed;\n use core_test_support::responses::ev_response_created;\n use core_test_support::responses::mount_sse_once;\n@@ -27,7 +28,8 @@ async fn hierarchical_agents_appends_to_project_doc_in_user_instructions() {\n })\n .with_workspace_setup(|cwd, fs| async move {\n let agents_md = cwd.join(\"AGENTS.md\");\n- fs.write_file(&agents_md, b\"be nice\".to_vec(), /*sandbox*/ None)\n+ let agents_md_uri = PathUri::from_path(&agents_md)?;\n+ fs.write_file(&agents_md_uri, b\"be nice\".to_vec(), /*sandbox*/ None)\n .await?;\n Ok::<(), anyhow::Error>(())\n });", + "path": "codex-rs/core/tests/suite/hierarchical_agents.rs", + "status": "modified" + }, + { + "additions": 57, + "deletions": 33, + "patch_excerpt": "@@ -28,6 +28,7 @@ use codex_protocol::request_permissions::RequestPermissionProfile;\n use codex_protocol::request_permissions::RequestPermissionsResponse;\n use codex_protocol::user_input::UserInput;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n use core_test_support::PathBufExt;\n use core_test_support::PathExt;\n use core_test_support::get_remote_test_env;\n@@ -155,19 +156,20 @@ async fn remote_test_env_can_connect_and_use_filesystem() -> Result<()> {\n let file_system = test_env.environment().get_filesystem();\n \n let file_path_abs = remote_test_file_path().abs();\n+ let file_path_uri = PathUri::from_path(&file_path_abs)?;\n let payload = b\"remote-test-env-ok\".to_vec();\n \n file_system\n- .write_file(&file_path_abs, payload.clone(), /*sandbox*/ None)\n+ .write_file(&file_path_uri, payload.clone(), /*sandbox*/ None)\n ...", + "path": "codex-rs/core/tests/suite/remote_env.rs", + "status": "modified" + }, + { + "additions": 4, + "deletions": 1, + "patch_excerpt": "@@ -48,6 +48,7 @@ use codex_protocol::protocol::McpToolCallBeginEvent;\n use codex_protocol::protocol::Op;\n use codex_protocol::user_input::UserInput;\n use codex_utils_cargo_bin::cargo_bin;\n+use codex_utils_path_uri::PathUri;\n use core_test_support::assert_regex_match;\n use core_test_support::remote_env_env_var;\n use core_test_support::responses;\n@@ -625,8 +626,10 @@ async fn stdio_server_uses_configured_cwd_before_runtime_fallback() -> anyhow::R\n \n let fixture = test_codex()\n .with_workspace_setup(|cwd, fs| async move {\n+ let configured_cwd = cwd.join(\"mcp-configured-cwd\");\n+ let configured_cwd_uri = PathUri::from_path(&configured_cwd)?;\n fs.create_directory(\n- &cwd.join(\"mcp-configured-cwd\"),\n+ &configured_cwd_uri,\n CreateDirectoryOptions { recursive: true },\n /*sandbox*/ None,\n ...", + "path": "codex-rs/core/tests/suite/rmcp_client.rs", + "status": "modified" + }, + { + "additions": 5, + "deletions": 2, + "patch_excerpt": "@@ -9,6 +9,7 @@ use codex_protocol::protocol::AskForApproval;\n use codex_protocol::protocol::Op;\n use codex_protocol::user_input::UserInput;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n use core_test_support::responses::ev_assistant_message;\n use core_test_support::responses::ev_completed;\n use core_test_support::responses::ev_response_created;\n@@ -29,15 +30,17 @@ async fn write_repo_skill(\n body: &str,\n ) -> Result<()> {\n let skill_dir = cwd.join(\".agents\").join(\"skills\").join(name);\n+ let skill_dir_uri = PathUri::from_path(&skill_dir)?;\n fs.create_directory(\n- &skill_dir,\n+ &skill_dir_uri,\n CreateDirectoryOptions { recursive: true },\n /*sandbox*/ None,\n )\n .await?;\n let contents = format!(\"---\\nname: {name}\\ndescription: {description}\\n---\\n\\n{body}\\n\");\n let path = skill_dir.join(\"SKI...", + "path": "codex-rs/core/tests/suite/skills.rs", + "status": "modified" + }, + { + "additions": 3, + "deletions": 1, + "patch_excerpt": "@@ -17,6 +17,7 @@ use codex_protocol::protocol::ExecCommandSource;\n use codex_protocol::protocol::ExecCommandStatus;\n use codex_protocol::protocol::Op;\n use codex_protocol::user_input::UserInput;\n+use codex_utils_path_uri::PathUri;\n use core_test_support::TempDirExt;\n use core_test_support::assert_regex_match;\n use core_test_support::managed_network_requirements_loader;\n@@ -228,9 +229,10 @@ async fn create_workspace_directory(\n rel_path: impl AsRef,\n ) -> Result {\n let abs_path = test.config.cwd.join(rel_path.as_ref());\n+ let abs_path_uri = PathUri::from_path(&abs_path)?;\n test.fs()\n .create_directory(\n- &abs_path,\n+ &abs_path_uri,\n CreateDirectoryOptions { recursive: true },\n /*sandbox*/ None,\n )", + "path": "codex-rs/core/tests/suite/unified_exec.rs", + "status": "modified" + }, + { + "additions": 12, + "deletions": 6, + "patch_excerpt": "@@ -29,6 +29,7 @@ use codex_protocol::protocol::EventMsg;\n use codex_protocol::protocol::Op;\n use codex_protocol::protocol::TurnEnvironmentSelection;\n use codex_protocol::user_input::UserInput;\n+use codex_utils_path_uri::PathUri;\n use core_test_support::PathBufExt;\n use core_test_support::PathExt;\n use core_test_support::get_remote_test_env;\n@@ -134,9 +135,10 @@ fn png_bytes(width: u32, height: u32, rgba: [u8; 4]) -> anyhow::Result>\n \n async fn create_workspace_directory(test: &TestCodex, rel_path: &str) -> anyhow::Result {\n let abs_path = test.config.cwd.join(rel_path);\n+ let abs_path_uri = PathUri::from_path(&abs_path)?;\n test.fs()\n .create_directory(\n- &abs_path,\n+ &abs_path_uri,\n CreateDirectoryOptions { recursive: true },\n /*sandbox*/ None,\n )\n@@ -151,16 +153,18 @@ async fn write_workspace_file...", + "path": "codex-rs/core/tests/suite/view_image.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -24,6 +24,7 @@ codex-protocol = { workspace = true }\n codex-sandboxing = { workspace = true }\n codex-shell-command = { workspace = true }\n codex-utils-absolute-path = { workspace = true }\n+codex-utils-path-uri = { workspace = true }\n codex-utils-pty = { workspace = true }\n codex-utils-rustls-provider = { workspace = true }\n futures = { workspace = true }", + "path": "codex-rs/exec-server/Cargo.toml", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -882,6 +882,7 @@ mod tests {\n std::env::current_exe().expect(\"current exe\").as_path(),\n )\n .expect(\"absolute current exe\");\n+ let path = codex_utils_path_uri::PathUri::from_abs_path(&path).expect(\"path URI\");\n let sandbox = crate::FileSystemSandboxContext::from_permission_profile(\n codex_protocol::models::PermissionProfile::from_runtime_permissions(\n &codex_protocol::permissions::FileSystemSandboxPolicy::restricted(Vec::new()),", + "path": "codex-rs/exec-server/src/environment.rs", + "status": "modified" + }, + { + "additions": 90, + "deletions": 21, + "patch_excerpt": "@@ -189,30 +189,36 @@ pub(crate) async fn run_direct_request(\n let file_system = DirectFileSystem;\n match request {\n FsHelperRequest::ReadFile(params) => {\n+ let path =\n+ codex_utils_path_uri::PathUri::from_abs_path(¶ms.path).map_err(map_fs_error)?;\n let data = file_system\n- .read_file(¶ms.path, /*sandbox*/ None)\n+ .read_file(&path, /*sandbox*/ None)\n .await\n .map_err(map_fs_error)?;\n Ok(FsHelperPayload::ReadFile(FsReadFileResponse {\n data_base64: STANDARD.encode(data),\n }))\n }\n FsHelperRequest::WriteFile(params) => {\n+ let path =\n+ codex_utils_path_uri::PathUri::from_abs_path(¶ms.path).map_err(map_fs_error)?;\n let bytes = STANDARD.decode(params.data_base64).map_err(|er...", + "path": "codex-rs/exec-server/src/fs_helper.rs", + "status": "modified" + }, + { + "additions": 47, + "deletions": 69, + "patch_excerpt": "@@ -1,5 +1,6 @@\n use async_trait::async_trait;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n use std::path::Path;\n use std::path::PathBuf;\n use std::sync::Arc;\n@@ -81,28 +82,16 @@ impl LocalFileSystem {\n impl ExecutorFileSystem for LocalFileSystem {\n async fn canonicalize(\n &self,\n- path: &AbsolutePathBuf,\n+ path: &PathUri,\n sandbox: Option<&FileSystemSandboxContext>,\n- ) -> FileSystemResult {\n+ ) -> FileSystemResult {\n let (file_system, sandbox) = self.file_system_for(sandbox)?;\n file_system.canonicalize(path, sandbox).await\n }\n \n- async fn join(\n- &self,\n- base_path: &AbsolutePathBuf,\n- path: &Path,\n- ) -> FileSystemResult {\n- self.unsandboxed.join(base_path, path).await\n- }\n-\n- async fn parent(&self, path...", + "path": "codex-rs/exec-server/src/local_file_system.rs", + "status": "modified" + }, + { + "additions": 27, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,27 @@\n+use codex_utils_path_uri::PathUri;\n+use pretty_assertions::assert_eq;\n+use tokio::io;\n+\n+use super::*;\n+\n+#[tokio::test]\n+async fn direct_file_system_rejects_non_native_uri_as_invalid_input() {\n+ let error = DirectFileSystem\n+ .read_file(&non_native_uri(), /*sandbox*/ None)\n+ .await\n+ .expect_err(\"non-native URI should be rejected\");\n+\n+ assert_eq!(error.kind(), io::ErrorKind::InvalidInput);\n+}\n+\n+fn non_native_uri() -> PathUri {\n+ #[cfg(unix)]\n+ let uri = \"file://server/share/file.txt\";\n+ #[cfg(windows)]\n+ let uri = \"file:///usr/local/file.txt\";\n+\n+ match PathUri::parse(uri) {\n+ Ok(uri) => uri,\n+ Err(err) => panic!(\"valid non-native URI should parse: {err}\"),\n+ }\n+}", + "path": "codex-rs/exec-server/src/local_file_system_path_uri_tests.rs", + "status": "added" + }, + { + "additions": 35, + "deletions": 51, + "patch_excerpt": "@@ -1,8 +1,7 @@\n use async_trait::async_trait;\n use base64::Engine as _;\n use base64::engine::general_purpose::STANDARD;\n-use codex_utils_absolute_path::AbsolutePathBuf;\n-use std::path::Path;\n+use codex_utils_path_uri::PathUri;\n use tokio::io;\n use tracing::trace;\n \n@@ -20,8 +19,6 @@ use crate::protocol::FsCanonicalizeParams;\n use crate::protocol::FsCopyParams;\n use crate::protocol::FsCreateDirectoryParams;\n use crate::protocol::FsGetMetadataParams;\n-use crate::protocol::FsJoinParams;\n-use crate::protocol::FsParentParams;\n use crate::protocol::FsReadDirectoryParams;\n use crate::protocol::FsReadFileParams;\n use crate::protocol::FsRemoveParams;\n@@ -45,58 +42,33 @@ impl RemoteFileSystem {\n impl ExecutorFileSystem for RemoteFileSystem {\n async fn canonicalize(\n &self,\n- path: &AbsolutePathBuf,\n+ path: &PathUri,\n sandbox: Option<&FileSystemSandboxContext>,\n- ...", + "path": "codex-rs/exec-server/src/remote_file_system.rs", + "status": "modified" + }, + { + "additions": 225, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,225 @@\n+#![allow(clippy::expect_used)]\n+\n+#[cfg(windows)]\n+use codex_app_server_protocol::JSONRPCMessage;\n+#[cfg(windows)]\n+use codex_app_server_protocol::JSONRPCResponse;\n+#[cfg(windows)]\n+use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n+#[cfg(windows)]\n+use futures::SinkExt;\n+#[cfg(windows)]\n+use futures::StreamExt;\n+use pretty_assertions::assert_eq;\n+use tokio::io;\n+#[cfg(windows)]\n+use tokio::net::TcpListener;\n+#[cfg(windows)]\n+use tokio::net::TcpStream;\n+#[cfg(windows)]\n+use tokio::sync::oneshot;\n+#[cfg(windows)]\n+use tokio::time::Duration;\n+#[cfg(windows)]\n+use tokio::time::timeout;\n+#[cfg(windows)]\n+use tokio_tungstenite::WebSocketStream;\n+#[cfg(windows)]\n+use tokio_tungstenite::accept_async;\n+#[cfg(windows)]\n+use tokio_tungstenite::tungstenite::Message;\n+\n+use super::*;\n+use crate::client_api::ExecServerTransportParams;\n+#[cfg(window...", + "path": "codex-rs/exec-server/src/remote_file_system_path_uri_tests.rs", + "status": "added" + }, + { + "additions": 25, + "deletions": 34, + "patch_excerpt": "@@ -2,8 +2,7 @@ use async_trait::async_trait;\n use base64::Engine as _;\n use base64::engine::general_purpose::STANDARD;\n use codex_app_server_protocol::JSONRPCErrorError;\n-use codex_utils_absolute_path::AbsolutePathBuf;\n-use std::path::Path;\n+use codex_utils_path_uri::PathUri;\n use tokio::io;\n \n use crate::CopyOptions;\n@@ -55,47 +54,35 @@ impl SandboxedFileSystem {\n impl ExecutorFileSystem for SandboxedFileSystem {\n async fn canonicalize(\n &self,\n- path: &AbsolutePathBuf,\n+ path: &PathUri,\n sandbox: Option<&FileSystemSandboxContext>,\n- ) -> FileSystemResult {\n+ ) -> FileSystemResult {\n let sandbox = require_platform_sandbox(sandbox)?;\n let response = self\n .run_sandboxed(\n sandbox,\n FsHelperRequest::Canonicalize(FsCanonicalizeParams {\n- path: pa...", + "path": "codex-rs/exec-server/src/sandboxed_file_system.rs", + "status": "modified" + }, + { + "additions": 43, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,43 @@\n+use codex_protocol::models::PermissionProfile;\n+use codex_protocol::permissions::FileSystemSandboxPolicy;\n+use codex_protocol::permissions::NetworkSandboxPolicy;\n+use codex_utils_path_uri::PathUri;\n+use pretty_assertions::assert_eq;\n+use tokio::io;\n+\n+use super::*;\n+\n+#[tokio::test]\n+async fn sandboxed_file_system_rejects_non_native_uri_as_invalid_input() {\n+ let runtime_paths = ExecServerRuntimePaths::new(\n+ std::env::current_exe().expect(\"current exe\"),\n+ /*codex_linux_sandbox_exe*/ None,\n+ )\n+ .expect(\"runtime paths\");\n+ let file_system = SandboxedFileSystem::new(runtime_paths);\n+ let sandbox = FileSystemSandboxContext::from_permission_profile(\n+ PermissionProfile::from_runtime_permissions(\n+ &FileSystemSandboxPolicy::restricted(Vec::new()),\n+ NetworkSandboxPolicy::Restricted,\n+ ),\n+ );\n+\n+ let er...", + "path": "codex-rs/exec-server/src/sandboxed_file_system_path_uri_tests.rs", + "status": "added" + }, + { + "additions": 73, + "deletions": 19, + "patch_excerpt": "@@ -3,6 +3,7 @@ use std::io;\n use base64::Engine as _;\n use base64::engine::general_purpose::STANDARD;\n use codex_app_server_protocol::JSONRPCErrorError;\n+use codex_utils_path_uri::PathUri;\n \n use crate::CopyOptions;\n use crate::CreateDirectoryOptions;\n@@ -52,9 +53,10 @@ impl FileSystemHandler {\n &self,\n params: FsReadFileParams,\n ) -> Result {\n+ let path = PathUri::from_abs_path(¶ms.path).map_err(map_fs_error)?;\n let bytes = self\n .file_system\n- .read_file(¶ms.path, params.sandbox.as_ref())\n+ .read_file(&path, params.sandbox.as_ref())\n .await\n .map_err(map_fs_error)?;\n Ok(FsReadFileResponse {\n@@ -66,13 +68,14 @@ impl FileSystemHandler {\n &self,\n params: FsWriteFileParams,\n ) -> Result) -> AbsolutePathBuf {\n- let path = path.as_ref().to_path_buf();\n+pub(crate) fn absolute_path(path: std::path::PathBuf) -> AbsolutePathBuf {\n assert!(\n path.is_absolute(),\n \"path must be absolute: {}\",", + "path": "codex-rs/exec-server/tests/file_system/support.rs", + "status": "modified" + }, + { + "additions": 31, + "deletions": 27, + "patch_excerpt": "@@ -22,6 +22,7 @@ use codex_exec_server::CreateDirectoryOptions;\n #[cfg(target_os = \"linux\")]\n use codex_exec_server::Environment;\n use codex_exec_server::RemoveOptions;\n+use codex_utils_path_uri::PathUri;\n use pretty_assertions::assert_eq;\n use tempfile::TempDir;\n use test_case::test_case;\n@@ -30,7 +31,6 @@ use test_case::test_case;\n use crate::common::exec_server::exec_server_with_env;\n \n use crate::support::FileSystemImplementation;\n-use crate::support::absolute_path;\n use crate::support::create_file_system_context;\n use crate::support::read_only_sandbox;\n use crate::support::workspace_write_sandbox;\n@@ -185,7 +185,7 @@ async fn sandboxed_file_system_helper_finds_bwrap_on_preserved_path() -> Result<\n \n file_system\n .write_file(\n- &absolute_path(&file_path),\n+ &PathUri::from_path(&file_path)?,\n b\"written through fs helper\".to_vec(),\n ...", + "path": "codex-rs/exec-server/tests/file_system_unix.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -21,6 +21,7 @@ codex-mcp = { workspace = true }\n codex-protocol = { workspace = true }\n codex-tools = { workspace = true }\n codex-utils-absolute-path = { workspace = true }\n+codex-utils-path-uri = { workspace = true }\n codex-utils-string = { workspace = true }\n schemars = { workspace = true }\n serde = { workspace = true, features = [\"derive\"] }", + "path": "codex-rs/ext/skills/Cargo.toml", + "status": "modified" + }, + { + "additions": 8, + "deletions": 1, + "patch_excerpt": "@@ -10,6 +10,7 @@ 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+use codex_utils_path_uri::PathUri;\n \n use crate::catalog::SkillAuthority;\n use crate::catalog::SkillCatalog;\n@@ -130,9 +131,15 @@ impl SkillProvider for ExecutorSkillProvider {\n \"executor skill resource references unavailable environment `{environment_id}`\"\n )));\n };\n+ let resource_path = PathUri::from_abs_path(resource_path).map_err(|err| {\n+ SkillProviderError::new(format!(\n+ \"failed to read executor skill resource {}: {err}\",\n+ request.resource.as_str()\n+ ))\n+ })?;\n let contents = environment\n .get_filesystem()\n- ...", + "path": "codex-rs/ext/skills/src/provider/executor.rs", + "status": "modified" + }, + { + "additions": 21, + "deletions": 31, + "patch_excerpt": "@@ -1,5 +1,4 @@\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@@ -24,6 +23,7 @@ use codex_skills_extension::ExecutorSkillProvider;\n use codex_skills_extension::provider::SkillListQuery;\n use codex_skills_extension::provider::SkillProvider;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n use pretty_assertions::assert_eq;\n \n const SKILL_CONTENTS: &str =\n@@ -60,34 +60,23 @@ impl SyntheticFileSystem {\n impl ExecutorFileSystem for SyntheticFileSystem {\n async fn canonicalize(\n &self,\n- path: &AbsolutePathBuf,\n+ path: &PathUri,\n _sandbox: Option<&FileSystemSandboxContext>,\n- ) -> FileSystemResult {\n- if path == &self.alias_root {\n- return Ok(self.canonical_root.clone());\n+ ) -> FileSystemResult,\n- ) -> FileSystemResult;\n-\n- /// Lexically joins a path onto an existing bound path.\n- async fn join(\n- &self,\n- base_path: &AbsolutePathBuf,\n- path: &Path,\n- ) -> FileSystemResult;\n-\n- /// Returns the parent directory of a bound path.\n- async fn parent(&self,...", + "path": "codex-rs/file-system/src/lib.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -14,6 +14,7 @@ chrono = { workspace = true }\n codex-file-system = { workspace = true }\n codex-protocol = { workspace = true }\n codex-utils-absolute-path = { workspace = true }\n+codex-utils-path-uri = { workspace = true }\n futures = { workspace = true, features = [\"alloc\"] }\n gix = { workspace = true }\n once_cell = { workspace = true }", + "path": "codex-rs/git-utils/Cargo.toml", + "status": "modified" + }, + { + "additions": 15, + "deletions": 4, + "patch_excerpt": "@@ -6,6 +6,7 @@ use std::path::PathBuf;\n \n use codex_file_system::ExecutorFileSystem;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n use futures::future::join_all;\n use schemars::JsonSchema;\n use serde::Deserialize;\n@@ -46,7 +47,8 @@ pub async fn get_git_repo_root_with_fs(\n fs: &dyn ExecutorFileSystem,\n cwd: &AbsolutePathBuf,\n ) -> Option {\n- let base = match fs.get_metadata(cwd, /*sandbox*/ None).await {\n+ let cwd_uri = PathUri::from_abs_path(cwd).ok()?;\n+ let base = match fs.get_metadata(&cwd_uri, /*sandbox*/ None).await {\n Ok(metadata) if metadata.is_directory => cwd.clone(),\n _ => cwd.parent()?,\n };\n@@ -803,16 +805,20 @@ pub async fn resolve_root_git_project_for_trust(\n ) -> Option {\n let repo_root = get_git_repo_root_with_fs(fs, cwd).await?;\n let dot_git = repo_root....", + "path": "codex-rs/git-utils/src/info.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -17,6 +17,7 @@ workspace = true\n codex-exec-server = { workspace = true }\n codex-login = { workspace = true }\n codex-utils-absolute-path = { workspace = true }\n+codex-utils-path-uri = { workspace = true }\n serde = { workspace = true, features = [\"derive\"] }\n serde_json = { workspace = true }", + "path": "codex-rs/utils/plugins/Cargo.toml", + "status": "modified" + }, + { + "additions": 5, + "deletions": 2, + "patch_excerpt": "@@ -2,6 +2,7 @@\n \n use codex_exec_server::ExecutorFileSystem;\n use codex_utils_absolute_path::AbsolutePathBuf;\n+use codex_utils_path_uri::PathUri;\n use std::path::Path;\n use std::path::PathBuf;\n \n@@ -29,7 +30,8 @@ async fn plugin_manifest_name(\n let mut manifest_path = None;\n for relative_path in DISCOVERABLE_PLUGIN_MANIFEST_PATHS {\n let candidate = plugin_root.join(relative_path);\n- match fs.get_metadata(&candidate, /*sandbox*/ None).await {\n+ let candidate_uri = PathUri::from_abs_path(&candidate).ok()?;\n+ match fs.get_metadata(&candidate_uri, /*sandbox*/ None).await {\n Ok(metadata) if metadata.is_file => {\n manifest_path = Some(candidate);\n break;\n@@ -38,8 +40,9 @@ async fn plugin_manifest_name(\n }\n }\n let manifest_path = manifest_path?;\n+ let manifest_path_uri = PathUri::from_abs_path(&...", + "path": "codex-rs/utils/plugins/src/plugin_namespace.rs", + "status": "modified" + } + ], + "linked_issues": [], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "## Why\r\n\r\nWe're moving exec-server to use PathUri for its internal path representations.\r\n\r\n## What\r\n\r\nMove `ExecutorFileSystem` APIs to use `PathUri` instead of `AbsolutePathBuf`. Future changes will convert higher-level parts of exec-server.", + "labels": [], + "merged_at": "2026-06-11T18:44:19Z", + "number": 27424, + "state": "merged", + "title": "[codex] migrate ExecutorFileSystem paths to PathUri", + "url": "https://github.com/openai/codex/pull/27424" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/bundles/openai-codex-pr-27433.json b/artifacts/github/bundles/openai-codex-pr-27433.json new file mode 100644 index 000000000..619fcec2f --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-27433.json @@ -0,0 +1,78 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "anp-oai", + "committed_at": "2026-06-10T00:19:56Z", + "message": "Remove EnvironmentPathRef", + "sha": "a8e9807f4a94cf84b288c0c9ce2678788c9d3228", + "url": "https://github.com/openai/codex/commit/a8e9807f4a94cf84b288c0c9ce2678788c9d3228" + } + ], + "default_branch": "main", + "docs_refs": [], + "examples_refs": [], + "extracted_flags": [ + "LOCAL_FS", + "UTF", + "SKILL", + "LOCAL_ENVIRONMENT_ID", + "REMOTE_ENVIRONMENT_ID", + "CODEX_FS_HELPER_ARG1", + "SKILL_CONTENTS" + ], + "files": [ + { + "additions": 0, + "deletions": 527, + "patch_excerpt": "@@ -1,527 +0,0 @@\n-use std::fmt;\n-use std::hash::Hash;\n-use std::hash::Hasher;\n-use std::io;\n-use std::path::Path;\n-use std::sync::Arc;\n-\n-use codex_utils_absolute_path::AbsolutePathBuf;\n-\n-use crate::ExecutorFileSystem;\n-use crate::FileMetadata;\n-use crate::FileSystemSandboxContext;\n-use crate::LOCAL_FS;\n-use crate::ReadDirectoryEntry;\n-\n-/// Binds an absolute path to the executor filesystem that owns it.\n-#[derive(Clone)]\n-pub struct EnvironmentPathRef {\n- file_system: Arc,\n- path: AbsolutePathBuf,\n-}\n-\n-impl EnvironmentPathRef {\n- /// Creates a path ref bound to the filesystem that owns `path`.\n- pub fn new(file_system: Arc, path: AbsolutePathBuf) -> Self {\n- Self { file_system, path }\n- }\n-\n- /// Creates a path ref bound to the shared unsandboxed local filesystem.\n- pub fn local(path: AbsolutePathBuf) -> Self...", + "path": "codex-rs/exec-server/src/environment_path.rs", + "status": "removed" + }, + { + "additions": 0, + "deletions": 2, + "patch_excerpt": "@@ -3,7 +3,6 @@ mod client_api;\n mod client_transport;\n mod connection;\n mod environment;\n-mod environment_path;\n mod environment_provider;\n mod environment_toml;\n mod fs_helper;\n@@ -44,7 +43,6 @@ pub use environment::Environment;\n pub use environment::EnvironmentManager;\n pub use environment::LOCAL_ENVIRONMENT_ID;\n pub use environment::REMOTE_ENVIRONMENT_ID;\n-pub use environment_path::EnvironmentPathRef;\n pub use environment_provider::DefaultEnvironmentProvider;\n pub use environment_provider::EnvironmentProvider;\n pub use fs_helper::CODEX_FS_HELPER_ARG1;", + "path": "codex-rs/exec-server/src/lib.rs", + "status": "modified" + }, + { + "additions": 21, + "deletions": 6, + "patch_excerpt": "@@ -1,5 +1,5 @@\n use codex_core_skills::model::SkillDependencies;\n-use codex_exec_server::EnvironmentPathRef;\n+use codex_utils_absolute_path::AbsolutePathBuf;\n \n /// Source authority that owns a skill package and must be used to read it.\n #[derive(Clone, Debug, PartialEq, Eq, Hash)]\n@@ -62,7 +62,7 @@ pub struct SkillPackageId(pub String);\n #[derive(Clone, Debug, PartialEq, Eq, Hash)]\n pub struct SkillResourceId {\n id: String,\n- environment_path: Option,\n+ environment_path: Option,\n }\n \n impl SkillResourceId {\n@@ -73,22 +73,37 @@ impl SkillResourceId {\n }\n }\n \n- pub fn environment(id: impl Into, path: EnvironmentPathRef) -> Self {\n+ pub fn environment(\n+ id: impl Into,\n+ environment_id: impl Into,\n+ path: AbsolutePathBuf,\n+ ) -> Self {\n Self {\n id: ...", + "path": "codex-rs/ext/skills/src/catalog.rs", + "status": "modified" + }, + { + "additions": 13, + "deletions": 7, + "patch_excerpt": "@@ -6,7 +6,6 @@ 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@@ -99,7 +98,7 @@ impl SkillProvider for ExecutorSkillProvider {\n enabled,\n authority.clone(),\n &selected_root_id,\n- Arc::clone(&file_system),\n+ &environment_id,\n ));\n }\n }\n@@ -121,13 +120,19 @@ impl SkillProvider for ExecutorSkillProvider {\n \"executor skill resource does not match its package\",\n ...", + "path": "codex-rs/ext/skills/src/provider/executor.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 60, + "patch_excerpt": "@@ -21,10 +21,8 @@ use codex_protocol::capabilities::CapabilityRootLocation;\n use codex_protocol::capabilities::SelectedCapabilityRoot;\n use codex_protocol::protocol::SkillScope;\n use codex_skills_extension::ExecutorSkillProvider;\n-use codex_skills_extension::catalog::SkillReadResult;\n use codex_skills_extension::provider::SkillListQuery;\n use codex_skills_extension::provider::SkillProvider;\n-use codex_skills_extension::provider::SkillReadRequest;\n use codex_utils_absolute_path::AbsolutePathBuf;\n use pretty_assertions::assert_eq;\n \n@@ -202,64 +200,6 @@ async fn skill_loading_and_reads_use_the_supplied_executor_file_system() {\n );\n }\n \n-#[tokio::test]\n-async fn executor_provider_reads_from_the_environment_instance_used_for_listing() {\n- let test_root = create_local_skill_root(\"bound-instance\").expect(\"create local skill root\");\n- let root_path = test_root.to_string_lossy().into_...", + "path": "codex-rs/ext/skills/tests/executor_file_system_authority.rs", + "status": "modified" + } + ], + "linked_issues": [ + "#27454" + ], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "We're switching to using a static encoding of the host path in `PathUri`. We may need a type like this again but we can add it when it's more compelling.\n\nStacked on #27454.", + "labels": [], + "merged_at": "2026-06-11T18:26:13Z", + "number": 27433, + "state": "merged", + "title": "[codex] remove EnvironmentPathRef", + "url": "https://github.com/openai/codex/pull/27433" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/bundles/openai-codex-pr-27646.json b/artifacts/github/bundles/openai-codex-pr-27646.json new file mode 100644 index 000000000..434e571ca --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-27646.json @@ -0,0 +1,50 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "jif-oai", + "committed_at": "2026-06-11T18:05:02Z", + "message": "feat: disable orchestrator skills for now", + "sha": "fef2bbfa4c23e6144afa8c2081ca4a44cca082dc", + "url": "https://github.com/openai/codex/commit/fef2bbfa4c23e6144afa8c2081ca4a44cca082dc" + } + ], + "default_branch": "main", + "docs_refs": [], + "examples_refs": [], + "extracted_flags": [ + "TODO", + "ORCHESTRATOR_SKILLS_ENABLED" + ], + "files": [ + { + "additions": 11, + "deletions": 5, + "patch_excerpt": "@@ -27,6 +27,9 @@ use crate::outgoing_message::OutgoingMessageSender;\n use crate::thread_state::ThreadListenerCommand;\n use crate::thread_state::ThreadStateManager;\n \n+// TODO(jif): Enable once /ps/mcp serves complete hosted skill packages.\n+const ORCHESTRATOR_SKILLS_ENABLED: bool = false;\n+\n pub(crate) struct ThreadExtensionDependencies {\n pub(crate) event_sink: Arc,\n pub(crate) auth_manager: Arc,\n@@ -73,13 +76,16 @@ where\n codex_mcp_extension::install(&mut builder);\n codex_web_search_extension::install(&mut builder, auth_manager.clone());\n codex_image_generation_extension::install(&mut builder, auth_manager);\n+ let mut skill_providers = codex_skills_extension::SkillProviders::new()\n+ .with_executor_provider(executor_skill_provider);\n+ if ORCHESTRATOR_SKILLS_ENABLED {\n+ skill_providers = skill_providers.with_or...", + "path": "codex-rs/app-server/src/extensions.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -124,6 +124,7 @@ async fn mcp_resource_read_returns_resource_contents() -> Result<()> {\n }\n \n #[tokio::test(flavor = \"multi_thread\", worker_threads = 2)]\n+#[ignore = \"orchestrator skills are disabled until /ps/mcp serves complete skill packages\"]\n async fn orchestrator_skill_can_read_referenced_resource_without_an_executor() -> Result<()> {\n let responses_server = responses::start_mock_server().await;\n let (apps_server_url, apps_server_handle) = start_resource_apps_mcp_server().await?;", + "path": "codex-rs/app-server/tests/suite/v2/mcp_resource.rs", + "status": "modified" + } + ], + "linked_issues": [], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "Temp disable orchestrator-only skills while waiting for the endpoint to be fixed", + "labels": [], + "merged_at": "2026-06-11T18:20:26Z", + "number": 27646, + "state": "merged", + "title": "feat: disable orchestrator skills for now", + "url": "https://github.com/openai/codex/pull/27646" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/impact/openai-codex-pr-27420.json b/artifacts/github/impact/openai-codex-pr-27420.json new file mode 100644 index 000000000..ea2daa444 --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-27420.json @@ -0,0 +1,45 @@ +{ + "candidate_followups": [ + "Check Decodex app/catalog UI consumers for strict app-summary snapshots that need the nullable `category` field.", + "Prefer upstream category values over local category inference when rendering plugin app groupings.", + "Keep protocol consumers tolerant of missing category values." + ], + "caveats": [ + "The field is nullable and additive.", + "Category values depend on plugin metadata quality and may be absent." + ], + "confidence": "confirmed", + "control_plane_impact": "candidate", + "evidence": [ + "`AppSummary` and `AppTemplateSummary` now include nullable `category` fields in Rust, TypeScript, and JSON schema output.", + "`PluginAppMetadata` parses optional local app categories from `.app.json`.", + "Plugin request processing maps local and remote app categories into app summaries.", + "Plugin read/install tests assert category propagation." + ], + "observed_change": "Codex app-server plugin responses now include nullable app category values derived from local `.app.json`, branding metadata, or remote app metadata.", + "public_signal_decision": "publish", + "publisher_angle": "practical_explainer", + "repo": "openai/codex", + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-27420", + "social_notes": [ + "Explain this as a plugin-app metadata/display improvement, not as a new app install capability.", + "Mention that missing categories remain possible because the new field is nullable." + ], + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-11T17:34:41Z", + "title": "[codex] Propagate plugin app categories", + "url": "https://github.com/openai/codex/pull/27420" + }, + { + "kind": "pull_request", + "meta": "artifacts/github/reviews/openai-codex-pr-27420.review.json", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/27420" + } + ] + } +} diff --git a/artifacts/github/impact/openai-codex-pr-27424.json b/artifacts/github/impact/openai-codex-pr-27424.json new file mode 100644 index 000000000..6d1298428 --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-27424.json @@ -0,0 +1,45 @@ +{ + "candidate_followups": [ + "Audit Decodex filesystem adapters, sandbox assumptions, and retained-lane path handling against upstream `PathUri` semantics.", + "Do not change JSON-RPC filesystem client payload expectations unless a later upstream PR removes the absolute-path adapter boundary.", + "Track follow-up PRs that remove temporary join/parent handlers or migrate higher-level exec-server surfaces." + ], + "caveats": [ + "JSON-RPC filesystem params still use absolute paths at app-server and exec-server adapter boundaries in this PR.", + "The upstream PR says higher-level exec-server migration is still future work." + ], + "confidence": "confirmed", + "control_plane_impact": "compat_risk", + "evidence": [ + "`ExecutorFileSystem` methods now accept `PathUri` and no longer include join/parent.", + "App-server and exec-server filesystem handlers convert absolute path params into `PathUri` before filesystem calls.", + "Remote filesystem calls convert `PathUri` back into absolute-path protocol params.", + "Apply-patch, config, skills, and git utility call sites now construct `PathUri` before filesystem operations." + ], + "observed_change": "Codex moves `ExecutorFileSystem` internals from absolute paths to `PathUri` while keeping filesystem JSON-RPC adapters on absolute-path payloads.", + "public_signal_decision": "publish", + "publisher_angle": "operator_impact", + "repo": "openai/codex", + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-27424", + "social_notes": [ + "Frame this as an internal authority/path migration with adapter-boundary caveats.", + "Avoid claiming JSON-RPC filesystem payloads changed in this PR." + ], + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-11T18:44:19Z", + "title": "[codex] migrate ExecutorFileSystem paths to PathUri", + "url": "https://github.com/openai/codex/pull/27424" + }, + { + "kind": "pull_request", + "meta": "artifacts/github/reviews/openai-codex-pr-27424.review.json", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/27424" + } + ] + } +} diff --git a/artifacts/github/impact/openai-codex-pr-27433.json b/artifacts/github/impact/openai-codex-pr-27433.json new file mode 100644 index 000000000..9b6294dad --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-27433.json @@ -0,0 +1,44 @@ +{ + "candidate_followups": [ + "Audit Decodex skill/resource handling for assumptions that a resource keeps a filesystem object alive after listing.", + "Prefer environment-id readback checks when diagnosing executor skill read failures.", + "Group public explanation with the broader PathUri filesystem migration instead of publishing this internal cleanup alone." + ], + "caveats": [ + "This is part of a stacked filesystem/path migration.", + "The PR removes an internal bound-path type, not a public app-server JSON-RPC method." + ], + "confidence": "confirmed", + "control_plane_impact": "compat_risk", + "evidence": [ + "`EnvironmentPathRef` implementation and export are removed.", + "`SkillResourceId` now stores environment id plus absolute path for environment resources.", + "Executor skill reads resolve the current environment from `EnvironmentManager` before reading.", + "The source review links this PR to the broader PathUri migration that follows." + ], + "observed_change": "Codex removes `EnvironmentPathRef` and represents executor skill resources as environment id plus absolute path.", + "public_signal_decision": "defer", + "publisher_angle": "watch_note", + "repo": "openai/codex", + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-27433", + "social_notes": [ + "If this becomes public, pair it with PR #27424 so the user-facing story is PathUri migration rather than an isolated internal type removal." + ], + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-11T18:26:13Z", + "title": "[codex] remove EnvironmentPathRef", + "url": "https://github.com/openai/codex/pull/27433" + }, + { + "kind": "pull_request", + "meta": "artifacts/github/reviews/openai-codex-pr-27433.review.json", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/27433" + } + ] + } +} diff --git a/artifacts/github/impact/openai-codex-pr-27646.json b/artifacts/github/impact/openai-codex-pr-27646.json new file mode 100644 index 000000000..b885ef82e --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-27646.json @@ -0,0 +1,45 @@ +{ + "candidate_followups": [ + "Treat absence of orchestrator-only skills as expected upstream behavior until a follow-up PR re-enables the provider.", + "Keep Decodex capability probes from failing closed solely because orchestrator skill resources are missing.", + "Watch for the `/ps/mcp` hosted-package fix that should reverse this temporary gate." + ], + "caveats": [ + "The disable is explicitly temporary.", + "Executor-backed skills remain installed through the app-server skill extension." + ], + "confidence": "confirmed", + "control_plane_impact": "compat_risk", + "evidence": [ + "`ORCHESTRATOR_SKILLS_ENABLED` is set to false in app-server extension wiring.", + "`OrchestratorSkillProvider` is added only when the flag is true.", + "The orchestrator skill resource read test is ignored until `/ps/mcp` serves complete skill packages.", + "The PR body frames the change as a temporary disable." + ], + "observed_change": "Codex temporarily disables app-server orchestrator skill providers while keeping executor-backed skills installed.", + "public_signal_decision": "publish", + "publisher_angle": "watch_note", + "repo": "openai/codex", + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-27646", + "social_notes": [ + "Use cautious language: temporary disable, not a permanent removal.", + "Mention executor skills still load so readers do not overgeneralize the outage." + ], + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-11T18:20:26Z", + "title": "feat: disable orchestrator skills for now", + "url": "https://github.com/openai/codex/pull/27646" + }, + { + "kind": "pull_request", + "meta": "artifacts/github/reviews/openai-codex-pr-27646.review.json", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/27646" + } + ] + } +} diff --git a/artifacts/github/review-queue/openai-codex-latest.json b/artifacts/github/review-queue/openai-codex-latest.json index 364d0bb8e..dc8705fec 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, + "critical": 21, "high": 11, "low": 0, - "normal": 12, + "normal": 8, "published_subjects_seen": 0, "recent_commits_scanned": 40, "subjects_queued": 40 }, - "generated_at": "2026-06-12T02:04:59.697624Z", + "generated_at": "2026-06-12T14:05:30.421011Z", "repo": "openai/codex", "schema": "upstream_review_queue/v1", "source": { @@ -17,209 +17,6 @@ "signals_dir": "site/src/content/signals" }, "subjects": [ - { - "attention_flags": [ - "auth_account", - "deprecated_removed", - "new_feature", - "protocol_change", - "security_policy" - ], - "changed_file_count": 8, - "commit_shas": [ - "c011f6e6809601b6cc138e055bf1bc57bf5b5d4c", - "571debf6883633a51c69f6654efd10c4e13e7f26", - "0b768f5016684ccf0266aef513ff7f7bdfcc5aa2" - ], - "committed_at": "2026-06-11T10:07:19Z", - "next_step": "ai_review_required", - "pr_number": 27573, - "pr_url": "https://github.com/openai/codex/pull/27573", - "review_priority": "critical", - "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, security_policy.", - "sample_paths": [ - "codex-rs/app-server/tests/suite/v2/compaction.rs", - "codex-rs/core/tests/suite/compact.rs", - "codex-rs/core/tests/suite/compact_remote.rs", - "codex-rs/core/tests/suite/compact_remote_parity.rs", - "codex-rs/core/tests/suite/hooks.rs", - "codex-rs/core/tests/suite/responses_lite.rs", - "codex-rs/features/src/lib.rs", - "codex-rs/features/src/tests.rs" - ], - "source_state": "merged", - "subject_id": "27573", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "config_hooks", - "tests_ci" - ], - "title": "core: enable remote compaction v2 by default", - "url": "https://github.com/openai/codex/pull/27573" - }, - { - "attention_flags": [ - "deprecated_removed", - "new_feature", - "protocol_change", - "release_packaging" - ], - "changed_file_count": 6, - "commit_shas": [ - "168cddddc1b5c5f4fe64534acc4e31ae69474365", - "fe04e86efaae705d0b47e3d076e82d54b2e1dca5", - "92644c48f26b1f5d92892c01cd1585b86fc381f1", - "e13920ef12be52e892db5cbf3e0a3402d5d33f6e" - ], - "committed_at": "2026-06-11T10:41:44Z", - "next_step": "ai_review_required", - "pr_number": 27569, - "pr_url": "https://github.com/openai/codex/pull/27569", - "review_priority": "critical", - "review_reason": "Needs AI review for deprecated_removed, new_feature, protocol_change, release_packaging.", - "sample_paths": [ - "codex-rs/core/src/config/config_tests.rs", - "codex-rs/core/src/config/mod.rs", - "codex-rs/core/src/tools/handlers/multi_agents_spec.rs", - "codex-rs/core/src/tools/handlers/multi_agents_spec_tests.rs", - "codex-rs/core/src/tools/spec_plan.rs", - "codex-rs/core/src/tools/spec_plan_tests.rs" - ], - "source_state": "merged", - "subject_id": "27569", - "subject_kind": "pr", - "surface_hints": [ - "config_hooks", - "tests_ci" - ], - "title": "multi-agent: move concurrency guidance into v2 usage hints", - "url": "https://github.com/openai/codex/pull/27569" - }, - { - "attention_flags": [ - "auth_account", - "deprecated_removed", - "new_feature", - "protocol_change" - ], - "changed_file_count": 4, - "commit_shas": [ - "0dd59d361fb64e7cad0641619eae8047f893a8d8" - ], - "committed_at": "2026-06-11T11:51:04Z", - "next_step": "ai_review_required", - "pr_number": 27591, - "pr_url": "https://github.com/openai/codex/pull/27591", - "review_priority": "critical", - "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change.", - "sample_paths": [ - "codex-rs/app-server/tests/suite/v2/mcp_resource.rs", - "codex-rs/core-skills/src/render.rs", - "codex-rs/ext/skills/src/render.rs", - "codex-rs/ext/skills/tests/skills_extension.rs" - ], - "source_state": "merged", - "subject_id": "27591", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "mcp_plugins", - "tests_ci" - ], - "title": "skills: render catalog locators by authority", - "url": "https://github.com/openai/codex/pull/27591" - }, - { - "attention_flags": [ - "breaking_change", - "deprecated_removed", - "new_feature", - "protocol_change", - "release_packaging" - ], - "changed_file_count": 10, - "commit_shas": [ - "9ff580bf7e426f19713de20aaa9a0138a4aa389f", - "3eb9c5126d277d5c6e2b92dfb71a3025942a19ef" - ], - "committed_at": "2026-06-11T12:03:53Z", - "next_step": "ai_review_required", - "pr_number": 27413, - "pr_url": "https://github.com/openai/codex/pull/27413", - "review_priority": "critical", - "review_reason": "Needs AI review for breaking_change, deprecated_removed, new_feature, protocol_change, release_packaging.", - "sample_paths": [ - "codex-rs/Cargo.lock", - "codex-rs/app-server/src/extensions.rs", - "codex-rs/ext/skills/Cargo.toml", - "codex-rs/ext/skills/src/config.rs", - "codex-rs/ext/skills/src/extension.rs", - "codex-rs/ext/skills/src/fragments.rs", - "codex-rs/ext/skills/src/lib.rs", - "codex-rs/ext/skills/src/render.rs", - "codex-rs/ext/skills/src/state.rs", - "codex-rs/ext/skills/tests/skills_extension.rs" - ], - "source_state": "merged", - "subject_id": "27413", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "config_hooks", - "tests_ci" - ], - "title": "skills: decouple the skills extension from core", - "url": "https://github.com/openai/codex/pull/27413" - }, - { - "attention_flags": [ - "auth_account", - "breaking_change", - "deprecated_removed", - "new_feature", - "protocol_change", - "rate_limit", - "release_packaging", - "security_policy" - ], - "changed_file_count": 13, - "commit_shas": [ - "69b921aa666b1059422309b6ab7f4cd1a03b65c9", - "44494bb402287988f3faf7590d0ea284ae234657" - ], - "committed_at": "2026-06-11T16:23:08Z", - "next_step": "ai_review_required", - "pr_number": 27490, - "pr_url": "https://github.com/openai/codex/pull/27490", - "review_priority": "critical", - "review_reason": "Needs AI review for auth_account, breaking_change, deprecated_removed, new_feature, protocol_change, rate_limit, release_packaging, security_policy.", - "sample_paths": [ - "codex-rs/app-server-client/src/lib.rs", - "codex-rs/tui/src/app.rs", - "codex-rs/tui/src/app/config_persistence.rs", - "codex-rs/tui/src/app/event_dispatch.rs", - "codex-rs/tui/src/chatwidget.rs", - "codex-rs/tui/src/chatwidget/constructor.rs", - "codex-rs/tui/src/chatwidget/permission_popups.rs", - "codex-rs/tui/src/chatwidget/settings.rs", - "codex-rs/tui/src/chatwidget/slash_dispatch.rs", - "codex-rs/tui/src/chatwidget/windows_sandbox_prompts.rs", - "codex-rs/tui/src/lib.rs", - "codex-rs/tui/src/onboarding/onboarding_screen.rs" - ], - "source_state": "merged", - "subject_id": "27490", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "cli_tui", - "config_hooks", - "sandbox_permissions" - ], - "title": "Remove TUI legacy Windows sandbox dependency", - "url": "https://github.com/openai/codex/pull/27490" - }, { "attention_flags": [ "auth_account", @@ -755,104 +552,438 @@ { "attention_flags": [ "auth_account", + "breaking_change", + "deprecated_removed", "new_feature", - "protocol_change" + "protocol_change", + "release_packaging", + "security_policy" ], - "changed_file_count": 12, + "changed_file_count": 33, "commit_shas": [ - "74066fb2c10e8e881f43faac5222e023527409d4", - "fbdff12dbc44263909c49bbd31cdd4fabc068153" + "c1c83d3db1c92450ee5104637673da205c3b53f1", + "11b7a3193c9c0b607a89154d613bf31bf9968356", + "37c9a1af8e791b935a7e6b79412097349b3be23a", + "2ccf773428b3e45ea0bf628f7cdc1f829acb4ec6", + "89e994bf64ee35e3e03915cea760486b67eeeddb", + "f06ad42c1964a93de5e96576e7c4244ac41f2e74", + "751a2a5ffa1105ebf86c0c89507d97b1dd8a203e", + "5d46286a8c47f23d546e431d8395861091407ac3", + "51201c3539709dc098c33bb5d917c3f3c2c360d1", + "51c0ede50280cb2b7720ad4edc795b99f2bbff8b", + "5957b62fc0479ae8ab34b1126edbfc482536d7a1", + "38fa3a8ac4472cf91ae78a7bcf46de916d96849a", + "6d519c7361e8c5d9ea93acd5a9ee2bdf8b52d76e", + "ffc649de3e5b2fb406e8fc84b26973bf375762ab", + "d4c46df25f4a90a7cb75380379d58bb301bcb9af", + "e34ec2789518918e9cd1d8b06187ce1da043b5b5" + ], + "committed_at": "2026-06-12T04:28:52Z", + "next_step": "ai_review_required", + "pr_number": 27445, + "pr_url": "https://github.com/openai/codex/pull/27445", + "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/app-server-daemon/src/backend/pid.rs", + "codex-rs/app-server-daemon/src/backend/pid_tests.rs", + "codex-rs/app-server-daemon/src/lib.rs", + "codex-rs/app-server-daemon/src/remote_control_client.rs", + "codex-rs/app-server-protocol/schema/json/ClientRequest.json", + "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json", + "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json", + "codex-rs/app-server-protocol/schema/typescript/v2/RemoteControlDisableParams.ts", + "codex-rs/app-server-protocol/schema/typescript/v2/RemoteControlEnableParams.ts", + "codex-rs/app-server-protocol/schema/typescript/v2/index.ts", + "codex-rs/app-server-protocol/src/protocol/common.rs", + "codex-rs/app-server-protocol/src/protocol/v2/remote_control.rs" ], - "committed_at": "2026-06-11T10:38:04Z", + "source_state": "merged", + "subject_id": "27445", + "subject_kind": "pr", + "surface_hints": [ + "app_server_protocol", + "cli_tui", + "docs_examples", + "tests_ci" + ], + "title": "feat(app-server): persist remote-control desired state", + "url": "https://github.com/openai/codex/pull/27445" + }, + { + "attention_flags": [ + "auth_account", + "deprecated_removed", + "new_feature", + "protocol_change", + "release_packaging", + "security_policy" + ], + "changed_file_count": 17, + "commit_shas": [ + "7fcf243caa6f8834c1d88fa7daddff28463424df", + "d4f8529190f9b4d4e9f527fd821038fa74332811", + "45674d25fca290b2193f147166e39231c6176072", + "bbc613c1dca65fa1b2c575eb83a2f90098a545cc", + "f2b7e7007a7077a2933627a690c3028b618cd2ff", + "e1d67f06b9abefe67d33231520aed075ed7731d7", + "a98925967179e545884a561f56321a4e905bd13a", + "62dbad3c1de1174856546c5cb62e798b18d2c58a", + "4075df843ae6e07aaba605a9c2139907f1160ab4", + "2cfb435d0e8a46aa536ece31817556832b344f82", + "71637bace336f2cad7f405e88a04841813767c8c", + "7d0addee9861574ed5f3dd7bc6e8b123ed9fed69", + "45e35b1147a70a06c3701933b636421ede421443", + "e2bae8628968b7f7e8e69d3117849c6397f64645", + "d68efcaa2e2bc4219129d4ad8589e7b34cb67270" + ], + "committed_at": "2026-06-12T05:26:31Z", "next_step": "ai_review_required", - "pr_number": 27388, - "pr_url": "https://github.com/openai/codex/pull/27388", - "review_priority": "high", - "review_reason": "Needs AI review for auth_account, new_feature, protocol_change.", + "pr_number": 27508, + "pr_url": "https://github.com/openai/codex/pull/27508", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, release_packaging, security_policy.", + "sample_paths": [ + "codex-rs/app-server-client/src/lib.rs", + "codex-rs/app-server-client/src/path.rs", + "codex-rs/app-server-client/src/remote.rs", + "codex-rs/tui/src/app/tests.rs", + "codex-rs/tui/src/app/thread_goal_actions.rs", + "codex-rs/tui/src/app_server_session.rs", + "codex-rs/tui/src/app_server_session/fs.rs", + "codex-rs/tui/src/bottom_pane/mod.rs", + "codex-rs/tui/src/chatwidget.rs", + "codex-rs/tui/src/chatwidget/goal_validation.rs", + "codex-rs/tui/src/chatwidget/slash_dispatch.rs", + "codex-rs/tui/src/chatwidget/tests.rs" + ], + "source_state": "merged", + "subject_id": "27508", + "subject_kind": "pr", + "surface_hints": [ + "app_server_protocol", + "cli_tui", + "tests_ci" + ], + "title": "[1 of 3] Support long raw TUI goal objectives", + "url": "https://github.com/openai/codex/pull/27508" + }, + { + "attention_flags": [ + "auth_account", + "breaking_change", + "new_feature", + "protocol_change", + "security_policy" + ], + "changed_file_count": 25, + "commit_shas": [ + "1c776a78980457d4c7300b47af0b3565bf5218ce", + "a2a6c6f2e513d21dec6b385d0e386212a257b5f8", + "ba0f8c7bd1cdc11d3706b368a9071abc3caebd43" + ], + "committed_at": "2026-06-12T05:30:41Z", + "next_step": "ai_review_required", + "pr_number": 27256, + "pr_url": "https://github.com/openai/codex/pull/27256", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, breaking_change, new_feature, protocol_change, security_policy.", + "sample_paths": [ + "codex-rs/app-server-client/src/lib.rs", + "codex-rs/app-server-protocol/schema/json/ServerRequest.json", + "codex-rs/app-server-protocol/schema/json/ToolRequestUserInputParams.json", + "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json", + "codex-rs/app-server-protocol/schema/typescript/v2/ToolRequestUserInputParams.ts", + "codex-rs/app-server-protocol/src/protocol/v2/item.rs", + "codex-rs/app-server/src/bespoke_event_handling.rs", + "codex-rs/app-server/src/outgoing_message.rs", + "codex-rs/app-server/src/request_processors/thread_processor_tests.rs", + "codex-rs/app-server/tests/suite/v2/request_user_input.rs", + "codex-rs/core/src/codex_delegate.rs", + "codex-rs/core/src/codex_delegate_tests.rs" + ], + "source_state": "merged", + "subject_id": "27256", + "subject_kind": "pr", + "surface_hints": [ + "app_server_protocol", + "cli_tui", + "mcp_plugins", + "tests_ci" + ], + "title": "Add request_user_input auto-resolution window contract", + "url": "https://github.com/openai/codex/pull/27256" + }, + { + "attention_flags": [ + "auth_account", + "deprecated_removed", + "new_feature", + "protocol_change", + "release_packaging", + "security_policy" + ], + "changed_file_count": 19, + "commit_shas": [ + "b371fc20b8ff9939400ad984ffc899285ec08811", + "7f78a47e466d319886fe85ffbb49c5aa5fd4c705", + "79d913b81e08e954455b55b347568f8147cc0880" + ], + "committed_at": "2026-06-12T05:37:26Z", + "next_step": "ai_review_required", + "pr_number": 27724, + "pr_url": "https://github.com/openai/codex/pull/27724", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, release_packaging, security_policy.", "sample_paths": [ "codex-rs/Cargo.lock", - "codex-rs/app-server/tests/suite/v2/mcp_resource.rs", - "codex-rs/ext/skills/Cargo.toml", - "codex-rs/ext/skills/src/extension.rs", - "codex-rs/ext/skills/src/lib.rs", - "codex-rs/ext/skills/src/provider/orchestrator.rs", - "codex-rs/ext/skills/src/sources.rs", - "codex-rs/ext/skills/src/tools/list.rs", - "codex-rs/ext/skills/src/tools/mod.rs", - "codex-rs/ext/skills/src/tools/read.rs", - "codex-rs/ext/skills/src/tools/schema.rs", - "codex-rs/tools/src/tool_output.rs" + "codex-rs/Cargo.toml", + "codex-rs/code-mode-host/BUILD.bazel", + "codex-rs/code-mode-host/Cargo.toml", + "codex-rs/code-mode-host/src/main.rs", + "codex-rs/code-mode-protocol/BUILD.bazel", + "codex-rs/code-mode-protocol/Cargo.toml", + "codex-rs/code-mode-protocol/src/description.rs", + "codex-rs/code-mode-protocol/src/lib.rs", + "codex-rs/code-mode-protocol/src/response.rs", + "codex-rs/code-mode-protocol/src/runtime.rs", + "codex-rs/code-mode-protocol/src/session.rs" ], "source_state": "merged", - "subject_id": "27388", + "subject_id": "27724", "subject_kind": "pr", "surface_hints": [ "app_server_protocol", "config_hooks", - "mcp_plugins", + "tests_ci" + ], + "title": "code-mode standalone: extract protocol and add host crate", + "url": "https://github.com/openai/codex/pull/27724" + }, + { + "attention_flags": [ + "deprecated_removed", + "new_feature", + "protocol_change", + "security_policy" + ], + "changed_file_count": 4, + "commit_shas": [ + "763e8b940bc7d2f1469a25580295cf4c3bc71c85", + "f87021864074363a282c1937081588060ed8a1e7", + "b99bf9064e35c399d35860b720897ab266b26acc", + "e1ca683c9e5f52952bc13b4de8b55673e1baeb1c" + ], + "committed_at": "2026-06-12T06:23:44Z", + "next_step": "ai_review_required", + "pr_number": 27316, + "pr_url": "https://github.com/openai/codex/pull/27316", + "review_priority": "critical", + "review_reason": "Needs AI review for deprecated_removed, new_feature, protocol_change, security_policy.", + "sample_paths": [ + "codex-rs/core/src/tools/spec_plan.rs", + "codex-rs/core/src/tools/spec_plan_tests.rs", + "codex-rs/core/tests/suite/code_mode.rs", + "codex-rs/core/tests/suite/model_runtime_selectors.rs" + ], + "source_state": "merged", + "subject_id": "27316", + "subject_kind": "pr", + "surface_hints": [ "model_provider", "tests_ci" ], - "title": "skills: expose remote skill resource tools", - "url": "https://github.com/openai/codex/pull/27388" + "title": "Keep request_user_input direct-model only", + "url": "https://github.com/openai/codex/pull/27316" }, { "attention_flags": [ + "deprecated_removed", "new_feature", - "protocol_change" + "protocol_change", + "release_packaging", + "security_policy" ], - "changed_file_count": 3, + "changed_file_count": 15, "commit_shas": [ - "fd1acbdba917067139984c12cb9c4288af38988a" + "bf7e046ef92cb66b11b5faad365f8fedf520e9a2", + "e4108a61e2c2202a3a023096d72e4b074eeea3f6", + "983e59bc4856168134a51bd61995848e0658e8a2", + "7349490148f4733f12d8a697cd0ca707125465ca", + "1d0be482e805f3da625b0463d497284658fbc1d1", + "a1acbe077be0ae8fb76ff52b597130bcc12fd15c", + "0cf644af40f76ffdfbac134b4b17aca78e8dcef5", + "bccf6b711e49e37f8bf1206853220c35f57b791a", + "385ae2e47da93cacbac76716b2a7338f96bb2353", + "22167d0053fc4a0446c9936e43efd042a0747e97", + "04393ff90d514aaf44ff0cf78454a1e2bbd05c94", + "6fdb655aab0160caa3d3144532f1ad65dc8deaec", + "6f9903d25d05b2ec36edff1084deb4766452d219", + "ba1b107d83e3d545436341b2451edb70fbeb096e", + "a4eb618a780b20e6d9ee2dd61cf880fe26019c4d", + "7d151cc5f3374795198fdcdabcde795e36e737d6", + "509459c428b5c3cf3ddffa281439330d2c71c0ce" + ], + "committed_at": "2026-06-12T07:10:06Z", + "next_step": "ai_review_required", + "pr_number": 27696, + "pr_url": "https://github.com/openai/codex/pull/27696", + "review_priority": "critical", + "review_reason": "Needs AI review for deprecated_removed, new_feature, protocol_change, release_packaging, security_policy.", + "sample_paths": [ + "codex-rs/core/src/agents_md.rs", + "codex-rs/core/src/agents_md_tests.rs", + "codex-rs/core/src/context/contextual_user_message_tests.rs", + "codex-rs/core/src/context/user_instructions.rs", + "codex-rs/core/src/environment_selection.rs", + "codex-rs/core/src/session/mod.rs", + "codex-rs/core/src/session/turn_context.rs", + "codex-rs/core/src/thread_manager_tests.rs", + "codex-rs/core/tests/common/context_snapshot.rs", + "codex-rs/core/tests/suite/agents_md.rs", + "codex-rs/core/tests/suite/client.rs", + "codex-rs/core/tests/suite/compact.rs" + ], + "source_state": "merged", + "subject_id": "27696", + "subject_kind": "pr", + "surface_hints": [ + "cli_tui", + "model_provider", + "tests_ci" ], - "committed_at": "2026-06-11T10:52:46Z", + "title": "[codex] Load AGENTS.md from all bound environments", + "url": "https://github.com/openai/codex/pull/27696" + }, + { + "attention_flags": [ + "auth_account", + "deprecated_removed", + "new_feature", + "protocol_change", + "release_packaging", + "security_policy" + ], + "changed_file_count": 18, + "commit_shas": [ + "79e15b02010c0cd19abff8b1cd8bee134cc9590e", + "f8256a5751a0963dbd38b1afbe082cfb1aae3d3d" + ], + "committed_at": "2026-06-12T09:20:34Z", "next_step": "ai_review_required", - "pr_number": 27585, - "pr_url": "https://github.com/openai/codex/pull/27585", - "review_priority": "high", - "review_reason": "Needs AI review for new_feature, protocol_change.", + "pr_number": 27670, + "pr_url": "https://github.com/openai/codex/pull/27670", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, release_packaging, security_policy.", + "sample_paths": [ + "codex-rs/app-server/src/mcp_refresh.rs", + "codex-rs/app-server/src/request_processors/mcp_processor.rs", + "codex-rs/core/src/codex_thread.rs", + "codex-rs/core/src/mcp.rs", + "codex-rs/core/src/mcp_skill_dependencies.rs", + "codex-rs/core/src/session/mcp.rs", + "codex-rs/core/src/session/mod.rs", + "codex-rs/core/src/session/session.rs", + "codex-rs/core/src/session/tests.rs", + "codex-rs/core/src/state/service.rs", + "codex-rs/core/src/thread_manager_tests.rs", + "codex-rs/ext/extension-api/src/contributors.rs" + ], + "source_state": "merged", + "subject_id": "27670", + "subject_kind": "pr", + "surface_hints": [ + "app_server_protocol", + "mcp_plugins", + "tests_ci" + ], + "title": "Make MCP server contributions thread-scoped", + "url": "https://github.com/openai/codex/pull/27670" + }, + { + "attention_flags": [ + "auth_account", + "breaking_change", + "deprecated_removed", + "new_feature", + "protocol_change", + "release_packaging", + "security_policy" + ], + "changed_file_count": 13, + "commit_shas": [ + "8b4a7e0b207750361b267e156596e508fcae4dea", + "8a69762b3a6353fc243440ae33dfcac0dbbe541a" + ], + "committed_at": "2026-06-12T11:37:33Z", + "next_step": "ai_review_required", + "pr_number": 27692, + "pr_url": "https://github.com/openai/codex/pull/27692", + "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/Cargo.lock", - "codex-rs/ext/skills/Cargo.toml", - "codex-rs/ext/skills/src/tools/read.rs" + "codex-rs/core-plugins/Cargo.toml", + "codex-rs/core-plugins/src/lib.rs", + "codex-rs/core-plugins/src/manifest.rs", + "codex-rs/core-plugins/src/provider.rs", + "codex-rs/core-plugins/src/provider_tests.rs", + "codex-rs/plugin/Cargo.toml", + "codex-rs/plugin/src/lib.rs", + "codex-rs/plugin/src/manifest.rs", + "codex-rs/plugin/src/provider.rs", + "codex-rs/plugin/src/provider_tests.rs", + "codex-rs/utils/plugins/src/lib.rs" ], "source_state": "merged", - "subject_id": "27585", + "subject_id": "27692", "subject_kind": "pr", "surface_hints": [ - "config_hooks" + "config_hooks", + "mcp_plugins", + "model_provider", + "tests_ci" ], - "title": "nit: cap error", - "url": "https://github.com/openai/codex/pull/27585" + "title": "Add executor-owned plugin resolution", + "url": "https://github.com/openai/codex/pull/27692" }, { "attention_flags": [ + "auth_account", + "breaking_change", "new_feature", "protocol_change" ], - "changed_file_count": 1, + "changed_file_count": 7, "commit_shas": [ - "68dc3b758d207d708025a8cb2df6a9eede57d17f" + "4157b14280055a67c0374686229f49add9c24c2a", + "2c491faf478bebfa1a7d9333dd8cc4cf66ec5591" ], - "committed_at": "2026-06-11T10:55:58Z", + "committed_at": "2026-06-12T13:10:05Z", "next_step": "ai_review_required", - "pr_number": 27404, - "pr_url": "https://github.com/openai/codex/pull/27404", - "review_priority": "high", - "review_reason": "Needs AI review for new_feature, protocol_change.", + "pr_number": 27863, + "pr_url": "https://github.com/openai/codex/pull/27863", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, breaking_change, new_feature, protocol_change.", "sample_paths": [ - "codex-rs/app-server/tests/suite/v2/mcp_resource.rs" + "codex-rs/Cargo.lock", + "codex-rs/codex-mcp/src/lib.rs", + "codex-rs/codex-mcp/src/plugin_config.rs", + "codex-rs/codex-mcp/src/plugin_config_tests.rs", + "codex-rs/core-plugins/Cargo.toml", + "codex-rs/core-plugins/src/loader.rs", + "codex-rs/core-plugins/src/loader_tests.rs" ], "source_state": "merged", - "subject_id": "27404", + "subject_id": "27863", "subject_kind": "pr", "surface_hints": [ - "app_server_protocol", + "config_hooks", "mcp_plugins", "tests_ci" ], - "title": "test: cover referenced backend skill reads without an executor", - "url": "https://github.com/openai/codex/pull/27404" + "title": "Extract shared plugin MCP config parsing", + "url": "https://github.com/openai/codex/pull/27863" }, { "attention_flags": [ @@ -1106,155 +1237,104 @@ }, { "attention_flags": [ - "protocol_change", "release_packaging" ], "changed_file_count": 1, "commit_shas": [ - "4f766def20881fa0e6644384dd7336568f704c6d" + "6cdfc74097433136f37f4969f16f22374e4f1fc0" ], - "committed_at": "2026-06-11T14:19:27Z", + "committed_at": "2026-06-12T02:44:36Z", "next_step": "ai_review_required", - "pr_number": 27527, - "pr_url": "https://github.com/openai/codex/pull/27527", - "review_priority": "normal", - "review_reason": "Needs AI review for protocol_change, release_packaging.", + "pr_number": 27702, + "pr_url": "https://github.com/openai/codex/pull/27702", + "review_priority": "high", + "review_reason": "Needs AI review for release_packaging.", "sample_paths": [ - ".github/workflows/rust-release.yml" + "codex-rs/Cargo.toml" ], "source_state": "merged", - "subject_id": "27527", + "subject_id": "27702", "subject_kind": "pr", "surface_hints": [ - "release_packaging", - "tests_ci" + "config_hooks" ], - "title": "[codex] publish npm packages concurrently", - "url": "https://github.com/openai/codex/pull/27527" + "title": "[codex] parallelize release code generation", + "url": "https://github.com/openai/codex/pull/27702" }, { "attention_flags": [ - "auth_account", - "release_packaging", + "new_feature", + "protocol_change", "security_policy" ], - "changed_file_count": 1, + "changed_file_count": 11, "commit_shas": [ - "c07c75ef754355a134c712b18dc470c0e21ce636" + "f285bd830523f2b3c05c0214a2eeb1f93baa330f" ], - "committed_at": "2026-06-11T14:23:46Z", + "committed_at": "2026-06-12T03:35:28Z", "next_step": "ai_review_required", - "pr_number": 27528, - "pr_url": "https://github.com/openai/codex/pull/27528", - "review_priority": "normal", - "review_reason": "Needs AI review for auth_account, release_packaging, security_policy.", - "sample_paths": [ - ".github/workflows/rust-release.yml" - ], - "source_state": "merged", - "subject_id": "27528", - "subject_kind": "pr", - "surface_hints": [ - "release_packaging", - "tests_ci" - ], - "title": "[codex] publish DotSlash alongside npm", - "url": "https://github.com/openai/codex/pull/27528" - }, - { - "attention_flags": [ - "auth_account", - "deprecated_removed", - "release_packaging" - ], - "changed_file_count": 1, - "commit_shas": [ - "d6c71bb414f08f61de227ce8bcfdad70184ae9a2" - ], - "committed_at": "2026-06-11T14:34:41Z", - "next_step": "ai_review_required", - "pr_number": 27529, - "pr_url": "https://github.com/openai/codex/pull/27529", - "review_priority": "normal", - "review_reason": "Needs AI review for auth_account, deprecated_removed, release_packaging.", - "sample_paths": [ - ".github/workflows/rust-release.yml" - ], - "source_state": "merged", - "subject_id": "27529", - "subject_kind": "pr", - "surface_hints": [ - "release_packaging", - "tests_ci" - ], - "title": "[codex] download only release artifacts", - "url": "https://github.com/openai/codex/pull/27529" - }, - { - "attention_flags": [ - "protocol_change" - ], - "changed_file_count": 3, - "commit_shas": [ - "44b802dda33f6dd369c1fa3536491302fb74cefd" - ], - "committed_at": "2026-06-11T16:55:53Z", - "next_step": "ai_review_required", - "pr_number": 27483, - "pr_url": "https://github.com/openai/codex/pull/27483", - "review_priority": "normal", - "review_reason": "Needs AI review for protocol_change.", + "pr_number": 27709, + "pr_url": "https://github.com/openai/codex/pull/27709", + "review_priority": "high", + "review_reason": "Needs AI review for new_feature, protocol_change, security_policy.", "sample_paths": [ - "codex-rs/analytics/src/analytics_client_tests.rs", - "codex-rs/analytics/src/events.rs", - "codex-rs/analytics/src/reducer.rs" + "codex-rs/app-server/src/request_processors/request_errors.rs", + "codex-rs/app-server/src/request_processors/thread_processor.rs", + "codex-rs/app-server/src/request_processors/turn_processor.rs", + "codex-rs/core/src/context/environment_context.rs", + "codex-rs/core/src/environment_selection.rs", + "codex-rs/core/src/session/session.rs", + "codex-rs/core/src/session/tests.rs", + "codex-rs/core/src/session/turn_context.rs", + "codex-rs/core/src/shell.rs", + "codex-rs/core/src/thread_manager.rs", + "codex-rs/core/tests/suite/remote_env.rs" ], "source_state": "merged", - "subject_id": "27483", + "subject_id": "27709", "subject_kind": "pr", "surface_hints": [ - "cli_tui", + "app_server_protocol", "tests_ci" ], - "title": "Emit plugin ID on MCP tool call analytics events", - "url": "https://github.com/openai/codex/pull/27483" + "title": "[codex] resolve environment shell metadata eagerly", + "url": "https://github.com/openai/codex/pull/27709" }, { "attention_flags": [ - "auth_account", - "breaking_change", "new_feature", "protocol_change" ], - "changed_file_count": 5, + "changed_file_count": 4, "commit_shas": [ - "ca736f650bbf6dbe664bb66f50baab760e7a70a0", - "90f100b8e5c09f2e299dbe6419d08c45843d790d", - "b522d62effdd8e2f2f3cd755ca9246617b9e85d4", - "794f5ad36787366bca6244e5b06eb8d98c36e582", - "97f7dbf6bcdcd7cc8c3cb6c28149d0374abe5bce" - ], - "committed_at": "2026-06-11T16:56:09Z", + "e1f5097af20944fd4ab67a85119cda325df034e0", + "cf6dfc47a4ce06f2c2f0fb3b8b3482a444c33024", + "9fb656edd473b51a766ced9d3156e5e919be3b0b", + "0c221b1bdba602903635ca905a69d271517097ea", + "e318c8c73787d0afdf445d170c2ef204ad6e7dda", + "e1511bb644aad5eb4a6f84e0a3d1626d0909bb03" + ], + "committed_at": "2026-06-12T09:49:17Z", "next_step": "ai_review_required", - "pr_number": 27417, - "pr_url": "https://github.com/openai/codex/pull/27417", - "review_priority": "normal", - "review_reason": "Needs AI review for auth_account, breaking_change, new_feature, protocol_change.", + "pr_number": 27732, + "pr_url": "https://github.com/openai/codex/pull/27732", + "review_priority": "high", + "review_reason": "Needs AI review for new_feature, protocol_change.", "sample_paths": [ - "codex-rs/cli/src/main.rs", - "codex-rs/tui/src/app.rs", - "codex-rs/tui/src/app/startup_prompts.rs", - "codex-rs/tui/src/lib.rs", - "codex-rs/tui/src/main.rs" + "codex-rs/code-mode-protocol/src/description.rs", + "codex-rs/code-mode/src/runtime/value.rs", + "codex-rs/code-mode/src/service.rs", + "codex-rs/core/tests/suite/code_mode.rs" ], "source_state": "merged", - "subject_id": "27417", + "subject_id": "27732", "subject_kind": "pr", "surface_hints": [ - "cli_tui" + "app_server_protocol", + "tests_ci" ], - "title": "Print TUI session info on fatal exits", - "url": "https://github.com/openai/codex/pull/27417" + "title": "[code-mode] Reject remote image URLs from output helpers", + "url": "https://github.com/openai/codex/pull/27732" }, { "attention_flags": [ @@ -1478,6 +1558,34 @@ ], "title": "ci(v8): gate Windows source builds on relevant changes", "url": "https://github.com/openai/codex/pull/27715" + }, + { + "attention_flags": [ + "new_feature", + "protocol_change", + "security_policy" + ], + "changed_file_count": 1, + "commit_shas": [ + "09d45b408a88670c30b2fd03a3c81d6d6456b436" + ], + "committed_at": "2026-06-12T06:20:36Z", + "next_step": "ai_review_required", + "pr_number": 27778, + "pr_url": "https://github.com/openai/codex/pull/27778", + "review_priority": "normal", + "review_reason": "Needs AI review for new_feature, protocol_change, security_policy.", + "sample_paths": [ + ".github/workflows/issue-translator.yml" + ], + "source_state": "merged", + "subject_id": "27778", + "subject_kind": "pr", + "surface_hints": [ + "tests_ci" + ], + "title": "Translate non-English issues", + "url": "https://github.com/openai/codex/pull/27778" } ] } diff --git a/artifacts/github/reviews/openai-codex-pr-27420.review.json b/artifacts/github/reviews/openai-codex-pr-27420.review.json new file mode 100644 index 000000000..ebb539d24 --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-27420.review.json @@ -0,0 +1,63 @@ +{ + "adoption_opportunity": "Expose or preserve app category values anywhere Decodex consumes Codex plugin app summaries, especially app/catalog UI surfaces that group plugin apps.", + "caveats": "This is an additive nullable protocol field. Older clients that ignore unknown fields should continue working, but generated TypeScript consumers may see a type shape change.", + "changed_surfaces": [ + "app-server protocol v2 AppSummary and AppTemplateSummary", + "plugin read and install responses", + "local .app.json parsing", + "remote app manifest category fallback", + "plugin read/install tests and generated schemas" + ], + "community_value": "High for plugin authors and app UI builders because it explains where plugin app categories now come from and how they appear in app-server responses.", + "compatibility_risk": "Low for tolerant JSON clients, but medium for strict generated clients or snapshots that assume AppSummary/AppTemplateSummary have no category field.", + "confidence": "confirmed", + "control_plane_relevance": "Moderate. Decodex plugin/app surfaces can now consume normalized categories from Codex app-server responses instead of deriving their own grouping.", + "deprecated_or_breaking_notes": "No removed behavior was observed. The protocol shape expands with a nullable category on app and template summaries.", + "evidence": [ + "PR #27420 says Codex parses optional `.app.json` category overrides, adds nullable category fields to app-server protocol summaries, and falls back from branding metadata to app metadata categories.", + "`codex-rs/app-server-protocol/src/protocol/v2/apps.rs` adds `AppInfo::category()` and a nullable `category` field on `AppSummary`.", + "`codex-rs/app-server-protocol/src/protocol/v2/plugin.rs` adds nullable `category` to `AppTemplateSummary`.", + "`codex-rs/core-plugins/src/loader.rs` parses optional app manifest categories into `PluginAppMetadata`.", + "`codex-rs/app-server/src/request_processors/plugins.rs` passes local and remote app categories into plugin read/install app summaries.", + "Tests in `plugin_install.rs` and `plugin_read.rs` assert category values for remote and local plugin app responses.", + "The normalized bundle `artifacts/github/bundles/openai-codex-pr-27420.json` records 16 changed files for the merged PR." + ], + "next_actions": [ + { + "reason": "The additive app-server protocol field may affect Decodex app/catalog UI and generated protocol consumers.", + "type": "upstream_impact" + }, + { + "reason": "The change has a clear practical explanation for plugin authors and app UI builders.", + "type": "social_candidate" + } + ], + "observed_change": "Codex app-server plugin responses now include nullable app category values derived from local `.app.json`, branding metadata, or remote app metadata.", + "repo": "openai/codex", + "reviewed_at": "2026-06-12T14:08:14Z", + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-27420", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-11T17:34:41Z", + "title": "[codex] Propagate plugin app categories", + "url": "https://github.com/openai/codex/pull/27420" + }, + { + "kind": "commit", + "title": "Propagate plugin app categories", + "url": "https://github.com/openai/codex/commit/2f6191ea633cd0a58580c484cc37d88191787385" + } + ] + }, + "subject": { + "commit_shas": [ + "2f6191ea633cd0a58580c484cc37d88191787385" + ], + "subject_id": "27420", + "subject_kind": "pr" + }, + "user_visible_path": "Users or clients reading plugin details, plugin install responses, or app templates can now see a normalized category for each app when upstream data supplies one." +} diff --git a/artifacts/github/reviews/openai-codex-pr-27424.review.json b/artifacts/github/reviews/openai-codex-pr-27424.review.json new file mode 100644 index 000000000..2b24b38c2 --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-27424.review.json @@ -0,0 +1,64 @@ +{ + "adoption_opportunity": "Align Decodex executor/app-server filesystem assumptions with PathUri internals while preserving public JSON-RPC absolute-path payload boundaries.", + "caveats": "The PR body says higher-level exec-server parts will be converted in future changes. Existing JSON-RPC filesystem payloads still carry absolute paths at adapter boundaries in this PR.", + "changed_surfaces": [ + "ExecutorFileSystem trait", + "app-server filesystem request processor", + "exec-server filesystem handler and helper", + "remote/local/sandboxed filesystem implementations", + "apply-patch/config/skills/git utilities that call ExecutorFileSystem", + "filesystem tests and PathUri test coverage" + ], + "community_value": "High for operator and integration audiences because PathUri changes the internal filesystem authority model while protocol adapters still preserve existing absolute-path request shapes.", + "compatibility_risk": "High for downstream Rust code that implements or calls `ExecutorFileSystem`; lower for JSON-RPC clients that stay on app-server/exec-server filesystem methods because adapters still convert absolute paths.", + "confidence": "confirmed", + "control_plane_relevance": "High. Decodex Control Plane uses filesystem, sandbox, apply-patch, skills, and app-server paths where PathUri authority and conversion behavior can affect retained-lane safety.", + "deprecated_or_breaking_notes": "`ExecutorFileSystem` methods now take `PathUri` instead of `AbsolutePathBuf`, return `PathUri` from canonicalize, and no longer expose join/parent in the trait.", + "evidence": [ + "PR #27424 says Codex is moving exec-server internals to `PathUri` while preserving native JSON-RPC filesystem payloads at protocol adapter boundaries.", + "`codex-rs/file-system/src/lib.rs` changes `ExecutorFileSystem` methods from `AbsolutePathBuf` to `PathUri` and removes `join` and `parent` from the trait.", + "`codex-rs/app-server/src/request_processors/fs_processor.rs` converts incoming absolute path params to `PathUri` before calling filesystem methods.", + "`codex-rs/exec-server/src/server/file_system_handler.rs` does the same conversion while leaving temporary join/parent handlers as lexical absolute-path operations.", + "`codex-rs/exec-server/src/remote_file_system.rs` converts `PathUri` back to absolute paths at the remote protocol call boundary.", + "`apply-patch`, config loading, core skills, git utilities, and skill provider code are updated to construct `PathUri` before filesystem reads/writes.", + "The normalized bundle `artifacts/github/bundles/openai-codex-pr-27424.json` records 52 changed files for the merged PR." + ], + "next_actions": [ + { + "reason": "The filesystem authority migration is a concrete Decodex Control Plane compatibility risk.", + "type": "upstream_impact" + }, + { + "reason": "The PathUri migration has a clear public operator explanation with important compatibility caveats.", + "type": "social_candidate" + } + ], + "observed_change": "Codex moves `ExecutorFileSystem` internals from absolute paths to `PathUri` while keeping filesystem JSON-RPC adapters on absolute-path payloads.", + "repo": "openai/codex", + "reviewed_at": "2026-06-12T14:08:14Z", + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-27424", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-11T18:44:19Z", + "title": "[codex] migrate ExecutorFileSystem paths to PathUri", + "url": "https://github.com/openai/codex/pull/27424" + }, + { + "kind": "commit", + "title": "Migrate ExecutorFileSystem paths to PathUri", + "url": "https://github.com/openai/codex/commit/32d2f04abebfd51a0062e3b68710bd60b5a51c98" + } + ] + }, + "subject": { + "commit_shas": [ + "32d2f04abebfd51a0062e3b68710bd60b5a51c98" + ], + "subject_id": "27424", + "subject_kind": "pr" + }, + "user_visible_path": "Rust integrations that implement filesystem traits must migrate to `PathUri`; app-server and exec-server JSON-RPC filesystem clients still send absolute-path payloads through adapter conversions." +} diff --git a/artifacts/github/reviews/openai-codex-pr-27433.review.json b/artifacts/github/reviews/openai-codex-pr-27433.review.json new file mode 100644 index 000000000..1ee1aa14f --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-27433.review.json @@ -0,0 +1,57 @@ +{ + "adoption_opportunity": "Model Decodex skill resource identities as environment id plus path rather than retaining a filesystem-bound path object across catalog and read calls.", + "caveats": "This PR is stacked on earlier filesystem adapter coverage and is followed by the broader PathUri migration in PR #27424.", + "changed_surfaces": [ + "exec-server public exports", + "skills catalog resource identity", + "executor skill resource reads", + "executor filesystem authority tests" + ], + "community_value": "Low to medium by itself because it is mostly an internal authority-model cleanup; public explanation is better grouped with the broader PathUri migration.", + "compatibility_risk": "Medium for first-party or downstream code that imported `EnvironmentPathRef` or expected skill resources to hold an executor filesystem instance directly.", + "confidence": "confirmed", + "control_plane_relevance": "High. Skill resource reads are a Control Plane surface, and Decodex must preserve environment authority when listing and later reading executor-backed skill resources.", + "deprecated_or_breaking_notes": "`EnvironmentPathRef` is removed from `codex-rs/exec-server/src/lib.rs` exports and its implementation file is deleted.", + "evidence": [ + "PR #27433 says Codex is switching to a static host-path encoding in `PathUri` and can reintroduce a bound path type later if needed.", + "`codex-rs/exec-server/src/environment_path.rs` is deleted and `EnvironmentPathRef` is no longer exported from `exec-server/src/lib.rs`.", + "`codex-rs/ext/skills/src/catalog.rs` replaces the bound `EnvironmentPathRef` with an internal `EnvironmentSkillResource` containing `environment_id` and `AbsolutePathBuf`.", + "`codex-rs/ext/skills/src/provider/executor.rs` now resolves the environment id at read time, then reads the skill resource through that environment filesystem.", + "A test that asserted reads remained bound to the original environment instance is removed, matching the new environment-id lookup model.", + "The normalized bundle `artifacts/github/bundles/openai-codex-pr-27433.json` records 5 changed files for the merged PR." + ], + "next_actions": [ + { + "reason": "The resource authority model affects Decodex skill/resource compatibility and should feed impact tracking.", + "type": "upstream_impact" + } + ], + "observed_change": "Codex removes `EnvironmentPathRef` and represents executor skill resources as environment id plus absolute path.", + "repo": "openai/codex", + "reviewed_at": "2026-06-12T14:08:14Z", + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-27433", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-11T18:26:13Z", + "title": "[codex] remove EnvironmentPathRef", + "url": "https://github.com/openai/codex/pull/27433" + }, + { + "kind": "commit", + "title": "Remove EnvironmentPathRef", + "url": "https://github.com/openai/codex/commit/a8e9807f4a94cf84b288c0c9ce2678788c9d3228" + } + ] + }, + "subject": { + "commit_shas": [ + "a8e9807f4a94cf84b288c0c9ce2678788c9d3228" + ], + "subject_id": "27433", + "subject_kind": "pr" + }, + "user_visible_path": "No direct TUI path was identified, but executor-backed skill resource reads may fail differently if their referenced environment is no longer available at read time." +} diff --git a/artifacts/github/reviews/openai-codex-pr-27646.review.json b/artifacts/github/reviews/openai-codex-pr-27646.review.json new file mode 100644 index 000000000..c58dfc6d3 --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-27646.review.json @@ -0,0 +1,59 @@ +{ + "adoption_opportunity": "Update Decodex expectations and tests so missing orchestrator skill resources are treated as current upstream behavior until the hosted skill package endpoint is restored.", + "caveats": "The upstream PR explicitly calls this a temporary disable while waiting for `/ps/mcp` to serve complete hosted skill packages.", + "changed_surfaces": [ + "app-server extension installation", + "skills extension provider wiring", + "orchestrator skill resource read test" + ], + "community_value": "Medium for operators troubleshooting why orchestrator-only skills are absent from app-server skill resources while executor skills still work.", + "compatibility_risk": "Medium for Decodex Control Plane and tests that expect orchestrator skills to be listed or readable through app-server resource APIs.", + "confidence": "confirmed", + "control_plane_relevance": "High. Decodex depends on app-server skill/resource behavior, and this PR intentionally suppresses the orchestrator skill provider while retaining executor skill support.", + "deprecated_or_breaking_notes": "Orchestrator-only skills are disabled behind `ORCHESTRATOR_SKILLS_ENABLED = false`; the test that reads an orchestrator skill resource is ignored until hosted skill packages are complete.", + "evidence": [ + "PR #27646 says orchestrator-only skills are temporarily disabled while waiting for `/ps/mcp` to serve complete hosted skill packages.", + "`codex-rs/app-server/src/extensions.rs` introduces `ORCHESTRATOR_SKILLS_ENABLED: bool = false`.", + "The app-server now builds skill providers with the executor provider first and adds `OrchestratorSkillProvider` only when that flag is true.", + "`codex-rs/app-server/tests/suite/v2/mcp_resource.rs` ignores the orchestrator skill resource read test with the same hosted-package caveat.", + "The normalized bundle `artifacts/github/bundles/openai-codex-pr-27646.json` records the two changed app-server files." + ], + "next_actions": [ + { + "reason": "Current app-server skill/resource behavior can affect Decodex Control Plane capability detection.", + "type": "upstream_impact" + }, + { + "reason": "This is a useful cautious public watch note for operators who expect hosted/orchestrator skills.", + "type": "social_candidate" + } + ], + "observed_change": "Codex temporarily disables app-server orchestrator skill providers while keeping executor-backed skills installed.", + "repo": "openai/codex", + "reviewed_at": "2026-06-12T14:08:14Z", + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-27646", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-11T18:20:26Z", + "title": "feat: disable orchestrator skills for now", + "url": "https://github.com/openai/codex/pull/27646" + }, + { + "kind": "commit", + "title": "feat: disable orchestrator skills for now", + "url": "https://github.com/openai/codex/commit/fef2bbfa4c23e6144afa8c2081ca4a44cca082dc" + } + ] + }, + "subject": { + "commit_shas": [ + "fef2bbfa4c23e6144afa8c2081ca4a44cca082dc" + ], + "subject_id": "27646", + "subject_kind": "pr" + }, + "user_visible_path": "Operators using app-server skill resources may see executor-backed skills but not orchestrator-only skills until upstream re-enables the orchestrator provider." +} diff --git a/artifacts/github/social-candidates/openai-codex-pr-27420.json b/artifacts/github/social-candidates/openai-codex-pr-27420.json new file mode 100644 index 000000000..9685bb25a --- /dev/null +++ b/artifacts/github/social-candidates/openai-codex-pr-27420.json @@ -0,0 +1,53 @@ +{ + "audience": "Codex plugin authors and app UI builders", + "candidate_text": [ + "Codex app-server plugin responses now include nullable app/template categories from `.app.json`, branding, or app metadata, so plugin detail UIs can group apps without custom lookups. PR: https://github.com/openai/codex/pull/27420" + ], + "caveats": [ + "The category field is nullable and additive.", + "Do not imply a new plugin install or auth capability." + ], + "channel": "x", + "claims": [ + { + "confidence": "confirmed", + "evidence": "artifacts/github/reviews/openai-codex-pr-27420.review.json", + "text": "Plugin app and template summaries now carry a nullable category field." + }, + { + "confidence": "confirmed", + "evidence": "artifacts/github/impact/openai-codex-pr-27420.json", + "text": "The category can come from local `.app.json`, branding metadata, or remote app metadata." + } + ], + "decision": { + "idempotency_key": "x:decodexspace:openai-codex-pr-27420:practical_explainer", + "reason": "The protocol addition has a concrete plugin UI and authoring explanation.", + "worthiness": "publish" + }, + "evidence_notes": [ + "`AppSummary` and `AppTemplateSummary` add nullable category fields.", + "Local and remote plugin metadata now feed category values into plugin responses.", + "Tests assert category propagation in plugin read/install responses." + ], + "mode": "practical_explainer", + "next_steps": [ + "Let Publisher automation decide whether to reserve or publish this candidate." + ], + "priority": "critical", + "repo": "openai/codex", + "schema": "social_candidate/v1", + "slug": "openai-codex-pr-27420", + "source_refs": { + "upstream_impacts": [ + "artifacts/github/impact/openai-codex-pr-27420.json" + ], + "upstream_reviews": [ + "artifacts/github/reviews/openai-codex-pr-27420.review.json" + ], + "urls": [ + "https://github.com/openai/codex/pull/27420" + ] + }, + "target_account": "decodexspace" +} diff --git a/artifacts/github/social-candidates/openai-codex-pr-27424.json b/artifacts/github/social-candidates/openai-codex-pr-27424.json new file mode 100644 index 000000000..c81ae6c7c --- /dev/null +++ b/artifacts/github/social-candidates/openai-codex-pr-27424.json @@ -0,0 +1,54 @@ +{ + "audience": "Codex filesystem, sandbox, and Control Plane integrators", + "candidate_text": [ + "Codex is moving executor file-system internals to PathUri. Protocol adapters still accept absolute-path JSON-RPC payloads, but filesystem implementations now read/write/canonicalize PathUri values. PR: https://github.com/openai/codex/pull/27424" + ], + "caveats": [ + "Do not claim JSON-RPC filesystem payloads changed in this PR.", + "Higher-level exec-server migration remains future upstream work." + ], + "channel": "x", + "claims": [ + { + "confidence": "confirmed", + "evidence": "artifacts/github/reviews/openai-codex-pr-27424.review.json", + "text": "`ExecutorFileSystem` internals now use `PathUri`." + }, + { + "confidence": "confirmed", + "evidence": "artifacts/github/impact/openai-codex-pr-27424.json", + "text": "The app-server and exec-server JSON-RPC filesystem boundaries still convert absolute-path params in this PR." + } + ], + "decision": { + "idempotency_key": "x:decodexspace:openai-codex-pr-27424:operator_impact", + "reason": "The PathUri migration has a concrete filesystem and Control Plane compatibility angle.", + "worthiness": "publish" + }, + "evidence_notes": [ + "`ExecutorFileSystem` method signatures now use `PathUri`.", + "Adapter code converts absolute path params into `PathUri` before filesystem calls.", + "Remote filesystem calls convert `PathUri` back to absolute protocol params." + ], + "mode": "operator_impact", + "next_steps": [ + "Let Publisher automation decide whether to reserve or publish this candidate.", + "Keep the adapter-boundary caveat in any downstream post." + ], + "priority": "critical", + "repo": "openai/codex", + "schema": "social_candidate/v1", + "slug": "openai-codex-pr-27424", + "source_refs": { + "upstream_impacts": [ + "artifacts/github/impact/openai-codex-pr-27424.json" + ], + "upstream_reviews": [ + "artifacts/github/reviews/openai-codex-pr-27424.review.json" + ], + "urls": [ + "https://github.com/openai/codex/pull/27424" + ] + }, + "target_account": "decodexspace" +} diff --git a/artifacts/github/social-candidates/openai-codex-pr-27646.json b/artifacts/github/social-candidates/openai-codex-pr-27646.json new file mode 100644 index 000000000..c0e626533 --- /dev/null +++ b/artifacts/github/social-candidates/openai-codex-pr-27646.json @@ -0,0 +1,54 @@ +{ + "audience": "Codex app-server and skill-resource operators", + "candidate_text": [ + "Codex temporarily disabled orchestrator-only skills: executor skills still load, but orchestrator skill resources wait on complete /ps/mcp packages. Treat missing orchestrator skills as expected for now. PR: https://github.com/openai/codex/pull/27646" + ], + "caveats": [ + "This is a temporary upstream gate.", + "Do not imply all skills or executor-backed skill resources are disabled." + ], + "channel": "x", + "claims": [ + { + "confidence": "confirmed", + "evidence": "artifacts/github/reviews/openai-codex-pr-27646.review.json", + "text": "Orchestrator-only skills are currently disabled behind an app-server feature flag." + }, + { + "confidence": "confirmed", + "evidence": "artifacts/github/impact/openai-codex-pr-27646.json", + "text": "Executor-backed skills still load through the app-server skill extension." + } + ], + "decision": { + "idempotency_key": "x:decodexspace:openai-codex-pr-27646:watch_note", + "reason": "The temporary gate can explain missing orchestrator skill resources for operators.", + "worthiness": "publish" + }, + "evidence_notes": [ + "`ORCHESTRATOR_SKILLS_ENABLED` is false.", + "The app-server adds `OrchestratorSkillProvider` only when that flag is true.", + "The orchestrator resource read test is ignored pending complete hosted skill packages." + ], + "mode": "watch_note", + "next_steps": [ + "Let Publisher automation decide whether to reserve or publish this candidate.", + "Watch for the follow-up PR that re-enables orchestrator skill packages." + ], + "priority": "critical", + "repo": "openai/codex", + "schema": "social_candidate/v1", + "slug": "openai-codex-pr-27646", + "source_refs": { + "upstream_impacts": [ + "artifacts/github/impact/openai-codex-pr-27646.json" + ], + "upstream_reviews": [ + "artifacts/github/reviews/openai-codex-pr-27646.review.json" + ], + "urls": [ + "https://github.com/openai/codex/pull/27646" + ] + }, + "target_account": "decodexspace" +} From 7b5cd8b64c01ed4b588cfec3f5614cc3ef381bd4 Mon Sep 17 00:00:00 2001 From: Yvette Carlisle Date: Sat, 13 Jun 2026 04:14:00 +0800 Subject: [PATCH 2/2] {"schema":"decodex/commit/1","summary":"Refresh upstream Radar review artifacts","authority":"manual"} --- .../github/bundles/openai-codex-pr-27318.json | 126 ++ .../github/bundles/openai-codex-pr-27445.json | 436 ++++++ .../github/bundles/openai-codex-pr-27475.json | 756 +++++++++++ .../github/bundles/openai-codex-pr-27498.json | 194 +++ .../github/impact/openai-codex-pr-27318.json | 45 + .../github/impact/openai-codex-pr-27445.json | 46 + .../github/impact/openai-codex-pr-27475.json | 45 + .../github/impact/openai-codex-pr-27498.json | 46 + .../review-queue/openai-codex-latest.json | 1164 +++++++++-------- .../reviews/openai-codex-pr-27318.review.json | 65 + .../reviews/openai-codex-pr-27445.review.json | 85 ++ .../reviews/openai-codex-pr-27475.review.json | 66 + .../reviews/openai-codex-pr-27498.review.json | 70 + .../openai-codex-pr-27445.json | 53 + .../openai-codex-pr-27498.json | 53 + 15 files changed, 2677 insertions(+), 573 deletions(-) create mode 100644 artifacts/github/bundles/openai-codex-pr-27318.json create mode 100644 artifacts/github/bundles/openai-codex-pr-27445.json create mode 100644 artifacts/github/bundles/openai-codex-pr-27475.json create mode 100644 artifacts/github/bundles/openai-codex-pr-27498.json create mode 100644 artifacts/github/impact/openai-codex-pr-27318.json create mode 100644 artifacts/github/impact/openai-codex-pr-27445.json create mode 100644 artifacts/github/impact/openai-codex-pr-27475.json create mode 100644 artifacts/github/impact/openai-codex-pr-27498.json create mode 100644 artifacts/github/reviews/openai-codex-pr-27318.review.json create mode 100644 artifacts/github/reviews/openai-codex-pr-27445.review.json create mode 100644 artifacts/github/reviews/openai-codex-pr-27475.review.json create mode 100644 artifacts/github/reviews/openai-codex-pr-27498.review.json create mode 100644 artifacts/github/social-candidates/openai-codex-pr-27445.json create mode 100644 artifacts/github/social-candidates/openai-codex-pr-27498.json diff --git a/artifacts/github/bundles/openai-codex-pr-27318.json b/artifacts/github/bundles/openai-codex-pr-27318.json new file mode 100644 index 000000000..7f29575fa --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-27318.json @@ -0,0 +1,126 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "wiltzius-openai", + "committed_at": "2026-06-10T05:26:14Z", + "message": "Add live thread history recorder hooks", + "sha": "eafa1fc84190009a6d53378565460290dba3ceb8", + "url": "https://github.com/openai/codex/commit/eafa1fc84190009a6d53378565460290dba3ceb8" + }, + { + "author": "wiltzius-openai", + "committed_at": "2026-06-11T18:15:44Z", + "message": "Remove stored item open flag", + "sha": "682f2b9c28f8bdc54c8b48e2f1587228b81c90ed", + "url": "https://github.com/openai/codex/commit/682f2b9c28f8bdc54c8b48e2f1587228b81c90ed" + }, + { + "author": "wiltzius-openai", + "committed_at": "2026-06-11T21:38:59Z", + "message": "Move raw append projection into thread stores", + "sha": "0b34bb09f82857993b511572569cdcfdaa9430ab", + "url": "https://github.com/openai/codex/commit/0b34bb09f82857993b511572569cdcfdaa9430ab" + }, + { + "author": "wiltzius-openai", + "committed_at": "2026-06-11T21:54:40Z", + "message": "Load resume history from explicit rollout path", + "sha": "6b06a574cc1be682580cfce269d755e3140e39f6", + "url": "https://github.com/openai/codex/commit/6b06a574cc1be682580cfce269d755e3140e39f6" + }, + { + "author": "wiltzius-openai", + "committed_at": "2026-06-11T22:00:22Z", + "message": "Keep resume path resolution inside stores", + "sha": "8f878400ea36dbcbc573a2f8d5bfacfe1b8c73b6", + "url": "https://github.com/openai/codex/commit/8f878400ea36dbcbc573a2f8d5bfacfe1b8c73b6" + }, + { + "author": "wiltzius-openai", + "committed_at": "2026-06-11T22:43:05Z", + "message": "Remove resume history comment", + "sha": "d2132fbc5250d96109f5c30b05a07432afa5afd3", + "url": "https://github.com/openai/codex/commit/d2132fbc5250d96109f5c30b05a07432afa5afd3" + } + ], + "default_branch": "main", + "docs_refs": [], + "examples_refs": [], + "extracted_flags": [ + "API" + ], + "files": [ + { + "additions": 8, + "deletions": 0, + "patch_excerpt": "@@ -124,6 +124,14 @@ impl ThreadHistoryBuilder {\n .or_else(|| self.turns.last().cloned())\n }\n \n+ pub fn turn_snapshot(&self, turn_id: &str) -> Option {\n+ self.current_turn\n+ .as_ref()\n+ .filter(|turn| turn.id == turn_id)\n+ .map(Turn::from)\n+ .or_else(|| self.turns.iter().find(|turn| turn.id == turn_id).cloned())\n+ }\n+\n /// Returns the index of the active turn snapshot within the finished turn list.\n ///\n /// When a turn is still open, this is the index it will occupy after", + "path": "codex-rs/app-server-protocol/src/protocol/thread_history.rs", + "status": "modified" + }, + { + "additions": 35, + "deletions": 41, + "patch_excerpt": "@@ -526,53 +526,47 @@ impl Session {\n } else {\n let live_thread = match &initial_history {\n InitialHistory::New | InitialHistory::Cleared | InitialHistory::Forked(_) => {\n- LiveThread::create(\n- Arc::clone(&thread_store),\n- CreateThreadParams {\n- thread_id,\n- extra_config: config.extra_config.clone(),\n- forked_from_id,\n- parent_thread_id,\n- source: session_source,\n- thread_source: session_configuration.thread_source.clone(),\n- base_instructions: BaseInstructions {\n- text: session_configuration.base_instructions.clone(...", + "path": "codex-rs/core/src/session/session.rs", + "status": "modified" + }, + { + "additions": 6, + "deletions": 1, + "patch_excerpt": "@@ -14,6 +14,7 @@ use codex_protocol::protocol::RolloutItem;\n use codex_protocol::protocol::SessionMeta;\n use codex_protocol::protocol::SessionMetaLine;\n use codex_protocol::protocol::ThreadMemoryMode;\n+use codex_rollout::persisted_rollout_items;\n \n use crate::AppendThreadItemsParams;\n use crate::ArchiveThreadParams;\n@@ -215,13 +216,17 @@ impl ThreadStore for InMemoryThreadStore {\n }\n \n async fn append_items(&self, params: AppendThreadItemsParams) -> ThreadStoreResult<()> {\n+ let canonical_items = persisted_rollout_items(params.items.as_slice());\n+ if canonical_items.is_empty() {\n+ return Ok(());\n+ }\n let mut state = self.state.lock().await;\n state.calls.append_items += 1;\n state\n .histories\n .entry(params.thread_id)\n .or_default()\n- .extend(params.items);\n+ .extend(c...", + "path": "codex-rs/thread-store/src/in_memory.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -40,6 +40,7 @@ pub use types::SearchThreadsParams;\n pub use types::SortDirection;\n pub use types::StoredThread;\n pub use types::StoredThreadHistory;\n+pub use types::StoredThreadItem;\n pub use types::StoredThreadSearchResult;\n pub use types::StoredTurn;\n pub use types::StoredTurnError;", + "path": "codex-rs/thread-store/src/lib.rs", + "status": "modified" + }, + { + "additions": 10, + "deletions": 3, + "patch_excerpt": "@@ -116,7 +116,11 @@ impl LiveThread {\n {\n Ok(history) => params.history = Some(history.items),\n Err(err) => {\n- let _ = thread_store.discard_thread(thread_id).await;\n+ if let Err(discard_err) = thread_store.discard_thread(thread_id).await {\n+ warn!(\n+ \"failed to discard thread persistence after resume history load failed: {discard_err}\"\n+ );\n+ }\n return Err(err);\n }\n }\n@@ -131,15 +135,18 @@ impl LiveThread {\n \n pub async fn append_items(&self, items: &[RolloutItem]) -> ThreadStoreResult<()> {\n let canonical_items = persisted_rollout_items(items);\n- if canonical_items.is_empty() {\n+ if items.is_empty() {\n return Ok(());\n }\n ...", + "path": "codex-rs/thread-store/src/live_thread.rs", + "status": "modified" + }, + { + "additions": 6, + "deletions": 1, + "patch_excerpt": "@@ -5,6 +5,7 @@ use codex_protocol::protocol::ThreadMemoryMode;\n use codex_rollout::RolloutConfig;\n use codex_rollout::RolloutRecorder;\n use codex_rollout::RolloutRecorderParams;\n+use codex_rollout::persisted_rollout_items;\n use tracing::warn;\n \n use super::LocalThreadStore;\n@@ -77,9 +78,13 @@ pub(super) async fn append_items(\n store: &LocalThreadStore,\n params: AppendThreadItemsParams,\n ) -> ThreadStoreResult<()> {\n+ let canonical_items = persisted_rollout_items(params.items.as_slice());\n+ if canonical_items.is_empty() {\n+ return Ok(());\n+ }\n let recorder = store.live_recorder(params.thread_id).await?;\n recorder\n- .record_canonical_items(params.items.as_slice())\n+ .record_canonical_items(canonical_items.as_slice())\n .await\n .map_err(thread_store_io_error)?;\n // LiveThread applies metadata immediately after append_items re...", + "path": "codex-rs/thread-store/src/local/live_writer.rs", + "status": "modified" + }, + { + "additions": 3, + "deletions": 4, + "patch_excerpt": "@@ -36,11 +36,10 @@ pub trait ThreadStore: Any + Send + Sync {\n /// Reopens an existing thread for live appends.\n async fn resume_thread(&self, params: ResumeThreadParams) -> ThreadStoreResult<()>;\n \n- /// Appends canonical rollout items to a live thread.\n+ /// Appends raw rollout items to a live thread.\n ///\n- /// This is the raw history API. It does not infer metadata from item contents. Callers that\n- /// need metadata updates should call [`ThreadStore::update_thread_metadata`] with explicit\n- /// metadata facts prepared above the store.\n+ /// Implementations should apply the shared rollout persistence policy before writing durable\n+ /// replay history and before updating any implementation-owned projections.\n async fn append_items(&self, params: AppendThreadItemsParams) -> ThreadStoreResult<()>;\n \n /// Materializes the thread if persistence is...", + "path": "codex-rs/thread-store/src/store.rs", + "status": "modified" + }, + { + "additions": 22, + "deletions": 4, + "patch_excerpt": "@@ -101,11 +101,14 @@ pub struct ResumeThreadParams {\n }\n \n /// Parameters for appending rollout items to a live thread.\n-#[derive(Clone, Debug, Serialize, Deserialize)]\n+#[derive(Clone, Debug)]\n pub struct AppendThreadItemsParams {\n /// Thread id to append to.\n pub thread_id: ThreadId,\n- /// Items to append in order.\n+ /// Raw rollout items to append in order.\n+ ///\n+ /// Store implementations are responsible for applying the shared rollout persistence policy\n+ /// before writing durable replay history or any implementation-owned projections.\n pub items: Vec,\n }\n \n@@ -297,6 +300,11 @@ pub struct StoredTurn {\n pub turn_id: String,\n /// Persisted rollout items associated with this turn, according to `items_view`.\n pub items: Vec,\n+ /// Opaque serialized turn metadata supplied by a projected durable store.\n+ pub metadat...", + "path": "codex-rs/thread-store/src/types.rs", + "status": "modified" + } + ], + "linked_issues": [], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "Move the application of the persistence policy into the thread store, so thread stores can get raw append items rather than canonical append items. This will enable store-specific projections over the raw input items.", + "labels": [], + "merged_at": "2026-06-11T23:24:13Z", + "number": 27318, + "state": "merged", + "title": "[codex] Move persistence policy application into ThreadStore", + "url": "https://github.com/openai/codex/pull/27318" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/bundles/openai-codex-pr-27445.json b/artifacts/github/bundles/openai-codex-pr-27445.json new file mode 100644 index 000000000..86c47f3fa --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-27445.json @@ -0,0 +1,436 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "apanasenko-oai", + "committed_at": "2026-06-10T19:26:10Z", + "message": "Persist remote-control desired state", + "sha": "c1c83d3db1c92450ee5104637673da205c3b53f1", + "url": "https://github.com/openai/codex/commit/c1c83d3db1c92450ee5104637673da205c3b53f1" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-10T22:24:00Z", + "message": "Complete durable remote-control enrollment on enable", + "sha": "11b7a3193c9c0b607a89154d613bf31bf9968356", + "url": "https://github.com/openai/codex/commit/11b7a3193c9c0b607a89154d613bf31bf9968356" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T04:01:16Z", + "message": "codex: fix CI failure on PR #27445", + "sha": "37c9a1af8e791b935a7e6b79412097349b3be23a", + "url": "https://github.com/openai/codex/commit/37c9a1af8e791b935a7e6b79412097349b3be23a" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T16:08:26Z", + "message": "codex: address PR review feedback (#27445)", + "sha": "2ccf773428b3e45ea0bf628f7cdc1f829acb4ec6", + "url": "https://github.com/openai/codex/commit/2ccf773428b3e45ea0bf628f7cdc1f829acb4ec6" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T16:23:27Z", + "message": "codex: address PR review feedback (#27445)", + "sha": "89e994bf64ee35e3e03915cea760486b67eeeddb", + "url": "https://github.com/openai/codex/commit/89e994bf64ee35e3e03915cea760486b67eeeddb" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T16:38:38Z", + "message": "Revert \"codex: address PR review feedback (#27445)\"", + "sha": "f06ad42c1964a93de5e96576e7c4244ac41f2e74", + "url": "https://github.com/openai/codex/commit/f06ad42c1964a93de5e96576e7c4244ac41f2e74" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T17:33:26Z", + "message": "codex: address PR review feedback (#27445)", + "sha": "751a2a5ffa1105ebf86c0c89507d97b1dd8a203e", + "url": "https://github.com/openai/codex/commit/751a2a5ffa1105ebf86c0c89507d97b1dd8a203e" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T17:44:47Z", + "message": "codex: fix argument comment lint on PR #27445", + "sha": "5d46286a8c47f23d546e431d8395861091407ac3", + "url": "https://github.com/openai/codex/commit/5d46286a8c47f23d546e431d8395861091407ac3" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T17:54:46Z", + "message": "codex: address PR review feedback (#27445)", + "sha": "51201c3539709dc098c33bb5d917c3f3c2c360d1", + "url": "https://github.com/openai/codex/commit/51201c3539709dc098c33bb5d917c3f3c2c360d1" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T18:07:10Z", + "message": "codex: address PR review feedback (#27445)", + "sha": "51c0ede50280cb2b7720ad4edc795b99f2bbff8b", + "url": "https://github.com/openai/codex/commit/51c0ede50280cb2b7720ad4edc795b99f2bbff8b" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T18:16:29Z", + "message": "codex: fix Windows clippy on PR #27445", + "sha": "5957b62fc0479ae8ab34b1126edbfc482536d7a1", + "url": "https://github.com/openai/codex/commit/5957b62fc0479ae8ab34b1126edbfc482536d7a1" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T18:25:58Z", + "message": "codex: address PR review feedback (#27445)", + "sha": "38fa3a8ac4472cf91ae78a7bcf46de916d96849a", + "url": "https://github.com/openai/codex/commit/38fa3a8ac4472cf91ae78a7bcf46de916d96849a" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T21:22:09Z", + "message": "codex: simplify remote control startup state", + "sha": "6d519c7361e8c5d9ea93acd5a9ee2bdf8b52d76e", + "url": "https://github.com/openai/codex/commit/6d519c7361e8c5d9ea93acd5a9ee2bdf8b52d76e" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T21:50:16Z", + "message": "codex: simplify remote control availability state", + "sha": "ffc649de3e5b2fb406e8fc84b26973bf375762ab", + "url": "https://github.com/openai/codex/commit/ffc649de3e5b2fb406e8fc84b26973bf375762ab" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-11T22:10:21Z", + "message": "fix remote control startup edge cases", + "sha": "d4c46df25f4a90a7cb75380379d58bb301bcb9af", + "url": "https://github.com/openai/codex/commit/d4c46df25f4a90a7cb75380379d58bb301bcb9af" + }, + { + "author": "apanasenko-oai", + "committed_at": "2026-06-12T00:07:56Z", + "message": "reject disabled transportless remote control startup", + "sha": "e34ec2789518918e9cd1d8b06187ce1da043b5b5", + "url": "https://github.com/openai/codex/commit/e34ec2789518918e9cd1d8b06187ce1da043b5b5" + } + ], + "default_branch": "main", + "docs_refs": [ + "codex-rs/app-server/README.md" + ], + "examples_refs": [], + "extracted_flags": [ + "RPC", + "CLI", + "NULL", + "REMOTE_CONTROL_DISABLED_ENV_VAR", + "--listen", + "JSONRPCM", + "JSONRPCN", + "JSONRPCR", + "REMOTE_CONTROL_READY_TIMEOUT", + "REMOTE_CONTROL_ENABLE_REQUEST_ID", + "REMOTE_CONTROL_REQUEST_ID", + "INVALID_PARAMS_ERROR_CODE", + "CONTROL_SOCKET_RESPONSE_TIMEOUT", + "JSONRPCE", + "TEST_SERVER_NAME", + "GENERATED", + "CODE", + "NOT", + "MODIFY", + "HAND", + "CHANNEL_CAPACITY", + "CODEX_INTERNAL_APP_SERVER_REMOTE_CONTROL_DISABLED", + "SAFETY", + "REMOTE_CONTROL_PROTOCOL_VERSION", + "TEST_REMOTE_CONTROL_URL", + "TEST_INSTALLATION_ID", + "URL", + "POST", + "HTTP", + "TEST_REFRESHED_REMOTE_CONTROL_SERVER_TOKEN", + "REMOTE_CONTROL_ACCOUNT_ID_RETRY_INTERVAL", + "INPUT_TOO_LARGE_ERROR_CODE", + "LOG_FORMAT_ENV_VAR", + "LOG_FORMAT", + "OTEL_SERVICE_NAME", + "DISABLE_PLUGIN_STARTUP_TASKS_ARG", + "--disable-plugin-startup-tas", + "DISABLE_MANAGED_CONFIG_ENV_VAR", + "CODEX_APP_SERVER_DISABLE_MANAGED_CONFIG", + "JSON", + "DEFAULT_CLIENT_NAME", + "DEFAULT_TIMEOUT", + "STARTUP_TIMEOUT", + "--remote-control", + "ALTER", + "TABLE", + "ADD", + "COLUMN", + "INTEGER", + "SELECT", + "FROM", + "WHERE", + "AND", + "INSERT", + "INTO", + "VALUES", + "CONFLICT", + "UPDATE", + "SET", + "STATE_MIGRATOR" + ], + "files": [ + { + "additions": 18, + "deletions": 0, + "patch_excerpt": "@@ -8,6 +8,8 @@ use std::time::Duration;\n use anyhow::Context;\n use anyhow::Result;\n use anyhow::bail;\n+#[cfg(unix)]\n+use codex_app_server_transport::REMOTE_CONTROL_DISABLED_ENV_VAR;\n use serde::Deserialize;\n use serde::Serialize;\n use tokio::fs;\n@@ -164,6 +166,9 @@ impl PidBackend {\n .stdin(Stdio::null())\n .stdout(Stdio::null())\n .stderr(Stdio::from(stderr_log.into_std().await));\n+ if let Some((key, value)) = self.command_env() {\n+ command.env(key, value);\n+ }\n \n #[cfg(unix)]\n {\n@@ -407,6 +412,19 @@ impl PidBackend {\n }\n }\n \n+ #[cfg(unix)]\n+ fn command_env(&self) -> Option<(&'static str, &'static str)> {\n+ match self.command_kind {\n+ PidCommandKind::AppServer {\n+ remote_control_enabled: false,\n+ } => Some((REMOTE_CONTROL_DISABLED_ENV_VAR, \"1\")),\n+ ...", + "path": "codex-rs/app-server-daemon/src/backend/pid.rs", + "status": "modified" + }, + { + "additions": 20, + "deletions": 0, + "patch_excerpt": "@@ -3,6 +3,8 @@ use std::time::Duration;\n use pretty_assertions::assert_eq;\n use tempfile::TempDir;\n \n+use codex_app_server_transport::REMOTE_CONTROL_DISABLED_ENV_VAR;\n+\n use super::PidBackend;\n use super::PidCommandKind;\n use super::PidFileState;\n@@ -174,6 +176,24 @@ fn app_server_remote_control_uses_runtime_flag() {\n );\n }\n \n+#[test]\n+fn app_server_disabled_remote_control_uses_compatible_args_and_runtime_env() {\n+ let backend = PidBackend::new(\n+ \"codex\".into(),\n+ \"app-server.pid\".into(),\n+ /*remote_control_enabled*/ false,\n+ );\n+\n+ assert_eq!(\n+ backend.command_args(),\n+ vec![\"app-server\", \"--listen\", \"unix://\"]\n+ );\n+ assert_eq!(\n+ backend.command_env(),\n+ Some((REMOTE_CONTROL_DISABLED_ENV_VAR, \"1\"))\n+ );\n+}\n+\n #[tokio::test]\n async fn read_stderr_log_tail_returns_recent_complete_lines() {\n let temp_dir = Temp...", + "path": "codex-rs/app-server-daemon/src/backend/pid_tests.rs", + "status": "modified" + }, + { + "additions": 10, + "deletions": 0, + "patch_excerpt": "@@ -543,6 +543,16 @@ impl Daemon {\n } else {\n None\n };\n+ if info.is_some() {\n+ match mode {\n+ RemoteControlMode::Enabled => {\n+ remote_control_client::enable_remote_control(&self.socket_path).await?;\n+ }\n+ RemoteControlMode::Disabled => {\n+ remote_control_client::disable_remote_control(&self.socket_path).await?;\n+ }\n+ }\n+ }\n return Ok(self.remote_control_output(\n already_remote_control_status(mode),\n backend.map(|_| BackendKind::Pid),", + "path": "codex-rs/app-server-daemon/src/lib.rs", + "status": "modified" + }, + { + "additions": 291, + "deletions": 58, + "patch_excerpt": "@@ -8,9 +8,13 @@ use codex_app_server_protocol::JSONRPCMessage;\n use codex_app_server_protocol::JSONRPCNotification;\n use codex_app_server_protocol::JSONRPCRequest;\n use codex_app_server_protocol::RemoteControlConnectionStatus;\n+use codex_app_server_protocol::RemoteControlDisableParams;\n+use codex_app_server_protocol::RemoteControlDisableResponse;\n+use codex_app_server_protocol::RemoteControlEnableParams;\n use codex_app_server_protocol::RemoteControlEnableResponse;\n use codex_app_server_protocol::RemoteControlStatusChangedNotification;\n use codex_app_server_protocol::RequestId;\n+use serde::de::DeserializeOwned;\n use tokio::io::AsyncRead;\n use tokio::io::AsyncWrite;\n use tokio::time::Instant;\n@@ -22,13 +26,33 @@ use crate::RemoteControlReadyStatus;\n use crate::client;\n \n const REMOTE_CONTROL_READY_TIMEOUT: Duration = Duration::from_secs(10);\n-const REMOTE_CONTROL_ENABLE_REQUEST_ID: Reques...", + "path": "codex-rs/app-server-daemon/src/remote_control_client.rs", + "status": "modified" + }, + { + "additions": 16, + "deletions": 0, + "patch_excerpt": "@@ -2124,6 +2124,22 @@\n }\n ]\n },\n+ \"RemoteControlDisableParams\": {\n+ \"properties\": {\n+ \"ephemeral\": {\n+ \"type\": \"boolean\"\n+ }\n+ },\n+ \"type\": \"object\"\n+ },\n+ \"RemoteControlEnableParams\": {\n+ \"properties\": {\n+ \"ephemeral\": {\n+ \"type\": \"boolean\"\n+ }\n+ },\n+ \"type\": \"object\"\n+ },\n \"RequestId\": {\n \"anyOf\": [\n {", + "path": "codex-rs/app-server-protocol/schema/json/ClientRequest.json", + "status": "modified" + }, + { + "additions": 16, + "deletions": 0, + "patch_excerpt": "@@ -13991,6 +13991,22 @@\n ],\n \"type\": \"string\"\n },\n+ \"RemoteControlDisableParams\": {\n+ \"properties\": {\n+ \"ephemeral\": {\n+ \"type\": \"boolean\"\n+ }\n+ },\n+ \"type\": \"object\"\n+ },\n+ \"RemoteControlEnableParams\": {\n+ \"properties\": {\n+ \"ephemeral\": {\n+ \"type\": \"boolean\"\n+ }\n+ },\n+ \"type\": \"object\"\n+ },\n \"RemoteControlStatusChangedNotification\": {\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"description\": \"Current remote-control connection status and remote identity exposed to clients.\",", + "path": "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json", + "status": "modified" + }, + { + "additions": 16, + "deletions": 0, + "patch_excerpt": "@@ -10493,6 +10493,22 @@\n ],\n \"type\": \"string\"\n },\n+ \"RemoteControlDisableParams\": {\n+ \"properties\": {\n+ \"ephemeral\": {\n+ \"type\": \"boolean\"\n+ }\n+ },\n+ \"type\": \"object\"\n+ },\n+ \"RemoteControlEnableParams\": {\n+ \"properties\": {\n+ \"ephemeral\": {\n+ \"type\": \"boolean\"\n+ }\n+ },\n+ \"type\": \"object\"\n+ },\n \"RemoteControlStatusChangedNotification\": {\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"description\": \"Current remote-control connection status and remote identity exposed to clients.\",", + "path": "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json", + "status": "modified" + }, + { + "additions": 5, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,5 @@\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+export type RemoteControlDisableParams = { ephemeral?: boolean, };", + "path": "codex-rs/app-server-protocol/schema/typescript/v2/RemoteControlDisableParams.ts", + "status": "added" + }, + { + "additions": 5, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,5 @@\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+export type RemoteControlEnableParams = { ephemeral?: boolean, };", + "path": "codex-rs/app-server-protocol/schema/typescript/v2/RemoteControlEnableParams.ts", + "status": "added" + }, + { + "additions": 2, + "deletions": 0, + "patch_excerpt": "@@ -325,6 +325,8 @@ export type { ReasoningSummaryPartAddedNotification } from \"./ReasoningSummaryPa\n export type { ReasoningSummaryTextDeltaNotification } from \"./ReasoningSummaryTextDeltaNotification\";\n export type { ReasoningTextDeltaNotification } from \"./ReasoningTextDeltaNotification\";\n export type { RemoteControlConnectionStatus } from \"./RemoteControlConnectionStatus\";\n+export type { RemoteControlDisableParams } from \"./RemoteControlDisableParams\";\n+export type { RemoteControlEnableParams } from \"./RemoteControlEnableParams\";\n export type { RemoteControlStatusChangedNotification } from \"./RemoteControlStatusChangedNotification\";\n export type { RequestPermissionProfile } from \"./RequestPermissionProfile\";\n export type { ResidencyRequirement } from \"./ResidencyRequirement\";", + "path": "codex-rs/app-server-protocol/schema/typescript/v2/index.ts", + "status": "modified" + }, + { + "additions": 2, + "deletions": 2, + "patch_excerpt": "@@ -842,13 +842,13 @@ client_request_definitions! {\n },\n #[experimental(\"remoteControl/enable\")]\n RemoteControlEnable => \"remoteControl/enable\" {\n- params: #[ts(type = \"undefined\")] #[serde(skip_serializing_if = \"Option::is_none\")] Option<()>,\n+ params: #[serde(skip_serializing_if = \"Option::is_none\")] v2::NullableRemoteControlEnableParams,\n serialization: global(\"remote-control\"),\n response: v2::RemoteControlEnableResponse,\n },\n #[experimental(\"remoteControl/disable\")]\n RemoteControlDisable => \"remoteControl/disable\" {\n- params: #[ts(type = \"undefined\")] #[serde(skip_serializing_if = \"Option::is_none\")] Option<()>,\n+ params: #[serde(skip_serializing_if = \"Option::is_none\")] v2::NullableRemoteControlDisableParams,\n serialization: global(\"remote-control\"),\n response: v2::RemoteControlDisableResponse,\n ...", + "path": "codex-rs/app-server-protocol/src/protocol/common.rs", + "status": "modified" + }, + { + "additions": 20, + "deletions": 0, + "patch_excerpt": "@@ -3,6 +3,26 @@ use serde::Deserialize;\n use serde::Serialize;\n use ts_rs::TS;\n \n+#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema, TS)]\n+#[serde(rename_all = \"camelCase\")]\n+#[ts(export_to = \"v2/\")]\n+pub struct RemoteControlEnableParams {\n+ #[serde(default, skip_serializing_if = \"std::ops::Not::not\")]\n+ pub ephemeral: bool,\n+}\n+\n+pub type NullableRemoteControlEnableParams = Option;\n+\n+#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema, TS)]\n+#[serde(rename_all = \"camelCase\")]\n+#[ts(export_to = \"v2/\")]\n+pub struct RemoteControlDisableParams {\n+ #[serde(default, skip_serializing_if = \"std::ops::Not::not\")]\n+ pub ephemeral: bool,\n+}\n+\n+pub type NullableRemoteControlDisableParams = Option;\n+\n /// Current remote-control connection status and remote identity expos...", + "path": "codex-rs/app-server-protocol/src/protocol/v2/remote_control.rs", + "status": "modified" + }, + { + "additions": 3, + "deletions": 0, + "patch_excerpt": "@@ -11,8 +11,10 @@ pub use transport::AppServerTransport;\n pub use transport::AppServerTransportParseError;\n pub use transport::CHANNEL_CAPACITY;\n pub use transport::ConnectionOrigin;\n+pub use transport::REMOTE_CONTROL_DISABLED_ENV_VAR;\n pub use transport::RemoteControlHandle;\n pub use transport::RemoteControlStartConfig;\n+pub use transport::RemoteControlStartupMode;\n pub use transport::RemoteControlUnavailable;\n pub use transport::TransportEvent;\n pub use transport::acquire_app_server_startup_lock;\n@@ -24,3 +26,4 @@ pub use transport::start_control_socket_acceptor;\n pub use transport::start_remote_control;\n pub use transport::start_stdio_connection;\n pub use transport::start_websocket_acceptor;\n+pub use transport::take_remote_control_disabled_env;", + "path": "codex-rs/app-server-transport/src/lib.rs", + "status": "modified" + }, + { + "additions": 3, + "deletions": 0, + "patch_excerpt": "@@ -30,10 +30,13 @@ mod unix_socket;\n mod unix_socket_tests;\n mod websocket;\n \n+pub use remote_control::REMOTE_CONTROL_DISABLED_ENV_VAR;\n pub use remote_control::RemoteControlHandle;\n pub use remote_control::RemoteControlStartConfig;\n+pub use remote_control::RemoteControlStartupMode;\n pub use remote_control::RemoteControlUnavailable;\n pub use remote_control::start_remote_control;\n+pub use remote_control::take_remote_control_disabled_env;\n pub use stdio::start_stdio_connection;\n pub use unix_socket::AppServerStartupLock;\n pub use unix_socket::acquire_app_server_startup_lock;", + "path": "codex-rs/app-server-transport/src/transport/mod.rs", + "status": "modified" + }, + { + "additions": 158, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,158 @@\n+use super::RemoteControlHandle;\n+use super::RemoteControlUnavailable;\n+use super::enroll::update_persisted_remote_control_enrollment;\n+use super::protocol::normalize_remote_control_url;\n+use super::publish_current_enrollment;\n+use super::websocket::RemoteControlStatusPublisher;\n+use codex_app_server_protocol::RemoteControlStatusChangedNotification;\n+use codex_state::RemoteControlEnrollmentRecord;\n+use std::io;\n+use tokio::sync::Semaphore;\n+use tokio::sync::SemaphorePermit;\n+\n+#[derive(Debug, Clone, Copy, PartialEq, Eq)]\n+pub(super) enum RemoteControlDesiredState {\n+ // `Unknown` exists only on plain startup before auth and enrollment scope resolve. Persisted\n+ // `1` is `Enabled { persistence_preference: Some(true) }`; `0`, `NULL`, or no row are\n+ // `Disabled`. Runtime-only enable is `Enabled { persistence_preference: None }`, so new rows\n+ // keep `NULL`;...", + "path": "codex-rs/app-server-transport/src/transport/remote_control/desired_state.rs", + "status": "added" + }, + { + "additions": 7, + "deletions": 0, + "patch_excerpt": "@@ -286,6 +286,7 @@ pub(super) async fn update_persisted_remote_control_enrollment(\n account_id: &str,\n app_server_client_name: Option<&str>,\n enrollment: Option<&RemoteControlEnrollment>,\n+ remote_control_enabled: Option,\n ) -> io::Result<()> {\n let Some(state_db) = state_db else {\n return Err(io::Error::new(\n@@ -316,6 +317,7 @@ pub(super) async fn update_persisted_remote_control_enrollment(\n server_id: enrollment.server_id.clone(),\n environment_id: enrollment.environment_id.clone(),\n server_name: enrollment.server_name.clone(),\n+ remote_control_enabled,\n })\n .await\n .map_err(io::Error::other)?;\n@@ -648,6 +650,7 @@ mod tests {\n \"account-a\",\n Some(\"desktop-client\"),\n Some(&first_enrollment),\n+ /*remote_control_e...", + "path": "codex-rs/app-server-transport/src/transport/remote_control/enroll.rs", + "status": "modified" + }, + { + "additions": 278, + "deletions": 157, + "patch_excerpt": "@@ -1,13 +1,16 @@\n mod auth;\n mod client_tracker;\n mod clients;\n+mod desired_state;\n mod enroll;\n mod protocol;\n mod segment;\n mod websocket;\n \n use self::auth::load_remote_control_auth;\n use self::auth::recover_remote_control_auth;\n+use self::desired_state::RemoteControlDesiredState;\n+use self::desired_state::acquire_persistence_lock;\n use self::enroll::RemoteControlEnrollment;\n use self::enroll::enroll_remote_control_server;\n use self::enroll::load_persisted_remote_control_enrollment;\n@@ -63,6 +66,26 @@ pub struct RemoteControlStartConfig {\n pub installation_id: String,\n }\n \n+#[derive(Debug, Clone, Copy, PartialEq, Eq)]\n+pub enum RemoteControlStartupMode {\n+ ResolvePersisted,\n+ DisabledEphemeral,\n+ EnabledEphemeral,\n+}\n+\n+/// Internal marker used by the daemon to disable remote control without requiring a new CLI flag.\n+pub const REMOTE_CONTROL_DISABLED_ENV_VAR: &str =\n+ ...", + "path": "codex-rs/app-server-transport/src/transport/remote_control/mod.rs", + "status": "modified" + }, + { + "additions": 478, + "deletions": 53, + "patch_excerpt": "@@ -9,6 +9,8 @@ use super::protocol::ClientId;\n use super::protocol::StreamId;\n use super::protocol::normalize_remote_control_url;\n use super::websocket::REMOTE_CONTROL_PROTOCOL_VERSION;\n+use super::websocket::RemoteControlWebsocket;\n+use super::websocket::RemoteControlWebsocketConfig;\n use super::*;\n use crate::outgoing_message::OutgoingMessage;\n use crate::outgoing_message::QueuedOutgoingMessage;\n@@ -33,6 +35,7 @@ use codex_login::CodexAuth;\n use codex_login::save_auth;\n use codex_login::token_data::TokenData;\n use codex_login::token_data::parse_chatgpt_jwt_claims;\n+use codex_state::RemoteControlEnrollmentRecord;\n use codex_state::StateRuntime;\n use futures::SinkExt;\n use futures::StreamExt;\n@@ -125,6 +128,137 @@ async fn remote_control_state_runtime(codex_home: &TempDir) -> Arc\n .expect(\"state runtime should initialize\")\n }\n \n+#[tokio::test]\n+async fn plain_start...", + "path": "codex-rs/app-server-transport/src/transport/remote_control/tests.rs", + "status": "modified" + }, + { + "additions": 4, + "deletions": 3, + "patch_excerpt": "@@ -13,17 +13,18 @@ fn client_management_handle(\n remote_control_url: String,\n auth_manager: Arc,\n ) -> RemoteControlHandle {\n- let (enabled_tx, _enabled_rx) = watch::channel(/*init*/ false);\n+ let desired_state_tx = watch::channel(RemoteControlDesiredState::Disabled).0;\n let (status_tx, _status_rx) = watch::channel(RemoteControlStatusChangedNotification {\n status: RemoteControlConnectionStatus::Disabled,\n server_name: test_server_name(),\n installation_id: TEST_INSTALLATION_ID.to_string(),\n environment_id: None,\n });\n RemoteControlHandle {\n- enabled_tx: Arc::new(enabled_tx),\n+ desired_state_tx: Arc::new(desired_state_tx),\n+ desired_state_rpc_lock: Arc::new(Semaphore::new(1)),\n+ desired_state_persistence_lock: Arc::new(Semaphore::new(1)),\n status_tx: Arc::new(status_tx),\n- sta...", + "path": "codex-rs/app-server-transport/src/transport/remote_control/tests/clients_tests.rs", + "status": "modified" + }, + { + "additions": 20, + "deletions": 11, + "patch_excerpt": "@@ -645,7 +645,9 @@ async fn remote_control_handle_disable_keeps_current_enrollment() {\n remote_control_auth_manager(),\n );\n \n- remote_handle.disable();\n+ remote_handle\n+ .desired_state_tx\n+ .send_replace(RemoteControlDesiredState::Disabled);\n assert!(\n remote_handle.current_enrollment.lock().await.is_some(),\n \"disabled remote control should keep the selected pairing server\"\n@@ -665,7 +667,6 @@ async fn remote_control_handle_reenrolls_after_stale_pairing_enrollment() {\n remote_control_auth_manager_with_home(&codex_home),\n );\n remote_handle.state_db = Some(state_db.clone());\n- remote_handle.disable();\n let stale_enrollment = remote_handle\n .current_enrollment\n .lock()\n@@ -688,9 +689,15 @@ async fn remote_control_handle_reenrolls_after_stale_pairing_enrollment() {\n \"account_id\",\n /*ap...", + "path": "codex-rs/app-server-transport/src/transport/remote_control/tests/pairing_tests.rs", + "status": "modified" + }, + { + "additions": 288, + "deletions": 81, + "patch_excerpt": "@@ -1,5 +1,9 @@\n use super::CurrentRemoteControlEnrollment;\n+use super::RemoteControlEnrollmentSelection;\n use super::RemoteControlPairingPersistenceKey;\n+use super::desired_state::RemoteControlDesiredState;\n+use super::desired_state::acquire_persistence_lock;\n+use super::desired_state::desired_state_from_persisted_enrollment;\n use super::protocol::ClientEnvelope;\n use super::protocol::ClientEvent;\n use super::protocol::ClientId;\n@@ -45,6 +49,7 @@ use std::io::ErrorKind;\n use std::sync::Arc;\n use tokio::net::TcpStream;\n use tokio::sync::Mutex;\n+use tokio::sync::Semaphore;\n use tokio::sync::mpsc;\n use tokio::sync::oneshot;\n use tokio::sync::watch;\n@@ -264,7 +269,9 @@ pub(crate) struct RemoteControlWebsocket {\n state: Arc>,\n server_event_rx: Arc>>,\n used_rx: watch::Receiver,\n- enabled_rx: watch::R...", + "path": "codex-rs/app-server-transport/src/transport/remote_control/websocket.rs", + "status": "modified" + }, + { + "additions": 2, + "deletions": 2, + "patch_excerpt": "@@ -207,8 +207,8 @@ Example with notification opt-out:\n - `plugin/skill/read` — read remote plugin skill markdown on demand by `remoteMarketplaceName`, `remotePluginId`, and `skillName`. This lets clients preview uninstalled remote plugin skills without downloading the plugin bundle.\n - `skills/changed` — notification emitted when watched local skill files change.\n - `app/list` — list available apps.\n-- `remoteControl/enable` — experimental; enable remote control for the current app-server process and return the current remote-control status snapshot. The caller is responsible for persisting the desired setting outside app-server.\n-- `remoteControl/disable` — experimental; disable remote control for the current app-server process and return the current remote-control status snapshot. This does not revoke already enrolled controller devices.\n+- `remoteControl/enable` — experimental; enabl...", + "path": "codex-rs/app-server/README.md", + "status": "modified" + }, + { + "additions": 38, + "deletions": 8, + "patch_excerpt": "@@ -106,10 +106,12 @@ mod transport;\n pub use crate::error_code::INPUT_TOO_LARGE_ERROR_CODE;\n pub use crate::error_code::INVALID_PARAMS_ERROR_CODE;\n pub use crate::transport::AppServerTransport;\n+pub use crate::transport::RemoteControlStartupMode;\n pub use crate::transport::app_server_control_socket_path;\n pub use crate::transport::auth::AppServerWebsocketAuthArgs;\n pub use crate::transport::auth::AppServerWebsocketAuthSettings;\n pub use crate::transport::auth::WebsocketAuthCliMode;\n+pub use crate::transport::take_remote_control_disabled_env;\n \n const LOG_FORMAT_ENV_VAR: &str = \"LOG_FORMAT\";\n const OTEL_SERVICE_NAME: &str = \"codex-app-server\";\n@@ -404,15 +406,15 @@ pub enum PluginStartupTasks {\n #[derive(Debug, Clone, Copy, PartialEq, Eq)]\n pub struct AppServerRuntimeOptions {\n pub plugin_startup_tasks: PluginStartupTasks,\n- pub remote_control_enabled: bool,\n+ pub remote_contro...", + "path": "codex-rs/app-server/src/lib.rs", + "status": "modified" + }, + { + "additions": 9, + "deletions": 3, + "patch_excerpt": "@@ -53,13 +53,14 @@ struct AppServerArgs {\n #[arg(long = \"disable-plugin-startup-tasks-for-tests\", hide = true)]\n disable_plugin_startup_tasks_for_tests: bool,\n \n- /// Enable remote control for this app-server process.\n+ /// Enable remote control for this app-server process without changing persistence.\n #[arg(long = \"remote-control\", hide = true)]\n remote_control: bool,\n }\n \n fn main() -> anyhow::Result<()> {\n- arg0_dispatch_or_else(|arg0_paths: Arg0DispatchPaths| async move {\n+ let remote_control_disabled = codex_app_server::take_remote_control_disabled_env();\n+ arg0_dispatch_or_else(move |arg0_paths: Arg0DispatchPaths| async move {\n let AppServerArgs {\n config_overrides,\n listen,\n@@ -84,7 +85,12 @@ fn main() -> anyhow::Result<()> {\n if disable_plugin_startup_tasks_for_tests {\n runtime_options.plugin_sta...", + "path": "codex-rs/app-server/src/main.rs", + "status": "modified" + }, + { + "additions": 12, + "deletions": 4, + "patch_excerpt": "@@ -940,13 +940,21 @@ impl MessageProcessor {\n .experimental_feature_enablement_set(request_id.clone(), params)\n .await\n }\n- ClientRequest::RemoteControlEnable { .. } => self\n+ ClientRequest::RemoteControlEnable { params, .. } => self\n .remote_control_processor\n- .enable()\n+ .enable(\n+ params.is_some_and(|params| params.ephemeral),\n+ app_server_client_name.as_deref(),\n+ )\n+ .await\n .map(|response| Some(response.into())),\n- ClientRequest::RemoteControlDisable { .. } => self\n+ ClientRequest::RemoteControlDisable { params, .. } => self\n .remote_control_processor\n- .disable()\n+ .disable(\n+ params.is_some_a...", + "path": "codex-rs/app-server/src/message_processor.rs", + "status": "modified" + }, + { + "additions": 36, + "deletions": 7, + "patch_excerpt": "@@ -28,17 +28,38 @@ impl RemoteControlRequestProcessor {\n }\n }\n \n- pub(crate) fn enable(&self) -> Result {\n+ pub(crate) async fn enable(\n+ &self,\n+ ephemeral: bool,\n+ app_server_client_name: Option<&str>,\n+ ) -> Result {\n let handle = self.handle()?;\n- handle\n- .enable()\n- .map(RemoteControlEnableResponse::from)\n- .map_err(map_unavailable)\n+ let status = if ephemeral {\n+ handle.enable_ephemeral().map_err(map_unavailable)?\n+ } else {\n+ handle\n+ .enable(app_server_client_name)\n+ .await\n+ .map_err(map_update_error)?\n+ };\n+ Ok(RemoteControlEnableResponse::from(status))\n }\n \n- pub(crate) fn disable(&self) -> R...", + "path": "codex-rs/app-server/src/request_processors/remote_control_processor.rs", + "status": "modified" + }, + { + "additions": 2, + "deletions": 0, + "patch_excerpt": "@@ -20,6 +20,7 @@ pub(crate) use codex_app_server_transport::OutgoingMessage;\n pub(crate) use codex_app_server_transport::QueuedOutgoingMessage;\n pub(crate) use codex_app_server_transport::RemoteControlHandle;\n pub(crate) use codex_app_server_transport::RemoteControlStartConfig;\n+pub use codex_app_server_transport::RemoteControlStartupMode;\n pub(crate) use codex_app_server_transport::RemoteControlUnavailable;\n pub(crate) use codex_app_server_transport::TransportEvent;\n pub(crate) use codex_app_server_transport::acquire_app_server_startup_lock;\n@@ -31,6 +32,7 @@ pub(crate) use codex_app_server_transport::start_control_socket_acceptor;\n pub(crate) use codex_app_server_transport::start_remote_control;\n pub(crate) use codex_app_server_transport::start_stdio_connection;\n pub(crate) use codex_app_server_transport::start_websocket_acceptor;\n+pub use codex_app_server_transport::take_remote_contr...", + "path": "codex-rs/app-server/src/transport.rs", + "status": "modified" + }, + { + "additions": 23, + "deletions": 0, + "patch_excerpt": "@@ -1,5 +1,6 @@\n use std::collections::VecDeque;\n use std::path::Path;\n+use std::process::ExitStatus;\n use std::process::Stdio;\n use std::sync::atomic::AtomicI64;\n use std::sync::atomic::Ordering;\n@@ -127,6 +128,10 @@ pub const DISABLE_PLUGIN_STARTUP_TASKS_ARG: &str = \"--disable-plugin-startup-tas\n const DISABLE_MANAGED_CONFIG_ENV_VAR: &str = \"CODEX_APP_SERVER_DISABLE_MANAGED_CONFIG\";\n \n impl TestAppServer {\n+ pub async fn wait_for_exit(&mut self) -> std::io::Result {\n+ self.process.wait().await\n+ }\n+\n pub async fn new(codex_home: &Path) -> anyhow::Result {\n Self::new_with_env_and_args(codex_home, &[], &[DISABLE_PLUGIN_STARTUP_TASKS_ARG]).await\n }\n@@ -635,12 +640,30 @@ impl TestAppServer {\n .await\n }\n \n+ /// Send a runtime-only `remoteControl/enable` JSON-RPC request.\n+ pub async fn send_remote_control_ephemeral_enable_...", + "path": "codex-rs/app-server/tests/common/test_app_server.rs", + "status": "modified" + }, + { + "additions": 245, + "deletions": 14, + "patch_excerpt": "@@ -3,6 +3,7 @@ use std::time::Duration;\n use anyhow::Context;\n use anyhow::Result;\n use app_test_support::ChatGptAuthFixture;\n+use app_test_support::DEFAULT_CLIENT_NAME;\n use app_test_support::TestAppServer;\n use app_test_support::to_response;\n use app_test_support::write_chatgpt_auth;\n@@ -24,6 +25,8 @@ use codex_app_server_protocol::RemoteControlPairingStatusResponse;\n use codex_app_server_protocol::RemoteControlStatusReadResponse;\n use codex_app_server_protocol::RequestId;\n use codex_config::types::AuthCredentialsStoreMode;\n+use codex_state::RemoteControlEnrollmentRecord;\n+use codex_state::StateRuntime;\n use pretty_assertions::assert_eq;\n use tempfile::TempDir;\n use tokio::io::AsyncBufReadExt;\n@@ -37,10 +40,92 @@ use tokio::task::JoinHandle;\n use tokio::time::timeout;\n \n const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);\n+const STARTUP_TIMEOUT: Duration = Duration::from_secs(3...", + "path": "codex-rs/app-server/tests/suite/v2/remote_control.rs", + "status": "modified" + }, + { + "additions": 26, + "deletions": 5, + "patch_excerpt": "@@ -517,7 +517,7 @@ struct AppServerCommand {\n #[arg(long = \"stdio\", conflicts_with = \"listen\")]\n stdio: bool,\n \n- /// Enable remote control for this app-server process.\n+ /// Enable remote control for this app-server process without changing persistence.\n #[arg(long = \"remote-control\", hide = true)]\n remote_control: bool,\n \n@@ -919,13 +919,17 @@ fn stage_str(stage: Stage) -> &'static str {\n }\n \n fn main() -> anyhow::Result<()> {\n- arg0_dispatch_or_else(|arg0_paths: Arg0DispatchPaths| async move {\n- cli_main(arg0_paths).await?;\n+ let remote_control_disabled = codex_app_server::take_remote_control_disabled_env();\n+ arg0_dispatch_or_else(move |arg0_paths: Arg0DispatchPaths| async move {\n+ cli_main(arg0_paths, remote_control_disabled).await?;\n Ok(())\n })\n }\n \n-async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {\n+a...", + "path": "codex-rs/cli/src/main.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 1, + "patch_excerpt": "@@ -115,7 +115,7 @@ async fn run_foreground_remote_control(\n socket_path: socket_path.clone(),\n };\n let runtime_options = AppServerRuntimeOptions {\n- remote_control_enabled: true,\n+ remote_control_startup_mode: codex_app_server::RemoteControlStartupMode::EnabledEphemeral,\n install_shutdown_signal_handler: false,\n ..Default::default()\n };", + "path": "codex-rs/cli/src/remote_control_cmd.rs", + "status": "modified" + }, + { + "additions": 2, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,2 @@\n+ALTER TABLE remote_control_enrollments\n+ADD COLUMN remote_control_enabled INTEGER;", + "path": "codex-rs/state/migrations/0037_remote_control_enrollments_enabled.sql", + "status": "added" + }, + { + "additions": 100, + "deletions": 2, + "patch_excerpt": "@@ -11,6 +11,7 @@ pub struct RemoteControlEnrollmentRecord {\n pub server_id: String,\n pub environment_id: String,\n pub server_name: String,\n+ pub remote_control_enabled: Option,\n }\n \n fn remote_control_app_server_client_name_key(app_server_client_name: Option<&str>) -> &str {\n@@ -34,7 +35,8 @@ impl StateRuntime {\n ) -> anyhow::Result> {\n let row = sqlx::query(\n r#\"\n-SELECT websocket_url, account_id, app_server_client_name, server_id, environment_id, server_name\n+SELECT websocket_url, account_id, app_server_client_name, server_id, environment_id, server_name,\n+ remote_control_enabled\n FROM remote_control_enrollments\n WHERE websocket_url = ? AND account_id = ? AND app_server_client_name = ?\n \"#,\n@@ -56,6 +58,7 @@ WHERE websocket_url = ? AND account_id = ? AND app_server_client_name = ?\n ...", + "path": "codex-rs/state/src/runtime/remote_control.rs", + "status": "modified" + } + ], + "linked_issues": [ + "#27445" + ], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "## Why\n\nRemote-control runtime enablement and persisted enrollment preference were represented by separate flags. That made startup rehydration, RPC persistence, and new-enrollment seeding race with one another, and it did not cleanly distinguish runtime-only CLI or daemon starts from durable app-server RPC changes.\n\n## What Changed\n\n- Replace the parallel enablement, seed, and rehydration flags with one transport-owned `RemoteControlDesiredState`.\n- Add nullable enrollment-scoped persistence and preserve existing preferences during enrollment upserts.\n- Rehydrate plain startup only after auth and client scope resolve, without overwriting a concurrent RPC transition.\n- Make ordinary `remoteControl/enable` and `remoteControl/disable` durable while retaining `ephemeral: true` for runtime-only callers.\n- Have the daemon explicitly request ephemeral enablement and regenerate the app-server schemas.\n\n## Verification\n\n- Covered migration and `NULL`/`0`/`1` persistence round trips.\n- Covered plain-start rehydration and runtime-only versus durable enrollment seeding.\n- Covered durable enable, durable disable, and ephemeral enable through app-server RPC.\n- Covered the daemon's exact `{ \"ephemeral\": true }` request payload.\n\nRelated issue: N/A (internal remote-control persistence architecture change).\n", + "labels": [ + "code-reviewed" + ], + "merged_at": "2026-06-12T04:28:53Z", + "number": 27445, + "state": "merged", + "title": "feat(app-server): persist remote-control desired state", + "url": "https://github.com/openai/codex/pull/27445" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/bundles/openai-codex-pr-27475.json b/artifacts/github/bundles/openai-codex-pr-27475.json new file mode 100644 index 000000000..34a02075a --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-27475.json @@ -0,0 +1,756 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "anp-oai", + "committed_at": "2026-06-11T18:12:41Z", + "message": "Remove async_trait from first-party code", + "sha": "9aba4e7c68322efaf4a930336061dc4ddf22eedb", + "url": "https://github.com/openai/codex/commit/9aba4e7c68322efaf4a930336061dc4ddf22eedb" + }, + { + "author": "anp-oai", + "committed_at": "2026-06-11T18:52:42Z", + "message": "Ban first-party async-trait dependencies", + "sha": "4df5f02d73bd57c728ec65880b2b702825256edc", + "url": "https://github.com/openai/codex/commit/4df5f02d73bd57c728ec65880b2b702825256edc" + } + ], + "default_branch": "main", + "docs_refs": [], + "examples_refs": [], + "extracted_flags": [ + "RUSTSEC", + "API", + "TRACE", + "LOCAL_FS", + "CONFIG_TOML_FILE", + "CODEX_PROXY_GIT_SSH_COMMAND_MARKER", + "CUSTOM_CA_ENV_KEYS", + "ENABLE_INTERCEPTED_EXEC_POLICY_SHELL_WRAPPER_PARSING", + "REMOTE_ENVIRONMENT_ID", + "DEFAULT_REMOTE_EXEC_SERVER_CONNECT_TIMEOUT", + "DEFAULT_REMOTE_EXEC_SERVER_INITIALIZE_TIMEOUT", + "LOCAL_ENVIRONMENT_ID", + "CODEX_FS_HELPER_ARG1", + "JSONRPCE", + "STANDARD", + "SKILL", + "SKILL_CONTENTS", + "UTF", + "CODEX_API_KEY_ENV_VAR", + "DEFAULT_MEMORY_CONSOLIDATION_PREFERRED_MODEL", + "URL", + "DEFAULT_MODEL_CACHE_TTL", + "AUDIT_TARGET", + "REASON_NOT_ALLOWED", + "REASON_NOT_ALLOWED_LOCAL", + "LOCK_TIMEOUT" + ], + "files": [ + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -1420,6 +1420,7 @@\n \"rama-utils_0.3.0-alpha.4\": \"{\\\"dependencies\\\":[{\\\"kind\\\":\\\"dev\\\",\\\"name\\\":\\\"ahash\\\",\\\"req\\\":\\\"^0.8\\\"},{\\\"name\\\":\\\"const_format\\\",\\\"req\\\":\\\"^0.2\\\"},{\\\"kind\\\":\\\"dev\\\",\\\"name\\\":\\\"loom\\\",\\\"req\\\":\\\"^0.7\\\",\\\"target\\\":\\\"cfg(loom)\\\"},{\\\"name\\\":\\\"parking_lot\\\",\\\"req\\\":\\\"^0.12\\\"},{\\\"name\\\":\\\"pin-project-lite\\\",\\\"req\\\":\\\"^0.2\\\"},{\\\"kind\\\":\\\"dev\\\",\\\"name\\\":\\\"quickcheck\\\",\\\"req\\\":\\\"^1.0\\\"},{\\\"name\\\":\\\"rama-macros\\\",\\\"req\\\":\\\"^0.3.0-alpha.4\\\"},{\\\"name\\\":\\\"regex\\\",\\\"req\\\":\\\"^1.12\\\"},{\\\"features\\\":[\\\"derive\\\"],\\\"name\\\":\\\"serde\\\",\\\"req\\\":\\\"^1.0\\\"},{\\\"kind\\\":\\\"dev\\\",\\\"name\\\":\\\"serde_json\\\",\\\"req\\\":\\\"^1.0\\\"},{\\\"kind\\\":\\\"dev\\\",\\\"name\\\":\\\"serde_test\\\",\\\"req\\\":\\\"^1\\\"},{\\\"features\\\":[\\\"write\\\",\\\"serde\\\",\\\"const_generics\\\",\\\"const_new\\\"],\\\"name\\\":\\\"smallvec\\\",\\\"req\\\":\\\"^1.15\\\"},{\\\"name\\\":\\\"smol_str\\\",\\\"req\\\":\\\"^0.3\\\"},{\\\"features\\\":[\\\"time\\\",\\\"macros\\\"],\\\"name\\\":\\\"tokio\\\",\\\"req\\\":\\...", + "path": "MODULE.bazel.lock", + "status": "modified" + }, + { + "additions": 9, + "deletions": 31, + "patch_excerpt": "@@ -213,7 +213,7 @@ dependencies = [\n \"lazy_static\",\n \"nom 7.1.3\",\n \"pin-project\",\n- \"rand 0.8.5\",\n+ \"rand 0.8.6\",\n \"rust-embed\",\n \"scrypt\",\n \"sha2 0.10.9\",\n@@ -234,7 +234,7 @@ dependencies = [\n \"hkdf 0.12.4\",\n \"io_tee\",\n \"nom 7.1.3\",\n- \"rand 0.8.5\",\n+ \"rand 0.8.6\",\n \"secrecy\",\n \"sha2 0.10.9\",\n ]\n@@ -786,7 +786,7 @@ dependencies = [\n \"hex\",\n \"http 1.4.0\",\n \"p256\",\n- \"rand 0.8.5\",\n+ \"rand 0.8.6\",\n \"ring\",\n \"sha2 0.10.9\",\n \"time\",\n@@ -1852,7 +1852,6 @@ dependencies = [\n name = \"codex-agent-graph-store\"\n version = \"0.0.0\"\n dependencies = [\n- \"async-trait\",\n \"codex-protocol\",\n \"codex-state\",\n \"pretty_assertions\",\n@@ -1919,7 +1918,6 @@ dependencies = [\n \"anyhow\",\n \"assert_matches\",\n \"async-channel\",\n- \"async-trait\",\n \"base64 0.22.1\",\n \"bytes\",\n \"chrono\",\n@@ -1953,7 +1951,6 @@ version = \"0.0.0\"\n dependencies = [\n \"anyhow\",\n \"app_test_support\",\n- \"async-trait\",\n \"ax...", + "path": "codex-rs/Cargo.lock", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -265,7 +265,6 @@ assert_matches = \"1.5.0\"\n async-channel = \"2.3.1\"\n async-io = \"2.6.0\"\n async-stream = \"0.3.6\"\n-async-trait = \"0.1.89\"\n aws-config = \"1\"\n aws-credential-types = \"1\"\n aws-sigv4 = \"1\"", + "path": "codex-rs/Cargo.toml", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -13,7 +13,6 @@ doctest = false\n workspace = true\n \n [dependencies]\n-async-trait = { workspace = true }\n codex-protocol = { workspace = true }\n codex-state = { workspace = true }\n serde = { workspace = true, features = [\"derive\"] }", + "path": "codex-rs/agent-graph-store/Cargo.toml", + "status": "modified" + }, + { + "additions": 0, + "deletions": 2, + "patch_excerpt": "@@ -1,4 +1,3 @@\n-use async_trait::async_trait;\n use codex_protocol::ThreadId;\n use codex_state::StateRuntime;\n use std::sync::Arc;\n@@ -29,7 +28,6 @@ impl LocalAgentGraphStore {\n }\n }\n \n-#[async_trait]\n impl AgentGraphStore for LocalAgentGraphStore {\n async fn upsert_thread_spawn_edge(\n &self,", + "path": "codex-rs/agent-graph-store/src/local.rs", + "status": "modified" + }, + { + "additions": 8, + "deletions": 10, + "patch_excerpt": "@@ -1,4 +1,3 @@\n-use async_trait::async_trait;\n use codex_protocol::ThreadId;\n \n use crate::AgentGraphStoreResult;\n@@ -8,48 +7,47 @@ use crate::ThreadSpawnEdgeStatus;\n ///\n /// Implementations are expected to return stable ordering for list methods so callers can merge\n /// persisted graph state with live in-memory state without introducing nondeterministic output.\n-#[async_trait]\n pub trait AgentGraphStore: Send + Sync {\n /// Insert or replace the directional parent/child edge for a spawned thread.\n ///\n /// `child_thread_id` has at most one persisted parent. Re-inserting the same child should\n /// update both the parent and status to match the supplied values.\n- async fn upsert_thread_spawn_edge(\n+ fn upsert_thread_spawn_edge(\n &self,\n parent_thread_id: ThreadId,\n child_thread_id: ThreadId,\n status: ThreadSpawnEdgeStatus,\n- ) -> ...", + "path": "codex-rs/agent-graph-store/src/store.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -22,7 +22,6 @@ workspace = true\n \n [dependencies]\n anyhow = { workspace = true }\n-async-trait = { workspace = true }\n base64 = { workspace = true }\n axum = { workspace = true, default-features = false, features = [\n \"http1\",", + "path": "codex-rs/app-server/Cargo.toml", + "status": "modified" + }, + { + "additions": 10, + "deletions": 3, + "patch_excerpt": "@@ -99,7 +99,6 @@ mod tests {\n use crate::extensions::ThreadExtensionDependencies;\n use crate::extensions::guardian_agent_spawner;\n use crate::extensions::thread_extensions;\n- use async_trait::async_trait;\n use codex_arg0::Arg0DispatchPaths;\n use codex_config::CloudConfigBundleLoader;\n use codex_config::LoaderOverrides;\n@@ -245,8 +244,7 @@ mod tests {\n bad_loads: AtomicUsize,\n }\n \n- #[async_trait]\n- impl ThreadConfigLoader for CountingThreadConfigLoader {\n+ impl CountingThreadConfigLoader {\n async fn load(\n &self,\n context: ThreadConfigContext,\n@@ -265,4 +263,13 @@ mod tests {\n Ok(Vec::new())\n }\n }\n+\n+ impl ThreadConfigLoader for CountingThreadConfigLoader {\n+ fn load(\n+ &self,\n+ context: ThreadConfigContext,\n+ ) -> codex_config::ThreadConfigLoade...", + "path": "codex-rs/app-server/src/mcp_refresh.rs", + "status": "modified" + }, + { + "additions": 13, + "deletions": 8, + "patch_excerpt": "@@ -46,7 +46,6 @@ use crate::thread_state::ConnectionCapabilities;\n use crate::thread_state::ThreadStateManager;\n use crate::transport::AppServerTransport;\n use crate::transport::RemoteControlHandle;\n-use async_trait::async_trait;\n use codex_analytics::AnalyticsEventsClient;\n use codex_analytics::AppServerRpcTransport;\n use codex_app_server_protocol::AuthMode as LoginAuthMode;\n@@ -106,13 +105,6 @@ impl ExternalAuthRefreshBridge {\n ExternalAuthRefreshReason::Unauthorized => ChatgptAuthTokensRefreshReason::Unauthorized,\n }\n }\n-}\n-\n-#[async_trait]\n-impl ExternalAuth for ExternalAuthRefreshBridge {\n- fn auth_mode(&self) -> LoginAuthMode {\n- LoginAuthMode::Chatgpt\n- }\n \n async fn refresh(\n &self,\n@@ -163,6 +155,19 @@ impl ExternalAuth for ExternalAuthRefreshBridge {\n }\n }\n \n+impl ExternalAuth for ExternalAuthRefreshBridge {\n+ fn auth_mod...", + "path": "codex-rs/app-server/src/message_processor.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -8,7 +8,6 @@ license.workspace = true\n workspace = true\n \n [dependencies]\n-async-trait.workspace = true\n tokio = { workspace = true, features = [\"macros\", \"rt\", \"rt-multi-thread\", \"time\"] }\n tokio-util.workspace = true", + "path": "codex-rs/async-utils/Cargo.toml", + "status": "modified" + }, + { + "additions": 4, + "deletions": 4, + "patch_excerpt": "@@ -1,4 +1,3 @@\n-use async_trait::async_trait;\n use std::future::Future;\n use tokio_util::sync::CancellationToken;\n \n@@ -7,14 +6,15 @@ pub enum CancelErr {\n Cancelled,\n }\n \n-#[async_trait]\n pub trait OrCancelExt: Sized {\n type Output;\n \n- async fn or_cancel(self, token: &CancellationToken) -> Result;\n+ fn or_cancel(\n+ self,\n+ token: &CancellationToken,\n+ ) -> impl Future> + Send;\n }\n \n-#[async_trait]\n impl OrCancelExt for F\n where\n F: Future + Send,", + "path": "codex-rs/async-utils/src/lib.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -15,7 +15,6 @@ workspace = true\n \n [dependencies]\n anyhow = { workspace = true }\n-async-trait = { workspace = true }\n chrono = { workspace = true, features = [\"serde\"] }\n codex-api = { workspace = true }\n codex-backend-client = { workspace = true }", + "path": "codex-rs/cloud-tasks-client/Cargo.toml", + "status": "modified" + }, + { + "additions": 26, + "deletions": 20, + "patch_excerpt": "@@ -2,8 +2,11 @@ use chrono::DateTime;\n use chrono::Utc;\n use serde::Deserialize;\n use serde::Serialize;\n+use std::future::Future;\n+use std::pin::Pin;\n \n pub type Result = std::result::Result;\n+pub type CloudBackendFuture<'a, T> = Pin> + Send + 'a>>;\n \n #[derive(Debug, thiserror::Error)]\n pub enum CloudTaskError {\n@@ -130,41 +133,44 @@ impl Default for TaskText {\n }\n }\n \n-#[async_trait::async_trait]\n pub trait CloudBackend: Send + Sync {\n- async fn list_tasks(\n- &self,\n- env: Option<&str>,\n+ fn list_tasks<'a>(\n+ &'a self,\n+ env: Option<&'a str>,\n limit: Option,\n- cursor: Option<&str>,\n- ) -> Result;\n- async fn get_task_summary(&self, id: TaskId) -> Result;\n- async fn get_task_diff(&self, id: TaskId) -> Result>;\n+ curso...", + "path": "codex-rs/cloud-tasks-client/src/api.rs", + "status": "modified" + }, + { + "additions": 46, + "deletions": 36, + "patch_excerpt": "@@ -2,6 +2,7 @@ use crate::ApplyOutcome;\n use crate::ApplyStatus;\n use crate::AttemptStatus;\n use crate::CloudBackend;\n+use crate::CloudBackendFuture;\n use crate::CloudTaskError;\n use crate::DiffSummary;\n use crate::Result;\n@@ -61,68 +62,77 @@ impl HttpClient {\n }\n }\n \n-#[async_trait::async_trait]\n impl CloudBackend for HttpClient {\n- async fn list_tasks(\n- &self,\n- env: Option<&str>,\n+ fn list_tasks<'a>(\n+ &'a self,\n+ env: Option<&'a str>,\n limit: Option,\n- cursor: Option<&str>,\n- ) -> Result {\n- self.tasks_api().list(env, limit, cursor).await\n+ cursor: Option<&'a str>,\n+ ) -> CloudBackendFuture<'a, TaskListPage> {\n+ Box::pin(async move { self.tasks_api().list(env, limit, cursor).await })\n }\n \n- async fn get_task_summary(&self, id: TaskId) -> Result {\n- self.task...", + "path": "codex-rs/cloud-tasks-client/src/http.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -4,6 +4,7 @@ pub use api::ApplyOutcome;\n pub use api::ApplyStatus;\n pub use api::AttemptStatus;\n pub use api::CloudBackend;\n+pub use api::CloudBackendFuture;\n pub use api::CloudTaskError;\n pub use api::CreatedTask;\n pub use api::DiffSummary;", + "path": "codex-rs/cloud-tasks-client/src/lib.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -15,7 +15,6 @@ doctest = false\n workspace = true\n \n [dependencies]\n-async-trait = { workspace = true }\n chrono = { workspace = true }\n codex-cloud-tasks-client = { workspace = true }\n diffy = { workspace = true }", + "path": "codex-rs/cloud-tasks-mock-client/Cargo.toml", + "status": "modified" + }, + { + "additions": 66, + "deletions": 2, + "patch_excerpt": "@@ -3,6 +3,7 @@ use codex_cloud_tasks_client::ApplyOutcome;\n use codex_cloud_tasks_client::ApplyStatus;\n use codex_cloud_tasks_client::AttemptStatus;\n use codex_cloud_tasks_client::CloudBackend;\n+use codex_cloud_tasks_client::CloudBackendFuture;\n use codex_cloud_tasks_client::CloudTaskError;\n use codex_cloud_tasks_client::CreatedTask;\n use codex_cloud_tasks_client::DiffSummary;\n@@ -17,8 +18,7 @@ use codex_cloud_tasks_client::TurnAttempt;\n #[derive(Clone, Default)]\n pub struct MockClient;\n \n-#[async_trait::async_trait]\n-impl CloudBackend for MockClient {\n+impl MockClient {\n async fn list_tasks(\n &self,\n _env: Option<&str>,\n@@ -160,6 +160,70 @@ impl CloudBackend for MockClient {\n }\n }\n \n+impl CloudBackend for MockClient {\n+ fn list_tasks<'a>(\n+ &'a self,\n+ env: Option<&'a str>,\n+ limit: Option,\n+ cursor: Option<&'a str>,\n+ ) ->...", + "path": "codex-rs/cloud-tasks-mock-client/src/mock.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 3, + "patch_excerpt": "@@ -39,8 +39,5 @@ tracing = { workspace = true, features = [\"log\"] }\n tracing-subscriber = { workspace = true, features = [\"env-filter\"] }\n unicode-width = { workspace = true }\n \n-[dependencies.async-trait]\n-workspace = true\n-\n [dev-dependencies]\n pretty_assertions = { workspace = true }", + "path": "codex-rs/cloud-tasks/Cargo.toml", + "status": "modified" + }, + { + "additions": 67, + "deletions": 45, + "patch_excerpt": "@@ -354,21 +354,21 @@ pub enum AppEvent {\n mod tests {\n use super::*;\n use chrono::Utc;\n+ use codex_cloud_tasks_client::CloudBackendFuture;\n use codex_cloud_tasks_client::CloudTaskError;\n \n struct FakeBackend {\n // maps env key to titles\n by_env: std::collections::HashMap, Vec<&'static str>>,\n }\n \n- #[async_trait::async_trait]\n- impl codex_cloud_tasks_client::CloudBackend for FakeBackend {\n+ impl FakeBackend {\n async fn list_tasks(\n &self,\n env: Option<&str>,\n limit: Option,\n cursor: Option<&str>,\n- ) -> codex_cloud_tasks_client::Result {\n+ ) -> Result {\n let key = env.map(str::to_string);\n let titles = self\n .by_env\n@...", + "path": "codex-rs/cloud-tasks/src/app.rs", + "status": "modified" + }, + { + "additions": 9, + "deletions": 6, + "patch_excerpt": "@@ -106,16 +106,20 @@ async fn init_backend(user_agent_suffix: &str) -> anyhow::Result\n })\n }\n \n-#[async_trait::async_trait]\n trait GitInfoProvider {\n- async fn default_branch_name(&self, path: &std::path::Path) -> Option;\n-\n- async fn current_branch_name(&self, path: &std::path::Path) -> Option;\n+ fn default_branch_name(\n+ &self,\n+ path: &std::path::Path,\n+ ) -> impl std::future::Future> + Send;\n+\n+ fn current_branch_name(\n+ &self,\n+ path: &std::path::Path,\n+ ) -> impl std::future::Future> + Send;\n }\n \n struct RealGitInfo;\n \n-#[async_trait::async_trait]\n impl GitInfoProvider for RealGitInfo {\n async fn default_branch_name(&self, path: &std::path::Path) -> Option {\n default_branch_name(path).await\n@@ -2156,7 +2160,6 @@ mod tests {\n ...", + "path": "codex-rs/cloud-tasks/src/lib.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -6,7 +6,6 @@ license.workspace = true\n \n [dependencies]\n async-channel = { workspace = true }\n-async-trait = { workspace = true }\n base64 = { workspace = true }\n bytes = { workspace = true }\n chrono = { workspace = true }", + "path": "codex-rs/codex-api/Cargo.toml", + "status": "modified" + }, + { + "additions": 11, + "deletions": 6, + "patch_excerpt": "@@ -1,7 +1,8 @@\n-use async_trait::async_trait;\n use codex_client::Request;\n use codex_client::TransportError;\n use http::HeaderMap;\n+use std::future::Future;\n+use std::pin::Pin;\n use std::sync::Arc;\n \n /// Error returned while applying authentication to an outbound request.\n@@ -26,7 +27,6 @@ impl From for TransportError {\n ///\n /// Header-only providers can implement `add_auth_headers`; providers that sign\n /// complete requests can override `apply_auth`.\n-#[async_trait]\n pub trait AuthProvider: Send + Sync {\n /// Adds any auth headers that are available without request body access.\n ///\n@@ -52,13 +52,18 @@ pub trait AuthProvider: Send + Sync {\n ///\n /// Callers must always use the returned request as authoritative.\n /// If this returns [`AuthError`], the request should not be sent.\n- async fn apply_auth(&self, request: Request) -> Result Result {\n Err(TransportError::Build(\"execute should not run\".to_string()))", + "path": "codex-rs/codex-api/src/endpoint/compact.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 2, + "patch_excerpt": "@@ -80,7 +80,6 @@ mod tests {\n use crate::images::ImageQuality;\n use crate::images::ImageUrl;\n use crate::provider::RetryConfig;\n- use async_trait::async_trait;\n use codex_client::Request;\n use codex_client::RequestBody;\n use codex_client::Response;\n@@ -114,7 +113,6 @@ mod tests {\n }\n }\n \n- #[async_trait]\n impl HttpTransport for CapturingTransport {\n async fn execute(&self, req: Request) -> Result {\n *self.last_request.lock().expect(\"lock request store\") = Some(req);", + "path": "codex-rs/codex-api/src/endpoint/images.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 3, + "patch_excerpt": "@@ -71,7 +71,6 @@ mod tests {\n use crate::common::RawMemory;\n use crate::common::RawMemoryMetadata;\n use crate::provider::RetryConfig;\n- use async_trait::async_trait;\n use codex_client::Request;\n use codex_client::RequestBody;\n use codex_client::Response;\n@@ -89,7 +88,6 @@ mod tests {\n #[derive(Clone, Default)]\n struct DummyTransport;\n \n- #[async_trait]\n impl HttpTransport for DummyTransport {\n async fn execute(&self, _req: Request) -> Result {\n Err(TransportError::Build(\"execute should not run\".to_string()))\n@@ -122,7 +120,6 @@ mod tests {\n }\n }\n \n- #[async_trait]\n impl HttpTransport for CapturingTransport {\n async fn execute(&self, req: Request) -> Result {\n *self.last_request.lock().expect(\"lock request store\") = Some(req);", + "path": "codex-rs/codex-api/src/endpoint/memories.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 2, + "patch_excerpt": "@@ -78,7 +78,6 @@ mod tests {\n use super::*;\n use crate::auth::AuthProvider;\n use crate::provider::RetryConfig;\n- use async_trait::async_trait;\n use codex_client::Request;\n use codex_client::Response;\n use codex_client::StreamResponse;\n@@ -108,7 +107,6 @@ mod tests {\n }\n }\n \n- #[async_trait]\n impl HttpTransport for CapturingTransport {\n async fn execute(&self, req: Request) -> Result {\n *self.last_request.lock().unwrap() = Some(req);", + "path": "codex-rs/codex-api/src/endpoint/models.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 2, + "patch_excerpt": "@@ -226,7 +226,6 @@ mod tests {\n use crate::endpoint::realtime_websocket::RealtimeOutputModality;\n use crate::endpoint::realtime_websocket::RealtimeSessionMode;\n use crate::provider::RetryConfig;\n- use async_trait::async_trait;\n use codex_client::Request;\n use codex_client::Response;\n use codex_client::StreamResponse;\n@@ -265,7 +264,6 @@ mod tests {\n }\n }\n \n- #[async_trait]\n impl HttpTransport for CapturingTransport {\n async fn execute(&self, req: Request) -> Result {\n *self.last_request.lock().unwrap() = Some(req);", + "path": "codex-rs/codex-api/src/endpoint/realtime_call.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 2, + "patch_excerpt": "@@ -64,7 +64,6 @@ mod tests {\n use crate::search::SearchInput;\n use crate::search::SearchQuery;\n use crate::search::SearchSettings;\n- use async_trait::async_trait;\n use codex_client::Request;\n use codex_client::RequestBody;\n use codex_client::Response;\n@@ -100,7 +99,6 @@ mod tests {\n }\n }\n \n- #[async_trait]\n impl HttpTransport for CapturingTransport {\n async fn execute(&self, req: Request) -> Result {\n *self.last_request.lock().expect(\"lock request store\") = Some(req);", + "path": "codex-rs/codex-api/src/endpoint/search.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -21,6 +21,7 @@ pub use crate::api_bridge::map_api_error;\n pub use crate::auth::AuthError;\n pub use crate::auth::AuthHeaderTelemetry;\n pub use crate::auth::AuthProvider;\n+pub use crate::auth::AuthProviderFuture;\n pub use crate::auth::SharedAuthProvider;\n pub use crate::auth::auth_header_telemetry;\n pub use crate::common::CompactionInput;", + "path": "codex-rs/codex-api/src/lib.rs", + "status": "modified" + }, + { + "additions": 8, + "deletions": 8, + "patch_excerpt": "@@ -3,7 +3,6 @@ use std::sync::Mutex;\n use std::time::Duration;\n \n use anyhow::Result;\n-use async_trait::async_trait;\n use bytes::Bytes;\n use codex_api::ApiError;\n use codex_api::AuthError;\n@@ -71,7 +70,6 @@ impl RecordingTransport {\n }\n }\n \n-#[async_trait]\n impl HttpTransport for RecordingTransport {\n async fn execute(&self, _req: Request) -> Result {\n Err(TransportError::Build(\"execute should not run\".to_string()))\n@@ -195,11 +193,6 @@ impl FailsOnceAuth {\n .lock()\n .unwrap_or_else(|err| panic!(\"mutex poisoned: {err}\"))\n }\n-}\n-\n-#[async_trait]\n-impl AuthProvider for FailsOnceAuth {\n- fn add_auth_headers(&self, _headers: &mut HeaderMap) {}\n \n async fn apply_auth(&self, request: Request) -> Result {\n let mut attempts = self\n@@ -219,7 +212,14 @@ impl AuthProvider for FailsOnceAuth {\n ...", + "path": "codex-rs/codex-api/tests/clients.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 2, + "patch_excerpt": "@@ -2,7 +2,6 @@ use std::sync::Arc;\n use std::time::Duration;\n \n use anyhow::Result;\n-use async_trait::async_trait;\n use bytes::Bytes;\n use codex_api::AuthProvider;\n use codex_api::Compression;\n@@ -32,7 +31,6 @@ impl FixtureSseTransport {\n }\n }\n \n-#[async_trait]\n impl HttpTransport for FixtureSseTransport {\n async fn execute(&self, _req: Request) -> Result {\n Err(TransportError::Build(\"execute should not run\".to_string()))", + "path": "codex-rs/codex-api/tests/sse_end_to_end.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -5,7 +5,6 @@ name = \"codex-client\"\n version.workspace = true\n \n [dependencies]\n-async-trait = { workspace = true }\n bytes = { workspace = true }\n eventsource-stream = { workspace = true }\n futures = { workspace = true }", + "path": "codex-rs/codex-client/Cargo.toml", + "status": "modified" + }, + { + "additions": 8, + "deletions": 5, + "patch_excerpt": "@@ -4,7 +4,6 @@ use crate::error::TransportError;\n use crate::request::Request;\n use crate::request::RequestBody;\n use crate::request::Response;\n-use async_trait::async_trait;\n use bytes::Bytes;\n use futures::StreamExt;\n use futures::stream::BoxStream;\n@@ -23,10 +22,15 @@ pub struct StreamResponse {\n pub bytes: ByteStream,\n }\n \n-#[async_trait]\n pub trait HttpTransport: Send + Sync {\n- async fn execute(&self, req: Request) -> Result;\n- async fn stream(&self, req: Request) -> Result;\n+ fn execute(\n+ &self,\n+ req: Request,\n+ ) -> impl std::future::Future> + Send;\n+ fn stream(\n+ &self,\n+ req: Request,\n+ ) -> impl std::future::Future> + Send;\n }\n \n #[derive(Clone, Debug)]\n@@ -86,7 +90,6 @@ fn reque...", + "path": "codex-rs/codex-client/src/transport.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -13,7 +13,6 @@ workspace = true\n \n [dependencies]\n anyhow = { workspace = true }\n-async-trait = { workspace = true }\n base64 = { workspace = true }\n codex-app-server-protocol = { workspace = true }\n codex-execpolicy = { workspace = true }", + "path": "codex-rs/config/Cargo.toml", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -150,6 +150,7 @@ pub use thread_config::ThreadConfigContext;\n pub use thread_config::ThreadConfigLoadError;\n pub use thread_config::ThreadConfigLoadErrorCode;\n pub use thread_config::ThreadConfigLoader;\n+pub use thread_config::ThreadConfigLoaderFuture;\n pub use thread_config::ThreadConfigSource;\n pub use thread_config::UserThreadConfig;\n pub use toml::Value as TomlValue;", + "path": "codex-rs/config/src/lib.rs", + "status": "modified" + }, + { + "additions": 57, + "deletions": 55, + "patch_excerpt": "@@ -1,9 +1,8 @@\n use super::*;\n-use async_trait::async_trait;\n use codex_file_system::CopyOptions;\n use codex_file_system::CreateDirectoryOptions;\n+use codex_file_system::ExecutorFileSystemFuture;\n use codex_file_system::FileMetadata;\n-use codex_file_system::FileSystemResult;\n use codex_file_system::FileSystemSandboxContext;\n use codex_file_system::ReadDirectoryEntry;\n use codex_file_system::RemoveOptions;\n@@ -13,78 +12,81 @@ use tempfile::tempdir;\n \n struct TestFileSystem;\n \n-#[async_trait]\n impl ExecutorFileSystem for TestFileSystem {\n- async fn canonicalize(\n- &self,\n- path: &PathUri,\n- _sandbox: Option<&FileSystemSandboxContext>,\n- ) -> FileSystemResult {\n- let path = path.to_abs_path()?;\n- let canonicalized = path.canonicalize()?;\n- PathUri::from_abs_path(&canonicalized)\n+ fn canonicalize<'a>(\n+ &'a self,\n+ pa...", + "path": "codex-rs/config/src/loader/tests.rs", + "status": "modified" + }, + { + "additions": 23, + "deletions": 20, + "patch_excerpt": "@@ -1,7 +1,8 @@\n use std::collections::BTreeMap;\n use std::collections::HashMap;\n+use std::future::Future;\n+use std::pin::Pin;\n \n-use async_trait::async_trait;\n use codex_app_server_protocol::ConfigLayerSource;\n use codex_model_provider_info::ModelProviderInfo;\n use codex_utils_absolute_path::AbsolutePathBuf;\n@@ -86,32 +87,36 @@ impl ThreadConfigLoadError {\n /// return typed payloads without applying precedence or merge rules. Callers\n /// are responsible for resolving the returned sources into the effective\n /// runtime config.\n-#[async_trait]\n pub trait ThreadConfigLoader: Send + Sync {\n /// Load source-specific typed config.\n ///\n /// Implementations should keep this method focused on fetching and parsing\n /// their owned sources. Most callers should use [`Self::load_config_layers`]\n /// so precedence and merging continue through the ordinary config layer\n /// ...", + "path": "codex-rs/config/src/thread_config.rs", + "status": "modified" + }, + { + "additions": 31, + "deletions": 6, + "patch_excerpt": "@@ -3,7 +3,6 @@ use std::collections::HashMap;\n use std::num::NonZeroU64;\n use std::time::Duration;\n \n-use async_trait::async_trait;\n use codex_model_provider_info::ModelProviderInfo;\n use codex_model_provider_info::WireApi;\n use codex_protocol::config_types::ModelProviderAuthInfo;\n@@ -14,6 +13,7 @@ use super::ThreadConfigContext;\n use super::ThreadConfigLoadError;\n use super::ThreadConfigLoadErrorCode;\n use super::ThreadConfigLoader;\n+use super::ThreadConfigLoaderFuture;\n use super::ThreadConfigSource;\n use super::UserThreadConfig;\n use proto::thread_config_loader_client::ThreadConfigLoaderClient;\n@@ -49,10 +49,7 @@ impl RemoteThreadConfigLoader {\n )\n })\n }\n-}\n \n-#[async_trait]\n-impl ThreadConfigLoader for RemoteThreadConfigLoader {\n async fn load(\n &self,\n context: ThreadConfigContext,\n@@ -73,6 +70,15 @@ impl ThreadConfigLoader for Re...", + "path": "codex-rs/config/src/thread_config/remote.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -19,7 +19,6 @@ workspace = true\n anyhow = { workspace = true }\n arc-swap = { workspace = true }\n async-channel = { workspace = true }\n-async-trait = { workspace = true }\n base64 = { workspace = true }\n bm25 = { workspace = true }\n chrono = { workspace = true, features = [\"serde\"] }", + "path": "codex-rs/core/Cargo.toml", + "status": "modified" + }, + { + "additions": 81, + "deletions": 3, + "patch_excerpt": "@@ -1,12 +1,12 @@\n use super::*;\n use crate::config::ConfigBuilder;\n-use async_trait::async_trait;\n use codex_config::ConfigLayerEntry;\n use codex_config::ConfigLayerStack;\n use codex_config::ConfigRequirements;\n use codex_config::ConfigRequirementsToml;\n use codex_exec_server::CopyOptions;\n use codex_exec_server::CreateDirectoryOptions;\n+use codex_exec_server::ExecutorFileSystemFuture;\n use codex_exec_server::FileMetadata;\n use codex_exec_server::FileSystemSandboxContext;\n use codex_exec_server::LOCAL_FS;\n@@ -39,8 +39,7 @@ struct FailingFileSystem {\n failure: InjectedFailure,\n }\n \n-#[async_trait]\n-impl ExecutorFileSystem for FailingFileSystem {\n+impl FailingFileSystem {\n async fn canonicalize(\n &self,\n _path: &PathUri,\n@@ -121,6 +120,85 @@ impl ExecutorFileSystem for FailingFileSystem {\n }\n }\n \n+impl ExecutorFileSystem for FailingFileSystem {\n+ fn canonica...", + "path": "codex-rs/core/src/agents_md_tests.rs", + "status": "modified" + }, + { + "additions": 5, + "deletions": 6, + "patch_excerpt": "@@ -1,8 +1,8 @@\n-use async_trait::async_trait;\n use codex_config::NetworkConstraints;\n use codex_execpolicy::Policy;\n use codex_network_proxy::BlockedRequestObserver;\n use codex_network_proxy::ConfigReloader;\n+use codex_network_proxy::ConfigReloaderFuture;\n use codex_network_proxy::ConfigState;\n use codex_network_proxy::NetworkDecision;\n use codex_network_proxy::NetworkPolicyDecider;\n@@ -58,14 +58,13 @@ impl StaticNetworkProxyReloader {\n }\n }\n \n-#[async_trait]\n impl ConfigReloader for StaticNetworkProxyReloader {\n- async fn maybe_reload(&self) -> anyhow::Result> {\n- Ok(None)\n+ fn maybe_reload(&self) -> ConfigReloaderFuture<'_, Option> {\n+ Box::pin(async { Ok(None) })\n }\n \n- async fn reload_now(&self) -> anyhow::Result {\n- Ok(self.state.clone())\n+ fn reload_now(&self) -> ConfigReloaderFuture<'_, ConfigS...", + "path": "codex-rs/core/src/config/network_proxy_spec.rs", + "status": "modified" + }, + { + "additions": 15, + "deletions": 8, + "patch_excerpt": "@@ -7,7 +7,6 @@ use crate::exec_policy::format_exec_policy_error_with_source;\n use crate::exec_policy::load_exec_policy;\n use anyhow::Context;\n use anyhow::Result;\n-use async_trait::async_trait;\n use codex_app_server_protocol::ConfigLayerSource;\n use codex_config::CONFIG_TOML_FILE;\n use codex_config::ConfigLayerStack;\n@@ -23,6 +22,7 @@ use codex_config::permissions_toml::PermissionsToml;\n use codex_config::permissions_toml::overlay_network_domain_permissions;\n use codex_exec_server::LOCAL_FS;\n use codex_network_proxy::ConfigReloader;\n+use codex_network_proxy::ConfigReloaderFuture;\n use codex_network_proxy::ConfigState;\n use codex_network_proxy::NetworkMode;\n use codex_network_proxy::NetworkProxyConfig;\n@@ -361,13 +361,6 @@ impl MtimeConfigReloader {\n }\n })\n }\n-}\n-\n-#[async_trait]\n-impl ConfigReloader for MtimeConfigReloader {\n- fn source_label(&self) -> String ...", + "path": "codex-rs/core/src/network_proxy_loader.rs", + "status": "modified" + }, + { + "additions": 5, + "deletions": 5, + "patch_excerpt": "@@ -10,6 +10,7 @@ use crate::tools::sandboxing::managed_network_for_sandbox_permissions;\n use codex_network_proxy::CODEX_PROXY_GIT_SSH_COMMAND_MARKER;\n use codex_network_proxy::CUSTOM_CA_ENV_KEYS;\n use codex_network_proxy::ConfigReloader;\n+use codex_network_proxy::ConfigReloaderFuture;\n use codex_network_proxy::ConfigState;\n use codex_network_proxy::NetworkProxy;\n use codex_network_proxy::NetworkProxyConfig;\n@@ -35,18 +36,17 @@ use tokio::sync::watch;\n \n struct StaticReloader;\n \n-#[async_trait::async_trait]\n impl ConfigReloader for StaticReloader {\n fn source_label(&self) -> String {\n \"test config state\".to_string()\n }\n \n- async fn maybe_reload(&self) -> anyhow::Result> {\n- Ok(None)\n+ fn maybe_reload(&self) -> ConfigReloaderFuture<'_, Option> {\n+ Box::pin(async { Ok(None) })\n }\n \n- async fn reload_now(&self) -> a...", + "path": "codex-rs/core/src/tools/runtimes/mod_tests.rs", + "status": "modified" + }, + { + "additions": 46, + "deletions": 6, + "patch_excerpt": "@@ -56,12 +56,14 @@ use codex_shell_escalation::EscalationDecision;\n use codex_shell_escalation::EscalationExecution;\n use codex_shell_escalation::EscalationPermissions;\n use codex_shell_escalation::EscalationPolicy;\n+use codex_shell_escalation::EscalationPolicyFuture;\n use codex_shell_escalation::EscalationSession;\n use codex_shell_escalation::ExecParams;\n use codex_shell_escalation::ExecResult;\n use codex_shell_escalation::PreparedExec;\n use codex_shell_escalation::ResolvedPermissionProfile;\n use codex_shell_escalation::ShellCommandExecutor;\n+use codex_shell_escalation::ShellCommandExecutorFuture;\n use codex_shell_escalation::Stopwatch;\n use codex_utils_absolute_path::AbsolutePathBuf;\n use std::collections::HashMap;\n@@ -597,8 +599,7 @@ impl CoreShellActionProvider {\n // execve interception.\n const ENABLE_INTERCEPTED_EXEC_POLICY_SHELL_WRAPPER_PARSING: bool = false;\n \n-#[async_trait::asy...", + "path": "codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -38,7 +38,6 @@ use codex_shell_escalation::EscalationExecution;\n use codex_shell_escalation::EscalationPermissions;\n use codex_shell_escalation::ExecResult;\n use codex_shell_escalation::ResolvedPermissionProfile;\n-use codex_shell_escalation::ShellCommandExecutor;\n use codex_utils_absolute_path::AbsolutePathBuf;\n use pretty_assertions::assert_eq;\n use serde_json::Value;", + "path": "codex-rs/core/src/tools/runtimes/shell/unix_escalation_tests.rs", + "status": "modified" + }, + { + "additions": 35, + "deletions": 23, + "patch_excerpt": "@@ -10,10 +10,9 @@ use crate::session::turn_context::TurnContext;\n use crate::tools::context::ExecCommandToolOutput;\n use crate::unified_exec::WriteStdinRequest;\n use crate::unified_exec::process::OutputHandles;\n-use async_trait::async_trait;\n use codex_exec_server::ExecProcess;\n use codex_exec_server::ExecProcessEventReceiver;\n-use codex_exec_server::ExecServerError;\n+use codex_exec_server::ExecProcessFuture;\n use codex_exec_server::ProcessId;\n use codex_exec_server::ProcessSignal;\n use codex_exec_server::ReadResponse;\n@@ -218,7 +217,31 @@ struct BlockingTerminateExecProcess {\n wake_tx: watch::Sender,\n }\n \n-#[async_trait]\n+impl BlockingTerminateExecProcess {\n+ async fn read(&self) -> Result {\n+ Ok(ReadResponse {\n+ chunks: Vec::new(),\n+ next_seq: 1,\n+ exited: false,\n+ exit_cod...", + "path": "codex-rs/core/src/unified_exec/mod_tests.rs", + "status": "modified" + }, + { + "additions": 35, + "deletions": 26, + "patch_excerpt": "@@ -1,8 +1,8 @@\n use super::process::UnifiedExecProcess;\n use crate::unified_exec::UnifiedExecError;\n-use async_trait::async_trait;\n use codex_exec_server::ExecProcess;\n use codex_exec_server::ExecProcessEventReceiver;\n+use codex_exec_server::ExecProcessFuture;\n use codex_exec_server::ExecServerError;\n use codex_exec_server::ProcessId;\n use codex_exec_server::ProcessSignal;\n@@ -26,7 +26,31 @@ struct MockExecProcess {\n wake_tx: watch::Sender,\n }\n \n-#[async_trait]\n+impl MockExecProcess {\n+ async fn read(&self) -> Result {\n+ Ok(self\n+ .read_responses\n+ .lock()\n+ .await\n+ .pop_front()\n+ .unwrap_or(ReadResponse {\n+ chunks: Vec::new(),\n+ next_seq: 1,\n+ exited: false,\n+ exit_code: None,\n+ closed: false,\n+ ...", + "path": "codex-rs/core/src/unified_exec/process_tests.rs", + "status": "modified" + }, + { + "additions": 10, + "deletions": 0, + "patch_excerpt": "@@ -221,6 +221,16 @@ deny = [\n # Wrapper crates can optionally be specified to allow the crate when it\n # is a direct dependency of the otherwise banned crate\n #{ crate = \"ansi_term@0.11.0\", wrappers = [\"this-crate-directly-depends-on-ansi_term\"] },\n+ # Removing async-trait materially improves debug build times:\n+ # https://github.com/openai/codex/pull/27304\n+ { crate = \"async-trait\", wrappers = [\n+ \"hickory-proto\",\n+ \"opentelemetry-http\",\n+ \"pagable\",\n+ \"rmcp\",\n+ \"tonic\",\n+ \"zbus\",\n+ ], reason = \"first-party traits must use native async trait methods with explicit Send bounds\" },\n ]\n \n # List of features to allow/deny", + "path": "codex-rs/deny.toml", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -12,7 +12,6 @@ workspace = true\n \n [dependencies]\n arc-swap = { workspace = true }\n-async-trait = { workspace = true }\n axum = { workspace = true, features = [\"http1\", \"tokio\", \"ws\"] }\n base64 = { workspace = true }\n bytes = { workspace = true }", + "path": "codex-rs/exec-server/Cargo.toml", + "status": "modified" + }, + { + "additions": 8, + "deletions": 6, + "patch_excerpt": "@@ -1,4 +1,5 @@\n-use async_trait::async_trait;\n+use std::future::Future;\n+use std::pin::Pin;\n \n use crate::Environment;\n use crate::ExecServerError;\n@@ -13,12 +14,14 @@ use crate::environment::REMOTE_ENVIRONMENT_ID;\n /// selection. Providers should only return provider-owned remote environments;\n /// `include_local` controls whether `EnvironmentManager` should add the local\n /// environment to the snapshot.\n-#[async_trait]\n pub trait EnvironmentProvider: Send + Sync {\n /// Returns the provider-owned environment startup snapshot.\n- async fn snapshot(&self) -> Result;\n+ fn snapshot(&self) -> EnvironmentProviderFuture<'_>;\n }\n \n+pub type EnvironmentProviderFuture<'a> =\n+ Pin> + Send + 'a>>;\n+\n #[derive(Clone, Debug)]\n pub struct EnvironmentProviderSnapshot ...", + "path": "codex-rs/exec-server/src/environment_provider.rs", + "status": "modified" + }, + { + "additions": 7, + "deletions": 4, + "patch_excerpt": "@@ -4,13 +4,13 @@ use std::path::Path;\n use std::path::PathBuf;\n use std::time::Duration;\n \n-use async_trait::async_trait;\n use serde::Deserialize;\n use tokio_tungstenite::tungstenite::client::IntoClientRequest;\n \n use crate::DefaultEnvironmentProvider;\n use crate::Environment;\n use crate::EnvironmentProvider;\n+use crate::EnvironmentProviderFuture;\n use crate::ExecServerError;\n use crate::client_api::DEFAULT_REMOTE_EXEC_SERVER_CONNECT_TIMEOUT;\n use crate::client_api::DEFAULT_REMOTE_EXEC_SERVER_INITIALIZE_TIMEOUT;\n@@ -92,10 +92,7 @@ impl TomlEnvironmentProvider {\n environments: parsed_environments,\n })\n }\n-}\n \n-#[async_trait]\n-impl EnvironmentProvider for TomlEnvironmentProvider {\n async fn snapshot(&self) -> Result {\n let mut environments = Vec::with_capacity(self.environments.len());\n for (id, tran...", + "path": "codex-rs/exec-server/src/environment_toml.rs", + "status": "modified" + }, + { + "additions": 4, + "deletions": 0, + "patch_excerpt": "@@ -33,6 +33,7 @@ pub use client_api::RemoteExecServerConnectArgs;\n pub use codex_file_system::CopyOptions;\n pub use codex_file_system::CreateDirectoryOptions;\n pub use codex_file_system::ExecutorFileSystem;\n+pub use codex_file_system::ExecutorFileSystemFuture;\n pub use codex_file_system::FileMetadata;\n pub use codex_file_system::FileSystemResult;\n pub use codex_file_system::FileSystemSandboxContext;\n@@ -45,14 +46,17 @@ pub use environment::LOCAL_ENVIRONMENT_ID;\n pub use environment::REMOTE_ENVIRONMENT_ID;\n pub use environment_provider::DefaultEnvironmentProvider;\n pub use environment_provider::EnvironmentProvider;\n+pub use environment_provider::EnvironmentProviderFuture;\n pub use fs_helper::CODEX_FS_HELPER_ARG1;\n pub use fs_helper_main::main as run_fs_helper_main;\n pub use local_file_system::LOCAL_FS;\n pub use local_file_system::LocalFileSystem;\n pub use process::ExecBackend;\n+pub use p...", + "path": "codex-rs/exec-server/src/lib.rs", + "status": "modified" + }, + { + "additions": 243, + "deletions": 7, + "patch_excerpt": "@@ -1,4 +1,3 @@\n-use async_trait::async_trait;\n use codex_utils_absolute_path::AbsolutePathBuf;\n use codex_utils_path_uri::PathUri;\n use std::path::Path;\n@@ -13,6 +12,7 @@ use crate::CopyOptions;\n use crate::CreateDirectoryOptions;\n use crate::ExecServerRuntimePaths;\n use crate::ExecutorFileSystem;\n+use crate::ExecutorFileSystemFuture;\n use crate::FileMetadata;\n use crate::FileSystemResult;\n use crate::FileSystemSandboxContext;\n@@ -78,8 +78,7 @@ impl LocalFileSystem {\n }\n }\n \n-#[async_trait]\n-impl ExecutorFileSystem for LocalFileSystem {\n+impl LocalFileSystem {\n async fn canonicalize(\n &self,\n path: &PathUri,\n@@ -160,8 +159,86 @@ impl ExecutorFileSystem for LocalFileSystem {\n }\n }\n \n-#[async_trait]\n-impl ExecutorFileSystem for UnsandboxedFileSystem {\n+impl ExecutorFileSystem for LocalFileSystem {\n+ fn canonicalize<'a>(\n+ &'a self,\n+ path: &'a ...", + "path": "codex-rs/exec-server/src/local_file_system.rs", + "status": "modified" + }, + { + "additions": 43, + "deletions": 15, + "patch_excerpt": "@@ -4,7 +4,6 @@ use std::collections::hash_map::Entry;\n use std::sync::Arc;\n use std::time::Duration;\n \n-use async_trait::async_trait;\n use codex_app_server_protocol::JSONRPCErrorError;\n use codex_protocol::config_types::EnvironmentVariablePattern;\n use codex_protocol::config_types::ShellEnvironmentPolicy;\n@@ -18,9 +17,11 @@ use tokio::sync::mpsc;\n use tokio::sync::watch;\n \n use crate::ExecBackend;\n+use crate::ExecBackendFuture;\n use crate::ExecProcess;\n use crate::ExecProcessEvent;\n use crate::ExecProcessEventReceiver;\n+use crate::ExecProcessFuture;\n use crate::ExecServerError;\n use crate::ProcessId;\n use crate::StartedExecProcess;\n@@ -460,8 +461,7 @@ fn shell_environment_policy(env_policy: &ExecEnvPolicy) -> ShellEnvironmentPolic\n }\n }\n \n-#[async_trait]\n-impl ExecBackend for LocalProcess {\n+impl LocalProcess {\n async fn start(&self, params: ExecParams) -> Result &ProcessId;\n \n fn subscribe_wake(&self) -> watch::Receiver;\n \n fn subscribe_events(&self) -> ExecProcessEventReceiver;\n \n- async fn read(\n+ fn read(\n &self,\n after_seq: Option,\n max_bytes: Option,\n wait_ms: Option,\n- ) -> Re...", + "path": "codex-rs/exec-server/src/process.rs", + "status": "modified" + }, + { + "additions": 80, + "deletions": 4, + "patch_excerpt": "@@ -1,4 +1,3 @@\n-use async_trait::async_trait;\n use base64::Engine as _;\n use base64::engine::general_purpose::STANDARD;\n use codex_utils_path_uri::PathUri;\n@@ -9,6 +8,7 @@ use crate::CopyOptions;\n use crate::CreateDirectoryOptions;\n use crate::ExecServerError;\n use crate::ExecutorFileSystem;\n+use crate::ExecutorFileSystemFuture;\n use crate::FileMetadata;\n use crate::FileSystemResult;\n use crate::FileSystemSandboxContext;\n@@ -36,10 +36,7 @@ impl RemoteFileSystem {\n trace!(\"remote fs new\");\n Self { client }\n }\n-}\n \n-#[async_trait]\n-impl ExecutorFileSystem for RemoteFileSystem {\n async fn canonicalize(\n &self,\n path: &PathUri,\n@@ -207,6 +204,85 @@ impl ExecutorFileSystem for RemoteFileSystem {\n }\n }\n \n+impl ExecutorFileSystem for RemoteFileSystem {\n+ fn canonicalize<'a>(\n+ &'a self,\n+ path: &'a PathUri,\n+ sandbox: Option<&...", + "path": "codex-rs/exec-server/src/remote_file_system.rs", + "status": "modified" + }, + { + "additions": 47, + "deletions": 19, + "patch_excerpt": "@@ -1,13 +1,13 @@\n use std::sync::Arc;\n \n-use async_trait::async_trait;\n use tokio::sync::watch;\n use tracing::trace;\n \n use crate::ExecBackend;\n+use crate::ExecBackendFuture;\n use crate::ExecProcess;\n use crate::ExecProcessEventReceiver;\n-use crate::ExecServerError;\n+use crate::ExecProcessFuture;\n use crate::StartedExecProcess;\n use crate::client::LazyRemoteExecServerClient;\n use crate::client::Session;\n@@ -30,11 +30,11 @@ impl RemoteProcess {\n trace!(\"remote process new\");\n Self { client }\n }\n-}\n \n-#[async_trait]\n-impl ExecBackend for RemoteProcess {\n- async fn start(&self, params: ExecParams) -> Result {\n+ async fn start(\n+ &self,\n+ params: ExecParams,\n+ ) -> Result {\n let process_id = params.process_id.clone();\n let client = self.client.get().awa...", + "path": "codex-rs/exec-server/src/remote_process.rs", + "status": "modified" + }, + { + "additions": 88, + "deletions": 3, + "patch_excerpt": "@@ -1,4 +1,3 @@\n-use async_trait::async_trait;\n use base64::Engine as _;\n use base64::engine::general_purpose::STANDARD;\n use codex_app_server_protocol::JSONRPCErrorError;\n@@ -9,6 +8,7 @@ use crate::CopyOptions;\n use crate::CreateDirectoryOptions;\n use crate::ExecServerRuntimePaths;\n use crate::ExecutorFileSystem;\n+use crate::ExecutorFileSystemFuture;\n use crate::FileMetadata;\n use crate::FileSystemResult;\n use crate::FileSystemSandboxContext;\n@@ -50,8 +50,7 @@ impl SandboxedFileSystem {\n }\n }\n \n-#[async_trait]\n-impl ExecutorFileSystem for SandboxedFileSystem {\n+impl SandboxedFileSystem {\n async fn canonicalize(\n &self,\n path: &PathUri,\n@@ -248,6 +247,92 @@ impl ExecutorFileSystem for SandboxedFileSystem {\n }\n }\n \n+impl ExecutorFileSystem for SandboxedFileSystem {\n+ fn canonicalize<'a>(\n+ &'a self,\n+ path: &'a PathUri,\n+ sandbox: Option...", + "path": "codex-rs/exec-server/src/sandboxed_file_system.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -31,6 +31,5 @@ tracing = { workspace = true }\n url = { workspace = true }\n \n [dev-dependencies]\n-async-trait = { workspace = true }\n pretty_assertions = { workspace = true }\n tokio = { workspace = true, features = [\"macros\", \"rt-multi-thread\"] }", + "path": "codex-rs/ext/skills/Cargo.toml", + "status": "modified" + }, + { + "additions": 86, + "deletions": 76, + "patch_excerpt": "@@ -3,16 +3,15 @@ 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::ExecutorFileSystemFuture;\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@@ -36,6 +35,42 @@ struct SyntheticFileSystem {\n }\n \n impl SyntheticFileSystem {\n+ async fn canonicalize(&self, path: &PathUri) -> io::Result {\n+ let path = path....", + "path": "codex-rs/ext/skills/tests/executor_file_system_authority.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -8,7 +8,6 @@ license.workspace = true\n workspace = true\n \n [dependencies]\n-async-trait = { workspace = true }\n codex-protocol = { workspace = true }\n codex-utils-absolute-path = { workspace = true }\n codex-utils-path-uri = { workspace = true }", + "path": "codex-rs/file-system/Cargo.toml", + "status": "modified" + }, + { + "additions": 60, + "deletions": 54, + "patch_excerpt": "@@ -1,4 +1,3 @@\n-use async_trait::async_trait;\n use codex_protocol::config_types::WindowsSandboxLevel;\n use codex_protocol::models::PermissionProfile;\n use codex_protocol::models::SandboxEnforcement;\n@@ -10,8 +9,10 @@ use codex_protocol::permissions::NetworkSandboxPolicy;\n use codex_protocol::protocol::SandboxPolicy;\n use codex_utils_absolute_path::AbsolutePathBuf;\n use codex_utils_path_uri::PathUri;\n+use std::future::Future;\n use std::io;\n use std::path::Path;\n+use std::pin::Pin;\n \n #[derive(Clone, Copy, Debug, Eq, PartialEq)]\n pub struct CreateDirectoryOptions {\n@@ -130,71 +131,76 @@ fn file_system_policy_has_cwd_dependent_entries(\n \n pub type FileSystemResult = io::Result;\n \n+/// Future returned by [`ExecutorFileSystem`] operations.\n+pub type ExecutorFileSystemFuture<'a, T> =\n+ Pin> + Send + 'a>>;\n+\n /// Abstract filesystem access u...", + "path": "codex-rs/file-system/src/lib.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -8,7 +8,6 @@ license.workspace = true\n workspace = true\n \n [dependencies]\n-async-trait = { workspace = true }\n base64 = { workspace = true }\n chrono = { workspace = true, features = [\"serde\"] }\n codex-agent-identity = { workspace = true }", + "path": "codex-rs/login/Cargo.toml", + "status": "modified" + }, + { + "additions": 18, + "deletions": 8, + "patch_excerpt": "@@ -1,7 +1,7 @@\n use super::manager::ExternalAuth;\n+use super::manager::ExternalAuthFuture;\n use super::manager::ExternalAuthRefreshContext;\n use super::manager::ExternalAuthTokens;\n-use async_trait::async_trait;\n use codex_app_server_protocol::AuthMode;\n use codex_protocol::config_types::ModelProviderAuthInfo;\n use std::fmt;\n@@ -25,13 +25,6 @@ impl BearerTokenRefresher {\n state: Arc::new(ExternalBearerAuthState::new(config)),\n }\n }\n-}\n-\n-#[async_trait]\n-impl ExternalAuth for BearerTokenRefresher {\n- fn auth_mode(&self) -> AuthMode {\n- AuthMode::ApiKey\n- }\n \n #[expect(\n clippy::await_holding_invalid_type,\n@@ -76,6 +69,23 @@ impl ExternalAuth for BearerTokenRefresher {\n }\n }\n \n+impl ExternalAuth for BearerTokenRefresher {\n+ fn auth_mode(&self) -> AuthMode {\n+ AuthMode::ApiKey\n+ }\n+\n+ fn resolve(&self) -> ExternalAuthFutu...", + "path": "codex-rs/login/src/auth/external_bearer.rs", + "status": "modified" + }, + { + "additions": 8, + "deletions": 6, + "patch_excerpt": "@@ -1,4 +1,3 @@\n-use async_trait::async_trait;\n use chrono::Utc;\n use reqwest::StatusCode;\n use serde::Deserialize;\n@@ -7,8 +6,10 @@ use serde::Serialize;\n use serial_test::serial;\n use std::env;\n use std::fmt::Debug;\n+use std::future::Future;\n use std::path::Path;\n use std::path::PathBuf;\n+use std::pin::Pin;\n use std::sync::Arc;\n use std::sync::Mutex;\n use std::sync::RwLock;\n@@ -167,7 +168,6 @@ pub struct ExternalAuthRefreshContext {\n pub previous_account_id: Option,\n }\n \n-#[async_trait]\n /// Pluggable auth provider used by `AuthManager` for externally managed auth flows.\n ///\n /// Implementations may either resolve auth eagerly via `resolve()` or provide refreshed\n@@ -178,17 +178,19 @@ pub trait ExternalAuth: Send + Sync {\n \n /// Returns cached or immediately available auth, if this provider can resolve it synchronously\n /// from the caller's perspective.\n- async...", + "path": "codex-rs/login/src/auth/manager.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -27,6 +27,7 @@ pub use auth::CODEX_API_KEY_ENV_VAR;\n pub use auth::CodexAuth;\n pub use auth::ExternalAuth;\n pub use auth::ExternalAuthChatgptMetadata;\n+pub use auth::ExternalAuthFuture;\n pub use auth::ExternalAuthRefreshContext;\n pub use auth::ExternalAuthRefreshReason;\n pub use auth::ExternalAuthTokens;", + "path": "codex-rs/login/src/lib.rs", + "status": "modified" + }, + { + "additions": 2, + "deletions": 9, + "patch_excerpt": "@@ -11,6 +11,7 @@ use codex_git_utils::reset_git_repository;\n use codex_login::AuthManager;\n use codex_login::CodexAuth;\n use codex_model_provider::ModelProvider;\n+use codex_model_provider::ModelProviderFuture;\n use codex_model_provider::ProviderAccountResult;\n use codex_model_provider::SharedModelProvider;\n use codex_model_provider::create_model_provider;\n@@ -38,10 +39,8 @@ use core_test_support::test_codex::TestCodex;\n use core_test_support::test_codex::test_codex;\n use core_test_support::wait_for_event;\n use pretty_assertions::assert_eq;\n-use std::future::Future;\n use std::path::Path;\n use std::path::PathBuf;\n-use std::pin::Pin;\n use std::sync::Arc;\n use tempfile::TempDir;\n use tokio::time::Duration;\n@@ -616,13 +615,7 @@ impl ModelProvider for MockMemoryModelProvider {\n self.delegate.auth_manager()\n }\n \n- fn auth<'life0, 'async_trait>(\n- &'life0 self,\n- ) -> P...", + "path": "codex-rs/memories/write/src/startup_tests.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -13,7 +13,6 @@ path = \"src/lib.rs\"\n workspace = true\n \n [dependencies]\n-async-trait = { workspace = true }\n codex-api = { workspace = true }\n codex-agent-identity = { workspace = true }\n codex-aws-auth = { workspace = true }", + "path": "codex-rs/model-provider/Cargo.toml", + "status": "modified" + }, + { + "additions": 8, + "deletions": 5, + "patch_excerpt": "@@ -133,11 +133,6 @@ impl BedrockMantleSigV4AuthProvider {\n fn new(context: AwsAuthContext) -> Self {\n Self { context }\n }\n-}\n-\n-#[async_trait::async_trait]\n-impl AuthProvider for BedrockMantleSigV4AuthProvider {\n- fn add_auth_headers(&self, _headers: &mut HeaderMap) {}\n \n async fn apply_auth(&self, request: Request) -> std::result::Result {\n let mut request = request;\n@@ -162,6 +157,14 @@ impl AuthProvider for BedrockMantleSigV4AuthProvider {\n }\n }\n \n+impl AuthProvider for BedrockMantleSigV4AuthProvider {\n+ fn add_auth_headers(&self, _headers: &mut HeaderMap) {}\n+\n+ fn apply_auth(&self, request: Request) -> codex_api::AuthProviderFuture<'_> {\n+ Box::pin(BedrockMantleSigV4AuthProvider::apply_auth(self, request))\n+ }\n+}\n+\n #[cfg(test)]\n mod tests {\n use codex_api::AuthProvider;", + "path": "codex-rs/model-provider/src/amazon_bedrock/auth.rs", + "status": "modified" + }, + { + "additions": 33, + "deletions": 17, + "patch_excerpt": "@@ -20,6 +20,7 @@ use codex_protocol::error::Result;\n use codex_protocol::openai_models::ModelsResponse;\n \n use crate::provider::ModelProvider;\n+use crate::provider::ModelProviderFuture;\n use crate::provider::ProviderAccountResult;\n use crate::provider::ProviderAccountState;\n use crate::provider::ProviderCapabilities;\n@@ -68,9 +69,32 @@ impl AmazonBedrockModelProvider {\n | CodexAuth::PersonalAccessToken(_) => None,\n })\n }\n+\n+ async fn auth(&self) -> Option {\n+ self.managed_auth().map(CodexAuth::BedrockApiKey)\n+ }\n+\n+ async fn api_provider(&self) -> Result {\n+ let managed_auth = self.managed_auth();\n+ let mut api_provider_info = self.info.clone();\n+ api_provider_info.base_url =\n+ Some(runtime_base_url(managed_auth.as_ref(), &self.aws).await?);\n+ api_provider_info.to_api_provider(/*a...", + "path": "codex-rs/model-provider/src/amazon_bedrock/mod.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -10,6 +10,7 @@ pub use bearer_auth_provider::BearerAuthProvider;\n pub use bearer_auth_provider::BearerAuthProvider as CoreAuthProvider;\n pub use codex_protocol::account::ProviderAccount;\n pub use provider::ModelProvider;\n+pub use provider::ModelProviderFuture;\n pub use provider::ProviderAccountError;\n pub use provider::ProviderAccountResult;\n pub use provider::ProviderAccountState;", + "path": "codex-rs/model-provider/src/lib.rs", + "status": "modified" + }, + { + "additions": 26, + "deletions": 16, + "patch_excerpt": "@@ -1,7 +1,6 @@\n use std::sync::Arc;\n use std::time::Duration;\n \n-use async_trait::async_trait;\n use codex_api::ModelsClient;\n use codex_api::RequestTelemetry;\n use codex_api::ReqwestTransport;\n@@ -17,6 +16,7 @@ use codex_login::collect_auth_env_telemetry;\n use codex_login::default_client::build_reqwest_client;\n use codex_model_provider_info::ModelProviderInfo;\n use codex_models_manager::manager::ModelsEndpointClient;\n+use codex_models_manager::manager::ModelsEndpointFuture;\n use codex_otel::TelemetryAuthMode;\n use codex_protocol::error::CodexErr;\n use codex_protocol::error::Result as CoreResult;\n@@ -56,21 +56,6 @@ impl OpenAiModelsEndpoint {\n }\n }\n \n- fn auth_env(&self) -> AuthEnvTelemetry {\n- let codex_api_key_env_enabled = self\n- .auth_manager\n- .as_ref()\n- .is_some_and(|auth_manager| auth_manager.codex_api_key_env_enabled());\n- ...", + "path": "codex-rs/model-provider/src/models_endpoint.rs", + "status": "modified" + }, + { + "additions": 29, + "deletions": 17, + "patch_excerpt": "@@ -1,5 +1,7 @@\n use std::fmt;\n+use std::future::Future;\n use std::path::PathBuf;\n+use std::pin::Pin;\n use std::sync::Arc;\n \n use codex_api::Provider;\n@@ -94,7 +96,6 @@ pub const DEFAULT_MEMORY_CONSOLIDATION_PREFERRED_MODEL: &str = \"gpt-5.4\";\n /// Implementations own provider-specific behavior for a model backend. The\n /// `ModelProviderInfo` returned by `info` is the serialized/configured provider\n /// metadata used by the default OpenAI-compatible implementation.\n-#[async_trait::async_trait]\n pub trait ModelProvider: fmt::Debug + Send + Sync {\n /// Returns the configured provider metadata.\n fn info(&self) -> &ModelProviderInfo;\n@@ -139,27 +140,35 @@ pub trait ModelProvider: fmt::Debug + Send + Sync {\n fn auth_manager(&self) -> Option>;\n \n /// Returns the current provider-scoped auth value, if one is configured.\n- async fn auth(&self) -> Option usize {\n self.fetch_count.load(Ordering::SeqCst)\n }\n+\n+ async fn list_models(&self) -> CoreResult<(Vec, Option)> {\n+ self.fetch_count.fetch_add(1, Ordering::SeqCst);\n+ let models = self\n+ .responses\n+ .lock()\n+ .expect(\"responses lock should not be poisoned\")\n+ .pop_front()\n+ .unwrap_or_default();\n+ Ok((models, None))\n+ }\n }\n \n #[derive(Debug)]\n struct TestExternalApiKeyAuth;\n \n-#[async_trait]\n impl ExternalAuth for TestExternalApiKeyAuth {\n fn auth_mode(&self) -> AuthMode {\n AuthMode::ApiKey\n }\n \n- async fn resolve(&self) -> std::io::Result> {\n- Ok(Some(ExternalAuthTokens::access_token_only(\n- \"test-external-api-key\",\n- )))\n+ ...", + "path": "codex-rs/models-manager/src/manager_tests.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -14,7 +14,6 @@ workspace = true\n \n [dependencies]\n anyhow = { workspace = true }\n-async-trait = { workspace = true }\n base64 = { workspace = true }\n clap = { workspace = true, features = [\"derive\"] }\n chrono = { workspace = true }", + "path": "codex-rs/network-proxy/Cargo.toml", + "status": "modified" + }, + { + "additions": 3, + "deletions": 0, + "patch_excerpt": "@@ -34,6 +34,7 @@ pub use mitm_hook::MitmHookMatchConfig;\n pub use network_policy::NetworkDecision;\n pub use network_policy::NetworkDecisionSource;\n pub use network_policy::NetworkPolicyDecider;\n+pub use network_policy::NetworkPolicyDeciderFuture;\n pub use network_policy::NetworkPolicyDecision;\n pub use network_policy::NetworkPolicyRequest;\n pub use network_policy::NetworkPolicyRequestArgs;\n@@ -59,7 +60,9 @@ pub use proxy::proxy_url_env_value;\n pub use runtime::BlockedRequest;\n pub use runtime::BlockedRequestArgs;\n pub use runtime::BlockedRequestObserver;\n+pub use runtime::BlockedRequestObserverFuture;\n pub use runtime::ConfigReloader;\n+pub use runtime::ConfigReloaderFuture;\n pub use runtime::ConfigState;\n pub use runtime::NetworkProxyState;\n pub use state::NetworkProxyAuditMetadata;", + "path": "codex-rs/network-proxy/src/lib.rs", + "status": "modified" + }, + { + "additions": 15, + "deletions": 15, + "patch_excerpt": "@@ -3,10 +3,10 @@ use crate::runtime::HostBlockDecision;\n use crate::runtime::HostBlockReason;\n use crate::state::NetworkProxyState;\n use anyhow::Result;\n-use async_trait::async_trait;\n use chrono::SecondsFormat;\n use chrono::Utc;\n use std::future::Future;\n+use std::pin::Pin;\n use std::sync::Arc;\n \n const AUDIT_TARGET: &str = \"codex_otel.network_proxy\";\n@@ -263,26 +263,26 @@ fn audit_timestamp() -> String {\n /// If `command` or `exec_policy_hint` is provided, callers can map exec-policy\n /// approvals to network access (e.g., allow all requests for commands matching\n /// approved prefixes like `curl *`).\n-#[async_trait]\n pub trait NetworkPolicyDecider: Send + Sync + 'static {\n- async fn decide(&self, req: NetworkPolicyRequest) -> NetworkDecision;\n+ fn decide(&self, req: NetworkPolicyRequest) -> NetworkPolicyDeciderFuture<'_>;\n }\n \n-#[async_trait]\n+pub type NetworkPolicyDeciderFutur...", + "path": "codex-rs/network-proxy/src/network_policy.rs", + "status": "modified" + }, + { + "additions": 17, + "deletions": 18, + "patch_excerpt": "@@ -20,7 +20,6 @@ use crate::state::build_config_state;\n use crate::state::validate_policy_against_constraints;\n use anyhow::Context;\n use anyhow::Result;\n-use async_trait::async_trait;\n use codex_utils_absolute_path::AbsolutePathBuf;\n use globset::GlobSet;\n use serde::Serialize;\n@@ -30,6 +29,7 @@ use std::future::Future;\n use std::net::IpAddr;\n use std::net::SocketAddr;\n use std::path::Path;\n+use std::pin::Pin;\n use std::sync::Arc;\n use std::time::Duration;\n use time::OffsetDateTime;\n@@ -168,38 +168,38 @@ pub struct ConfigState {\n pub blocked_total: u64,\n }\n \n-#[async_trait]\n pub trait ConfigReloader: Send + Sync {\n /// Human-readable description of where config is loaded from, for logs.\n fn source_label(&self) -> String;\n \n /// Return a freshly loaded state if a reload is needed; otherwise, return `None`.\n- async fn maybe_reload(&self) -> Result>;...", + "path": "codex-rs/network-proxy/src/runtime.rs", + "status": "modified" + }, + { + "additions": 5, + "deletions": 6, + "patch_excerpt": "@@ -714,10 +714,10 @@ mod tests {\n use crate::network_policy::test_support::capture_events;\n use crate::network_policy::test_support::find_event_by_name;\n use crate::runtime::ConfigReloader;\n+ use crate::runtime::ConfigReloaderFuture;\n use crate::runtime::ConfigState;\n use crate::state::NetworkProxyConstraints;\n use crate::state::build_config_state;\n- use async_trait::async_trait;\n use pretty_assertions::assert_eq;\n use rama_core::extensions::Extensions;\n use rama_core::extensions::ExtensionsMut;\n@@ -738,14 +738,13 @@ mod tests {\n state: ConfigState,\n }\n \n- #[async_trait]\n impl ConfigReloader for StaticReloader {\n- async fn maybe_reload(&self) -> anyhow::Result> {\n- Ok(None)\n+ fn maybe_reload(&self) -> ConfigReloaderFuture<'_, Option> {\n+ Box::pin(async { Ok(N...", + "path": "codex-rs/network-proxy/src/socks5.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -14,7 +14,6 @@ workspace = true\n \n [dependencies]\n anyhow = { workspace = true }\n-async-trait = { workspace = true }\n chrono = { workspace = true, features = [\"serde\"] }\n codex-file-search = { workspace = true }\n codex-git-utils = { workspace = true }", + "path": "codex-rs/rollout/Cargo.toml", + "status": "modified" + }, + { + "additions": 2, + "deletions": 6, + "patch_excerpt": "@@ -1,6 +1,5 @@\n #![allow(warnings, clippy::all)]\n \n-use async_trait::async_trait;\n use codex_utils_path as path_utils;\n use std::cmp::Reverse;\n use std::ffi::OsStr;\n@@ -195,15 +194,14 @@ impl AnchorState {\n ///\n /// We need to apply different logic if we're ultimately going to be returning\n /// threads ordered by created_at or updated_at.\n-#[async_trait]\n trait RolloutFileVisitor {\n- async fn visit(\n+ fn visit(\n &mut self,\n ts: OffsetDateTime,\n id: Uuid,\n path: PathBuf,\n scanned: usize,\n- ) -> ControlFlow<()>;\n+ ) -> impl std::future::Future> + Send;\n }\n \n /// Collects thread items during directory traversal in created_at order,\n@@ -218,7 +216,6 @@ struct FilesByCreatedAtVisitor<'a> {\n cwd_filters: Option<&'a [PathBuf]>,\n }\n \n-#[async_trait]\n impl<'a> RolloutFileVisitor for FilesByCreatedAtVisitor<'a> {\n ...", + "path": "codex-rs/rollout/src/list.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -26,7 +26,6 @@ which = { workspace = true }\n \n [dev-dependencies]\n anyhow = { workspace = true }\n-async-trait = { workspace = true }\n pretty_assertions = { workspace = true }\n tempfile = { workspace = true }\n tokio = { workspace = true, features = [\"macros\", \"rt\"] }", + "path": "codex-rs/sandboxing/Cargo.toml", + "status": "modified" + }, + { + "additions": 5, + "deletions": 5, + "patch_excerpt": "@@ -12,6 +12,7 @@ use super::seatbelt_regex_for_unreadable_glob;\n use super::unix_socket_dir_params;\n use super::unix_socket_policy;\n use codex_network_proxy::ConfigReloader;\n+use codex_network_proxy::ConfigReloaderFuture;\n use codex_network_proxy::ConfigState;\n use codex_network_proxy::NetworkMode;\n use codex_network_proxy::NetworkProxy;\n@@ -81,18 +82,17 @@ fn seatbelt_protected_metadata_name_requirements(root: &Path) -> String {\n \n struct TestConfigReloader;\n \n-#[async_trait::async_trait]\n impl ConfigReloader for TestConfigReloader {\n fn source_label(&self) -> String {\n \"seatbelt test config\".to_string()\n }\n \n- async fn maybe_reload(&self) -> anyhow::Result> {\n- Ok(None)\n+ fn maybe_reload(&self) -> ConfigReloaderFuture<'_, Option> {\n+ Box::pin(async { Ok(None) })\n }\n \n- async fn reload_now(&self) -> anyhow::Res...", + "path": "codex-rs/sandboxing/src/seatbelt_tests.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -13,7 +13,6 @@ workspace = true\n \n [dependencies]\n anyhow = { workspace = true }\n-async-trait = { workspace = true }\n clap = { workspace = true, features = [\"derive\"] }\n codex-protocol = { workspace = true }\n codex-utils-absolute-path = { workspace = true }", + "path": "codex-rs/shell-escalation/Cargo.toml", + "status": "modified" + }, + { + "additions": 4, + "deletions": 0, + "patch_excerpt": "@@ -16,6 +16,8 @@ pub use unix::EscalationPermissions;\n #[cfg(unix)]\n pub use unix::EscalationPolicy;\n #[cfg(unix)]\n+pub use unix::EscalationPolicyFuture;\n+#[cfg(unix)]\n pub use unix::EscalationSession;\n #[cfg(unix)]\n pub use unix::ExecParams;\n@@ -28,6 +30,8 @@ pub use unix::ResolvedPermissionProfile;\n #[cfg(unix)]\n pub use unix::ShellCommandExecutor;\n #[cfg(unix)]\n+pub use unix::ShellCommandExecutorFuture;\n+#[cfg(unix)]\n pub use unix::Stopwatch;\n #[cfg(unix)]\n pub use unix::main_execve_wrapper;", + "path": "codex-rs/shell-escalation/src/lib.rs", + "status": "modified" + }, + { + "additions": 112, + "deletions": 61, + "patch_excerpt": "@@ -1,6 +1,8 @@\n use std::collections::HashMap;\n+use std::future::Future;\n use std::os::fd::AsRawFd;\n use std::path::PathBuf;\n+use std::pin::Pin;\n use std::process::Stdio;\n use std::sync::Arc;\n use std::sync::Mutex;\n@@ -31,7 +33,6 @@ use crate::unix::socket::AsyncSocket;\n /// This lets `shell-escalation` own the Unix escalation protocol while the caller\n /// keeps control over process spawning, output capture, and sandbox integration.\n /// Implementations can capture any sandbox state they need.\n-#[async_trait::async_trait]\n pub trait ShellCommandExecutor: Send + Sync {\n /// Runs the requested shell command and returns the captured result.\n ///\n@@ -41,26 +42,29 @@ pub trait ShellCommandExecutor: Send + Sync {\n /// for the shell process. `after_spawn` should be invoked immediately after\n /// the shell process has been spawned so the parent copy of the inherited\n /// es...", + "path": "codex-rs/shell-escalation/src/unix/escalate_server.rs", + "status": "modified" + }, + { + "additions": 12, + "deletions": 7, + "patch_excerpt": "@@ -1,14 +1,19 @@\n+use std::future::Future;\n+use std::pin::Pin;\n+\n use codex_utils_absolute_path::AbsolutePathBuf;\n \n use crate::unix::escalate_protocol::EscalationDecision;\n \n /// Decides what action to take in response to an execve request from a client.\n-#[async_trait::async_trait]\n pub trait EscalationPolicy: Send + Sync {\n- async fn determine_action(\n- &self,\n- file: &AbsolutePathBuf,\n- argv: &[String],\n- workdir: &AbsolutePathBuf,\n- ) -> anyhow::Result;\n+ fn determine_action<'a>(\n+ &'a self,\n+ file: &'a AbsolutePathBuf,\n+ argv: &'a [String],\n+ workdir: &'a AbsolutePathBuf,\n+ ) -> EscalationPolicyFuture<'a>;\n }\n+\n+pub type EscalationPolicyFuture<'a> =\n+ Pin> + Send + 'a>>;", + "path": "codex-rs/shell-escalation/src/unix/escalation_policy.rs", + "status": "modified" + }, + { + "additions": 2, + "deletions": 0, + "patch_excerpt": "@@ -72,7 +72,9 @@ pub use self::escalate_server::ExecParams;\n pub use self::escalate_server::ExecResult;\n pub use self::escalate_server::PreparedExec;\n pub use self::escalate_server::ShellCommandExecutor;\n+pub use self::escalate_server::ShellCommandExecutorFuture;\n pub use self::escalation_policy::EscalationPolicy;\n+pub use self::escalation_policy::EscalationPolicyFuture;\n pub use self::execve_wrapper::main_execve_wrapper;\n pub use self::stopwatch::Stopwatch;\n pub use codex_protocol::approvals::EscalationPermissions;", + "path": "codex-rs/shell-escalation/src/unix/mod.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -13,7 +13,6 @@ doctest = false\n workspace = true\n \n [dependencies]\n-async-trait = { workspace = true }\n chrono = { workspace = true, features = [\"serde\"] }\n codex-git-utils = { workspace = true }\n codex-install-context = { workspace = true }", + "path": "codex-rs/thread-store/Cargo.toml", + "status": "modified" + }, + { + "additions": 98, + "deletions": 43, + "patch_excerpt": "@@ -5,7 +5,6 @@ use std::sync::Mutex;\n use std::sync::MutexGuard;\n use std::sync::OnceLock;\n \n-use async_trait::async_trait;\n use chrono::Utc;\n use codex_protocol::ThreadId;\n use codex_protocol::models::PermissionProfile;\n@@ -31,6 +30,7 @@ use crate::ThreadMetadataPatch;\n use crate::ThreadPage;\n use crate::ThreadStore;\n use crate::ThreadStoreError;\n+use crate::ThreadStoreFuture;\n use crate::ThreadStoreResult;\n use crate::UpdateThreadMetadataParams;\n \n@@ -160,13 +160,6 @@ impl InMemoryThreadStore {\n pub async fn calls(&self) -> InMemoryThreadStoreCalls {\n self.state.lock().await.calls.clone()\n }\n-}\n-\n-#[async_trait]\n-impl ThreadStore for InMemoryThreadStore {\n- fn as_any(&self) -> &dyn std::any::Any {\n- self\n- }\n \n async fn create_thread(&self, params: CreateThreadParams) -> ThreadStoreResult<()> {\n let mut state = self.state.lock().await;\n@@ -230,...", + "path": "codex-rs/thread-store/src/in_memory.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -21,6 +21,7 @@ pub use live_thread::LiveThreadInitGuard;\n pub use local::LocalThreadStore;\n pub use local::LocalThreadStoreConfig;\n pub use store::ThreadStore;\n+pub use store::ThreadStoreFuture;\n pub use types::AppendThreadItemsParams;\n pub use types::ArchiveThreadParams;\n pub use types::ClearableField;", + "path": "codex-rs/thread-store/src/lib.rs", + "status": "modified" + }, + { + "additions": 70, + "deletions": 58, + "patch_excerpt": "@@ -12,7 +12,6 @@ mod update_thread_metadata;\n #[cfg(test)]\n mod test_support;\n \n-use async_trait::async_trait;\n use codex_protocol::ThreadId;\n use codex_rollout::RolloutRecorder;\n use codex_rollout::StateDbHandle;\n@@ -38,6 +37,7 @@ use crate::ThreadPage;\n use crate::ThreadSearchPage;\n use crate::ThreadStore;\n use crate::ThreadStoreError;\n+use crate::ThreadStoreFuture;\n use crate::ThreadStoreResult;\n use crate::UpdateThreadMetadataParams;\n \n@@ -166,41 +166,6 @@ impl LocalThreadStore {\n }\n }\n }\n-}\n-\n-#[async_trait]\n-impl ThreadStore for LocalThreadStore {\n- fn as_any(&self) -> &dyn std::any::Any {\n- self\n- }\n-\n- async fn create_thread(&self, params: CreateThreadParams) -> ThreadStoreResult<()> {\n- live_writer::create_thread(self, params).await\n- }\n-\n- async fn resume_thread(&self, params: ResumeThreadParams) -> ThreadStoreResult<()> {\n-...", + "path": "codex-rs/thread-store/src/local/mod.rs", + "status": "modified" + }, + { + "additions": 39, + "deletions": 33, + "patch_excerpt": "@@ -1,6 +1,7 @@\n-use async_trait::async_trait;\n use codex_protocol::ThreadId;\n use std::any::Any;\n+use std::future::Future;\n+use std::pin::Pin;\n \n use crate::AppendThreadItemsParams;\n use crate::ArchiveThreadParams;\n@@ -24,102 +25,107 @@ use crate::ThreadStoreResult;\n use crate::TurnPage;\n use crate::UpdateThreadMetadataParams;\n \n+/// Future returned by [`ThreadStore`] operations.\n+pub type ThreadStoreFuture<'a, T> = Pin> + Send + 'a>>;\n+\n /// Storage-neutral thread persistence boundary.\n-#[async_trait]\n pub trait ThreadStore: Any + Send + Sync {\n /// Return this store as [`Any`] for implementation-owned escape hatches.\n fn as_any(&self) -> &dyn Any;\n \n /// Creates a new live thread.\n- async fn create_thread(&self, params: CreateThreadParams) -> ThreadStoreResult<()>;\n+ fn create_thread(&self, params: CreateThreadParams) -> T...", + "path": "codex-rs/thread-store/src/store.rs", + "status": "modified" + }, + { + "additions": 2, + "deletions": 3, + "patch_excerpt": "@@ -138,9 +138,8 @@ pub(crate) trait WorkspaceCommandExecutor: Send + Sync {\n /// Runs a workspace command and returns captured output or an app-server request error.\n ///\n /// Callers should treat errors as infrastructure failures and should treat successful output\n- /// with a non-zero exit code as ordinary command failure. Returning a future instead of using\n- /// `async_trait` keeps the trait object-safe while matching the repo's native async trait\n- /// conventions.\n+ /// with a non-zero exit code as ordinary command failure. Returning a boxed future keeps the\n+ /// trait object-safe.\n fn run(\n &self,\n command: WorkspaceCommand,", + "path": "codex-rs/tui/src/workspace_command.rs", + "status": "modified" + }, + { + "additions": 0, + "deletions": 1, + "patch_excerpt": "@@ -5,7 +5,6 @@ edition.workspace = true\n license.workspace = true\n \n [dependencies]\n-async-trait = { workspace = true }\n thiserror = { workspace = true }\n time = { workspace = true }\n tokio = { workspace = true, features = [\"sync\", \"time\"] }", + "path": "codex-rs/utils/readiness/Cargo.toml", + "status": "modified" + }, + { + "additions": 8, + "deletions": 5, + "patch_excerpt": "@@ -17,7 +17,6 @@ pub struct Token(i32);\n \n const LOCK_TIMEOUT: Duration = Duration::from_millis(1000);\n \n-#[async_trait::async_trait]\n pub trait Readiness: Send + Sync + 'static {\n /// Returns true if the flag is currently marked ready. At least one token needs to be marked\n /// as ready before.\n@@ -27,17 +26,22 @@ pub trait Readiness: Send + Sync + 'static {\n /// Subscribe to readiness and receive an authorization token.\n ///\n /// If the flag is already ready, returns `FlagAlreadyReady`.\n- async fn subscribe(&self) -> Result;\n+ fn subscribe(\n+ &self,\n+ ) -> impl std::future::Future> + Send;\n \n /// Attempt to mark the flag ready, validated by the provided token.\n ///\n /// Returns `true` iff:\n /// - `token` is currently subscribed, and\n /// - the flag was ...", + "path": "codex-rs/utils/readiness/src/lib.rs", + "status": "modified" + } + ], + "linked_issues": [ + "#27303", + "#27304" + ], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "## Why\n\nFirst-party async traits should expose their `Send` contracts explicitly without requiring `async_trait`. This completes the migration pattern established in #27303 and #27304.\n\n## What changed\n\n- Replaced the remaining first-party `async_trait` traits with native return-position `impl Future + Send` where statically dispatched and explicit boxed `Send` futures where object safety is required.\n- Kept implementations behavior-preserving, outlining existing async bodies into inherent methods where that keeps the diff reviewable.\n- Removed all direct first-party `async-trait` dependencies and the workspace dependency declaration.\n- Added a cargo-deny policy that permits `async-trait` only through the remaining transitive wrapper crates.\n- Updated `rand` from 0.8.5 to 0.8.6 to resolve RUSTSEC-2026-0097 and keep the full cargo-deny check passing.\n\n## Validation\n\n- `just test -p codex-exec-server`: 216 passed, 2 skipped.\n- `just test -p codex-model-provider`: 39 passed.\n- `just test -p codex-core` and `just test`: changed tests passed; remaining failures are environment-sensitive suites unrelated to this migration.\n- `cargo deny check`\n- `just fix`\n- `just fmt`\n- `cargo shear`\n- `just bazel-lock-check`\n", + "labels": [], + "merged_at": "2026-06-12T01:16:39Z", + "number": 27475, + "state": "merged", + "title": "[codex] Remove async_trait from first-party code", + "url": "https://github.com/openai/codex/pull/27475" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/bundles/openai-codex-pr-27498.json b/artifacts/github/bundles/openai-codex-pr-27498.json new file mode 100644 index 000000000..7f3dd603e --- /dev/null +++ b/artifacts/github/bundles/openai-codex-pr-27498.json @@ -0,0 +1,194 @@ +{ + "analysis_mode": "pr_first", + "commits": [ + { + "author": "won-openai", + "committed_at": "2026-06-11T00:19:53Z", + "message": "draft", + "sha": "27e50cfa078191d4d61f281fcb4307b3fd8d2e97", + "url": "https://github.com/openai/codex/commit/27e50cfa078191d4d61f281fcb4307b3fd8d2e97" + }, + { + "author": "won-openai", + "committed_at": "2026-06-11T16:02:28Z", + "message": "fix image environment test arguments", + "sha": "526c3e8565b00151ee29f620978650f07610e9ee", + "url": "https://github.com/openai/codex/commit/526c3e8565b00151ee29f620978650f07610e9ee" + }, + { + "author": "won-openai", + "committed_at": "2026-06-11T16:28:04Z", + "message": "fix test", + "sha": "6467362a57ce5befcf5895c4df10d5bae82a92e6", + "url": "https://github.com/openai/codex/commit/6467362a57ce5befcf5895c4df10d5bae82a92e6" + }, + { + "author": "won-openai", + "committed_at": "2026-06-11T17:41:36Z", + "message": "address image sandbox review feedback", + "sha": "2feef6f6c77bcd8140bc126377410bcdf3b89915", + "url": "https://github.com/openai/codex/commit/2feef6f6c77bcd8140bc126377410bcdf3b89915" + }, + { + "author": "won-openai", + "committed_at": "2026-06-11T18:00:54Z", + "message": "move extension sandbox coverage to core suite", + "sha": "18126046137392d29cb21f2f734160b52cfa1ea5", + "url": "https://github.com/openai/codex/commit/18126046137392d29cb21f2f734160b52cfa1ea5" + }, + { + "author": "won-openai", + "committed_at": "2026-06-11T18:44:51Z", + "message": "respecting additional permissions?", + "sha": "f8ab6ef5dc39035114a695d5dc5952ff1aad7fa6", + "url": "https://github.com/openai/codex/commit/f8ab6ef5dc39035114a695d5dc5952ff1aad7fa6" + }, + { + "author": "won-openai", + "committed_at": "2026-06-11T19:13:16Z", + "message": "fix test output", + "sha": "03f5b38cf9b4d10eb8d9f1a94ddd0d503aacd257", + "url": "https://github.com/openai/codex/commit/03f5b38cf9b4d10eb8d9f1a94ddd0d503aacd257" + }, + { + "author": "won-openai", + "committed_at": "2026-06-11T19:35:02Z", + "message": "CODEX STOP PUTTING WEIRD STUFF IN MY TEST", + "sha": "59544fbc520493779b297162c114ee185392c521", + "url": "https://github.com/openai/codex/commit/59544fbc520493779b297162c114ee185392c521" + } + ], + "default_branch": "main", + "docs_refs": [], + "examples_refs": [], + "extracted_flags": [ + "--tests", + "CODEX", + "STOP", + "PUTTING", + "WEIRD", + "STUFF", + "TEST", + "TINY_PNG_BYTES", + "TINY_PNG_DATA_URL", + "POST", + "IMAGE_GEN_NAMESPACE", + "IMAGEGEN_TOOL_NAME", + "MAX_EDIT_IMAGES" + ], + "files": [ + { + "additions": 2, + "deletions": 0, + "patch_excerpt": "@@ -3115,6 +3115,7 @@ dependencies = [\n \"schemars 0.8.22\",\n \"serde\",\n \"serde_json\",\n+ \"tokio\",\n ]\n \n [[package]]\n@@ -3916,6 +3917,7 @@ dependencies = [\n \"codex-app-server-protocol\",\n \"codex-code-mode\",\n \"codex-features\",\n+ \"codex-file-system\",\n \"codex-protocol\",\n \"codex-utils-absolute-path\",\n \"codex-utils-cargo-bin\",", + "path": "codex-rs/Cargo.lock", + "status": "modified" + }, + { + "additions": 2, + "deletions": 5, + "patch_excerpt": "@@ -34,6 +34,7 @@ const TINY_PNG_BYTES: &[u8] = &[\n 0, 0, 31, 21, 196, 137, 0, 0, 0, 11, 73, 68, 65, 84, 120, 156, 99, 96, 0, 2, 0, 0, 5, 0, 1,\n 122, 94, 171, 63, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130,\n ];\n+const TINY_PNG_DATA_URL: &str = \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVR4nGNgAAIAAAUAAXpeqz8AAAAASUVORK5CYII=\";\n \n #[derive(Clone, Copy)]\n enum ImagegenTestMode {\n@@ -170,11 +171,7 @@ async fn standalone_image_edit_uses_attached_model_visible_image() -> Result<()>\n })\n .await?;\n assert_eq!(edit_request[\"prompt\"], \"add a red hat\");\n- assert!(\n- edit_request[\"images\"][0][\"image_url\"]\n- .as_str()\n- .is_some_and(|image_url| image_url.starts_with(\"data:image/png;base64,\"))\n- );\n+ assert_eq!(edit_request[\"images\"][0][\"image_url\"], TINY_PNG_DATA_URL);\n \n Ok(())\n }", + "path": "codex-rs/app-server/tests/suite/v2/imagegen_extension.rs", + "status": "modified" + }, + { + "additions": 24, + "deletions": 0, + "patch_excerpt": "@@ -5,18 +5,21 @@ use codex_protocol::items::TurnItem;\n use codex_tools::ConversationHistory;\n use codex_tools::ExtensionTurnItem;\n use codex_tools::ToolCall as ExtensionToolCall;\n+use codex_tools::ToolEnvironment;\n use codex_tools::ToolName;\n use codex_tools::ToolSearchInfo;\n use codex_tools::ToolSpec;\n use codex_tools::TurnItemEmissionFuture;\n use codex_tools::TurnItemEmitter;\n \n+use crate::sandboxing::SandboxPermissions;\n use crate::session::session::Session;\n use crate::session::turn_context::TurnContext;\n use crate::stream_events_utils::TurnItemContributorPolicy;\n use crate::stream_events_utils::finalize_turn_item;\n use crate::tools::context::ToolInvocation;\n use crate::tools::context::ToolPayload;\n+use crate::tools::handlers::apply_granted_turn_permissions;\n use crate::tools::registry::CoreToolRuntime;\n use crate::tools::registry::ToolExecutor;\n \n@@ -109,6 +112,26 @@ impl TurnItemE...", + "path": "codex-rs/core/src/tools/handlers/extension_tools.rs", + "status": "modified" + }, + { + "additions": 305, + "deletions": 0, + "patch_excerpt": "@@ -0,0 +1,305 @@\n+use std::sync::Arc;\n+\n+use anyhow::Context;\n+use anyhow::Result;\n+use codex_core::config::Config;\n+use codex_core::config::Constrained;\n+use codex_extension_api::ExtensionRegistry;\n+use codex_extension_api::ExtensionRegistryBuilder;\n+use codex_features::Feature;\n+use codex_image_generation_extension::install as install_image_generation_extension;\n+use codex_login::CodexAuth;\n+use codex_protocol::config_types::ApprovalsReviewer;\n+use codex_protocol::config_types::WebSearchMode;\n+use codex_protocol::models::FileSystemPermissions;\n+use codex_protocol::models::PermissionProfile;\n+use codex_protocol::openai_models::InputModality;\n+use codex_protocol::permissions::FileSystemAccessMode;\n+use codex_protocol::permissions::FileSystemPath;\n+use codex_protocol::permissions::FileSystemSandboxEntry;\n+use codex_protocol::permissions::FileSystemSandboxPolicy;\n+use codex_protocol::perm...", + "path": "codex-rs/core/tests/suite/extension_sandbox.rs", + "status": "added" + }, + { + "additions": 2, + "deletions": 0, + "patch_excerpt": "@@ -51,6 +51,8 @@ mod compact_resume_fork;\n mod deprecation_notice;\n mod exec;\n mod exec_policy;\n+#[cfg(not(target_os = \"windows\"))]\n+mod extension_sandbox;\n mod fork_thread;\n #[cfg(not(target_os = \"windows\"))]\n mod guardian_review;", + "path": "codex-rs/core/tests/suite/mod.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -19,6 +19,7 @@ pub use codex_tools::JsonToolOutput;\n pub use codex_tools::NoopTurnItemEmitter;\n pub use codex_tools::ResponsesApiTool;\n pub use codex_tools::ToolCall;\n+pub use codex_tools::ToolEnvironment;\n pub use codex_tools::ToolExecutor;\n pub use codex_tools::ToolExecutorFuture;\n pub use codex_tools::ToolName;", + "path": "codex-rs/ext/extension-api/src/lib.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -1341,6 +1341,7 @@ fn tool_call(tool_name: &str, call_id: &str, arguments: serde_json::Value) -> To\n truncation_policy: TruncationPolicy::Bytes(1024),\n conversation_history: codex_extension_api::ConversationHistory::default(),\n turn_item_emitter: Arc::new(NoopTurnItemEmitter),\n+ environments: Vec::new(),\n payload: ToolPayload::Function {\n arguments: arguments.to_string(),\n },", + "path": "codex-rs/ext/goal/tests/goal_extension_backend.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -30,3 +30,4 @@ serde_json = { workspace = true }\n \n [dev-dependencies]\n pretty_assertions = { workspace = true }\n+tokio = { workspace = true, features = [\"macros\", \"rt\"] }", + "path": "codex-rs/ext/image-generation/Cargo.toml", + "status": "modified" + }, + { + "additions": 27, + "deletions": 17, + "patch_excerpt": "@@ -21,7 +21,7 @@ use super::GeneratedImageOutput;\n use super::ImageRequest;\n use super::ImagegenArgs;\n use super::imagegen_tool_spec;\n-use super::request_for_args;\n+use super::request_for_call_args;\n use crate::IMAGE_GEN_NAMESPACE;\n use crate::IMAGEGEN_TOOL_NAME;\n \n@@ -37,17 +37,19 @@ fn uses_reserved_image_gen_namespace() {\n assert_eq!(function.name, IMAGEGEN_TOOL_NAME);\n }\n \n-#[test]\n-fn omitted_references_generate_with_fixed_defaults() {\n+#[tokio::test]\n+async fn omitted_references_generate_with_fixed_defaults() {\n assert_eq!(\n- request_for_args(\n+ request_for_call_args(\n &ImagegenArgs {\n prompt: \"paint a moonlit lake\".to_string(),\n referenced_image_paths: None,\n num_last_images_to_include: None,\n },\n- &[]\n+ &[],\n+ &[],\n )\n+ .await\n .ex...", + "path": "codex-rs/ext/image-generation/src/tests.rs", + "status": "modified" + }, + { + "additions": 32, + "deletions": 12, + "patch_excerpt": "@@ -10,6 +10,7 @@ use codex_core::image_generation_artifact_path;\n use codex_extension_api::ExtensionTurnItem;\n use codex_extension_api::FunctionCallError;\n use codex_extension_api::ToolCall;\n+use codex_extension_api::ToolEnvironment;\n use codex_extension_api::ToolExecutor;\n use codex_extension_api::ToolName;\n use codex_extension_api::ToolOutput;\n@@ -103,7 +104,9 @@ impl ToolExecutor for ImageGenerationTool {\n impl ImageGenerationTool {\n async fn handle_call(&self, call: ToolCall) -> Result, FunctionCallError> {\n let args = parse_args(&call)?;\n- let request = request_for_args(&args, call.conversation_history.items())?;\n+ let request =\n+ request_for_call_args(&args, call.conversation_history.items(), &call.environments)\n+ .await?;\n call.turn_item_emitter\n .emit_started(ExtensionTurnItem::...", + "path": "codex-rs/ext/image-generation/src/tool.rs", + "status": "modified" + }, + { + "additions": 6, + "deletions": 0, + "patch_excerpt": "@@ -215,6 +215,7 @@ async fn add_ad_hoc_note_tool_creates_note_file() {\n truncation_policy: TruncationPolicy::Bytes(1024),\n conversation_history: codex_extension_api::ConversationHistory::default(),\n turn_item_emitter: Arc::new(NoopTurnItemEmitter),\n+ environments: Vec::new(),\n payload: payload.clone(),\n })\n .await\n@@ -258,6 +259,7 @@ async fn add_ad_hoc_note_tool_rejects_paths_as_filenames() {\n truncation_policy: TruncationPolicy::Bytes(1024),\n conversation_history: codex_extension_api::ConversationHistory::default(),\n turn_item_emitter: Arc::new(NoopTurnItemEmitter),\n+ environments: Vec::new(),\n payload,\n })\n .await;\n@@ -302,6 +304,7 @@ async fn read_tool_reads_memory_file() {\n truncation_policy: TruncationPolicy::Bytes(1024),...", + "path": "codex-rs/ext/memories/src/tests.rs", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -11,6 +11,7 @@ workspace = true\n codex-app-server-protocol = { workspace = true }\n codex-code-mode = { workspace = true }\n codex-features = { workspace = true }\n+codex-file-system = { workspace = true }\n codex-protocol = { workspace = true }\n codex-utils-absolute-path = { workspace = true }\n codex-utils-output-truncation = { workspace = true }", + "path": "codex-rs/tools/Cargo.toml", + "status": "modified" + }, + { + "additions": 1, + "deletions": 0, + "patch_excerpt": "@@ -66,6 +66,7 @@ pub use tool_call::ConversationHistory;\n pub use tool_call::ExtensionTurnItem;\n pub use tool_call::NoopTurnItemEmitter;\n pub use tool_call::ToolCall;\n+pub use tool_call::ToolEnvironment;\n pub use tool_call::TurnItemEmissionFuture;\n pub use tool_call::TurnItemEmitter;\n pub use tool_config::ShellCommandBackendConfig;", + "path": "codex-rs/tools/src/lib.rs", + "status": "modified" + }, + { + "additions": 18, + "deletions": 0, + "patch_excerpt": "@@ -1,9 +1,12 @@\n use crate::FunctionCallError;\n use crate::ToolName;\n use crate::ToolPayload;\n+use codex_file_system::ExecutorFileSystem;\n+use codex_file_system::FileSystemSandboxContext;\n use codex_protocol::items::ImageGenerationItem;\n use codex_protocol::items::WebSearchItem;\n use codex_protocol::models::ResponseItem;\n+use codex_utils_absolute_path::AbsolutePathBuf;\n use codex_utils_output_truncation::TruncationPolicy;\n use std::future::Future;\n use std::pin::Pin;\n@@ -49,6 +52,19 @@ pub trait TurnItemEmitter: Send + Sync {\n fn emit_completed<'a>(&'a self, item: ExtensionTurnItem) -> TurnItemEmissionFuture<'a>;\n }\n \n+/// Host-owned turn environment summary visible to extension tools.\n+#[derive(Clone)]\n+pub struct ToolEnvironment {\n+ /// Stable host environment id used to route executor-scoped capabilities.\n+ pub environment_id: String,\n+ /// Effective working directory fo...", + "path": "codex-rs/tools/src/tool_call.rs", + "status": "modified" + } + ], + "linked_issues": [], + "notes": [ + "Built from GitHub pull-request, commits, files, and repo endpoints." + ], + "primary_pr": { + "body": "## Why\r\n\r\nImage generation used `std::fs::read` for referenced image paths, which did not support environment-backed filesystems or their sandbox context.\r\n\r\n## What changed\r\n\r\n- Expose optional turn environments to extension tool calls.\r\n- Include each environment’s ID, working directory, filesystem, and sandbox context.\r\n- Read referenced images through the selected environment filesystem.\r\n- Keep sandbox usage at the extension call site so extensions can choose the appropriate access mode.\r\n- Consolidate image request construction into one async function.\r\n- Add coverage for successful environment reads and read failures.\r\n\r\n## Validation\r\n\r\n- `cargo check -p codex-image-generation-extension --tests`\r\n- `just fmt`\r\n- `just bazel-lock-update`\r\n- `just bazel-lock-check`\r\n\r\n`just test -p codex-image-generation-extension` could not complete because the build exhausted available disk space.", + "labels": [], + "merged_at": "2026-06-11T23:32:52Z", + "number": 27498, + "state": "merged", + "title": "Route image extension reads through turn environments v2", + "url": "https://github.com/openai/codex/pull/27498" + }, + "repo": "openai/codex", + "schema": "github_change_bundle/v1" +} diff --git a/artifacts/github/impact/openai-codex-pr-27318.json b/artifacts/github/impact/openai-codex-pr-27318.json new file mode 100644 index 000000000..291e95264 --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-27318.json @@ -0,0 +1,45 @@ +{ + "candidate_followups": [ + "Audit Decodex retained-lane replay and recovery assumptions that treat thread-store append inputs as already canonical.", + "Keep any Decodex store projections tolerant of raw rollout items and explicit metadata updates.", + "Use the review as release-rollup context for Codex thread history and resume semantics." + ], + "caveats": [ + "No direct user-facing command or protocol method changed in the reviewed bundle.", + "The main risk is source and persistence-boundary drift for thread history consumers." + ], + "confidence": "confirmed", + "control_plane_impact": "compat_risk", + "evidence": [ + "The ThreadStore append contract now says implementations receive raw rollout items and apply the persistence policy themselves.", + "Local and in-memory stores call `persisted_rollout_items` before writing durable replay history.", + "LiveThread and Session wiring move creation, resume, and append handling through the store-owned projection path.", + "The source-backed review is recorded at `artifacts/github/reviews/openai-codex-pr-27318.review.json`." + ], + "observed_change": "Codex moved rollout persistence-policy projection into ThreadStore implementations so live stores receive raw append items and own canonical replay writes.", + "public_signal_decision": "defer", + "publisher_angle": "operator_impact", + "repo": "openai/codex", + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-27318", + "social_notes": [ + "Potential future operator note if several thread-history changes are rolled up together.", + "Avoid presenting this as a standalone user feature." + ], + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-11T23:24:13Z", + "title": "[codex] Move persistence policy application into ThreadStore", + "url": "https://github.com/openai/codex/pull/27318" + }, + { + "kind": "pull_request", + "meta": "artifacts/github/reviews/openai-codex-pr-27318.review.json", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/27318" + } + ] + } +} diff --git a/artifacts/github/impact/openai-codex-pr-27445.json b/artifacts/github/impact/openai-codex-pr-27445.json new file mode 100644 index 000000000..6e83baa2b --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-27445.json @@ -0,0 +1,46 @@ +{ + "candidate_followups": [ + "Update Decodex remote-control callers to use `ephemeral: true` when they need process-only behavior.", + "Audit operator documentation for any statement that remoteControl/enable or disable is process-only.", + "Track state migration behavior for persisted remote_control_enabled enrollment values." + ], + "caveats": [ + "The remote-control methods are still experimental upstream.", + "Clients that omit params remain schema-valid, but their default persistence semantics changed." + ], + "confidence": "confirmed", + "control_plane_impact": "compat_risk", + "evidence": [ + "remoteControl enable and disable params changed from undefined to nullable param objects with optional `ephemeral`.", + "RemoteControlDesiredState separates persisted enabled/disabled state from runtime-only enablement.", + "A state migration adds `remote_control_enabled` to remote-control enrollments.", + "Daemon and app-server tests cover durable enable, durable disable, and ephemeral enable behavior.", + "The source-backed review is recorded at `artifacts/github/reviews/openai-codex-pr-27445.review.json`." + ], + "observed_change": "Codex remote-control enable and disable requests now persist desired state by default while retaining `ephemeral: true` for runtime-only callers.", + "public_signal_decision": "publish", + "publisher_angle": "operator_impact", + "repo": "openai/codex", + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-27445", + "social_notes": [ + "Frame as a Control Plane compatibility note for app-server remote-control clients.", + "Emphasize that `ephemeral: true` is the runtime-only escape hatch." + ], + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-12T04:28:53Z", + "title": "feat(app-server): persist remote-control desired state", + "url": "https://github.com/openai/codex/pull/27445" + }, + { + "kind": "pull_request", + "meta": "artifacts/github/reviews/openai-codex-pr-27445.review.json", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/27445" + } + ] + } +} diff --git a/artifacts/github/impact/openai-codex-pr-27475.json b/artifacts/github/impact/openai-codex-pr-27475.json new file mode 100644 index 000000000..134e9984a --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-27475.json @@ -0,0 +1,45 @@ +{ + "candidate_followups": [ + "Watch for downstream source patches that still expect async_trait-generated trait methods.", + "Treat this as release-rollup maintenance context rather than a standalone Publisher candidate.", + "Note the rand 0.8.6 security-related bump if dependency provenance is audited later." + ], + "caveats": [ + "No direct app-server protocol or end-user workflow change was identified.", + "Compatibility impact is mainly for source-level integrations and fork maintenance." + ], + "confidence": "confirmed", + "control_plane_impact": "watch", + "evidence": [ + "The workspace `async-trait` dependency was removed from first-party crates.", + "Several first-party traits now return native `impl Future + Send` or explicit boxed Send future aliases.", + "cargo-deny policy now limits async-trait to remaining transitive wrapper crates.", + "rand was updated from 0.8.5 to 0.8.6.", + "The source-backed review is recorded at `artifacts/github/reviews/openai-codex-pr-27475.review.json`." + ], + "observed_change": "Codex removed direct first-party async-trait usage by moving first-party async traits to explicit Send future signatures and tightening dependency policy.", + "public_signal_decision": "skip", + "publisher_angle": "none", + "repo": "openai/codex", + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-27475", + "social_notes": [ + "No social candidate: the source evidence is maintenance and compatibility oriented, without a concrete user-facing path." + ], + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-12T01:16:39Z", + "title": "[codex] Remove async_trait from first-party code", + "url": "https://github.com/openai/codex/pull/27475" + }, + { + "kind": "pull_request", + "meta": "artifacts/github/reviews/openai-codex-pr-27475.review.json", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/27475" + } + ] + } +} diff --git a/artifacts/github/impact/openai-codex-pr-27498.json b/artifacts/github/impact/openai-codex-pr-27498.json new file mode 100644 index 000000000..df65654cf --- /dev/null +++ b/artifacts/github/impact/openai-codex-pr-27498.json @@ -0,0 +1,46 @@ +{ + "candidate_followups": [ + "Check Decodex extension execution for ToolCall construction sites that need to pass turn environments.", + "Prefer environment-backed file reads for media references in sandboxed or remote filesystem contexts.", + "Keep image-generation caveats explicit where full test execution was disk-space limited upstream." + ], + "caveats": [ + "The upstream PR reports disk-space exhaustion for one full image-generation test command.", + "The behavior depends on the selected turn environment exposing the referenced file." + ], + "confidence": "confirmed", + "control_plane_impact": "compat_risk", + "evidence": [ + "ToolCall now carries `ToolEnvironment` entries with filesystem and sandbox context.", + "Core extension execution passes turn environments into extension calls and applies granted permissions.", + "The image-generation extension reads referenced images via `request_for_call_args(..., &call.environments).await`.", + "Sandbox tests cover successful environment reads and read failures.", + "The source-backed review is recorded at `artifacts/github/reviews/openai-codex-pr-27498.review.json`." + ], + "observed_change": "Codex image-generation extension reads referenced image paths through the selected turn environment filesystem instead of plain local filesystem reads.", + "public_signal_decision": "publish", + "publisher_angle": "practical_explainer", + "repo": "openai/codex", + "schema": "upstream_impact/v1", + "slug": "openai-codex-pr-27498", + "social_notes": [ + "Frame this as safer and more capable referenced-image path handling.", + "Do not imply image generation model behavior changed; this is file access and environment routing." + ], + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-11T23:32:52Z", + "title": "Route image extension reads through turn environments v2", + "url": "https://github.com/openai/codex/pull/27498" + }, + { + "kind": "pull_request", + "meta": "artifacts/github/reviews/openai-codex-pr-27498.review.json", + "title": "Source-backed Decodex upstream review", + "url": "https://github.com/openai/codex/pull/27498" + } + ] + } +} diff --git a/artifacts/github/review-queue/openai-codex-latest.json b/artifacts/github/review-queue/openai-codex-latest.json index dc8705fec..31a0e1bbc 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": 21, - "high": 11, - "low": 0, - "normal": 8, + "critical": 22, + "high": 10, + "low": 1, + "normal": 7, "published_subjects_seen": 0, "recent_commits_scanned": 40, "subjects_queued": 40 }, - "generated_at": "2026-06-12T14:05:30.421011Z", + "generated_at": "2026-06-12T20:06:37.368497Z", "repo": "openai/codex", "schema": "upstream_review_queue/v1", "source": { @@ -17,396 +17,6 @@ "signals_dir": "site/src/content/signals" }, "subjects": [ - { - "attention_flags": [ - "auth_account", - "deprecated_removed", - "new_feature", - "protocol_change", - "release_packaging" - ], - "changed_file_count": 16, - "commit_shas": [ - "2f6191ea633cd0a58580c484cc37d88191787385" - ], - "committed_at": "2026-06-11T17:34:41Z", - "next_step": "ai_review_required", - "pr_number": 27420, - "pr_url": "https://github.com/openai/codex/pull/27420", - "review_priority": "critical", - "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, release_packaging.", - "sample_paths": [ - "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json", - "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json", - "codex-rs/app-server-protocol/schema/json/v2/PluginInstallResponse.json", - "codex-rs/app-server-protocol/schema/json/v2/PluginReadResponse.json", - "codex-rs/app-server-protocol/schema/typescript/v2/AppSummary.ts", - "codex-rs/app-server-protocol/schema/typescript/v2/AppTemplateSummary.ts", - "codex-rs/app-server-protocol/src/protocol/v2/apps.rs", - "codex-rs/app-server-protocol/src/protocol/v2/plugin.rs", - "codex-rs/app-server/src/request_processors/plugins.rs", - "codex-rs/app-server/tests/suite/v2/plugin_install.rs", - "codex-rs/app-server/tests/suite/v2/plugin_read.rs", - "codex-rs/core-plugins/src/loader.rs" - ], - "source_state": "merged", - "subject_id": "27420", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "cli_tui", - "mcp_plugins", - "release_packaging", - "tests_ci" - ], - "title": "[codex] Propagate plugin app categories", - "url": "https://github.com/openai/codex/pull/27420" - }, - { - "attention_flags": [ - "auth_account", - "deprecated_removed", - "new_feature", - "protocol_change" - ], - "changed_file_count": 2, - "commit_shas": [ - "fef2bbfa4c23e6144afa8c2081ca4a44cca082dc" - ], - "committed_at": "2026-06-11T18:20:26Z", - "next_step": "ai_review_required", - "pr_number": 27646, - "pr_url": "https://github.com/openai/codex/pull/27646", - "review_priority": "critical", - "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change.", - "sample_paths": [ - "codex-rs/app-server/src/extensions.rs", - "codex-rs/app-server/tests/suite/v2/mcp_resource.rs" - ], - "source_state": "merged", - "subject_id": "27646", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "mcp_plugins", - "tests_ci" - ], - "title": "feat: disable orchestrator skills for now", - "url": "https://github.com/openai/codex/pull/27646" - }, - { - "attention_flags": [ - "auth_account", - "deprecated_removed", - "new_feature", - "protocol_change", - "security_policy" - ], - "changed_file_count": 5, - "commit_shas": [ - "a8e9807f4a94cf84b288c0c9ce2678788c9d3228" - ], - "committed_at": "2026-06-11T18:26:12Z", - "next_step": "ai_review_required", - "pr_number": 27433, - "pr_url": "https://github.com/openai/codex/pull/27433", - "review_priority": "critical", - "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, security_policy.", - "sample_paths": [ - "codex-rs/exec-server/src/environment_path.rs", - "codex-rs/exec-server/src/lib.rs", - "codex-rs/ext/skills/src/catalog.rs", - "codex-rs/ext/skills/src/provider/executor.rs", - "codex-rs/ext/skills/tests/executor_file_system_authority.rs" - ], - "source_state": "merged", - "subject_id": "27433", - "subject_kind": "pr", - "surface_hints": [ - "auth_accounts", - "model_provider", - "tests_ci" - ], - "title": "[codex] remove EnvironmentPathRef", - "url": "https://github.com/openai/codex/pull/27433" - }, - { - "attention_flags": [ - "auth_account", - "deprecated_removed", - "new_feature", - "protocol_change", - "security_policy" - ], - "changed_file_count": 52, - "commit_shas": [ - "32d2f04abebfd51a0062e3b68710bd60b5a51c98" - ], - "committed_at": "2026-06-11T18:44:18Z", - "next_step": "ai_review_required", - "pr_number": 27424, - "pr_url": "https://github.com/openai/codex/pull/27424", - "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/Cargo.toml", - "codex-rs/app-server/Cargo.toml", - "codex-rs/app-server/src/request_processors/fs_processor.rs", - "codex-rs/apply-patch/Cargo.toml", - "codex-rs/apply-patch/src/invocation.rs", - "codex-rs/apply-patch/src/lib.rs", - "codex-rs/config/Cargo.toml", - "codex-rs/config/src/loader/layer_io.rs", - "codex-rs/config/src/loader/mod.rs", - "codex-rs/config/src/loader/tests.rs", - "codex-rs/core-skills/Cargo.toml" - ], - "source_state": "merged", - "subject_id": "27424", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "auth_accounts", - "cli_tui", - "config_hooks", - "mcp_plugins", - "model_provider", - "sandbox_permissions", - "tests_ci" - ], - "title": "[codex] migrate ExecutorFileSystem paths to PathUri", - "url": "https://github.com/openai/codex/pull/27424" - }, - { - "attention_flags": [ - "auth_account", - "breaking_change", - "deprecated_removed", - "new_feature", - "protocol_change", - "release_packaging", - "security_policy" - ], - "changed_file_count": 49, - "commit_shas": [ - "86c3be87bb3b56f7b00b1ad678f7749d5ccf5e0d", - "6058bbf755e4b659ad0a45021911e8d6342b1519", - "db55f399a2d96fb0afee96daa5cc4a2d86efad8a", - "c75787f5e79a31b4f7702e68b34070e1a13c4124", - "ae7666463b7c59a22afaa97c38064eea342b4b1f", - "9d056247c33e1b4380c768e9b8c7b0cc45355285", - "5ab337bd440e284e5caf2cc50760026c98362c06", - "991be42cc3bb7ba7a60880c7a6af4d6d55bd3b57", - "56e017522bc978db21118184d6217425883f37e9", - "802d4ca0df4f6d9124299fae252d6186fef49413", - "1ce912ed71c8284c97b01ea7dfcc566ea32b4a36", - "02f04f2ad6655e71067b68df88129ee5b20fdf80", - "493e0057247fd619b0fabaed742801715fbe9c09", - "8aca78feb7f73cb5d55f762ead36060b4020c71b", - "922a7f27cccdb0dbfc322179dd51da27a2085e72" - ], - "committed_at": "2026-06-11T19:28:47Z", - "next_step": "ai_review_required", - "pr_number": 27101, - "pr_url": "https://github.com/openai/codex/pull/27101", - "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/Cargo.lock", - "codex-rs/Cargo.toml", - "codex-rs/app-server/Cargo.toml", - "codex-rs/app-server/src/mcp_refresh.rs", - "codex-rs/app-server/src/message_processor.rs", - "codex-rs/app-server/tests/suite/v2/thread_start.rs", - "codex-rs/cli/Cargo.toml", - "codex-rs/cli/src/main.rs", - "codex-rs/codex-home/BUILD.bazel", - "codex-rs/codex-home/Cargo.toml", - "codex-rs/codex-home/src/instructions/mod.rs", - "codex-rs/codex-home/src/instructions/tests.rs" - ], - "source_state": "merged", - "subject_id": "27101", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "cli_tui", - "config_hooks", - "mcp_plugins", - "tests_ci" - ], - "title": "[codex] Load user instructions through an injected provider", - "url": "https://github.com/openai/codex/pull/27101" - }, - { - "attention_flags": [ - "auth_account", - "breaking_change", - "deprecated_removed", - "new_feature", - "protocol_change", - "security_policy" - ], - "changed_file_count": 14, - "commit_shas": [ - "a59cb23505a814d56fa756fa1dd62d9141446fe4", - "14a0e947fd75a0948baa5e0d10287fdfb1c79265", - "a0a3850c9ef28a3417e02d9850d4204a183ec54f" - ], - "committed_at": "2026-06-11T19:54:52Z", - "next_step": "ai_review_required", - "pr_number": 27634, - "pr_url": "https://github.com/openai/codex/pull/27634", - "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/codex-mcp/src/catalog.rs", - "codex-rs/codex-mcp/src/catalog_tests.rs", - "codex-rs/codex-mcp/src/lib.rs", - "codex-rs/codex-mcp/src/mcp/mod.rs", - "codex-rs/codex-mcp/src/mcp/mod_tests.rs", - "codex-rs/core/src/config/config_tests.rs", - "codex-rs/core/src/config/mod.rs", - "codex-rs/core/src/connectors.rs", - "codex-rs/core/src/mcp.rs", - "codex-rs/core/src/session/mcp.rs", - "codex-rs/core/src/session/session.rs", - "codex-rs/ext/extension-api/src/contributors.rs" - ], - "source_state": "merged", - "subject_id": "27634", - "subject_kind": "pr", - "surface_hints": [ - "config_hooks", - "mcp_plugins", - "tests_ci" - ], - "title": "Resolve MCP server registrations through a catalog", - "url": "https://github.com/openai/codex/pull/27634" - }, - { - "attention_flags": [ - "auth_account", - "deprecated_removed", - "new_feature", - "protocol_change", - "security_policy" - ], - "changed_file_count": 27, - "commit_shas": [ - "07499eb7263dc91e44e04ba86a3704c758b80860", - "3e9298af57a7c3057ded958ac4d8a630919523ac", - "2637659fc3571c1e31136107285db749400a9082" - ], - "committed_at": "2026-06-11T20:42:09Z", - "next_step": "ai_review_required", - "pr_number": 27122, - "pr_url": "https://github.com/openai/codex/pull/27122", - "review_priority": "critical", - "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, security_policy.", - "sample_paths": [ - "codex-rs/app-server-protocol/src/protocol/v2/turn.rs", - "codex-rs/app-server/tests/suite/v2/client_metadata.rs", - "codex-rs/core/src/client.rs", - "codex-rs/core/src/client_tests.rs", - "codex-rs/core/src/compact.rs", - "codex-rs/core/src/compact_remote.rs", - "codex-rs/core/src/compact_remote_v2.rs", - "codex-rs/core/src/lib.rs", - "codex-rs/core/src/responses_metadata.rs", - "codex-rs/core/src/session/review.rs", - "codex-rs/core/src/session/session.rs", - "codex-rs/core/src/session/tests.rs" - ], - "source_state": "merged", - "subject_id": "27122", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "auth_accounts", - "cli_tui", - "tests_ci" - ], - "title": "core: Consolidate Responses API Codex metadata", - "url": "https://github.com/openai/codex/pull/27122" - }, - { - "attention_flags": [ - "breaking_change", - "deprecated_removed", - "protocol_change", - "security_policy" - ], - "changed_file_count": 7, - "commit_shas": [ - "15a21e11f315c88a65b197f34ad84eef9475aa9b", - "eafb482e8d0e8d723794462bc543798272031b9f", - "f69b2d1e2a1e1c6db6e2aaf2a10ed2aca461a289", - "9a8ae04cb9831aebe459f0e45b492cd6bbfb9dc9", - "8eb6f5af6fcdd069dbb0b31d6fd62f91900d9443" - ], - "committed_at": "2026-06-11T22:09:12Z", - "next_step": "ai_review_required", - "pr_number": 27653, - "pr_url": "https://github.com/openai/codex/pull/27653", - "review_priority": "critical", - "review_reason": "Needs AI review for breaking_change, deprecated_removed, protocol_change, security_policy.", - "sample_paths": [ - "codex-rs/exec-server/README.md", - "codex-rs/exec-server/src/fs_helper.rs", - "codex-rs/exec-server/src/protocol.rs", - "codex-rs/exec-server/src/remote_file_system.rs", - "codex-rs/exec-server/src/remote_file_system_path_uri_tests.rs", - "codex-rs/exec-server/src/sandboxed_file_system.rs", - "codex-rs/exec-server/src/server/file_system_handler.rs" - ], - "source_state": "merged", - "subject_id": "27653", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "docs_examples", - "sandbox_permissions", - "tests_ci" - ], - "title": "[codex] migrate exec-server filesystem protocol to PathUri", - "url": "https://github.com/openai/codex/pull/27653" - }, - { - "attention_flags": [ - "breaking_change", - "deprecated_removed", - "protocol_change" - ], - "changed_file_count": 6, - "commit_shas": [ - "fe16ca355a264215ee5b05fa9afc5dd7f5e83c65" - ], - "committed_at": "2026-06-11T22:48:53Z", - "next_step": "ai_review_required", - "pr_number": 27700, - "pr_url": "https://github.com/openai/codex/pull/27700", - "review_priority": "critical", - "review_reason": "Needs AI review for breaking_change, deprecated_removed, protocol_change.", - "sample_paths": [ - "codex-rs/exec-server/src/client.rs", - "codex-rs/exec-server/src/lib.rs", - "codex-rs/exec-server/src/protocol.rs", - "codex-rs/exec-server/src/server/file_system_handler.rs", - "codex-rs/exec-server/src/server/handler.rs", - "codex-rs/exec-server/src/server/registry.rs" - ], - "source_state": "merged", - "subject_id": "27700", - "subject_kind": "pr", - "surface_hints": [ - "app_server_protocol", - "cli_tui" - ], - "title": "Remove fs/join and fs/parent from exec-server protocol", - "url": "https://github.com/openai/codex/pull/27700" - }, { "attention_flags": [ "deprecated_removed", @@ -988,165 +598,432 @@ { "attention_flags": [ "auth_account", + "breaking_change", "new_feature", "protocol_change" ], - "changed_file_count": 3, + "changed_file_count": 13, "commit_shas": [ - "e14573d583899a66897d439c1561e655aa1141aa" + "c21e3e96455cdee04da62579c680de6b4bbffe8d" ], - "committed_at": "2026-06-11T21:17:37Z", + "committed_at": "2026-06-12T14:19:17Z", "next_step": "ai_review_required", - "pr_number": 27450, - "pr_url": "https://github.com/openai/codex/pull/27450", - "review_priority": "high", - "review_reason": "Needs AI review for auth_account, new_feature, protocol_change.", + "pr_number": 27703, + "pr_url": "https://github.com/openai/codex/pull/27703", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, breaking_change, new_feature, protocol_change.", "sample_paths": [ - "codex-rs/cli/src/login.rs", - "codex-rs/login/src/auth/auth_tests.rs", - "codex-rs/login/src/auth/manager.rs" + "codex-rs/tui/src/app_event.rs", + "codex-rs/tui/src/app_server_session.rs", + "codex-rs/tui/src/external_agent_config_migration.rs", + "codex-rs/tui/src/external_agent_config_migration/render.rs", + "codex-rs/tui/src/external_agent_config_migration_flow.rs", + "codex-rs/tui/src/slash_command.rs", + "codex-rs/tui/src/snapshots/codex_tui__external_agent_config_migration__tests__external_agent_config_migration_customize.snap", + "codex-rs/tui/src/snapshots/codex_tui__external_agent_config_migration__tests__external_agent_config_migration_customize_action.snap", + "codex-rs/tui/src/snapshots/codex_tui__external_agent_config_migration__tests__external_agent_config_migration_customize_action_windows.snap", + "codex-rs/tui/src/snapshots/codex_tui__external_agent_config_migration__tests__external_agent_config_migration_customize_windows.snap", + "codex-rs/tui/src/snapshots/codex_tui__external_agent_config_migration__tests__external_agent_config_migration_prompt.snap", + "codex-rs/tui/src/snapshots/codex_tui__external_agent_config_migration__tests__external_agent_config_migration_prompt_windows.snap" ], "source_state": "merged", - "subject_id": "27450", + "subject_id": "27703", + "subject_kind": "pr", + "surface_hints": [ + "app_server_protocol", + "cli_tui", + "config_hooks", + "tests_ci" + ], + "title": "[codex] restore source-specific import copy", + "url": "https://github.com/openai/codex/pull/27703" + }, + { + "attention_flags": [ + "auth_account", + "deprecated_removed", + "protocol_change" + ], + "changed_file_count": 2, + "commit_shas": [ + "7192731641fdaf92db6c3325456c311db1e1fbe8" + ], + "committed_at": "2026-06-12T14:24:08Z", + "next_step": "ai_review_required", + "pr_number": 27879, + "pr_url": "https://github.com/openai/codex/pull/27879", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, deprecated_removed, protocol_change.", + "sample_paths": [ + "codex-rs/login/src/auth/auth_tests.rs", + "codex-rs/login/src/auth/bedrock_api_key_tests.rs" + ], + "source_state": "merged", + "subject_id": "27879", "subject_kind": "pr", "surface_hints": [ "auth_accounts", + "tests_ci" + ], + "title": "fix: serialize auth environment tests", + "url": "https://github.com/openai/codex/pull/27879" + }, + { + "attention_flags": [ + "deprecated_removed", + "release_packaging", + "security_policy" + ], + "changed_file_count": 2, + "commit_shas": [ + "cb142c49ffb7b172a9da1e75854b8e5c0618715d", + "8050d6acbd3f4849f23abe51020d1670f4fb8226", + "b1d8c54465e9bf2a28dd8f845d8abd3949761b09" + ], + "committed_at": "2026-06-12T17:21:00Z", + "next_step": "ai_review_required", + "pr_number": 27901, + "pr_url": "https://github.com/openai/codex/pull/27901", + "review_priority": "critical", + "review_reason": "Needs AI review for deprecated_removed, release_packaging, security_policy.", + "sample_paths": [ + "sdk/python/pyproject.toml", + "sdk/python/tests/test_artifact_workflow_and_binaries.py" + ], + "source_state": "merged", + "subject_id": "27901", + "subject_kind": "pr", + "surface_hints": [ + "config_hooks", + "tests_ci" + ], + "title": "Use uv as Python SDK build backend", + "url": "https://github.com/openai/codex/pull/27901" + }, + { + "attention_flags": [ + "auth_account", + "breaking_change", + "new_feature", + "protocol_change", + "release_packaging", + "security_policy" + ], + "changed_file_count": 22, + "commit_shas": [ + "37efa545e8004b930a496c91c10ccc860937c29d", + "efd9be5adb25da27764e9e5a2221d14356ce7838", + "44dee73a25a44376823a6c3015779f6c476d47af", + "ebad839a70f8719b40fa78586fc4fa5f5e130e4b", + "3a9e2d6f25149e2b2e3fe707ce682b211c007349", + "c8f27780ed88df644693301f7fb79c661a6995d4", + "66a18813f2cded55678c34de157ca9143f8a432b", + "fa3b65a7e43afac7a10f8c052539b133f2d6dd1f" + ], + "committed_at": "2026-06-12T18:11:13Z", + "next_step": "ai_review_required", + "pr_number": 27720, + "pr_url": "https://github.com/openai/codex/pull/27720", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, breaking_change, new_feature, protocol_change, release_packaging, security_policy.", + "sample_paths": [ + "codex-rs/app-server-protocol/schema/json/ClientRequest.json", + "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json", + "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json", + "codex-rs/app-server-protocol/schema/typescript/RealtimeConversationArchitecture.ts", + "codex-rs/app-server-protocol/schema/typescript/index.ts", + "codex-rs/app-server-protocol/src/protocol/common.rs", + "codex-rs/app-server-protocol/src/protocol/v2/realtime.rs", + "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/codex-api/src/endpoint/realtime_call.rs", + "codex-rs/config/src/config_toml.rs" + ], + "source_state": "merged", + "subject_id": "27720", + "subject_kind": "pr", + "surface_hints": [ + "app_server_protocol", "cli_tui", + "config_hooks", "tests_ci" ], - "title": "[codex-rs] enforce PAT workspace restrictions", - "url": "https://github.com/openai/codex/pull/27450" + "title": "realtime: add AVAS architecture override", + "url": "https://github.com/openai/codex/pull/27720" }, { "attention_flags": [ "auth_account", + "breaking_change", + "deprecated_removed", "new_feature", "protocol_change", + "release_packaging", "security_policy" ], - "changed_file_count": 8, + "changed_file_count": 40, "commit_shas": [ - "24f2071d12595ecdbdb1274e3033e80d1008bae6", - "5bcc69e3736702540c73b38112eecbe52daf680c" + "69a5b897facddfdb48dc4cccb173541f5349aa6f", + "db68524fe5280a98ae8a500448d2c7eb46b33164", + "a57dab38147d453e05cd391eed4a3ab83a251f71" ], - "committed_at": "2026-06-11T22:10:29Z", + "committed_at": "2026-06-12T18:38:01Z", "next_step": "ai_review_required", - "pr_number": 27663, - "pr_url": "https://github.com/openai/codex/pull/27663", - "review_priority": "high", - "review_reason": "Needs AI review for auth_account, new_feature, protocol_change, security_policy.", + "pr_number": 27816, + "pr_url": "https://github.com/openai/codex/pull/27816", + "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/core/src/context/token_budget_context.rs", - "codex-rs/core/src/session/mod.rs", - "codex-rs/core/src/tools/handlers/get_context_remaining.rs", - "codex-rs/core/src/tools/handlers/get_context_remaining_spec.rs", - "codex-rs/core/src/tools/spec_plan.rs", - "codex-rs/core/tests/suite/code_mode.rs", - "codex-rs/core/tests/suite/snapshots/all__suite__token_budget__token_budget_new_context_window_tool_full_context.snap", - "codex-rs/core/tests/suite/token_budget.rs" + "codex-rs/Cargo.lock", + "codex-rs/core/src/agents_md.rs", + "codex-rs/core/src/agents_md_tests.rs", + "codex-rs/core/src/context/environment_context.rs", + "codex-rs/core/src/environment_selection.rs", + "codex-rs/core/src/exec.rs", + "codex-rs/core/src/guardian/review_session.rs", + "codex-rs/core/src/sandboxing/mod.rs", + "codex-rs/core/src/session/mcp.rs", + "codex-rs/core/src/session/session.rs", + "codex-rs/core/src/session/tests.rs", + "codex-rs/core/src/session/turn.rs" + ], + "source_state": "merged", + "subject_id": "27816", + "subject_kind": "pr", + "surface_hints": [ + "app_server_protocol", + "config_hooks", + "mcp_plugins", + "sandbox_permissions", + "tests_ci" + ], + "title": "sandboxing: migrate cwd inputs to PathUri", + "url": "https://github.com/openai/codex/pull/27816" + }, + { + "attention_flags": [ + "auth_account", + "deprecated_removed", + "new_feature", + "protocol_change", + "release_packaging" + ], + "changed_file_count": 11, + "commit_shas": [ + "79e6ea4a8182b747e0329082a2b70215a70253b3", + "f63cf1908952d8daed71bcdb63efda76bfa15ef2" + ], + "committed_at": "2026-06-12T18:53:55Z", + "next_step": "ai_review_required", + "pr_number": 27890, + "pr_url": "https://github.com/openai/codex/pull/27890", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, release_packaging.", + "sample_paths": [ + "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json", + "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json", + "codex-rs/app-server-protocol/schema/json/v2/PluginReadResponse.json", + "codex-rs/app-server-protocol/schema/typescript/v2/PluginDetail.ts", + "codex-rs/app-server-protocol/src/protocol/v2/plugin.rs", + "codex-rs/app-server/README.md", + "codex-rs/app-server/src/request_processors/plugins.rs", + "codex-rs/app-server/tests/suite/v2/plugin_read.rs", + "codex-rs/core-plugins/src/remote.rs", + "codex-rs/tui/src/chatwidget/tests/helpers.rs", + "codex-rs/tui/src/chatwidget/tests/popups_and_settings.rs" ], "source_state": "merged", - "subject_id": "27663", + "subject_id": "27890", "subject_kind": "pr", "surface_hints": [ + "app_server_protocol", + "cli_tui", + "config_hooks", + "docs_examples", + "mcp_plugins", + "tests_ci" + ], + "title": "[codex] expose remote plugin share URL", + "url": "https://github.com/openai/codex/pull/27890" + }, + { + "attention_flags": [ + "auth_account", + "deprecated_removed", + "new_feature", + "protocol_change", + "security_policy" + ], + "changed_file_count": 11, + "commit_shas": [ + "138e4eeeeaaeed2d04a74283e13e30124a75bcd1", + "d4e267882417929bfa34d49398f7043f95cddc3c" + ], + "committed_at": "2026-06-12T19:12:08Z", + "next_step": "ai_review_required", + "pr_number": 27927, + "pr_url": "https://github.com/openai/codex/pull/27927", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, security_policy.", + "sample_paths": [ + "codex-rs/core-plugins/src/provider_tests.rs", + "codex-rs/exec-server/src/fs_helper.rs", + "codex-rs/exec-server/src/local_file_system.rs", + "codex-rs/exec-server/src/protocol.rs", + "codex-rs/exec-server/src/remote_file_system.rs", + "codex-rs/exec-server/src/sandboxed_file_system.rs", + "codex-rs/exec-server/src/server/file_system_handler.rs", + "codex-rs/exec-server/tests/file_system/shared.rs", + "codex-rs/exec-server/tests/file_system_unix.rs", + "codex-rs/ext/skills/tests/executor_file_system_authority.rs", + "codex-rs/file-system/src/lib.rs" + ], + "source_state": "merged", + "subject_id": "27927", + "subject_kind": "pr", + "surface_hints": [ + "app_server_protocol", "auth_accounts", + "mcp_plugins", + "model_provider", + "sandbox_permissions", "tests_ci" ], - "title": "Include thread id in token budget context", - "url": "https://github.com/openai/codex/pull/27663" + "title": "[codex] Add size to internal filesystem metadata", + "url": "https://github.com/openai/codex/pull/27927" }, { "attention_flags": [ - "new_feature" + "auth_account", + "breaking_change", + "deprecated_removed", + "new_feature", + "protocol_change", + "security_policy" ], - "changed_file_count": 2, + "changed_file_count": 8, "commit_shas": [ - "88334ad08f5aaa25bcccd8383d5b71ab7f94481b", - "492b77a792d74008f2de14de1a06053c01672848" + "07d66eccd904cd15cd754c43d3f74a72d63a1980", + "3e3379b56006b9e877f5db4ba65009b4ad41c49c" ], - "committed_at": "2026-06-11T22:25:55Z", + "committed_at": "2026-06-12T19:15:21Z", "next_step": "ai_review_required", - "pr_number": 26418, - "pr_url": "https://github.com/openai/codex/pull/26418", - "review_priority": "high", - "review_reason": "Needs AI review for new_feature.", + "pr_number": 27504, + "pr_url": "https://github.com/openai/codex/pull/27504", + "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/hooks/src/engine/discovery.rs", - "codex-rs/hooks/src/engine/mod_tests.rs" + "codex-rs/config/src/types.rs", + "codex-rs/core/config.schema.json", + "codex-rs/core/src/config/auth_keyring.rs", + "codex-rs/core/src/config/auth_keyring_tests.rs", + "codex-rs/core/src/config/config_tests.rs", + "codex-rs/core/src/config/mod.rs", + "codex-rs/features/src/lib.rs", + "codex-rs/features/src/tests.rs" ], "source_state": "merged", - "subject_id": "26418", + "subject_id": "27504", "subject_kind": "pr", "surface_hints": [ + "auth_accounts", "config_hooks", "tests_ci" ], - "title": "[codex] Avoid duplicate hooks.json discovery with profiles", - "url": "https://github.com/openai/codex/pull/26418" + "title": "feat: add secret auth storage configuration", + "url": "https://github.com/openai/codex/pull/27504" }, { "attention_flags": [ "auth_account", + "deprecated_removed", "new_feature", - "protocol_change" + "protocol_change", + "security_policy" ], - "changed_file_count": 4, + "changed_file_count": 9, "commit_shas": [ - "7115762f8f49eb11a5ee4061ddd7b2d7dd9de37f" + "bfd992f6dbf9acffcbdafbcee3c092d729725759", + "94185dff59cd43d21450db876ab4b595383ae959", + "f45d36dc66dfe7eba7478c6921a69ced53a92c07", + "21c45654a19f658a83b37ada768ab8e109f06955" ], - "committed_at": "2026-06-11T22:33:38Z", + "committed_at": "2026-06-12T19:38:30Z", "next_step": "ai_review_required", - "pr_number": 27689, - "pr_url": "https://github.com/openai/codex/pull/27689", - "review_priority": "high", - "review_reason": "Needs AI review for auth_account, new_feature, protocol_change.", + "pr_number": 27674, + "pr_url": "https://github.com/openai/codex/pull/27674", + "review_priority": "critical", + "review_reason": "Needs AI review for auth_account, deprecated_removed, new_feature, protocol_change, security_policy.", "sample_paths": [ - "codex-rs/model-provider/src/amazon_bedrock/auth.rs", - "codex-rs/model-provider/src/amazon_bedrock/mantle.rs", - "codex-rs/model-provider/src/amazon_bedrock/mod.rs", - "codex-rs/model-provider/src/provider.rs" + "codex-rs/Cargo.lock", + "codex-rs/cli/Cargo.toml", + "codex-rs/cli/src/login.rs", + "codex-rs/cli/tests/login.rs", + "codex-rs/login/src/auth/manager.rs", + "codex-rs/login/src/auth/mod.rs", + "codex-rs/login/src/auth/revoke.rs", + "codex-rs/login/src/server.rs", + "codex-rs/login/tests/suite/logout.rs" ], "source_state": "merged", - "subject_id": "27689", + "subject_id": "27674", "subject_kind": "pr", "surface_hints": [ "auth_accounts", - "model_provider" + "cli_tui", + "config_hooks", + "tests_ci" ], - "title": "feat: prefer managed Bedrock auth in model provider", - "url": "https://github.com/openai/codex/pull/27689" + "title": "[login] revoke existing auth before starting login", + "url": "https://github.com/openai/codex/pull/27674" }, { "attention_flags": [ + "auth_account", + "breaking_change", + "deprecated_removed", "new_feature", - "protocol_change" + "protocol_change", + "release_packaging", + "security_policy" ], - "changed_file_count": 3, + "changed_file_count": 11, "commit_shas": [ - "e328232510870ff1b681078f1953e2910e23270c", - "00d340119b0ffb310544cc046d366ea101610bcd", - "e11078f3a82b0a8eeb0c92453bda658d780d3820" + "07d66eccd904cd15cd754c43d3f74a72d63a1980", + "3e3379b56006b9e877f5db4ba65009b4ad41c49c", + "e026ff2133ba7c2e740eee1ecf0cc0ec5a7479a8", + "30f6722a49e562b8d8fccbaf221aa278d39ab30c" ], - "committed_at": "2026-06-11T23:08:07Z", + "committed_at": "2026-06-12T19:52:49Z", "next_step": "ai_review_required", - "pr_number": 26426, - "pr_url": "https://github.com/openai/codex/pull/26426", - "review_priority": "high", - "review_reason": "Needs AI review for new_feature, protocol_change.", + "pr_number": 27535, + "pr_url": "https://github.com/openai/codex/pull/27535", + "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/config/src/hook_config.rs", - "codex-rs/config/src/hooks_tests.rs", - "codex-rs/hooks/src/engine/mod_tests.rs" + "codex-rs/config/src/types.rs", + "codex-rs/core/config.schema.json", + "codex-rs/core/src/config/auth_keyring.rs", + "codex-rs/core/src/config/auth_keyring_tests.rs", + "codex-rs/core/src/config/config_tests.rs", + "codex-rs/core/src/config/mod.rs", + "codex-rs/features/src/lib.rs", + "codex-rs/features/src/tests.rs", + "codex-rs/keyring-store/src/lib.rs", + "codex-rs/secrets/src/lib.rs", + "codex-rs/secrets/src/local.rs" ], "source_state": "merged", - "subject_id": "26426", + "subject_id": "27535", "subject_kind": "pr", "surface_hints": [ + "auth_accounts", "config_hooks", "tests_ci" ], - "title": "Warn when hooks.json has unsupported top-level fields", - "url": "https://github.com/openai/codex/pull/26426" + "title": "feat: add auth-specific encrypted secret namespaces", + "url": "https://github.com/openai/codex/pull/27535" }, { "attention_flags": [ @@ -1338,162 +1215,157 @@ }, { "attention_flags": [ - "new_feature", - "protocol_change" - ], - "changed_file_count": 8, - "commit_shas": [ - "b73a14d7936a093f28f75a52dd054e5e2b6255c1", - "6ec09b71d7ba945822bd08a8ac8409b018d61cdf" - ], - "committed_at": "2026-06-11T17:24:42Z", - "next_step": "ai_review_required", - "pr_number": 27507, - "pr_url": "https://github.com/openai/codex/pull/27507", - "review_priority": "normal", - "review_reason": "Needs AI review for new_feature, protocol_change.", - "sample_paths": [ - "AGENTS.md", - "tools/argument-comment-lint/README.md", - "tools/argument-comment-lint/src/lib.rs", - "tools/argument-comment-lint/ui/allow_self_documenting_methods.rs", - "tools/argument-comment-lint/ui/comment_mismatch.rs", - "tools/argument-comment-lint/ui/comment_mismatch.stderr", - "tools/argument-comment-lint/ui/multiple_method_arguments.rs", - "tools/argument-comment-lint/ui/multiple_method_arguments.stderr" - ], - "source_state": "merged", - "subject_id": "27507", - "subject_kind": "pr", - "surface_hints": [ - "docs_examples" - ], - "title": "lint: allow self-documenting builder arguments", - "url": "https://github.com/openai/codex/pull/27507" - }, - { - "attention_flags": [ - "deprecated_removed", "new_feature", "protocol_change", "security_policy" ], - "changed_file_count": 5, + "changed_file_count": 12, "commit_shas": [ - "5e772771b5c51f6f15892e47b7eabb0c45b325c9" + "514332328d8921a89660a83cba137ff5dd904717", + "5e98dd7a4f3a2cf349caec88449c400f282bde3a" ], - "committed_at": "2026-06-11T17:53:18Z", + "committed_at": "2026-06-12T16:06:58Z", "next_step": "ai_review_required", - "pr_number": 27454, - "pr_url": "https://github.com/openai/codex/pull/27454", - "review_priority": "normal", - "review_reason": "Needs AI review for deprecated_removed, new_feature, protocol_change, security_policy.", + "pr_number": 27075, + "pr_url": "https://github.com/openai/codex/pull/27075", + "review_priority": "high", + "review_reason": "Needs AI review for new_feature, protocol_change, security_policy.", "sample_paths": [ - "codex-rs/exec-server/tests/file_system.rs", - "codex-rs/exec-server/tests/file_system/shared.rs", - "codex-rs/exec-server/tests/file_system/support.rs", - "codex-rs/exec-server/tests/file_system_unix.rs", - "codex-rs/exec-server/tests/file_system_windows.rs" + "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json", + "codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json", + "codex-rs/app-server-protocol/schema/json/v2/ConfigReadResponse.json", + "codex-rs/app-server-protocol/schema/typescript/v2/AppsDefaultConfig.ts", + "codex-rs/app-server-protocol/src/protocol/v2/config.rs", + "codex-rs/app-server/README.md", + "codex-rs/app-server/tests/suite/v2/config_rpc.rs", + "codex-rs/config/src/types.rs", + "codex-rs/core/config.schema.json", + "codex-rs/core/src/connectors.rs", + "codex-rs/core/src/connectors_tests.rs", + "codex-rs/core/tests/suite/mcp_turn_metadata.rs" ], "source_state": "merged", - "subject_id": "27454", + "subject_id": "27075", "subject_kind": "pr", "surface_hints": [ + "app_server_protocol", + "config_hooks", + "docs_examples", + "mcp_plugins", "tests_ci" ], - "title": "[codex] add cross-platform filesystem adapter coverage", - "url": "https://github.com/openai/codex/pull/27454" + "title": "[ez][codex-rs] Support approvals reviewer in app defaults", + "url": "https://github.com/openai/codex/pull/27075" }, { "attention_flags": [ - "deprecated_removed", - "new_feature", - "protocol_change" + "release_packaging" ], - "changed_file_count": 6, + "changed_file_count": 8, "commit_shas": [ - "af6121ba5beeed92c19a3ef2e4c9fc082be7a1d9" + "4cda8ee60cad306ee3fd5313098d7435b1de6789", + "126848293a2773a2423528aa33c19bb8fff6cacd", + "8919a0099d65fec3af09bf4b3e7e2784142d9cf1" ], - "committed_at": "2026-06-11T18:01:16Z", + "committed_at": "2026-06-12T16:10:07Z", "next_step": "ai_review_required", - "pr_number": 27415, - "pr_url": "https://github.com/openai/codex/pull/27415", - "review_priority": "normal", - "review_reason": "Needs AI review for deprecated_removed, new_feature, protocol_change.", + "pr_number": 27538, + "pr_url": "https://github.com/openai/codex/pull/27538", + "review_priority": "high", + "review_reason": "Needs AI review for release_packaging.", "sample_paths": [ - "codex-rs/exec/src/event_processor_with_human_output.rs", - "codex-rs/exec/src/event_processor_with_jsonl_output.rs", - "codex-rs/exec/src/event_processor_with_jsonl_output_tests.rs", - "codex-rs/exec/src/lib.rs", - "codex-rs/exec/src/lib_tests.rs", - "codex-rs/exec/tests/suite/agents_md.rs" + ".github/workflows/python-sdk-release.yml", + ".github/workflows/sdk.yml", + "scripts/format.py", + "sdk/python/docs/getting-started.md", + "sdk/python/examples/README.md", + "sdk/python/pyproject.toml", + "sdk/python/tests/test_artifact_workflow_and_binaries.py", + "sdk/python/uv.lock" ], "source_state": "merged", - "subject_id": "27415", + "subject_id": "27538", "subject_kind": "pr", "surface_hints": [ + "config_hooks", + "docs_examples", + "release_packaging", "tests_ci" ], - "title": "[codex] Surface runtime warnings in codex exec", - "url": "https://github.com/openai/codex/pull/27415" + "title": "Use dependency groups for Python SDK tooling", + "url": "https://github.com/openai/codex/pull/27538" }, { "attention_flags": [ - "new_feature", + "auth_account", "protocol_change", - "release_packaging" + "security_policy" ], - "changed_file_count": 1, + "changed_file_count": 4, "commit_shas": [ - "f89eb8e014cead41e86d7dddfca4782224975b92" + "3b96f165c11c5ad348600e2a4a665c4d976b4ef4", + "bf374d31fffb7542c394893a819bb723a4a7f01d" ], - "committed_at": "2026-06-11T18:04:24Z", + "committed_at": "2026-06-12T18:17:12Z", "next_step": "ai_review_required", - "pr_number": 27639, - "pr_url": "https://github.com/openai/codex/pull/27639", - "review_priority": "normal", - "review_reason": "Needs AI review for new_feature, protocol_change, release_packaging.", + "pr_number": 27919, + "pr_url": "https://github.com/openai/codex/pull/27919", + "review_priority": "high", + "review_reason": "Needs AI review for auth_account, protocol_change, security_policy.", "sample_paths": [ - ".github/workflows/rust-release.yml" + "codex-rs/core/src/config/mod.rs", + "codex-rs/core/src/tools/handlers/multi_agents_spec.rs", + "codex-rs/core/tests/suite/search_tool.rs", + "codex-rs/core/tests/suite/spawn_agent_description.rs" ], "source_state": "merged", - "subject_id": "27639", + "subject_id": "27919", "subject_kind": "pr", "surface_hints": [ - "release_packaging", + "config_hooks", "tests_ci" ], - "title": "[codex] revert concurrent npm publishing", - "url": "https://github.com/openai/codex/pull/27639" + "title": "chore: prompt MAv2", + "url": "https://github.com/openai/codex/pull/27919" }, { "attention_flags": [ - "new_feature", - "release_packaging" + "protocol_change" ], - "changed_file_count": 3, + "changed_file_count": 10, "commit_shas": [ - "21633f6d2301ad1d88db3aabb4629abe71a91b05" + "edc3e87b3d2f5db1c3b79ac348bd91f7ea5dd85a", + "0ca854c673e53ff602a98fff87e4e3f146a94c1b", + "df3603dd3107c78f8a40388990a8f667bc688dfa" ], - "committed_at": "2026-06-11T18:21:47Z", + "committed_at": "2026-06-12T18:57:22Z", "next_step": "ai_review_required", - "pr_number": 27323, - "pr_url": "https://github.com/openai/codex/pull/27323", - "review_priority": "normal", - "review_reason": "Needs AI review for new_feature, release_packaging.", + "pr_number": 27920, + "pr_url": "https://github.com/openai/codex/pull/27920", + "review_priority": "high", + "review_reason": "Needs AI review for protocol_change.", "sample_paths": [ - "MODULE.bazel", - "patches/BUILD.bazel", - "patches/llvm_windows_arm64_powl.patch" + "codex-rs/app-server/tests/suite/v2/imagegen_extension.rs", + "codex-rs/core/src/stream_events_utils.rs", + "codex-rs/ext/image-generation/src/tool.rs", + "codex-rs/tui/src/chatwidget/replay.rs", + "codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__failed_image_generation_call_history_snapshot.snap", + "codex-rs/tui/src/chatwidget/tests/exec_flow.rs", + "codex-rs/tui/src/chatwidget/tests/helpers.rs", + "codex-rs/tui/src/chatwidget/tool_lifecycle.rs", + "codex-rs/tui/src/history_cell/patches.rs", + "codex-rs/tui/src/history_cell/tests.rs" ], "source_state": "merged", - "subject_id": "27323", + "subject_id": "27920", "subject_kind": "pr", "surface_hints": [ - "internal_churn" + "app_server_protocol", + "cli_tui", + "tests_ci" ], - "title": "[codex] Provide ARM64 MinGW powl compatibility support", - "url": "https://github.com/openai/codex/pull/27323" + "title": "Handle standalone image generation failures as terminal items", + "url": "https://github.com/openai/codex/pull/27920" }, { "attention_flags": [ @@ -1586,6 +1458,152 @@ ], "title": "Translate non-English issues", "url": "https://github.com/openai/codex/pull/27778" + }, + { + "attention_flags": [ + "auth_account", + "release_packaging" + ], + "changed_file_count": 4, + "commit_shas": [ + "41408389e4bd9c8b937b0ca10eb305d43ea6439b", + "29ac1384a5af6fb0aa9790e6af4e7aa18a8f12c0", + "0b508a84e79acc7bd298050f99565e9083d22323" + ], + "committed_at": "2026-06-12T16:26:08Z", + "next_step": "ai_review_required", + "pr_number": 27783, + "pr_url": "https://github.com/openai/codex/pull/27783", + "review_priority": "normal", + "review_reason": "Needs AI review for auth_account, release_packaging.", + "sample_paths": [ + "codex-rs/tui/src/lib.rs", + "codex-rs/tui/src/updates.rs", + "codex-rs/tui/src/updates_cache.rs", + "codex-rs/tui/src/updates_cache_tests.rs" + ], + "source_state": "merged", + "subject_id": "27783", + "subject_kind": "pr", + "surface_hints": [ + "cli_tui", + "tests_ci" + ], + "title": "Persist update dismissal without cache", + "url": "https://github.com/openai/codex/pull/27783" + }, + { + "attention_flags": [ + "auth_account", + "new_feature" + ], + "changed_file_count": 2, + "commit_shas": [ + "0b53736536efdca3894f9e5f972da1b87be48e91" + ], + "committed_at": "2026-06-12T16:30:25Z", + "next_step": "ai_review_required", + "pr_number": 27814, + "pr_url": "https://github.com/openai/codex/pull/27814", + "review_priority": "normal", + "review_reason": "Needs AI review for auth_account, new_feature.", + "sample_paths": [ + "codex-rs/tui/src/bottom_pane/slash_commands.rs", + "codex-rs/tui/src/chatwidget/tests/slash_commands.rs" + ], + "source_state": "merged", + "subject_id": "27814", + "subject_kind": "pr", + "surface_hints": [ + "cli_tui", + "tests_ci" + ], + "title": "tui: Allow extra o's in /goal command", + "url": "https://github.com/openai/codex/pull/27814" + }, + { + "attention_flags": [ + "deprecated_removed", + "new_feature", + "protocol_change" + ], + "changed_file_count": 2, + "commit_shas": [ + "6b2c572c7a2e3cd662afaf7ee62c8a202e32ae53", + "e263eedd3acbd3852ae139e88b82893dc8e6b46b", + "312807de7287117c496988a4fac00e976c0bd3c9", + "4dbf491551b67756e6657fe0145b384ebef71ade" + ], + "committed_at": "2026-06-12T18:54:28Z", + "next_step": "ai_review_required", + "pr_number": 27913, + "pr_url": "https://github.com/openai/codex/pull/27913", + "review_priority": "normal", + "review_reason": "Needs AI review for deprecated_removed, new_feature, protocol_change.", + "sample_paths": [ + "codex-rs/apply-patch/src/parser.rs", + "codex-rs/apply-patch/src/streaming_parser.rs" + ], + "source_state": "merged", + "subject_id": "27913", + "subject_kind": "pr", + "surface_hints": [ + "internal_churn" + ], + "title": "[codex] unify apply patch parsing", + "url": "https://github.com/openai/codex/pull/27913" + }, + { + "attention_flags": [ + "new_feature", + "protocol_change" + ], + "changed_file_count": 1, + "commit_shas": [ + "1b73843628fdfbb3968f89427fc272b8add483b0" + ], + "committed_at": "2026-06-12T20:00:21Z", + "next_step": "ai_review_required", + "pr_number": 27939, + "pr_url": "https://github.com/openai/codex/pull/27939", + "review_priority": "normal", + "review_reason": "Needs AI review for new_feature, protocol_change.", + "sample_paths": [ + "AGENTS.md" + ], + "source_state": "merged", + "subject_id": "27939", + "subject_kind": "pr", + "surface_hints": [ + "internal_churn" + ], + "title": "[codex] Add crate API surface review rule", + "url": "https://github.com/openai/codex/pull/27939" + }, + { + "attention_flags": [], + "changed_file_count": 2, + "commit_shas": [ + "59ff44bc76660a6b9e8e3ab135cda64d2abc93f3" + ], + "committed_at": "2026-06-12T15:58:08Z", + "next_step": "ai_review_required", + "pr_number": 27791, + "pr_url": "https://github.com/openai/codex/pull/27791", + "review_priority": "low", + "review_reason": "Needs AI review for surface hints: cli_tui.", + "sample_paths": [ + "codex-rs/tui/src/app/input.rs", + "codex-rs/tui/src/app_backtrack.rs" + ], + "source_state": "merged", + "subject_id": "27791", + "subject_kind": "pr", + "surface_hints": [ + "cli_tui" + ], + "title": "Reject transcript backtrack in side conversations", + "url": "https://github.com/openai/codex/pull/27791" } ] } diff --git a/artifacts/github/reviews/openai-codex-pr-27318.review.json b/artifacts/github/reviews/openai-codex-pr-27318.review.json new file mode 100644 index 000000000..e1fb738f7 --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-27318.review.json @@ -0,0 +1,65 @@ +{ + "adoption_opportunity": "Align Decodex retained-lane history and resume handling with store-owned projections instead of assuming callers pre-filter rollout items before append.", + "caveats": "This is mostly an internal persistence boundary change. The bundle does not show a new CLI command or public JSON-RPC method, but app-server history/resume consumers may still feel projection differences.", + "changed_surfaces": [ + "thread-store append_items contract", + "local and in-memory thread-store writers", + "LiveThread create, resume, and append paths", + "core session thread creation and resume wiring", + "app-server thread history turn snapshots", + "stored turn metadata model" + ], + "community_value": "Low for general users, but useful for operators tracking Codex thread replay, resume, and durable history semantics.", + "compatibility_risk": "Medium for store implementations, tests, or integrations that assumed append_items receives already-canonical rollout items or that stores should persist every raw input item.", + "confidence": "confirmed", + "control_plane_relevance": "High for Decodex Control Plane history and recovery work because thread stores now own persistence-policy projection for live append replay.", + "deprecated_or_breaking_notes": "The ThreadStore append_items documentation changes from canonical rollout items to raw rollout items. AppendThreadItemsParams is no longer Serialize/Deserialize, and store implementations now apply persisted_rollout_items themselves.", + "evidence": [ + "PR #27318 says the persistence policy moved into thread stores so stores receive raw append items and can build store-specific projections.", + "`codex-rs/thread-store/src/store.rs` changes append_items documentation from appending canonical rollout items to appending raw rollout items, with implementations applying the shared persistence policy.", + "`codex-rs/thread-store/src/local/live_writer.rs` and `codex-rs/thread-store/src/in_memory.rs` call `persisted_rollout_items` before writing durable replay history.", + "`codex-rs/thread-store/src/live_thread.rs` keeps raw non-empty appends flowing to stores while applying metadata updates around the store append.", + "`codex-rs/core/src/session/session.rs` moves thread creation and resume history handling through the store-owned LiveThread path.", + "`codex-rs/app-server-protocol/src/protocol/thread_history.rs` adds `turn_snapshot` lookup support used by history projections.", + "The normalized bundle `artifacts/github/bundles/openai-codex-pr-27318.json` records 8 changed files for the merged PR." + ], + "next_actions": [ + { + "reason": "Store-owned persistence projection can affect Decodex retained history, resume recovery, and thread replay assumptions.", + "type": "upstream_impact" + } + ], + "observed_change": "Codex moved rollout persistence-policy projection into ThreadStore implementations so live stores receive raw append items and own canonical replay writes.", + "repo": "openai/codex", + "reviewed_at": "2026-06-12T20:08:11Z", + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-27318", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-11T23:24:13Z", + "title": "[codex] Move persistence policy application into ThreadStore", + "url": "https://github.com/openai/codex/pull/27318" + }, + { + "kind": "commit", + "title": "Move raw append projection into thread stores", + "url": "https://github.com/openai/codex/commit/0b34bb09f82857993b511572569cdcfdaa9430ab" + } + ] + }, + "subject": { + "commit_shas": [ + "eafa1fc84190009a6d53378565460290dba3ceb8", + "682f2b9c28f8bdc54c8b48e2f1587228b81c90ed", + "0b34bb09f82857993b511572569cdcfdaa9430ab", + "6b06a574cc1be682580cfce269d755e3140e39f6", + "8f878400ea36dbcbc573a2f8d5bfacfe1b8c73b6", + "d2132fbc5250d96109f5c30b05a07432afa5afd3" + ], + "subject_id": "27318", + "subject_kind": "pr" + }, + "user_visible_path": "No direct UI path was introduced, but thread resume, history projection, and replay behavior can affect app-server clients that inspect or recover live thread history." +} diff --git a/artifacts/github/reviews/openai-codex-pr-27445.review.json b/artifacts/github/reviews/openai-codex-pr-27445.review.json new file mode 100644 index 000000000..570cc5b99 --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-27445.review.json @@ -0,0 +1,85 @@ +{ + "adoption_opportunity": "Update Decodex remote-control clients and operator docs to treat ordinary remoteControl enable or disable requests as durable, and use `ephemeral: true` only for runtime-only starts.", + "caveats": "The methods remain marked experimental in the protocol. Existing clients that omit params still have valid nullable params, but their persistence semantics changed.", + "changed_surfaces": [ + "remoteControl/enable and remoteControl/disable protocol params", + "remote-control startup desired state", + "remote-control enrollment persistence", + "app-server daemon runtime-only startup behavior", + "state migration for remote_control_enrollments", + "generated JSON and TypeScript app-server schemas", + "remote-control app-server and daemon tests" + ], + "community_value": "High for operators and app-server clients because it clarifies when remote-control state persists versus when it is runtime-only.", + "compatibility_risk": "High for Control Plane clients that assumed remoteControl enable or disable was process-only. They now need to send `ephemeral: true` for runtime-only behavior or expect durable enrollment preference updates.", + "confidence": "confirmed", + "control_plane_relevance": "High. Decodex Control Plane remote-control orchestration must distinguish durable operator preference from ephemeral daemon or CLI startup behavior.", + "deprecated_or_breaking_notes": "RemoteControlEnable and RemoteControlDisable params changed from undefined to nullable param objects with an optional `ephemeral` boolean. A new state migration adds `remote_control_enabled` to persisted enrollments.", + "evidence": [ + "PR #27445 says remote-control runtime enablement and persisted enrollment preference were replaced by a transport-owned RemoteControlDesiredState.", + "`codex-rs/app-server-protocol/src/protocol/common.rs` changes remoteControl enable and disable params from undefined to nullable params objects.", + "`codex-rs/app-server-protocol/src/protocol/v2/remote_control.rs` adds `RemoteControlEnableParams` and `RemoteControlDisableParams` with optional `ephemeral` booleans.", + "`codex-rs/app-server-transport/src/transport/remote_control/desired_state.rs` adds the desired-state model separating persisted and runtime-only enablement.", + "`codex-rs/state/migrations/0037_remote_control_enrollments_enabled.sql` adds persisted `remote_control_enabled` storage.", + "`codex-rs/app-server-daemon/src/remote_control_client.rs` and related tests cover durable enable, durable disable, and ephemeral enable behavior.", + "The normalized bundle `artifacts/github/bundles/openai-codex-pr-27445.json` records 33 changed files for the merged PR." + ], + "next_actions": [ + { + "reason": "Durable remote-control semantics are a concrete Decodex Control Plane compatibility risk.", + "type": "upstream_impact" + }, + { + "reason": "Operators need a public-facing explanation of durable remote-control state versus `ephemeral: true` runtime-only behavior.", + "type": "social_candidate" + } + ], + "observed_change": "Codex remote-control enable and disable requests now persist desired state by default while retaining `ephemeral: true` for runtime-only callers.", + "repo": "openai/codex", + "reviewed_at": "2026-06-12T20:08:11Z", + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-27445", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-12T04:28:53Z", + "title": "feat(app-server): persist remote-control desired state", + "url": "https://github.com/openai/codex/pull/27445" + }, + { + "kind": "commit", + "title": "Persist remote-control desired state", + "url": "https://github.com/openai/codex/commit/c1c83d3db1c92450ee5104637673da205c3b53f1" + }, + { + "kind": "commit", + "title": "reject disabled transportless remote control startup", + "url": "https://github.com/openai/codex/commit/e34ec2789518918e9cd1d8b06187ce1da043b5b5" + } + ] + }, + "subject": { + "commit_shas": [ + "c1c83d3db1c92450ee5104637673da205c3b53f1", + "11b7a3193c9c0b607a89154d613bf31bf9968356", + "37c9a1af8e791b935a7e6b79412097349b3be23a", + "2ccf773428b3e45ea0bf628f7cdc1f829acb4ec6", + "89e994bf64ee35e3e03915cea760486b67eeeddb", + "f06ad42c1964a93de5e96576e7c4244ac41f2e74", + "751a2a5ffa1105ebf86c0c89507d97b1dd8a203e", + "5d46286a8c47f23d546e431d8395861091407ac3", + "51201c3539709dc098c33bb5d917c3f3c2c360d1", + "51c0ede50280cb2b7720ad4edc795b99f2bbff8b", + "5957b62fc0479ae8ab34b1126edbfc482536d7a1", + "38fa3a8ac4472cf91ae78a7bcf46de916d96849a", + "6d519c7361e8c5d9ea93acd5a9ee2bdf8b52d76e", + "ffc649de3e5b2fb406e8fc84b26973bf375762ab", + "d4c46df25f4a90a7cb75380379d58bb301bcb9af", + "e34ec2789518918e9cd1d8b06187ce1da043b5b5" + ], + "subject_id": "27445", + "subject_kind": "pr" + }, + "user_visible_path": "App-server clients calling remoteControl/enable or remoteControl/disable now change durable desired state by default; runtime-only callers must use the new `ephemeral: true` parameter." +} diff --git a/artifacts/github/reviews/openai-codex-pr-27475.review.json b/artifacts/github/reviews/openai-codex-pr-27475.review.json new file mode 100644 index 000000000..fc778ee31 --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-27475.review.json @@ -0,0 +1,66 @@ +{ + "adoption_opportunity": "Track upstream trait signatures and dependency policy if Decodex patches or embeds Codex Rust crates that previously used async_trait-based object-safe traits.", + "caveats": "The PR body describes changed tests passing while broader `just test` failures were environment-sensitive and unrelated. The reviewed bundle does not show a new user-facing feature.", + "changed_surfaces": [ + "workspace dependency declarations", + "cargo-deny policy", + "first-party async trait definitions", + "cloud tasks, thread store, file system, model provider, network proxy, and shell escalation traits", + "rand dependency version", + "Bazel and Cargo lockfiles" + ], + "community_value": "Moderate for Rust maintainers interested in native async trait migration and dependency policy, but low for everyday Codex users.", + "compatibility_risk": "Medium for forks, tests, or downstream crates that compile against first-party Codex traits. Low for app-server JSON clients because the bundle does not show a protocol method change.", + "confidence": "confirmed", + "control_plane_relevance": "Moderate watch item. Decodex does not need a runtime protocol change, but source-level integrations and local patches may need to follow the new explicit Send future signatures.", + "deprecated_or_breaking_notes": "First-party direct `async-trait` dependencies and the workspace dependency declaration were removed. Traits now expose native return-position `impl Future + Send` or boxed Send futures where object safety is needed; `rand` moves from 0.8.5 to 0.8.6.", + "evidence": [ + "PR #27475 says remaining first-party async_trait traits were replaced with native or boxed Send futures and direct first-party async-trait dependencies were removed.", + "`codex-rs/Cargo.toml` removes the workspace `async-trait` dependency.", + "`codex-rs/deny.toml` adds policy allowing async-trait only through remaining transitive wrapper crates.", + "`codex-rs/thread-store/src/store.rs` adds a boxed ThreadStoreFuture type and changes ThreadStore methods from async_trait methods to explicit future-returning methods.", + "`codex-rs/cloud-tasks-client/src/api.rs`, `codex-rs/network-proxy/src/network_policy.rs`, and `codex-rs/shell-escalation/src/unix/escalation_policy.rs` show the same explicit future migration pattern.", + "`codex-rs/Cargo.lock` updates rand from 0.8.5 to 0.8.6.", + "The normalized bundle `artifacts/github/bundles/openai-codex-pr-27475.json` records 93 changed files for the merged PR." + ], + "next_actions": [ + { + "reason": "The change is mainly source-level compatibility and dependency-policy context for Decodex maintainers, not a public publishing candidate.", + "type": "upstream_impact" + } + ], + "observed_change": "Codex removed direct first-party async-trait usage by moving first-party async traits to explicit Send future signatures and tightening dependency policy.", + "repo": "openai/codex", + "reviewed_at": "2026-06-12T20:08:11Z", + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-27475", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-12T01:16:39Z", + "title": "[codex] Remove async_trait from first-party code", + "url": "https://github.com/openai/codex/pull/27475" + }, + { + "kind": "commit", + "title": "Remove async_trait from first-party code", + "url": "https://github.com/openai/codex/commit/9aba4e7c68322efaf4a930336061dc4ddf22eedb" + }, + { + "kind": "commit", + "title": "Ban first-party async-trait dependencies", + "url": "https://github.com/openai/codex/commit/4df5f02d73bd57c728ec65880b2b702825256edc" + } + ] + }, + "subject": { + "commit_shas": [ + "9aba4e7c68322efaf4a930336061dc4ddf22eedb", + "4df5f02d73bd57c728ec65880b2b702825256edc" + ], + "subject_id": "27475", + "subject_kind": "pr" + }, + "user_visible_path": "No direct end-user path was identified. The observable effect is source and dependency compatibility for Codex Rust crates and maintainers." +} diff --git a/artifacts/github/reviews/openai-codex-pr-27498.review.json b/artifacts/github/reviews/openai-codex-pr-27498.review.json new file mode 100644 index 000000000..1ded22d1b --- /dev/null +++ b/artifacts/github/reviews/openai-codex-pr-27498.review.json @@ -0,0 +1,70 @@ +{ + "adoption_opportunity": "Use turn-environment-backed reads when Decodex invokes or evaluates extension tools that consume referenced file paths, especially in sandboxed or remote filesystems.", + "caveats": "The PR body says the image-generation extension test target could not complete because the build exhausted disk space, although targeted checks and sandbox coverage were added.", + "changed_surfaces": [ + "extension ToolCall environment payload", + "extension API ToolEnvironment export", + "core extension tool execution", + "image-generation extension request construction", + "sandbox permission handling around extension calls", + "extension sandbox and image-generation tests" + ], + "community_value": "High for users and extension authors who pass referenced images by path, because the behavior now respects selected turn environments and sandbox context.", + "compatibility_risk": "Medium for extension tests or custom callers constructing ToolCall values because ToolCall now carries an environments list and image request construction is async.", + "confidence": "confirmed", + "control_plane_relevance": "High. Decodex Control Plane extension and environment routing should preserve the selected environment filesystem and sandbox context for referenced media reads.", + "deprecated_or_breaking_notes": "No user-facing image feature was removed. Source callers must handle the new ToolCall environments field and async image request helper.", + "evidence": [ + "PR #27498 says image generation previously used `std::fs::read`, which did not support environment-backed filesystems or sandbox context.", + "`codex-rs/tools/src/tool_call.rs` adds `ToolEnvironment` with environment id, working directory, filesystem, and sandbox context.", + "`codex-rs/core/src/tools/handlers/extension_tools.rs` passes turn environments and applies granted turn permissions at the extension call site.", + "`codex-rs/ext/image-generation/src/tool.rs` builds image requests with `request_for_call_args(..., &call.environments).await`.", + "`codex-rs/core/tests/suite/extension_sandbox.rs` adds coverage for environment reads and sandbox behavior.", + "The normalized bundle `artifacts/github/bundles/openai-codex-pr-27498.json` records 14 changed files for the merged PR." + ], + "next_actions": [ + { + "reason": "Environment-backed extension file reads can affect Decodex extension execution, sandbox routing, and remote filesystem compatibility.", + "type": "upstream_impact" + }, + { + "reason": "The change has a clear practical user explanation for referenced image paths in sandboxed or environment-backed Codex runs.", + "type": "social_candidate" + } + ], + "observed_change": "Codex image-generation extension reads referenced image paths through the selected turn environment filesystem instead of plain local filesystem reads.", + "repo": "openai/codex", + "reviewed_at": "2026-06-12T20:08:11Z", + "schema": "upstream_review/v1", + "slug": "openai-codex-pr-27498", + "source_refs": { + "items": [ + { + "kind": "pull_request", + "meta": "Merged 2026-06-11T23:32:52Z", + "title": "Route image extension reads through turn environments v2", + "url": "https://github.com/openai/codex/pull/27498" + }, + { + "kind": "commit", + "title": "address image sandbox review feedback", + "url": "https://github.com/openai/codex/commit/2feef6f6c77bcd8140bc126377410bcdf3b89915" + } + ] + }, + "subject": { + "commit_shas": [ + "27e50cfa078191d4d61f281fcb4307b3fd8d2e97", + "526c3e8565b00151ee29f620978650f07610e9ee", + "6467362a57ce5befcf5895c4df10d5bae82a92e6", + "2feef6f6c77bcd8140bc126377410bcdf3b89915", + "18126046137392d29cb21f2f734160b52cfa1ea5", + "f8ab6ef5dc39035114a695d5dc5952ff1aad7fa6", + "03f5b38cf9b4d10eb8d9f1a94ddd0d503aacd257", + "59544fbc520493779b297162c114ee185392c521" + ], + "subject_id": "27498", + "subject_kind": "pr" + }, + "user_visible_path": "Users attaching referenced image paths to image-generation extension calls can now rely on the selected turn environment filesystem and sandbox context instead of only local host paths." +} diff --git a/artifacts/github/social-candidates/openai-codex-pr-27445.json b/artifacts/github/social-candidates/openai-codex-pr-27445.json new file mode 100644 index 000000000..f855bb315 --- /dev/null +++ b/artifacts/github/social-candidates/openai-codex-pr-27445.json @@ -0,0 +1,53 @@ +{ + "audience": "Codex app-server and Control Plane operators", + "candidate_text": [ + "Codex remoteControl/enable and disable are now durable by default, with `ephemeral: true` for runtime-only callers. Control-plane clients should recheck persistence assumptions. PR: https://github.com/openai/codex/pull/27445" + ], + "caveats": [ + "The remote-control methods remain experimental upstream.", + "Do not imply Decodex has already adopted the new semantics." + ], + "channel": "x", + "claims": [ + { + "confidence": "confirmed", + "evidence": "artifacts/github/reviews/openai-codex-pr-27445.review.json", + "text": "remoteControl enable and disable now have nullable params with optional `ephemeral`." + }, + { + "confidence": "confirmed", + "evidence": "artifacts/github/impact/openai-codex-pr-27445.json", + "text": "Ordinary enable and disable requests now affect durable desired state by default." + } + ], + "decision": { + "idempotency_key": "x:decodexspace:openai-codex-pr-27445:operator_impact", + "reason": "The change is a concrete app-server Control Plane compatibility note with an operator action.", + "worthiness": "publish" + }, + "evidence_notes": [ + "RemoteControlEnableParams and RemoteControlDisableParams add optional `ephemeral`.", + "RemoteControlDesiredState separates persisted and runtime-only state.", + "State migration adds remote_control_enabled persistence for enrollments." + ], + "mode": "operator_impact", + "next_steps": [ + "Let Publisher automation decide whether to reserve or publish this candidate." + ], + "priority": "critical", + "repo": "openai/codex", + "schema": "social_candidate/v1", + "slug": "openai-codex-pr-27445", + "source_refs": { + "upstream_impacts": [ + "artifacts/github/impact/openai-codex-pr-27445.json" + ], + "upstream_reviews": [ + "artifacts/github/reviews/openai-codex-pr-27445.review.json" + ], + "urls": [ + "https://github.com/openai/codex/pull/27445" + ] + }, + "target_account": "decodexspace" +} diff --git a/artifacts/github/social-candidates/openai-codex-pr-27498.json b/artifacts/github/social-candidates/openai-codex-pr-27498.json new file mode 100644 index 000000000..6fc192bed --- /dev/null +++ b/artifacts/github/social-candidates/openai-codex-pr-27498.json @@ -0,0 +1,53 @@ +{ + "audience": "Codex users and extension authors who attach image paths", + "candidate_text": [ + "Codex image extension refs now read through the selected turn environment instead of plain std::fs, so attached image paths can respect environment-backed filesystems and sandbox context. PR: https://github.com/openai/codex/pull/27498" + ], + "caveats": [ + "Do not imply image model behavior changed.", + "Mention that the upstream full image-generation test command hit a disk-space limit." + ], + "channel": "x", + "claims": [ + { + "confidence": "confirmed", + "evidence": "artifacts/github/reviews/openai-codex-pr-27498.review.json", + "text": "Referenced image paths are read through the selected turn environment filesystem." + }, + { + "confidence": "confirmed", + "evidence": "artifacts/github/impact/openai-codex-pr-27498.json", + "text": "The change carries sandbox and environment-routing implications for extension calls." + } + ], + "decision": { + "idempotency_key": "x:decodexspace:openai-codex-pr-27498:practical_explainer", + "reason": "The change has a concrete user-facing explanation for referenced image paths in environment-backed or sandboxed runs.", + "worthiness": "publish" + }, + "evidence_notes": [ + "ToolCall now carries ToolEnvironment entries.", + "Image request construction receives call.environments and reads referenced paths through that context.", + "Sandbox tests cover environment-backed image reads." + ], + "mode": "practical_explainer", + "next_steps": [ + "Let Publisher automation decide whether to reserve or publish this candidate." + ], + "priority": "critical", + "repo": "openai/codex", + "schema": "social_candidate/v1", + "slug": "openai-codex-pr-27498", + "source_refs": { + "upstream_impacts": [ + "artifacts/github/impact/openai-codex-pr-27498.json" + ], + "upstream_reviews": [ + "artifacts/github/reviews/openai-codex-pr-27498.review.json" + ], + "urls": [ + "https://github.com/openai/codex/pull/27498" + ] + }, + "target_account": "decodexspace" +}