pub fn render_explain(a: &str, b: &str, found: &[ExplainedEdge]) -> StringExpand description
One header, then one line per rule-derived edge, capped like every other task digest.
Rule names, edge types and predicate fields are all graph content — a rule
is named by whoever created it — so each goes through
sanitize before it reaches a line-structured digest.