diff --git a/codex-rs/core/src/config/config_tests.rs b/codex-rs/core/src/config/config_tests.rs index 044c6c828..500483f65 100644 --- a/codex-rs/core/src/config/config_tests.rs +++ b/codex-rs/core/src/config/config_tests.rs @@ -3628,8 +3628,7 @@ async fn set_feature_enabled_updates_profile() -> anyhow::Result<()> { } #[tokio::test] -async fn set_feature_enabled_persists_default_false_feature_disable_in_profile() --> anyhow::Result<()> { +async fn set_feature_enabled_persists_feature_disable_in_profile() -> anyhow::Result<()> { let codex_home = TempDir::new()?; ConfigEditsBuilder::new(codex_home.path()) @@ -6881,7 +6880,7 @@ smart_approvals = true .build() .await?; - assert!(!config.features.enabled(Feature::GuardianApproval)); + assert!(config.features.enabled(Feature::GuardianApproval)); assert_eq!(config.approvals_reviewer, ApprovalsReviewer::User); let serialized = tokio::fs::read_to_string(codex_home.path().join(CONFIG_TOML_FILE)).await?; @@ -6910,7 +6909,7 @@ smart_approvals = true .build() .await?; - assert!(!config.features.enabled(Feature::GuardianApproval)); + assert!(config.features.enabled(Feature::GuardianApproval)); assert_eq!(config.approvals_reviewer, ApprovalsReviewer::User); let serialized = tokio::fs::read_to_string(codex_home.path().join(CONFIG_TOML_FILE)).await?; diff --git a/codex-rs/features/src/lib.rs b/codex-rs/features/src/lib.rs index 18f3eef9e..9b9dddfc9 100644 --- a/codex-rs/features/src/lib.rs +++ b/codex-rs/features/src/lib.rs @@ -917,12 +917,8 @@ pub const FEATURES: &[FeatureSpec] = &[ FeatureSpec { id: Feature::GuardianApproval, key: "guardian_approval", - stage: Stage::Experimental { - name: "Auto-review", - menu_description: "When Codex needs approval for higher-risk actions (e.g. sandbox escapes or blocked network access), route eligible approval requests to a carefully-prompted security reviewer subagent rather than blocking the agent on your input. This can consume significantly more tokens because it runs a subagent on every approval request.", - announcement: "", - }, - default_enabled: false, + stage: Stage::Stable, + default_enabled: true, }, FeatureSpec { id: Feature::CollaborationModes, diff --git a/codex-rs/features/src/tests.rs b/codex-rs/features/src/tests.rs index 276e573ab..f5704dd71 100644 --- a/codex-rs/features/src/tests.rs +++ b/codex-rs/features/src/tests.rs @@ -87,20 +87,11 @@ fn code_mode_only_requires_code_mode() { } #[test] -fn guardian_approval_is_experimental_and_user_toggleable() { +fn guardian_approval_is_stable_and_enabled_by_default() { let spec = Feature::GuardianApproval.info(); - let stage = spec.stage; - assert!(matches!(stage, Stage::Experimental { .. })); - assert_eq!(stage.experimental_menu_name(), Some("Auto-review")); - assert_eq!( - stage.experimental_menu_description().map(str::to_owned), - Some( - "When Codex needs approval for higher-risk actions (e.g. sandbox escapes or blocked network access), route eligible approval requests to a carefully-prompted security reviewer subagent rather than blocking the agent on your input. This can consume significantly more tokens because it runs a subagent on every approval request.".to_string() - ) - ); - assert_eq!(stage.experimental_announcement(), None); - assert_eq!(Feature::GuardianApproval.default_enabled(), false); + assert_eq!(spec.stage, Stage::Stable); + assert_eq!(Feature::GuardianApproval.default_enabled(), true); } #[test] diff --git a/codex-rs/tui/src/chatwidget/tests/permissions.rs b/codex-rs/tui/src/chatwidget/tests/permissions.rs index 7ea604770..f9fcd3179 100644 --- a/codex-rs/tui/src/chatwidget/tests/permissions.rs +++ b/codex-rs/tui/src/chatwidget/tests/permissions.rs @@ -401,7 +401,7 @@ async fn permissions_selection_hides_auto_review_when_feature_disabled() { assert!( !popup.contains("Auto-review"), - "expected Auto-review to stay hidden until the experimental feature is enabled: {popup}" + "expected Auto-review to stay hidden until the feature is enabled: {popup}" ); } @@ -433,7 +433,7 @@ async fn permissions_selection_hides_auto_review_when_feature_disabled_even_if_a assert!( !popup.contains("Auto-review"), - "expected Auto-review to stay hidden when the experimental feature is disabled: {popup}" + "expected Auto-review to stay hidden when the feature is disabled: {popup}" ); } diff --git a/codex-rs/tui/src/chatwidget/tests/popups_and_settings.rs b/codex-rs/tui/src/chatwidget/tests/popups_and_settings.rs index e891e4391..776741d05 100644 --- a/codex-rs/tui/src/chatwidget/tests/popups_and_settings.rs +++ b/codex-rs/tui/src/chatwidget/tests/popups_and_settings.rs @@ -1,5 +1,6 @@ use super::*; use codex_app_server_protocol::AppInfo; +use codex_features::Stage; use pretty_assertions::assert_eq; #[tokio::test] @@ -1747,31 +1748,22 @@ async fn experimental_popup_shows_js_repl_node_requirement() { } #[tokio::test] -async fn experimental_popup_includes_guardian_approval() { +async fn experimental_popup_omits_stable_guardian_approval() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; let guardian_stage = FEATURES .iter() .find(|spec| spec.id == Feature::GuardianApproval) .map(|spec| spec.stage) .expect("expected guardian approval feature metadata"); - let guardian_name = guardian_stage - .experimental_menu_name() - .expect("expected guardian approval experimental menu name"); - let guardian_description = guardian_stage - .experimental_menu_description() - .expect("expected guardian approval experimental description"); + + assert_eq!(guardian_stage, Stage::Stable); chat.open_experimental_popup(); let popup = render_bottom_popup(&chat, /*width*/ 120); - let normalized_popup = popup.split_whitespace().collect::>().join(" "); assert!( - popup.contains(guardian_name), - "expected auto-review entry in experimental popup, got:\n{popup}" - ); - assert!( - normalized_popup.contains(guardian_description), - "expected auto-review description in experimental popup, got:\n{popup}" + !popup.contains("Auto-review"), + "expected stable auto-review feature to be omitted from experimental popup, got:\n{popup}" ); }