//! Watcher event types emitted to WebSocket clients and internal subscribers. use serde::Serialize; /// A lifecycle event emitted by the filesystem watcher. #[derive(Clone, Debug, Serialize)] #[serde(tag = "type", rename_all = "snake_case")] pub enum WatcherEvent { /// A work-pipeline file was created, modified, or deleted. WorkItem { /// Pipeline stage directory (e.g. `"2_current"`, `"5_archived"`). stage: String, /// Work item ID (filename stem without extension, e.g. `"42_story_my_feature"`). item_id: String, /// Semantic action inferred from the stage (e.g. `"start"`, `"accept"`). action: String, /// The deterministic git commit message used (or that would have been used). commit_msg: String, /// The pipeline stage the item moved FROM, populated for move operations. /// `None` for creations, deletions, or synthetic events. from_stage: Option, }, /// `.huskies/project.toml` was modified at the project root (not inside a worktree). ConfigChanged, /// An agent's state changed (started, stopped, completed, etc.). /// Triggers a pipeline state refresh so the frontend can update agent /// assignments without waiting for a filesystem event. AgentStateChanged, /// A story encountered a failure (e.g. merge failure). /// Triggers an error notification to configured Matrix rooms. MergeFailure { /// Work item ID (e.g. `"42_story_my_feature"`). story_id: String, /// Human-readable description of the failure. reason: String, }, /// An agent hit an API rate limit. /// Triggers a warning notification to configured chat rooms. RateLimitWarning { /// Work item ID the agent is working on. story_id: String, /// Name of the agent that hit the rate limit. agent_name: String, }, /// A story has been blocked (e.g. retry limit exceeded, empty diff). /// Triggers a warning notification to configured chat rooms. StoryBlocked { /// Work item ID (e.g. `"42_story_my_feature"`). story_id: String, /// Human-readable reason the story was blocked. reason: String, }, /// An agent hit a hard API rate limit and will be blocked until `reset_at`. /// Triggers auto-scheduling of a timer and a notification with the resume time. RateLimitHardBlock { /// Work item ID the agent is working on. story_id: String, /// Name of the agent that hit the hard rate limit. agent_name: String, /// UTC instant at which the rate limit resets. reset_at: chrono::DateTime, }, /// An OAuth account pool swap succeeded: a different account is now active. /// Triggers a notification to chat transports naming the new account. OAuthAccountSwapped { /// Email address of the newly activated account. new_email: String, }, /// All OAuth accounts in the pool are rate-limited — no swap was possible. /// Triggers a notification to chat transports with the earliest reset time. OAuthAccountsExhausted { /// Human-readable message describing when the earliest reset occurs. earliest_reset_msg: String, }, /// An agent transitioned to the Running state for a story. /// Triggers a status notification to configured chat rooms. AgentStarted { /// Work item ID the agent is working on. story_id: String, /// Name of the agent that started. agent_name: String, }, /// An agent finished processing a story (gates passed or failed). /// Triggers a status notification to configured chat rooms. AgentCompleted { /// Work item ID the agent was working on. story_id: String, /// Name of the agent that completed. agent_name: String, /// `true` if acceptance gates passed; `false` if they failed. success: bool, }, /// A new work item was successfully created and added to the backlog. /// Triggers a creation notification to configured chat rooms. NewItemCreated { /// Work item ID (e.g. `"1075_refactor_split_stage_enum"`). item_id: String, /// Human-readable item type (`"story"`, `"bug"`, `"refactor"`, `"spike"`). item_type: String, /// Human-readable item name. name: String, }, }