From 8d3992d830fd9db59180c00fa7baea8e7a568e3a Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Tue, 28 Apr 2026 17:11:17 -0700 Subject: [PATCH] core tests: migrate plan item turns to profiles (#20026) ## Why The core item tests still had a cluster of plan-mode `Op::UserTurn` literals that used `SandboxPolicy::DangerFullAccess` and omitted `permission_profile`. These tests are validating emitted item lifecycle events, so keeping them on the legacy sandbox-only turn shape adds noise to the broader permissions migration without testing legacy behavior. ## What Changed - Adds a local `disabled_plan_turn()` helper that preserves the existing `std::env::current_dir()` turn cwd behavior. - Uses `turn_permission_fields(PermissionProfile::Disabled, cwd)` to populate both the compatibility `sandbox_policy` and canonical `permission_profile` fields. - Replaces the plan-mode hand-built turns in `codex-rs/core/tests/suite/items.rs`, removing all `SandboxPolicy` references from that file and reducing remaining `codex-rs/core/tests` `SandboxPolicy` files from 16 to 15. ## Verification - `cargo check -p codex-core --tests` --- codex-rs/core/tests/suite/items.rs | 152 +++++++++++------------------ 1 file changed, 57 insertions(+), 95 deletions(-) diff --git a/codex-rs/core/tests/suite/items.rs b/codex-rs/core/tests/suite/items.rs index db4f7d758..053f03ca9 100644 --- a/codex-rs/core/tests/suite/items.rs +++ b/codex-rs/core/tests/suite/items.rs @@ -6,7 +6,9 @@ use codex_protocol::config_types::ModeKind; use codex_protocol::config_types::Settings; use codex_protocol::items::AgentMessageContent; use codex_protocol::items::TurnItem; +use codex_protocol::models::PermissionProfile; use codex_protocol::models::WebSearchAction; +use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::ItemCompletedEvent; use codex_protocol::protocol::ItemStartedEvent; @@ -33,12 +35,42 @@ use core_test_support::responses::start_mock_server; use core_test_support::skip_if_no_network; use core_test_support::test_codex::TestCodex; use core_test_support::test_codex::test_codex; +use core_test_support::test_codex::turn_permission_fields; use core_test_support::wait_for_event; use core_test_support::wait_for_event_match; use pretty_assertions::assert_eq; use std::path::Path; use std::path::PathBuf; +fn disabled_plan_turn( + text: &str, + model: String, + collaboration_mode: CollaborationMode, +) -> anyhow::Result { + let cwd = std::env::current_dir()?; + let (sandbox_policy, permission_profile) = + turn_permission_fields(PermissionProfile::Disabled, cwd.as_path()); + Ok(Op::UserTurn { + environments: None, + items: vec![UserInput::Text { + text: text.into(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + cwd, + approval_policy: AskForApproval::Never, + approvals_reviewer: None, + sandbox_policy, + permission_profile, + model, + effort: None, + summary: None, + service_tier: None, + collaboration_mode: Some(collaboration_mode), + personality: None, + }) +} + fn image_generation_artifact_path(codex_home: &Path, session_id: &str, call_id: &str) -> PathBuf { fn sanitize(value: &str) -> String { let mut sanitized: String = value @@ -529,25 +561,11 @@ async fn plan_mode_emits_plan_item_from_proposed_plan_block() -> anyhow::Result< }; codex - .submit(Op::UserTurn { - environments: None, - items: vec![UserInput::Text { - text: "please plan".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - cwd: std::env::current_dir()?, - approval_policy: codex_protocol::protocol::AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess, - permission_profile: None, - model: session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: Some(collaboration_mode), - personality: None, - }) + .submit(disabled_plan_turn( + "please plan", + session_configured.model.clone(), + collaboration_mode, + )?) .await?; let plan_delta = wait_for_event_match(&codex, |ev| match ev { @@ -608,25 +626,11 @@ async fn plan_mode_strips_plan_from_agent_messages() -> anyhow::Result<()> { }; codex - .submit(Op::UserTurn { - environments: None, - items: vec![UserInput::Text { - text: "please plan".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - cwd: std::env::current_dir()?, - approval_policy: codex_protocol::protocol::AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess, - permission_profile: None, - model: session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: Some(collaboration_mode), - personality: None, - }) + .submit(disabled_plan_turn( + "please plan", + session_configured.model.clone(), + collaboration_mode, + )?) .await?; let mut agent_deltas = Vec::new(); @@ -719,25 +723,11 @@ async fn plan_mode_streaming_citations_are_stripped_across_added_deltas_and_done }; codex - .submit(Op::UserTurn { - environments: None, - items: vec![UserInput::Text { - text: "please plan with citations".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - cwd: std::env::current_dir()?, - approval_policy: codex_protocol::protocol::AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess, - permission_profile: None, - model: session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: Some(collaboration_mode), - personality: None, - }) + .submit(disabled_plan_turn( + "please plan with citations", + session_configured.model.clone(), + collaboration_mode, + )?) .await?; let mut agent_started = None; @@ -908,25 +898,11 @@ async fn plan_mode_streaming_proposed_plan_tag_split_across_added_and_delta_is_p }; codex - .submit(Op::UserTurn { - environments: None, - items: vec![UserInput::Text { - text: "please plan".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - cwd: std::env::current_dir()?, - approval_policy: codex_protocol::protocol::AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess, - permission_profile: None, - model: session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: Some(collaboration_mode), - personality: None, - }) + .submit(disabled_plan_turn( + "please plan", + session_configured.model.clone(), + collaboration_mode, + )?) .await?; let mut agent_started = None; @@ -1024,25 +1000,11 @@ async fn plan_mode_handles_missing_plan_close_tag() -> anyhow::Result<()> { }; codex - .submit(Op::UserTurn { - environments: None, - items: vec![UserInput::Text { - text: "please plan".into(), - text_elements: Vec::new(), - }], - final_output_json_schema: None, - cwd: std::env::current_dir()?, - approval_policy: codex_protocol::protocol::AskForApproval::Never, - approvals_reviewer: None, - sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess, - permission_profile: None, - model: session_configured.model.clone(), - effort: None, - summary: None, - service_tier: None, - collaboration_mode: Some(collaboration_mode), - personality: None, - }) + .submit(disabled_plan_turn( + "please plan", + session_configured.model.clone(), + collaboration_mode, + )?) .await?; let mut plan_delta = None;