mirror of
https://github.com/openai/codex.git
synced 2026-11-10 21:00:47 +00:00
Remove partial-history subagent forks (#51329)
## What changed - Limit multi-agent V2 `fork_turns` guidance to `all` and `none`. Accept legacy positive integer strings as full-history forks instead of truncating parent history. - Remove partial-history fork handling and telemetry, and direct model override usage to `fork_turns: "none"`. - Strip inherited `multi_agent.role_instructions` and `multi_agent.usage_hint` content by kind, including persisted hints whose wording predates the current bundled instructions. ## Testing Update regression coverage for legacy `"1"` and `"3"` values inheriting full history, invalid and zero values being rejected, and stale parent hints being removed from compacted history with both marked and unmarked instructions. GitOrigin-RevId: 8f6017dc66ad8deefd7745399ef76e1bb1435bb2
This commit is contained in:
@@ -7,7 +7,6 @@ use crate::agent::child_config::build_agent_resume_config;
|
||||
use crate::agent::role::apply_role_to_config;
|
||||
use crate::agent::types::AgentMetadata;
|
||||
use crate::agent::types::LiveAgent;
|
||||
use crate::agent::types::SpawnAgentForkMode;
|
||||
use crate::agent::types::SpawnAgentOptions;
|
||||
use crate::agents_md_manager::SessionInstructions;
|
||||
use crate::codex_thread::CodexThread;
|
||||
@@ -122,8 +121,7 @@ fn keep_forked_rollout_item(item: &RolloutItem, preserve_context_baselines: bool
|
||||
| RolloutItem::RetainedContext(_)
|
||||
| RolloutItem::SecurityRiskScore(_) => false,
|
||||
// Full-history forks preserve the cached prompt prefix and can keep diffing
|
||||
// from the parent's durable baseline. Truncated forks drop part of that prompt,
|
||||
// so they must rebuild context on their first child turn.
|
||||
// from the parent's durable baseline unless legacy compaction requires rebuilding it.
|
||||
RolloutItem::TurnContext(_) | RolloutItem::WorldState(_) => preserve_context_baselines,
|
||||
// Child threads inherit model context, not the parent's cumulative usage state.
|
||||
RolloutItem::TokenUsageRecord(_) => false,
|
||||
@@ -140,7 +138,11 @@ fn retain_forked_developer_message(item: &mut ResponseItem, usage_hint_texts: &[
|
||||
return false;
|
||||
};
|
||||
content.retain(|content_item| {
|
||||
if content_item.kind().0 == "guardian.approved_action" {
|
||||
// Persisted role hints can predate the current bundled wording and lack markers.
|
||||
if matches!(
|
||||
content_item.kind().0.as_str(),
|
||||
"guardian.approved_action" | "multi_agent.role_instructions" | "multi_agent.usage_hint"
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
let ContentItem::InputText { text } = content_item.content() else {
|
||||
@@ -990,11 +992,11 @@ impl LocalAgentControl {
|
||||
"spawn_agent fork requires a parent spawn call id".to_string(),
|
||||
));
|
||||
}
|
||||
let Some(fork_mode) = options.fork_mode.as_ref() else {
|
||||
if options.fork_mode.is_none() {
|
||||
return Err(CodexErr::Fatal(
|
||||
"spawn_agent fork requires a fork mode".to_string(),
|
||||
));
|
||||
};
|
||||
}
|
||||
let SessionSource::SubAgent(SubAgentSource::ThreadSpawn {
|
||||
parent_thread_id, ..
|
||||
}) = &session_source
|
||||
@@ -1062,10 +1064,6 @@ impl LocalAgentControl {
|
||||
Some(meta_line.meta.selected_capability_roots.clone())
|
||||
})
|
||||
.unwrap_or_default();
|
||||
if let SpawnAgentForkMode::LastNTurns(last_n_turns) = fork_mode {
|
||||
forked_rollout_items =
|
||||
truncate_rollout_to_last_n_fork_turns(forked_rollout_items, *last_n_turns);
|
||||
}
|
||||
let multi_agent_v2_usage_hint_texts_to_filter: Vec<String> =
|
||||
if multi_agent_version == MultiAgentVersion::V2 {
|
||||
let parent_config = parent_thread.session.get_config().await;
|
||||
@@ -1082,19 +1080,17 @@ impl LocalAgentControl {
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
let mut preserve_context_baselines = matches!(fork_mode, SpawnAgentForkMode::FullHistory);
|
||||
if preserve_context_baselines {
|
||||
for item in forked_rollout_items.iter().rev() {
|
||||
let RolloutItem::Compacted(compacted) = item else {
|
||||
continue;
|
||||
};
|
||||
// Legacy checkpoints force the child to rebuild context regardless of the
|
||||
// live parent's reference baseline; an older superseded checkpoint does not.
|
||||
if compacted.replacement_history.is_none() {
|
||||
preserve_context_baselines = false;
|
||||
}
|
||||
break;
|
||||
let mut preserve_context_baselines = true;
|
||||
for item in forked_rollout_items.iter().rev() {
|
||||
let RolloutItem::Compacted(compacted) = item else {
|
||||
continue;
|
||||
};
|
||||
// Legacy checkpoints force the child to rebuild context regardless of the
|
||||
// live parent's reference baseline; an older superseded checkpoint does not.
|
||||
if compacted.replacement_history.is_none() {
|
||||
preserve_context_baselines = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
let mut replaced_parent_developer_instructions = false;
|
||||
// Scrub inherited hints and replace only the parent's developer-instruction fragment.
|
||||
|
||||
@@ -28,7 +28,6 @@ pub(super) fn record_spawn_success(
|
||||
let fork_mode = match fork_mode {
|
||||
None => "none",
|
||||
Some(SpawnAgentForkMode::FullHistory) => "all",
|
||||
Some(SpawnAgentForkMode::LastNTurns(_)) => "last_n",
|
||||
};
|
||||
let history_mode = match measurements.history_mode {
|
||||
ThreadHistoryMode::Legacy => "legacy",
|
||||
|
||||
@@ -39,7 +39,7 @@ fn records_bounded_spawn_phase_metrics() {
|
||||
|
||||
record_spawn_success(
|
||||
&telemetry,
|
||||
Some(&SpawnAgentForkMode::LastNTurns(3)),
|
||||
Some(&SpawnAgentForkMode::FullHistory),
|
||||
MultiAgentVersion::V2,
|
||||
SpawnMeasurements {
|
||||
history_mode: ThreadHistoryMode::Paginated,
|
||||
@@ -74,7 +74,7 @@ fn records_bounded_spawn_phase_metrics() {
|
||||
})
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
assert_eq!(attributes.len(), 5);
|
||||
assert_eq!(attributes["fork_mode"], "last_n");
|
||||
assert_eq!(attributes["fork_mode"], "all");
|
||||
assert_eq!(attributes["history_mode"], "paginated");
|
||||
assert_eq!(attributes["multi_agent_version"], "v2");
|
||||
assert_eq!(attributes["product_sku"], "codex");
|
||||
|
||||
Reference in New Issue
Block a user