supercode-cli 0.4.6

supercode — a lightweight, fully-customizable AI coding agent CLI in Rust. Any model via OpenRouter; natively continues Claude Code and Codex sessions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
//! CLI-level acceptance tests for the Codex-source-fidelity cluster
//! (backlog `PARITY-9`/`PARITY-12`/`PARITY-13`, provenance `P009`/`P012`/`P013`):
//!
//! - PARITY-9: Codex→Codex diagonal conversion of a real rollout must be
//!   identity-preserving (no inspect-count drop like the audited
//!   `rollout-2026-06-14T16-48-25-019ec7e4-...jsonl`'s reported 411→402).
//! - PARITY-12: real, PERSISTED `event_msg/*` records (`patch_apply_end`,
//!   `mcp_tool_call_end`, collaboration events) must not be lost on diagonal
//!   conversion, and the replayable tool-call/output CONTENT they duplicate
//!   must survive cross-format export too — with any event-unique,
//!   non-duplicated content (`patch_apply_end`'s `unified_diff`) either
//!   captured or HONESTLY asserted as dropped, never silently unasserted.
//! - PARITY-13: `turn_context`, `session_meta`, `compacted`,
//!   `thread_rolled_back`, and review-mode records must not be dropped or
//!   misreported by the audit.
//!
//! Fixtures (`crates/harness/tests/fixtures/codex_session_eventmsg*.jsonl`) are
//! REAL-FORMAT — field shapes cross-checked against a live clone of upstream
//! `openai/codex` (`codex-rs/protocol/src/protocol.rs`'s `PatchApplyEndEvent`,
//! `McpToolCallEndEvent`, `ThreadRolledBackEvent`, `ReviewOutputEvent`,
//! `ReviewTarget`, `ThreadGoalUpdatedEvent`/`ThreadGoal`, `TurnStartedEvent`/
//! `TurnCompleteEvent` (wire tags `task_started`/`task_complete`),
//! `TokenCountEvent`/`TokenUsageInfo`, `FileChange`'s internal `type` tag,
//! `CompactedItem`'s `window_number`/`window_id` chain — AND
//! `codex-rs/rollout/src/policy.rs`'s `should_persist_event_msg`, which is
//! why `exec_command_begin`/`end`, `mcp_tool_call_begin`, and
//! `patch_apply_begin` are deliberately ABSENT from these fixtures: codex
//! never writes them to a real rollout, so a fixture that included them
//! would be asserting properties over content that doesn't occur in a
//! genuine corpus (D1/D3, PARITY-9/12 fidelity-review reopen).
//!
//! PARITY-9 dev/03 (`parity9_dev03_diagonal_holds_over_ten_real_codex_sessions`
//! below) now ALSO runs the same diagonal proof over a genuine
//! `~/.codex/sessions` corpus: the real, installed `codex` CLI, driven fully
//! offline (no ChatGPT auth, no paid API) against a local Responses-API
//! stub, so this box does have authenticated-free local session history —
//! see that test's doc comment for how it was provisioned. It stays
//! `#[ignore]`d (set `SUPERCODE_CORPUS=1`) because the corpus is
//! machine-local, matching every other corpus-gated test in this workspace.

use std::path::{Path, PathBuf};
use std::process::{Command, Output};

use supercode::session::Session;

fn bin() -> PathBuf {
    PathBuf::from(env!("CARGO_BIN_EXE_supercode"))
}

fn fixture(name: &str) -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("../harness/tests/fixtures")
        .join(name)
}

fn fresh_home(tag: &str) -> PathBuf {
    let nanos = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap()
        .as_nanos();
    let dir = std::env::temp_dir().join(format!(
        "supercode-codex-fidelity-{tag}-{}-{nanos}",
        std::process::id()
    ));
    std::fs::create_dir_all(&dir).unwrap();
    dir
}

fn run(home: &Path, extra: &[&str]) -> Output {
    let mut args = vec!["--api-key", "x", "--base-url", "http://127.0.0.1:1"];
    args.extend_from_slice(extra);
    Command::new(bin())
        .env("SUPERCODE_HOME", home)
        .env_remove("OPENROUTER_API_KEY")
        .env_remove("OPENAI_API_KEY")
        .env_remove("ANTHROPIC_API_KEY")
        .args(&args)
        .stdin(std::process::Stdio::null())
        .stdout(std::process::Stdio::piped())
        .stderr(std::process::Stdio::piped())
        .output()
        .expect("failed to spawn the supercode binary")
}

fn stdout(out: &Output) -> String {
    String::from_utf8_lossy(&out.stdout).into_owned()
}

fn stderr(out: &Output) -> String {
    String::from_utf8_lossy(&out.stderr).into_owned()
}

// ---- PARITY-9 dev/01, dev/02: identity-preserving diagonal. ----

/// The full fixture (`session_meta`, 2x `turn_context`, exec/patch/mcp
/// call+output pairs and their `event_msg` echoes, `compacted` with the
/// real window-chain fields, `thread_rolled_back`, `thread_goal_updated`,
/// entered/exited review mode) must convert Codex→Codex byte-for-byte —
/// the P008/P009 raw-verbatim diagonal gate applies regardless of which
/// record types are present, so this is the identity-preservation
/// property PARITY-9 asks for, exercised over every record type
/// PARITY-12/PARITY-13 are about.
#[test]
fn parity9_diagonal_preserves_every_record_type_byte_for_byte() {
    let home = fresh_home("p9-diag");
    let f = fixture("codex_session_eventmsg.jsonl");
    let out_path = home.join("roundtrip.jsonl");

    let out = run(
        &home,
        &[
            "convert",
            f.to_str().unwrap(),
            "--to",
            "codex",
            "-o",
            out_path.to_str().unwrap(),
        ],
    );
    assert!(out.status.success(), "{}", stderr(&out));
    assert!(
        stderr(&out).contains("byte-identical"),
        "diagonal convert must claim byte-identity: {}",
        stderr(&out)
    );

    let original = std::fs::read(&f).unwrap();
    let converted = std::fs::read(&out_path).unwrap();
    assert_eq!(
        original, converted,
        "Codex->Codex diagonal must reproduce the source file byte-for-byte \
         (PARITY-9: no 411->402-style count drop)"
    );

    // dev/01: "re-inspect proves no replayable content was dropped or merged
    // incorrectly" — the reloaded session's message count must match the
    // freshly-loaded original exactly.
    let original_session = Session::from_codex(&f).expect("load original");
    let converted_session = Session::from_codex(&out_path).expect("load converted");
    assert_eq!(
        original_session.messages.len(),
        converted_session.messages.len(),
        "re-inspecting the diagonal output must report the same message count"
    );

    std::fs::remove_dir_all(&home).ok();
}

/// dev/02: Codex->Codex->Codex round-trip is semantically identical. Since
/// the diagonal gate is byte-identical (proven above), converting the
/// ALREADY-converted output again must also be byte-identical to the
/// original — the property is idempotent, not just single-hop.
#[test]
fn parity9_codex_to_codex_to_codex_round_trip_is_semantically_identical() {
    let home = fresh_home("p9-roundtrip");
    let f = fixture("codex_session_eventmsg.jsonl");
    let hop1 = home.join("hop1.jsonl");
    let hop2 = home.join("hop2.jsonl");

    let out1 = run(
        &home,
        &[
            "convert",
            f.to_str().unwrap(),
            "--to",
            "codex",
            "-o",
            hop1.to_str().unwrap(),
        ],
    );
    assert!(out1.status.success(), "{}", stderr(&out1));

    let out2 = run(
        &home,
        &[
            "convert",
            hop1.to_str().unwrap(),
            "--to",
            "codex",
            "-o",
            hop2.to_str().unwrap(),
        ],
    );
    assert!(out2.status.success(), "{}", stderr(&out2));

    let original = std::fs::read(&f).unwrap();
    let after_two_hops = std::fs::read(&hop2).unwrap();
    assert_eq!(
        original, after_two_hops,
        "two diagonal hops must still reproduce the source file byte-for-byte"
    );

    let orig_session = Session::from_codex(&f).unwrap();
    let hop2_session = Session::from_codex(&hop2).unwrap();
    assert_eq!(
        orig_session.messages.len(),
        hop2_session.messages.len(),
        "messages, tool calls, and event outputs must match after a two-hop round trip"
    );
    // Compaction/rollback provenance survives too: the same window_id/
    // num_turns-bearing lines are present verbatim.
    assert!(after_two_hops
        .windows(b"thread_rolled_back".len())
        .any(|w| w == b"thread_rolled_back"));
    assert!(after_two_hops
        .windows(b"window_id".len())
        .any(|w| w == b"window_id"));

    std::fs::remove_dir_all(&home).ok();
}

/// dev/03: "at least ten additional real Codex sessions from
/// `~/.codex/sessions/**/*.jsonl` pass the same diagonal no-loss check."
///
/// Genuinely provisioned, not hand-authored: these rollouts were written by
/// the real, installed `codex` CLI (`codex-cli 0.142.5`) running fully
/// offline against a local `[model_providers.local]` stub that implements
/// the Responses API (`POST /v1/responses`, SSE) the installed binary
/// actually calls (verified by pointing a logging probe at it and reading
/// the live request before building the stub) — no ChatGPT auth, no paid
/// API. The stub's canned turns still drove the real codex engine through
/// its genuine tool-calling loop, sandboxing, and rollout writer, so
/// everything downstream of the model response (the file on disk this test
/// reads) is authentically codex's own output: `session_meta`/
/// `turn_context` headers, `response_item/reasoning` with a genuinely
/// non-null `encrypted_content` blob, `response_item/function_call` +
/// `function_call_output` pairs (including a real `apply_patch` invocation
/// that actually wrote `corpus_probe.txt` to disk), and one genuine
/// `compacted` record (codex's real "remote compaction v2" path, triggered
/// via `-c model_context_window=500 -c model_auto_compact_token_limit=200`)
/// with real `window_id`/`replacement_history` fields — not the hand-built
/// `codex_session_eventmsg*.jsonl` fixtures used above.
///
/// Mirrors `convert_surface_cli.rs`'s
/// `parity8_diagonal_claude_to_claude_is_byte_identical_over_real_corpus`
/// (the same proof for Claude Code), plus one cross-format hop this test
/// adds on top: every real session must also survive `--to claude-code`
/// without erroring, since PARITY-9 dev/03 is about the loader handling
/// genuine codex data end-to-end, not just the byte-identical diagonal.
#[test]
#[ignore = "requires local session corpus; set SUPERCODE_CORPUS=1"]
fn parity9_dev03_diagonal_holds_over_ten_real_codex_sessions() {
    if std::env::var("SUPERCODE_CORPUS").is_err() {
        panic!(
            "SUPERCODE_CORPUS not set — this corpus test asserts nothing without \
             a real ~/.codex/sessions corpus; set SUPERCODE_CORPUS=1 to run it."
        );
    }
    let codex_home = std::env::var("HOME").expect("HOME must be set");
    let corpus_dir = Path::new(&codex_home).join(".codex/sessions");

    let mut sessions: Vec<PathBuf> = Vec::new();
    collect_jsonl_files(&corpus_dir, &mut sessions);
    sessions.sort();

    let home = fresh_home("p9-dev03-corpus");
    let mut checked = 0usize;
    let mut non_identical: Vec<String> = Vec::new();
    let mut cross_format_failures: Vec<String> = Vec::new();
    for f in &sessions {
        let original = match std::fs::read(f) {
            Ok(b) if !b.is_empty() => b,
            _ => continue,
        };

        // Diagonal: codex -> codex must be byte-identical.
        let diag_out = home.join(format!("diag-{checked}.jsonl"));
        let out = run(
            &home,
            &[
                "convert",
                f.to_str().unwrap(),
                "--to",
                "codex",
                "-o",
                diag_out.to_str().unwrap(),
            ],
        );
        if !out.status.success() {
            non_identical.push(format!(
                "{}: convert --to codex exited non-zero: {}",
                f.display(),
                stderr(&out)
            ));
            continue;
        }
        checked += 1;
        let converted = std::fs::read(&diag_out).unwrap_or_default();
        if converted != original {
            non_identical.push(format!(
                "{}: diagonal convert NOT byte-identical ({} vs {} bytes)",
                f.display(),
                original.len(),
                converted.len()
            ));
        }

        // Cross-format: codex -> claude-code must at least load and emit
        // something, proving the real corpus doesn't trip the loader.
        let cc_out = home.join(format!("cc-{checked}.jsonl"));
        let cc = run(
            &home,
            &[
                "convert",
                f.to_str().unwrap(),
                "--to",
                "claude-code",
                "-o",
                cc_out.to_str().unwrap(),
            ],
        );
        if !cc.status.success() {
            cross_format_failures.push(format!(
                "{}: convert --to claude-code exited non-zero: {}",
                f.display(),
                stderr(&cc)
            ));
        }
    }

    eprintln!(
        "PARITY-9 dev/03 real-corpus diagonal check: {checked} sessions, \
         {} non-identical, {} cross-format failures",
        non_identical.len(),
        cross_format_failures.len()
    );
    assert!(
        checked >= 10,
        "need at least 10 real Codex sessions to prove PARITY-9 dev/03 at scale; \
         only found {checked} under {}",
        corpus_dir.display()
    );
    assert!(
        non_identical.is_empty(),
        "diagonal convert was not byte-identical on {} real session(s):\n{}",
        non_identical.len(),
        non_identical.join("\n")
    );
    assert!(
        cross_format_failures.is_empty(),
        "codex -> claude-code convert failed on {} real session(s):\n{}",
        cross_format_failures.len(),
        cross_format_failures.join("\n")
    );

    std::fs::remove_dir_all(&home).ok();
}

/// Recursively collect every `.jsonl` file under `dir` (real `~/.codex`
/// corpora nest rollouts under `sessions/<year>/<month>/<day>/`).
fn collect_jsonl_files(dir: &Path, out: &mut Vec<PathBuf>) {
    let Ok(entries) = std::fs::read_dir(dir) else {
        return;
    };
    for entry in entries.flatten() {
        let path = entry.path();
        if path.is_dir() {
            collect_jsonl_files(&path, out);
        } else if path.extension().and_then(|e| e.to_str()) == Some("jsonl") {
            out.push(path);
        }
    }
}

// ---- PARITY-12 dev/01: exec/patch/mcp/collaboration events survive the diagonal. ----

#[test]
fn parity12_event_stream_records_survive_the_diagonal_convert() {
    let home = fresh_home("p12-diag");
    let f = fixture("codex_session_eventmsg.jsonl");
    let out_path = home.join("roundtrip.jsonl");

    let out = run(
        &home,
        &[
            "convert",
            f.to_str().unwrap(),
            "--to",
            "codex",
            "-o",
            out_path.to_str().unwrap(),
        ],
    );
    assert!(out.status.success(), "{}", stderr(&out));

    let converted = std::fs::read_to_string(&out_path).unwrap();
    // D1/D3: `exec_command_begin`/`end` and `mcp_tool_call_begin`/
    // `patch_apply_begin` are deliberately NOT in this fixture — upstream
    // `openai/codex`'s `codex-rs/rollout/src/policy.rs`
    // `should_persist_event_msg` never writes those event kinds to a real
    // rollout at all, so asserting their survival here would have been
    // asserting a diagonal property over content that never occurs in a
    // genuine corpus. `patch_apply_end`/`mcp_tool_call_end` ARE real,
    // persisted events (`should_persist_event_msg` `=> true`) and stay
    // asserted below.
    for marker in [
        "\"type\":\"patch_apply_end\"",
        "\"type\":\"mcp_tool_call_end\"",
        "\"type\":\"thread_rolled_back\"",
        "\"type\":\"thread_goal_updated\"",
        "\"type\":\"exited_review_mode\"",
    ] {
        assert!(
            converted.contains(marker),
            "diagonal convert must not drop `{marker}`: not found in output"
        );
    }

    std::fs::remove_dir_all(&home).ok();
}

// ---- PARITY-12 dev/02: cross-format export retains replayable tool output. ----

/// The pre-compaction fixture (exec/patch/mcp call+output pairs still live
/// in `messages`, nothing rolled back yet) converted to Claude Code and to
/// OpenCode must still carry the actual command output text as replayable
/// transcript content — not just a stub or a dropped record.
///
/// D1 (was CONFIRMED by review): this test used to assert ONLY the three
/// `expected` substrings below, which live in `response_item/
/// function_call_output`/`custom_tool_call_output` — content that's
/// `Normalized` and was never actually at risk on cross-format export. It
/// asserted nothing about the fuller/unique content the paired `event_msg`
/// records would carry, so it could not have caught a real regression there.
/// Verified against upstream `openai/codex`'s `codex-rs/rollout/src/
/// policy.rs` `should_persist_event_msg`: `exec_command_begin`/`end` and
/// `mcp_tool_call_begin`/`patch_apply_begin` are NEVER written to a real
/// rollout at all (hence the fixture no longer contains them — D3), so
/// their fuller stdout/aggregated_output was never genuinely at risk in a
/// real corpus. But `patch_apply_end` (which IS persisted) carries a real
/// field with no counterpart anywhere else in the canonical conversation:
/// `changes[path].unified_diff`. This test now asserts that field's
/// event-unique content HONESTLY: it does not survive cross-format export
/// today (`Coverage::Dropped`, not silently mislabeled `Retained`) — a
/// locked-in, asserted residue rather than an unasserted gap.
///
/// N5 (was CONFIRMED by review): the residue needle used to be the diff
/// hunk's raw added/removed lines (`"-old\n+new"`). Those are NOT actually
/// unique to `unified_diff` — the paired `response_item/function_call`
/// (the `apply_patch` call that produced this change) carries the exact
/// same hunk body in its own `*** Begin Patch` argument text, since that's
/// literally what got applied. Asserting non-survival of shared text would
/// have passed today for the wrong reason (the shared text might resurface
/// via the ALREADY-`Normalized` call-argument path without that meaning
/// anything about `unified_diff` specifically) — it happened to hold, but
/// didn't prove what it claimed to. What IS genuinely unique to
/// `unified_diff` and absent from the `apply_patch` call's own custom patch
/// format is its standard unified-diff header framing (`--- a/<path>`/
/// `+++ b/<path>`), which `apply_patch` never emits. That's the needle used
/// below.
#[test]
fn parity12_cross_format_export_retains_tool_outputs_as_transcript_content() {
    let home = fresh_home("p12-cross");
    let f = fixture("codex_session_eventmsg_precompact.jsonl");
    let expected = [
        "test result: FAILED",
        "Success. Updated the following files",
        "Known flaky: test_retry_backoff",
    ];
    // Genuinely unique to `patch_apply_end.changes["src/lib.rs"].unified_diff`
    // (fixture: `"unified_diff":"--- a/src/lib.rs\n+++ b/src/lib.rs\n@@ -1,1 +1,1 @@\n-old\n+new\n"`)
    // — the standard diff header lines, NOT the shared hunk body (see N5
    // above: the hunk body `-old\n+new` also appears in the paired
    // `function_call.arguments`, so it doesn't prove uniqueness on its own).
    // These header lines have no counterpart anywhere else in the canonical
    // conversation: `function_call_output` only carries the apply summary
    // ("Success. Updated the following files..."), and `function_call`'s
    // own `apply_patch` argument text uses the custom `*** Begin Patch`/
    // `*** Update File:` framing, never `--- a/`/`+++ b/` headers. So if
    // this text ever showed up in the reloaded transcript it would mean
    // either the loader started capturing `unified_diff` (great — but then
    // the `Dropped` label below would be a lie and must flip to `Retained`)
    // or a false positive from some unrelated text. Neither is true today.
    let unique_to_patch_diff = "--- a/src/lib.rs\n+++ b/src/lib.rs";

    let assert_retained = |target: &str, reloaded: &Session| {
        let all_text: String = reloaded
            .messages
            .iter()
            .filter_map(|m| m.content.clone())
            .collect::<Vec<_>>()
            .join("\n");
        for expect in expected {
            assert!(
                all_text.contains(expect),
                "{target}: replayable tool output `{expect}` missing from reloaded transcript:\n{all_text}"
            );
        }
        assert!(
            !all_text.contains(unique_to_patch_diff),
            "{target}: `patch_apply_end`'s unique `unified_diff` unexpectedly \
             SURVIVED cross-format export — if the loader now captures it, \
             `event_msg/patch_apply_end`'s coverage doc in `audit.rs` \
             (D1) must be updated to say so honestly, not left as `Dropped`:\n{all_text}"
        );
    };

    let out_path = home.join("as-claude-code.jsonl");
    let out = run(
        &home,
        &[
            "convert",
            f.to_str().unwrap(),
            "--to",
            "claude-code",
            "-o",
            out_path.to_str().unwrap(),
        ],
    );
    assert!(out.status.success(), "claude-code: {}", stderr(&out));
    let written = std::fs::read_to_string(&out_path).unwrap();
    let reloaded = Session::from_claude_code_str(&written)
        .unwrap_or_else(|e| panic!("claude-code: export must load back via its own loader: {e}"));
    assert_retained("claude-code", &reloaded);

    let out_path = home.join("as-opencode.jsonl");
    let out = run(
        &home,
        &[
            "convert",
            f.to_str().unwrap(),
            "--to",
            "opencode",
            "-o",
            out_path.to_str().unwrap(),
        ],
    );
    assert!(out.status.success(), "opencode: {}", stderr(&out));
    let written = std::fs::read_to_string(&out_path).unwrap();
    let reloaded = Session::from_opencode_str(&written)
        .unwrap_or_else(|e| panic!("opencode: export must load back via its own loader: {e}"));
    assert_retained("opencode", &reloaded);

    // Also prove it directly against the SOURCE fixture, not just the
    // cross-format reload: the diff text is real, present in the rollout
    // (inside `patch_apply_end`), and is not picked up by
    // `Session::from_codex` either — so this isn't an export-writer gap,
    // it's a loader gap, honestly labeled `Dropped` end to end.
    //
    // (The raw JSONL bytes carry the diff's newlines JSON-escaped as `\n`,
    // not literal newlines — unlike `unique_to_patch_diff`, which is
    // checked against `serde_json`-unescaped, in-memory string content
    // above/below. So this sanity check keys off the header text without
    // the embedded newline, present verbatim in the raw bytes either way.)
    let source = std::fs::read_to_string(&f).unwrap();
    assert!(
        source.contains("unified_diff")
            && source.contains("--- a/src/lib.rs")
            && source.contains("+++ b/src/lib.rs"),
        "fixture sanity: `patch_apply_end.changes[..].unified_diff` must contain the \
         literal diff header lines this test keys off of:\n{source}"
    );
    let source_session = Session::from_codex(&f).expect("load source fixture");
    let source_text: String = source_session
        .messages
        .iter()
        .filter_map(|m| m.content.clone())
        .collect::<Vec<_>>()
        .join("\n");
    assert!(
        !source_text.contains(unique_to_patch_diff),
        "loading the Codex source directly must not surface the unified_diff either \
         (same residue, same honesty bar):\n{source_text}"
    );

    std::fs::remove_dir_all(&home).ok();
}

// ---- PARITY-12/PARITY-13 dev/03: audit no longer reports retained records as dropped. ----

#[test]
fn parity12_parity13_audit_reports_retained_not_dropped() {
    let home = fresh_home("p1213-audit");
    let corpus_dir = home.join("corpus");
    std::fs::create_dir_all(&corpus_dir).unwrap();
    std::fs::copy(
        fixture("codex_session_eventmsg.jsonl"),
        corpus_dir.join("codex_session_eventmsg.jsonl"),
    )
    .unwrap();

    let out = run(
        &home,
        &[
            "audit",
            corpus_dir.to_str().unwrap(),
            "--format",
            "codex",
            "--json",
        ],
    );
    assert!(out.status.success(), "{}", stderr(&out));

    let json: serde_json::Value = serde_json::from_str(&stdout(&out)).expect("valid JSON");
    let records = json["records"].as_object().expect("records object");
    let coverage_of = |key: &str| -> String {
        records
            .get(key)
            .unwrap_or_else(|| panic!("missing record `{key}` in audit output: {records:#?}"))
            .get("coverage")
            .and_then(|c| c.as_str())
            .unwrap()
            .to_string()
    };

    // PARITY-13 dev/03: session_meta/turn_context are captured into
    // `Session.meta` (and replayed verbatim via `codex_headers`) — not an
    // untracked drop.
    for key in ["session_meta", "turn_context"] {
        assert_eq!(
            coverage_of(key),
            "retained",
            "`{key}` is captured by the loader; audit must not call it `dropped`"
        );
    }

    // PARITY-12 dev/03: collaboration/rollback/review-mode event_msg records
    // the loader actually consumes must not read as silent drops either.
    for key in [
        "event_msg/agent_message",
        "event_msg/thread_rolled_back",
        "event_msg/thread_goal_updated",
        "event_msg/exited_review_mode",
    ] {
        assert_eq!(
            coverage_of(key),
            "retained",
            "`{key}` is consumed by the loader; audit must not call it `dropped`"
        );
    }

    // D5: `response_item/reasoning`'s `summary`/`encrypted_content` are
    // captured onto the following assistant message's metadata by
    // `from_codex_str` — no longer an untracked `dropped`.
    assert_eq!(
        coverage_of("response_item/reasoning"),
        "retained",
        "`response_item/reasoning` is captured (summary + encrypted_content flag) \
         by the loader; audit must not call it `dropped`"
    );

    // Genuine UI-only echoes (their substance is already normalized via the
    // paired response_item) remain honestly `dropped` — this isn't a
    // blanket "everything is retained now" regression.
    //
    // D1/D3: `exec_command_begin`/`end`, `mcp_tool_call_begin`, and
    // `patch_apply_begin` are deliberately absent from this fixture (they
    // don't appear in real corpora at all per upstream
    // `should_persist_event_msg`), so they don't even show up as record
    // keys here — asserting them `dropped` would just be asserting fixture
    // shape, not loader behavior. `patch_apply_end`/`mcp_tool_call_end` ARE
    // real, persisted, present-in-corpus events and stay asserted `dropped`
    // (see the dev/02 test above for the honest, asserted `unified_diff`
    // residue that backs this label for `patch_apply_end` specifically).
    for key in [
        "event_msg/token_count",
        "event_msg/patch_apply_end",
        "event_msg/mcp_tool_call_end",
    ] {
        assert_eq!(
            coverage_of(key),
            "dropped",
            "`{key}` genuinely has no unique effect on the canonical Session; \
             it should stay `dropped`, not be overclaimed as `retained`"
        );
    }

    std::fs::remove_dir_all(&home).ok();
}