Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ RUST_LOG=buzz_relay=debug,buzz_datastore=info,buzz_db=debug,buzz_auth=debug,buzz
# Use `buzz-acp models` to discover available model IDs.
# BUZZ_ACP_MODEL=

# Reviewer for eligible Codex sandbox approval requests.
# Values: user, auto-review (alias: auto_review). Unset preserves Codex's default.
# BUZZ_ACP_CODEX_APPROVALS_REVIEWER=auto-review

# ── Timeouts & sessions ──────────────────────────────────────────────────────
# Max seconds per agent turn before timeout (default 320 = ~5 min).
# BUZZ_ACP_TURN_TIMEOUT=320
Expand Down
1 change: 1 addition & 0 deletions crates/buzz-acp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ All configuration is via environment variables (or CLI flags — every env var h
| `BUZZ_ACP_AGENT_COMMAND` | no | `goose` | Agent binary to spawn. |
| `BUZZ_ACP_AGENT_ARGS` | no | `acp` | Agent arguments (comma-separated). |
| `BUZZ_ACP_MCP_COMMAND` | no | `""` (empty) | Path to an optional MCP server binary to provide to the agent subprocess. |
| `BUZZ_ACP_CODEX_APPROVALS_REVIEWER` | no | Codex default | Reviewer for eligible Codex sandbox approval requests: `user` or `auto-review` (`auto_review` alias). Auto-review is Codex's “Approve for me” behavior and does not widen the sandbox. |
| `BUZZ_ACP_IDLE_TIMEOUT` | no | `620` | Idle timeout: max seconds of silence before cancelling a turn. Resets on any agent stdout activity. |
| `BUZZ_ACP_MAX_TURN_DURATION` | no | `7200` | Absolute wall-clock cap per turn (safety valve). |
| `BUZZ_API_TOKEN` | no | — | API token (required if relay enforces token auth). |
Expand Down
41 changes: 41 additions & 0 deletions crates/buzz-acp/src/acp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4271,6 +4271,8 @@ mod tests {
}

const GENERATED: &str = r#"{"sandbox_workspace_write":{"network_access":true}}"#;
const GENERATED_AUTO_REVIEW: &str =
r#"{"approvals_reviewer":"auto_review","sandbox_workspace_write":{"network_access":true}}"#;

#[test]
fn build_codex_config_env_returns_none_when_no_codex_config_in_extra_env() {
Expand Down Expand Up @@ -4364,6 +4366,45 @@ mod tests {
);
}

#[test]
fn build_codex_config_env_merges_auto_review_with_persona_and_parent_precedence() {
let persona = r#"{"approvals_reviewer":"user","some_feature":{"enabled":true}}"#;
let extra = env(&[
("CODEX_CONFIG", persona),
("CODEX_CONFIG", GENERATED_AUTO_REVIEW),
]);

let merged = build_codex_config_env(&extra, None, true).unwrap().unwrap();
let value: serde_json::Value = serde_json::from_str(&merged).unwrap();
assert_eq!(
value["approvals_reviewer"], "auto_review",
"generated reviewer must overlay the persona value"
);
assert_eq!(
value["some_feature"]["enabled"], true,
"unrelated persona config must survive"
);
assert_eq!(
value["sandbox_workspace_write"]["network_access"], true,
"generated relay network access must survive"
);

let parent = r#"{"approvals_reviewer":"user","parent_key":"keep"}"#;
let merged = build_codex_config_env(&extra, Some(parent), true)
.unwrap()
.unwrap();
let value: serde_json::Value = serde_json::from_str(&merged).unwrap();
assert_eq!(
value["approvals_reviewer"], "user",
"parent CODEX_CONFIG must retain its established collision precedence"
);
assert_eq!(value["parent_key"], "keep");
assert_eq!(
value["sandbox_workspace_write"]["network_access"], true,
"forced relay network access remains the final invariant"
);
}

#[test]
fn build_codex_config_env_nested_persona_keys_survive_when_parent_has_same_top_level_key() {
// Persona has sandbox_workspace_write.persona_only; parent has
Expand Down
Loading