Claude Code commited on
Commit
d079764
·
1 Parent(s): 543ee28

god: Detect and reset corrupted conversation history

Browse files

[PROBLEM] When A2A communication fails partway through, it leaves
corrupted messages (empty, cut-off with '-') that poison all subsequent
agent responses. The emergency override would trigger, but the cycle
would repeat because the corrupted history persisted.

[FIX] Added CONV-RESET mechanism that:
- Detects empty messages, messages ending with '-' (cut off)
- Detects repeated emergency loop breaks (stuck pattern)
- Resets history, keeping only recent God messages for continuity
- Clears chatlog on frontend
- Resets discussion_loop_count to 0

This allows agents to start fresh with clean context instead of being
stuck in an infinite loop of poisoned responses.

Files changed (1) hide show
  1. scripts/conversation-loop.py +25 -0
scripts/conversation-loop.py CHANGED
@@ -2758,6 +2758,31 @@ while True:
2758
  except Exception as e:
2759
  print(f"[A2A-HEALTH] Error checking health: {e}", file=sys.stderr)
2760
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2761
  # UNCONDITIONAL AUTO-TERMINATE: Break deadlock when CC is stuck with 0 pushes
2762
  # This runs EVERY iteration, not just when agents submit tasks (which they can't when CC is stuck!)
2763
  # Prevents infinite discussion loops where agents wait forever for stuck CC
 
2758
  except Exception as e:
2759
  print(f"[A2A-HEALTH] Error checking health: {e}", file=sys.stderr)
2760
 
2761
+ # CORRUPTED CONVERSATION RESET: Detect and reset poisoned conversation history
2762
+ # Symptoms: empty messages, messages ending with "-" (cut off), repeated emergency loops
2763
+ # This happens when A2A communication fails partway through, leaving unusable context
2764
+ # Note: history and _discussion_loop_count are module-level globals, no 'global' keyword needed here
2765
+ if history and turn_count >= 3:
2766
+ # Check for corruption patterns
2767
+ has_empty = any(h.get("text", "").strip() == "" for h in history[-2:])
2768
+ has_cutoff = any(h.get("text", "").rstrip().endswith("-") for h in history[-2:])
2769
+ repeated_emergency = sum(1 for h in history[-5:] if "[EMERGENCY LOOP BREAK]" in h.get("text", "")) >= 2
2770
+
2771
+ if has_empty or has_cutoff or repeated_emergency:
2772
+ print(f"[CONV-RESET] Detected corrupted conversation (empty={has_empty}, cutoff={has_cutoff}, repeated_emergency={repeated_emergency}). Resetting history to allow fresh start.")
2773
+ # Keep only the most recent God message (if any) to show continuity
2774
+ god_messages = [h for h in history if h.get("speaker") == "God" and "Found issue" in h.get("text", "")]
2775
+ keep = god_messages[-1:] if god_messages else []
2776
+ history = keep
2777
+ # Clear chatlog on frontend
2778
+ try:
2779
+ post_chatlog(history)
2780
+ print(f"[CONV-RESET] Cleared corrupted chatlog, kept {len(keep)} God message(s)")
2781
+ except Exception as e:
2782
+ print(f"[CONV-RESET] Failed to post cleared chatlog: {e}")
2783
+ # Reset discussion loop counter since we're starting fresh
2784
+ _discussion_loop_count = 0
2785
+
2786
  # UNCONDITIONAL AUTO-TERMINATE: Break deadlock when CC is stuck with 0 pushes
2787
  # This runs EVERY iteration, not just when agents submit tasks (which they can't when CC is stuck!)
2788
  # Prevents infinite discussion loops where agents wait forever for stuck CC