[codex] Remove child AGENTS.md prompt experiment (#28993)

## Why

`child_agents_md` is a disabled, under-development experiment that adds
a second model-visible explanation of hierarchical `AGENTS.md` behavior.
Keeping it leaves unused prompt, configuration, documentation, and test
surface.

## What changed

- remove the `ChildAgentsMd` feature and `child_agents_md` config schema
entry
- remove the hierarchical prompt asset, export, and instruction
injection
- remove feature-specific tests and documentation
- keep the generic unstable-feature warning coverage using
`apply_patch_streaming_events`

Normal project `AGENTS.md` discovery and composition are unchanged.

## Testing

- `just test -p codex-features`
- `just test -p codex-prompts`
- `just test -p codex-core agents_md`
- `just test -p codex-core unstable_features_warning`
This commit is contained in:
pakrym-oai
2026-06-18 16:13:07 -07:00
committed by GitHub
Unverified
parent 772c5c5195
commit bb72e151e5
12 changed files with 11 additions and 239 deletions
-9
View File
@@ -26,8 +26,6 @@ use codex_config::merge_toml_values;
use codex_config::project_root_markers_from_config;
use codex_exec_server::ExecutorFileSystem;
use codex_extension_api::UserInstructions;
use codex_features::Feature;
use codex_prompts::HIERARCHICAL_AGENTS_MESSAGE;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_path_uri::PathUri;
use std::io;
@@ -72,13 +70,6 @@ pub(crate) async fn load_project_instructions(
}
}
if config.features.enabled(Feature::ChildAgentsMd) {
loaded.entries.push(InstructionEntry {
contents: HIERARCHICAL_AGENTS_MESSAGE.to_string(),
provenance: InstructionProvenance::Internal,
});
}
(!loaded.is_empty()).then_some(loaded)
}
-96
View File
@@ -909,32 +909,6 @@ async fn secondary_environment_invalid_utf8_does_not_suppress_other_docs() {
assert!(loaded.text().contains("secondary\u{FFFD}doc"));
}
#[tokio::test]
async fn child_agents_guidance_is_appended_once_after_environment_groups() {
let primary = tempfile::tempdir().expect("primary tempdir");
let secondary = tempfile::tempdir().expect("secondary tempdir");
fs::write(primary.path().join("AGENTS.md"), "primary doc").unwrap();
fs::write(secondary.path().join("AGENTS.md"), "secondary doc").unwrap();
let mut config = make_config(&primary, /*limit*/ 4096, /*instructions*/ None).await;
config.features.enable(Feature::ChildAgentsMd).unwrap();
let environments = resolved_local_environments([
("primary", config.cwd.clone()),
("secondary", secondary.abs()),
]);
let loaded = load_project_instructions(
&config.config,
/*user_instructions*/ None,
&environments,
)
.await
.expect("instructions expected");
let text = loaded.text();
assert_eq!(text.matches(HIERARCHICAL_AGENTS_MESSAGE).count(), 1);
assert!(text.ends_with(HIERARCHICAL_AGENTS_MESSAGE));
}
/// If there are existing system instructions but AGENTS.md docs are
/// missing we expect the original instructions to be returned unchanged.
#[tokio::test]
@@ -1098,32 +1072,6 @@ async fn agents_md_paths_preserve_symlinked_cwd() {
assert_eq!(res, "project doc");
}
#[tokio::test]
async fn child_agents_message_after_global_instructions_uses_plain_separator() {
let tmp = tempfile::tempdir().expect("tempdir");
let mut cfg = make_config(&tmp, /*limit*/ 4096, Some("global doc")).await;
cfg.features.enable(Feature::ChildAgentsMd).unwrap();
let loaded = load_agents_md(&cfg).await.expect("instructions expected");
let global_agents = cfg.codex_home.join(DEFAULT_AGENTS_MD_FILENAME);
let expected = LoadedAgentsMd {
user_instructions: Some(UserInstructions {
text: "global doc".to_string(),
source: global_agents,
}),
entries: vec![InstructionEntry {
contents: HIERARCHICAL_AGENTS_MESSAGE.to_string(),
provenance: InstructionProvenance::Internal,
}],
};
assert_eq!(loaded, expected);
assert_eq!(
loaded.text(),
format!("global doc\n\n{HIERARCHICAL_AGENTS_MESSAGE}")
);
}
#[tokio::test]
async fn instruction_sources_include_global_before_agents_md_docs() {
let tmp = tempfile::tempdir().expect("tempdir");
@@ -1162,50 +1110,6 @@ async fn instruction_sources_include_global_before_agents_md_docs() {
);
}
#[tokio::test]
async fn child_agents_message_after_project_docs_is_not_an_instruction_source() {
let tmp = tempfile::tempdir().expect("tempdir");
fs::write(tmp.path().join("AGENTS.md"), "project doc").unwrap();
let mut cfg = make_config(&tmp, /*limit*/ 4096, Some("global doc")).await;
cfg.features.enable(Feature::ChildAgentsMd).unwrap();
let global_agents = cfg.codex_home.join(DEFAULT_AGENTS_MD_FILENAME);
fs::create_dir_all(&cfg.codex_home).unwrap();
fs::write(&global_agents, "global doc").unwrap();
let loaded = load_agents_md(&cfg).await.expect("instructions expected");
let project_agents = cfg.cwd.join("AGENTS.md");
let expected = LoadedAgentsMd {
user_instructions: Some(UserInstructions {
text: "global doc".to_string(),
source: global_agents.clone(),
}),
entries: vec![
InstructionEntry {
contents: "project doc".to_string(),
provenance: project_provenance(project_agents.clone(), cfg.cwd.clone()),
},
InstructionEntry {
contents: HIERARCHICAL_AGENTS_MESSAGE.to_string(),
provenance: InstructionProvenance::Internal,
},
],
};
assert_eq!(loaded, expected);
assert_eq!(
loaded.sources().collect::<Vec<_>>(),
vec![
PathUri::from_abs_path(&global_agents),
PathUri::from_abs_path(&project_agents),
]
);
assert_eq!(
loaded.text(),
format!("global doc{AGENTS_MD_SEPARATOR}project doc\n\n{HIERARCHICAL_AGENTS_MESSAGE}")
);
}
/// AGENTS.override.md is preferred over AGENTS.md when both are present.
#[tokio::test]
async fn agents_local_md_preferred() {