fix(domain,application,infrastructure,backend,web-server,app-tauri,frontend): statut/LED projet indexé par projectId, source LiveSessions/LiveStateStore/ReconcileLiveState — la fin d'un agent dans un projet non actif repasse désormais la LED du projet au repos — domain: DomainEvent::AgentBusyChanged porte project_id ; infrastructure input: busy émis au démarrage du tour et idle au mark_idle avec le projet possesseur ; backend: DTO agentBusyChanged sérialise project_id (busy_changed_keeps_owning_project_on_the_wire) ; application workstate: ReconcileLiveState exécuté aussi avant les lectures de projection (plus seulement à l'ouverture) et liveness évaluée par (projectId, agentId) — un même agent_id vivant dans un autre projet n'épargne plus un orphelin ; web-server: ws_send_chat libère le busy avant le Final visible et la route work-state projet reste au contrat tauri ; app-tauri: commandes work-state/busy alignées sur le projectId possesseur ; frontend: useProjectActivity agrège l'activité par projectId (busy_changed filtré par projet possesseur, plus le seul projet courant), wsLiveClient/wsLiveClientReconnect propagant project_id, AnnouncementsProvider/CustomAgentChatView/WebWorkspaceLive/LayoutGrid.cellControlsLayering alignés — #373 (QA verte: cargo check --tests -p domain -p application -p infrastructure -p backend -p app-tauri -p web-server, cargo test -p application workstate::reconcile::tests, cargo test -p infrastructure input::tests::busy_event_fires_on_turn_start_and_idle_on_mark_idle, cargo test -p backend events::tests::busy_changed_keeps_owning_project_on_the_wire, cargo test -p web-server websocket_chat_send_releases_busy_before_visible_final + authorized_get_project_work_state_returns_tauri_contract, npm test -- useProjectActivity wsLiveClient wsLiveClientReconnect workstate AnnouncementsProvider CustomAgentChatView WebWorkspaceLive LayoutGrid.cellControlsLayering, npm run typecheck, cargo fmt --all -- --check, git diff --check ; fichiers .ideai/* et scripts/ hors périmètre ; aucun push)
This commit is contained in:
@ -274,6 +274,8 @@ pub enum DomainEventDto {
|
||||
/// "Envoyer" while `busy` is `true`.
|
||||
#[serde(rename_all = "camelCase")]
|
||||
AgentBusyChanged {
|
||||
/// Owning project id.
|
||||
project_id: String,
|
||||
/// Agent id.
|
||||
agent_id: String,
|
||||
/// `true` when a turn is in flight, `false` when idle.
|
||||
@ -956,7 +958,12 @@ impl From<&DomainEvent> for DomainEventDto {
|
||||
DomainEvent::TicketAssistantClosed { issue_ref } => Self::TicketAssistantClosed {
|
||||
issue_ref: issue_ref.to_string(),
|
||||
},
|
||||
DomainEvent::AgentBusyChanged { agent_id, busy } => Self::AgentBusyChanged {
|
||||
DomainEvent::AgentBusyChanged {
|
||||
project_id,
|
||||
agent_id,
|
||||
busy,
|
||||
} => Self::AgentBusyChanged {
|
||||
project_id: project_id.to_string(),
|
||||
agent_id: agent_id.to_string(),
|
||||
busy: *busy,
|
||||
},
|
||||
@ -1465,6 +1472,27 @@ mod tests {
|
||||
assert_eq!(json["status"]["reused"], true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn busy_changed_keeps_owning_project_on_the_wire() {
|
||||
let project_id = ProjectId::from_uuid(uuid::Uuid::from_u128(41));
|
||||
let agent_id = agent(42);
|
||||
let dto = DomainEventDto::from(&DomainEvent::AgentBusyChanged {
|
||||
project_id,
|
||||
agent_id,
|
||||
busy: false,
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
serde_json::to_value(dto).expect("serialisable"),
|
||||
json!({
|
||||
"type": "agentBusyChanged",
|
||||
"projectId": project_id.to_string(),
|
||||
"agentId": agent_id.to_string(),
|
||||
"busy": false,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plugin_reloaded_relays_hashes_and_changed_flag_to_wire() {
|
||||
let plugin_id = domain::PluginId::new("dev.acme.gitgraph").unwrap();
|
||||
|
||||
Reference in New Issue
Block a user