cargowatch-core 0.1.0

Shared domain types, configuration, and session state for CargoWatch.
Documentation
//! Shared event model for runners, detectors, and persistence.

use std::path::PathBuf;

use serde::{Deserialize, Serialize};
use time::OffsetDateTime;

/// Whether a session is launched by CargoWatch or passively detected.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum SessionMode {
    /// CargoWatch launched and supervised the process.
    Managed,
    /// CargoWatch detected an existing process on the machine.
    Detected,
}

/// Lifecycle status for a session.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum SessionStatus {
    /// The process is still running.
    Running,
    /// The process finished successfully.
    Succeeded,
    /// The process finished with a non-zero exit code.
    Failed,
    /// The process was cancelled by the user.
    Cancelled,
    /// A detected external process disappeared.
    Lost,
}

/// Output stream classification.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum OutputStream {
    /// Standard output.
    Stdout,
    /// Standard error.
    Stderr,
    /// Synthetic system messages created by CargoWatch.
    System,
}

/// Severity level used for diagnostics and filtered logs.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum Severity {
    /// Compiler or build error.
    Error,
    /// Compiler warning.
    Warning,
    /// Additional note.
    Note,
    /// Suggested remediation or tip.
    Help,
    /// Informational message.
    Info,
    /// Positive completion or success status.
    Success,
}

/// Session metadata.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SessionInfo {
    /// Stable session identifier.
    pub session_id: String,
    /// Whether this is managed or detected.
    pub mode: SessionMode,
    /// Human-friendly title shown in the UI.
    pub title: String,
    /// Command line tokens.
    pub command: Vec<String>,
    /// Current working directory.
    pub cwd: PathBuf,
    /// Best-effort workspace root.
    pub workspace_root: Option<PathBuf>,
    /// Start timestamp.
    pub started_at: OffsetDateTime,
    /// Current status.
    pub status: SessionStatus,
    /// External process id, if one exists.
    pub external_pid: Option<u32>,
    /// Best-effort classification for the detected or managed command.
    pub classification: Option<DetectedProcessClass>,
}

/// A raw or rendered output line.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct LogEntry {
    /// Monotonic line sequence per session.
    pub sequence: u64,
    /// Timestamp when CargoWatch observed the line.
    pub timestamp: OffsetDateTime,
    /// Source stream.
    pub stream: OutputStream,
    /// Display-ready text.
    pub text: String,
    /// Original raw text, when it differs from display text.
    pub raw: Option<String>,
    /// Optional inferred severity.
    pub severity: Option<Severity>,
}

/// A compiler or build diagnostic.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct DiagnosticRecord {
    /// Unique diagnostic fingerprint within the session.
    pub id: String,
    /// Time observed.
    pub timestamp: OffsetDateTime,
    /// Diagnostic severity.
    pub severity: Severity,
    /// Main message.
    pub message: String,
    /// ANSI-rendered message when available.
    pub rendered: Option<String>,
    /// Rust diagnostic code, when present.
    pub code: Option<String>,
    /// File path for the primary span.
    pub file: Option<PathBuf>,
    /// Line for the primary span.
    pub line: Option<u32>,
    /// Column for the primary span.
    pub column: Option<u32>,
    /// Related target name.
    pub target: Option<String>,
    /// Related package id.
    pub package_id: Option<String>,
}

/// A compiled or otherwise produced build artifact.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ArtifactRecord {
    /// Monotonic event sequence within the session.
    pub sequence: u64,
    /// Time observed.
    pub timestamp: OffsetDateTime,
    /// Package id associated with the artifact.
    pub package_id: Option<String>,
    /// Target name.
    pub target: Option<String>,
    /// Generated output files.
    pub filenames: Vec<PathBuf>,
    /// Generated executable path, if any.
    pub executable: Option<PathBuf>,
    /// Whether the build reused a cached artifact.
    pub fresh: bool,
}

/// Summary counts for diagnostics.
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
pub struct SummaryCounts {
    /// Error count.
    pub errors: u32,
    /// Warning count.
    pub warnings: u32,
    /// Note count.
    pub notes: u32,
    /// Help count.
    pub help: u32,
    /// Informational line count.
    pub info: u32,
}

impl SummaryCounts {
    /// Increment counts for the provided severity.
    pub fn observe(&mut self, severity: Severity) {
        match severity {
            Severity::Error => self.errors += 1,
            Severity::Warning => self.warnings += 1,
            Severity::Note => self.notes += 1,
            Severity::Help => self.help += 1,
            Severity::Info | Severity::Success => self.info += 1,
        }
    }
}

/// Classification of a Rust-related process.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum DetectedProcessClass {
    /// `cargo build`
    CargoBuild,
    /// `cargo check`
    CargoCheck,
    /// `cargo test`
    CargoTest,
    /// `cargo clippy`
    CargoClippy,
    /// `cargo doc`
    CargoDoc,
    /// `rustc`
    RustcCompile,
    /// `rustdoc`
    Rustdoc,
    /// Anything else in the Rust toolchain family.
    UnknownRustProcess,
}

impl DetectedProcessClass {
    /// Display-friendly label.
    pub fn label(self) -> &'static str {
        match self {
            Self::CargoBuild => "cargo build",
            Self::CargoCheck => "cargo check",
            Self::CargoTest => "cargo test",
            Self::CargoClippy => "cargo clippy",
            Self::CargoDoc => "cargo doc",
            Self::RustcCompile => "rustc compile",
            Self::Rustdoc => "rustdoc",
            Self::UnknownRustProcess => "rust process",
        }
    }
}

/// Snapshot of a detected external process.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct DetectedProcess {
    /// Stable session identifier derived from process identity.
    pub session_id: String,
    /// Operating system pid.
    pub pid: u32,
    /// Executable or process name.
    pub process_name: String,
    /// Full command line.
    pub command: Vec<String>,
    /// Best-effort current working directory.
    pub cwd: Option<PathBuf>,
    /// Best-effort workspace root.
    pub workspace_root: Option<PathBuf>,
    /// Inferred process class.
    pub classification: DetectedProcessClass,
    /// Process start time.
    pub started_at: OffsetDateTime,
    /// Most recent observation time.
    pub last_seen_at: OffsetDateTime,
    /// Elapsed runtime in milliseconds.
    pub elapsed_ms: i64,
}

/// Completion payload for a finished session.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SessionFinished {
    /// Session identifier.
    pub session_id: String,
    /// End timestamp.
    pub finished_at: OffsetDateTime,
    /// Final session status.
    pub status: SessionStatus,
    /// Process exit code.
    pub exit_code: Option<i32>,
    /// Duration in milliseconds.
    pub duration_ms: i64,
    /// Final summary.
    pub summary: SummaryCounts,
}

/// Unified event stream emitted by the app's runtime services.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum SessionEvent {
    /// Managed or detected session created.
    SessionStarted(SessionInfo),
    /// Output line observed.
    OutputLine {
        /// Session receiving the log entry.
        session_id: String,
        /// Observed output line.
        entry: LogEntry,
    },
    /// Structured diagnostic observed.
    Diagnostic {
        /// Session receiving the diagnostic.
        session_id: String,
        /// Structured diagnostic payload.
        diagnostic: DiagnosticRecord,
    },
    /// Artifact built.
    ArtifactBuilt {
        /// Session receiving the artifact event.
        session_id: String,
        /// Produced artifact metadata.
        artifact: ArtifactRecord,
    },
    /// Session finished.
    SessionFinished(SessionFinished),
    /// External process first observed.
    ProcessDetected(DetectedProcess),
    /// External process changed status.
    ProcessUpdated(DetectedProcess),
    /// External process vanished.
    ProcessGone {
        /// Session id associated with the process.
        session_id: String,
        /// Process id.
        pid: u32,
        /// Observation time.
        observed_at: OffsetDateTime,
    },
}