skill
EDA Bridge Standard: one way for an AI to drive every PCB tool
Public Made by Adomby adom
The standard every Adom EDA bridge follows so one AI can drive Altium, KiCad, Fusion 360 and any future PCB tool the same way: shared verb names in tiers, the board model JSON, reply and refusal conventions, and a coverage table of each bridge against the Altium reference.
← Commit history
standard 0.4.2, engine 0.1.1: stack_layers names copper layers by the stack entry's layer, or by place (In<n>.Cu), planes included, per 0.3.1 (altium-lane's patch from its vendored copy, #8)
8 files changed
+18−11
README.md+2@@ -155,6 +155,8 @@ Decisions so far (proposals from the KiCad and Fusion bridges, 2026-10-27; issue ## Status +Version 0.4.2: the engine (0.1.1) names a stack's copper layers by the stack entry's `layer`, or by place (`In<n>.Cu`),+planes included, as 0.3.1 settled; from altium-lane, which runs the engine inside the Altium bridge now. Version 0.4.1: coverage counts only what works: a bridge marks a verb `partial` (with a note) or `unsupported` in its equivalents file ([conventions](docs/conventions.md)); `sheet` on a tool without sheet files is the sheet number. Version 0.4.0: the checks engine, `adom-eda-checks`, is on this page in `engine/` with its first five checks; fab limits
engine/Cargo.lock+1−1@@ -4,7 +4,7 @@ version = 4 [[package]] name = "adom-eda-checks"-version = "0.1.0"+version = "0.1.1" dependencies = [ "serde_json", ]
engine/Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "adom-eda-checks"-version = "0.1.0"+version = "0.1.1" edition = "2021" description = "The EDA Bridge Standard's checks, computed from the board model JSON: no bridge calls, no tool." license = "MIT"
engine/src/coppermap.rs+10−5@@ -84,14 +84,16 @@ impl Raster { pub fn count(&self) -> usize { self.cells.iter().filter(|c| **c).count() } } -/// The stack's copper layers in order as (routing_state name, plane?, plane net).+/// The stack's copper layers in order as (board model name, plane?, plane net). The name is the stack entry's `layer`+/// when the bridge gives it, else its place in the copper stack (F.Cu, In<n>.Cu, B.Cu): a plane is named like any other+/// inner layer (standard 0.3.1), never by a tool's id. pub fn stack_layers(stack: &Value) -> Vec<(String, bool, String)> { let ls: Vec<Value> = stack["layers"].as_array().cloned().unwrap_or_default(); let n = ls.len(); ls.iter().enumerate().map(|(i, l)| {- if l["kind"] == "plane" { return (format!("L{}", 38 + l["plane"].as_i64().unwrap_or(1)), true, l["net"].as_str().unwrap_or("").to_string()); }- let name = if i == 0 { "F.Cu".to_string() } else if i + 1 == n { "B.Cu".to_string() } else { format!("In{}.Cu", l["mid"].as_i64().unwrap_or(i as i64)) };- (name, false, String::new())+ let plane = l["kind"] == "plane";+ let name = l["layer"].as_str().map(str::to_string).unwrap_or_else(|| if i == 0 { "F.Cu".to_string() } else if i + 1 == n { "B.Cu".to_string() } else { format!("In{i}.Cu") });+ (name, plane, if plane { l["net"].as_str().unwrap_or("").to_string() } else { String::new() }) }).collect() } @@ -418,8 +420,11 @@ mod tests { fn stack_names_match_routing_state() { let s = json!({"layers": [{"name": "Top"}, {"kind": "plane", "plane": 1, "net": "GND"}, {"kind": "signal", "mid": 1}, {"name": "Bottom"}]}); let l = stack_layers(&s);- assert_eq!(l.iter().map(|x| x.0.as_str()).collect::<Vec<_>>(), vec!["F.Cu", "L39", "In1.Cu", "B.Cu"]);+ assert_eq!(l.iter().map(|x| x.0.as_str()).collect::<Vec<_>>(), vec!["F.Cu", "In1.Cu", "In2.Cu", "B.Cu"]); assert!(l[1].1 && l[1].2 == "GND");+ // the bridge's own name wins when it gives one+ let named = json!({"layers": [{"layer": "F.Cu"}, {"layer": "In1.Cu", "kind": "plane", "net": "GND", "layerId": 39}, {"layer": "B.Cu"}]});+ assert_eq!(stack_layers(&named)[1], ("In1.Cu".to_string(), true, "GND".to_string())); } #[test] fn gap_runs_group_and_the_fix_patches_the_neighbour() {
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "eda-bridge-standard",- "version": "0.4.1",+ "version": "0.4.2", "type": "skill", "title": "EDA Bridge Standard: one way for an AI to drive every PCB tool", "description": "The standard every Adom EDA bridge follows so one AI can drive Altium, KiCad, Fusion 360 and any future PCB tool the same way: shared verb names in tiers, the board model JSON, reply and refusal conventions, and a coverage table of each bridge against the Altium reference.",
page.json+1−1@@ -4,7 +4,7 @@ "type": "skill", "title": "EDA Bridge Standard: one way for an AI to drive every PCB tool", "brief": "The standard every Adom EDA bridge follows so one AI can drive Altium, KiCad, Fusion 360 and any future PCB tool the same way: shared verb names in tiers, the board model JSON, reply and refusal conventions, and a coverage table of each bridge against the Altium reference.",- "version": "0.4.1",+ "version": "0.4.2", "hero": { "type": "billboard", "headline": "One standard for every EDA bridge",
verbs/coverage.json+1−1@@ -1,5 +1,5 @@ {- "standard": "0.4.1",+ "standard": "0.4.2", "reference": { "bridge": "altium", "version": "0.2.76"
verbs/standard.json+1−1@@ -1,5 +1,5 @@ {- "standard": "0.4.1",+ "standard": "0.4.2", "reference": { "bridge": "altium", "version": "0.2.76"