Make auto-review on-request prompt more proactive (#26496)

## Why

`on-request` approval policy text is currently tuned for user-reviewed
approvals. For auto-reviewed productivity runs, likely sandbox blocks
should be escalated earlier so commands that need remote services,
authentication, or other out-of-sandbox access do not first fail or hang
inside the sandbox.

## What changed

- Adds a separate `on_request_auto_review.md` permissions prompt
selected for `AskForApproval::OnRequest` with
`ApprovalsReviewer::AutoReview`.
- Keeps the normal user-reviewed `on-request` wording unchanged.
- Makes the `When to request escalation` bullets more explicit about
likely sandbox blocks, network access, remote
auth/cluster/cloud/database access, out-of-sandbox environment access,
git operations that may write lock files, and short-timeout reruns after
likely sandbox-blocked attempts.
- Omits approved command prefix and `prefix_rule` guidance for the
auto-review on-request prompt.
- Adds prompt tests covering the auto-review path, normal on-request
wording, and inline permission request behavior.
This commit is contained in:
maja-openai
2026-06-18 13:16:14 -07:00
committed by GitHub
Unverified
parent f4602b7516
commit d9dace8a59
3 changed files with 132 additions and 2 deletions
@@ -22,6 +22,8 @@ const APPROVAL_POLICY_ON_FAILURE: &str =
include_str!("../templates/permissions/approval_policy/on_failure.md");
const APPROVAL_POLICY_ON_REQUEST_RULE: &str =
include_str!("../templates/permissions/approval_policy/on_request.md");
const APPROVAL_POLICY_ON_REQUEST_AUTO_REVIEW: &str =
include_str!("../templates/permissions/approval_policy/on_request_auto_review.md");
const APPROVAL_POLICY_ON_REQUEST_RULE_REQUEST_PERMISSION: &str =
include_str!("../templates/permissions/approval_policy/on_request_rule_request_permission.md");
const AUTO_REVIEW_APPROVAL_SUFFIX: &str = "`approvals_reviewer` is `auto_review`: Sandbox escalations with require_escalated will be reviewed for compliance with the policy. If a rejection happens, you should proceed only with a materially safer alternative, or inform the user of the risk and send a final message to ask for approval.";
@@ -208,6 +210,8 @@ fn approval_text(
let on_request_instructions = || {
let on_request_rule = if exec_permission_approvals_enabled {
APPROVAL_POLICY_ON_REQUEST_RULE_REQUEST_PERMISSION.to_string()
} else if approvals_reviewer == ApprovalsReviewer::AutoReview {
APPROVAL_POLICY_ON_REQUEST_AUTO_REVIEW.to_string()
} else {
APPROVAL_POLICY_ON_REQUEST_RULE.to_string()
};
@@ -257,17 +257,98 @@ fn on_request_includes_tool_guidance_alongside_inline_permission_guidance_when_b
#[test]
fn auto_review_approvals_append_auto_review_specific_guidance() {
let mut exec_policy = Policy::empty();
exec_policy
.add_prefix_rule(&["git".to_string(), "pull".to_string()], Decision::Allow)
.expect("add rule");
let text = approval_text(
AskForApproval::OnRequest,
ApprovalsReviewer::AutoReview,
&Policy::empty(),
&exec_policy,
/*exec_permission_approvals_enabled*/ false,
/*request_permissions_tool_enabled*/ false,
);
assert!(text.contains("`approvals_reviewer` is `auto_review`"));
assert!(!text.contains("`approvals_reviewer` is `guardian_subagent`"));
assert!(text.contains("materially safer alternative"));
assert!(!text.contains("`approvals_reviewer` is `guardian_subagent`"));
assert!(text.contains(
"When the sandbox is likely to block a command needed for the task, request escalation up front"
));
assert!(text.contains(
"When unsure, prefer requesting escalation unnecessarily over failing to request it when needed"
));
assert!(
text.contains(
"Request escalation for commands that need write access outside writable roots"
)
);
assert!(text.contains(
"Request escalation for git operations that may write lock files, such as updating the index or refs"
));
assert!(!text.contains("Request escalation for GUI commands"));
assert!(!text.contains("Use escalation when it is the direct or most reliable way"));
assert!(!text.contains("Do not spend extra turns running likely-to-fail sandbox probes first"));
assert!(text.contains("Do not include a `prefix_rule` parameter."));
assert!(text.contains(
"Request escalation for commands that may need network access, including HTTP calls, package registries, internal services, data-service APIs, remote queries, data fetches, or live probes"
));
assert!(text.contains(
"Request escalation for commands that may need remote authentication, cluster, cloud, or database access"
));
assert!(text.contains(
"Request escalation for commands that may need process, cache, or other environment access outside the sandbox"
));
assert!(
text.contains(
"including DNS, connection, authentication, retry, or service endpoint errors"
)
);
assert!(text.contains(
"Request escalation before potentially destructive actions, such as `rm` or `git reset`"
));
assert!(text.contains(
"If a command may be hanging on sandbox-blocked access, stop after a short timeout and rerun with `require_escalated`"
));
assert!(!text.contains("Be judicious with escalating"));
assert!(text.contains("Approved command prefixes"));
assert!(text.contains(r#"["git", "pull"]"#));
assert!(!text.contains("prefix_rule guidance"));
}
#[test]
fn normal_on_request_keeps_user_approval_wording() {
let text = approval_text(
AskForApproval::OnRequest,
ApprovalsReviewer::User,
&Policy::empty(),
/*exec_permission_approvals_enabled*/ false,
/*request_permissions_tool_enabled*/ false,
);
assert!(text.contains("approved by the user"));
assert!(text.contains("Be judicious with escalating"));
assert!(!text.contains(
"When the sandbox is likely to block a command needed for the task, request escalation up front"
));
}
#[test]
fn auto_review_on_request_with_inline_permission_requests_keeps_suffix() {
let text = approval_text(
AskForApproval::OnRequest,
ApprovalsReviewer::AutoReview,
&Policy::empty(),
/*exec_permission_approvals_enabled*/ true,
/*request_permissions_tool_enabled*/ false,
);
assert!(text.contains("with_additional_permissions"));
assert!(text.contains("`approvals_reviewer` is `auto_review`"));
assert!(text.contains("materially safer alternative"));
assert!(!text.contains(
"When the sandbox is likely to block a command needed for the task, request escalation up front"
));
}
#[test]
@@ -0,0 +1,45 @@
# Escalation Requests
Commands are run outside the sandbox after approval. The command string is split into independent command segments at shell control operators, including but not limited to:
- Pipes: |
- Logical operators: &&, ||
- Command separators: ;
- Subshell boundaries: (...), $()
Each resulting segment is evaluated independently for sandbox restrictions and approval requirements.
Example:
git pull | tee output.txt
This is treated as two command segments:
["git", "pull"]
["tee", "output.txt"]
Commands that use more advanced shell features like redirection (>, >>, <), substitutions ($(...), ...), environment variables (FOO=bar), or wildcard patterns (*, ?) require care because each independent command segment is evaluated separately.
## How to request escalation
IMPORTANT: To request approval to execute a command that will require escalated privileges:
- Provide the `sandbox_permissions` parameter with the value `"require_escalated"`
- Include a concise `justification` parameter that explains why escalated privileges are needed.
- Do not include a `prefix_rule` parameter.
## When to request escalation
While commands are running inside the sandbox, here are some scenarios that justify escalation:
- When the sandbox is likely to block a command needed for the task, request escalation up front.
- Request escalation for commands that need write access outside writable roots, such as tests that write to `/var`.
- Request escalation for git operations that may write lock files, such as updating the index or refs.
- Request escalation for commands that may need network access, including HTTP calls, package registries, internal services, data-service APIs, remote queries, data fetches, or live probes.
- Request escalation for commands that may need remote authentication, cluster, cloud, or database access.
- Request escalation for commands that may need process, cache, or other environment access outside the sandbox.
- If a sandboxed attempt fails with sandboxing or likely network symptoms, including DNS, connection, authentication, retry, or service endpoint errors, rerun with `sandbox_permissions` set to `"require_escalated"` and include `justification`.
- If a command may be hanging on sandbox-blocked access, stop after a short timeout and rerun with `require_escalated`.
- Request escalation before potentially destructive actions, such as `rm` or `git reset`, that the user did not explicitly ask for.
- When unsure, prefer requesting escalation unnecessarily over failing to request it when needed.