mirror of
https://github.com/openai/codex.git
synced 2026-05-01 09:56:37 +00:00
guardian initial feedback / tweaks (#13897)
## Summary - remove the remaining model-visible guardian-specific `on-request` prompt additions so enabling the feature does not change the main approval-policy instructions - neutralize user-facing guardian wording to talk about automatic approval review / approval requests rather than a second reviewer or only sandbox escalations - tighten guardian retry-context handling so agent-authored `justification` stays in the structured action JSON and is not also injected as raw retry context - simplify guardian review plumbing in core by deleting dead prompt-append paths and trimming some request/transcript setup code ## Notable Changes - delete the dead `permissions/approval_policy/guardian.md` append path and stop threading `guardian_approval_enabled` through model-facing developer-instruction builders - rename the experimental feature copy to `Automatic approval review` and update the `/experimental` snapshot text accordingly - make approval-review status strings generic across shell, patch, network, and MCP review types - forward real sandbox/network retry reasons for shell and unified-exec guardian review, but do not pass agent-authored justification as raw retry context - simplify `guardian.rs` by removing the one-field request wrapper, deduping reasoning-effort selection, and cleaning up transcript entry collection ## Testing - `just fmt` - full validation left to CI --------- Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
committed by
GitHub
parent
2bc3e52a91
commit
f23fcd6ced
@@ -1,6 +1,6 @@
|
||||
use crate::codex::Session;
|
||||
use crate::guardian::GUARDIAN_REJECTION_MESSAGE;
|
||||
use crate::guardian::GuardianReviewRequest;
|
||||
use crate::guardian::GuardianApprovalRequest;
|
||||
use crate::guardian::review_approval_request;
|
||||
use crate::guardian::routes_approval_to_guardian;
|
||||
use crate::network_policy_decision::denied_network_policy_message;
|
||||
@@ -21,7 +21,6 @@ use codex_protocol::protocol::EventMsg;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use codex_protocol::protocol::WarningEvent;
|
||||
use indexmap::IndexMap;
|
||||
use serde_json::json;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
@@ -344,14 +343,11 @@ impl NetworkApprovalService {
|
||||
review_approval_request(
|
||||
&session,
|
||||
&turn_context,
|
||||
GuardianReviewRequest {
|
||||
action: json!({
|
||||
"tool": "network_access",
|
||||
"target": target,
|
||||
"host": request.host,
|
||||
"protocol": key.protocol,
|
||||
"port": key.port,
|
||||
}),
|
||||
GuardianApprovalRequest::NetworkAccess {
|
||||
target,
|
||||
host: request.host,
|
||||
protocol,
|
||||
port: key.port,
|
||||
},
|
||||
Some(policy_denial_message.clone()),
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//! `codex --codex-run-as-apply-patch`, and runs under the current
|
||||
//! `SandboxAttempt` with a minimal environment.
|
||||
use crate::exec::ExecToolCallOutput;
|
||||
use crate::guardian::GuardianReviewRequest;
|
||||
use crate::guardian::GuardianApprovalRequest;
|
||||
use crate::guardian::review_approval_request;
|
||||
use crate::guardian::routes_approval_to_guardian;
|
||||
use crate::sandboxing::CommandSpec;
|
||||
@@ -28,7 +28,6 @@ use codex_protocol::protocol::FileChange;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use futures::future::BoxFuture;
|
||||
use serde_json::json;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -50,15 +49,12 @@ impl ApplyPatchRuntime {
|
||||
Self
|
||||
}
|
||||
|
||||
fn build_guardian_review_request(req: &ApplyPatchRequest) -> GuardianReviewRequest {
|
||||
GuardianReviewRequest {
|
||||
action: json!({
|
||||
"tool": "apply_patch",
|
||||
"cwd": req.action.cwd,
|
||||
"files": req.file_paths,
|
||||
"change_count": req.changes.len(),
|
||||
"patch": req.action.patch,
|
||||
}),
|
||||
fn build_guardian_review_request(req: &ApplyPatchRequest) -> GuardianApprovalRequest {
|
||||
GuardianApprovalRequest::ApplyPatch {
|
||||
cwd: req.action.cwd.clone(),
|
||||
files: req.file_paths.clone(),
|
||||
change_count: req.changes.len(),
|
||||
patch: req.action.patch.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,8 +131,8 @@ impl Approvable<ApplyPatchRequest> for ApplyPatchRuntime {
|
||||
let changes = req.changes.clone();
|
||||
Box::pin(async move {
|
||||
if routes_approval_to_guardian(turn) {
|
||||
let request = ApplyPatchRuntime::build_guardian_review_request(req);
|
||||
return review_approval_request(session, turn, request, retry_reason).await;
|
||||
let action = ApplyPatchRuntime::build_guardian_review_request(req);
|
||||
return review_approval_request(session, turn, action, retry_reason).await;
|
||||
}
|
||||
if let Some(reason) = retry_reason {
|
||||
let rx_approve = session
|
||||
@@ -256,14 +252,11 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
guardian_request,
|
||||
GuardianReviewRequest {
|
||||
action: json!({
|
||||
"tool": "apply_patch",
|
||||
"cwd": expected_cwd,
|
||||
"files": request.file_paths,
|
||||
"change_count": 1usize,
|
||||
"patch": expected_patch,
|
||||
}),
|
||||
GuardianApprovalRequest::ApplyPatch {
|
||||
cwd: expected_cwd,
|
||||
files: request.file_paths,
|
||||
change_count: 1usize,
|
||||
patch: expected_patch,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ pub(crate) mod zsh_fork_backend;
|
||||
use crate::command_canonicalization::canonicalize_command_for_approval;
|
||||
use crate::exec::ExecToolCallOutput;
|
||||
use crate::features::Feature;
|
||||
use crate::guardian::GuardianReviewRequest;
|
||||
use crate::guardian::GuardianApprovalRequest;
|
||||
use crate::guardian::review_approval_request;
|
||||
use crate::guardian::routes_approval_to_guardian;
|
||||
use crate::powershell::prefix_powershell_script_with_utf8;
|
||||
@@ -38,7 +38,6 @@ use codex_network_proxy::NetworkProxy;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use futures::future::BoxFuture;
|
||||
use serde_json::json;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -145,33 +144,26 @@ impl Approvable<ShellRequest> for ShellRuntime {
|
||||
let keys = self.approval_keys(req);
|
||||
let command = req.command.clone();
|
||||
let cwd = req.cwd.clone();
|
||||
let reason = ctx
|
||||
.retry_reason
|
||||
.clone()
|
||||
.or_else(|| req.justification.clone());
|
||||
let retry_reason = ctx.retry_reason.clone();
|
||||
let reason = retry_reason.clone().or_else(|| req.justification.clone());
|
||||
let session = ctx.session;
|
||||
let turn = ctx.turn;
|
||||
let call_id = ctx.call_id.to_string();
|
||||
Box::pin(async move {
|
||||
if routes_approval_to_guardian(turn) {
|
||||
let mut action = json!({
|
||||
"tool": "shell",
|
||||
"command": command,
|
||||
"cwd": cwd,
|
||||
"sandbox_permissions": req.sandbox_permissions,
|
||||
"additional_permissions": req.additional_permissions,
|
||||
"justification": reason,
|
||||
});
|
||||
if let Some(action) = action.as_object_mut() {
|
||||
if req.additional_permissions.is_none() {
|
||||
action.remove("additional_permissions");
|
||||
}
|
||||
if reason.is_none() {
|
||||
action.remove("justification");
|
||||
}
|
||||
}
|
||||
let request = GuardianReviewRequest { action };
|
||||
return review_approval_request(session, turn, request, None).await;
|
||||
return review_approval_request(
|
||||
session,
|
||||
turn,
|
||||
GuardianApprovalRequest::Shell {
|
||||
command,
|
||||
cwd,
|
||||
sandbox_permissions: req.sandbox_permissions,
|
||||
additional_permissions: req.additional_permissions.clone(),
|
||||
justification: req.justification.clone(),
|
||||
},
|
||||
retry_reason,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
with_cached_approval(&session.services, "shell", keys, move || async move {
|
||||
let available_decisions = None;
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::exec::SandboxType;
|
||||
use crate::exec::is_likely_sandbox_denied;
|
||||
use crate::exec_policy::prompt_is_rejected_by_policy;
|
||||
use crate::features::Feature;
|
||||
use crate::guardian::GuardianReviewRequest;
|
||||
use crate::guardian::GuardianApprovalRequest;
|
||||
use crate::guardian::review_approval_request;
|
||||
use crate::guardian::routes_approval_to_guardian;
|
||||
use crate::sandboxing::ExecRequest;
|
||||
@@ -50,7 +50,6 @@ use codex_shell_escalation::PreparedExec;
|
||||
use codex_shell_escalation::ShellCommandExecutor;
|
||||
use codex_shell_escalation::Stopwatch;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use serde_json::json;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
@@ -386,16 +385,19 @@ impl CoreShellActionProvider {
|
||||
Ok(stopwatch
|
||||
.pause_for(async move {
|
||||
if routes_approval_to_guardian(&turn) {
|
||||
let request = GuardianReviewRequest {
|
||||
action: json!({
|
||||
"tool": tool_name,
|
||||
"program": program,
|
||||
"argv": argv,
|
||||
"cwd": workdir,
|
||||
"additional_permissions": additional_permissions,
|
||||
}),
|
||||
};
|
||||
return review_approval_request(&session, &turn, request, None).await;
|
||||
return review_approval_request(
|
||||
&session,
|
||||
&turn,
|
||||
GuardianApprovalRequest::Execve {
|
||||
tool_name: tool_name.to_string(),
|
||||
program: program.to_string_lossy().into_owned(),
|
||||
argv: argv.to_vec(),
|
||||
cwd: workdir,
|
||||
additional_permissions,
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
let available_decisions = vec![
|
||||
Some(ReviewDecision::Approved),
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::error::CodexErr;
|
||||
use crate::error::SandboxErr;
|
||||
use crate::exec::ExecExpiration;
|
||||
use crate::features::Feature;
|
||||
use crate::guardian::GuardianReviewRequest;
|
||||
use crate::guardian::GuardianApprovalRequest;
|
||||
use crate::guardian::review_approval_request;
|
||||
use crate::guardian::routes_approval_to_guardian;
|
||||
use crate::powershell::prefix_powershell_script_with_utf8;
|
||||
@@ -41,7 +41,6 @@ use codex_network_proxy::NetworkProxy;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use futures::future::BoxFuture;
|
||||
use serde_json::json;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -113,31 +112,24 @@ impl Approvable<UnifiedExecRequest> for UnifiedExecRuntime<'_> {
|
||||
let call_id = ctx.call_id.to_string();
|
||||
let command = req.command.clone();
|
||||
let cwd = req.cwd.clone();
|
||||
let reason = ctx
|
||||
.retry_reason
|
||||
.clone()
|
||||
.or_else(|| req.justification.clone());
|
||||
let retry_reason = ctx.retry_reason.clone();
|
||||
let reason = retry_reason.clone().or_else(|| req.justification.clone());
|
||||
Box::pin(async move {
|
||||
if routes_approval_to_guardian(turn) {
|
||||
let mut action = json!({
|
||||
"tool": "exec_command",
|
||||
"command": command,
|
||||
"cwd": cwd,
|
||||
"sandbox_permissions": req.sandbox_permissions,
|
||||
"additional_permissions": req.additional_permissions,
|
||||
"justification": reason,
|
||||
"tty": req.tty,
|
||||
});
|
||||
if let Some(action) = action.as_object_mut() {
|
||||
if req.additional_permissions.is_none() {
|
||||
action.remove("additional_permissions");
|
||||
}
|
||||
if reason.is_none() {
|
||||
action.remove("justification");
|
||||
}
|
||||
}
|
||||
let request = GuardianReviewRequest { action };
|
||||
return review_approval_request(session, turn, request, None).await;
|
||||
return review_approval_request(
|
||||
session,
|
||||
turn,
|
||||
GuardianApprovalRequest::ExecCommand {
|
||||
command,
|
||||
cwd,
|
||||
sandbox_permissions: req.sandbox_permissions,
|
||||
additional_permissions: req.additional_permissions.clone(),
|
||||
justification: req.justification.clone(),
|
||||
tty: req.tty,
|
||||
},
|
||||
retry_reason,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
with_cached_approval(&session.services, "unified_exec", keys, || async move {
|
||||
let available_decisions = None;
|
||||
|
||||
Reference in New Issue
Block a user