feat(auto-review) short-circuit (#18890)

## Summary
Short circuit the convo if auto-review hits too many denials

## Testing
- [x] Added unit tests

---------

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Dylan Hurd
2026-04-22 20:34:15 +00:00
committed by GitHub
co-authored by Codex
parent b77791c228
commit ed4def8286
28 changed files with 645 additions and 22 deletions
@@ -45,6 +45,7 @@ use codex_app_server_protocol::FileChangeRequestApprovalParams;
use codex_app_server_protocol::FileChangeRequestApprovalResponse;
use codex_app_server_protocol::FileUpdateChange;
use codex_app_server_protocol::GrantedPermissionProfile as V2GrantedPermissionProfile;
use codex_app_server_protocol::GuardianWarningNotification;
use codex_app_server_protocol::HookCompletedNotification;
use codex_app_server_protocol::HookStartedNotification;
use codex_app_server_protocol::InterruptConversationResponse;
@@ -286,6 +287,22 @@ pub(crate) async fn apply_bespoke_event_handling(
.await;
}
}
EventMsg::GuardianWarning(warning_event) => {
if let ApiVersion::V2 = api_version {
let notification = GuardianWarningNotification {
thread_id: conversation_id.to_string(),
message: warning_event.message,
};
if let Some(analytics_events_client) = analytics_events_client.as_ref() {
analytics_events_client.track_notification(
ServerNotification::GuardianWarning(notification.clone()),
);
}
outgoing
.send_server_notification(ServerNotification::GuardianWarning(notification))
.await;
}
}
EventMsg::GuardianAssessment(assessment) => {
if let ApiVersion::V2 = api_version {
let pending_command_execution = match build_item_from_guardian_event(
@@ -657,6 +657,7 @@ mod tests {
use codex_app_server_protocol::ConfigWarningNotification;
use codex_app_server_protocol::DynamicToolCallParams;
use codex_app_server_protocol::FileChangeRequestApprovalParams;
use codex_app_server_protocol::GuardianWarningNotification;
use codex_app_server_protocol::ModelRerouteReason;
use codex_app_server_protocol::ModelReroutedNotification;
use codex_app_server_protocol::RateLimitSnapshot;
@@ -812,6 +813,28 @@ mod tests {
);
}
#[test]
fn verify_guardian_warning_notification_serialization() {
let notification = ServerNotification::GuardianWarning(GuardianWarningNotification {
thread_id: "thread-1".to_string(),
message: "Automatic approval review denied the requested action.".to_string(),
});
let jsonrpc_notification = OutgoingMessage::AppServerNotification(notification);
assert_eq!(
json!({
"method": "guardianWarning",
"params": {
"threadId": "thread-1",
"message": "Automatic approval review denied the requested action.",
},
}),
serde_json::to_value(jsonrpc_notification)
.expect("ensure the notification serializes correctly"),
"ensure the notification serializes correctly"
);
}
#[test]
fn verify_model_rerouted_notification_serialization() {
let notification = ServerNotification::ModelRerouted(ModelReroutedNotification {