Persist Guardian review failures for reports across restarts (#51651)

## 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
This commit is contained in:
jif
2026-10-07 11:18:05 +00:00
committed by copyberry
parent 37eaae6eeb
commit 30bdfec59d
17 changed files with 442 additions and 74 deletions
@@ -145,7 +145,8 @@ impl FeedbackRequestProcessor {
},
None => Vec::new(),
};
let failures = guardian_review_failures(&feedback_thread_ids);
let failures =
guardian_review_failures(state_db_ctx.as_deref(), &feedback_thread_ids).await;
let mut feedback_thread_ids = feedback_thread_ids;
if let Some(conversation_id) = conversation_id {
let index =
@@ -73,9 +73,9 @@ impl FeedbackThreadIndex {
process_discarded_review_records: failures.process_discarded_records,
notes: "Selection only, not an upload receipt. Null filenames mean no path was available. \
Omitted threads exceeded the rollout thread limit; their retained reviews are \
still in auto-review-failures.jsonl. Review evidence is process-local and bounded; \
missing evidence does not imply no denial. The discarded-record count is \
process-wide, not specific to this tree, and resets on restart.",
still in auto-review-failures.jsonl. Review evidence is persisted and bounded; \
missing evidence does not imply no denial. The discarded-record count covers \
only the process-wide in-memory fallback and resets on restart.",
}
}