From b81d891b0bb1631261f5e1314149eefaa265f4f6 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Thu, 14 May 2026 15:38:35 -0700 Subject: [PATCH] Comment turn context update flow --- .../src/request_processors/turn_processor.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/codex-rs/app-server/src/request_processors/turn_processor.rs b/codex-rs/app-server/src/request_processors/turn_processor.rs index abd21a4a7b..2ae905cc39 100644 --- a/codex-rs/app-server/src/request_processors/turn_processor.rs +++ b/codex-rs/app-server/src/request_processors/turn_processor.rs @@ -360,6 +360,10 @@ impl TurnRequestProcessor { base_snapshot: &ThreadConfigSnapshot, request: TurnContextOverrideRequest, ) -> Result, JSONRPCErrorError> { + // Both turn/start and thread/turnContext/update accept the same + // persistent turn-context fields. Resolve them once into the core + // override shape so validation and permission-profile expansion stay + // consistent between the two entry points. if request.sandbox_policy.is_some() && request.permissions.is_some() { return Err(invalid_request( "`permissions` cannot be combined with `sandboxPolicy`", @@ -415,6 +419,9 @@ impl TurnRequestProcessor { (None, None) }; + // None means the caller sent no context fields at all. Some means at + // least one explicit override was present, even if the effective value + // matches the current thread context. Ok(Some(CodexThreadTurnContextOverrides { cwd, approval_policy, @@ -516,6 +523,8 @@ impl TurnRequestProcessor { .await?; let has_turn_context_overrides = resolved_overrides.is_some(); if let Some(overrides) = resolved_overrides.as_ref() { + // Validate before accepting input so the request can fail without + // queuing a user turn. thread .preview_turn_context_overrides(overrides.clone()) .await @@ -561,6 +570,10 @@ impl TurnRequestProcessor { })?; if has_turn_context_overrides { + // The queued UserInputWithTurnContext owns the sticky context + // mutation. Wait for core to start processing that turn before + // reporting the effective state, otherwise a later direct update + // can appear to win and then be overwritten by this turn. let thread_state = self.thread_state_manager.thread_state(thread_id).await; let turn_started = { let mut thread_state = thread_state.lock().await; @@ -651,6 +664,8 @@ impl TurnRequestProcessor { .await?; let after_snapshot = if let Some(overrides) = resolved_overrides { + // There is no queued turn to order against here, so applying + // directly gives the caller a synchronized response snapshot. thread .update_turn_context_overrides(overrides) .await