From 46142c3cb0f2d5de2b12920bbda84468b3a526b0 Mon Sep 17 00:00:00 2001 From: Won Park Date: Wed, 22 Apr 2026 15:45:35 -0700 Subject: [PATCH] Rebrand approvals reviewer config to auto-review (#18504) ### Why Auto-review is the user-facing name for the approvals reviewer, but the config/API value still exposed the old `guardian_subagent` name. That made new configs and generated schemas point users at Guardian terminology even though the intended product surface is Auto-review. This PR updates the external `approvals_reviewer` value while preserving compatibility for existing configs and clients. ### What changed - Makes `auto_review` the canonical serialized value for `approvals_reviewer`. - Keeps `guardian_subagent` accepted as a legacy alias. - Keeps `user` accepted and serialized as `user`. - Updates generated config and app-server schemas so `approvals_reviewer` includes: - `user` - `auto_review` - `guardian_subagent` - Updates app-server README docs for the reviewer value. - Updates analytics and config requirements tests for the canonical auto_review value. ### Compatibility Existing configs and API payloads using: ```toml approvals_reviewer = "guardian_subagent" ``` continue to load and map to the Auto-review reviewer behavior. New serialization emits: ```toml approvals_reviewer = "auto_review" ``` This PR intentionally does not rename the [features].guardian_approval key or broad internal Guardian symbols. Those are split out for a follow-up PR to keep this migration small and avoid touching large TUI/internal surfaces. **Verification** cargo test -p codex-protocol approvals_reviewer_serializes_auto_review_and_accepts_legacy_guardian_subagent cargo test -p codex-app-server-protocol approvals_reviewer_serializes_auto_review_and_accepts_legacy_guardian_subagent --- .../analytics/src/analytics_client_tests.rs | 6 +- .../schema/json/ClientRequest.json | 3 +- .../codex_app_server_protocol.schemas.json | 3 +- .../codex_app_server_protocol.v2.schemas.json | 3 +- .../schema/json/v2/ConfigReadResponse.json | 3 +- .../v2/ConfigRequirementsReadResponse.json | 3 +- .../schema/json/v2/ThreadForkParams.json | 3 +- .../schema/json/v2/ThreadForkResponse.json | 3 +- .../schema/json/v2/ThreadResumeParams.json | 3 +- .../schema/json/v2/ThreadResumeResponse.json | 3 +- .../schema/json/v2/ThreadStartParams.json | 3 +- .../schema/json/v2/ThreadStartResponse.json | 3 +- .../schema/json/v2/TurnStartParams.json | 3 +- .../schema/typescript/v2/ApprovalsReviewer.ts | 4 +- .../app-server-protocol/src/protocol/v2.rs | 73 +++++++++++++++++- codex-rs/app-server/README.md | 2 +- codex-rs/config/src/config_requirements.rs | 22 +++++- codex-rs/core/config.schema.json | 3 +- codex-rs/core/src/config_loader/mod.rs | 6 +- codex-rs/protocol/src/config_types.rs | 74 +++++++++++++++++-- codex-rs/tui/src/app/tests.rs | 6 +- codex-rs/tui/src/debug_config.rs | 4 +- 22 files changed, 197 insertions(+), 39 deletions(-) diff --git a/codex-rs/analytics/src/analytics_client_tests.rs b/codex-rs/analytics/src/analytics_client_tests.rs index 03592c9ff..cd96bac62 100644 --- a/codex-rs/analytics/src/analytics_client_tests.rs +++ b/codex-rs/analytics/src/analytics_client_tests.rs @@ -1334,7 +1334,7 @@ fn subagent_thread_started_other_serializes_explicit_parent_thread_id() { }, )); - let payload = serde_json::to_value(&event).expect("serialize guardian subagent event"); + let payload = serde_json::to_value(&event).expect("serialize auto-review subagent event"); assert_eq!(payload["event_params"]["subagent_source"], "guardian"); assert_eq!( payload["event_params"]["parent_thread_id"], @@ -1758,7 +1758,7 @@ fn turn_event_serializes_expected_shape() { reasoning_summary: Some("detailed".to_string()), service_tier: "flex".to_string(), approval_policy: "on-request".to_string(), - approvals_reviewer: "guardian_subagent".to_string(), + approvals_reviewer: "auto_review".to_string(), sandbox_network_access: true, collaboration_mode: Some("plan"), personality: Some("pragmatic".to_string()), @@ -1819,7 +1819,7 @@ fn turn_event_serializes_expected_shape() { "reasoning_summary": "detailed", "service_tier": "flex", "approval_policy": "on-request", - "approvals_reviewer": "guardian_subagent", + "approvals_reviewer": "auto_review", "sandbox_network_access": true, "collaboration_mode": "plan", "personality": "pragmatic", diff --git a/codex-rs/app-server-protocol/schema/json/ClientRequest.json b/codex-rs/app-server-protocol/schema/json/ClientRequest.json index ada860ae2..d941238ca 100644 --- a/codex-rs/app-server-protocol/schema/json/ClientRequest.json +++ b/codex-rs/app-server-protocol/schema/json/ClientRequest.json @@ -13,9 +13,10 @@ "type": "string" }, "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index 51fb74407..c463df699 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -5728,9 +5728,10 @@ "type": "object" }, "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json index 6291b5b98..20e0f8f6e 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json @@ -605,9 +605,10 @@ "type": "object" }, "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ConfigReadResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ConfigReadResponse.json index 58f818626..c348e7d95 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ConfigReadResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ConfigReadResponse.json @@ -97,9 +97,10 @@ "type": "object" }, "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ConfigRequirementsReadResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ConfigRequirementsReadResponse.json index 614575a95..f75833af1 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ConfigRequirementsReadResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ConfigRequirementsReadResponse.json @@ -2,9 +2,10 @@ "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkParams.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkParams.json index 6b227dec3..16a41d0d2 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkParams.json @@ -6,9 +6,10 @@ "type": "string" }, "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json index 91f6db519..f62d60025 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json @@ -9,9 +9,10 @@ "type": "string" }, "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json index d4dce1b65..7fb27c08e 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json @@ -6,9 +6,10 @@ "type": "string" }, "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json index 79128bdac..710a701f9 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json @@ -9,9 +9,10 @@ "type": "string" }, "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartParams.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartParams.json index a382edd66..0c5f21764 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartParams.json @@ -6,9 +6,10 @@ "type": "string" }, "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json index 95063f2c9..9fe3bc62b 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json @@ -9,9 +9,10 @@ "type": "string" }, "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnStartParams.json b/codex-rs/app-server-protocol/schema/json/v2/TurnStartParams.json index 3af55e729..062771029 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/TurnStartParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/TurnStartParams.json @@ -6,9 +6,10 @@ "type": "string" }, "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ApprovalsReviewer.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ApprovalsReviewer.ts index a5a26ae0e..1d932946c 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ApprovalsReviewer.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ApprovalsReviewer.ts @@ -5,8 +5,8 @@ /** * Configures who approval requests are routed to for review. Examples * include sandbox escapes, blocked network access, MCP approval prompts, and - * ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully + * ARC escalations. Defaults to `user`. `auto_review` uses a carefully * prompted subagent to gather relevant context and apply a risk-based * decision framework before approving or denying the request. */ -export type ApprovalsReviewer = "user" | "guardian_subagent"; +export type ApprovalsReviewer = "user" | "auto_review" | "guardian_subagent"; diff --git a/codex-rs/app-server-protocol/src/protocol/v2.rs b/codex-rs/app-server-protocol/src/protocol/v2.rs index 2e492e379..2760313dc 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2.rs @@ -101,6 +101,11 @@ use codex_protocol::user_input::TextElement as CoreTextElement; use codex_protocol::user_input::UserInput as CoreUserInput; use codex_utils_absolute_path::AbsolutePathBuf; use schemars::JsonSchema; +use schemars::r#gen::SchemaGenerator; +use schemars::schema::InstanceType; +use schemars::schema::Metadata; +use schemars::schema::Schema; +use schemars::schema::SchemaObject; use serde::Deserialize; use serde::Serialize; use serde_json::Value as JsonValue; @@ -304,19 +309,54 @@ impl From for AskForApproval { } } -#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)] -#[serde(rename_all = "snake_case")] -#[ts(rename_all = "snake_case", export_to = "v2/")] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, TS)] +#[ts( + type = r#""user" | "auto_review" | "guardian_subagent""#, + export_to = "v2/" +)] /// Configures who approval requests are routed to for review. Examples /// include sandbox escapes, blocked network access, MCP approval prompts, and -/// ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully +/// ARC escalations. Defaults to `user`. `auto_review` uses a carefully /// prompted subagent to gather relevant context and apply a risk-based /// decision framework before approving or denying the request. pub enum ApprovalsReviewer { + #[serde(rename = "user")] User, + #[serde(rename = "auto_review", alias = "guardian_subagent")] GuardianSubagent, } +impl JsonSchema for ApprovalsReviewer { + fn schema_name() -> String { + "ApprovalsReviewer".to_string() + } + + fn json_schema(_generator: &mut SchemaGenerator) -> Schema { + string_enum_schema_with_description( + &["user", "auto_review", "guardian_subagent"], + "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + ) + } +} + +fn string_enum_schema_with_description(values: &[&str], description: &str) -> Schema { + let mut schema = SchemaObject { + instance_type: Some(InstanceType::String.into()), + metadata: Some(Box::new(Metadata { + description: Some(description.to_string()), + ..Default::default() + })), + ..Default::default() + }; + schema.enum_values = Some( + values + .iter() + .map(|value| JsonValue::String((*value).to_string())) + .collect(), + ); + Schema::Object(schema) +} + impl ApprovalsReviewer { pub fn to_core(self) -> CoreApprovalsReviewer { match self { @@ -7346,6 +7386,31 @@ mod tests { absolute_path("readable") } + #[test] + fn approvals_reviewer_serializes_auto_review_and_accepts_legacy_guardian_subagent() { + assert_eq!( + serde_json::to_string(&ApprovalsReviewer::User).expect("serialize reviewer"), + "\"user\"" + ); + assert_eq!( + serde_json::to_string(&ApprovalsReviewer::GuardianSubagent) + .expect("serialize reviewer"), + "\"auto_review\"" + ); + + for value in ["user", "auto_review", "guardian_subagent"] { + let json = format!("\"{value}\""); + let reviewer: ApprovalsReviewer = + serde_json::from_str(&json).expect("deserialize reviewer"); + let expected = if value == "user" { + ApprovalsReviewer::User + } else { + ApprovalsReviewer::GuardianSubagent + }; + assert_eq!(expected, reviewer); + } + } + #[test] fn thread_list_params_accepts_single_cwd() { let params = serde_json::from_value::(json!({ diff --git a/codex-rs/app-server/README.md b/codex-rs/app-server/README.md index 62e490dee..15b7f9a5b 100644 --- a/codex-rs/app-server/README.md +++ b/codex-rs/app-server/README.md @@ -529,7 +529,7 @@ You can optionally specify config overrides on the new turn. If specified, these `approvalsReviewer` accepts: - `"user"` — default. Review approval requests directly in the client. -- `"guardian_subagent"` — route approval requests to a carefully prompted subagent, which gathers relevant context and applies a risk-based decision framework before approving or denying the request. +- `"auto_review"` — route approval requests to a carefully prompted subagent, which gathers relevant context and applies a risk-based decision framework before approving or denying the request. The legacy value `"guardian_subagent"` is still accepted for compatibility. ```json { "method": "turn/start", "id": 30, "params": { diff --git a/codex-rs/config/src/config_requirements.rs b/codex-rs/config/src/config_requirements.rs index 800a68876..ac954a1f4 100644 --- a/codex-rs/config/src/config_requirements.rs +++ b/codex-rs/config/src/config_requirements.rs @@ -1649,7 +1649,7 @@ allowed_approvals_reviewers = ["user"] let source: ConfigRequirementsToml = from_str( r#" allowed_approval_policies = ["on-request"] - allowed_approvals_reviewers = ["guardian_subagent"] + allowed_approvals_reviewers = ["auto_review"] allowed_sandbox_modes = ["read-only"] "#, )?; @@ -1730,7 +1730,7 @@ allowed_approvals_reviewers = ["user"] let source: ConfigRequirementsToml = from_str( r#" allowed_approval_policies = ["on-request"] - allowed_approvals_reviewers = ["guardian_subagent"] + allowed_approvals_reviewers = ["auto_review"] allowed_sandbox_modes = ["read-only"] allowed_web_search_modes = ["cached"] enforce_residency = "us" @@ -1830,7 +1830,7 @@ allowed_approvals_reviewers = ["user"] #[test] fn deserialize_allowed_approvals_reviewers() -> Result<()> { let toml_str = r#" - allowed_approvals_reviewers = ["guardian_subagent", "user"] + allowed_approvals_reviewers = ["auto_review", "user"] "#; let config: ConfigRequirementsToml = from_str(toml_str)?; let requirements: ConfigRequirements = with_unknown_source(config).try_into()?; @@ -1856,6 +1856,22 @@ allowed_approvals_reviewers = ["user"] Ok(()) } + #[test] + fn deserialize_legacy_allowed_approvals_reviewer() -> Result<()> { + let toml_str = r#" + allowed_approvals_reviewers = ["guardian_subagent", "user"] + "#; + let config: ConfigRequirementsToml = from_str(toml_str)?; + let requirements: ConfigRequirements = with_unknown_source(config).try_into()?; + + assert_eq!( + requirements.approvals_reviewer.value(), + ApprovalsReviewer::GuardianSubagent + ); + + Ok(()) + } + #[test] fn empty_allowed_approvals_reviewers_is_rejected() -> Result<()> { let toml_str = r#" diff --git a/codex-rs/core/config.schema.json b/codex-rs/core/config.schema.json index 828120f9d..245a55e1b 100644 --- a/codex-rs/core/config.schema.json +++ b/codex-rs/core/config.schema.json @@ -169,9 +169,10 @@ "type": "object" }, "ApprovalsReviewer": { - "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.", + "description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", "enum": [ "user", + "auto_review", "guardian_subagent" ], "type": "string" diff --git a/codex-rs/core/src/config_loader/mod.rs b/codex-rs/core/src/config_loader/mod.rs index 3b08de32a..d7a215c17 100644 --- a/codex-rs/core/src/config_loader/mod.rs +++ b/codex-rs/core/src/config_loader/mod.rs @@ -1025,8 +1025,8 @@ async fn load_project_layers( /// /// If present, re-interpret `managed_config.toml` as a `requirements.toml` /// where each specified field is treated as a constraint. Most fields allow -/// only the specified value. `approvals_reviewer = "guardian_subagent"` also -/// allows `user` so people can opt out of the guardian reviewer. +/// only the specified value. `approvals_reviewer = "auto_review"` also allows +/// `user` so people can opt out of the auto-reviewer. #[derive(Deserialize, Debug, Clone, Default, PartialEq)] struct LegacyManagedConfigToml { approval_policy: Option, @@ -1145,7 +1145,7 @@ foo = "xyzzy" requirements.allowed_approvals_reviewers, Some(vec![ ApprovalsReviewer::GuardianSubagent, - ApprovalsReviewer::User + ApprovalsReviewer::User, ]) ); } diff --git a/codex-rs/protocol/src/config_types.rs b/codex-rs/protocol/src/config_types.rs index 5fd09c24b..5c407d996 100644 --- a/codex-rs/protocol/src/config_types.rs +++ b/codex-rs/protocol/src/config_types.rs @@ -1,7 +1,13 @@ use codex_utils_absolute_path::AbsolutePathBuf; use schemars::JsonSchema; +use schemars::r#gen::SchemaGenerator; +use schemars::schema::InstanceType; +use schemars::schema::Metadata; +use schemars::schema::Schema; +use schemars::schema::SchemaObject; use serde::Deserialize; use serde::Serialize; +use serde_json::Value; use std::num::NonZeroU64; use std::time::Duration; use strum_macros::Display; @@ -69,22 +75,54 @@ pub enum SandboxMode { DangerFullAccess, } -#[derive( - Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Display, JsonSchema, TS, -)] -#[serde(rename_all = "snake_case")] +#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Display, TS)] #[strum(serialize_all = "snake_case")] +#[ts(type = r#""user" | "auto_review" | "guardian_subagent""#)] /// Configures who approval requests are routed to for review. Examples /// include sandbox escapes, blocked network access, MCP approval prompts, and -/// ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully +/// ARC escalations. Defaults to `user`. `auto_review` uses a carefully /// prompted subagent to gather relevant context and apply a risk-based /// decision framework before approving or denying the request. pub enum ApprovalsReviewer { #[default] + #[serde(rename = "user")] User, + #[serde(rename = "auto_review", alias = "guardian_subagent")] + #[strum(serialize = "auto_review")] GuardianSubagent, } +impl JsonSchema for ApprovalsReviewer { + fn schema_name() -> String { + "ApprovalsReviewer".to_string() + } + + fn json_schema(_generator: &mut SchemaGenerator) -> Schema { + string_enum_schema_with_description( + &["user", "auto_review", "guardian_subagent"], + "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.", + ) + } +} + +fn string_enum_schema_with_description(values: &[&str], description: &str) -> Schema { + let mut schema = SchemaObject { + instance_type: Some(InstanceType::String.into()), + metadata: Some(Box::new(Metadata { + description: Some(description.to_string()), + ..Default::default() + })), + ..Default::default() + }; + schema.enum_values = Some( + values + .iter() + .map(|value| Value::String((*value).to_string())) + .collect(), + ); + Schema::Object(schema) +} + #[derive( Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Display, JsonSchema, TS, )] @@ -562,6 +600,32 @@ mod tests { } } + #[test] + fn approvals_reviewer_serializes_auto_review_and_accepts_legacy_guardian_subagent() { + assert_eq!(ApprovalsReviewer::User.to_string(), "user"); + assert_eq!( + serde_json::to_string(&ApprovalsReviewer::User).expect("serialize reviewer"), + "\"user\"" + ); + assert_eq!( + serde_json::to_string(&ApprovalsReviewer::GuardianSubagent) + .expect("serialize reviewer"), + "\"auto_review\"" + ); + + for value in ["user", "auto_review", "guardian_subagent"] { + let json = format!("\"{value}\""); + let reviewer: ApprovalsReviewer = + serde_json::from_str(&json).expect("deserialize reviewer"); + let expected = if value == "user" { + ApprovalsReviewer::User + } else { + ApprovalsReviewer::GuardianSubagent + }; + assert_eq!(expected, reviewer); + } + } + #[test] fn tui_visible_collaboration_modes_match_mode_kind_visibility() { let expected = [ModeKind::Default, ModeKind::Plan]; diff --git a/codex-rs/tui/src/app/tests.rs b/codex-rs/tui/src/app/tests.rs index a1a658a24..87b7faa34 100644 --- a/codex-rs/tui/src/app/tests.rs +++ b/codex-rs/tui/src/app/tests.rs @@ -1675,7 +1675,7 @@ async fn update_feature_flags_enabling_guardian_selects_guardian_approvals() -> let config = std::fs::read_to_string(codex_home.path().join("config.toml"))?; assert!(config.contains("guardian_approval = true")); - assert!(config.contains("approvals_reviewer = \"guardian_subagent\"")); + assert!(config.contains("approvals_reviewer = \"auto_review\"")); assert!(config.contains("approval_policy = \"on-request\"")); assert!(config.contains("sandbox_mode = \"workspace-write\"")); Ok(()) @@ -1835,7 +1835,7 @@ async fn update_feature_flags_enabling_guardian_overrides_explicit_manual_review ); let config = std::fs::read_to_string(codex_home.path().join("config.toml"))?; - assert!(config.contains("approvals_reviewer = \"guardian_subagent\"")); + assert!(config.contains("approvals_reviewer = \"auto_review\"")); assert!(config.contains("guardian_approval = true")); assert!(config.contains("approval_policy = \"on-request\"")); assert!(config.contains("sandbox_mode = \"workspace-write\"")); @@ -1969,7 +1969,7 @@ async fn update_feature_flags_enabling_guardian_in_profile_sets_profile_auto_rev ); assert_eq!( profile_config.get("approvals_reviewer"), - Some(&TomlValue::String("guardian_subagent".to_string())) + Some(&TomlValue::String("auto_review".to_string())) ); Ok(()) } diff --git a/codex-rs/tui/src/debug_config.rs b/codex-rs/tui/src/debug_config.rs index b16121c59..057611af2 100644 --- a/codex-rs/tui/src/debug_config.rs +++ b/codex-rs/tui/src/debug_config.rs @@ -690,7 +690,7 @@ mod tests { rendered.contains("allowed_approval_policies: on-request (source: cloud requirements)") ); assert!(rendered.contains( - "allowed_approvals_reviewers: guardian_subagent (source: MDM managed_config.toml (legacy))" + "allowed_approvals_reviewers: auto_review (source: MDM managed_config.toml (legacy))" )); assert!( rendered.contains( @@ -745,7 +745,7 @@ mod tests { let rendered = render_to_text(&render_debug_config_lines(&stack)); assert!(rendered.contains( - "allowed_approvals_reviewers: guardian_subagent (source: MDM managed_config.toml (legacy))" + "allowed_approvals_reviewers: auto_review (source: MDM managed_config.toml (legacy))" )); assert!(!rendered.contains("Requirements:\n ")); }