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,8 +2,6 @@ use std::sync::Arc;
use codex_protocol::protocol::ReviewDecision;
use crate::ApprovalPolicyContributor;
use crate::ApprovalRequirement;
use crate::ApprovalReviewContributor;
use crate::ConfigContributor;
use crate::ContextContributor;
@@ -35,7 +33,6 @@ impl<C: Sync> Default for ExtensionRegistryBuilder<C> {
config_contributors: Vec::new(),
token_usage_contributors: Vec::new(),
skill_invocation_contributors: Vec::new(),
approval_policy_contributors: Vec::new(),
approval_review_contributors: Vec::new(),
context_contributors: Vec::new(),
mcp_server_contributors: Vec::new(),
@@ -66,11 +63,6 @@ impl<C: Sync> ExtensionRegistryBuilder<C> {
Arc::clone(&self.registry.event_sink)
}
/// Registers one thread-scoped approval-policy contributor.
pub fn approval_policy_contributor(&mut self, contributor: Arc<dyn ApprovalPolicyContributor>) {
self.registry.approval_policy_contributors.push(contributor);
}
/// Registers one approval-review contributor.
pub fn approval_review_contributor(&mut self, contributor: Arc<dyn ApprovalReviewContributor>) {
self.registry.approval_review_contributors.push(contributor);
@@ -161,7 +153,6 @@ pub struct ExtensionRegistry<C: Sync> {
tool_contributors: Vec<Arc<dyn ToolContributor>>,
tool_lifecycle_contributors: Vec<Arc<dyn ToolLifecycleContributor>>,
turn_item_contributors: Vec<Arc<dyn TurnItemContributor>>,
approval_policy_contributors: Vec<Arc<dyn ApprovalPolicyContributor>>,
approval_review_contributors: Vec<Arc<dyn ApprovalReviewContributor>>,
}
@@ -196,18 +187,6 @@ impl<C: Sync> ExtensionRegistry<C> {
&self.skill_invocation_contributors
}
/// Resolves the strongest approval requirement for the current thread.
pub fn approval_requirement(&self, thread_store: &ExtensionData) -> ApprovalRequirement {
if self.approval_policy_contributors.iter().any(|contributor| {
contributor.approval_requirement(thread_store)
== ApprovalRequirement::RequireAutomaticReview
}) {
ApprovalRequirement::RequireAutomaticReview
} else {
ApprovalRequirement::Default
}
}
/// Claims the first rendered approval-review prompt accepted by an
/// installed contributor.
pub async fn approval_review(