mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Skip Guardian scoring in User approval mode (#42256)
## What changed - Skip Guardian prewarming and asynchronous scoring when `approvalsReviewer` is `"user"`, including when the reviewer changes during an active turn. - Automatically accept ordinary `node_repl.js` execution confirmations in this mode while continuing to surface sensitive-action checks and requests for user input. - Cover transitions between User approval, automatic review, and Full Access in the app-server integration tests. GitOrigin-RevId: 599c8ebb672728b9bf3d64c34377ddec230325f8
This commit is contained in:
1 parent
bdfd769640
commit
a0dcfe2ada
7 files changed
+182
-54
No files matched your search
@@ -40,6 +40,7 @@ use codex_login::AgentIdentityAuthPolicy;
|
||||
use codex_login::AuthManager;
|
||||
use codex_model_provider::create_model_provider;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::config_types::ApprovalsReviewer;
|
||||
use codex_protocol::mcp::is_node_repl_backed_server;
|
||||
use codex_protocol::mcp::is_node_repl_backed_tool;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
@@ -214,16 +215,18 @@ impl ThreadLifecycleContributor<Config> for GuardianV2Extension {
|
||||
.insert(TrustedSkillRoots::from_config(input.config));
|
||||
input.thread_store.insert(guardian_v2_enabled);
|
||||
|
||||
// Keep the sampler available if a later turn leaves Full Access, but do
|
||||
// not open Guardian connections while Full Access is selected.
|
||||
if !has_full_access(
|
||||
input.config.permissions.approval_policy.value(),
|
||||
&input.config.permissions.effective_permission_profile(),
|
||||
input
|
||||
.environments
|
||||
.iter()
|
||||
.map(|environment| &environment.config),
|
||||
) {
|
||||
// Keep the sampler available for later automatic review, but do not
|
||||
// prewarm while User approval mode or Full Access is selected.
|
||||
if input.config.approvals_reviewer == ApprovalsReviewer::AutoReview
|
||||
&& !has_full_access(
|
||||
input.config.permissions.approval_policy.value(),
|
||||
&input.config.permissions.effective_permission_profile(),
|
||||
input
|
||||
.environments
|
||||
.iter()
|
||||
.map(|environment| &environment.config),
|
||||
)
|
||||
{
|
||||
tokio::spawn(async move {
|
||||
sampler.prewarm().await;
|
||||
});
|
||||
@@ -493,10 +496,11 @@ impl GuardianV2Extension {
|
||||
return;
|
||||
}
|
||||
};
|
||||
// Read current permissions, not the startup config: existing threads can
|
||||
// enter Full Access after the sampler has already been initialized.
|
||||
// Use the live reviewer, not the startup config or per-app reviewer overrides.
|
||||
let snapshot = thread.config_snapshot().await;
|
||||
if snapshot.full_access {
|
||||
if snapshot.full_access
|
||||
|| thread.approvals_reviewer_for_turn(input.turn_id).await == ApprovalsReviewer::User
|
||||
{
|
||||
// A skipped call invalidates older scores, including ones still in flight.
|
||||
score_progress
|
||||
.latest_failed_tool_call
|
||||
|
||||
@@ -34,6 +34,7 @@ use codex_login::ExternalAuthRefreshContext;
|
||||
use codex_model_provider_info::ModelProviderInfo;
|
||||
use codex_protocol::ResponseItemId;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::config_types::ApprovalsReviewer;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputPayload;
|
||||
@@ -115,7 +116,10 @@ async fn installed_extension_warms_connections_without_blocking_thread_start() -
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let thread_server = responses::start_mock_server().await;
|
||||
let test = test_codex().build_with_auto_env(&thread_server).await?;
|
||||
let test = test_codex()
|
||||
.with_config(|config| config.approvals_reviewer = ApprovalsReviewer::AutoReview)
|
||||
.build_with_auto_env(&thread_server)
|
||||
.await?;
|
||||
let mut connections = vec![
|
||||
WebSocketConnectionConfig {
|
||||
requests: Vec::new(),
|
||||
@@ -172,7 +176,10 @@ async fn installed_extension_reconnects_after_auth_refresh() -> Result<()> {
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let thread_server = responses::start_mock_server().await;
|
||||
let test = test_codex().build_with_auto_env(&thread_server).await?;
|
||||
let test = test_codex()
|
||||
.with_config(|config| config.approvals_reviewer = ApprovalsReviewer::AutoReview)
|
||||
.build_with_auto_env(&thread_server)
|
||||
.await?;
|
||||
let events = vec![
|
||||
ev_assistant_message("sample", "low"),
|
||||
ev_completed("response-1"),
|
||||
@@ -903,7 +910,10 @@ async fn sample_configured_conversation_history_with_source(
|
||||
.policy = Some(TEST_CATALOG_GUARDIAN_POLICY.to_owned());
|
||||
})
|
||||
.with_model("gpt-5.5")
|
||||
.with_config(move |config| config.guardian_policy_config = guardian_policy)
|
||||
.with_config(move |config| {
|
||||
config.approvals_reviewer = ApprovalsReviewer::AutoReview;
|
||||
config.guardian_policy_config = guardian_policy;
|
||||
})
|
||||
.with_pre_build_hook(move |home| {
|
||||
std::fs::write(home.join("config.toml"), guardian_config)
|
||||
.expect("Guardian v2 configuration should be written");
|
||||
@@ -2171,6 +2181,7 @@ async fn contributor_skips_required_models_in_standard_scope() -> Result<()> {
|
||||
let test = test_codex()
|
||||
.with_home(Arc::clone(&initial.home))
|
||||
.with_config(move |config| {
|
||||
config.approvals_reviewer = ApprovalsReviewer::AutoReview;
|
||||
config.config_layer_stack = config_layer_stack;
|
||||
config
|
||||
.features
|
||||
@@ -2806,6 +2817,7 @@ async fn contributor_reuses_the_latest_compatible_parent_compaction() -> Result<
|
||||
|
||||
let thread_server = responses::start_mock_server().await;
|
||||
let test = test_codex()
|
||||
.with_config(|config| config.approvals_reviewer = ApprovalsReviewer::AutoReview)
|
||||
.with_pre_build_hook(|home| {
|
||||
std::fs::write(
|
||||
home.join("config.toml"),
|
||||
|
||||
Reference in new issue
Block a user