move plugin/skill instructions into dev msg and reorder (#14609)

Move the general `Apps`, `Skills` and `Plugins` instructions blocks out
of `user_instructions` and into the developer message, with new `Apps ->
Skills -> Plugins` order for better clarity.

Also wrap those sections in stable XML-style instruction tags (like
other sections) and update prompt-layout tests/snapshots. This makes the
tests less brittle in snapshot output (we can parse the sections), and
it consolidates the capability instructions in one place.

#### Tests
Updated snapshots, added tests.

`<AGENTS_MD>` disappearing in snapshots is expected: before this change,
the wrapped user-instructions message was kept alive by `Skills`
content. Now that `Skills` and `Plugins` are in the developer message,
that wrapper only appears when there is real
project-doc/user-instructions content.

---------

Co-authored-by: Charley Cunningham <ccunningham@openai.com>
This commit is contained in:
sayan-oai
2026-03-13 20:51:01 -07:00
committed by GitHub
parent 7f571396c8
commit d272f45058
44 changed files with 344 additions and 362 deletions

View File

@@ -1083,7 +1083,7 @@ async fn omits_apps_guidance_for_api_key_auth_even_when_feature_enabled() {
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn skills_append_to_instructions() {
async fn skills_append_to_developer_message() {
skip_if_no_network!();
let server = MockServer::start().await;
@@ -1129,27 +1129,21 @@ async fn skills_append_to_instructions() {
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
let request = resp_mock.single_request();
let request_body = request.body_json();
assert_message_role(&request_body["input"][0], "developer");
assert_message_role(&request_body["input"][1], "user");
let instructions_text = request_body["input"][1]["content"][0]["text"]
.as_str()
.expect("instructions text");
let developer_messages = request.message_input_texts("developer");
let developer_text = developer_messages.join("\n\n");
assert!(
instructions_text.contains("## Skills"),
"expected skills section present"
developer_text.contains("## Skills"),
"expected skills section present: {developer_messages:?}"
);
assert!(
instructions_text.contains("demo: build charts"),
"expected skill summary"
developer_text.contains("demo: build charts"),
"expected skill summary: {developer_messages:?}"
);
let expected_path = normalize_path(skill_dir.join("SKILL.md")).unwrap();
let expected_path_str = expected_path.to_string_lossy().replace('\\', "/");
assert!(
instructions_text.contains(&expected_path_str),
"expected path {expected_path_str} in instructions"
developer_text.contains(&expected_path_str),
"expected path {expected_path_str} in developer message: {developer_messages:?}"
);
let _codex_home_guard = codex_home;
}