project
Adom Custom Electronic Load
Public Made by Adomby adom
Two-layer digitally controlled electronic-load prototype. Compact R11 is under active electrical, cooling and probe-access review; not a manufacturing release.
← Commit history
Prepare guarded copper replay and document remaining thermal work; no live landing
9 files changed
+3587
checkpoints/unclipped-hotspots-v1/candidate-v30.complete-diff.json+1851checkpoints/unclipped-hotspots-v1/drc-v30.json+36design/hotspot-v30-landing-plan.json+1214docs/completion-plan.md+4docs/reverse-protection-alternative.md+9tools/hotspot_via_candidate_v28.py+134tools/hotspot_via_candidate_v29.py+142tools/hotspot_via_candidate_v30.py+144tools/prepare_hotspot_landing.py+53checkpoints/unclipped-hotspots-v1/candidate-v30.complete-diff.jsonadded+1851@@ -0,0 +1,1851 @@+{+ "baselineSha256": "54f1aab0a34622d1c3675c13f4aeb7a678b0cee8b5a4d3bfd7484b10edb8dcf6",+ "candidateSha256": "0b4dacf6b7ac07cca64edf604c6f662ca7d5321a9035d72424f262f6cf507549",+ "formalAcceptance": false,+ "existingCopperNetChanges": [],+ "footprintChanges": [+ {+ "ref": "Q2",+ "before": {+ "at": [+ "124",+ "85.3"+ ],+ "pads": {+ "1": {+ "at": [+ "-0.9375",+ "-0.95"+ ],+ "size": [+ "1.475",+ "0.6"+ ],+ "net": [+ "CLAMP_BASE"+ ]+ },+ "2": {+ "at": [+ "-0.9375",+ "0.95"+ ],+ "size": [+ "1.475",+ "0.6"+ ],+ "net": [+ "GND"+ ]+ },+ "3": {+ "at": [+ "0.9375",+ "0"+ ],+ "size": [+ "1.475",+ "0.6"+ ],+ "net": [+ "GATE"+ ]+ }+ }+ },+ "after": {+ "at": [+ "123.7",+ "85.3"+ ],+ "pads": {+ "1": {+ "at": [+ "-0.9375",+ "-0.95"+ ],+ "size": [+ "1.475",+ "0.6"+ ],+ "net": [+ "CLAMP_BASE"+ ]+ },+ "2": {+ "at": [+ "-0.9375",+ "0.95"+ ],+ "size": [+ "1.475",+ "0.6"+ ],+ "net": [+ "GND"+ ]+ },+ "3": {+ "at": [+ "0.9375",+ "0"+ ],+ "size": [+ "1.475",+ "0.6"+ ],+ "net": [+ "GATE"+ ]+ }+ }+ }+ },+ {+ "ref": "R7",+ "before": {+ "at": [+ "129",+ "84"+ ],+ "pads": {+ "1": {+ "at": [+ "-0.51",+ "0"+ ],+ "size": [+ "0.54",+ "0.64"+ ],+ "net": [+ "SERVO_OUT"+ ]+ },+ "2": {+ "at": [+ "0.51",+ "0"+ ],+ "size": [+ "0.54",+ "0.64"+ ],+ "net": [+ "GATE"+ ]+ }+ }+ },+ "after": {+ "at": [+ "129.1",+ "84"+ ],+ "pads": {+ "1": {+ "at": [+ "-0.51",+ "0"+ ],+ "size": [+ "0.54",+ "0.64"+ ],+ "net": [+ "SERVO_OUT"+ ]+ },+ "2": {+ "at": [+ "0.51",+ "0"+ ],+ "size": [+ "0.54",+ "0.64"+ ],+ "net": [+ "GATE"+ ]+ }+ }+ }+ },+ {+ "ref": "U3",+ "before": {+ "at": [+ "129",+ "87"+ ],+ "pads": {+ "1": {+ "at": [+ "-1.1375",+ "-0.95"+ ],+ "size": [+ "1.325",+ "0.6"+ ],+ "net": [+ "SERVO_OUT"+ ]+ },+ "2": {+ "at": [+ "-1.1375",+ "0"+ ],+ "size": [+ "1.325",+ "0.6"+ ],+ "net": [+ "SHUNT_N_SENSE"+ ]+ },+ "3": {+ "at": [+ "-1.1375",+ "0.95"+ ],+ "size": [+ "1.325",+ "0.6"+ ],+ "net": [+ "I_SET"+ ]+ },+ "4": {+ "at": [+ "1.1375",+ "0.95"+ ],+ "size": [+ "1.325",+ "0.6"+ ],+ "net": [+ "SERVO_FB"+ ]+ },+ "5": {+ "at": [+ "1.1375",+ "-0.95"+ ],+ "size": [+ "1.325",+ "0.6"+ ],+ "net": [+ "V_GATE"+ ]+ }+ }+ },+ "after": {+ "at": [+ "129.3",+ "87"+ ],+ "pads": {+ "1": {+ "at": [+ "-1.1375",+ "-0.95"+ ],+ "size": [+ "1.325",+ "0.6"+ ],+ "net": [+ "SERVO_OUT"+ ]+ },+ "2": {+ "at": [+ "-1.1375",+ "0"+ ],+ "size": [+ "1.325",+ "0.6"+ ],+ "net": [+ "SHUNT_N_SENSE"+ ]+ },+ "3": {+ "at": [+ "-1.1375",+ "0.95"+ ],+ "size": [+ "1.325",+ "0.6"+ ],+ "net": [+ "I_SET"+ ]+ },+ "4": {+ "at": [+ "1.1375",+ "0.95"+ ],+ "size": [+ "1.325",+ "0.6"+ ],+ "net": [+ "SERVO_FB"+ ]+ },+ "5": {+ "at": [+ "1.1375",+ "-0.95"+ ],+ "size": [+ "1.325",+ "0.6"+ ],+ "net": [+ "V_GATE"+ ]+ }+ }+ }+ }+ ],+ "copperChanges": [+ {+ "uuid": "0698f584-2df0-479e-808e-687b3cb57a96",+ "before": {+ "kind": "segment",+ "start": [+ "123.5",+ "85.5"+ ],+ "end": [+ "123.6",+ "85.4"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_P_SENSE"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "123.5",+ "85.5"+ ],+ "end": [+ "123.3",+ "85.4"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_P_SENSE"+ ]+ }+ },+ {+ "uuid": "13d2f936-e4d3-40cb-9bf7-1b6b26ca4cf2",+ "before": {+ "kind": "segment",+ "start": [+ "126.4",+ "86.5"+ ],+ "end": [+ "126.35",+ "87"+ ],+ "width": [+ "1.2"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "126.4",+ "86.7"+ ],+ "end": [+ "126.35",+ "87"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ }+ },+ {+ "uuid": "1b8745ed-5e25-4c09-967f-7c78cd2514a2",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "139.4",+ "92"+ ],+ "end": [+ "138.4",+ "93"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ }+ },+ {+ "uuid": "24176a5c-806d-4462-b8fa-3f8435ffaa32",+ "before": {+ "kind": "segment",+ "start": [+ "132",+ "85.4"+ ],+ "end": [+ "134.1",+ "87.5"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P_SENSE"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "132.199999",+ "85.6"+ ],+ "end": [+ "134.1",+ "87.5"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P_SENSE"+ ]+ }+ },+ {+ "uuid": "2e78989f-e345-4946-a7c1-57779b596274",+ "before": null,+ "after": {+ "kind": "via",+ "at": [+ "133",+ "100.8"+ ],+ "size": [+ "0.8"+ ],+ "drill": [+ "0.4"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ }+ },+ {+ "uuid": "2f235494-7976-4048-be2d-b71507b2b45e",+ "before": {+ "kind": "segment",+ "start": [+ "124.9",+ "82.3"+ ],+ "end": [+ "124.92",+ "82"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "124.9",+ "82.3"+ ],+ "end": [+ "124.92",+ "82"+ ],+ "width": [+ "1.75"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ }+ },+ {+ "uuid": "30d9e8bc-805a-4b1d-8a79-ad625ee59388",+ "before": {+ "kind": "segment",+ "start": [+ "124.92",+ "82"+ ],+ "end": [+ "125.15",+ "83.4"+ ],+ "width": [+ "0.8"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ },+ "after": null+ },+ {+ "uuid": "32514162-b870-4c7a-95a2-b85b8db79257",+ "before": {+ "kind": "via",+ "at": [+ "126.4",+ "86.5"+ ],+ "size": [+ "0.8"+ ],+ "drill": [+ "0.4"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ },+ "after": {+ "kind": "via",+ "at": [+ "126.05",+ "86.7"+ ],+ "size": [+ "0.8"+ ],+ "drill": [+ "0.4"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ }+ },+ {+ "uuid": "32cd5f76-8c9c-4680-a071-fe4f71064f23",+ "before": {+ "kind": "segment",+ "start": [+ "134.4",+ "84.8"+ ],+ "end": [+ "133.8",+ "84.2"+ ],+ "width": [+ "1.2"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "134.4",+ "84.8"+ ],+ "end": [+ "133.8",+ "84.2"+ ],+ "width": [+ "1.6"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ }+ },+ {+ "uuid": "333e5fd1-7ad1-4b4f-8564-dfd172900763",+ "before": null,+ "after": {+ "kind": "via",+ "at": [+ "139.4",+ "92.4"+ ],+ "size": [+ "0.6"+ ],+ "drill": [+ "0.3"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ }+ },+ {+ "uuid": "34d3207a-b14a-40d8-be82-5b108c2b867b",+ "before": {+ "kind": "via",+ "at": [+ "134.4",+ "84.8"+ ],+ "size": [+ "0.8"+ ],+ "drill": [+ "0.4"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ },+ "after": null+ },+ {+ "uuid": "3a40c212-8d02-4e06-9bb1-5e98ca69b783",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "126.35",+ "87"+ ],+ "end": [+ "126.35",+ "89"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ }+ },+ {+ "uuid": "3e849937-6253-4e1c-b2c7-a04c3370eb1c",+ "before": {+ "kind": "via",+ "at": [+ "123.6",+ "85.4"+ ],+ "size": [+ "0.6"+ ],+ "drill": [+ "0.3"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "SHUNT_P_SENSE"+ ]+ },+ "after": {+ "kind": "via",+ "at": [+ "123.3",+ "85.4"+ ],+ "size": [+ "0.6"+ ],+ "drill": [+ "0.3"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "SHUNT_P_SENSE"+ ]+ }+ },+ {+ "uuid": "4abaae68-59a0-4ef4-9e3f-aeaedcbe08f1",+ "before": {+ "kind": "segment",+ "start": [+ "128",+ "87.3"+ ],+ "end": [+ "128.8",+ "87.3"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_N_SENSE"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "128",+ "87.3"+ ],+ "end": [+ "129",+ "87.3"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_N_SENSE"+ ]+ }+ },+ {+ "uuid": "689e5fa5-c40f-45f4-a9d1-ba5472dbf8db",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "127.46",+ "83.3"+ ],+ "end": [+ "126.4",+ "84.36"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ }+ },+ {+ "uuid": "6c1000f8-eec8-4f16-b335-3229825e1e47",+ "before": null,+ "after": {+ "kind": "via",+ "at": [+ "126.8",+ "86.7"+ ],+ "size": [+ "0.8"+ ],+ "drill": [+ "0.4"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ }+ },+ {+ "uuid": "79153970-5f91-4edb-a4de-378a4df9ef87",+ "before": null,+ "after": {+ "kind": "via",+ "at": [+ "139.8",+ "90.4"+ ],+ "size": [+ "0.6"+ ],+ "drill": [+ "0.3"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ }+ },+ {+ "uuid": "7bc77112-205b-436c-9c16-a56d708ff750",+ "before": null,+ "after": {+ "kind": "via",+ "at": [+ "136.5",+ "93"+ ],+ "size": [+ "1"+ ],+ "drill": [+ "0.6"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ }+ },+ {+ "uuid": "84135c5a-17c6-4a91-9d08-393fc99c1c14",+ "before": null,+ "after": {+ "kind": "via",+ "at": [+ "139",+ "90.4"+ ],+ "size": [+ "0.6"+ ],+ "drill": [+ "0.3"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ }+ },+ {+ "uuid": "898fb7bb-ebf6-4bbe-ada6-dd6d7720c0cb",+ "before": {+ "kind": "via",+ "at": [+ "139.4",+ "86.8"+ ],+ "size": [+ "0.8"+ ],+ "drill": [+ "0.4"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ },+ "after": null+ },+ {+ "uuid": "8e11aefd-5918-4bff-9845-de39db1d3f45",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "123",+ "89.7"+ ],+ "end": [+ "125.65",+ "89.7"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ }+ },+ {+ "uuid": "8e5d5e2b-78f3-4ed2-af96-409d2ea9d57b",+ "before": {+ "kind": "segment",+ "start": [+ "126.35",+ "89.7"+ ],+ "end": [+ "119.8",+ "89.7"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ },+ "after": null+ },+ {+ "uuid": "8e6911fa-13c2-4fb7-aa5f-cbbd280346f8",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "119.8",+ "89.7"+ ],+ "end": [+ "123",+ "89.7"+ ],+ "width": [+ "1.75"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ }+ },+ {+ "uuid": "8fc8b35b-e02e-45db-b56f-6ec45639d24a",+ "before": {+ "kind": "segment",+ "start": [+ "129.1",+ "87.6"+ ],+ "end": [+ "129.1",+ "88.6"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_N_SENSE"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "129.3",+ "87.6"+ ],+ "end": [+ "129.3",+ "88.6"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_N_SENSE"+ ]+ }+ },+ {+ "uuid": "91eed079-74e4-4863-8dc1-f211a19b6ee0",+ "before": {+ "kind": "segment",+ "start": [+ "126.4",+ "83.06"+ ],+ "end": [+ "126.4",+ "86.5"+ ],+ "width": [+ "1"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ },+ "after": null+ },+ {+ "uuid": "94453548-40be-40a1-9d0c-8bea6d271842",+ "before": null,+ "after": {+ "kind": "via",+ "at": [+ "139.4",+ "91.4"+ ],+ "size": [+ "0.6"+ ],+ "drill": [+ "0.3"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ }+ },+ {+ "uuid": "9a71af6b-ea83-4f97-b7f6-3f69253c7314",+ "before": {+ "kind": "via",+ "at": [+ "135",+ "85"+ ],+ "size": [+ "0.6"+ ],+ "drill": [+ "0.3"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ },+ "after": null+ },+ {+ "uuid": "9d9d8b15-9a37-4645-9d18-76ec6617ac6a",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "126.4",+ "84.36"+ ],+ "end": [+ "126.4",+ "86.7"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ }+ },+ {+ "uuid": "9f3de474-1934-4b7b-bcb4-a64c70a25453",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "133",+ "84.7"+ ],+ "end": [+ "134.7",+ "85.5"+ ],+ "width": [+ "1.2"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ }+ },+ {+ "uuid": "aa6c5964-74d4-410e-a69e-ffb2cd9c9999",+ "before": {+ "kind": "via",+ "at": [+ "133.8",+ "84.2"+ ],+ "size": [+ "0.8"+ ],+ "drill": [+ "0.4"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ },+ "after": {+ "kind": "via",+ "at": [+ "133.699999",+ "83.6"+ ],+ "size": [+ "0.8"+ ],+ "drill": [+ "0.4"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ }+ },+ {+ "uuid": "ad353074-a567-44a9-a20a-744b8057c5a9",+ "before": {+ "kind": "segment",+ "start": [+ "127.46",+ "82"+ ],+ "end": [+ "126.4",+ "83.06"+ ],+ "width": [+ "1.2"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ },+ "after": null+ },+ {+ "uuid": "b0be4552-5079-4f48-9af6-897111d684aa",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "126.35",+ "89"+ ],+ "end": [+ "126.35",+ "89.7"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ }+ },+ {+ "uuid": "b486fb59-b64e-41ee-a1a7-5a72fcf0a780",+ "before": {+ "kind": "segment",+ "start": [+ "126.35",+ "87"+ ],+ "end": [+ "126.35",+ "89.7"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ },+ "after": null+ },+ {+ "uuid": "b5aa4e9c-8aa1-444b-b685-388c1edaa7c9",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "139.4",+ "90.4"+ ],+ "end": [+ "139.4",+ "92"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ }+ },+ {+ "uuid": "c0de0369-7fd9-46e7-97ef-a914aedc0e9f",+ "before": {+ "kind": "segment",+ "start": [+ "123.6",+ "85.4"+ ],+ "end": [+ "132",+ "85.4"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P_SENSE"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "123.3",+ "85.6"+ ],+ "end": [+ "132.199999",+ "85.6"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P_SENSE"+ ]+ }+ },+ {+ "uuid": "c3fefd84-b213-453e-a4c1-1872b958a7e3",+ "before": null,+ "after": {+ "kind": "via",+ "at": [+ "139",+ "93"+ ],+ "size": [+ "0.8"+ ],+ "drill": [+ "0.4"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ }+ },+ {+ "uuid": "c9f172f9-19b5-4d52-9cb2-d585686e91b6",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "138.4",+ "93"+ ],+ "end": [+ "136.5",+ "93"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ }+ },+ {+ "uuid": "ca44bc38-8c76-4b55-947c-921ba9ed0482",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "126.35",+ "89"+ ],+ "end": [+ "125.65",+ "89.7"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ }+ },+ {+ "uuid": "ca660f66-f997-4d04-8a34-eee1e53505d1",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "126.35",+ "89.7"+ ],+ "end": [+ "125.65",+ "89.7"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ }+ },+ {+ "uuid": "cd48c727-15bf-4276-b4b8-ae4d936d829d",+ "before": {+ "kind": "via",+ "at": [+ "125.15",+ "83.4"+ ],+ "size": [+ "0.6"+ ],+ "drill": [+ "0.3"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ },+ "after": null+ },+ {+ "uuid": "cecc8caa-bb93-470d-a793-50ae2c93732f",+ "before": {+ "kind": "segment",+ "start": [+ "134.4",+ "84.8"+ ],+ "end": [+ "135.4317",+ "85.8317"+ ],+ "width": [+ "1.2"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "134.4",+ "84.8"+ ],+ "end": [+ "135.4317",+ "85.8317"+ ],+ "width": [+ "1.6"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ }+ },+ {+ "uuid": "d992c300-f09d-49e7-9dde-c2ae4917d635",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "127.46",+ "82"+ ],+ "end": [+ "127.46",+ "83.3"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "LOAD_POS"+ ]+ }+ },+ {+ "uuid": "daccf8f3-fa70-46a6-bf04-fecfe4368e61",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "133.699999",+ "83.6"+ ],+ "end": [+ "133.8",+ "84.2"+ ],+ "width": [+ "1.2"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ }+ },+ {+ "uuid": "db6b0745-1575-4d1f-ade0-c076147bd7f9",+ "before": {+ "kind": "segment",+ "start": [+ "128.8",+ "87.3"+ ],+ "end": [+ "129.1",+ "87.6"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_N_SENSE"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "129",+ "87.3"+ ],+ "end": [+ "129.3",+ "87.6"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_N_SENSE"+ ]+ }+ },+ {+ "uuid": "df518747-a905-4088-afc1-956ab121c431",+ "before": null,+ "after": {+ "kind": "via",+ "at": [+ "138",+ "100.8"+ ],+ "size": [+ "0.8"+ ],+ "drill": [+ "0.4"+ ],+ "layers": [+ "F.Cu",+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ }+ },+ {+ "uuid": "e331836e-4eff-4040-be8e-0505e6e90842",+ "before": null,+ "after": {+ "kind": "segment",+ "start": [+ "139",+ "90.4"+ ],+ "end": [+ "139.8",+ "90.4"+ ],+ "width": [+ "1.2"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "GND"+ ]+ }+ },+ {+ "uuid": "ec56cc46-09f5-4ff9-a1b6-61699db68686",+ "before": {+ "kind": "segment",+ "start": [+ "126.5",+ "84"+ ],+ "end": [+ "124.9",+ "82.3"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "126.5",+ "84"+ ],+ "end": [+ "124.9",+ "82.3"+ ],+ "width": [+ "1.75"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ }+ },+ {+ "uuid": "f120f8db-288f-4938-acbf-98ff5e4065df",+ "before": {+ "kind": "segment",+ "start": [+ "133.5",+ "84"+ ],+ "end": [+ "126.5",+ "84"+ ],+ "width": [+ "1.5"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "133.5",+ "84.25"+ ],+ "end": [+ "126.8",+ "84.25"+ ],+ "width": [+ "2"+ ],+ "layer": [+ "B.Cu"+ ],+ "net": [+ "SHUNT_P"+ ]+ }+ },+ {+ "uuid": "f29acf3e-748d-407f-92e0-ec0544f3474e",+ "before": {+ "kind": "segment",+ "start": [+ "129.3",+ "88.8"+ ],+ "end": [+ "130",+ "88.8"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_N_SENSE"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "129.5",+ "88.8"+ ],+ "end": [+ "130",+ "88.8"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_N_SENSE"+ ]+ }+ },+ {+ "uuid": "f69214e6-434b-473f-b017-0dd038575d19",+ "before": {+ "kind": "segment",+ "start": [+ "129.1",+ "88.6"+ ],+ "end": [+ "129.3",+ "88.8"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_N_SENSE"+ ]+ },+ "after": {+ "kind": "segment",+ "start": [+ "129.3",+ "88.6"+ ],+ "end": [+ "129.5",+ "88.8"+ ],+ "width": [+ "0.25"+ ],+ "layer": [+ "F.Cu"+ ],+ "net": [+ "SHUNT_N_SENSE"+ ]+ }+ }+ ],+ "note": "All track/via changes inventoried by saved UUID. Native net invariant additionally checks newly created copper before and after connectivity/fill/save. Zone fill geometry and placement still require visual/native review."+}
checkpoints/unclipped-hotspots-v1/drc-v30.jsonadded+36@@ -0,0 +1,36 @@+{ + "$schema": "https://schemas.kicad.org/drc.v1.json", + "coordinate_units": "mm", + "date": "2026-10-10T07:57:21", + "ignored_checks": [ + { + "description": "Footprint has no courtyard defined", + "key": "missing_courtyard" + }, + { + "description": "Track endpoint not centered on via", + "key": "track_not_centered_on_via" + }, + { + "description": "Tuning profile track geometries", + "key": "tuning_profile_track_geometries" + }, + { + "description": "Footprint doesn't match symbol's footprint filters", + "key": "footprint_filters_mismatch" + }, + { + "description": "Footprint component type doesn't match footprint pads", + "key": "footprint_type_mismatch" + } + ], + "included_severities": [ + "error", + "warning" + ], + "kicad_version": "10.0.5", + "schematic_parity": [], + "source": "candidate-v30.kicad_pcb", + "unconnected_items": [], + "violations": [] +}
design/hotspot-v30-landing-plan.jsonadded+1214@@ -0,0 +1,1214 @@+{+ "status": "DO NOT EXECUTE: fine-mesh and full engineering acceptance pending",+ "sourceBoard": "aiflow/run/board-19.kicad_pcb",+ "sourceSha256": "54f1aab0a34622d1c3675c13f4aeb7a678b0cee8b5a4d3bfd7484b10edb8dcf6",+ "candidate": "checkpoints/unclipped-hotspots-v1/candidate-v30.kicad_pcb",+ "candidateSha256": "0b4dacf6b7ac07cca64edf604c6f662ca7d5321a9035d72424f262f6cf507549",+ "expectedLiveRevision": "3213474890590f6f65d1603120ae19fabb7590241498da6d85c4736062ff51cc",+ "removeCopperIds": [+ "0698f584-2df0-479e-808e-687b3cb57a96",+ "24176a5c-806d-4462-b8fa-3f8435ffaa32",+ "c0de0369-7fd9-46e7-97ef-a914aedc0e9f",+ "30d9e8bc-805a-4b1d-8a79-ad625ee59388",+ "2f235494-7976-4048-be2d-b71507b2b45e",+ "32cd5f76-8c9c-4680-a071-fe4f71064f23",+ "cecc8caa-bb93-470d-a793-50ae2c93732f",+ "ec56cc46-09f5-4ff9-a1b6-61699db68686",+ "f120f8db-288f-4938-acbf-98ff5e4065df",+ "4abaae68-59a0-4ef4-9e3f-aeaedcbe08f1",+ "8fc8b35b-e02e-45db-b56f-6ec45639d24a",+ "db6b0745-1575-4d1f-ade0-c076147bd7f9",+ "f29acf3e-748d-407f-92e0-ec0544f3474e",+ "f69214e6-434b-473f-b017-0dd038575d19",+ "91eed079-74e4-4863-8dc1-f211a19b6ee0",+ "ad353074-a567-44a9-a20a-744b8057c5a9",+ "13d2f936-e4d3-40cb-9bf7-1b6b26ca4cf2",+ "8e5d5e2b-78f3-4ed2-af96-409d2ea9d57b",+ "b486fb59-b64e-41ee-a1a7-5a72fcf0a780",+ "898fb7bb-ebf6-4bbe-ada6-dd6d7720c0cb",+ "3e849937-6253-4e1c-b2c7-a04c3370eb1c",+ "34d3207a-b14a-40d8-be82-5b108c2b867b",+ "9a71af6b-ea83-4f97-b7f6-3f69253c7314",+ "aa6c5964-74d4-410e-a69e-ffb2cd9c9999",+ "cd48c727-15bf-4276-b4b8-ae4d936d829d",+ "32514162-b870-4c7a-95a2-b85b8db79257"+ ],+ "moveFootprints": [+ {+ "ref": "U3",+ "x": 129.3,+ "y": 87.0,+ "rotation": 0+ },+ {+ "ref": "Q2",+ "x": 123.7,+ "y": 85.3,+ "rotation": 0+ },+ {+ "ref": "R7",+ "x": 129.1,+ "y": 84.0,+ "rotation": 0+ }+ ],+ "routes": [+ {+ "net": "GND",+ "layer": "B.Cu",+ "width": 1.2,+ "paths": [+ [+ [+ 139.0,+ 90.4+ ],+ [+ 139.8,+ 90.4+ ]+ ]+ ],+ "validate": false+ },+ {+ "net": "GND",+ "layer": "B.Cu",+ "width": 1.5,+ "paths": [+ [+ [+ 139.4,+ 92.0+ ],+ [+ 138.4,+ 93.0+ ]+ ],+ [+ [+ 139.4,+ 90.4+ ],+ [+ 139.4,+ 92.0+ ]+ ],+ [+ [+ 138.4,+ 93.0+ ],+ [+ 136.5,+ 93.0+ ]+ ]+ ],+ "validate": false+ },+ {+ "net": "GND",+ "layer": "F.Cu",+ "width": 0.25,+ "paths": [+ [+ [+ 139.4,+ 92.4+ ],+ {+ "x": 139.4,+ "y": 92.4,+ "layer": "B.Cu"+ }+ ],+ [+ [+ 139.8,+ 90.4+ ],+ {+ "x": 139.8,+ "y": 90.4,+ "layer": "B.Cu"+ }+ ],+ [+ [+ 139.0,+ 90.4+ ],+ {+ "x": 139.0,+ "y": 90.4,+ "layer": "B.Cu"+ }+ ],+ [+ [+ 139.4,+ 91.4+ ],+ {+ "x": 139.4,+ "y": 91.4,+ "layer": "B.Cu"+ }+ ]+ ],+ "validate": false,+ "viaSize": 0.6,+ "viaDrill": 0.3+ },+ {+ "net": "GND",+ "layer": "F.Cu",+ "width": 0.25,+ "paths": [+ [+ [+ 133.0,+ 100.8+ ],+ {+ "x": 133.0,+ "y": 100.8,+ "layer": "B.Cu"+ }+ ],+ [+ [+ 139.0,+ 93.0+ ],+ {+ "x": 139.0,+ "y": 93.0,+ "layer": "B.Cu"+ }+ ],+ [+ [+ 138.0,+ 100.8+ ],+ {+ "x": 138.0,+ "y": 100.8,+ "layer": "B.Cu"+ }+ ]+ ],+ "validate": false,+ "viaSize": 0.8,+ "viaDrill": 0.4+ },+ {+ "net": "GND",+ "layer": "F.Cu",+ "width": 0.25,+ "paths": [+ [+ [+ 136.5,+ 93.0+ ],+ {+ "x": 136.5,+ "y": 93.0,+ "layer": "B.Cu"+ }+ ]+ ],+ "validate": false,+ "viaSize": 1.0,+ "viaDrill": 0.6+ },+ {+ "net": "LOAD_POS",+ "layer": "B.Cu",+ "width": 1.5,+ "paths": [+ [+ [+ 126.4,+ 86.7+ ],+ [+ 126.35,+ 87.0+ ]+ ],+ [+ [+ 126.35,+ 87.0+ ],+ [+ 126.35,+ 89.0+ ]+ ],+ [+ [+ 123.0,+ 89.7+ ],+ [+ 125.65,+ 89.7+ ]+ ],+ [+ [+ 126.35,+ 89.0+ ],+ [+ 126.35,+ 89.7+ ]+ ],+ [+ [+ 126.35,+ 89.0+ ],+ [+ 125.65,+ 89.7+ ]+ ],+ [+ [+ 126.35,+ 89.7+ ],+ [+ 125.65,+ 89.7+ ]+ ]+ ],+ "validate": false+ },+ {+ "net": "LOAD_POS",+ "layer": "B.Cu",+ "width": 1.75,+ "paths": [+ [+ [+ 119.8,+ 89.7+ ],+ [+ 123.0,+ 89.7+ ]+ ]+ ],+ "validate": false+ },+ {+ "net": "LOAD_POS",+ "layer": "F.Cu",+ "width": 0.25,+ "paths": [+ [+ [+ 126.05,+ 86.7+ ],+ {+ "x": 126.05,+ "y": 86.7,+ "layer": "B.Cu"+ }+ ],+ [+ [+ 126.8,+ 86.7+ ],+ {+ "x": 126.8,+ "y": 86.7,+ "layer": "B.Cu"+ }+ ]+ ],+ "validate": false,+ "viaSize": 0.8,+ "viaDrill": 0.4+ },+ {+ "net": "LOAD_POS",+ "layer": "F.Cu",+ "width": 1.5,+ "paths": [+ [+ [+ 127.46,+ 83.3+ ],+ [+ 126.4,+ 84.36+ ]+ ],+ [+ [+ 126.4,+ 84.36+ ],+ [+ 126.4,+ 86.7+ ]+ ],+ [+ [+ 127.46,+ 82.0+ ],+ [+ 127.46,+ 83.3+ ]+ ]+ ],+ "validate": false+ },+ {+ "net": "SHUNT_N_SENSE",+ "layer": "F.Cu",+ "width": 0.25,+ "paths": [+ [+ [+ 128.0,+ 87.3+ ],+ [+ 129.0,+ 87.3+ ]+ ],+ [+ [+ 129.3,+ 87.6+ ],+ [+ 129.3,+ 88.6+ ]+ ],+ [+ [+ 129.0,+ 87.3+ ],+ [+ 129.3,+ 87.6+ ]+ ],+ [+ [+ 129.5,+ 88.8+ ],+ [+ 130.0,+ 88.8+ ]+ ],+ [+ [+ 129.3,+ 88.6+ ],+ [+ 129.5,+ 88.8+ ]+ ]+ ],+ "validate": false+ },+ {+ "net": "SHUNT_P",+ "layer": "B.Cu",+ "width": 1.2,+ "paths": [+ [+ [+ 133.0,+ 84.7+ ],+ [+ 134.7,+ 85.5+ ]+ ]+ ],+ "validate": false+ },+ {+ "net": "SHUNT_P",+ "layer": "B.Cu",+ "width": 1.6,+ "paths": [+ [+ [+ 134.4,+ 84.8+ ],+ [+ 133.8,+ 84.2+ ]+ ],+ [+ [+ 134.4,+ 84.8+ ],+ [+ 135.4317,+ 85.8317+ ]+ ]+ ],+ "validate": false+ },+ {+ "net": "SHUNT_P",+ "layer": "B.Cu",+ "width": 1.75,+ "paths": [+ [+ [+ 124.9,+ 82.3+ ],+ [+ 124.92,+ 82.0+ ]+ ],+ [+ [+ 126.5,+ 84.0+ ],+ [+ 124.9,+ 82.3+ ]+ ]+ ],+ "validate": false+ },+ {+ "net": "SHUNT_P",+ "layer": "B.Cu",+ "width": 2.0,+ "paths": [+ [+ [+ 133.5,+ 84.25+ ],+ [+ 126.8,+ 84.25+ ]+ ]+ ],+ "validate": false+ },+ {+ "net": "SHUNT_P",+ "layer": "F.Cu",+ "width": 0.25,+ "paths": [+ [+ [+ 133.699999,+ 83.6+ ],+ {+ "x": 133.699999,+ "y": 83.6,+ "layer": "B.Cu"+ }+ ]+ ],+ "validate": false,+ "viaSize": 0.8,+ "viaDrill": 0.4+ },+ {+ "net": "SHUNT_P",+ "layer": "F.Cu",+ "width": 1.2,+ "paths": [+ [+ [+ 133.699999,+ 83.6+ ],+ [+ 133.8,+ 84.2+ ]+ ]+ ],+ "validate": false+ },+ {+ "net": "SHUNT_P_SENSE",+ "layer": "B.Cu",+ "width": 0.25,+ "paths": [+ [+ [+ 132.199999,+ 85.6+ ],+ [+ 134.1,+ 87.5+ ]+ ],+ [+ [+ 123.3,+ 85.6+ ],+ [+ 132.199999,+ 85.6+ ]+ ]+ ],+ "validate": false+ },+ {+ "net": "SHUNT_P_SENSE",+ "layer": "F.Cu",+ "width": 0.25,+ "paths": [+ [+ [+ 123.3,+ 85.4+ ],+ {+ "x": 123.3,+ "y": 85.4,+ "layer": "B.Cu"+ }+ ]+ ],+ "validate": false,+ "viaSize": 0.6,+ "viaDrill": 0.3+ },+ {+ "net": "SHUNT_P_SENSE",+ "layer": "F.Cu",+ "width": 0.25,+ "paths": [+ [+ [+ 123.5,+ 85.5+ ],+ [+ 123.3,+ 85.4+ ]+ ]+ ],+ "validate": false+ }+ ],+ "zoneDefinitionsUnchanged": true,+ "addedCopper": [+ {+ "kind": "segment",+ "net": "GND",+ "layer": "B.Cu",+ "width": 1.5,+ "start": [+ 139.4,+ 92.0+ ],+ "end": [+ 138.4,+ 93.0+ ],+ "uuid": "1b8745ed-5e25-4c09-967f-7c78cd2514a2"+ },+ {+ "kind": "segment",+ "net": "GND",+ "layer": "B.Cu",+ "width": 1.5,+ "start": [+ 139.4,+ 90.4+ ],+ "end": [+ 139.4,+ 92.0+ ],+ "uuid": "b5aa4e9c-8aa1-444b-b685-388c1edaa7c9"+ },+ {+ "kind": "segment",+ "net": "GND",+ "layer": "B.Cu",+ "width": 1.5,+ "start": [+ 138.4,+ 93.0+ ],+ "end": [+ 136.5,+ 93.0+ ],+ "uuid": "c9f172f9-19b5-4d52-9cb2-d585686e91b6"+ },+ {+ "kind": "segment",+ "net": "GND",+ "layer": "B.Cu",+ "width": 1.2,+ "start": [+ 139.0,+ 90.4+ ],+ "end": [+ 139.8,+ 90.4+ ],+ "uuid": "e331836e-4eff-4040-be8e-0505e6e90842"+ },+ {+ "kind": "segment",+ "net": "SHUNT_P_SENSE",+ "layer": "F.Cu",+ "width": 0.25,+ "start": [+ 123.5,+ 85.5+ ],+ "end": [+ 123.3,+ 85.4+ ],+ "uuid": "0698f584-2df0-479e-808e-687b3cb57a96"+ },+ {+ "kind": "segment",+ "net": "SHUNT_P_SENSE",+ "layer": "B.Cu",+ "width": 0.25,+ "start": [+ 132.199999,+ 85.6+ ],+ "end": [+ 134.1,+ 87.5+ ],+ "uuid": "24176a5c-806d-4462-b8fa-3f8435ffaa32"+ },+ {+ "kind": "segment",+ "net": "SHUNT_P_SENSE",+ "layer": "B.Cu",+ "width": 0.25,+ "start": [+ 123.3,+ 85.6+ ],+ "end": [+ 132.199999,+ 85.6+ ],+ "uuid": "c0de0369-7fd9-46e7-97ef-a914aedc0e9f"+ },+ {+ "kind": "segment",+ "net": "SHUNT_P",+ "layer": "F.Cu",+ "width": 1.2,+ "start": [+ 133.699999,+ 83.6+ ],+ "end": [+ 133.8,+ 84.2+ ],+ "uuid": "daccf8f3-fa70-46a6-bf04-fecfe4368e61"+ },+ {+ "kind": "segment",+ "net": "SHUNT_P",+ "layer": "B.Cu",+ "width": 1.75,+ "start": [+ 124.9,+ 82.3+ ],+ "end": [+ 124.92,+ 82.0+ ],+ "uuid": "2f235494-7976-4048-be2d-b71507b2b45e"+ },+ {+ "kind": "segment",+ "net": "SHUNT_P",+ "layer": "B.Cu",+ "width": 1.6,+ "start": [+ 134.4,+ 84.8+ ],+ "end": [+ 133.8,+ 84.2+ ],+ "uuid": "32cd5f76-8c9c-4680-a071-fe4f71064f23"+ },+ {+ "kind": "segment",+ "net": "SHUNT_P",+ "layer": "B.Cu",+ "width": 1.2,+ "start": [+ 133.0,+ 84.7+ ],+ "end": [+ 134.7,+ 85.5+ ],+ "uuid": "9f3de474-1934-4b7b-bcb4-a64c70a25453"+ },+ {+ "kind": "segment",+ "net": "SHUNT_P",+ "layer": "B.Cu",+ "width": 1.6,+ "start": [+ 134.4,+ 84.8+ ],+ "end": [+ 135.4317,+ 85.8317+ ],+ "uuid": "cecc8caa-bb93-470d-a793-50ae2c93732f"+ },+ {+ "kind": "segment",+ "net": "SHUNT_P",+ "layer": "B.Cu",+ "width": 1.75,+ "start": [+ 126.5,+ 84.0+ ],+ "end": [+ 124.9,+ 82.3+ ],+ "uuid": "ec56cc46-09f5-4ff9-a1b6-61699db68686"+ },+ {+ "kind": "segment",+ "net": "SHUNT_P",+ "layer": "B.Cu",+ "width": 2.0,+ "start": [+ 133.5,+ 84.25+ ],+ "end": [+ 126.8,+ 84.25+ ],+ "uuid": "f120f8db-288f-4938-acbf-98ff5e4065df"+ },+ {+ "kind": "segment",+ "net": "SHUNT_N_SENSE",+ "layer": "F.Cu",+ "width": 0.25,+ "start": [+ 128.0,+ 87.3+ ],+ "end": [+ 129.0,+ 87.3+ ],+ "uuid": "4abaae68-59a0-4ef4-9e3f-aeaedcbe08f1"+ },+ {+ "kind": "segment",+ "net": "SHUNT_N_SENSE",+ "layer": "F.Cu",+ "width": 0.25,+ "start": [+ 129.3,+ 87.6+ ],+ "end": [+ 129.3,+ 88.6+ ],+ "uuid": "8fc8b35b-e02e-45db-b56f-6ec45639d24a"+ },+ {+ "kind": "segment",+ "net": "SHUNT_N_SENSE",+ "layer": "F.Cu",+ "width": 0.25,+ "start": [+ 129.0,+ 87.3+ ],+ "end": [+ 129.3,+ 87.6+ ],+ "uuid": "db6b0745-1575-4d1f-ade0-c076147bd7f9"+ },+ {+ "kind": "segment",+ "net": "SHUNT_N_SENSE",+ "layer": "F.Cu",+ "width": 0.25,+ "start": [+ 129.5,+ 88.8+ ],+ "end": [+ 130.0,+ 88.8+ ],+ "uuid": "f29acf3e-748d-407f-92e0-ec0544f3474e"+ },+ {+ "kind": "segment",+ "net": "SHUNT_N_SENSE",+ "layer": "F.Cu",+ "width": 0.25,+ "start": [+ 129.3,+ 88.6+ ],+ "end": [+ 129.5,+ 88.8+ ],+ "uuid": "f69214e6-434b-473f-b017-0dd038575d19"+ },+ {+ "kind": "segment",+ "net": "LOAD_POS",+ "layer": "F.Cu",+ "width": 1.5,+ "start": [+ 127.46,+ 83.3+ ],+ "end": [+ 126.4,+ 84.36+ ],+ "uuid": "689e5fa5-c40f-45f4-a9d1-ba5472dbf8db"+ },+ {+ "kind": "segment",+ "net": "LOAD_POS",+ "layer": "F.Cu",+ "width": 1.5,+ "start": [+ 126.4,+ 84.36+ ],+ "end": [+ 126.4,+ 86.7+ ],+ "uuid": "9d9d8b15-9a37-4645-9d18-76ec6617ac6a"+ },+ {+ "kind": "segment",+ "net": "LOAD_POS",+ "layer": "F.Cu",+ "width": 1.5,+ "start": [+ 127.46,+ 82.0+ ],+ "end": [+ 127.46,+ 83.3+ ],+ "uuid": "d992c300-f09d-49e7-9dde-c2ae4917d635"+ },+ {+ "kind": "segment",+ "net": "LOAD_POS",+ "layer": "B.Cu",+ "width": 1.5,+ "start": [+ 126.4,+ 86.7+ ],+ "end": [+ 126.35,+ 87.0+ ],+ "uuid": "13d2f936-e4d3-40cb-9bf7-1b6b26ca4cf2"+ },+ {+ "kind": "segment",+ "net": "LOAD_POS",+ "layer": "B.Cu",+ "width": 1.5,+ "start": [+ 126.35,+ 87.0+ ],+ "end": [+ 126.35,+ 89.0+ ],+ "uuid": "3a40c212-8d02-4e06-9bb1-5e98ca69b783"+ },+ {+ "kind": "segment",+ "net": "LOAD_POS",+ "layer": "B.Cu",+ "width": 1.5,+ "start": [+ 123.0,+ 89.7+ ],+ "end": [+ 125.65,+ 89.7+ ],+ "uuid": "8e11aefd-5918-4bff-9845-de39db1d3f45"+ },+ {+ "kind": "segment",+ "net": "LOAD_POS",+ "layer": "B.Cu",+ "width": 1.75,+ "start": [+ 119.8,+ 89.7+ ],+ "end": [+ 123.0,+ 89.7+ ],+ "uuid": "8e6911fa-13c2-4fb7-aa5f-cbbd280346f8"+ },+ {+ "kind": "segment",+ "net": "LOAD_POS",+ "layer": "B.Cu",+ "width": 1.5,+ "start": [+ 126.35,+ 89.0+ ],+ "end": [+ 126.35,+ 89.7+ ],+ "uuid": "b0be4552-5079-4f48-9af6-897111d684aa"+ },+ {+ "kind": "segment",+ "net": "LOAD_POS",+ "layer": "B.Cu",+ "width": 1.5,+ "start": [+ 126.35,+ 89.0+ ],+ "end": [+ 125.65,+ 89.7+ ],+ "uuid": "ca44bc38-8c76-4b55-947c-921ba9ed0482"+ },+ {+ "kind": "segment",+ "net": "LOAD_POS",+ "layer": "B.Cu",+ "width": 1.5,+ "start": [+ 126.35,+ 89.7+ ],+ "end": [+ 125.65,+ 89.7+ ],+ "uuid": "ca660f66-f997-4d04-8a34-eee1e53505d1"+ },+ {+ "kind": "via",+ "net": "GND",+ "size": 0.8,+ "drill": 0.4,+ "at": [+ 133.0,+ 100.8+ ],+ "uuid": "2e78989f-e345-4946-a7c1-57779b596274"+ },+ {+ "kind": "via",+ "net": "GND",+ "size": 0.6,+ "drill": 0.3,+ "at": [+ 139.4,+ 92.4+ ],+ "uuid": "333e5fd1-7ad1-4b4f-8564-dfd172900763"+ },+ {+ "kind": "via",+ "net": "GND",+ "size": 0.6,+ "drill": 0.3,+ "at": [+ 139.8,+ 90.4+ ],+ "uuid": "79153970-5f91-4edb-a4de-378a4df9ef87"+ },+ {+ "kind": "via",+ "net": "GND",+ "size": 1.0,+ "drill": 0.6,+ "at": [+ 136.5,+ 93.0+ ],+ "uuid": "7bc77112-205b-436c-9c16-a56d708ff750"+ },+ {+ "kind": "via",+ "net": "GND",+ "size": 0.6,+ "drill": 0.3,+ "at": [+ 139.0,+ 90.4+ ],+ "uuid": "84135c5a-17c6-4a91-9d08-393fc99c1c14"+ },+ {+ "kind": "via",+ "net": "GND",+ "size": 0.6,+ "drill": 0.3,+ "at": [+ 139.4,+ 91.4+ ],+ "uuid": "94453548-40be-40a1-9d0c-8bea6d271842"+ },+ {+ "kind": "via",+ "net": "GND",+ "size": 0.8,+ "drill": 0.4,+ "at": [+ 139.0,+ 93.0+ ],+ "uuid": "c3fefd84-b213-453e-a4c1-1872b958a7e3"+ },+ {+ "kind": "via",+ "net": "GND",+ "size": 0.8,+ "drill": 0.4,+ "at": [+ 138.0,+ 100.8+ ],+ "uuid": "df518747-a905-4088-afc1-956ab121c431"+ },+ {+ "kind": "via",+ "net": "SHUNT_P_SENSE",+ "size": 0.6,+ "drill": 0.3,+ "at": [+ 123.3,+ 85.4+ ],+ "uuid": "3e849937-6253-4e1c-b2c7-a04c3370eb1c"+ },+ {+ "kind": "via",+ "net": "SHUNT_P",+ "size": 0.8,+ "drill": 0.4,+ "at": [+ 133.699999,+ 83.6+ ],+ "uuid": "aa6c5964-74d4-410e-a69e-ffb2cd9c9999"+ },+ {+ "kind": "via",+ "net": "LOAD_POS",+ "size": 0.8,+ "drill": 0.4,+ "at": [+ 126.05,+ 86.7+ ],+ "uuid": "32514162-b870-4c7a-95a2-b85b8db79257"+ },+ {+ "kind": "via",+ "net": "LOAD_POS",+ "size": 0.8,+ "drill": 0.4,+ "at": [+ 126.8,+ 86.7+ ],+ "uuid": "6c1000f8-eec8-4f16-b335-3229825e1e47"+ }+ ]+}
docs/completion-plan.md+4@@ -1,3 +1,7 @@+## Latest continuation — v30 fine mesh running++V27 failed 0.1 mm with GND 72.94, LOAD_POS 60.66 and SHUNT_P 70.56 A/mm2. V29 splits the return transfer and widens the two necks; v30 additionally fills the inside shunt bend. V30 passes native DRC 0/0/0 and the 0.2 mm three-net screen. Fresh v29/v30 fine solves are running. V30 plan is prepared but marked DO NOT EXECUTE; zone definitions and existing copper nets are unchanged. Installed AIFlow 0.1.81 correctly rejects the v27 fine result in an isolated CLI regression. The new current-map review clip brings raw takes to 70; storyboard now has 13 clips. Live board unchanged, current and thermal gates open.+ ## Current checkpoint — corrected plated-wall model, candidate v27 AIFlow 0.1.81 is source-pushed, registry-published and installed here; 130 tests and workflow checks pass. Fields PR9 remains under owner review and shared Fields is unchanged. Candidate v27 has zero native DRC errors, opens and warnings with actual project libraries present; complete diff has 44 copper changes, Q2/R7/U3 moves and zero existing copper net changes. Corrected 0.2 mm GND/LOAD_POS/SHUNT_P peaks are 50.70/57.68/59.67 A/mm2. The 0.1 mm refinement is running. Live board unchanged; current and thermal acceptance remain open. Continue engineering rather than stopping at this checkpoint.
docs/reverse-protection-alternative.mdadded+9@@ -0,0 +1,9 @@+# Lower-loss reverse-polarity candidate — not adopted++The corrected diode-only attribution solve still predicts D1 copper rise of 107.6 C in still air and 82.7 C with the model moving-air coefficient, at 1.65 W. This is an isolated diagnostic, not the operating thermal model.++DMP6023LE-13 is a possible SOT223 P-channel replacement circuit: 60 V, 28 mΩ maximum at −10 V gate drive and 35 mΩ at −4.5 V. At 3 A these imply 0.252 W and 0.315 W respectively at the datasheet test condition. Its 60 K/W ambient figure uses a 1-inch-square, 2 oz test board and must not be transferred to this PCB. The available sheet is marked advance information; obtain current qualified documentation before selection. [Manufacturer datasheet](https://www.diodes.com/datasheet/download/DMP6023LE.pdf).++This would require a new circuit, not a diode footprint substitution: verify body-diode direction, add a source-to-gate clamp and a gate pull-down for the 24 V input, assess startup and low-voltage behavior, then regenerate the schematic, component assets, BOM, board and tests. A single MOSFET does not guarantee reverse-current blocking while enabled. Temperature-dependent resistance, fault operation, stock and cost remain unverified. No part has been purchased or added to the board.++Keep the existing diode until a complete comparison justifies the change. More copper or an engineered heat path remain alternatives.
tools/hotspot_via_candidate_v28.pyadded+134@@ -0,0 +1,134 @@+"""Run using native desktop KiCad Python; modifies only an isolated board copy."""+import pcbnew,sys,json+from pathlib import Path+source=Path(sys.argv[1]);out=Path(sys.argv[2]);board=pcbnew.LoadBoard(str(source));nets=board.GetNetsByName()+changes=[]+for net,x,y in [('GND',133.0,100.8),('GND',138.0,100.8),('GND',139.0,93.0),('GND',136.5,93.0),('GND',139.4,90.4),('GND',139.4,91.4),('GND',139.4,92.4)]:+ via=pcbnew.PCB_VIA(board);via.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(x),pcbnew.FromMM(y)));via.SetWidth(pcbnew.FromMM(.8));via.SetDrill(pcbnew.FromMM(.4));via.SetLayerPair(pcbnew.F_Cu,pcbnew.B_Cu);via.SetNet(nets[net]);board.Add(via);changes.append({'kind':'via','net':net,'at':[x,y],'sizeMm':.8,'drillMm':.4,'uuid':str(via.m_Uuid.AsString())})+for item in board.GetTracks():+ uid=str(item.m_Uuid.AsString())+ if uid=='32514162-b870-4c7a-95a2-b85b8db79257':+ item.SetWidth(pcbnew.FromMM(1.0));item.SetDrill(pcbnew.FromMM(.6));changes.append({'kind':'resize-via','uuid':uid,'net':'LOAD_POS','sizeMm':1.0,'drillMm':.6})+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid in ['91eed079-74e4-4863-8dc1-f211a19b6ee0','ad353074-a567-44a9-a20a-744b8057c5a9']:+ board.Remove(item);changes.append({'kind':'remove-track','uuid':uid})+ if uid=='aa6c5964-74d4-410e-a69e-ffb2cd9c9999':+ item.SetWidth(pcbnew.FromMM(1.0));item.SetDrill(pcbnew.FromMM(.6));changes.append({'kind':'resize-via','uuid':uid,'sizeMm':1.0,'drillMm':.6})+def track(net,layer,a,b,width):+ t=pcbnew.PCB_TRACK(board);t.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(a[0]),pcbnew.FromMM(a[1])));t.SetEnd(pcbnew.VECTOR2I(pcbnew.FromMM(b[0]),pcbnew.FromMM(b[1])));t.SetWidth(pcbnew.FromMM(width));t.SetLayer(layer);t.SetNet(nets[net]);board.Add(t);changes.append({'kind':'track','net':net,'start':a,'end':b,'widthMm':width,'layer':board.GetLayerName(layer)})+for a,b in [((127.46,82),(127.46,83.3)),((127.46,83.3),(126.4,84.36)),((126.4,84.36),(126.4,86.5))]:track('LOAD_POS',pcbnew.F_Cu,a,b,1.5)+for a,b in [((139.4,90.4),(139.4,92)),((139.4,92),(138.4,93)),((138.4,93),(136.5,93))]:track('GND',pcbnew.B_Cu,a,b,1.5)+for item in board.GetTracks():+ if isinstance(item,pcbnew.PCB_VIA) and item.GetNetname()=='GND':+ p=item.GetPosition();xy=(round(pcbnew.ToMM(p.x),3),round(pcbnew.ToMM(p.y),3))+ if xy in [(139.4,86.8),(136.5,93.0),(139.4,90.4),(139.4,91.4),(139.4,92.4)]:item.SetWidth(pcbnew.FromMM(1));item.SetDrill(pcbnew.FromMM(.6));changes.append({'kind':'resize-via','at':xy,'sizeMm':1,'drillMm':.6})+for fp in board.GetFootprints():+ delta={'Q2':-.3,'U3':.3,'R7':.1}.get(fp.GetReference())+ if delta:+ pos=fp.GetPosition();pos.x+=pcbnew.FromMM(delta);fp.SetPosition(pos);changes.append({'kind':'move-footprint','ref':fp.GetReference(),'dxMm':delta})+for item in list(board.GetTracks()):+ if item.GetNetname()=='SHUNT_P_SENSE' and isinstance(item,pcbnew.PCB_VIA):+ pos=item.GetPosition()+ if abs(pcbnew.ToMM(pos.x)-123.6)<.001 and abs(pcbnew.ToMM(pos.y)-85.4)<.001:+ pos.x=pcbnew.FromMM(123.3);item.SetPosition(pos);changes.append({'kind':'move-sense-via','from':[123.6,85.4],'to':[123.3,85.4]})+ if isinstance(item,pcbnew.PCB_VIA):continue+ if item.GetNetname()=='SHUNT_P_SENSE':+ for getter,setter in [(item.GetStart,item.SetStart),(item.GetEnd,item.SetEnd)]:+ pos=getter()+ if abs(pcbnew.ToMM(pos.x)-123.6)<.001 and abs(pcbnew.ToMM(pos.y)-85.4)<.001:pos.x=pcbnew.FromMM(123.3);setter(pos)+ if item.GetNetname()=='SHUNT_N_SENSE' and item.GetLayer()==pcbnew.F_Cu:+ for getter,setter in [(item.GetStart,item.SetStart),(item.GetEnd,item.SetEnd)]:+ pos=getter();x,y=pcbnew.ToMM(pos.x),pcbnew.ToMM(pos.y)+ if 128.79<x<129.31 and 87.29<y<88.81:pos.x+=pcbnew.FromMM(.2);setter(pos)+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid=='32514162-b870-4c7a-95a2-b85b8db79257':+ item.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(126.4),pcbnew.FromMM(86.7)))+ if uid=='13d2f936-e4d3-40cb-9bf7-1b6b26ca4cf2':+ item.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(126.4),pcbnew.FromMM(86.7)));item.SetWidth(pcbnew.FromMM(1.5))+ if uid=='f120f8db-288f-4938-acbf-98ff5e4065df':+ item.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(133.5),pcbnew.FromMM(84.2)));item.SetEnd(pcbnew.VECTOR2I(pcbnew.FromMM(126.8),pcbnew.FromMM(84.2)));item.SetWidth(pcbnew.FromMM(1.9))+ if not isinstance(item,pcbnew.PCB_VIA) and item.GetNetname()=='LOAD_POS' and item.GetLayer()==pcbnew.F_Cu:+ for getter,setter in [(item.GetStart,item.SetStart),(item.GetEnd,item.SetEnd)]:+ p=getter()+ if abs(pcbnew.ToMM(p.x)-126.4)<.001 and abs(pcbnew.ToMM(p.y)-86.5)<.001:p.y=pcbnew.FromMM(86.7);setter(p)+for item in board.GetTracks():+ if isinstance(item,pcbnew.PCB_VIA) or item.GetLayer()!=pcbnew.B_Cu or item.GetNetname()!='SHUNT_P_SENSE':continue+ for getter,setter in [(item.GetStart,item.SetStart),(item.GetEnd,item.SetEnd)]:+ p=getter();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if abs(y-85.4)<.001 and (abs(x-123.3)<.001 or abs(x-132)<.001):+ p.y=pcbnew.FromMM(85.6)+ if abs(x-132)<.001:p.x=pcbnew.FromMM(132.2)+ setter(p)+# Ease the drain right-angle turn; relocate its adjacent setpoint via with endpoints.+track('LOAD_POS',pcbnew.B_Cu,(126.35,89.0),(125.65,89.7),1.5)+# Preserve explicit branch junctions instead of overlapped dangling endpoints.+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid=='32514162-b870-4c7a-95a2-b85b8db79257':+ item.SetWidth(pcbnew.FromMM(.8));item.SetDrill(pcbnew.FromMM(.4));item.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(126.05),pcbnew.FromMM(86.7)))+ if uid in ['b486fb59-b64e-41ee-a1a7-5a72fcf0a780','8e5d5e2b-78f3-4ed2-af96-409d2ea9d57b']:+ a=item.GetStart();b=item.GetEnd();start=(pcbnew.ToMM(a.x),pcbnew.ToMM(a.y));end=(pcbnew.ToMM(b.x),pcbnew.ToMM(b.y))+ mid=(126.35,89.0) if uid=='b486fb59-b64e-41ee-a1a7-5a72fcf0a780' else (125.65,89.7)+ board.Remove(item);track('LOAD_POS',pcbnew.B_Cu,start,mid,1.5);track('LOAD_POS',pcbnew.B_Cu,mid,end,1.5)+via=pcbnew.PCB_VIA(board);via.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(126.8),pcbnew.FromMM(86.7)));via.SetWidth(pcbnew.FromMM(.8));via.SetDrill(pcbnew.FromMM(.4));via.SetLayerPair(pcbnew.F_Cu,pcbnew.B_Cu);via.SetNet(nets['LOAD_POS']);board.Add(via)+# Do not enlarge holes through narrow in-plane paths. Keep the three dedicated shunt thermal vias.+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid in ['34d3207a-b14a-40d8-be82-5b108c2b867b','9a71af6b-ea83-4f97-b7f6-3f69253c7314']:+ board.Remove(item);continue+ if isinstance(item,pcbnew.PCB_VIA):+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if uid=='aa6c5964-74d4-410e-a69e-ffb2cd9c9999' or (item.GetNetname()=='GND' and abs(x-139.4)<.001 and abs(y-86.8)<.001):+ item.SetWidth(pcbnew.FromMM(.8));item.SetDrill(pcbnew.FromMM(.4))+# Move the transfer hole off the center of the shunt bus; remove a nearly unused ground hole through the return neck.+for item in list(board.GetTracks()):+ if not isinstance(item,pcbnew.PCB_VIA):continue+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if item.GetNetname()=='GND' and abs(x-139.4)<.001 and abs(y-86.8)<.001:board.Remove(item)+ if str(item.m_Uuid.AsString())=='aa6c5964-74d4-410e-a69e-ffb2cd9c9999':item.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(133.7),pcbnew.FromMM(83.6)))+track('SHUNT_P',pcbnew.F_Cu,(133.7,83.6),(133.8,84.2),1.2)+# Preserve the full plated Q1 source connection; remove its redundant neck-drilling spur.+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid in ['cd48c727-15bf-4276-b4b8-ae4d936d829d','30d9e8bc-805a-4b1d-8a79-ad625ee59388']:+ board.Remove(item);continue+ if isinstance(item,pcbnew.PCB_VIA) and item.GetNetname()=='GND':+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if abs(x-139.4)<.001 and any(abs(y-t)<.001 for t in [90.4,91.4,92.4]):p.x=pcbnew.FromMM(139.8);item.SetPosition(p)+# Share vertical current with smaller holes and widen the plated-source exit.+for item in board.GetTracks():+ uid=str(item.m_Uuid.AsString())+ if uid in ['2f235494-7976-4048-be2d-b71507b2b45e','ec56cc46-09f5-4ff9-a1b6-61699db68686']:item.SetWidth(pcbnew.FromMM(1.75))+ if isinstance(item,pcbnew.PCB_VIA) and item.GetNetname()=='GND':+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if abs(x-139.8)<.001 and any(abs(y-t)<.001 for t in [90.4,91.4,92.4]):+ p.x=pcbnew.FromMM(139.4);item.SetPosition(p);item.SetWidth(pcbnew.FromMM(.6));item.SetDrill(pcbnew.FromMM(.3))+for item in board.GetTracks():+ if str(item.m_Uuid.AsString())=='f120f8db-288f-4938-acbf-98ff5e4065df':+ item.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(133.5),pcbnew.FromMM(84.25)));item.SetEnd(pcbnew.VECTOR2I(pcbnew.FromMM(126.8),pcbnew.FromMM(84.25)));item.SetWidth(pcbnew.FromMM(2.0))+# Fine-grid hotspot revision: spread the return transfer and soften the two power necks.+for item in board.GetTracks():+ if isinstance(item,pcbnew.PCB_VIA):+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if item.GetNetname()=='GND' and abs(x-139.4)<.001 and abs(y-90.4)<.001:+ p.x=pcbnew.FromMM(139.0);item.SetPosition(p)+ continue+ uid=str(item.m_Uuid.AsString())+ if uid in ['32cd5f76-8c9c-4680-a071-fe4f71064f23','cecc8caa-bb93-470d-a793-50ae2c93732f']:item.SetWidth(pcbnew.FromMM(1.6))+ if item.GetNetname()=='LOAD_POS' and item.GetLayer()==pcbnew.B_Cu:+ a=item.GetStart();b=item.GetEnd()+ if abs(pcbnew.ToMM(a.y)-89.7)<.001 and abs(pcbnew.ToMM(b.y)-89.7)<.001:item.SetWidth(pcbnew.FromMM(1.75))+via=pcbnew.PCB_VIA(board);via.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(139.8),pcbnew.FromMM(90.4)));via.SetWidth(pcbnew.FromMM(.6));via.SetDrill(pcbnew.FromMM(.3));via.SetLayerPair(pcbnew.F_Cu,pcbnew.B_Cu);via.SetNet(nets['GND']);board.Add(via)+track('GND',pcbnew.B_Cu,(139.0,90.4),(139.8,90.4),1.2)+expected_nets={str(item.m_Uuid.AsString()):item.GetNetname() for item in board.GetTracks()}+board.BuildConnectivity()+actual_nets={str(item.m_Uuid.AsString()):item.GetNetname() for item in board.GetTracks()}+assert actual_nets==expected_nets, {'unexpectedNetChanges':[(k,v,actual_nets.get(k)) for k,v in expected_nets.items() if actual_nets.get(k)!=v]}+for zone in board.Zones():zone.SetNeedRefill(True)+pcbnew.ZONE_FILLER(board).Fill(board.Zones());assert {str(item.m_Uuid.AsString()):item.GetNetname() for item in board.GetTracks()}==expected_nets, 'Zone fill changed copper nets'+pcbnew.SaveBoard(str(out),board)+readback=pcbnew.LoadBoard(str(out))+assert {str(item.m_Uuid.AsString()):item.GetNetname() for item in readback.GetTracks()}==expected_nets, 'Save/readback changed copper nets' +out.with_suffix('.changes.json').write_text(json.dumps({'source':str(source),'candidate':str(out),'changes':changes},indent=2));print(json.dumps({'saved':str(out),'changes':changes}))
tools/hotspot_via_candidate_v29.pyadded+142@@ -0,0 +1,142 @@+"""Run using native desktop KiCad Python; modifies only an isolated board copy."""+import pcbnew,sys,json+from pathlib import Path+source=Path(sys.argv[1]);out=Path(sys.argv[2]);board=pcbnew.LoadBoard(str(source));nets=board.GetNetsByName()+changes=[]+for net,x,y in [('GND',133.0,100.8),('GND',138.0,100.8),('GND',139.0,93.0),('GND',136.5,93.0),('GND',139.4,90.4),('GND',139.4,91.4),('GND',139.4,92.4)]:+ via=pcbnew.PCB_VIA(board);via.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(x),pcbnew.FromMM(y)));via.SetWidth(pcbnew.FromMM(.8));via.SetDrill(pcbnew.FromMM(.4));via.SetLayerPair(pcbnew.F_Cu,pcbnew.B_Cu);via.SetNet(nets[net]);board.Add(via);changes.append({'kind':'via','net':net,'at':[x,y],'sizeMm':.8,'drillMm':.4,'uuid':str(via.m_Uuid.AsString())})+for item in board.GetTracks():+ uid=str(item.m_Uuid.AsString())+ if uid=='32514162-b870-4c7a-95a2-b85b8db79257':+ item.SetWidth(pcbnew.FromMM(1.0));item.SetDrill(pcbnew.FromMM(.6));changes.append({'kind':'resize-via','uuid':uid,'net':'LOAD_POS','sizeMm':1.0,'drillMm':.6})+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid in ['91eed079-74e4-4863-8dc1-f211a19b6ee0','ad353074-a567-44a9-a20a-744b8057c5a9']:+ board.Remove(item);changes.append({'kind':'remove-track','uuid':uid})+ if uid=='aa6c5964-74d4-410e-a69e-ffb2cd9c9999':+ item.SetWidth(pcbnew.FromMM(1.0));item.SetDrill(pcbnew.FromMM(.6));changes.append({'kind':'resize-via','uuid':uid,'sizeMm':1.0,'drillMm':.6})+def track(net,layer,a,b,width):+ t=pcbnew.PCB_TRACK(board);t.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(a[0]),pcbnew.FromMM(a[1])));t.SetEnd(pcbnew.VECTOR2I(pcbnew.FromMM(b[0]),pcbnew.FromMM(b[1])));t.SetWidth(pcbnew.FromMM(width));t.SetLayer(layer);t.SetNet(nets[net]);board.Add(t);changes.append({'kind':'track','net':net,'start':a,'end':b,'widthMm':width,'layer':board.GetLayerName(layer)})+for a,b in [((127.46,82),(127.46,83.3)),((127.46,83.3),(126.4,84.36)),((126.4,84.36),(126.4,86.5))]:track('LOAD_POS',pcbnew.F_Cu,a,b,1.5)+for a,b in [((139.4,90.4),(139.4,92)),((139.4,92),(138.4,93)),((138.4,93),(136.5,93))]:track('GND',pcbnew.B_Cu,a,b,1.5)+for item in board.GetTracks():+ if isinstance(item,pcbnew.PCB_VIA) and item.GetNetname()=='GND':+ p=item.GetPosition();xy=(round(pcbnew.ToMM(p.x),3),round(pcbnew.ToMM(p.y),3))+ if xy in [(139.4,86.8),(136.5,93.0),(139.4,90.4),(139.4,91.4),(139.4,92.4)]:item.SetWidth(pcbnew.FromMM(1));item.SetDrill(pcbnew.FromMM(.6));changes.append({'kind':'resize-via','at':xy,'sizeMm':1,'drillMm':.6})+for fp in board.GetFootprints():+ delta={'Q2':-.3,'U3':.3,'R7':.1}.get(fp.GetReference())+ if delta:+ pos=fp.GetPosition();pos.x+=pcbnew.FromMM(delta);fp.SetPosition(pos);changes.append({'kind':'move-footprint','ref':fp.GetReference(),'dxMm':delta})+for item in list(board.GetTracks()):+ if item.GetNetname()=='SHUNT_P_SENSE' and isinstance(item,pcbnew.PCB_VIA):+ pos=item.GetPosition()+ if abs(pcbnew.ToMM(pos.x)-123.6)<.001 and abs(pcbnew.ToMM(pos.y)-85.4)<.001:+ pos.x=pcbnew.FromMM(123.3);item.SetPosition(pos);changes.append({'kind':'move-sense-via','from':[123.6,85.4],'to':[123.3,85.4]})+ if isinstance(item,pcbnew.PCB_VIA):continue+ if item.GetNetname()=='SHUNT_P_SENSE':+ for getter,setter in [(item.GetStart,item.SetStart),(item.GetEnd,item.SetEnd)]:+ pos=getter()+ if abs(pcbnew.ToMM(pos.x)-123.6)<.001 and abs(pcbnew.ToMM(pos.y)-85.4)<.001:pos.x=pcbnew.FromMM(123.3);setter(pos)+ if item.GetNetname()=='SHUNT_N_SENSE' and item.GetLayer()==pcbnew.F_Cu:+ for getter,setter in [(item.GetStart,item.SetStart),(item.GetEnd,item.SetEnd)]:+ pos=getter();x,y=pcbnew.ToMM(pos.x),pcbnew.ToMM(pos.y)+ if 128.79<x<129.31 and 87.29<y<88.81:pos.x+=pcbnew.FromMM(.2);setter(pos)+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid=='32514162-b870-4c7a-95a2-b85b8db79257':+ item.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(126.4),pcbnew.FromMM(86.7)))+ if uid=='13d2f936-e4d3-40cb-9bf7-1b6b26ca4cf2':+ item.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(126.4),pcbnew.FromMM(86.7)));item.SetWidth(pcbnew.FromMM(1.5))+ if uid=='f120f8db-288f-4938-acbf-98ff5e4065df':+ item.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(133.5),pcbnew.FromMM(84.2)));item.SetEnd(pcbnew.VECTOR2I(pcbnew.FromMM(126.8),pcbnew.FromMM(84.2)));item.SetWidth(pcbnew.FromMM(1.9))+ if not isinstance(item,pcbnew.PCB_VIA) and item.GetNetname()=='LOAD_POS' and item.GetLayer()==pcbnew.F_Cu:+ for getter,setter in [(item.GetStart,item.SetStart),(item.GetEnd,item.SetEnd)]:+ p=getter()+ if abs(pcbnew.ToMM(p.x)-126.4)<.001 and abs(pcbnew.ToMM(p.y)-86.5)<.001:p.y=pcbnew.FromMM(86.7);setter(p)+for item in board.GetTracks():+ if isinstance(item,pcbnew.PCB_VIA) or item.GetLayer()!=pcbnew.B_Cu or item.GetNetname()!='SHUNT_P_SENSE':continue+ for getter,setter in [(item.GetStart,item.SetStart),(item.GetEnd,item.SetEnd)]:+ p=getter();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if abs(y-85.4)<.001 and (abs(x-123.3)<.001 or abs(x-132)<.001):+ p.y=pcbnew.FromMM(85.6)+ if abs(x-132)<.001:p.x=pcbnew.FromMM(132.2)+ setter(p)+# Ease the drain right-angle turn; relocate its adjacent setpoint via with endpoints.+track('LOAD_POS',pcbnew.B_Cu,(126.35,89.0),(125.65,89.7),1.5)+# Preserve explicit branch junctions instead of overlapped dangling endpoints.+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid=='32514162-b870-4c7a-95a2-b85b8db79257':+ item.SetWidth(pcbnew.FromMM(.8));item.SetDrill(pcbnew.FromMM(.4));item.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(126.05),pcbnew.FromMM(86.7)))+ if uid in ['b486fb59-b64e-41ee-a1a7-5a72fcf0a780','8e5d5e2b-78f3-4ed2-af96-409d2ea9d57b']:+ a=item.GetStart();b=item.GetEnd();start=(pcbnew.ToMM(a.x),pcbnew.ToMM(a.y));end=(pcbnew.ToMM(b.x),pcbnew.ToMM(b.y))+ mid=(126.35,89.0) if uid=='b486fb59-b64e-41ee-a1a7-5a72fcf0a780' else (125.65,89.7)+ board.Remove(item);track('LOAD_POS',pcbnew.B_Cu,start,mid,1.5);track('LOAD_POS',pcbnew.B_Cu,mid,end,1.5)+via=pcbnew.PCB_VIA(board);via.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(126.8),pcbnew.FromMM(86.7)));via.SetWidth(pcbnew.FromMM(.8));via.SetDrill(pcbnew.FromMM(.4));via.SetLayerPair(pcbnew.F_Cu,pcbnew.B_Cu);via.SetNet(nets['LOAD_POS']);board.Add(via)+# Do not enlarge holes through narrow in-plane paths. Keep the three dedicated shunt thermal vias.+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid in ['34d3207a-b14a-40d8-be82-5b108c2b867b','9a71af6b-ea83-4f97-b7f6-3f69253c7314']:+ board.Remove(item);continue+ if isinstance(item,pcbnew.PCB_VIA):+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if uid=='aa6c5964-74d4-410e-a69e-ffb2cd9c9999' or (item.GetNetname()=='GND' and abs(x-139.4)<.001 and abs(y-86.8)<.001):+ item.SetWidth(pcbnew.FromMM(.8));item.SetDrill(pcbnew.FromMM(.4))+# Move the transfer hole off the center of the shunt bus; remove a nearly unused ground hole through the return neck.+for item in list(board.GetTracks()):+ if not isinstance(item,pcbnew.PCB_VIA):continue+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if item.GetNetname()=='GND' and abs(x-139.4)<.001 and abs(y-86.8)<.001:board.Remove(item)+ if str(item.m_Uuid.AsString())=='aa6c5964-74d4-410e-a69e-ffb2cd9c9999':item.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(133.7),pcbnew.FromMM(83.6)))+track('SHUNT_P',pcbnew.F_Cu,(133.7,83.6),(133.8,84.2),1.2)+# Preserve the full plated Q1 source connection; remove its redundant neck-drilling spur.+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid in ['cd48c727-15bf-4276-b4b8-ae4d936d829d','30d9e8bc-805a-4b1d-8a79-ad625ee59388']:+ board.Remove(item);continue+ if isinstance(item,pcbnew.PCB_VIA) and item.GetNetname()=='GND':+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if abs(x-139.4)<.001 and any(abs(y-t)<.001 for t in [90.4,91.4,92.4]):p.x=pcbnew.FromMM(139.8);item.SetPosition(p)+# Share vertical current with smaller holes and widen the plated-source exit.+for item in board.GetTracks():+ uid=str(item.m_Uuid.AsString())+ if uid in ['2f235494-7976-4048-be2d-b71507b2b45e','ec56cc46-09f5-4ff9-a1b6-61699db68686']:item.SetWidth(pcbnew.FromMM(1.75))+ if isinstance(item,pcbnew.PCB_VIA) and item.GetNetname()=='GND':+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if abs(x-139.8)<.001 and any(abs(y-t)<.001 for t in [90.4,91.4,92.4]):+ p.x=pcbnew.FromMM(139.4);item.SetPosition(p);item.SetWidth(pcbnew.FromMM(.6));item.SetDrill(pcbnew.FromMM(.3))+for item in board.GetTracks():+ if str(item.m_Uuid.AsString())=='f120f8db-288f-4938-acbf-98ff5e4065df':+ item.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(133.5),pcbnew.FromMM(84.25)));item.SetEnd(pcbnew.VECTOR2I(pcbnew.FromMM(126.8),pcbnew.FromMM(84.25)));item.SetWidth(pcbnew.FromMM(2.0))+# Fine-grid hotspot revision: spread the return transfer and soften the two power necks.+for item in board.GetTracks():+ if isinstance(item,pcbnew.PCB_VIA):+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if item.GetNetname()=='GND' and abs(x-139.4)<.001 and abs(y-90.4)<.001:+ p.x=pcbnew.FromMM(139.0);item.SetPosition(p)+ continue+ uid=str(item.m_Uuid.AsString())+ if uid in ['32cd5f76-8c9c-4680-a071-fe4f71064f23','cecc8caa-bb93-470d-a793-50ae2c93732f']:item.SetWidth(pcbnew.FromMM(1.6))+ if item.GetNetname()=='LOAD_POS' and item.GetLayer()==pcbnew.B_Cu:+ a=item.GetStart();b=item.GetEnd()+ if abs(pcbnew.ToMM(a.y)-89.7)<.001 and abs(pcbnew.ToMM(b.y)-89.7)<.001:item.SetWidth(pcbnew.FromMM(1.75))+via=pcbnew.PCB_VIA(board);via.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(139.8),pcbnew.FromMM(90.4)));via.SetWidth(pcbnew.FromMM(.6));via.SetDrill(pcbnew.FromMM(.3));via.SetLayerPair(pcbnew.F_Cu,pcbnew.B_Cu);via.SetNet(nets['GND']);board.Add(via)+track('GND',pcbnew.B_Cu,(139.0,90.4),(139.8,90.4),1.2)+# Keep clearance beside the setpoint via; widen only the diode-spread junction.+for item in list(board.GetTracks()):+ if isinstance(item,pcbnew.PCB_VIA) or item.GetNetname()!='LOAD_POS' or item.GetLayer()!=pcbnew.B_Cu:continue+ a=item.GetStart();b=item.GetEnd();ax,ay=pcbnew.ToMM(a.x),pcbnew.ToMM(a.y);bx,by=pcbnew.ToMM(b.x),pcbnew.ToMM(b.y)+ if abs(ay-89.7)<.001 and abs(by-89.7)<.001:+ item.SetWidth(pcbnew.FromMM(1.5))+ if min(ax,bx)<120 and max(ax,bx)>125:+ board.Remove(item);track('LOAD_POS',pcbnew.B_Cu,(119.8,89.7),(123.0,89.7),1.75);track('LOAD_POS',pcbnew.B_Cu,(123.0,89.7),(125.65,89.7),1.5)+expected_nets={str(item.m_Uuid.AsString()):item.GetNetname() for item in board.GetTracks()}+board.BuildConnectivity()+actual_nets={str(item.m_Uuid.AsString()):item.GetNetname() for item in board.GetTracks()}+assert actual_nets==expected_nets, {'unexpectedNetChanges':[(k,v,actual_nets.get(k)) for k,v in expected_nets.items() if actual_nets.get(k)!=v]}+for zone in board.Zones():zone.SetNeedRefill(True)+pcbnew.ZONE_FILLER(board).Fill(board.Zones());assert {str(item.m_Uuid.AsString()):item.GetNetname() for item in board.GetTracks()}==expected_nets, 'Zone fill changed copper nets'+pcbnew.SaveBoard(str(out),board)+readback=pcbnew.LoadBoard(str(out))+assert {str(item.m_Uuid.AsString()):item.GetNetname() for item in readback.GetTracks()}==expected_nets, 'Save/readback changed copper nets' +out.with_suffix('.changes.json').write_text(json.dumps({'source':str(source),'candidate':str(out),'changes':changes},indent=2));print(json.dumps({'saved':str(out),'changes':changes}))
tools/hotspot_via_candidate_v30.pyadded+144@@ -0,0 +1,144 @@+"""Run using native desktop KiCad Python; modifies only an isolated board copy."""+import pcbnew,sys,json+from pathlib import Path+source=Path(sys.argv[1]);out=Path(sys.argv[2]);board=pcbnew.LoadBoard(str(source));nets=board.GetNetsByName()+changes=[]+for net,x,y in [('GND',133.0,100.8),('GND',138.0,100.8),('GND',139.0,93.0),('GND',136.5,93.0),('GND',139.4,90.4),('GND',139.4,91.4),('GND',139.4,92.4)]:+ via=pcbnew.PCB_VIA(board);via.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(x),pcbnew.FromMM(y)));via.SetWidth(pcbnew.FromMM(.8));via.SetDrill(pcbnew.FromMM(.4));via.SetLayerPair(pcbnew.F_Cu,pcbnew.B_Cu);via.SetNet(nets[net]);board.Add(via);changes.append({'kind':'via','net':net,'at':[x,y],'sizeMm':.8,'drillMm':.4,'uuid':str(via.m_Uuid.AsString())})+for item in board.GetTracks():+ uid=str(item.m_Uuid.AsString())+ if uid=='32514162-b870-4c7a-95a2-b85b8db79257':+ item.SetWidth(pcbnew.FromMM(1.0));item.SetDrill(pcbnew.FromMM(.6));changes.append({'kind':'resize-via','uuid':uid,'net':'LOAD_POS','sizeMm':1.0,'drillMm':.6})+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid in ['91eed079-74e4-4863-8dc1-f211a19b6ee0','ad353074-a567-44a9-a20a-744b8057c5a9']:+ board.Remove(item);changes.append({'kind':'remove-track','uuid':uid})+ if uid=='aa6c5964-74d4-410e-a69e-ffb2cd9c9999':+ item.SetWidth(pcbnew.FromMM(1.0));item.SetDrill(pcbnew.FromMM(.6));changes.append({'kind':'resize-via','uuid':uid,'sizeMm':1.0,'drillMm':.6})+def track(net,layer,a,b,width):+ t=pcbnew.PCB_TRACK(board);t.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(a[0]),pcbnew.FromMM(a[1])));t.SetEnd(pcbnew.VECTOR2I(pcbnew.FromMM(b[0]),pcbnew.FromMM(b[1])));t.SetWidth(pcbnew.FromMM(width));t.SetLayer(layer);t.SetNet(nets[net]);board.Add(t);changes.append({'kind':'track','net':net,'start':a,'end':b,'widthMm':width,'layer':board.GetLayerName(layer)})+for a,b in [((127.46,82),(127.46,83.3)),((127.46,83.3),(126.4,84.36)),((126.4,84.36),(126.4,86.5))]:track('LOAD_POS',pcbnew.F_Cu,a,b,1.5)+for a,b in [((139.4,90.4),(139.4,92)),((139.4,92),(138.4,93)),((138.4,93),(136.5,93))]:track('GND',pcbnew.B_Cu,a,b,1.5)+for item in board.GetTracks():+ if isinstance(item,pcbnew.PCB_VIA) and item.GetNetname()=='GND':+ p=item.GetPosition();xy=(round(pcbnew.ToMM(p.x),3),round(pcbnew.ToMM(p.y),3))+ if xy in [(139.4,86.8),(136.5,93.0),(139.4,90.4),(139.4,91.4),(139.4,92.4)]:item.SetWidth(pcbnew.FromMM(1));item.SetDrill(pcbnew.FromMM(.6));changes.append({'kind':'resize-via','at':xy,'sizeMm':1,'drillMm':.6})+for fp in board.GetFootprints():+ delta={'Q2':-.3,'U3':.3,'R7':.1}.get(fp.GetReference())+ if delta:+ pos=fp.GetPosition();pos.x+=pcbnew.FromMM(delta);fp.SetPosition(pos);changes.append({'kind':'move-footprint','ref':fp.GetReference(),'dxMm':delta})+for item in list(board.GetTracks()):+ if item.GetNetname()=='SHUNT_P_SENSE' and isinstance(item,pcbnew.PCB_VIA):+ pos=item.GetPosition()+ if abs(pcbnew.ToMM(pos.x)-123.6)<.001 and abs(pcbnew.ToMM(pos.y)-85.4)<.001:+ pos.x=pcbnew.FromMM(123.3);item.SetPosition(pos);changes.append({'kind':'move-sense-via','from':[123.6,85.4],'to':[123.3,85.4]})+ if isinstance(item,pcbnew.PCB_VIA):continue+ if item.GetNetname()=='SHUNT_P_SENSE':+ for getter,setter in [(item.GetStart,item.SetStart),(item.GetEnd,item.SetEnd)]:+ pos=getter()+ if abs(pcbnew.ToMM(pos.x)-123.6)<.001 and abs(pcbnew.ToMM(pos.y)-85.4)<.001:pos.x=pcbnew.FromMM(123.3);setter(pos)+ if item.GetNetname()=='SHUNT_N_SENSE' and item.GetLayer()==pcbnew.F_Cu:+ for getter,setter in [(item.GetStart,item.SetStart),(item.GetEnd,item.SetEnd)]:+ pos=getter();x,y=pcbnew.ToMM(pos.x),pcbnew.ToMM(pos.y)+ if 128.79<x<129.31 and 87.29<y<88.81:pos.x+=pcbnew.FromMM(.2);setter(pos)+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid=='32514162-b870-4c7a-95a2-b85b8db79257':+ item.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(126.4),pcbnew.FromMM(86.7)))+ if uid=='13d2f936-e4d3-40cb-9bf7-1b6b26ca4cf2':+ item.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(126.4),pcbnew.FromMM(86.7)));item.SetWidth(pcbnew.FromMM(1.5))+ if uid=='f120f8db-288f-4938-acbf-98ff5e4065df':+ item.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(133.5),pcbnew.FromMM(84.2)));item.SetEnd(pcbnew.VECTOR2I(pcbnew.FromMM(126.8),pcbnew.FromMM(84.2)));item.SetWidth(pcbnew.FromMM(1.9))+ if not isinstance(item,pcbnew.PCB_VIA) and item.GetNetname()=='LOAD_POS' and item.GetLayer()==pcbnew.F_Cu:+ for getter,setter in [(item.GetStart,item.SetStart),(item.GetEnd,item.SetEnd)]:+ p=getter()+ if abs(pcbnew.ToMM(p.x)-126.4)<.001 and abs(pcbnew.ToMM(p.y)-86.5)<.001:p.y=pcbnew.FromMM(86.7);setter(p)+for item in board.GetTracks():+ if isinstance(item,pcbnew.PCB_VIA) or item.GetLayer()!=pcbnew.B_Cu or item.GetNetname()!='SHUNT_P_SENSE':continue+ for getter,setter in [(item.GetStart,item.SetStart),(item.GetEnd,item.SetEnd)]:+ p=getter();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if abs(y-85.4)<.001 and (abs(x-123.3)<.001 or abs(x-132)<.001):+ p.y=pcbnew.FromMM(85.6)+ if abs(x-132)<.001:p.x=pcbnew.FromMM(132.2)+ setter(p)+# Ease the drain right-angle turn; relocate its adjacent setpoint via with endpoints.+track('LOAD_POS',pcbnew.B_Cu,(126.35,89.0),(125.65,89.7),1.5)+# Preserve explicit branch junctions instead of overlapped dangling endpoints.+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid=='32514162-b870-4c7a-95a2-b85b8db79257':+ item.SetWidth(pcbnew.FromMM(.8));item.SetDrill(pcbnew.FromMM(.4));item.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(126.05),pcbnew.FromMM(86.7)))+ if uid in ['b486fb59-b64e-41ee-a1a7-5a72fcf0a780','8e5d5e2b-78f3-4ed2-af96-409d2ea9d57b']:+ a=item.GetStart();b=item.GetEnd();start=(pcbnew.ToMM(a.x),pcbnew.ToMM(a.y));end=(pcbnew.ToMM(b.x),pcbnew.ToMM(b.y))+ mid=(126.35,89.0) if uid=='b486fb59-b64e-41ee-a1a7-5a72fcf0a780' else (125.65,89.7)+ board.Remove(item);track('LOAD_POS',pcbnew.B_Cu,start,mid,1.5);track('LOAD_POS',pcbnew.B_Cu,mid,end,1.5)+via=pcbnew.PCB_VIA(board);via.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(126.8),pcbnew.FromMM(86.7)));via.SetWidth(pcbnew.FromMM(.8));via.SetDrill(pcbnew.FromMM(.4));via.SetLayerPair(pcbnew.F_Cu,pcbnew.B_Cu);via.SetNet(nets['LOAD_POS']);board.Add(via)+# Do not enlarge holes through narrow in-plane paths. Keep the three dedicated shunt thermal vias.+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid in ['34d3207a-b14a-40d8-be82-5b108c2b867b','9a71af6b-ea83-4f97-b7f6-3f69253c7314']:+ board.Remove(item);continue+ if isinstance(item,pcbnew.PCB_VIA):+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if uid=='aa6c5964-74d4-410e-a69e-ffb2cd9c9999' or (item.GetNetname()=='GND' and abs(x-139.4)<.001 and abs(y-86.8)<.001):+ item.SetWidth(pcbnew.FromMM(.8));item.SetDrill(pcbnew.FromMM(.4))+# Move the transfer hole off the center of the shunt bus; remove a nearly unused ground hole through the return neck.+for item in list(board.GetTracks()):+ if not isinstance(item,pcbnew.PCB_VIA):continue+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if item.GetNetname()=='GND' and abs(x-139.4)<.001 and abs(y-86.8)<.001:board.Remove(item)+ if str(item.m_Uuid.AsString())=='aa6c5964-74d4-410e-a69e-ffb2cd9c9999':item.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(133.7),pcbnew.FromMM(83.6)))+track('SHUNT_P',pcbnew.F_Cu,(133.7,83.6),(133.8,84.2),1.2)+# Preserve the full plated Q1 source connection; remove its redundant neck-drilling spur.+for item in list(board.GetTracks()):+ uid=str(item.m_Uuid.AsString())+ if uid in ['cd48c727-15bf-4276-b4b8-ae4d936d829d','30d9e8bc-805a-4b1d-8a79-ad625ee59388']:+ board.Remove(item);continue+ if isinstance(item,pcbnew.PCB_VIA) and item.GetNetname()=='GND':+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if abs(x-139.4)<.001 and any(abs(y-t)<.001 for t in [90.4,91.4,92.4]):p.x=pcbnew.FromMM(139.8);item.SetPosition(p)+# Share vertical current with smaller holes and widen the plated-source exit.+for item in board.GetTracks():+ uid=str(item.m_Uuid.AsString())+ if uid in ['2f235494-7976-4048-be2d-b71507b2b45e','ec56cc46-09f5-4ff9-a1b6-61699db68686']:item.SetWidth(pcbnew.FromMM(1.75))+ if isinstance(item,pcbnew.PCB_VIA) and item.GetNetname()=='GND':+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if abs(x-139.8)<.001 and any(abs(y-t)<.001 for t in [90.4,91.4,92.4]):+ p.x=pcbnew.FromMM(139.4);item.SetPosition(p);item.SetWidth(pcbnew.FromMM(.6));item.SetDrill(pcbnew.FromMM(.3))+for item in board.GetTracks():+ if str(item.m_Uuid.AsString())=='f120f8db-288f-4938-acbf-98ff5e4065df':+ item.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(133.5),pcbnew.FromMM(84.25)));item.SetEnd(pcbnew.VECTOR2I(pcbnew.FromMM(126.8),pcbnew.FromMM(84.25)));item.SetWidth(pcbnew.FromMM(2.0))+# Fine-grid hotspot revision: spread the return transfer and soften the two power necks.+for item in board.GetTracks():+ if isinstance(item,pcbnew.PCB_VIA):+ p=item.GetPosition();x,y=pcbnew.ToMM(p.x),pcbnew.ToMM(p.y)+ if item.GetNetname()=='GND' and abs(x-139.4)<.001 and abs(y-90.4)<.001:+ p.x=pcbnew.FromMM(139.0);item.SetPosition(p)+ continue+ uid=str(item.m_Uuid.AsString())+ if uid in ['32cd5f76-8c9c-4680-a071-fe4f71064f23','cecc8caa-bb93-470d-a793-50ae2c93732f']:item.SetWidth(pcbnew.FromMM(1.6))+ if item.GetNetname()=='LOAD_POS' and item.GetLayer()==pcbnew.B_Cu:+ a=item.GetStart();b=item.GetEnd()+ if abs(pcbnew.ToMM(a.y)-89.7)<.001 and abs(pcbnew.ToMM(b.y)-89.7)<.001:item.SetWidth(pcbnew.FromMM(1.75))+via=pcbnew.PCB_VIA(board);via.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(139.8),pcbnew.FromMM(90.4)));via.SetWidth(pcbnew.FromMM(.6));via.SetDrill(pcbnew.FromMM(.3));via.SetLayerPair(pcbnew.F_Cu,pcbnew.B_Cu);via.SetNet(nets['GND']);board.Add(via)+track('GND',pcbnew.B_Cu,(139.0,90.4),(139.8,90.4),1.2)+# Keep clearance beside the setpoint via; widen only the diode-spread junction.+for item in list(board.GetTracks()):+ if isinstance(item,pcbnew.PCB_VIA) or item.GetNetname()!='LOAD_POS' or item.GetLayer()!=pcbnew.B_Cu:continue+ a=item.GetStart();b=item.GetEnd();ax,ay=pcbnew.ToMM(a.x),pcbnew.ToMM(a.y);bx,by=pcbnew.ToMM(b.x),pcbnew.ToMM(b.y)+ if abs(ay-89.7)<.001 and abs(by-89.7)<.001:+ item.SetWidth(pcbnew.FromMM(1.5))+ if min(ax,bx)<120 and max(ax,bx)>125:+ board.Remove(item);track('LOAD_POS',pcbnew.B_Cu,(119.8,89.7),(123.0,89.7),1.75);track('LOAD_POS',pcbnew.B_Cu,(123.0,89.7),(125.65,89.7),1.5)+# Fill the inside shunt-bus bend with a diagonal copper path.+track('SHUNT_P',pcbnew.B_Cu,(133.0,84.7),(134.7,85.5),1.2)+expected_nets={str(item.m_Uuid.AsString()):item.GetNetname() for item in board.GetTracks()}+board.BuildConnectivity()+actual_nets={str(item.m_Uuid.AsString()):item.GetNetname() for item in board.GetTracks()}+assert actual_nets==expected_nets, {'unexpectedNetChanges':[(k,v,actual_nets.get(k)) for k,v in expected_nets.items() if actual_nets.get(k)!=v]}+for zone in board.Zones():zone.SetNeedRefill(True)+pcbnew.ZONE_FILLER(board).Fill(board.Zones());assert {str(item.m_Uuid.AsString()):item.GetNetname() for item in board.GetTracks()}==expected_nets, 'Zone fill changed copper nets'+pcbnew.SaveBoard(str(out),board)+readback=pcbnew.LoadBoard(str(out))+assert {str(item.m_Uuid.AsString()):item.GetNetname() for item in readback.GetTracks()}==expected_nets, 'Save/readback changed copper nets' +out.with_suffix('.changes.json').write_text(json.dumps({'source':str(source),'candidate':str(out),'changes':changes},indent=2));print(json.dumps({'saved':str(out),'changes':changes}))
tools/prepare_hotspot_landing.pyadded+53@@ -0,0 +1,53 @@+"""Prepare an exact copper/placement replay plan. Never edits the live PCB."""+from pathlib import Path+from collections import defaultdict+import json, hashlib, sys+import sexp+root=Path(__file__).resolve().parents[1]+source=root/'aiflow/run/board-19.kicad_pcb'+candidate=Path(sys.argv[1]).resolve();output=Path(sys.argv[2]).resolve()+a=sexp.parse(source.read_text());b=sexp.parse(candidate.read_text())+def val(t,n): return sexp.first(t,n)[1:]+def without(t,names):+ return [v for v in t if not (isinstance(v,list) and v and v[0] in names)]+def copper(board):+ out={}+ for kind in ['segment','via']:+ for t in sexp.find(board,kind):+ uid=val(t,'uuid')[0];net=val(t,'net')[-1]+ if kind=='segment': g=dict(kind=kind,net=net,layer=val(t,'layer')[0],width=float(val(t,'width')[0]),start=list(map(float,val(t,'start'))),end=list(map(float,val(t,'end'))))+ else:+ assert val(t,'layers')==['F.Cu','B.Cu'],'Only through vias supported'+ g=dict(kind=kind,net=net,size=float(val(t,'size')[0]),drill=float(val(t,'drill')[0]),at=list(map(float,val(t,'at'))))+ out[uid]=g+ return out+ca,cb=copper(a),copper(b)+assert all(cb[u]['net']==v['net'] for u,v in ca.items() if u in cb),'Existing copper net changed'+remove=[u for u,g in ca.items() if cb.get(u)!=g]+added=[dict(g,uuid=u) for u,g in cb.items() if ca.get(u)!=g]+groups=defaultdict(list)+for g in added:+ if g['kind']=='segment':groups[(g['net'],g['layer'],g['width'],None,None)].append([g['start'],g['end']])+ else:+ x,y=g['at'];groups[(g['net'],'F.Cu',.25,g['size'],g['drill'])].append([[x,y],dict(x=x,y=y,layer='B.Cu')])+routes=[]+for (net,layer,width,size,drill),paths in sorted(groups.items(),key=lambda x:str(x[0])):+ route=dict(net=net,layer=layer,width=width,paths=paths,validate=False)+ if size is not None:route.update(viaSize=size,viaDrill=drill)+ routes.append(route)+def footprints(board):+ return {next(p[2] for p in sexp.find(f,'property') if p[1]=='Reference'):f for f in sexp.find(board,'footprint')}+fa,fb=footprints(a),footprints(b);assert fa.keys()==fb.keys();moves=[]+for ref,f in fa.items():+ g=fb[ref];assert without(f,{'at'})==without(g,{'at'}),f'Footprint content changed: {ref}'+ if val(f,'at')!=val(g,'at'):+ p=list(map(float,val(g,'at')));moves.append(dict(ref=ref,x=p[0],y=p[1],rotation=p[2] if len(p)>2 else 0))+assert {m['ref'] for m in moves}=={'Q2','R7','U3'}+# No zone replay: compare every definition, including keepouts, ignoring only regenerated UUIDs/fill caches.+za=[without(z,{'uuid','filled_polygon','filled_areas_thickness'}) for z in sexp.find(a,'zone')]+zb=[without(z,{'uuid','filled_polygon','filled_areas_thickness'}) for z in sexp.find(b,'zone')]+assert sorted(map(repr,za))==sorted(map(repr,zb)),'Zone definitions changed'+sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()+report=dict(status='DO NOT EXECUTE: fine-mesh and full engineering acceptance pending',sourceBoard=str(source.relative_to(root)),sourceSha256=sha(source),candidate=str(candidate.relative_to(root)),candidateSha256=sha(candidate),expectedLiveRevision='3213474890590f6f65d1603120ae19fabb7590241498da6d85c4736062ff51cc',removeCopperIds=remove,moveFootprints=moves,routes=routes,zoneDefinitionsUnchanged=True,addedCopper=added)+output.write_text(json.dumps(report,indent=2)+'\n')+print(json.dumps({'plan':str(output),'remove':len(remove),'added':len(added),'routeGroups':len(routes),'moves':moves,'zoneDefinitionsUnchanged':True}))