# Autonomous Message Response Fix

## Problem
When Miku's autonomous system decided to respond immediately after someone sent a message, she would sometimes say something general/random instead of responding to what the person said. This happened because the decision engine could return `"general"` action type even when triggered by a fresh message.

## Root Cause
The issue had two parts:

1. The `should_take_action()` method in `autonomous_engine.py` didn't distinguish between:
   - **Scheduled checks** - Running periodically on a timer (appropriate for "general" actions)
   - **Message-triggered checks** - Running immediately after someone sends a message (should respond to that message)

2. **The main bug**: `_check_and_act()` was calling `autonomous_tick_v2()`, which then called `should_take_action()` **again** without the `triggered_by_message` flag. This caused the decision to be re-evaluated and potentially changed from `"join_conversation"` to `"general"`.

When the "break silence" condition was met, the flow was:
1. `_check_and_act()` calls `should_take_action(triggered_by_message=True)` → returns `"join_conversation"`
2. Calls `autonomous_tick_v2()`
3. `autonomous_tick_v2()` calls `should_take_action()` **again** (without flag) → returns `"general"`
4. Executes general action instead of joining conversation

## Solution
Added a `triggered_by_message` parameter to the decision logic:

### Changes Made

#### 1. `autonomous_engine.py`
- Added `triggered_by_message: bool = False` parameter to `should_take_action()`
- Modified the "break silence" decision logic to check this flag
- When `triggered_by_message=True` and "break silence" condition is met, return `"join_conversation"` instead of `"general"`
- This ensures Miku responds to the recent message rather than saying something random

#### 2. `autonomous.py`
- Updated `_check_and_act()` to:
  1. Pass `triggered_by_message=True` when calling `should_take_action()`
  2. **Execute the action directly** instead of calling `autonomous_tick_v2()` (which would check again)
  3. Include rate limiting and error handling
- This prevents the decision from being re-evaluated and potentially changed
- Added documentation explaining the importance of direct execution

## Behavior Changes

### Before Fix
```
User: "Hey everyone, how's it going?"
Miku: "I wonder if there are clouds on Mars... 🤔"  # Random general statement
```

### After Fix
```
User: "Hey everyone, how's it going?"
Miku: "Hey! I'm doing great! How about you? 😊"  # Responds to the message
```

## Technical Details

The decision priority order remains:
1. **join_conversation** - High conversation momentum
2. **engage_user** - User activity detected (status change, started activity)
3. **join_conversation (FOMO)** - Lots of messages without Miku participating
4. **general OR join_conversation** - Break silence (depends on `triggered_by_message` flag)
5. **share_tweet** - Low activity, wants to share content

The key change is in step 4:
- **Scheduled check** (`triggered_by_message=False`): Returns `"general"` - Miku says something random
- **Message-triggered check** (`triggered_by_message=True`): Returns `"join_conversation"` - Miku responds to recent messages

## Testing
To verify the fix:
1. Have Miku idle for a while (to meet "break silence" condition)
2. Send a message in the autonomous channel
3. If Miku responds, she should now reply to your message instead of saying something random

## Date
December 5, 2025
