Files
codex/codex-rs/app-server/tests/suite/v2/guardian_stateful_async_tests.rs
T
felixxia-oai 4b1cf9a4c9 Use conversations for all Guardian v2 async classification (#56556)
## What changed

- Always use the retained conversation backend for asynchronous classification; keep snapshot sampling test-only.
- Accept legacy `async_classifier_mode` values in configuration and model metadata but ignore them. Emit a startup warning when `[features.guardianv2].async_classifier_mode` is configured.
- Ignore legacy classifier mode differences when checking model-switch compatibility, and fail closed if the conversation backend is missing.

## Testing

Update coverage for legacy configuration warnings, model-switch compatibility, retained approval-review context, and conversation-based scoring.

GitOrigin-RevId: 5e8bb7e4e6e7d1589572f38bfe2498c9fa6825a0
2026-10-23 18:48:10 +00:00

37 lines
2.1 KiB
Rust

use super::*;
use codex_protocol::openai_models::AsyncClassifierMode;
use test_case::test_case;
#[test_case(GuardianRisk::Low, ThreadLifecycle::New, ModelReviewRequirement::Optional; "low")]
#[test_case(GuardianRisk::Low, ThreadLifecycle::ReviewContinuations, ModelReviewRequirement::Optional; "retained_sync_review_delivered_once")]
#[test_case(GuardianRisk::High, ThreadLifecycle::ReviewContinuations, ModelReviewRequirement::Optional; "new_sync_review_appended")]
#[test_case(GuardianRisk::LowWithStreamFailure, ThreadLifecycle::ReviewContinuations, ModelReviewRequirement::Optional; "sync_review_restored_after_failed_stream")]
#[test_case(GuardianRisk::Low, ThreadLifecycle::RootUserRestriction, ModelReviewRequirement::Optional; "new_user_instruction_resets_conversation")]
#[test_case(GuardianRisk::LowWithStreamFailure, ThreadLifecycle::New, ModelReviewRequirement::Optional; "failure_after_early_score")]
#[test_case(GuardianRisk::Low, ThreadLifecycle::RootRestrictionDuringClassification, ModelReviewRequirement::Optional; "authorization_changed_during_classification")]
#[test_case(GuardianRisk::High, ThreadLifecycle::New, ModelReviewRequirement::Optional; "high")]
#[test_case(GuardianRisk::InvalidResponse, ThreadLifecycle::New, ModelReviewRequirement::Optional; "failed")]
#[test_case(GuardianRisk::Low, ThreadLifecycle::Resume, ModelReviewRequirement::Optional; "resume")]
#[test_case(GuardianRisk::Low, ThreadLifecycle::Fork, ModelReviewRequirement::Optional; "fork")]
#[test_case(GuardianRisk::Low, ThreadLifecycle::New, ModelReviewRequirement::Required; "mandatory_review")]
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn conversation_classifier_preserves_approval_matrix(
risk: GuardianRisk,
lifecycle: ThreadLifecycle,
requirement: ModelReviewRequirement,
) -> Result<()> {
skip_if_no_network!(Ok(()));
guardian_v2_routes_scoped_tool_approvals(
risk,
lifecycle,
requirement,
ReviewOutcome::Allow,
TranscriptContent::Normal,
GuardianToolScope::AllTools,
/*sensitive_action*/ None,
AsyncClassifierMode::Conversation,
)
.await?;
Ok(())
}