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 9c12ea2cdb370c6ac5818f64a6efeeb22547bf8c
Parent: 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-cospan
1 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 
cospan · schematic version control on atproto built on AT Protocol