fix: classify structural changes for all 248 tree-sitter languages resolve_protocol now constructs a Protocol from the tree-sitter grammar's ExtractedTheoryMeta for any language. The protocol's edge_rules are populated from the grammar's edge_kinds, so all named field removals are classified as breaking changes. Previously, only atproto-lexicon and raw-file had protocols, so Rust, TypeScript, Python, etc. produced empty breaking/compatible lists (the entire value proposition was invisible for 99% of code).
Author: Aaron Steven White
Commit
9c12ea2cdb370c6ac5818f64a6efeeb22547bf8cParent: 8fb2ed0de2
Structural diff unavailable
These commits were pushed via plain git push, so no pre-parsed
schemas are available. Install git-remote-cospan and re-push via panproto:// to
see scope-level changes, breaking change detection, and semantic diffs.
brew install panproto/tap/git-remote-cospan1 file changed +28 -8
@@ -206,21 +206,41 @@ fn detect_json_protocol(json: &Value) -> Option<(Schema, String)> {
206206 } 207207 208208 /// Recover a `Protocol` definition from its name so we can classify 209-/// the diff. Protocols that panproto-protocols exposes via a zero-arg 210-/// `protocol()` function work here; anything else falls through to a 211-/// conservative classification. 209+/// the diff. For protocols in panproto-protocols, returns the 210+/// explicit protocol. For tree-sitter-derived languages, constructs 211+/// a protocol from the extracted theory metadata so that all grammar 212+/// edges are classified as governed (removals are breaking). 212213 pub(crate) fn resolve_protocol(name: &str) -> Option<Protocol> { 213- // Lexicon is the most common case for Cospan's own repo, and the 214- // atproto module re-exports the protocol constructor. 214+ // Lexicon is the most common case for Cospan's own repo. 215215 if name == "atproto-lexicon" || name == "dev.panproto.atproto-lexicon" { 216216 return Some(atproto::protocol()); 217217 } 218218 if name == "raw-file" || name == "raw_file" { 219219 return Some(panproto_protocols::raw_file::protocol()); 220220 } 221- // Tree-sitter-derived schemas carry their own theory; the 222- // classifier handles those via the generic protocol encoded in the 223- // schema. Until that pipe is plumbed, fall back to None. 221+ // For tree-sitter languages: build a protocol from the grammar's 222+ // theory metadata. This makes all named edge kinds governed, so 223+ // removing a field/method/parameter is classified as breaking. 224+ let registry = panproto_parse::ParserRegistry::new(); 225+ if let Some(meta) = registry.theory_meta(name) { 226+ let edge_rules: Vec<panproto_schema::EdgeRule> = meta 227+ .edge_kinds 228+ .iter() 229+ .map(|ek| panproto_schema::EdgeRule { 230+ edge_kind: ek.clone(), 231+ src_kinds: vec![], 232+ tgt_kinds: vec![], 233+ }) 234+ .collect(); 235+ return Some(Protocol { 236+ name: name.to_string(), 237+ edge_rules, 238+ obj_kinds: meta.vertex_kinds.clone(), 239+ has_order: !meta.ordered_fields.is_empty(), 240+ has_coproducts: !meta.supertypes.is_empty(), 241+ ..Protocol::default() 242+ }); 243+ } 224244 None 225245 } 226246