fix(agents): enforcer l'invariant « 1 session vivante par agent » (singleton)
Un agent ne peut tourner que dans une seule cellule à la fois. La garde dans LaunchAgent refuse le spawn si l'agent est déjà vivant dans un autre node (AGENT_ALREADY_RUNNING) ; idempotent sur le même node ; le chemin resume (agent mort) reste inchangé. Le node_id est désormais plombé jusqu'au use case. Corrige le reset asymétrique d'une cellule au changement d'onglet : deux leaves partageant le même agent id rendaient session_for_agent/is_agent_live/stop_agent ambigus (cible arbitraire). Le churn reset/reattach déclenchait aussi les accents mélangés (FIFO intact, non touché). - snapshot agentWasRunning calculé par node (is_node_live) et non par agent - commande list_live_agents + live_agents()/node_for_agent()/is_node_live() - UI : dropdown grise les agents déjà placés ailleurs ; 2e cellule en doublon affiche « disponible » au lieu d'une relance fantôme Tests : cargo test (application + app-tauri) vert ; tsc + vitest vert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -87,8 +87,12 @@ impl SnapshotRunningAgents {
|
||||
let mut changed = false;
|
||||
|
||||
for named in &mut doc.layouts {
|
||||
for (leaf_id, agent_id) in named.tree.agent_leaves() {
|
||||
let running = self.live.is_agent_live(&agent_id);
|
||||
for (leaf_id, _agent_id) in named.tree.agent_leaves() {
|
||||
// Liveness is keyed on the hosting *node*, not the agent: with the
|
||||
// one-live-session-per-agent invariant, an agent pinned on several
|
||||
// leaves is live in at most one cell, so only that cell must be
|
||||
// marked running (a duplicate leaf for the same agent stays false).
|
||||
let running = self.live.is_node_live(&leaf_id);
|
||||
if running {
|
||||
out.running += 1;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user