Skip to main content

ralph/queue/validation/
mod.rs

1//! Queue validation facade.
2//!
3//! Responsibilities:
4//! - Expose queue validation entrypoints and warning types.
5//! - Coordinate queue-file checks with dependency, relationship, and parent validators.
6//! - Keep shared validation data structures local to this module tree.
7//!
8//! Not handled here:
9//! - Queue persistence or mutation workflows.
10//! - Config validation or CLI reporting.
11//!
12//! Invariants/assumptions:
13//! - Task IDs are unique within a queue file and across active/done files, except rejected tasks.
14//! - Dependency and blocking graphs must remain acyclic.
15//! - Warnings are non-blocking and may be logged separately by callers.
16
17mod dependency_graph;
18mod parent;
19mod queue_files;
20mod relationships;
21mod shared;
22mod task_fields;
23
24use anyhow::Result;
25
26pub(crate) use task_fields::validate_task_id;
27
28/// Represents a validation issue that doesn't prevent queue operation but should be reported.
29#[derive(Debug, Clone)]
30pub struct ValidationWarning {
31    pub task_id: String,
32    pub message: String,
33}
34
35impl ValidationWarning {
36    /// Log this warning using the standard logging framework.
37    pub fn log(&self) {
38        log::warn!("[{}] {}", self.task_id, self.message);
39    }
40}
41
42/// Log all validation warnings.
43pub fn log_warnings(warnings: &[ValidationWarning]) {
44    for warning in warnings {
45        warning.log();
46    }
47}
48
49/// Result of dependency and relationship validation containing warnings.
50#[derive(Debug, Default)]
51pub struct DependencyValidationResult {
52    pub warnings: Vec<ValidationWarning>,
53}
54
55/// Validate a single queue file.
56pub fn validate_queue(
57    queue: &crate::contracts::QueueFile,
58    id_prefix: &str,
59    id_width: usize,
60) -> Result<()> {
61    queue_files::validate_queue(queue, id_prefix, id_width)
62}
63
64/// Validate an optional done archive file.
65pub(crate) fn validate_done_queue(
66    done: Option<&crate::contracts::QueueFile>,
67    id_prefix: &str,
68    id_width: usize,
69) -> Result<()> {
70    queue_files::validate_done_queue(done, id_prefix, id_width)
71}
72
73/// Validate active and optional done queues together, returning non-blocking warnings.
74pub fn validate_queue_set(
75    active: &crate::contracts::QueueFile,
76    done: Option<&crate::contracts::QueueFile>,
77    id_prefix: &str,
78    id_width: usize,
79    max_dependency_depth: u8,
80) -> Result<Vec<ValidationWarning>> {
81    queue_files::validate_queue(active, id_prefix, id_width)?;
82    queue_files::validate_done_queue(done, id_prefix, id_width)?;
83    queue_files::validate_cross_file_duplicates(active, done)?;
84
85    let catalog = shared::TaskCatalog::new(active, done);
86    let mut result = DependencyValidationResult::default();
87
88    dependency_graph::validate_dependency_graph(&catalog, max_dependency_depth, &mut result)?;
89    relationships::validate_relationships(&catalog, &mut result)?;
90    parent::validate_parent_ids(&catalog, &mut result)?;
91
92    Ok(result.warnings)
93}
94
95#[cfg(test)]
96mod tests;