mirror of
https://github.com/openai/codex.git
synced 2026-10-19 16:17:49 +00:00
## Why Failed Guardian review evidence was process-local, so restarting Codex lost the context needed for later diagnostic reports. ## What changed - Persist failed-review records in SQLite before reviewer cleanup, retaining at most 64 records globally, eight per thread, and 8 MiB of evidence. Delete persisted evidence when its reviewed thread is deleted. - Recover and deduplicate persisted and in-memory records for the reported task tree when uploading `auto-review-failures.jsonl`. - Bound persistence attempts to 250 ms and retain an in-memory fallback when storage is unavailable. Keep capture gated by user opt-in and non-ephemeral sessions, and export evidence only when logs are included. ## Testing Add coverage for persistence across reopen and process restart, retention limits, cascading deletion, busy-storage fallback, and report uploads with and without logs, including SQLite log failures. GitOrigin-RevId: ea2da1818d4a5da3da29f211042ca45e834342bc
63 lines
2.0 KiB
Rust
63 lines
2.0 KiB
Rust
use super::*;
|
|
use pretty_assertions::assert_eq;
|
|
use serde_json::json;
|
|
|
|
#[test]
|
|
fn capture_honors_privacy_and_keeps_oversized_context_action_and_decision() -> anyhow::Result<()> {
|
|
let thread_id = ThreadId::new();
|
|
let reviewer_thread_id = ThreadId::new();
|
|
let decision = r#"{"outcome":"deny","rationale":"Missing approval."}"#;
|
|
let action = r#"{"command":"git push"}"#;
|
|
let outcome = GuardianReviewSessionOutcome::Completed(Ok(Some(decision.to_owned())));
|
|
for settings in [
|
|
ReviewFeedbackSettings {
|
|
enabled: false,
|
|
ephemeral: false,
|
|
},
|
|
ReviewFeedbackSettings {
|
|
enabled: true,
|
|
ephemeral: true,
|
|
},
|
|
] {
|
|
assert!(FailedReviewFeedback::for_outcome(&outcome, settings).is_none());
|
|
}
|
|
let feedback = FailedReviewFeedback::for_outcome(
|
|
&outcome,
|
|
ReviewFeedbackSettings {
|
|
enabled: true,
|
|
ephemeral: false,
|
|
},
|
|
)
|
|
.expect("denials retain feedback");
|
|
let record = feedback.into_record(ReviewFeedbackContext {
|
|
reviewed_thread_id: thread_id,
|
|
reviewed_turn_id: "parent-turn",
|
|
target_item_id: Some("push-call"),
|
|
reviewer_thread_id,
|
|
model: "review-model",
|
|
action,
|
|
action_truncated: false,
|
|
instructions: Some(&"x".repeat(MAX_RECORD_BYTES)),
|
|
history: Vec::new(),
|
|
});
|
|
let contents = record.expect("failed-review record").record;
|
|
assert_eq!(
|
|
serde_json::from_slice::<serde_json::Value>(&contents)?,
|
|
json!({
|
|
"reviewed_thread_id": thread_id,
|
|
"reviewed_turn_id": "parent-turn",
|
|
"target_item_id": "push-call",
|
|
"reviewer_thread_id": reviewer_thread_id,
|
|
"model": "review-model",
|
|
"status": "denied",
|
|
"decision": decision,
|
|
"action": action,
|
|
"action_truncated": false,
|
|
"instructions": null,
|
|
"history": [],
|
|
"context_omitted": true,
|
|
})
|
|
);
|
|
Ok(())
|
|
}
|