feat(orchestrator): modèle de désignation d'orchestrateur + sink de diagnostic
Introduit le modèle AgentManifest { version, entries, orchestrator } et la
garde d'écriture directe may_write_directly(..., &OrchestratorDesignation) :
seul l'orchestrateur désigné peut écrire directement, les autres passent par
le rendez-vous médié. Câble la désignation à travers domain → application →
infrastructure → app-tauri (context_guard, service, lifecycle, ports).
Ajoute crates/application/src/diag.rs : sink de diagnostic best-effort, sans
dépendance, qui miroite les traces du rendez-vous inter-agents de
l'orchestrateur vers un fichier de log persistant (utile au lancement via
AppImage où stderr est jeté), avec la même discipline « zéro dépendance,
ne casse jamais le rendez-vous ».
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -258,6 +258,19 @@ pub enum DomainEvent {
|
||||
/// sinon `None` (l'utilisateur fournira l'heure).
|
||||
resets_at_ms: Option<i64>,
|
||||
},
|
||||
/// The project's **orchestrator designation** changed (cadrage « orchestrateur
|
||||
/// du projet », T1). Emitted when an agent is designated (radio selection) or the
|
||||
/// designation is cleared back to the default (e.g. the designated agent was
|
||||
/// deleted — lazy succession to the oldest agent). Relayed to the front so the UI
|
||||
/// can move the radio / refresh the orchestrator badge. Model-agnostic: carries
|
||||
/// only the neutral fact « who orchestrates now ».
|
||||
OrchestratorChanged {
|
||||
/// The project whose designation changed.
|
||||
project_id: ProjectId,
|
||||
/// The newly designated orchestrator agent, or `None` for the default
|
||||
/// (the oldest agent orchestrates).
|
||||
orchestrator: Option<AgentId>,
|
||||
},
|
||||
/// Raw PTY output (usually routed to a dedicated channel, not this bus).
|
||||
PtyOutput {
|
||||
/// The session.
|
||||
@ -358,6 +371,30 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn orchestrator_changed_constructs_and_compares() {
|
||||
let project = ProjectId::from_uuid(uuid::Uuid::from_u128(100));
|
||||
let ev = DomainEvent::OrchestratorChanged {
|
||||
project_id: project,
|
||||
orchestrator: Some(agent(1)),
|
||||
};
|
||||
assert_eq!(
|
||||
ev,
|
||||
DomainEvent::OrchestratorChanged {
|
||||
project_id: project,
|
||||
orchestrator: Some(agent(1)),
|
||||
}
|
||||
);
|
||||
// Clearing to the default (None) is a distinct event.
|
||||
assert_ne!(
|
||||
ev,
|
||||
DomainEvent::OrchestratorChanged {
|
||||
project_id: project,
|
||||
orchestrator: None,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn distinct_session_limit_variants_are_not_equal() {
|
||||
// Les variantes ne se confondent pas entre elles malgré des champs proches.
|
||||
|
||||
Reference in New Issue
Block a user