Record sandbox backends in command execution analytics (#47568)

## Why

Command execution analytics lack the observed sandbox backend. Older execution servers may omit this information, so an unknown backend must remain distinguishable from an explicitly unsandboxed process.

## What changed

- Carry optional `sandbox_type` metadata through command execution items and emit its metric tag as `sandbox_backend` in analytics.
- Propagate the observed backend through unified execution completion and failure events, including asynchronous exits.
- Preserve missing backend information as `None` and mark executed user shell commands as `Some(SandboxType::None)`.
- Exclude the metadata from serialized command items and generated schemas and TypeScript types.

## Testing

Extend tests for missing and explicit executor backends, backend propagation on failed execution, and analytics payloads, including platform-specific backend tags in app-server integration coverage.

GitOrigin-RevId: 178fe46824a6194910802ec02168ed40ee0b2019
This commit is contained in:
iceweasel-oai
2026-09-23 15:05:59 +00:00
committed by copyberry
parent d6c4c6aea4
commit 6f6af0fce4
29 changed files with 113 additions and 21 deletions
@@ -170,6 +170,7 @@ fn command_execution_started_and_completed_translate_to_thread_events() {
let mut processor = EventProcessorWithJsonOutput::new(/*last_message_path*/ None);
let command_item = ThreadItem::CommandExecution {
model_context: None,
sandbox_type: None,
id: "cmd-1".to_string(),
command: "ls".to_string(),
cwd: test_path_buf("/tmp/project").abs().into(),
@@ -213,6 +214,7 @@ fn command_execution_started_and_completed_translate_to_thread_events() {
ItemCompletedNotification {
item: ThreadItem::CommandExecution {
model_context: None,
sandbox_type: None,
id: "cmd-1".to_string(),
command: "ls".to_string(),
cwd: test_path_buf("/tmp/project").abs().into(),
@@ -1415,6 +1417,7 @@ fn turn_completion_reconciles_started_items_from_turn_items() {
processor.collect_thread_events(ServerNotification::ItemStarted(ItemStartedNotification {
item: ThreadItem::CommandExecution {
model_context: None,
sandbox_type: None,
id: "cmd-1".to_string(),
command: "ls".to_string(),
cwd: test_path_buf("/tmp/project").abs().into(),
@@ -1458,6 +1461,7 @@ fn turn_completion_reconciles_started_items_from_turn_items() {
items_view: codex_app_server_protocol::TurnItemsView::Full,
items: vec![ThreadItem::CommandExecution {
model_context: None,
sandbox_type: None,
id: "cmd-1".to_string(),
command: "ls".to_string(),
cwd: test_path_buf("/tmp/project").abs().into(),