diff --git a/lib/crates/fabro-validate/src/rules/inert_attribute.rs b/lib/crates/fabro-validate/src/rules/inert_attribute.rs index cb3d18035..fef9c5454 100644 --- a/lib/crates/fabro-validate/src/rules/inert_attribute.rs +++ b/lib/crates/fabro-validate/src/rules/inert_attribute.rs @@ -1,4 +1,4 @@ -use fabro_graphviz::graph::Graph; +use fabro_graphviz::graph::{self, Graph}; use crate::{Diagnostic, LintRule, Severity}; @@ -39,6 +39,9 @@ impl LintRule for Rule { let Some(handler) = node.handler_type() else { continue; }; + if !graph::is_known_handler_type(handler) { + continue; + } for (attr, consumers) in HANDLER_SPECIFIC_ATTRS { if !node.attrs.contains_key(*attr) { continue; @@ -217,4 +220,20 @@ mod tests { ); assert!(Rule.apply(&g).is_empty()); } + + #[test] + fn ignores_handler_specific_attrs_on_unrecognized_explicit_types() { + let mut g = minimal_graph(); + let mut node = Node::new("custom"); + node.attrs.insert( + "type".to_string(), + AttrValue::String("custom.handler".to_string()), + ); + node.attrs.insert( + "script".to_string(), + AttrValue::String("echo hi".to_string()), + ); + g.nodes.insert("custom".to_string(), node); + assert!(Rule.apply(&g).is_empty()); + } } diff --git a/lib/crates/fabro-validate/src/rules/parallel_branch_inert_attribute.rs b/lib/crates/fabro-validate/src/rules/parallel_branch_inert_attribute.rs index 6193f2700..eb051281e 100644 --- a/lib/crates/fabro-validate/src/rules/parallel_branch_inert_attribute.rs +++ b/lib/crates/fabro-validate/src/rules/parallel_branch_inert_attribute.rs @@ -11,7 +11,7 @@ pub(super) fn rule() -> Box { /// Attributes that parallel branch execution does not resolve. Branch nodes /// are dispatched with a snapshot of the context taken when the parallel node /// started, so per-branch `fidelity` never changes what a branch sees, and -/// branches never join conversation threads regardless of `thread_id`. +/// per-branch `thread_id` never replaces the thread inherited in that snapshot. const BRANCH_IGNORED_ATTRS: &[&str] = &["fidelity", "thread_id"]; struct Rule; @@ -39,7 +39,10 @@ fn fix_message(attr: &str, parallel_ids: &[String]) -> String { ) } } - _ => format!("Remove '{attr}': parallel branches never join conversation threads"), + "thread_id" => format!( + "Remove '{attr}': parallel branches inherit the thread resolved when the parallel node started" + ), + _ => format!("Remove '{attr}'"), } } @@ -210,6 +213,12 @@ mod tests { Some(("fork".to_string(), "branch_a".to_string())) ); assert!(d[0].message.contains("'thread_id'")); + assert_eq!( + d[0].fix.as_deref(), + Some( + "Remove 'thread_id': parallel branches inherit the thread resolved when the parallel node started" + ) + ); } #[test]