fn parse_semver_triple(s: &str) -> Option<(u32, u32, u32)>
Parse "<major>.<minor>.<patch>" (any trailing non-numeric suffix ignored). Missing minor/patch default to 0.
"<major>.<minor>.<patch>"