feat(agent): backend hot-swap profil (A0+A1) + inventaire reprise session (B1) — L15

Cadrage Architecture §15 (figé) : « agent = entité à session persistante ».

- A0 (domaine) : Agent::with_profile, LayoutTree::leaf, event AgentProfileChanged
  (+ DTO miroir DomainEventDto camelCase).
- A1 (application) : use case ChangeAgentProfile — no-op si profil identique,
  mutation manifeste, nettoyage conversation_id/agent_was_running sur layouts
  persistés, swap à chaud (kill PTY + relance même cellule via composition de
  LaunchAgent), event AgentProfileChanged. Décision : repartir à neuf (on garde
  .md + mémoire, on jette l'historique de conversation).
- B1 (application) : use case ListResumableAgents (lecture seule) — inventaire des
  cellules was_running||conversation_id, resume_supported selon profil, best-effort.

Aucun nouveau port/adapter (composition de l'existant). Hexagonal strict.
Tests : domaine 11 + app-tauri dto + ChangeAgentProfile 9 + ListResumableAgents 8,
suite application complète verte (0 régression).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 09:55:44 +02:00
parent 62bd5130fb
commit 2433e173a1
15 changed files with 2630 additions and 11 deletions

View File

@ -107,6 +107,16 @@ impl Agent {
})
}
/// Change le profil runtime de l'agent. Le contexte `.md`, l'origine template
/// et la synchronisation sont **inchangés** (décision verrouillée : on garde le
/// `.md`/mémoire, on ne touche qu'au moteur). Pur, infaillible (un `ProfileId`
/// est déjà un VO validé).
#[must_use]
pub fn with_profile(mut self, profile_id: ProfileId) -> Self {
self.profile_id = profile_id;
self
}
/// Returns a copy of this agent carrying the given assigned skills,
/// deduplicated by `skill_id` (keeping first occurrence).
#[must_use]