Use step environments for Guardian approval reviews (#37618)

## Why

Deferred environments can become ready after a turn starts. Guardian approval
reviews must use the environment selected for the current step so their working
directory and permission context are not taken from the stale turn snapshot.

## What changed

- Carry `StepContext` through tool execution and approval handling.
- Add a Guardian review context that pairs the parent turn with the current
  step's environment snapshot.
- Use that snapshot for Guardian prompts, reviewer sessions, and delegated
  reviewer threads while retaining turn-level fallbacks for callers without a
  step context.

## Testing

Added an integration test that makes a deferred remote environment ready before
an escalated command and verifies Guardian receives that environment's working
directory and denied-read policy instead of the initial local environment's.

GitOrigin-RevId: 779096bc7d0e0c7453a009c02141029714b9b407
This commit is contained in:
sayan-oai authored and copyberry committed 2026-08-08 20:07:27 +00:00
1 parent 936f5eb3ee
commit dd43a9967f
29 files changed
+387 -131

No files matched your search

+4 -3
View File
@@ -2478,12 +2478,14 @@ impl Session {
)]
pub(crate) async fn request_permissions_for_environment(
self: &Arc<Self>,
turn_context: &Arc<TurnContext>,
review_context: impl Into<crate::guardian::GuardianReviewContext>,
call_id: String,
args: RequestPermissionsArgs,
environment: TurnEnvironmentSelection,
cancellation_token: CancellationToken,
) -> Option<RequestPermissionsResponse> {
let review_context = review_context.into();
let turn_context = review_context.turn();
match turn_context.as_ref().approval_policy() {
AskForApproval::Never => {
return Some(RequestPermissionsResponse {
@@ -2527,7 +2529,6 @@ impl Session {
};
let review_id = crate::guardian::new_guardian_review_id();
let session = Arc::clone(self);
let turn = Arc::clone(turn_context);
let request = crate::guardian::GuardianApprovalRequest::RequestPermissions {
id: call_id,
turn_id: turn_context.sub_id.clone(),
@@ -2536,7 +2537,7 @@ impl Session {
};
let review_rx = crate::guardian::spawn_approval_request_review(
session,
turn,
review_context.clone(),
review_id,
request,
/*retry_reason*/ None,