From e0cae1bbc1ba7e013ef139171ef82350456deeb5 Mon Sep 17 00:00:00 2001 From: Iraklis Analitis Date: Mon, 21 Sep 2026 19:28:09 -0500 Subject: [PATCH] fix(session): persist debug, canary and improve-mode state on a blank session `Session::save()` returns early when a session has no visible message, no title and no parent, on the grounds that a freshly opened panel must not turn its hidden session-context message into a transcript on disk. That guard already carries exemptions for caller-set explicit state (`custom_title`, `title`, `parent_id", added by #1144), but `is_debug`, `is_canary` and `improve_mode` are explicit state by the same argument and were never added, so setting one and saving drops it silently: `save()` returns `Ok(())`, nothing is logged, and a later load-by-id fails with ENOENT. The issue names three e2e failures and one `jcode-tui` failure; the `improve_mode` clause is required for the fourth, which the issue's suggested fix (is_debug and canary only) would have left failing. Reproduced on macOS at origin/master `2a4edaa02` with the guard reverted: e2e session_flow: 3 failed (all "No such file or directory (os error 2)") test_clear_preserves_debug_for_resumed_debug_session test_debug_create_selfdev_session_marks_canary test_debug_create_session_marks_debug jcode-tui --lib: 1 failed (same error) test_improve_mode_persists_in_session_file With this change: cargo test --test e2e session_flow:: -- --test-threads=1 test result: ok. 6 passed; 0 failed cargo test -p jcode-tui --lib test_improve_mode_persists_in_session_file test result: ok. 1 passed; 0 failed Two intermediate measurements, so each clause is shown necessary rather than merely stated: with only the is_debug/is_canary clauses the three e2e tests pass and `test_improve_mode_persists_in_session_file` still fails with the identical ENOENT, which is why the improve_mode clause is here. Related: #1119, #1249, #1144. --- crates/jcode-base/src/session/persistence.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crates/jcode-base/src/session/persistence.rs b/crates/jcode-base/src/session/persistence.rs index 9d4d57198e..09dfa0cfbb 100644 --- a/crates/jcode-base/src/session/persistence.rs +++ b/crates/jcode-base/src/session/persistence.rs @@ -387,6 +387,16 @@ impl Session { // id find no file and silently treat the session as missing. // Parent linkage is also explicit state: an empty fork carries only a // hidden fork notice but must be loadable when its new client attaches. + // The debug and canary flags are explicit state by the same argument + // (#1339): `create_headless_session` sets them on a session that has no + // messages, title or parent yet, and `Agent::set_debug` saves + // immediately, so skipping the write here drops the flag silently - the + // save returns `Ok(())`, nothing is logged, and a later load-by-id fails + // with ENOENT. + // `improve_mode` is explicit state for the same reason and reaches the + // same failure: a caller that sets it and saves before the first visible + // message gets no file, so its own load-by-id fails + // (`test_improve_mode_persists_in_session_file`). if !self.persist_state.snapshot_exists && !self .messages @@ -396,6 +406,9 @@ impl Session { && self.custom_title.is_none() && self.title.is_none() && self.parent_id.is_none() + && self.improve_mode.is_none() + && !self.is_debug + && !self.is_canary { return Ok(()); }