From fe287ac467e915a4a75fccb8ce7b7b82d5c12e53 Mon Sep 17 00:00:00 2001 From: gabec-openai Date: Thu, 19 Mar 2026 12:10:41 -0700 Subject: [PATCH] Log automated reviewer approval sources distinctly (#15201) ## Summary - log guardian-reviewed tool approvals as `source=automated_reviewer` in `codex.tool_decision` - keep direct user approvals as `source=user` and config-driven approvals as `source=config` ## Testing - `/Users/gabec/.codex/skills/codex-oss-fastdev/scripts/codex-rs-fmt-quiet.sh` - `/Users/gabec/.codex/skills/codex-oss-fastdev/scripts/codex-rs-test-quiet.sh -p codex-otel` (fails in sandboxed loopback bind tests under `otel/tests/suite/otlp_http_loopback.rs`) - `cargo test -p codex-core guardian -- --nocapture` (original-tree run reached Guardian tests and only hit sandbox-related listener/proxy failures) Co-authored-by: Codex --- codex-rs/core/src/tools/orchestrator.rs | 15 +++++++++++++-- codex-rs/otel/src/lib.rs | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/codex-rs/core/src/tools/orchestrator.rs b/codex-rs/core/src/tools/orchestrator.rs index e41b90b4d..4b53ac156 100644 --- a/codex-rs/core/src/tools/orchestrator.rs +++ b/codex-rs/core/src/tools/orchestrator.rs @@ -112,6 +112,7 @@ impl ToolOrchestrator { let otel_tn = &tool_ctx.tool_name; let otel_ci = &tool_ctx.call_id; let otel_user = ToolDecisionSource::User; + let otel_automated_reviewer = ToolDecisionSource::AutomatedReviewer; let otel_cfg = ToolDecisionSource::Config; // 1) Approval @@ -136,8 +137,13 @@ impl ToolOrchestrator { network_approval_context: None, }; let decision = tool.start_approval_async(req, approval_ctx).await; + let otel_source = if routes_approval_to_guardian(turn_ctx) { + otel_automated_reviewer.clone() + } else { + otel_user.clone() + }; - otel.tool_decision(otel_tn, otel_ci, &decision, otel_user.clone()); + otel.tool_decision(otel_tn, otel_ci, &decision, otel_source); match decision { ReviewDecision::Denied | ReviewDecision::Abort => { @@ -286,7 +292,12 @@ impl ToolOrchestrator { }; let decision = tool.start_approval_async(req, approval_ctx).await; - otel.tool_decision(otel_tn, otel_ci, &decision, otel_user); + let otel_source = if routes_approval_to_guardian(turn_ctx) { + otel_automated_reviewer + } else { + otel_user + }; + otel.tool_decision(otel_tn, otel_ci, &decision, otel_source); match decision { ReviewDecision::Denied | ReviewDecision::Abort => { diff --git a/codex-rs/otel/src/lib.rs b/codex-rs/otel/src/lib.rs index 353130976..4eb27a56e 100644 --- a/codex-rs/otel/src/lib.rs +++ b/codex-rs/otel/src/lib.rs @@ -31,6 +31,7 @@ pub use codex_utils_string::sanitize_metric_tag_value; #[derive(Debug, Clone, Serialize, Display)] #[serde(rename_all = "snake_case")] pub enum ToolDecisionSource { + AutomatedReviewer, Config, User, }