Share guardian prewarm prompt assembly

Route the prewarm request through the same prompt assembly helper as the
real guardian review path so the cached-prefix structure cannot drift.

Tighten the guardian prompt test to compare the shared section layout
instead of just the first two items.

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Charles Cunningham
2026-03-18 21:47:35 -07:00
parent 9abea56d41
commit ccaffa1945
2 changed files with 31 additions and 33 deletions

View File

@@ -87,6 +87,29 @@ pub(crate) async fn build_guardian_prompt_items(
let (transcript_entries, omission_note) =
render_guardian_transcript_entries(transcript_entries.as_slice());
Ok(assemble_guardian_prompt_items(
transcript_entries,
omission_note,
retry_reason,
planned_action_json,
))
}
pub(crate) fn build_guardian_prewarm_prompt_items() -> Vec<UserInput> {
assemble_guardian_prompt_items(
vec![GUARDIAN_PREWARM_TRANSCRIPT_PLACEHOLDER.to_string()],
None,
None,
GUARDIAN_PREWARM_ACTION_PLACEHOLDER.to_string(),
)
}
fn assemble_guardian_prompt_items(
transcript_entries: Vec<String>,
omission_note: Option<String>,
retry_reason: Option<String>,
planned_action_json: String,
) -> Vec<UserInput> {
let mut items = Vec::new();
let mut push_text = |text: String| {
items.push(UserInput::Text {
@@ -116,31 +139,7 @@ pub(crate) async fn build_guardian_prompt_items(
push_text(format!("{planned_action_json}\n"));
push_text(GUARDIAN_APPROVAL_REQUEST_END.to_string());
push_text(GUARDIAN_OUTPUT_SCHEMA_INSTRUCTIONS.to_string());
Ok(items)
}
pub(crate) fn build_guardian_prewarm_prompt_items() -> Vec<UserInput> {
[
GUARDIAN_TRANSCRIPT_INTRO,
GUARDIAN_TRANSCRIPT_START,
GUARDIAN_PREWARM_TRANSCRIPT_PLACEHOLDER,
"\n",
GUARDIAN_TRANSCRIPT_END,
GUARDIAN_ACTION_INTRO,
GUARDIAN_APPROVAL_REQUEST_START,
GUARDIAN_ACTION_ASSESSMENT_INSTRUCTIONS,
GUARDIAN_PLANNED_ACTION_JSON_LABEL,
GUARDIAN_PREWARM_ACTION_PLACEHOLDER,
"\n",
GUARDIAN_APPROVAL_REQUEST_END,
GUARDIAN_OUTPUT_SCHEMA_INSTRUCTIONS,
]
.into_iter()
.map(|text| UserInput::Text {
text: text.to_string(),
text_elements: Vec::new(),
})
.collect()
items
}
/// Keeps all user turns plus a bounded amount of recent assistant/tool context.

View File

@@ -140,7 +140,7 @@ async fn guardian_prewarm_prompt_matches_review_request_prefix() -> anyhow::Resu
let (session, _turn) = guardian_test_session_and_turn(&server).await;
let review_prompt = build_guardian_prompt_items(
session.as_ref(),
Some("Retry because the previous attempt lost connectivity.".to_string()),
None,
GuardianApprovalRequest::Shell {
id: "shell-1".to_string(),
command: vec!["git".to_string(), "push".to_string()],
@@ -154,13 +154,12 @@ async fn guardian_prewarm_prompt_matches_review_request_prefix() -> anyhow::Resu
let review_prompt = prompt_item_texts(review_prompt);
let prewarm_prompt = prompt_item_texts(build_guardian_prewarm_prompt_items());
assert_eq!(prewarm_prompt[0], review_prompt[0]);
assert_eq!(prewarm_prompt[1], review_prompt[1]);
assert!(
prewarm_prompt
.iter()
.any(|item| item.contains("guardian_prewarm"))
);
assert_eq!(prewarm_prompt.len(), review_prompt.len());
for index in [0, 1, 3, 4, 5, 6, 7, 9, 10] {
assert_eq!(prewarm_prompt[index], review_prompt[index]);
}
assert!(prewarm_prompt[2].contains("guardian prewarm placeholder"));
assert!(prewarm_prompt[8].contains("guardian_prewarm"));
Ok(())
}