mirror of
https://github.com/openai/codex.git
synced 2026-11-13 06:45:07 +00:00
Source Guardian REPL policy from model metadata (#41919)
## What changed - Add `auto_review.node_repl_policy` to model messages for `node_repl` and `cua_repl` reviews. - Use the reviewer model's configured policy, falling back to the bundled policy when the field is absent and skipping injection when it is explicitly empty. - Include the effective policy in Guardian session reuse checks and reject unsafe parent-model fallback transitions that would change it. ## Testing - Cover catalog, bundled, and explicitly empty policies across Node and CUA review paths. - Verify that policy changes invalidate cached reviewer sessions and incompatible fallback transitions. GitOrigin-RevId: 51c0bdfed9b464091b6eb47d91ca5a0990d7a315
This commit is contained in:
1 parent
746798b2f7
commit
865bbf9a69
11 files changed
+144
-24
No files matched your search
@@ -8,6 +8,7 @@ use super::step_settings::StepSettingsUpdate;
|
||||
use super::turn_context::TurnContext;
|
||||
use crate::config::Config;
|
||||
use crate::config::ConstraintResult;
|
||||
use crate::context::GuardianNodeReplPolicy;
|
||||
use crate::exec_policy::AllowPrefixRules;
|
||||
use crate::guardian::BUNDLED_GUARDIAN_POLICY_TEMPLATE;
|
||||
use codex_features::Feature;
|
||||
@@ -173,6 +174,17 @@ fn check_legacy_model_safety(
|
||||
// catalog refresh. V1 uses the admitted config; V2 can use the live config.
|
||||
// An unchanged explicit reviewer override prevents both fallback paths.
|
||||
if destination.auto_review_model_override.is_none() {
|
||||
let destination_node_repl_policy =
|
||||
GuardianNodeReplPolicy::from_model_messages(destination.model_messages.as_ref());
|
||||
for model in retained_models {
|
||||
let policy = GuardianNodeReplPolicy::from_model_messages(model.model_messages.as_ref());
|
||||
if policy != destination_node_repl_policy {
|
||||
return Err(
|
||||
"the destination changes the Guardian parent-fallback node REPL policy"
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
for config in [admitted_config, live_config] {
|
||||
let destination_policy =
|
||||
config.resolve_guardian_policy(destination.model_messages.as_ref());
|
||||
|
||||
@@ -861,6 +861,7 @@ fn parent_review_messages(model: &mut ModelInfo) -> &mut AutoReviewMessages {
|
||||
.get_or_insert(AutoReviewMessages {
|
||||
policy: None,
|
||||
policy_template: None,
|
||||
node_repl_policy: None,
|
||||
rejection_instructions: None,
|
||||
timeout_instructions: None,
|
||||
})
|
||||
@@ -996,6 +997,11 @@ async fn parent_fallback_preserves_explicit_empty_and_bundled_defaults() {
|
||||
);
|
||||
parent_review_messages(&mut destination).policy = None;
|
||||
assert_eq!(check(&destination), Ok(()));
|
||||
parent_review_messages(&mut destination).node_repl_policy = Some(String::new());
|
||||
assert_eq!(
|
||||
check(&destination),
|
||||
Err("the destination changes the Guardian parent-fallback node REPL policy".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -1008,6 +1014,7 @@ async fn unchanged_explicit_reviewer_does_not_use_parent_policy() {
|
||||
parent_review_messages(&mut admitted).policy = Some("catalog policy A".to_string());
|
||||
parent_review_messages(&mut destination).policy = Some("catalog policy B".to_string());
|
||||
parent_review_messages(&mut destination).policy_template = Some(String::new());
|
||||
parent_review_messages(&mut destination).node_repl_policy = Some(String::new());
|
||||
assert_eq!(
|
||||
check_legacy_model_safety(
|
||||
&admitted,
|
||||
|
||||
@@ -411,6 +411,7 @@ async fn model_resolution_preserves_startup_overrides_and_instruction_provenance
|
||||
let auto_review = AutoReviewMessages {
|
||||
policy: Some("catalog review policy".to_string()),
|
||||
policy_template: Some("catalog review template".to_string()),
|
||||
node_repl_policy: None,
|
||||
rejection_instructions: None,
|
||||
timeout_instructions: None,
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user