Fix: Proper session rotation detection (v1.2)

Fixes the bug where watcher stayed stuck on old sessions after /new or /reset.

Changes:
- Added file_score() function combining mtime + size for better detection
- Added INACTIVITY_THRESHOLD (30s) - if no new data, check for active session
- Tracks last_data_time and file size to detect stale sessions
- Switches to newer session when current is inactive

The previous v1.1 fix (mtime polling) was incomplete because new sessions
can have older mtime than recently-written old sessions.

Tested: Watcher now properly follows session rotation on /new and /reset
This commit is contained in:
root
2026-02-28 19:09:38 -06:00
parent a053ec1c3d
commit 5c2014cb11

View File

@@ -1,9 +1,15 @@
#!/usr/bin/env python3
"""
TrueRecall v1.1 - Real-time Qdrant Watcher
TrueRecall v1.2 - Real-time Qdrant Watcher
Monitors OpenClaw sessions and stores to memories_tr instantly.
This is the CAPTURE component. For curation and injection, install v2.
Changelog:
- v1.2: Fixed session rotation bug - added inactivity detection (30s threshold)
and improved file scoring to properly detect new sessions on /new or /reset
- v1.1: Added 1-second mtime polling for session rotation
- v1.0: Initial release
"""
import os
@@ -134,6 +140,11 @@ def store_to_qdrant(turn: Dict[str, Any], dry_run: bool = False) -> bool:
def get_current_session_file():
"""Find the most recently active session file.
Uses a combination of creation time and modification time to handle
session rotation when /new or /reset is used.
"""
if not SESSIONS_DIR.exists():
return None
@@ -141,7 +152,20 @@ def get_current_session_file():
if not files:
return None
return max(files, key=lambda p: p.stat().st_mtime)
# Score files by: recency (mtime) + size activity
# Files with very recent mtime AND non-zero size are likely active
def file_score(p: Path) -> float:
try:
stat = p.stat()
mtime = stat.st_mtime
size = stat.st_size
# Prefer files with recent mtime and non-zero size
# Add small bonus for larger files (active sessions grow)
return mtime + (size / 1e9) # size bonus is tiny vs mtime
except Exception:
return 0
return max(files, key=file_score)
def parse_turn(line: str, session_name: str) -> Optional[Dict[str, Any]]:
@@ -225,6 +249,10 @@ def watch_session(session_file: Path, dry_run: bool = False):
last_position = 0
last_session_check = time.time()
last_data_time = time.time() # Track when we last saw new data
last_file_size = session_file.stat().st_size if session_file.exists() else 0
INACTIVITY_THRESHOLD = 30 # seconds - if no data for 30s, check for new session
with open(session_file, 'r') as f:
while running:
@@ -232,15 +260,45 @@ def watch_session(session_file: Path, dry_run: bool = False):
print("Session file removed, looking for new session...")
return None
current_time = time.time()
# Check for newer session every 1 second
if time.time() - last_session_check > 1.0:
last_session_check = time.time()
if current_time - last_session_check > 1.0:
last_session_check = current_time
newest_session = get_current_session_file()
if newest_session and newest_session != session_file:
print(f"Newer session detected: {newest_session.name}")
return newest_session
# Check if current file is stale (no new data for threshold)
if current_time - last_data_time > INACTIVITY_THRESHOLD:
try:
current_size = session_file.stat().st_size
# If file hasn't grown, check if another session is active
if current_size == last_file_size:
newest_session = get_current_session_file()
if newest_session and newest_session != session_file:
print(f"Current session inactive, switching to: {newest_session.name}")
return newest_session
else:
# File grew, update tracking
last_file_size = current_size
last_data_time = current_time
except Exception:
pass
# Process new lines and update activity tracking
old_position = last_position
process_new_lines(f, session_name, dry_run)
# If we processed new data, update activity timestamp
if last_position > old_position:
last_data_time = current_time
try:
last_file_size = session_file.stat().st_size
except Exception:
pass
time.sleep(0.1)
return session_file