Align SQLite feedback logs with feedback formatter (#13494)

## Summary
- store a pre-rendered `feedback_log_body` in SQLite so `/feedback`
exports keep span prefixes and structured event fields
- render SQLite feedback exports with timestamps and level prefixes to
match the old in-memory feedback formatter, while preserving existing
trailing newlines
- count `feedback_log_body` in the SQLite retention budget so structured
or span-prefixed rows still prune correctly
- bound `/feedback` row loading in SQL with the retention estimate, then
apply exact whole-line truncation in Rust so uploads stay capped without
splitting lines

## Details
- add a `feedback_log_body` column to `logs` and backfill it from
`message` for existing rows
- capture span names plus formatted span and event fields at write time,
since SQLite does not retain enough structure to reconstruct the old
formatter later
- keep SQLite feedback queries scoped to the requested thread plus
same-process threadless rows
- restore a SQL-side cumulative `estimated_bytes` cap for feedback
export queries so over-retained partitions do not load every matching
row before truncation
- add focused formatting coverage for exported feedback lines and parity
coverage against `tracing_subscriber`

## Testing
- cargo test -p codex-state
- just fix -p codex-state
- just fmt

codex author: `codex resume 019ca1b0-0ecc-78b1-85eb-6befdd7e4f1f`

---------

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Charley Cunningham
2026-03-18 15:44:31 -07:00
committed by GitHub
parent 7b37a0350f
commit ebbbc52ce4
7 changed files with 386 additions and 90 deletions

View File

@@ -46,7 +46,7 @@ struct Args {
#[arg(long = "thread-id")]
thread_id: Vec<String>,
/// Substring match against the log message.
/// Substring match against the rendered log body.
#[arg(long)]
search: Option<String>,
@@ -62,7 +62,7 @@ struct Args {
#[arg(long, default_value_t = 500)]
poll_ms: u64,
/// Show compact output with only time, level, and message.
/// Show compact output with only time, level, and rendered log body.
#[arg(long)]
compact: bool,
}
@@ -295,7 +295,7 @@ fn heuristic_formatting(message: &str) -> String {
mod matcher {
pub(super) fn apply_patch(message: &str) -> bool {
message.starts_with("ToolCall: apply_patch")
message.contains("ToolCall: apply_patch")
}
}