Compare commits

...

2 Commits

Author SHA1 Message Date
Dylan Hurd
cac26a2048 codex: fix CI failure on PR #22780 2026-05-16 00:44:55 -07:00
Dylan Hurd
acdb0c3a07 Remove personality feature switch
Co-authored-by: Codex <noreply@openai.com>
2026-05-16 00:22:34 -07:00
16 changed files with 36 additions and 254 deletions

View File

@@ -206,12 +206,7 @@ async fn turn_start_sends_originator_header() -> Result<()> {
let server = create_mock_responses_server_sequence_unchecked(responses).await;
let codex_home = TempDir::new()?;
create_config_toml(
codex_home.path(),
&server.uri(),
"never",
&BTreeMap::from([(Feature::Personality, true)]),
)?;
create_config_toml(codex_home.path(), &server.uri(), "never", &BTreeMap::new())?;
let mut mcp = McpProcess::new(codex_home.path()).await?;
timeout(
@@ -282,12 +277,7 @@ async fn turn_start_emits_user_message_item_with_text_elements() -> Result<()> {
let server = create_mock_responses_server_sequence_unchecked(responses).await;
let codex_home = TempDir::new()?;
create_config_toml(
codex_home.path(),
&server.uri(),
"never",
&BTreeMap::from([(Feature::Personality, true)]),
)?;
create_config_toml(codex_home.path(), &server.uri(), "never", &BTreeMap::new())?;
let mut mcp = McpProcess::new(codex_home.path()).await?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
@@ -369,12 +359,7 @@ async fn turn_start_emits_thread_scoped_warning_notification_for_trimmed_skills(
let server = create_mock_responses_server_sequence_unchecked(responses).await;
let codex_home = TempDir::new()?;
create_config_toml(
codex_home.path(),
&server.uri(),
"never",
&BTreeMap::from([(Feature::Personality, true)]),
)?;
create_config_toml(codex_home.path(), &server.uri(), "never", &BTreeMap::new())?;
write_models_cache(codex_home.path())?;
let cache_path = codex_home.path().join("models_cache.json");
let mut cache: serde_json::Value =
@@ -722,12 +707,7 @@ async fn turn_start_accepts_text_at_limit_with_mention_item() -> Result<()> {
let server = create_mock_responses_server_sequence_unchecked(responses).await;
let codex_home = TempDir::new()?;
create_config_toml(
codex_home.path(),
&server.uri(),
"never",
&BTreeMap::from([(Feature::Personality, true)]),
)?;
create_config_toml(codex_home.path(), &server.uri(), "never", &BTreeMap::new())?;
let mut mcp = McpProcess::new(codex_home.path()).await?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
@@ -785,7 +765,7 @@ async fn turn_start_rejects_combined_oversized_text_input() -> Result<()> {
codex_home.path(),
"http://localhost/unused",
"never",
&BTreeMap::from([(Feature::Personality, true)]),
&BTreeMap::new(),
)?;
let mut mcp = McpProcess::new(codex_home.path()).await?;
@@ -860,7 +840,7 @@ async fn turn_start_rejects_invalid_permission_selection_before_starting_turn()
codex_home.path(),
"http://localhost/unused",
"never",
&BTreeMap::from([(Feature::Personality, true)]),
&BTreeMap::new(),
)?;
std::fs::write(
codex_home.path().join("managed_config.toml"),
@@ -998,12 +978,7 @@ async fn turn_start_emits_notifications_and_accepts_model_override() -> Result<(
let server = create_mock_responses_server_sequence_unchecked(responses).await;
let codex_home = TempDir::new()?;
create_config_toml(
codex_home.path(),
&server.uri(),
"never",
&BTreeMap::from([(Feature::Personality, true)]),
)?;
create_config_toml(codex_home.path(), &server.uri(), "never", &BTreeMap::new())?;
let mut mcp = McpProcess::new(codex_home.path()).await?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
@@ -1310,12 +1285,7 @@ async fn turn_start_accepts_personality_override_v2() -> Result<()> {
let response_mock = responses::mount_sse_once(&server, body).await;
let codex_home = TempDir::new()?;
create_config_toml(
codex_home.path(),
&server.uri(),
"never",
&BTreeMap::from([(Feature::Personality, true)]),
)?;
create_config_toml(codex_home.path(), &server.uri(), "never", &BTreeMap::new())?;
let mut mcp = McpProcess::new(codex_home.path()).await?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
@@ -1391,12 +1361,7 @@ async fn turn_start_change_personality_mid_thread_v2() -> Result<()> {
let response_mock = responses::mount_sse_sequence(&server, vec![sse1, sse2]).await;
let codex_home = TempDir::new()?;
create_config_toml(
codex_home.path(),
&server.uri(),
"never",
&BTreeMap::from([(Feature::Personality, true)]),
)?;
create_config_toml(codex_home.path(), &server.uri(), "never", &BTreeMap::new())?;
let mut mcp = McpProcess::new(codex_home.path()).await?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
@@ -1497,12 +1462,7 @@ async fn turn_start_uses_migrated_pragmatic_personality_without_override_v2() ->
let response_mock = responses::mount_sse_once(&server, body).await;
let codex_home = TempDir::new()?;
create_config_toml(
codex_home.path(),
&server.uri(),
"never",
&BTreeMap::from([(Feature::Personality, true)]),
)?;
create_config_toml(codex_home.path(), &server.uri(), "never", &BTreeMap::new())?;
create_fake_rollout(
codex_home.path(),
"2025-01-01T00-00-00",
@@ -3643,12 +3603,7 @@ async fn turn_start_with_elevated_override_does_not_persist_project_trust() -> R
let server = create_mock_responses_server_sequence_unchecked(responses).await;
let codex_home = TempDir::new()?;
create_config_toml(
codex_home.path(),
&server.uri(),
"never",
&BTreeMap::from([(Feature::Personality, true)]),
)?;
create_config_toml(codex_home.path(), &server.uri(), "never", &BTreeMap::new())?;
let workspace = TempDir::new()?;

View File

@@ -9599,7 +9599,7 @@ async fn feature_requirements_normalize_effective_feature_values() -> std::io::R
Ok(Some(codex_config::ConfigRequirementsToml {
feature_requirements: Some(codex_config::FeatureRequirementsToml {
entries: BTreeMap::from([
("personality".to_string(), true),
("memories".to_string(), true),
("shell_tool".to_string(), false),
]),
}),
@@ -9609,7 +9609,7 @@ async fn feature_requirements_normalize_effective_feature_values() -> std::io::R
.build()
.await?;
assert!(config.features.enabled(Feature::Personality));
assert!(config.features.enabled(Feature::MemoryTool));
assert!(!config.features.enabled(Feature::ShellTool));
assert!(
!config
@@ -9749,7 +9749,7 @@ async fn explicit_feature_config_is_normalized_by_requirements() -> std::io::Res
codex_home.path().join(CONFIG_TOML_FILE),
r#"
[features]
personality = false
memories = false
shell_tool = true
"#,
)?;
@@ -9761,7 +9761,7 @@ shell_tool = true
Ok(Some(codex_config::ConfigRequirementsToml {
feature_requirements: Some(codex_config::FeatureRequirementsToml {
entries: BTreeMap::from([
("personality".to_string(), true),
("memories".to_string(), true),
("shell_tool".to_string(), false),
]),
}),
@@ -9771,7 +9771,7 @@ shell_tool = true
.build()
.await?;
assert!(config.features.enabled(Feature::Personality));
assert!(config.features.enabled(Feature::MemoryTool));
assert!(!config.features.enabled(Feature::ShellTool));
assert!(
!config
@@ -10477,7 +10477,7 @@ async fn feature_requirements_normalize_runtime_feature_mutations() -> std::io::
Ok(Some(codex_config::ConfigRequirementsToml {
feature_requirements: Some(codex_config::FeatureRequirementsToml {
entries: BTreeMap::from([
("personality".to_string(), true),
("memories".to_string(), true),
("shell_tool".to_string(), false),
]),
}),
@@ -10489,7 +10489,7 @@ async fn feature_requirements_normalize_runtime_feature_mutations() -> std::io::
let mut requested = config.features.get().clone();
requested
.disable(Feature::Personality)
.disable(Feature::MemoryTool)
.enable(Feature::ShellTool);
assert!(config.features.can_set(&requested).is_ok());
config
@@ -10497,7 +10497,7 @@ async fn feature_requirements_normalize_runtime_feature_mutations() -> std::io::
.set(requested)
.expect("managed feature mutations should normalize successfully");
assert!(config.features.enabled(Feature::Personality));
assert!(config.features.enabled(Feature::MemoryTool));
assert!(!config.features.enabled(Feature::ShellTool));
Ok(())

View File

@@ -1247,7 +1247,6 @@ impl Config {
model_auto_compact_token_limit: self.model_auto_compact_token_limit,
tool_output_token_limit: self.tool_output_token_limit,
base_instructions: self.base_instructions.clone(),
personality_enabled: self.features.enabled(Feature::Personality),
model_supports_reasoning_summaries: self.model_supports_reasoning_summaries,
model_catalog: self.model_catalog.clone(),
}
@@ -3127,11 +3126,7 @@ impl Config {
let personality = personality
.or(config_profile.personality)
.or(cfg.personality)
.or_else(|| {
features
.enabled(Feature::Personality)
.then_some(Personality::Pragmatic)
});
.or(Some(Personality::Pragmatic));
let experimental_compact_prompt_path = config_profile
.experimental_compact_prompt_file

View File

@@ -1572,7 +1572,7 @@ impl Session {
current_context,
shell.as_ref(),
exec_policy.as_ref(),
self.features.enabled(Feature::Personality),
/*personality_feature_enabled*/ true,
)
}
@@ -2704,9 +2704,7 @@ impl Session {
) {
developer_sections.push(realtime_update);
}
if self.features.enabled(Feature::Personality)
&& let Some(personality) = turn_context.personality
{
if let Some(personality) = turn_context.personality {
let model_info = turn_context.model_info.clone();
let has_baked_personality = model_info.supports_personality()
&& base_instructions == model_info.get_model_instructions(Some(personality));

View File

@@ -9293,7 +9293,6 @@ async fn sample_rollout(
matches!(c, ContentItem::InputText { text } if text.contains("<personality_spec>"))
}))
}) && let Some(p) = reconstruction_turn.personality
&& session.features.enabled(Feature::Personality)
&& let Some(personality_message) = reconstruction_turn
.model_info
.model_messages

View File

@@ -1,6 +1,5 @@
use anyhow::Result;
use codex_config::types::Personality;
use codex_features::Feature;
use codex_login::CodexAuth;
use codex_models_manager::manager::RefreshStrategy;
use codex_protocol::config_types::ReasoningSummary;
@@ -213,14 +212,7 @@ async fn model_and_personality_change_only_appends_model_instructions() -> Resul
)
.await;
let mut builder = test_codex()
.with_model("gpt-5.3-codex")
.with_config(|config| {
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
});
let mut builder = test_codex().with_model("gpt-5.3-codex");
let test = builder.build(&server).await?;
let next_model = "exp-codex-personality";

View File

@@ -5,7 +5,6 @@ use std::sync::Arc;
use anyhow::Result;
use codex_config::types::Personality;
use codex_features::Feature;
use codex_protocol::models::PermissionProfile;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::EventMsg;
@@ -103,10 +102,6 @@ async fn snapshot_model_visible_layout_turn_overrides() -> Result<()> {
let mut builder = test_codex()
.with_model("gpt-5.3-codex")
.with_config(|config| {
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
config.personality = Some(Personality::Pragmatic);
});
let test = builder.build(&server).await?;
@@ -361,10 +356,6 @@ async fn snapshot_model_visible_layout_resume_with_personality_change() -> Resul
let mut resume_builder = test_codex().with_config(|config| {
config.model = Some("gpt-5.3-codex".to_string());
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
config.personality = Some(Personality::Pragmatic);
});
let resumed = resume_builder.resume(&server, home, rollout_path).await?;

View File

@@ -1,5 +1,4 @@
use codex_config::types::Personality;
use codex_features::Feature;
use codex_models_manager::manager::RefreshStrategy;
use codex_models_manager::manager::SharedModelsManager;
use codex_protocol::config_types::ReasoningSummary;
@@ -85,10 +84,6 @@ fn read_only_text_turn_with_personality(
async fn personality_does_not_mutate_base_instructions_without_template() {
let codex_home = TempDir::new().expect("create temp dir");
let mut config = load_default_config_for_test(&codex_home).await;
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
config.personality = Some(Personality::Friendly);
let model_info = codex_core::test_support::construct_model_info_offline("gpt-5.4", &config);
@@ -102,10 +97,6 @@ async fn personality_does_not_mutate_base_instructions_without_template() {
async fn base_instructions_override_disables_personality_template() {
let codex_home = TempDir::new().expect("create temp dir");
let mut config = load_default_config_for_test(&codex_home).await;
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
config.personality = Some(Personality::Friendly);
config.base_instructions = Some("override instructions".to_string());
@@ -125,14 +116,7 @@ async fn user_turn_personality_none_does_not_add_update_message() -> anyhow::Res
let server = start_mock_server().await;
let resp_mock = mount_sse_once(&server, sse_completed("resp-1")).await;
let mut builder = test_codex()
.with_model("gpt-5.3-codex")
.with_config(|config| {
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
});
let mut builder = test_codex().with_model("gpt-5.3-codex");
let test = builder.build(&server).await?;
test.codex
@@ -167,10 +151,6 @@ async fn config_personality_some_sets_instructions_template() -> anyhow::Result<
let mut builder = test_codex()
.with_model("gpt-5.3-codex")
.with_config(|config| {
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
config.personality = Some(Personality::Friendly);
});
let test = builder.build(&server).await?;
@@ -214,10 +194,6 @@ async fn config_personality_none_sends_no_personality() -> anyhow::Result<()> {
let mut builder = test_codex()
.with_model("gpt-5.3-codex")
.with_config(|config| {
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
config.personality = Some(Personality::None);
});
let test = builder.build(&server).await?;
@@ -265,14 +241,7 @@ async fn default_personality_is_pragmatic_without_config_toml() -> anyhow::Resul
let server = start_mock_server().await;
let resp_mock = mount_sse_once(&server, sse_completed("resp-1")).await;
let mut builder = test_codex()
.with_model("gpt-5.3-codex")
.with_config(|config| {
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
});
let mut builder = test_codex().with_model("gpt-5.3-codex");
let test = builder.build(&server).await?;
test.codex
@@ -306,14 +275,7 @@ async fn user_turn_personality_some_adds_update_message() -> anyhow::Result<()>
vec![sse_completed("resp-1"), sse_completed("resp-2")],
)
.await;
let mut builder = test_codex()
.with_model("exp-codex-personality")
.with_config(|config| {
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
});
let mut builder = test_codex().with_model("exp-codex-personality");
let test = builder.build(&server).await?;
test.codex
@@ -392,10 +354,6 @@ async fn user_turn_personality_same_value_does_not_add_update_message() -> anyho
let mut builder = test_codex()
.with_model("exp-codex-personality")
.with_config(|config| {
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
config.personality = Some(Personality::Pragmatic);
});
let test = builder.build(&server).await?;
@@ -457,102 +415,6 @@ async fn user_turn_personality_same_value_does_not_add_update_message() -> anyho
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn instructions_uses_base_if_feature_disabled() -> anyhow::Result<()> {
let codex_home = TempDir::new().expect("create temp dir");
let mut config = load_default_config_for_test(&codex_home).await;
config
.features
.disable(Feature::Personality)
.expect("test config should allow feature update");
config.personality = Some(Personality::Friendly);
let model_info =
codex_core::test_support::construct_model_info_offline("gpt-5.3-codex", &config);
assert_eq!(
model_info.get_model_instructions(config.personality),
model_info.base_instructions
);
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn user_turn_personality_skips_if_feature_disabled() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
let resp_mock = mount_sse_sequence(
&server,
vec![sse_completed("resp-1"), sse_completed("resp-2")],
)
.await;
let mut builder = test_codex()
.with_model("exp-codex-personality")
.with_config(|config| {
config
.features
.disable(Feature::Personality)
.expect("test config should allow feature update");
});
let test = builder.build(&server).await?;
test.codex
.submit(read_only_text_turn(
&test,
"hello",
test.session_configured.model.clone(),
test.config.permissions.approval_policy.value(),
))
.await?;
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
test.codex
.submit(Op::OverrideTurnContext {
cwd: None,
approval_policy: None,
approvals_reviewer: None,
sandbox_policy: None,
permission_profile: None,
windows_sandbox_level: None,
model: None,
effort: None,
summary: None,
service_tier: None,
collaboration_mode: None,
personality: Some(Personality::Pragmatic),
})
.await?;
test.codex
.submit(read_only_text_turn(
&test,
"hello",
test.session_configured.model.clone(),
test.config.permissions.approval_policy.value(),
))
.await?;
wait_for_event(&test.codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
let requests = resp_mock.requests();
assert_eq!(requests.len(), 2, "expected two requests");
let request = requests
.last()
.expect("expected personality update request");
let developer_texts = request.message_input_texts("developer");
let personality_text = developer_texts
.iter()
.find(|text| text.contains("<personality_spec>"));
assert!(
personality_text.is_none(),
"expected no personality preamble, got {personality_text:?}"
);
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn remote_model_friendly_personality_instructions_with_feature() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
@@ -623,10 +485,6 @@ async fn remote_model_friendly_personality_instructions_with_feature() -> anyhow
let mut builder = test_codex()
.with_auth(codex_login::CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_config(|config| {
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
config.model = Some(remote_slug.to_string());
config.personality = Some(Personality::Friendly);
});
@@ -736,10 +594,6 @@ async fn user_turn_personality_remote_model_template_includes_update_message() -
let mut builder = test_codex()
.with_auth(codex_login::CodexAuth::create_dummy_chatgpt_auth_for_testing())
.with_config(|config| {
config
.features
.enable(Feature::Personality)
.expect("test config should allow feature update");
config.model = Some("gpt-5.3-codex".to_string());
});
let test = builder.build(&server).await?;

View File

@@ -182,7 +182,7 @@ pub enum Feature {
ToolCallMcpElicitation,
/// Prompt Codex Apps connector auth failures through MCP URL elicitations.
AuthElicitation,
/// Enable personality selection in the TUI.
/// Removed compatibility flag. Personality selection is always enabled.
Personality,
/// Enable native artifact tools.
Artifact,
@@ -1099,7 +1099,7 @@ pub const FEATURES: &[FeatureSpec] = &[
FeatureSpec {
id: Feature::Personality,
key: "personality",
stage: Stage::Stable,
stage: Stage::Removed,
default_enabled: true,
},
FeatureSpec {

View File

@@ -76,6 +76,12 @@ fn apply_patch_freeform_is_removed_and_disabled_by_default() {
);
}
#[test]
fn personality_is_removed_and_enabled_by_default() {
assert_eq!(Feature::Personality.stage(), Stage::Removed);
assert_eq!(Feature::Personality.default_enabled(), true);
}
#[test]
fn code_mode_only_requires_code_mode() {
let mut features = Features::with_defaults();

View File

@@ -6,7 +6,6 @@ pub struct ModelsManagerConfig {
pub model_auto_compact_token_limit: Option<i64>,
pub tool_output_token_limit: Option<usize>,
pub base_instructions: Option<String>,
pub personality_enabled: bool,
pub model_supports_reasoning_summaries: Option<bool>,
pub model_catalog: Option<ModelsResponse>,
}

View File

@@ -55,8 +55,6 @@ pub fn with_config_overrides(mut model: ModelInfo, config: &ModelsManagerConfig)
if let Some(base_instructions) = &config.base_instructions {
model.base_instructions = base_instructions.clone();
model.model_messages = None;
} else if !config.personality_enabled {
model.model_messages = None;
}
model

View File

@@ -329,7 +329,6 @@ impl ChatWidget {
let personality = self
.config
.personality
.filter(|_| self.config.features.enabled(Feature::Personality))
.filter(|_| self.current_model_supports_personality());
let service_tier = match self.config.service_tier.clone() {
Some(service_tier) => Some(Some(service_tier)),

View File

@@ -68,9 +68,6 @@ impl ChatWidget {
if feature == Feature::FastMode {
self.sync_service_tier_commands();
}
if feature == Feature::Personality {
self.sync_personality_command_enabled();
}
if feature == Feature::Plugins {
self.sync_plugins_command_enabled();
self.refresh_plugin_mentions();
@@ -275,7 +272,7 @@ impl ChatWidget {
pub(super) fn sync_personality_command_enabled(&mut self) {
self.bottom_pane
.set_personality_command_enabled(self.config.features.enabled(Feature::Personality));
.set_personality_command_enabled(/*enabled*/ true);
}
pub(super) fn sync_plugins_command_enabled(&mut self) {

View File

@@ -912,7 +912,7 @@ impl ChatWidget {
plugins_command_enabled: self.config.features.enabled(Feature::Plugins),
goal_command_enabled: self.config.features.enabled(Feature::Goals),
service_tier_commands_enabled: self.fast_mode_enabled(),
personality_command_enabled: self.config.features.enabled(Feature::Personality),
personality_command_enabled: true,
realtime_conversation_enabled: self.realtime_conversation_enabled(),
audio_device_selection_enabled: self.realtime_audio_device_selection_enabled(),
allow_elevate_sandbox,

View File

@@ -1608,7 +1608,6 @@ async fn collab_mode_applies_default_preset() {
#[tokio::test]
async fn user_turn_includes_personality_from_config() {
let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await;
chat.set_feature_enabled(Feature::Personality, /*enabled*/ true);
chat.thread_id = Some(ThreadId::new());
chat.set_model("gpt-5.3-codex");
chat.set_personality(Personality::Friendly);