fix(cli): z-order Cancel #151 + projection live événements avant Final #167 (+ alignement fixture plugin #165/#166) — QA verte

This commit is contained in:
2026-08-06 19:09:07 +02:00
parent 3d4ea6859e
commit b45deabe6d
4 changed files with 133 additions and 24 deletions

View File

@ -1216,10 +1216,12 @@ mod tests {
}
#[tokio::test]
async fn codex_send_with_tap_emits_each_agent_message_live_as_announcement() {
async fn codex_send_with_tap_emits_provider_events_live_before_final_without_replay() {
let fake = FakeCli::printing(&[
r#"{"type":"thread.started","thread_id":"c"}"#,
r#"{"type":"item.completed","item":{"id":"i0","type":"agent_message","text":"je regarde"}}"#,
r#"{"type":"turn.started"}"#,
r#"{"type":"item.completed","item":{"id":"tool0","type":"command","text":"cargo test"}}"#,
r#"{"type":"turn.completed"}"#,
r#"{"type":"item.completed","item":{"id":"i1","type":"agent_message","text":"résultat"}}"#,
]);
let s = CodexExecSession::new(
@ -1237,24 +1239,31 @@ mod tests {
let events: Vec<_> = s.send_with_tap("x", tx).await.expect("send").collect();
let live: Vec<_> = rx.into_iter().collect();
assert_eq!(
live,
vec![
ReplyEvent::Announcement {
text: "je regarde".into()
},
ReplyEvent::Announcement {
text: "résultat".into()
},
],
"le tap live publie chaque agent_message, y compris celui qui deviendra Final"
assert!(
matches!(live.first(), Some(ReplyEvent::Progress { progress }) if progress.native_event.as_deref() == Some("turn.started")),
"le démarrage du tour provider doit être tapé live en premier"
);
assert!(
live.iter().any(
|event| matches!(event, ReplyEvent::ToolActivity { label } if label == "command")
),
"l'activité outil provider doit être tapée live"
);
assert!(
live.iter().any(|event| matches!(event, ReplyEvent::Progress { progress } if progress.native_event.as_deref() == Some("turn.completed"))),
"la fin de tour provider doit être tapée live avant le Final"
);
assert!(
live.iter()
.all(|event| !matches!(event, ReplyEvent::Final { .. })),
"le Final reste réservé au flux autoritaire"
);
assert_eq!(
without_progress(events.clone()),
vec![ReplyEvent::Final {
content: "résultat".into()
}],
"le flux final du chemin tap garde seulement le dernier Final pour le demandeur"
"le flux final du chemin tap ne rejoue pas les événements déjà projetés live"
);
}