mirror of
https://github.com/openai/codex.git
synced 2026-11-02 16:20:35 +00:00
Rebrand approvals reviewer config to auto-review (#18504)
### Why Auto-review is the user-facing name for the approvals reviewer, but the config/API value still exposed the old `guardian_subagent` name. That made new configs and generated schemas point users at Guardian terminology even though the intended product surface is Auto-review. This PR updates the external `approvals_reviewer` value while preserving compatibility for existing configs and clients. ### What changed - Makes `auto_review` the canonical serialized value for `approvals_reviewer`. - Keeps `guardian_subagent` accepted as a legacy alias. - Keeps `user` accepted and serialized as `user`. - Updates generated config and app-server schemas so `approvals_reviewer` includes: - `user` - `auto_review` - `guardian_subagent` - Updates app-server README docs for the reviewer value. - Updates analytics and config requirements tests for the canonical auto_review value. ### Compatibility Existing configs and API payloads using: ```toml approvals_reviewer = "guardian_subagent" ``` continue to load and map to the Auto-review reviewer behavior. New serialization emits: ```toml approvals_reviewer = "auto_review" ``` This PR intentionally does not rename the [features].guardian_approval key or broad internal Guardian symbols. Those are split out for a follow-up PR to keep this migration small and avoid touching large TUI/internal surfaces. **Verification** cargo test -p codex-protocol approvals_reviewer_serializes_auto_review_and_accepts_legacy_guardian_subagent cargo test -p codex-app-server-protocol approvals_reviewer_serializes_auto_review_and_accepts_legacy_guardian_subagent
This commit is contained in:
1 parent
0e25c5ff42
commit
46142c3cb0
22 files changed
+197
-39
No files matched your search
@@ -1334,7 +1334,7 @@ fn subagent_thread_started_other_serializes_explicit_parent_thread_id() {
|
|||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
let payload = serde_json::to_value(&event).expect("serialize guardian subagent event");
|
let payload = serde_json::to_value(&event).expect("serialize auto-review subagent event");
|
||||||
assert_eq!(payload["event_params"]["subagent_source"], "guardian");
|
assert_eq!(payload["event_params"]["subagent_source"], "guardian");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
payload["event_params"]["parent_thread_id"],
|
payload["event_params"]["parent_thread_id"],
|
||||||
@@ -1758,7 +1758,7 @@ fn turn_event_serializes_expected_shape() {
|
|||||||
reasoning_summary: Some("detailed".to_string()),
|
reasoning_summary: Some("detailed".to_string()),
|
||||||
service_tier: "flex".to_string(),
|
service_tier: "flex".to_string(),
|
||||||
approval_policy: "on-request".to_string(),
|
approval_policy: "on-request".to_string(),
|
||||||
approvals_reviewer: "guardian_subagent".to_string(),
|
approvals_reviewer: "auto_review".to_string(),
|
||||||
sandbox_network_access: true,
|
sandbox_network_access: true,
|
||||||
collaboration_mode: Some("plan"),
|
collaboration_mode: Some("plan"),
|
||||||
personality: Some("pragmatic".to_string()),
|
personality: Some("pragmatic".to_string()),
|
||||||
@@ -1819,7 +1819,7 @@ fn turn_event_serializes_expected_shape() {
|
|||||||
"reasoning_summary": "detailed",
|
"reasoning_summary": "detailed",
|
||||||
"service_tier": "flex",
|
"service_tier": "flex",
|
||||||
"approval_policy": "on-request",
|
"approval_policy": "on-request",
|
||||||
"approvals_reviewer": "guardian_subagent",
|
"approvals_reviewer": "auto_review",
|
||||||
"sandbox_network_access": true,
|
"sandbox_network_access": true,
|
||||||
"collaboration_mode": "plan",
|
"collaboration_mode": "plan",
|
||||||
"personality": "pragmatic",
|
"personality": "pragmatic",
|
||||||
|
|||||||
+2
-1
@@ -13,9 +13,10 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
+2
-1
@@ -5728,9 +5728,10 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
+2
-1
@@ -605,9 +605,10 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
@@ -97,9 +97,10 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
+2
-1
@@ -2,9 +2,10 @@
|
|||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
@@ -6,9 +6,10 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
@@ -9,9 +9,10 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
@@ -6,9 +6,10 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
@@ -9,9 +9,10 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
@@ -6,9 +6,10 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
@@ -9,9 +9,10 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
@@ -6,9 +6,10 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
/**
|
/**
|
||||||
* Configures who approval requests are routed to for review. Examples
|
* Configures who approval requests are routed to for review. Examples
|
||||||
* include sandbox escapes, blocked network access, MCP approval prompts, and
|
* include sandbox escapes, blocked network access, MCP approval prompts, and
|
||||||
* ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully
|
* ARC escalations. Defaults to `user`. `auto_review` uses a carefully
|
||||||
* prompted subagent to gather relevant context and apply a risk-based
|
* prompted subagent to gather relevant context and apply a risk-based
|
||||||
* decision framework before approving or denying the request.
|
* decision framework before approving or denying the request.
|
||||||
*/
|
*/
|
||||||
export type ApprovalsReviewer = "user" | "guardian_subagent";
|
export type ApprovalsReviewer = "user" | "auto_review" | "guardian_subagent";
|
||||||
@@ -101,6 +101,11 @@ use codex_protocol::user_input::TextElement as CoreTextElement;
|
|||||||
use codex_protocol::user_input::UserInput as CoreUserInput;
|
use codex_protocol::user_input::UserInput as CoreUserInput;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
|
use schemars::r#gen::SchemaGenerator;
|
||||||
|
use schemars::schema::InstanceType;
|
||||||
|
use schemars::schema::Metadata;
|
||||||
|
use schemars::schema::Schema;
|
||||||
|
use schemars::schema::SchemaObject;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
@@ -304,19 +309,54 @@ impl From<CoreAskForApproval> for AskForApproval {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, TS)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[ts(
|
||||||
#[ts(rename_all = "snake_case", export_to = "v2/")]
|
type = r#""user" | "auto_review" | "guardian_subagent""#,
|
||||||
|
export_to = "v2/"
|
||||||
|
)]
|
||||||
/// Configures who approval requests are routed to for review. Examples
|
/// Configures who approval requests are routed to for review. Examples
|
||||||
/// include sandbox escapes, blocked network access, MCP approval prompts, and
|
/// include sandbox escapes, blocked network access, MCP approval prompts, and
|
||||||
/// ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully
|
/// ARC escalations. Defaults to `user`. `auto_review` uses a carefully
|
||||||
/// prompted subagent to gather relevant context and apply a risk-based
|
/// prompted subagent to gather relevant context and apply a risk-based
|
||||||
/// decision framework before approving or denying the request.
|
/// decision framework before approving or denying the request.
|
||||||
pub enum ApprovalsReviewer {
|
pub enum ApprovalsReviewer {
|
||||||
|
#[serde(rename = "user")]
|
||||||
User,
|
User,
|
||||||
|
#[serde(rename = "auto_review", alias = "guardian_subagent")]
|
||||||
GuardianSubagent,
|
GuardianSubagent,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl JsonSchema for ApprovalsReviewer {
|
||||||
|
fn schema_name() -> String {
|
||||||
|
"ApprovalsReviewer".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_schema(_generator: &mut SchemaGenerator) -> Schema {
|
||||||
|
string_enum_schema_with_description(
|
||||||
|
&["user", "auto_review", "guardian_subagent"],
|
||||||
|
"Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string_enum_schema_with_description(values: &[&str], description: &str) -> Schema {
|
||||||
|
let mut schema = SchemaObject {
|
||||||
|
instance_type: Some(InstanceType::String.into()),
|
||||||
|
metadata: Some(Box::new(Metadata {
|
||||||
|
description: Some(description.to_string()),
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
schema.enum_values = Some(
|
||||||
|
values
|
||||||
|
.iter()
|
||||||
|
.map(|value| JsonValue::String((*value).to_string()))
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
Schema::Object(schema)
|
||||||
|
}
|
||||||
|
|
||||||
impl ApprovalsReviewer {
|
impl ApprovalsReviewer {
|
||||||
pub fn to_core(self) -> CoreApprovalsReviewer {
|
pub fn to_core(self) -> CoreApprovalsReviewer {
|
||||||
match self {
|
match self {
|
||||||
@@ -7346,6 +7386,31 @@ mod tests {
|
|||||||
absolute_path("readable")
|
absolute_path("readable")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn approvals_reviewer_serializes_auto_review_and_accepts_legacy_guardian_subagent() {
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_string(&ApprovalsReviewer::User).expect("serialize reviewer"),
|
||||||
|
"\"user\""
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_string(&ApprovalsReviewer::GuardianSubagent)
|
||||||
|
.expect("serialize reviewer"),
|
||||||
|
"\"auto_review\""
|
||||||
|
);
|
||||||
|
|
||||||
|
for value in ["user", "auto_review", "guardian_subagent"] {
|
||||||
|
let json = format!("\"{value}\"");
|
||||||
|
let reviewer: ApprovalsReviewer =
|
||||||
|
serde_json::from_str(&json).expect("deserialize reviewer");
|
||||||
|
let expected = if value == "user" {
|
||||||
|
ApprovalsReviewer::User
|
||||||
|
} else {
|
||||||
|
ApprovalsReviewer::GuardianSubagent
|
||||||
|
};
|
||||||
|
assert_eq!(expected, reviewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn thread_list_params_accepts_single_cwd() {
|
fn thread_list_params_accepts_single_cwd() {
|
||||||
let params = serde_json::from_value::<ThreadListParams>(json!({
|
let params = serde_json::from_value::<ThreadListParams>(json!({
|
||||||
|
|||||||
@@ -529,7 +529,7 @@ You can optionally specify config overrides on the new turn. If specified, these
|
|||||||
`approvalsReviewer` accepts:
|
`approvalsReviewer` accepts:
|
||||||
|
|
||||||
- `"user"` — default. Review approval requests directly in the client.
|
- `"user"` — default. Review approval requests directly in the client.
|
||||||
- `"guardian_subagent"` — route approval requests to a carefully prompted subagent, which gathers relevant context and applies a risk-based decision framework before approving or denying the request.
|
- `"auto_review"` — route approval requests to a carefully prompted subagent, which gathers relevant context and applies a risk-based decision framework before approving or denying the request. The legacy value `"guardian_subagent"` is still accepted for compatibility.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "method": "turn/start", "id": 30, "params": {
|
{ "method": "turn/start", "id": 30, "params": {
|
||||||
|
|||||||
@@ -1649,7 +1649,7 @@ allowed_approvals_reviewers = ["user"]
|
|||||||
let source: ConfigRequirementsToml = from_str(
|
let source: ConfigRequirementsToml = from_str(
|
||||||
r#"
|
r#"
|
||||||
allowed_approval_policies = ["on-request"]
|
allowed_approval_policies = ["on-request"]
|
||||||
allowed_approvals_reviewers = ["guardian_subagent"]
|
allowed_approvals_reviewers = ["auto_review"]
|
||||||
allowed_sandbox_modes = ["read-only"]
|
allowed_sandbox_modes = ["read-only"]
|
||||||
"#,
|
"#,
|
||||||
)?;
|
)?;
|
||||||
@@ -1730,7 +1730,7 @@ allowed_approvals_reviewers = ["user"]
|
|||||||
let source: ConfigRequirementsToml = from_str(
|
let source: ConfigRequirementsToml = from_str(
|
||||||
r#"
|
r#"
|
||||||
allowed_approval_policies = ["on-request"]
|
allowed_approval_policies = ["on-request"]
|
||||||
allowed_approvals_reviewers = ["guardian_subagent"]
|
allowed_approvals_reviewers = ["auto_review"]
|
||||||
allowed_sandbox_modes = ["read-only"]
|
allowed_sandbox_modes = ["read-only"]
|
||||||
allowed_web_search_modes = ["cached"]
|
allowed_web_search_modes = ["cached"]
|
||||||
enforce_residency = "us"
|
enforce_residency = "us"
|
||||||
@@ -1830,7 +1830,7 @@ allowed_approvals_reviewers = ["user"]
|
|||||||
#[test]
|
#[test]
|
||||||
fn deserialize_allowed_approvals_reviewers() -> Result<()> {
|
fn deserialize_allowed_approvals_reviewers() -> Result<()> {
|
||||||
let toml_str = r#"
|
let toml_str = r#"
|
||||||
allowed_approvals_reviewers = ["guardian_subagent", "user"]
|
allowed_approvals_reviewers = ["auto_review", "user"]
|
||||||
"#;
|
"#;
|
||||||
let config: ConfigRequirementsToml = from_str(toml_str)?;
|
let config: ConfigRequirementsToml = from_str(toml_str)?;
|
||||||
let requirements: ConfigRequirements = with_unknown_source(config).try_into()?;
|
let requirements: ConfigRequirements = with_unknown_source(config).try_into()?;
|
||||||
@@ -1856,6 +1856,22 @@ allowed_approvals_reviewers = ["user"]
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deserialize_legacy_allowed_approvals_reviewer() -> Result<()> {
|
||||||
|
let toml_str = r#"
|
||||||
|
allowed_approvals_reviewers = ["guardian_subagent", "user"]
|
||||||
|
"#;
|
||||||
|
let config: ConfigRequirementsToml = from_str(toml_str)?;
|
||||||
|
let requirements: ConfigRequirements = with_unknown_source(config).try_into()?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
requirements.approvals_reviewer.value(),
|
||||||
|
ApprovalsReviewer::GuardianSubagent
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_allowed_approvals_reviewers_is_rejected() -> Result<()> {
|
fn empty_allowed_approvals_reviewers_is_rejected() -> Result<()> {
|
||||||
let toml_str = r#"
|
let toml_str = r#"
|
||||||
|
|||||||
@@ -169,9 +169,10 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"ApprovalsReviewer": {
|
"ApprovalsReviewer": {
|
||||||
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request.",
|
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
"enum": [
|
"enum": [
|
||||||
"user",
|
"user",
|
||||||
|
"auto_review",
|
||||||
"guardian_subagent"
|
"guardian_subagent"
|
||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
@@ -1025,8 +1025,8 @@ async fn load_project_layers(
|
|||||||
///
|
///
|
||||||
/// If present, re-interpret `managed_config.toml` as a `requirements.toml`
|
/// If present, re-interpret `managed_config.toml` as a `requirements.toml`
|
||||||
/// where each specified field is treated as a constraint. Most fields allow
|
/// where each specified field is treated as a constraint. Most fields allow
|
||||||
/// only the specified value. `approvals_reviewer = "guardian_subagent"` also
|
/// only the specified value. `approvals_reviewer = "auto_review"` also allows
|
||||||
/// allows `user` so people can opt out of the guardian reviewer.
|
/// `user` so people can opt out of the auto-reviewer.
|
||||||
#[derive(Deserialize, Debug, Clone, Default, PartialEq)]
|
#[derive(Deserialize, Debug, Clone, Default, PartialEq)]
|
||||||
struct LegacyManagedConfigToml {
|
struct LegacyManagedConfigToml {
|
||||||
approval_policy: Option<AskForApproval>,
|
approval_policy: Option<AskForApproval>,
|
||||||
@@ -1145,7 +1145,7 @@ foo = "xyzzy"
|
|||||||
requirements.allowed_approvals_reviewers,
|
requirements.allowed_approvals_reviewers,
|
||||||
Some(vec![
|
Some(vec![
|
||||||
ApprovalsReviewer::GuardianSubagent,
|
ApprovalsReviewer::GuardianSubagent,
|
||||||
ApprovalsReviewer::User
|
ApprovalsReviewer::User,
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
|
use schemars::r#gen::SchemaGenerator;
|
||||||
|
use schemars::schema::InstanceType;
|
||||||
|
use schemars::schema::Metadata;
|
||||||
|
use schemars::schema::Schema;
|
||||||
|
use schemars::schema::SchemaObject;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use serde_json::Value;
|
||||||
use std::num::NonZeroU64;
|
use std::num::NonZeroU64;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use strum_macros::Display;
|
use strum_macros::Display;
|
||||||
@@ -69,22 +75,54 @@ pub enum SandboxMode {
|
|||||||
DangerFullAccess,
|
DangerFullAccess,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Display, TS)]
|
||||||
Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Display, JsonSchema, TS,
|
|
||||||
)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
#[strum(serialize_all = "snake_case")]
|
#[strum(serialize_all = "snake_case")]
|
||||||
|
#[ts(type = r#""user" | "auto_review" | "guardian_subagent""#)]
|
||||||
/// Configures who approval requests are routed to for review. Examples
|
/// Configures who approval requests are routed to for review. Examples
|
||||||
/// include sandbox escapes, blocked network access, MCP approval prompts, and
|
/// include sandbox escapes, blocked network access, MCP approval prompts, and
|
||||||
/// ARC escalations. Defaults to `user`. `guardian_subagent` uses a carefully
|
/// ARC escalations. Defaults to `user`. `auto_review` uses a carefully
|
||||||
/// prompted subagent to gather relevant context and apply a risk-based
|
/// prompted subagent to gather relevant context and apply a risk-based
|
||||||
/// decision framework before approving or denying the request.
|
/// decision framework before approving or denying the request.
|
||||||
pub enum ApprovalsReviewer {
|
pub enum ApprovalsReviewer {
|
||||||
#[default]
|
#[default]
|
||||||
|
#[serde(rename = "user")]
|
||||||
User,
|
User,
|
||||||
|
#[serde(rename = "auto_review", alias = "guardian_subagent")]
|
||||||
|
#[strum(serialize = "auto_review")]
|
||||||
GuardianSubagent,
|
GuardianSubagent,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl JsonSchema for ApprovalsReviewer {
|
||||||
|
fn schema_name() -> String {
|
||||||
|
"ApprovalsReviewer".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_schema(_generator: &mut SchemaGenerator) -> Schema {
|
||||||
|
string_enum_schema_with_description(
|
||||||
|
&["user", "auto_review", "guardian_subagent"],
|
||||||
|
"Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string_enum_schema_with_description(values: &[&str], description: &str) -> Schema {
|
||||||
|
let mut schema = SchemaObject {
|
||||||
|
instance_type: Some(InstanceType::String.into()),
|
||||||
|
metadata: Some(Box::new(Metadata {
|
||||||
|
description: Some(description.to_string()),
|
||||||
|
..Default::default()
|
||||||
|
})),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
schema.enum_values = Some(
|
||||||
|
values
|
||||||
|
.iter()
|
||||||
|
.map(|value| Value::String((*value).to_string()))
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
Schema::Object(schema)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Display, JsonSchema, TS,
|
Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Display, JsonSchema, TS,
|
||||||
)]
|
)]
|
||||||
@@ -562,6 +600,32 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn approvals_reviewer_serializes_auto_review_and_accepts_legacy_guardian_subagent() {
|
||||||
|
assert_eq!(ApprovalsReviewer::User.to_string(), "user");
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_string(&ApprovalsReviewer::User).expect("serialize reviewer"),
|
||||||
|
"\"user\""
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_string(&ApprovalsReviewer::GuardianSubagent)
|
||||||
|
.expect("serialize reviewer"),
|
||||||
|
"\"auto_review\""
|
||||||
|
);
|
||||||
|
|
||||||
|
for value in ["user", "auto_review", "guardian_subagent"] {
|
||||||
|
let json = format!("\"{value}\"");
|
||||||
|
let reviewer: ApprovalsReviewer =
|
||||||
|
serde_json::from_str(&json).expect("deserialize reviewer");
|
||||||
|
let expected = if value == "user" {
|
||||||
|
ApprovalsReviewer::User
|
||||||
|
} else {
|
||||||
|
ApprovalsReviewer::GuardianSubagent
|
||||||
|
};
|
||||||
|
assert_eq!(expected, reviewer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tui_visible_collaboration_modes_match_mode_kind_visibility() {
|
fn tui_visible_collaboration_modes_match_mode_kind_visibility() {
|
||||||
let expected = [ModeKind::Default, ModeKind::Plan];
|
let expected = [ModeKind::Default, ModeKind::Plan];
|
||||||
|
|||||||
@@ -1675,7 +1675,7 @@ async fn update_feature_flags_enabling_guardian_selects_guardian_approvals() ->
|
|||||||
|
|
||||||
let config = std::fs::read_to_string(codex_home.path().join("config.toml"))?;
|
let config = std::fs::read_to_string(codex_home.path().join("config.toml"))?;
|
||||||
assert!(config.contains("guardian_approval = true"));
|
assert!(config.contains("guardian_approval = true"));
|
||||||
assert!(config.contains("approvals_reviewer = \"guardian_subagent\""));
|
assert!(config.contains("approvals_reviewer = \"auto_review\""));
|
||||||
assert!(config.contains("approval_policy = \"on-request\""));
|
assert!(config.contains("approval_policy = \"on-request\""));
|
||||||
assert!(config.contains("sandbox_mode = \"workspace-write\""));
|
assert!(config.contains("sandbox_mode = \"workspace-write\""));
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1835,7 +1835,7 @@ async fn update_feature_flags_enabling_guardian_overrides_explicit_manual_review
|
|||||||
);
|
);
|
||||||
|
|
||||||
let config = std::fs::read_to_string(codex_home.path().join("config.toml"))?;
|
let config = std::fs::read_to_string(codex_home.path().join("config.toml"))?;
|
||||||
assert!(config.contains("approvals_reviewer = \"guardian_subagent\""));
|
assert!(config.contains("approvals_reviewer = \"auto_review\""));
|
||||||
assert!(config.contains("guardian_approval = true"));
|
assert!(config.contains("guardian_approval = true"));
|
||||||
assert!(config.contains("approval_policy = \"on-request\""));
|
assert!(config.contains("approval_policy = \"on-request\""));
|
||||||
assert!(config.contains("sandbox_mode = \"workspace-write\""));
|
assert!(config.contains("sandbox_mode = \"workspace-write\""));
|
||||||
@@ -1969,7 +1969,7 @@ async fn update_feature_flags_enabling_guardian_in_profile_sets_profile_auto_rev
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
profile_config.get("approvals_reviewer"),
|
profile_config.get("approvals_reviewer"),
|
||||||
Some(&TomlValue::String("guardian_subagent".to_string()))
|
Some(&TomlValue::String("auto_review".to_string()))
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -690,7 +690,7 @@ mod tests {
|
|||||||
rendered.contains("allowed_approval_policies: on-request (source: cloud requirements)")
|
rendered.contains("allowed_approval_policies: on-request (source: cloud requirements)")
|
||||||
);
|
);
|
||||||
assert!(rendered.contains(
|
assert!(rendered.contains(
|
||||||
"allowed_approvals_reviewers: guardian_subagent (source: MDM managed_config.toml (legacy))"
|
"allowed_approvals_reviewers: auto_review (source: MDM managed_config.toml (legacy))"
|
||||||
));
|
));
|
||||||
assert!(
|
assert!(
|
||||||
rendered.contains(
|
rendered.contains(
|
||||||
@@ -745,7 +745,7 @@ mod tests {
|
|||||||
|
|
||||||
let rendered = render_to_text(&render_debug_config_lines(&stack));
|
let rendered = render_to_text(&render_debug_config_lines(&stack));
|
||||||
assert!(rendered.contains(
|
assert!(rendered.contains(
|
||||||
"allowed_approvals_reviewers: guardian_subagent (source: MDM managed_config.toml (legacy))"
|
"allowed_approvals_reviewers: auto_review (source: MDM managed_config.toml (legacy))"
|
||||||
));
|
));
|
||||||
assert!(!rendered.contains("Requirements:\n <none>"));
|
assert!(!rendered.contains("Requirements:\n <none>"));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user