KiCad - the KiCad Bridge
Public Made by Adomby adom
Reference implementation of the KiCad bridge: multi-instance Python server, forward path via kicad-cli, reverse path via in-process plugin. Most complex of the three bundled bridges.
Expose complete saved-board model bindings for variant verification #10
The current board model check reports only footprints with warnings, so consumers cannot verify successful bindings to their selected etched or LED variants. Add a complete modelBindings inventory containing footprint UUID, reference, layer, model paths, resolution, transforms and hidden state. Preserve existing warning/count behavior and explicitly identify the result as saved-file evidence, not unsaved editor or rendered evidence.
This addresses the inspection portion of issue #101. It does not implement native model mutation or claim render verification. The linked KiCad IPC FootprintInstance schema does not expose a model list, so mutation must not be faked by silently changing the file underneath an open editor.
Validation: 12 model-check tests passed with --no-default-features, including successful bindings, missing models, intentional model-free footprints, and an inventory unaffected by the warning limit. The default-feature build initially lacked cmake on PATH; the changed module has no IPC dependency. No shared bridge was replaced. Native Windows acceptance remains with the bridge owner before publication.
Diff Skip to comments (1)
@@ -1,928 +1,952 @@⋯ 645 unchanged lines ⋯ }; let project_dir = p.parent().map(norm).unwrap_or_default(); let mut per = Vec::new();+ let mut bindings = Vec::new(); let (mut footprints, mut with_model, mut no_model_expected_n, mut missing, mut unresolved, mut nwarn) = (0u64, 0u64, 0u64, 0u64, 0u64, 0u64); for fp in tree.find_all("footprint") { let fp_id = fp.atom_at(1).unwrap_or("?").to_string();⋯ 7 unchanged lines ⋯ } let rows = model_rows(fp, ctx, Some(&project_dir)); let a = attrs(fp);+ bindings.push(json!({+ "itemId": fp.find("uuid").and_then(|x| x.atom_at(1)),+ "reference": reference,+ "footprint": fp_id,+ "layer": fp.find("layer").and_then(|x| x.atom_at(1)),+ "models": rows,+ "noModelExpected": rows.is_empty() && no_model_expected(&fp_id, &a),+ })); footprints += 1; let mut w = tag_warnings(&rows); if !rows.is_empty() {⋯ 24 unchanged lines ⋯ "counts": {"footprints": footprints, "withModel": with_model, "noModelExpected": no_model_expected_n, "missingModel": missing, "unresolvedModel": unresolved, "warnings": nwarn}, "footprintsWithWarnings": per,+ "modelBindings": bindings,+ "bindingsComplete": true,+ "evidenceSource": "saved-board-file",+ "unsavedEditorStateIncluded": false, "ok": nwarn == 0, "renderVerified": false, "nextCheck": "kicad_show_3d_board and read the frame: bodies on every populated footprint are the proof.",⋯ 202 unchanged lines ⋯ let r = check_board(&f.ctx, &norm(&board), 1); assert_eq!(r["footprintsWithWarnings"].as_array().unwrap().len(), 1); assert_eq!(r["counts"]["warnings"], json!(2));+ // Warning limit must never hide successful bindings or model-free items.+ let bindings = r["modelBindings"].as_array().unwrap();+ assert_eq!(bindings.len(), 4);+ assert_eq!(bindings[0]["reference"], "U1");+ assert_eq!(bindings[0]["layer"], "F.Cu");+ assert_eq!(bindings[0]["models"][0]["exists"], true);+ assert_eq!(bindings[2]["noModelExpected"], true);+ assert_eq!(bindings[3]["models"], json!([]));+ assert_eq!(r["bindingsComplete"], true);+ assert_eq!(r["unsavedEditorStateIncluded"], false); } #[test]⋯ 23 unchanged lines ⋯ assert_eq!(ctx.expand("${KICAD10_3RD_PARTY}/x.step", None).0, "/custom/3rd/x.step"); } }+@@ -1,184 +1,191 @@⋯ 181 unchanged lines ⋯ - [ ] USB-C connector visible if present - [ ] LED packages visible and arranged in expected pattern - [ ] No error dialogs in KiCad++## Inspect every saved model binding++`kicad_model_check {"boardPath":"<saved board>"}` returns `modelBindings` for every footprint, including successful bindings and intentionally model-free footprints. Each row carries the footprint UUID, reference, layer and model resolution, transforms and hidden state. `limit` truncates only the warning list, never this inventory. Compare these bindings to the selected library variants before filming.++This is explicitly `evidenceSource: saved-board-file`: unsaved editor edits are not included. Save the exact intended board first. `renderVerified` remains false; inspect the native 3D viewer to verify placement, appearance and visibility. A resolved file is not proof of correct geometry or orientation.+
Comments
Log in to comment.
Merged and shipped in KiCad Bridge 1.0.22 (insiders). Verified on ConfRoomROG against the ESC board: 149
modelBindingsfor 149 footprints, 128 with models, 21noModelExpected, whilefootprintsWithWarningsstays capped at 38, so the inventory is complete regardless of the warning limit.bindingsComplete:true,evidenceSource:"saved-board-file",unsavedEditorStateIncluded:false, as the PR says. Clean merge, no conflicts.