# Agent: Heuristic Analyzers A1-A5

## Your Task

Implement 5 heuristic analyzers in `analysis-14022026/analyzers/`. These are independent — each reads session/message data and outputs a JSON dict.

**Read these first:**
- `analysis-14022026/session_view_scripts/research/ideation.md` — full feature specs (sections A1-A5)
- `analysis-14022026/session_view_scripts/research/06_interrupt_output_taxonomy.py` — interrupt parsing
- `analysis-14022026/session_view_scripts/research/02_interruption_patterns.py` — interrupt research
- `analysis-14022026/session_view_scripts/research/03_autonomy_and_streaks.py` — autonomy research
- `analysis-14022026/session_view_scripts/research/04_undo_revert_and_ai_behavior.py` — undo/revert research

**Read the shared foundation code (created by another agent, may not exist yet — create stubs if needed):**
- `analysis-14022026/analyzers/base.py` — BaseAnalyzer class
- `analysis-14022026/analyzers/helpers.py` — tool name sets, `clean_user_content()`, `detect_interrupt_pattern()`, `is_shell_error()`, `categorize_tool()`

If `base.py`/`helpers.py` don't exist yet, create them with the minimal interface you need. The foundation agent is building them in parallel.

## Analyzers to Implement

### A1: `a01_interruptions.py` (ideation.md section A1)
Per-session analysis of interruption events.
- Walk messages to find interrupt `tool_result` entries (use `detect_interrupt_pattern()` from helpers)
- For each interrupt: find the interrupted tool (walk backwards to nearest `tool_call`), compute position %, extract guidance text
- Extraction logic for corrective guidance (CRITICAL — 3 sources):
  1. Parse `tool_result.output` for `"the user said:"` — text after is inline correction (34% of cases)
  2. If no inline, find next `msg_type='user'` message, skipping consecutive interrupt tool_results — that's the correction (59%)
  3. If neither exists — user abandoned (7%)
- Output: `total_interrupts`, `sessions_with_interrupts`, per-session: `interrupt_count`, `first_interrupt_position_pct`, `interrupt_position_bucket` (mostly_early/mostly_late/spread), per-interrupt: `tool_name`, `tool_category`, `position_pct`, `guidance_source` (inline/next_msg/abandoned/stop), `guidance_text`, `time_to_next_msg_sec`, `session_recovered`

### A2: `a02_autonomy.py` (ideation.md section A2)
Tool streak analysis.
- Walk messages per session, count consecutive `tool_call` messages between `user` messages
- Per-session: `tool_calls_per_user_msg`, `max_tool_streak`, `avg_tool_streak`, `autonomous_segments` (streaks >= 5), `user_intervention_rate` (user_msgs / (tool_calls + assistant_msgs))

### A3: `a03_prompt_signals.py` (ideation.md section A3)
Scan user message content for signals. **Must strip source-specific noise first** using `clean_user_content()`.
- Per-session (scanning all user messages): `has_error_paste`, `has_log_paste`, `has_url`, `has_structured_data`, `has_code_paste`, `has_terminal_output`, `prompt_is_terse`, `first_prompt_char_len`
- Detection patterns from ideation.md:
  - error_paste: `Traceback (most recent call last)`, `Error:` at line boundary, `FAILED`, `ERR!`, `exit status 1`
  - log_paste: ≥3 lines matching timestamp patterns
  - url: `https?://\S+`
  - structured_data: ≥3 `{` and ≥3 `}` and ≥3 `:`
  - code_paste: ≥200 chars with high density of code tokens
  - terminal_output: `$` or `%` at line starts
  - terse: cleaned msg ≤15 chars

### A4: `a04_session_outcomes.py` (ideation.md section A4)
- Per-session: `has_edits`, `edit_count`, `files_edited` (distinct file paths from tool_input of edit tools), `has_git_commit`, `has_git_push`, `has_test_run`, `has_test_pass_after_fail`, `session_ended_with_user_msg`, `git_operations` dict
- Shell tool names to check: `Bash`, `shell_command`, `exec_command`, `run_shell_command`, `run_terminal_cmd`
- Edit tool names: `Edit`, `Write`, `MultiEdit`, `MultiEditTool`, `replace`
- Test detection: shell tool input contains `pytest`, `npm test`, `go test`, `jest`, `cargo test`

### A5: `a05_undo_revert.py` (ideation.md section A5)
- Per-session: `user_requested_undo` (user msg contains: `undo`, `revert this/that/the`, `roll back`, `go back to`, `put it back`), `undo_request_count`, `git_revert_in_session` (shell input has `git checkout --`, `git reset`, `git restore`, `git stash`), `ai_self_corrected` (assistant msg contains `I apologize`, `my mistake`, `let me fix that`, `that was incorrect`), `ai_self_correction_count`
- **Important:** Must strip gemini file refs and compaction summaries before keyword matching

## Output Format

Each analyzer returns a dict with:
- Summary stats (totals, counts)
- `per_session`: list of dicts, one per session with `session_id` + all computed features

## Verification

After implementing, test with:
```bash
python -c "
import sys; sys.path.insert(0, '.')
from analysis-14022026.analyzers.a01_interruptions import InterruptionAnalyzer
# ... quick smoke test with sample data
"
```

## Commit Convention
Use conventional commits: `feat:`, `fix:`, etc. No Claude/Anthropic attribution.
