← Commit history

Keep native copper refill and measurement on the explicitly selected KiCad endpoint

John Lauer ·65c0692eb5 · ·parent 6ffc663
3 files changed +24−7
SKILL.md+3−1
@@ -436,4 +436,6 @@ Read `skills/aiflow-project-page/SKILL.md` and run `adom-aiflow project-page-che  ### Explicit native read endpoint -For multiple-editor IPC conflicts, read `docs/isolated-kicad-read-socket.md`. `ADOM_AIFLOW_KICAD_READ_SOCKET` selects a verified instance for the four read/validation verbs only; it does not redirect mutations or window capture. Preserve unsaved editors, require live-editor identity, and keep every native DRC gate. A renamed PCB checkpoint must carry matching project/rule sidecars before it is opened.+For multiple-editor IPC conflicts, read `docs/isolated-kicad-read-socket.md`. `ADOM_AIFLOW_KICAD_READ_SOCKET` selects a verified instance for read/validation and zone-measurement verbs; zone measurement includes its single refill request. It does not redirect route, placement, zone-edit or window-capture calls. Preserve unsaved editors, require live-editor identity, and keep every native DRC gate. A renamed PCB checkpoint must carry matching project/rule sidecars before it is opened.++Copper measurement uses the same explicit `ADOM_AIFLOW_KICAD_READ_SOCKET` as placement/routing reads. This includes its one native refill request and delayed zone snapshots; it does not enable route or placement edits on isolated endpoints. See `docs/isolated-kicad-read-socket.md`.
crates/aiflow-bridge/src/lib.rs+17−4
@@ -94,12 +94,13 @@ fn pull_until_landed(local: &Path, attempts: usize, mut pull: impl FnMut(), mut     (false, attempts.max(1)) } -/// Opt-in endpoint for the four native read/validate verbs whose published-/// schemas support socketPath. Never silently redirect a mutation or a window verb.+/// Opt-in endpoint for native read/validate and zone-measurement calls.+/// Zone measurement includes its one refill request and subsequent readbacks.+/// Never redirect placement, routing, zone-edit, or window-control calls. fn read_socket_args(verb: &str, args: &Value, socket: Option<&str>) -> Value {     let mut result = args.clone();     if matches!(verb, "kicad_routing_state" | "kicad_routing_validate" |-        "kicad_placement_state" | "kicad_placement_validate") {+        "kicad_placement_state" | "kicad_placement_validate" | "kicad_zone_state") {         if let (Some(object), Some(socket)) = (result.as_object_mut(), socket) {             if !socket.trim().is_empty() && !object.contains_key("socketPath") {                 object.insert("socketPath".into(), Value::String(socket.into()));@@ -555,12 +556,24 @@ mod read_socket_tests {         assert_eq!(read_socket_args("kicad_placement_state",&explicit,Some("other")),explicit);     }     #[test]+    fn zone_refill_and_readbacks_use_the_same_selected_endpoint() {+        for refill in [true, false] {+            let args = json!({"filePath":"exact-board", "refill":refill});+            let routed = read_socket_args("kicad_zone_state", &args, Some("ipc://isolated/api.sock"));+            assert_eq!(routed["socketPath"], "ipc://isolated/api.sock");+            assert_eq!(routed["filePath"], args["filePath"]);+            assert_eq!(routed["refill"], refill);+        }+        let explicit = json!({"filePath":"exact-board", "refill":false, "socketPath":"ipc://explicit/api.sock"});+        assert_eq!(read_socket_args("kicad_zone_state", &explicit, Some("other")), explicit);+    }+    #[test]     fn absent_empty_and_unrelated_calls_are_unchanged() {         let a=json!({"filePath":"board"});         for socket in [None,Some(""),Some("  ")] {             assert_eq!(read_socket_args("kicad_placement_state",&a,socket),a);         }-        for verb in ["kicad_move_footprint","kicad_open_board","kicad_apply_tracks","fusion_routing_state","desktop_record_window_start"] {+        for verb in ["kicad_move_footprint","kicad_open_board","kicad_apply_tracks","kicad_apply_zone_plan","kicad_add_zone","fusion_routing_state","desktop_record_window_start"] {             assert_eq!(read_socket_args(verb,&a,Some("ipc://isolated/api.sock")),a);         }         assert_eq!(read_socket_args("kicad_placement_state",&Value::Null,Some("x")),Value::Null);
docs/isolated-kicad-read-socket.md+4−2
@@ -1,11 +1,13 @@-# Read-only checks with multiple KiCad editors+# Read checks and copper measurement with multiple KiCad editors  Some Windows KiCad 10 sessions expose only one default IPC pipe even with multiple PCB editors. A saved-file fallback is not live placement evidence. Keep a board mismatch failed; never close unrelated unsaved editors or relabel file snapshots as live. -For an independently verified native instance, `ADOM_AIFLOW_KICAD_READ_SOCKET=ipc://<exact-pipe>` selects its endpoint for only `kicad_placement_state`, `kicad_placement_validate`, `kicad_routing_state`, and `kicad_routing_validate`. An explicit `socketPath` in the call wins. No mutation, window-control, capture, Fusion or other verb is redirected. This is not general multiple-instance mutation support.+For an independently verified native instance, `ADOM_AIFLOW_KICAD_READ_SOCKET=ipc://<exact-pipe>` selects its endpoint for only `kicad_placement_state`, `kicad_placement_validate`, `kicad_routing_state`, `kicad_routing_validate`, and `kicad_zone_state`. An explicit `socketPath` in the call wins. For zone measurement this includes the single native refill request and both delayed readbacks, all against the exact requested board. No placement, route, zone-edit, window-control, capture, Fusion or other verb is redirected. This is not general multiple-instance mutation support.  Verify the returned board path, revision, `source: live-editor`, native validation and window identity. Existing gates still compare saved and live footprints, exact revision, complete DRC and reviewed edge-connector geometry. An invalid endpoint or file fallback must fail those gates.  A task-owned instance can be launched with a process-local TEMP/TMP directory to give its API pipe a separate name. This workaround requires native verification on the selected desktop; it is not a promise for every KiCad build. Do not change global environment/configuration or replace a shared runtime. Native edits needing endpoint selection remain a bridge-owned capability gap until their schemas explicitly support it.  When preparing renamed PCB checkpoints, copy matching `.kicad_pro` and `.kicad_dru` sidecars to the output basename before opening it. Copying only the input basename can cause KiCad to create a default project for the output file, changing the DRC rules. Close only the saved task-owned editor before replacing its sidecars, then reopen and verify the actual rules. Never adjust acceptance thresholds to match an accidental default project.++Zone endpoint selection was verified with KiCad Bridge 1.0.55, including native board identity and filled-area readback. Its catalog did not list the accepted socketPath parameter; verify your bridge behavior before relying on this opt-in. A board mismatch must remain an error, not a saved-file fallback.