Let extensions resolve approval reviews before Guardian (#38592)

## What changed

- Give approval review contributors the first opportunity to resolve an action when automatic review is not required for the model.
- Return an extension's decision directly and fall back to Guardian when no extension claims the review.
- Update Guardian V2 to approve actions below its risk threshold through the review contributor API, and remove the extension approval-policy API.

## Testing

- Verify that an extension approval bypasses both the Guardian model call and the user approval prompt.
- Cover Guardian V2 review decisions for low-risk, high-risk, and disabled threads.

GitOrigin-RevId: 5be56941143aff6f358b75b5f8101b7c047147ae
This commit is contained in:
jif authored and copyberry committed 2026-08-14 15:24:10 +00:00
1 parent 5bc8da6d78
commit 23094236ac
12 files changed
+174 -149

No files matched your search

+2 -34
View File
@@ -2512,9 +2512,7 @@ impl Session {
});
};
if crate::guardian::routes_approval_to_guardian(turn_context.as_ref())
|| self.extension_strict_auto_review_enabled().await
{
if crate::guardian::routes_approval_to_guardian(turn_context.as_ref()) {
let originating_turn_state = {
let active = self.active_turn.lock().await;
active.as_ref().map(|active| Arc::clone(&active.turn_state))
@@ -2853,41 +2851,11 @@ impl Session {
pub(crate) async fn active_turn_context_and_strict_auto_review(
&self,
) -> Option<(Arc<TurnContext>, bool)> {
let extension_strict_auto_review = self.extension_strict_auto_review_enabled().await;
let active = self.active_turn.lock().await;
let active = active.as_ref()?;
let turn_context = Arc::clone(&active.task.as_ref()?.turn_context);
let ts = active.turn_state.lock().await;
Some((
turn_context,
ts.strict_auto_review_enabled() || extension_strict_auto_review,
))
}
pub(crate) async fn extension_strict_auto_review_enabled(&self) -> bool {
if self
.services
.extensions
.approval_requirement(&self.services.thread_extension_data)
!= codex_extension_api::ApprovalRequirement::RequireAutomaticReview
{
return false;
}
let state = self.state.lock().await;
let configuration = &state.session_configuration;
!configuration.trusted_guardian_reviewer
&& configuration
.original_config_do_not_use
.features
.enabled(Feature::GuardianApproval)
&& configuration
.original_config_do_not_use
.config_layer_stack
.requirements()
.approvals_reviewer
.can_set(&ApprovalsReviewer::AutoReview)
.is_ok()
Some((turn_context, ts.strict_auto_review_enabled()))
}
pub(crate) async fn granted_session_permissions(