# E2E Spec: Core Dispatcher

## Overview
Test the Dispatcher message routing, agent resolution, and session lifecycle.
Covers `internal/dispatcher/dispatcher.go`.

## Setup
Create Dispatcher with mock channel manager.
Use temp config directory for profile isolation.

## Test Cases

### Agent Resolution Priority
- `msg.AgentID` takes highest priority
- AgentTeamMeta.AgentID used when msg.AgentID is empty
- AgentOverrides checked after AgentTeamMeta
- Channel config agentID used when no override
- Default agent used when no channel config
- Single agent used when no default
- Resolution fails when no agents configured (error reply)

### Message Routing
- Slash commands (`/`) routed to InstructionHandler
- Normal messages dispatched to agent session
- Nil message is silently ignored
- Nil context replaced with Background

### Session Lifecycle
- First message creates new session
- Subsequent messages reuse existing session
- Session includes agent config, runtime, workspace dir
- Session cleanup on process exit (non-sleeping)
- Session retained on process exit (sleeping)

### History
- History entries accumulate per session
- History capped at 2000 entries
- Pagination with before/after/limit
- Limit clamped to [1, 200]

### Attachments
- Channel MCP handlers resolve attachment file paths against SessionSnapshot.WorkDir
- Attachment path resolution rejects directories
- Channels pass resolved attachment paths directly when sending messages

### Recovery
- RestoreAgentRecoveryPoint validates capability
- Live restore attempted first
- Falls back to detached when agent busy
- GCRecoveryPoints skips entries with empty strategy/ref

### Deferred Delivery
- Deferred entries stored and sorted
- consumeNextDeferredDelivery marks ReplayPending
- ReconcileDeferredDeliveries removes matched entries
- HasDeferredDeliveries reports correctly

### Conversation ID
- buildConversationAgentID produces deterministic SHA1 hash
- Same channel+conversation always maps to same ID
