mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
Preserve base instruction provenance across sessions (#37446)
## Why Persisted base instructions need to retain whether they were explicitly customized or generated from a model template. Without that distinction, forks and config-lock replays can treat model-generated instructions as custom and keep the wrong template after a model or personality change. ## What changed - Record custom or model provenance with base instructions in rollouts and config locks. - Preserve custom instructions across model changes, while allowing model-generated instructions to follow the selected model and personality. - Keep legacy rollouts without provenance compatible and propagate provenance through forks and spawned agents. ## Testing - Cover provenance serialization and legacy rollout decoding. - Cover role personality changes, forked model changes, config-lock replay, and multi-agent configuration. GitOrigin-RevId: 801c26559835f558027ce5112700c0cd31fcb21b
This commit is contained in:
@@ -182,6 +182,7 @@ pub(crate) fn build_agent_spawn_config(
|
||||
) -> Result<Config, FunctionCallError> {
|
||||
let mut config = build_agent_shared_config(turn, environment)?;
|
||||
config.base_instructions = Some(base_instructions.text.clone());
|
||||
config.base_instructions_provenance = base_instructions.provenance.clone();
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
@@ -192,6 +193,7 @@ pub(crate) fn build_agent_resume_config(
|
||||
let mut config = build_agent_shared_config(turn, environment)?;
|
||||
// For resume, keep base instructions sourced from rollout/session metadata.
|
||||
config.base_instructions = None;
|
||||
config.base_instructions_provenance = None;
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ use codex_protocol::config_types::ServiceTier;
|
||||
use codex_protocol::config_types::ShellEnvironmentPolicy;
|
||||
use codex_protocol::mcp::ClientMcpExtensions;
|
||||
use codex_protocol::models::BaseInstructions;
|
||||
use codex_protocol::models::BaseInstructionsProvenance;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputBody;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
@@ -4442,6 +4443,9 @@ async fn build_agent_spawn_config_uses_turn_context_values() {
|
||||
let (_session, mut turn) = make_session_and_context().await;
|
||||
let base_instructions = BaseInstructions {
|
||||
text: "base".to_string(),
|
||||
provenance: Some(BaseInstructionsProvenance::Model {
|
||||
model: turn.model_info.slug.clone(),
|
||||
}),
|
||||
};
|
||||
turn.developer_instructions = Some("dev".to_string());
|
||||
let mut config = (*turn.config).clone();
|
||||
@@ -4486,6 +4490,7 @@ async fn build_agent_spawn_config_uses_turn_context_values() {
|
||||
let config = build_agent_spawn_config(&base_instructions, &turn, turn.environments.primary())
|
||||
.expect("spawn config");
|
||||
let mut expected = (*turn.config).clone();
|
||||
expected.base_instructions_provenance = base_instructions.provenance.clone();
|
||||
expected.base_instructions = Some(base_instructions.text);
|
||||
expected.model = Some(turn.model_info.slug.clone());
|
||||
expected.model_provider = turn.provider.info().clone();
|
||||
@@ -4513,6 +4518,9 @@ async fn build_agent_resume_config_clears_base_instructions() {
|
||||
let (_session, mut turn) = make_session_and_context().await;
|
||||
let mut base_config = (*turn.config).clone();
|
||||
base_config.base_instructions = Some("caller-base".to_string());
|
||||
base_config.base_instructions_provenance = Some(BaseInstructionsProvenance::Model {
|
||||
model: turn.model_info.slug.clone(),
|
||||
});
|
||||
turn.config = Arc::new(base_config);
|
||||
Arc::make_mut(&mut turn.config)
|
||||
.permissions
|
||||
@@ -4541,6 +4549,7 @@ async fn build_agent_resume_config_clears_base_instructions() {
|
||||
|
||||
let mut expected = (*turn.config).clone();
|
||||
expected.base_instructions = None;
|
||||
expected.base_instructions_provenance = None;
|
||||
expected.model = Some(turn.model_info.slug.clone());
|
||||
expected.model_provider = turn.provider.info().clone();
|
||||
expected.model_reasoning_effort = turn.reasoning_effort.clone();
|
||||
|
||||
Reference in New Issue
Block a user