---
issueRef: "#30"
version: 8
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1783941648176
---
## Cadrage Architect (2026-07-13) — cas DIRECT, actionnable

Débloqué : #27 fermé. #30 ≠ #15 (#15 = cas délégué, différé).

**Périmètre** : le chemin direct de session agent (agent directement adressé, ex. Main) ne remonte pas la limite vers `SessionLimitService`. Fix = accrocher le détecteur sur le chemin direct, avant résolution finale du tour.

**Frontière hexagonale** : infra détecte (adapter provider/profil déclaratif extrait la limite du flux structuré/regex → `ReplyEvent::RateLimited { resets_at_ms? }`) ; application arme la reprise (`SessionLimitService::on_rate_limited(agent_id,node_id,conversation_id,resets_at_ms)`) ; app-tauri relaie ; React affiche/annule. Aucune logique provider dans domaine/application.

**Contrat d'événements** :
- `DomainEvent::AgentRateLimited { agent_id, resets_at_ms }`
- `DomainEvent::AgentResumeScheduled { agent_id, fire_at_ms }` si reprise armée
- reprise auto au reset, annulable via `cancel_resume` (contrat existant conservé)
- si heure de reset non récupérable : fallback niveau humain déjà cadré (état suspect + saisie d'heure, pas de silence)

**Point clé** : identité runtime — résoudre l'agent courant + `node_id` vivant + `conversation_id` via le registre/session meta existant (pas de convention UI). Sans `conversation_id`, ne PAS prétendre la reprise armée.

**Découpage** : B1 tap `ReplyEvent::RateLimited → on_rate_limited` dans le runner direct ; B2 résolution identité/session (agent_id/node_id/conversation_id) pour l'agent adressé ; B3 tests application/app-tauri (flux direct rate-limit avec resets_at_ms → AgentRateLimited puis AgentResumeScheduled) ; F1 régression badge existant (pas de nouveau contrat) ; F2 QA réelle (limite provoquée/mockée sur Main → heure affichée, annulation, reprise planifiée).

**Sous-lot adjacent** (ferme #7/F2, mémoire `ticket7-f2-delegated-limit-no-agentratelimited`) : la branche rendez-vous délégué publie seulement `DelegationRateLimited` et doit aussi armer `on_rate_limited(target,…)`. Traité dans la même branche mais en commit séparé.