From 41034bb3f35348f09b24bd4b134652a3ee97501a Mon Sep 17 00:00:00 2001 From: TheArchitectit Date: Wed, 3 Jun 2026 13:44:20 -0500 Subject: [PATCH] fix: address CI test failure and add empty-session error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix latest_session_alias_resolves_most_recent_managed_session test: the test created sessions with 0 messages, which are now filtered out by the message_count > 0 check in latest_session_excluding(). Updated the test to call push_user_text() before saving so sessions have at least one message and are findable by /resume latest. - Add distinct error message when all sessions are empty (0 messages). Previously, the same "no managed sessions found" message was returned whether there were zero sessions or all sessions had 0 messages. Now: - No sessions at all → "no managed sessions found in {path}. Start claw to create a session..." - Sessions exist but all empty → "all sessions are empty (0 messages) in {path}. This usually means a fresh claw session is running but no messages have been sent yet. Wait for a response in your other session, then try --resume latest again." - Add test for the all-sessions-empty error path. Addresses reviewer feedback on #3216. --- rust/crates/runtime/src/session_control.rs | 54 ++++++++++++++++++++++ rust/crates/rusty-claude-cli/src/main.rs | 26 +++++++---- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/rust/crates/runtime/src/session_control.rs b/rust/crates/runtime/src/session_control.rs index 896ad915..b00dfce1 100644 --- a/rust/crates/runtime/src/session_control.rs +++ b/rust/crates/runtime/src/session_control.rs @@ -199,6 +199,21 @@ impl SessionStore { { return Ok(latest); } + // Distinguish between "no sessions at all" and "sessions exist but + // all are empty" so the user gets a clear signal about what to do. + let has_any_session = self + .list_sessions()? + .iter() + .any(|s| s.id != exclude) + || self + .scan_global_sessions()? + .iter() + .any(|s| s.id != exclude); + if has_any_session { + return Err(SessionControlError::Format( + format_all_sessions_empty(&self.sessions_root), + )); + } Err(SessionControlError::Format(format_no_managed_sessions( &self.sessions_root, ))) @@ -774,6 +789,16 @@ fn format_no_managed_sessions(sessions_root: &Path) -> String { ) } +fn format_all_sessions_empty(sessions_root: &Path) -> String { + let fingerprint_dir = sessions_root + .file_name() + .and_then(|f| f.to_str()) + .unwrap_or(""); + format!( + "all sessions are empty (0 messages) in .claw/sessions/{fingerprint_dir}/\nThis usually means a fresh `claw` session is running but no messages have been sent yet.\nWait for a response in your other session, then try `--resume {LATEST_SESSION_REFERENCE}` again." + ) +} + fn format_legacy_session_missing_workspace_root( session_path: &Path, workspace_root: &Path, @@ -1229,6 +1254,35 @@ mod tests { fs::remove_dir_all(base).expect("temp dir should clean up"); } + #[test] + fn latest_session_returns_all_empty_error_when_sessions_exist_but_have_no_messages() { + // given — create sessions with 0 messages (empty) + let base = temp_dir(); + fs::create_dir_all(&base).expect("base dir should exist"); + let store = SessionStore::from_cwd(&base).expect("store should build"); + + let empty_handle = store.create_handle("empty-session"); + Session::new() + .with_persistence_path(empty_handle.path.clone()) + .save_to_path(&empty_handle.path) + .expect("empty session should save"); + + // when — latest_session should fail with the "all sessions empty" message + let result = store.latest_session(); + assert!(result.is_err(), "latest_session should fail when all sessions are empty"); + let err_msg = result.unwrap_err().to_string(); + assert!( + err_msg.contains("all sessions are empty"), + "error should mention 'all sessions are empty', got: {err_msg}" + ); + assert!( + err_msg.contains("0 messages"), + "error should mention '0 messages', got: {err_msg}" + ); + + fs::remove_dir_all(base).expect("temp dir should clean up"); + } + #[test] fn session_exists_and_delete_are_scoped_to_workspace_store() { // given diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index 7ee36c88..f3ba3112 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -15377,16 +15377,26 @@ UU conflicted.rs", std::env::set_current_dir(&workspace).expect("switch cwd"); let older = create_managed_session_handle("session-older").expect("older handle"); - Session::new() - .with_persistence_path(older.path.clone()) - .save_to_path(&older.path) - .expect("older session should save"); + { + let mut session = Session::new().with_persistence_path(older.path.clone()); + session + .push_user_text("older session message") + .expect("older message should save"); + session + .save_to_path(&older.path) + .expect("older session should save"); + } std::thread::sleep(Duration::from_millis(20)); let newer = create_managed_session_handle("session-newer").expect("newer handle"); - Session::new() - .with_persistence_path(newer.path.clone()) - .save_to_path(&newer.path) - .expect("newer session should save"); + { + let mut session = Session::new().with_persistence_path(newer.path.clone()); + session + .push_user_text("newer session message") + .expect("newer message should save"); + session + .save_to_path(&newer.path) + .expect("newer session should save"); + } let resolved = resolve_session_reference("latest").expect("latest session should resolve"); assert_eq!(