Files
codex/codex-rs/core/src/features_tests.rs
Charley Cunningham 6fdeb1d602 Reuse guardian session across approvals (#14668)
## Summary
- reuse a guardian subagent session across approvals so reviews keep a
stable prompt cache key and avoid one-shot startup overhead
- clear the guardian child history before each review so prior guardian
decisions do not leak into later approvals
- include the `smart_approvals` -> `guardian_approval` feature flag
rename in the same PR to minimize release latency on a very tight
timeline
- add regression coverage for prompt-cache-key reuse without
prior-review prompt bleed

## Request
- Bug/enhancement request: internal guardian prompt-cache and latency
improvement request

---------

Co-authored-by: Codex <noreply@openai.com>
2026-03-15 22:56:18 -07:00

186 lines
6.1 KiB
Rust

use super::*;
use pretty_assertions::assert_eq;
#[test]
fn under_development_features_are_disabled_by_default() {
for spec in FEATURES {
if matches!(spec.stage, Stage::UnderDevelopment) {
assert_eq!(
spec.default_enabled, false,
"feature `{}` is under development and must be disabled by default",
spec.key
);
}
}
}
#[test]
fn default_enabled_features_are_stable() {
for spec in FEATURES {
if spec.default_enabled {
assert!(
matches!(spec.stage, Stage::Stable | Stage::Removed),
"feature `{}` is enabled by default but is not stable/removed ({:?})",
spec.key,
spec.stage
);
}
}
}
#[test]
fn use_legacy_landlock_is_stable_and_disabled_by_default() {
assert_eq!(Feature::UseLegacyLandlock.stage(), Stage::Stable);
assert_eq!(Feature::UseLegacyLandlock.default_enabled(), false);
}
#[test]
fn use_linux_sandbox_bwrap_is_removed_and_disabled_by_default() {
assert_eq!(Feature::UseLinuxSandboxBwrap.stage(), Stage::Removed);
assert_eq!(Feature::UseLinuxSandboxBwrap.default_enabled(), false);
}
#[test]
fn js_repl_is_experimental_and_user_toggleable() {
let spec = Feature::JsRepl.info();
let stage = spec.stage;
let expected_node_version = include_str!("../../node-version.txt").trim_end();
assert!(matches!(stage, Stage::Experimental { .. }));
assert_eq!(stage.experimental_menu_name(), Some("JavaScript REPL"));
assert_eq!(
stage.experimental_menu_description().map(str::to_owned),
Some(format!(
"Enable a persistent Node-backed JavaScript REPL for interactive website debugging and other inline JavaScript execution capabilities. Requires Node >= v{expected_node_version} installed."
))
);
assert_eq!(Feature::JsRepl.default_enabled(), false);
}
#[test]
fn code_mode_only_requires_code_mode() {
let mut features = Features::with_defaults();
features.enable(Feature::CodeModeOnly);
features.normalize_dependencies();
assert_eq!(features.enabled(Feature::CodeModeOnly), true);
assert_eq!(features.enabled(Feature::CodeMode), true);
}
#[test]
fn guardian_approval_is_experimental_and_user_toggleable() {
let spec = Feature::GuardianApproval.info();
let stage = spec.stage;
assert!(matches!(stage, Stage::Experimental { .. }));
assert_eq!(stage.experimental_menu_name(), Some("Guardian Approvals"));
assert_eq!(
stage.experimental_menu_description().map(str::to_owned),
Some(
"When Codex needs approval for higher-risk actions (e.g. sandbox escapes or blocked network access), route eligible approval requests to a carefully-prompted security reviewer subagent rather than blocking the agent on your input. This can consume significantly more tokens because it runs a subagent on every approval request.".to_string()
)
);
assert_eq!(stage.experimental_announcement(), None);
assert_eq!(Feature::GuardianApproval.default_enabled(), false);
}
#[test]
fn request_permissions_is_under_development() {
assert_eq!(
Feature::ExecPermissionApprovals.stage(),
Stage::UnderDevelopment
);
assert_eq!(Feature::ExecPermissionApprovals.default_enabled(), false);
}
#[test]
fn request_permissions_tool_is_under_development() {
assert_eq!(
Feature::RequestPermissionsTool.stage(),
Stage::UnderDevelopment
);
assert_eq!(Feature::RequestPermissionsTool.default_enabled(), false);
}
#[test]
fn tool_suggest_is_under_development() {
assert_eq!(Feature::ToolSuggest.stage(), Stage::UnderDevelopment);
assert_eq!(Feature::ToolSuggest.default_enabled(), false);
}
#[test]
fn use_linux_sandbox_bwrap_is_a_removed_feature_key() {
assert_eq!(
feature_for_key("use_legacy_landlock"),
Some(Feature::UseLegacyLandlock)
);
assert_eq!(
feature_for_key("use_linux_sandbox_bwrap"),
Some(Feature::UseLinuxSandboxBwrap)
);
}
#[test]
fn image_generation_is_under_development() {
assert_eq!(Feature::ImageGeneration.stage(), Stage::UnderDevelopment);
assert_eq!(Feature::ImageGeneration.default_enabled(), false);
}
#[test]
fn image_detail_original_feature_is_under_development() {
assert_eq!(
Feature::ImageDetailOriginal.stage(),
Stage::UnderDevelopment
);
assert_eq!(Feature::ImageDetailOriginal.default_enabled(), false);
}
#[test]
fn collab_is_legacy_alias_for_multi_agent() {
assert_eq!(feature_for_key("multi_agent"), Some(Feature::Collab));
assert_eq!(feature_for_key("collab"), Some(Feature::Collab));
}
#[test]
fn multi_agent_is_stable_and_enabled_by_default() {
assert_eq!(Feature::Collab.stage(), Stage::Stable);
assert_eq!(Feature::Collab.default_enabled(), true);
}
#[test]
fn enable_fanout_is_under_development() {
assert_eq!(Feature::SpawnCsv.stage(), Stage::UnderDevelopment);
assert_eq!(Feature::SpawnCsv.default_enabled(), false);
}
#[test]
fn enable_fanout_normalization_enables_multi_agent_one_way() {
let mut enable_fanout_features = Features::with_defaults();
enable_fanout_features.enable(Feature::SpawnCsv);
enable_fanout_features.normalize_dependencies();
assert_eq!(enable_fanout_features.enabled(Feature::SpawnCsv), true);
assert_eq!(enable_fanout_features.enabled(Feature::Collab), true);
let mut collab_features = Features::with_defaults();
collab_features.enable(Feature::Collab);
collab_features.normalize_dependencies();
assert_eq!(collab_features.enabled(Feature::Collab), true);
assert_eq!(collab_features.enabled(Feature::SpawnCsv), false);
}
#[test]
fn apps_require_feature_flag_and_chatgpt_auth() {
let mut features = Features::with_defaults();
assert!(!features.apps_enabled_for_auth(None));
features.enable(Feature::Apps);
assert!(!features.apps_enabled_for_auth(None));
let api_key_auth = CodexAuth::from_api_key("test-api-key");
assert!(!features.apps_enabled_for_auth(Some(&api_key_auth)));
let chatgpt_auth = CodexAuth::create_dummy_chatgpt_auth_for_testing();
assert!(features.apps_enabled_for_auth(Some(&chatgpt_auth)));
}