Remove retired model entries while preserving migration prompts (#44250)

## Why

Saved model selections can outlive their bundled catalog entries and still need migration guidance.

## What changed

- Remove `gpt-5.2` and `gpt-5.4-mini` from the bundled model catalog.
- Preserve migration from saved `gpt-5.4-mini` selections to `gpt-5.6-luna` when the old model is absent, while respecting catalog-provided migration metadata.
- Update tests and snapshots to use current models or explicit test fixtures, and remove the obsolete prompt fixture.

## Testing

Extend migration tests to cover catalog metadata precedence, saved selections, replacement model and reasoning-effort persistence, acknowledged prompts, and missing or hidden migration targets.

GitOrigin-RevId: 82beea504cc4a15699677c28a61ec0939af3069c
This commit is contained in:
rhan-oai authored and copyberry committed 2026-09-09 17:56:33 +00:00
1 parent 6eecd04fc1
commit eb7bd64ef9
58 files changed
+670 -1192

No files matched your search

@@ -57,8 +57,8 @@ fn activation_models() -> Vec<ModelInfo> {
.expect("bundled models")
.models
.into_iter()
.find(|model| model.slug == "gpt-5.4")
.expect("bundled gpt-5.4");
.find(|model| model.slug == "gpt-5.5")
.expect("bundled gpt-5.5");
[MODEL_A, MODEL_B]
.into_iter()
.map(|slug| ModelInfo {
+4 -72
View File
@@ -9,7 +9,6 @@ use crate::agents_md_manager::AgentsMdManager;
use crate::compact::InitialContextInjection;
use crate::config::ConfigBuilder;
use crate::config::ConfigOverrides;
use crate::config::test_config;
use crate::context::ContextualUserFragment;
use crate::context::DeveloperInstructions;
use crate::context::GuardianContextMode;
@@ -54,7 +53,6 @@ use codex_login::auth::AgentIdentityAuthPolicy;
use codex_model_provider::create_model_provider;
use codex_model_provider_info::ModelProviderInfo;
use codex_model_provider_info::built_in_model_providers;
use codex_models_manager::bundled_models_response;
use codex_models_manager::model_info;
use codex_models_manager::test_support::construct_model_info_offline_for_tests;
use codex_models_manager::test_support::get_model_offline_for_tests;
@@ -294,11 +292,6 @@ impl StepContext {
mod guardian_tests;
struct InstructionsTestCase {
slug: &'static str,
expects_apply_patch_description: bool,
}
fn user_message(text: &str) -> ResponseItem {
ResponseItem::Message {
id: None,
@@ -1616,67 +1609,6 @@ async fn user_shell_commands_remain_login_shells_when_model_login_shells_are_dis
Ok(())
}
#[tokio::test]
async fn get_base_instructions_no_user_content() {
let prompt_path = codex_utils_cargo_bin::find_resource!(
"tests/fixtures/prompt_with_apply_patch_instructions.md"
)
.expect("resolve prompt fixture path");
let prompt_with_apply_patch_instructions =
std::fs::read_to_string(prompt_path).expect("read prompt fixture");
let models_response = bundled_models_response()
.unwrap_or_else(|err| panic!("bundled models.json should parse: {err}"));
let model_info_for_slug = |slug: &str, config: &Config| {
let model = models_response
.models
.iter()
.find(|candidate| candidate.slug == slug)
.cloned()
.unwrap_or_else(|| panic!("model slug {slug} is missing from models.json"));
model_info::with_config_overrides(model, &config.to_models_manager_config())
};
let test_cases = vec![
InstructionsTestCase {
slug: "gpt-5.4",
expects_apply_patch_description: false,
},
InstructionsTestCase {
slug: "gpt-5.4-mini",
expects_apply_patch_description: false,
},
InstructionsTestCase {
slug: "gpt-5.5",
expects_apply_patch_description: false,
},
InstructionsTestCase {
slug: "gpt-5.2",
expects_apply_patch_description: false,
},
];
let (session, _turn_context) = make_session_and_context().await;
let config = test_config().await;
for test_case in test_cases {
let model_info = model_info_for_slug(test_case.slug, &config);
let model_instructions = model_info.get_model_instructions(config.personality);
if test_case.expects_apply_patch_description {
assert_eq!(
model_instructions.as_str(),
prompt_with_apply_patch_instructions
);
}
{
let mut state = session.state.lock().await;
state.session_configuration.base_instructions = model_instructions.clone();
}
let base_instructions = session.get_base_instructions().await;
assert_eq!(base_instructions.text, model_instructions);
}
}
#[tokio::test]
async fn reload_user_config_layer_updates_effective_apps_config() {
let (session, _turn_context) = make_session_and_context().await;
@@ -4876,13 +4808,13 @@ async fn turn_context_with_model_updates_model_fields() {
));
turn_context.current_settings.store(Arc::clone(&current));
let updated = turn_context
.with_model("gpt-5.4".to_string(), &session.services.models_manager)
.with_model("gpt-5.5".to_string(), &session.services.models_manager)
.await;
let expected_model_info = session
.services
.models_manager
.get_model_info(
"gpt-5.4",
"gpt-5.5",
&updated.config.as_ref().to_models_manager_config(),
)
.await;
@@ -4923,8 +4855,8 @@ async fn turn_context_with_model_updates_model_fields() {
&updated.current_settings.load_full(),
&turn_context.current_settings.load_full()
));
assert_eq!(updated.config.model.as_deref(), Some("gpt-5.4"));
assert_eq!(updated.collaboration_mode().model(), "gpt-5.4");
assert_eq!(updated.config.model.as_deref(), Some("gpt-5.5"));
assert_eq!(updated.collaboration_mode().model(), "gpt-5.5");
assert_eq!(updated.model_info().as_ref(), &expected_model_info);
assert_eq!(
updated.reasoning_effort(),