fabgate 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. fabgate-0.1.0/.gitignore +13 -0
  2. fabgate-0.1.0/LICENSE +21 -0
  3. fabgate-0.1.0/PKG-INFO +114 -0
  4. fabgate-0.1.0/README.md +80 -0
  5. fabgate-0.1.0/config/default_rules.yaml +36 -0
  6. fabgate-0.1.0/config/design_spec.example.yaml +24 -0
  7. fabgate-0.1.0/config/product.yaml +13 -0
  8. fabgate-0.1.0/pyproject.toml +64 -0
  9. fabgate-0.1.0/src/kitty/__init__.py +3 -0
  10. fabgate-0.1.0/src/kitty/__main__.py +3 -0
  11. fabgate-0.1.0/src/kitty/analyzers/__init__.py +29 -0
  12. fabgate-0.1.0/src/kitty/analyzers/base.py +19 -0
  13. fabgate-0.1.0/src/kitty/analyzers/drc_severity.py +50 -0
  14. fabgate-0.1.0/src/kitty/analyzers/emcopilot.py +92 -0
  15. fabgate-0.1.0/src/kitty/analyzers/gerber_dfm.py +112 -0
  16. fabgate-0.1.0/src/kitty/analyzers/kicad_drc.py +236 -0
  17. fabgate-0.1.0/src/kitty/analyzers/layout_rules.py +218 -0
  18. fabgate-0.1.0/src/kitty/analyzers/stub.py +41 -0
  19. fabgate-0.1.0/src/kitty/audit.py +97 -0
  20. fabgate-0.1.0/src/kitty/auto_fixers/__init__.py +3 -0
  21. fabgate-0.1.0/src/kitty/auto_fixers/pcb_mutations.py +242 -0
  22. fabgate-0.1.0/src/kitty/autonomous.py +182 -0
  23. fabgate-0.1.0/src/kitty/cli.py +564 -0
  24. fabgate-0.1.0/src/kitty/config/default_rules.yaml +36 -0
  25. fabgate-0.1.0/src/kitty/config/design_spec.example.yaml +24 -0
  26. fabgate-0.1.0/src/kitty/config/product.yaml +13 -0
  27. fabgate-0.1.0/src/kitty/design.py +303 -0
  28. fabgate-0.1.0/src/kitty/emcopilot_client.py +140 -0
  29. fabgate-0.1.0/src/kitty/evaluate.py +197 -0
  30. fabgate-0.1.0/src/kitty/export_bundle.py +57 -0
  31. fabgate-0.1.0/src/kitty/findings_triage.py +108 -0
  32. fabgate-0.1.0/src/kitty/ingest.py +116 -0
  33. fabgate-0.1.0/src/kitty/kicad_paths.py +127 -0
  34. fabgate-0.1.0/src/kitty/kicad_project.py +130 -0
  35. fabgate-0.1.0/src/kitty/models.py +103 -0
  36. fabgate-0.1.0/src/kitty/optimize.py +383 -0
  37. fabgate-0.1.0/src/kitty/pipeline.py +88 -0
  38. fabgate-0.1.0/src/kitty/pkg_paths.py +11 -0
  39. fabgate-0.1.0/src/kitty/product_config.py +71 -0
  40. fabgate-0.1.0/src/kitty/scoring.py +107 -0
  41. fabgate-0.1.0/src/kitty/visualization.py +91 -0
  42. fabgate-0.1.0/src/kitty/workflow.py +110 -0
  43. fabgate-0.1.0/test-board.kicad_pcb +1 -0
  44. fabgate-0.1.0/test-board.kicad_prl +105 -0
  45. fabgate-0.1.0/tests/fixtures/gerber-good/board-B_Cu.gbr +2 -0
  46. fabgate-0.1.0/tests/fixtures/gerber-good/board-Edge_Cuts.gbr +2 -0
  47. fabgate-0.1.0/tests/fixtures/gerber-good/board-F_Cu.gbr +2 -0
  48. fabgate-0.1.0/tests/fixtures/gerber-good/board-F_Mask.gbr +2 -0
  49. fabgate-0.1.0/tests/fixtures/gerber-good/board-PTH.drl +2 -0
  50. fabgate-0.1.0/tests/test_audit.py +23 -0
  51. fabgate-0.1.0/tests/test_autonomous.py +168 -0
  52. fabgate-0.1.0/tests/test_design_optimize.py +92 -0
  53. fabgate-0.1.0/tests/test_drc_severity.py +23 -0
  54. fabgate-0.1.0/tests/test_emcopilot_client.py +14 -0
  55. fabgate-0.1.0/tests/test_export.py +24 -0
  56. fabgate-0.1.0/tests/test_gerber.py +42 -0
  57. fabgate-0.1.0/tests/test_improvements.py +88 -0
  58. fabgate-0.1.0/tests/test_ingest.py +14 -0
  59. fabgate-0.1.0/tests/test_kicad_drc.py +50 -0
  60. fabgate-0.1.0/tests/test_kicad_project.py +33 -0
  61. fabgate-0.1.0/tests/test_layout_rules.py +64 -0
  62. fabgate-0.1.0/tests/test_scoring.py +53 -0
  63. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/.github/ISSUE_TEMPLATE/bug_report.yml +36 -0
  64. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
  65. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/.github/PULL_REQUEST_TEMPLATE.md +12 -0
  66. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/.github/workflows/ci.yml +42 -0
  67. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/.github/workflows/release.yml +17 -0
  68. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/.gitignore +99 -0
  69. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/CHANGELOG.md +137 -0
  70. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/CONTRIBUTING.md +152 -0
  71. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/LICENSE +661 -0
  72. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/README.md +312 -0
  73. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/assets/logo-banner.svg +122 -0
  74. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/assets/logo.svg +134 -0
  75. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/CLAUDE_REVIEW_PLAYBOOK.md +301 -0
  76. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/MARKET_INTAKE_MATRIX.md +158 -0
  77. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/MCP_PCB_EMCopilot_Framework.docx +0 -0
  78. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/SELF_CRITIQUE_CHECKLIST.md +151 -0
  79. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/STANDARDS_COVERAGE_MATRIX.md +89 -0
  80. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/architecture.md +134 -0
  81. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagram_emc_test.svg +112 -0
  82. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagram_rf_chain.svg +130 -0
  83. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagram_stackup.svg +292 -0
  84. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/architecture.png +0 -0
  85. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/architecture.svg +110 -0
  86. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/emc_test.png +0 -0
  87. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/emc_test.svg +64 -0
  88. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/rf_analysis.png +0 -0
  89. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/rf_analysis.svg +63 -0
  90. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/stackup.png +0 -0
  91. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/stackup.svg +66 -0
  92. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/workflow.png +0 -0
  93. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/workflow.svg +64 -0
  94. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/generate_framework_doc.py +1557 -0
  95. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/index.md +65 -0
  96. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/superpowers/plans/2026-03-12-v1-production-ready.md +702 -0
  97. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/superpowers/plans/2026-03-13-report-builder.md +1097 -0
  98. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/superpowers/specs/2026-03-13-report-builder-design.md +310 -0
  99. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/tools.md +150 -0
  100. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/usage.md +125 -0
  101. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/examples/README.md +36 -0
  102. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/examples/cispr25_quick_scan.md +81 -0
  103. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/kicad_plugin/README.md +19 -0
  104. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/kicad_plugin/__init__.py +1 -0
  105. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/kicad_plugin/emcopilot_plugin.py +159 -0
  106. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/kicad_plugin/metadata.json +25 -0
  107. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/mkdocs.yml +82 -0
  108. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/pyproject.toml +117 -0
  109. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/__init__.py +3 -0
  110. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/__init__.py +119 -0
  111. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/antenna/__init__.py +23 -0
  112. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/antenna/cable_coupling.py +397 -0
  113. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/antenna/common_mode.py +413 -0
  114. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/antenna/slot_antenna.py +388 -0
  115. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/antenna/trace_antenna.py +424 -0
  116. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/comparison.py +261 -0
  117. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/dfm/__init__.py +22 -0
  118. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/dfm/assembly_check.py +677 -0
  119. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/dfm/component_placement.py +636 -0
  120. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/dfm/solder_paste.py +455 -0
  121. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/dfm/thermal_relief.py +435 -0
  122. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/dfm/tolerance_analysis.py +485 -0
  123. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/__init__.py +25 -0
  124. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/automotive_emc.py +279 -0
  125. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/clock_emi_analyzer.py +915 -0
  126. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/compliance_predictor.py +614 -0
  127. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/conducted_emissions.py +514 -0
  128. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/current_density.py +670 -0
  129. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/current_loop.py +354 -0
  130. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/emi_risk_scorer.py +1088 -0
  131. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/esd_assessment.py +511 -0
  132. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/filter_design.py +647 -0
  133. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/ground_island_analyzer.py +234 -0
  134. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/grounding.py +487 -0
  135. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/immunity.py +476 -0
  136. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/limits_provider.py +434 -0
  137. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/near_field.py +418 -0
  138. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/radiated_emissions.py +425 -0
  139. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/return_path_analyzer.py +820 -0
  140. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/rf_isolation_analyzer.py +213 -0
  141. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/shielding.py +425 -0
  142. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/smps_loop_analyzer.py +302 -0
  143. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/__init__.py +52 -0
  144. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/ddr_analyzer.py +819 -0
  145. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/ddr_topology.py +603 -0
  146. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/emmc_analyzer.py +432 -0
  147. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/ethernet_analyzer.py +501 -0
  148. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/length_matching.py +328 -0
  149. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/pcie_analyzer.py +481 -0
  150. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/pcie_link_budget.py +299 -0
  151. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/sdio_analyzer.py +397 -0
  152. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/usb_analyzer.py +545 -0
  153. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/__init__.py +44 -0
  154. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/cavity_resonance.py +182 -0
  155. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/current_profiler.py +1003 -0
  156. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/decap_adequacy_checker.py +191 -0
  157. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/decap_placement.py +578 -0
  158. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/pdn_analyzer.py +490 -0
  159. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/pdn_impedance.py +228 -0
  160. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/power_plane_analyzer.py +477 -0
  161. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/trace_current_validator.py +248 -0
  162. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/vrm_analyzer.py +481 -0
  163. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/__init__.py +21 -0
  164. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/coexistence_analyzer.py +445 -0
  165. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/crosstalk_analyzer.py +590 -0
  166. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/differential_pair.py +590 -0
  167. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/eye_diagram.py +330 -0
  168. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/gnss_analyzer.py +388 -0
  169. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/halow_analyzer.py +412 -0
  170. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/impedance_calculator.py +680 -0
  171. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/mode_conversion.py +295 -0
  172. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/rf_impedance_analyzer.py +256 -0
  173. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/rf_simulation_extractor.py +686 -0
  174. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/sparam_calculator.py +601 -0
  175. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/sparam_extractor.py +291 -0
  176. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/via_modeler.py +566 -0
  177. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/__init__.py +26 -0
  178. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/_normalise.py +197 -0
  179. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/component_rating.py +149 -0
  180. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/decoupling_per_ic.py +152 -0
  181. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/power_topology.py +228 -0
  182. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/protection_circuits.py +237 -0
  183. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/signal_flow.py +287 -0
  184. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/signal_integrity/__init__.py +13 -0
  185. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/signal_integrity/crosstalk_analyzer.py +374 -0
  186. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/signal_integrity/diff_pair_width_checker.py +157 -0
  187. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/signal_integrity/ibis_eye.py +1393 -0
  188. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/signal_integrity/impedance_validator.py +576 -0
  189. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/signal_integrity/return_path_viz.py +598 -0
  190. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/stackup_optimizer.py +948 -0
  191. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/thermal/__init__.py +33 -0
  192. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/thermal/copper_spreading.py +310 -0
  193. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/thermal/hotspot_detector.py +299 -0
  194. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/thermal/power_dissipation.py +375 -0
  195. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/thermal/thermal_via.py +341 -0
  196. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/__init__.py +32 -0
  197. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/bom_cross_reference.py +278 -0
  198. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/bom_validator.py +147 -0
  199. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/copper_pour_checker.py +193 -0
  200. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/cross_validator.py +820 -0
  201. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/reference_design_db.py +135 -0
  202. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/revision_comparator.py +98 -0
  203. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/schematic_layout_validator.py +176 -0
  204. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/three_way_xref.py +344 -0
  205. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/classifiers/__init__.py +17 -0
  206. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/classifiers/design_classifier.py +473 -0
  207. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/classifiers/interface_detector.py +708 -0
  208. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/classifiers/net_classifier.py +651 -0
  209. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/errors.py +116 -0
  210. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/integrations/__init__.py +1 -0
  211. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/integrations/drawio_bridge.py +173 -0
  212. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/integrations/external_actions.py +167 -0
  213. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/integrations/nec2_bridge.py +144 -0
  214. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/integrations/openems_bridge.py +977 -0
  215. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/integrations/regulations_bridge.py +222 -0
  216. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/market_packs.py +502 -0
  217. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/models/__init__.py +17 -0
  218. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/models/common.py +37 -0
  219. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/models/pcb_data.py +225 -0
  220. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/orchestrator.py +2264 -0
  221. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/__init__.py +672 -0
  222. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/_pin_net_geometric.py +109 -0
  223. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/allegro_parser.py +755 -0
  224. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/altium_parser.py +2047 -0
  225. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/bom_parser.py +316 -0
  226. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/gerber_parser.py +1324 -0
  227. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/ibis_parser.py +694 -0
  228. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/ipc2581_parser.py +965 -0
  229. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/kicad_pcb_parser.py +916 -0
  230. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/netlist_parser.py +196 -0
  231. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/odb_models.py +374 -0
  232. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/odb_parser.py +1929 -0
  233. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/pdf_schematic_parser.py +395 -0
  234. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/schematic_dispatch.py +232 -0
  235. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/schematic_parser.py +566 -0
  236. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/stackup_parser.py +479 -0
  237. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/step_parser.py +931 -0
  238. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/touchstone_parser.py +665 -0
  239. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/py.typed +0 -0
  240. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/review_context.py +550 -0
  241. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/review_playbook.py +456 -0
  242. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/server.py +3669 -0
  243. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/session.py +176 -0
  244. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/standards/__init__.py +23 -0
  245. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/standards/coverage.py +335 -0
  246. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/standards/preflight.py +153 -0
  247. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/visualization/__init__.py +11 -0
  248. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/visualization/annotator.py +306 -0
  249. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/visualization/board_renderer.py +578 -0
  250. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/visualization/exporter.py +117 -0
  251. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/visualization/finding_annotator.py +304 -0
  252. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/visualization/stackup_renderer.py +265 -0
  253. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/web/__init__.py +1 -0
  254. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/web/app.py +415 -0
  255. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/web/cli.py +20 -0
  256. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/conftest.py +111 -0
  257. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/README.md +43 -0
  258. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/generate_schematic_pdf.py +96 -0
  259. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/mixed_signal_4layer.kicad_pcb +312 -0
  260. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/mixed_signal_4layer.kicad_prl +105 -0
  261. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample.SchDoc +0 -0
  262. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample.ibis +40 -0
  263. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample.s2p +8 -0
  264. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_2sheet.kicad_sch +83 -0
  265. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_allegro.txt +152 -0
  266. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_channel.s2p +29 -0
  267. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_design.xml +110 -0
  268. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_io.ibs +130 -0
  269. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_netlist.NET +31 -0
  270. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_schematic.pdf +67 -0
  271. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_top_copper.gbr +42 -0
  272. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/simple_2layer.kicad_pcb +139 -0
  273. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/simple_2layer.kicad_prl +105 -0
  274. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_all_tools_smoke.py +225 -0
  275. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_allegro_parser.py +574 -0
  276. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_altium_parameter_records.py +340 -0
  277. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_altium_parser_smoke.py +173 -0
  278. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_analysis_cache.py +30 -0
  279. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_automotive_emc.py +186 -0
  280. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_cavity_resonance.py +507 -0
  281. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_comparison.py +197 -0
  282. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_conducted_emissions.py +330 -0
  283. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_current_density_and_emi.py +629 -0
  284. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_drawio_bridge.py +106 -0
  285. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_end_to_end_review.py +110 -0
  286. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_errors.py +157 -0
  287. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_export_and_report.py +298 -0
  288. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_external_actions.py +176 -0
  289. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_eye_and_ddr.py +660 -0
  290. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_filter_design.py +390 -0
  291. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_format_detection.py +134 -0
  292. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_gerber_parser.py +183 -0
  293. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_html_report.py +773 -0
  294. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_ibis_eye.py +582 -0
  295. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_ibis_parser.py +458 -0
  296. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_immunity.py +387 -0
  297. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_integration_odb.py +395 -0
  298. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_ipc2581_parser.py +227 -0
  299. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_kicad_parser.py +397 -0
  300. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_kicad_plugin.py +48 -0
  301. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_kicad_schematic_parser.py +104 -0
  302. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_limits_provider.py +159 -0
  303. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_low_coverage_analyzers.py +147 -0
  304. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_low_coverage_parsers.py +168 -0
  305. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_more_coverage.py +246 -0
  306. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_near_field.py +511 -0
  307. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_nec2_bridge.py +108 -0
  308. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_netlist_parser.py +104 -0
  309. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_odb_synthetic_fixture.py +169 -0
  310. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_openems_attach_loop.py +201 -0
  311. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_openems_bridge.py +637 -0
  312. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_orchestrator.py +832 -0
  313. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_orchestrator_skip_branches.py +125 -0
  314. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_parser_errors.py +217 -0
  315. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_pcb_start_professional_review.py +141 -0
  316. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_pdf_schematic.py +825 -0
  317. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_pdn_and_pcie.py +517 -0
  318. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_phase3_mcp_tools.py +289 -0
  319. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_phase4_mcp_tools.py +185 -0
  320. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_phase4b_mcp_tools.py +163 -0
  321. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_preflight.py +119 -0
  322. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_regulations_bridge.py +115 -0
  323. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_report_builder.py +219 -0
  324. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_return_path_and_emi.py +474 -0
  325. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_return_path_viz.py +256 -0
  326. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_review_context_multi_market.py +159 -0
  327. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_review_finding_schema.py +89 -0
  328. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_review_playbook.py +267 -0
  329. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_schematic_analyzers.py +295 -0
  330. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_schematic_dispatch.py +93 -0
  331. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_section_registry.py +74 -0
  332. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_signal_flow.py +140 -0
  333. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_sparam_and_mode.py +403 -0
  334. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_specialty_analyzers_smoke.py +287 -0
  335. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_stackup_optimizer.py +356 -0
  336. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_standards_coverage.py +91 -0
  337. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_step_parser.py +918 -0
  338. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_test_plan.py +422 -0
  339. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_tool_validation.py +595 -0
  340. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_touchstone_parser.py +385 -0
  341. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_tracked_finding.py +192 -0
  342. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_visualization.py +674 -0
  343. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_web_app.py +111 -0
  344. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/uv.lock +2240 -0
  345. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/README.md +33 -0
  346. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/package.json +43 -0
  347. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/postcss.config.js +6 -0
  348. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/__tests__/app.test.tsx +11 -0
  349. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/__tests__/smoke.test.tsx +3 -0
  350. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/api/client.ts +745 -0
  351. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/components/PCBViewer/LayerControls.tsx +95 -0
  352. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/components/PCBViewer/PCBCanvas.tsx +438 -0
  353. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/components/PCBViewer/PCBViewer.tsx +158 -0
  354. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/components/PCBViewer/ViewControls.tsx +76 -0
  355. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/components/PCBViewer/index.ts +2 -0
  356. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/components/ThermalMapViewer.tsx +579 -0
  357. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/main.tsx +78 -0
  358. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/AIReviewPage.tsx +444 -0
  359. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/AnalysisReportPage.tsx +600 -0
  360. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/FindingsViewerPage.tsx +1022 -0
  361. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/ProjectDetailPage.tsx +352 -0
  362. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/ProjectsPage.tsx +118 -0
  363. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/ResultsViewerPage.tsx +832 -0
  364. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/RuleEditorPage.tsx +815 -0
  365. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/RuleViolationsPage.tsx +576 -0
  366. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/SimulationConfigPage.tsx +503 -0
  367. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/ViolationsPanel.tsx +638 -0
  368. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/styles.css +276 -0
  369. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/tailwind.config.js +8 -0
  370. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/tsconfig.json +19 -0
  371. fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/vite.config.ts +3 -0
@@ -0,0 +1,13 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .pytest_cache/
8
+ .mypy_cache/
9
+ .ruff_cache/
10
+ *.html
11
+ reports/
12
+ .kitty/
13
+ .env
fabgate-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 coderlifevyn12
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
fabgate-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,114 @@
1
+ Metadata-Version: 2.4
2
+ Name: fabgate
3
+ Version: 0.1.0
4
+ Summary: Pre-fab PCB design review and release gate for KiCad boards
5
+ Project-URL: Homepage, https://pypi.org/project/fabgate/
6
+ Project-URL: Repository, https://github.com/coderlifevyn12/fabgate
7
+ Author: coderlifevyn12
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: dfm,drc,emc,hardware,kicad,pcb,release-gate
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: pydantic-settings>=2.3.0
23
+ Requires-Dist: pydantic>=2.7.0
24
+ Requires-Dist: pyyaml>=6.0
25
+ Requires-Dist: rich>=13.7.0
26
+ Requires-Dist: typer>=0.12.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=8.0; extra == 'dev'
29
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
30
+ Provides-Extra: emcopilot
31
+ Requires-Dist: matplotlib>=3.10.8; extra == 'emcopilot'
32
+ Requires-Dist: mcp>=1.0.0; extra == 'emcopilot'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # FabGate
36
+
37
+ Pre-fab PCB design review and release gate for KiCad boards.
38
+
39
+ **v0.1** — evaluate your board, get a scored pass/hold/fail report, and a fix checklist before fabrication.
40
+
41
+ ## Prerequisites
42
+
43
+ - [Python 3.11+](https://www.python.org/downloads/)
44
+ - [KiCad 9+](https://www.kicad.org/download/) with `kicad-cli` available
45
+
46
+ ## Install
47
+
48
+ ```powershell
49
+ pip install fabgate
50
+ ```
51
+
52
+ Optional deep physics review (EMC / power / signal integrity):
53
+
54
+ ```powershell
55
+ pip install "fabgate[emcopilot]"
56
+ ```
57
+
58
+ ## Quick start
59
+
60
+ ```powershell
61
+ # Check toolchain
62
+ fabgate doctor
63
+
64
+ # Review an existing KiCad project
65
+ fabgate evaluate "C:\path\to\your-kicad-project"
66
+
67
+ # CI / release gate (exit 0=pass, 1=hold, 2=fail)
68
+ fabgate gate "C:\path\to\your-kicad-project"
69
+
70
+ # Open board in KiCad
71
+ fabgate open "C:\path\to\your-kicad-project"
72
+ ```
73
+
74
+ Reports are written to `reports/` as HTML + JSON.
75
+
76
+ ## What it checks
77
+
78
+ | Check | Engine |
79
+ |-------|--------|
80
+ | DRC violations | KiCad `kicad-cli` |
81
+ | Schematic parity | KiCad |
82
+ | EMC / power / SI physics | emcopilot (optional) |
83
+ | Scoring + pass/hold/fail | FabGate rules |
84
+
85
+ FabGate does **not** call an LLM. It uses deterministic KiCad and physics-based analyzers.
86
+
87
+ ## Commands
88
+
89
+ | Command | Purpose |
90
+ |---------|---------|
91
+ | `fabgate doctor` | Check KiCad CLI + optional emcopilot |
92
+ | `fabgate evaluate` | Full evaluation + HTML report |
93
+ | `fabgate review` | Basic review |
94
+ | `fabgate gate` | CI exit code |
95
+ | `fabgate optimize run` | Optimization plan + safe auto-fixes |
96
+ | `fabgate auto run` | Autonomous optimize loop (with rollback guardrail) |
97
+ | `fabgate design create` | Scaffold new KiCad project |
98
+ | `fabgate workflow` | Design → evaluate → optimize |
99
+ | `fabgate open` | Open in KiCad GUI |
100
+
101
+ ## Development install
102
+
103
+ ```powershell
104
+ git clone <repo-url>
105
+ cd fabgate
106
+ python -m venv .venv
107
+ .\.venv\Scripts\Activate.ps1
108
+ pip install -e ".[dev,emcopilot]"
109
+ fabgate doctor
110
+ ```
111
+
112
+ ## License
113
+
114
+ MIT
@@ -0,0 +1,80 @@
1
+ # FabGate
2
+
3
+ Pre-fab PCB design review and release gate for KiCad boards.
4
+
5
+ **v0.1** — evaluate your board, get a scored pass/hold/fail report, and a fix checklist before fabrication.
6
+
7
+ ## Prerequisites
8
+
9
+ - [Python 3.11+](https://www.python.org/downloads/)
10
+ - [KiCad 9+](https://www.kicad.org/download/) with `kicad-cli` available
11
+
12
+ ## Install
13
+
14
+ ```powershell
15
+ pip install fabgate
16
+ ```
17
+
18
+ Optional deep physics review (EMC / power / signal integrity):
19
+
20
+ ```powershell
21
+ pip install "fabgate[emcopilot]"
22
+ ```
23
+
24
+ ## Quick start
25
+
26
+ ```powershell
27
+ # Check toolchain
28
+ fabgate doctor
29
+
30
+ # Review an existing KiCad project
31
+ fabgate evaluate "C:\path\to\your-kicad-project"
32
+
33
+ # CI / release gate (exit 0=pass, 1=hold, 2=fail)
34
+ fabgate gate "C:\path\to\your-kicad-project"
35
+
36
+ # Open board in KiCad
37
+ fabgate open "C:\path\to\your-kicad-project"
38
+ ```
39
+
40
+ Reports are written to `reports/` as HTML + JSON.
41
+
42
+ ## What it checks
43
+
44
+ | Check | Engine |
45
+ |-------|--------|
46
+ | DRC violations | KiCad `kicad-cli` |
47
+ | Schematic parity | KiCad |
48
+ | EMC / power / SI physics | emcopilot (optional) |
49
+ | Scoring + pass/hold/fail | FabGate rules |
50
+
51
+ FabGate does **not** call an LLM. It uses deterministic KiCad and physics-based analyzers.
52
+
53
+ ## Commands
54
+
55
+ | Command | Purpose |
56
+ |---------|---------|
57
+ | `fabgate doctor` | Check KiCad CLI + optional emcopilot |
58
+ | `fabgate evaluate` | Full evaluation + HTML report |
59
+ | `fabgate review` | Basic review |
60
+ | `fabgate gate` | CI exit code |
61
+ | `fabgate optimize run` | Optimization plan + safe auto-fixes |
62
+ | `fabgate auto run` | Autonomous optimize loop (with rollback guardrail) |
63
+ | `fabgate design create` | Scaffold new KiCad project |
64
+ | `fabgate workflow` | Design → evaluate → optimize |
65
+ | `fabgate open` | Open in KiCad GUI |
66
+
67
+ ## Development install
68
+
69
+ ```powershell
70
+ git clone <repo-url>
71
+ cd fabgate
72
+ python -m venv .venv
73
+ .\.venv\Scripts\Activate.ps1
74
+ pip install -e ".[dev,emcopilot]"
75
+ fabgate doctor
76
+ ```
77
+
78
+ ## License
79
+
80
+ MIT
@@ -0,0 +1,36 @@
1
+ # Kitty Release Gate — default scoring rules (v1)
2
+ # Severity: blocking | warning | info
3
+
4
+ version: "1.0"
5
+
6
+ thresholds:
7
+ pass_score: 80
8
+ hold_score: 60
9
+
10
+ weights:
11
+ blocking: 12
12
+ warning: 3
13
+ info: 1
14
+
15
+ # Prevent large boards with many cosmetic DRC items from scoring 0/100.
16
+ penalty_caps:
17
+ blocking: 48
18
+ warning: 36
19
+ info: 12
20
+
21
+ categories:
22
+ - id: drc
23
+ label: Design Rule Check
24
+ enabled: true
25
+ - id: emc
26
+ label: EMC Pre-Compliance
27
+ enabled: true
28
+ - id: si
29
+ label: Signal Integrity
30
+ enabled: true
31
+ - id: pi
32
+ label: Power Integrity
33
+ enabled: true
34
+ - id: dfm
35
+ label: Design for Manufacturing
36
+ enabled: true
@@ -0,0 +1,24 @@
1
+ # Kitty design spec — used by: kitty design create --spec design_spec.yaml
2
+
3
+ name: my-carrier-board
4
+ company: Acme Corp
5
+
6
+ # Board outline (mm)
7
+ width_mm: 80
8
+ height_mm: 60
9
+ layers: 4 # 2 or 4
10
+ thickness_mm: 1.6
11
+
12
+ # Design intent (drives stackup / review recommendations)
13
+ interfaces:
14
+ - usb
15
+ - ethernet
16
+ - gpio
17
+
18
+ power_rails:
19
+ - "+3V3"
20
+ - "+5V"
21
+ - GND
22
+
23
+ notes: |
24
+ Carrier board for module X. Target 4-layer stackup with solid GND plane.
@@ -0,0 +1,13 @@
1
+ # Kitty Release Gate — product configuration
2
+ product:
3
+ name: "Kitty Release Gate"
4
+ version: "0.3.0"
5
+ tagline: "Autonomous PCB design, evaluation, and optimization release gate"
6
+
7
+ report:
8
+ company_name: "" # set via kitty init or edit here
9
+ footer: "Advisory report — engineering sign-off required before fabrication."
10
+
11
+ audit:
12
+ enabled: true
13
+ directory: ".kitty/audit"
@@ -0,0 +1,64 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "fabgate"
7
+ version = "0.1.0"
8
+ description = "Pre-fab PCB design review and release gate for KiCad boards"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.11"
12
+ authors = [
13
+ { name = "coderlifevyn12" },
14
+ ]
15
+ keywords = ["pcb", "kicad", "drc", "emc", "dfm", "release-gate", "hardware"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Environment :: Console",
19
+ "Intended Audience :: Developers",
20
+ "Intended Audience :: Science/Research",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Operating System :: OS Independent",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
27
+ ]
28
+ dependencies = [
29
+ "pydantic>=2.7.0",
30
+ "pydantic-settings>=2.3.0",
31
+ "pyyaml>=6.0",
32
+ "rich>=13.7.0",
33
+ "typer>=0.12.0",
34
+ ]
35
+
36
+ [project.optional-dependencies]
37
+ dev = [
38
+ "pytest>=8.0",
39
+ "ruff>=0.4.0",
40
+ ]
41
+ emcopilot = [
42
+ "matplotlib>=3.10.8",
43
+ "mcp>=1.0.0",
44
+ ]
45
+
46
+ [project.urls]
47
+ Homepage = "https://pypi.org/project/fabgate/"
48
+ Repository = "https://github.com/coderlifevyn12/fabgate"
49
+
50
+ [project.scripts]
51
+ fabgate = "kitty.cli:app"
52
+
53
+ [tool.hatch.build.targets.wheel]
54
+ packages = ["kitty"]
55
+
56
+ [tool.hatch.build.targets.wheel.force-include]
57
+ "src/kitty" = "kitty"
58
+
59
+ [tool.pytest.ini_options]
60
+ testpaths = ["tests"]
61
+
62
+ [tool.ruff]
63
+ line-length = 100
64
+ target-version = "py311"
@@ -0,0 +1,3 @@
1
+ """FabGate — pre-fab PCB review and release gate."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,3 @@
1
+ from kitty.cli import app
2
+
3
+ app()
@@ -0,0 +1,29 @@
1
+ from kitty.analyzers.base import Analyzer
2
+ from kitty.analyzers.emcopilot import EmcopilotAnalyzer
3
+ from kitty.analyzers.gerber_dfm import GerberDfmAnalyzer
4
+ from kitty.analyzers.kicad_drc import KiCadDrcAnalyzer
5
+ from kitty.analyzers.layout_rules import LayoutRulesAnalyzer
6
+ from kitty.analyzers.stub import StubAnalyzer
7
+ from kitty.emcopilot_client import emcopilot_available
8
+
9
+ __all__ = [
10
+ "Analyzer",
11
+ "EmcopilotAnalyzer",
12
+ "GerberDfmAnalyzer",
13
+ "KiCadDrcAnalyzer",
14
+ "LayoutRulesAnalyzer",
15
+ "StubAnalyzer",
16
+ "default_analyzers",
17
+ ]
18
+
19
+
20
+ def default_analyzers() -> list[Analyzer]:
21
+ analyzers: list[Analyzer] = [
22
+ KiCadDrcAnalyzer(),
23
+ LayoutRulesAnalyzer(),
24
+ GerberDfmAnalyzer(),
25
+ EmcopilotAnalyzer(),
26
+ ]
27
+ if not emcopilot_available():
28
+ analyzers.append(StubAnalyzer("si", "Signal Integrity", "si"))
29
+ return analyzers
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
4
+ from pathlib import Path
5
+
6
+ from kitty.models import AnalyzerResult, LayoutFormat
7
+
8
+
9
+ class Analyzer(ABC):
10
+ analyzer_id: str
11
+ analyzer_name: str
12
+
13
+ @abstractmethod
14
+ def supports(self, layout_format: LayoutFormat) -> bool:
15
+ raise NotImplementedError
16
+
17
+ @abstractmethod
18
+ def run(self, layout_path: Path, layout_format: LayoutFormat) -> AnalyzerResult:
19
+ raise NotImplementedError
@@ -0,0 +1,50 @@
1
+ from __future__ import annotations
2
+
3
+ from kitty.models import Severity
4
+
5
+ # KiCad DRC types that are fab-critical — always treat as blocking when KiCad says error.
6
+ DRC_CRITICAL_TYPES = {
7
+ "copper_edge_clearance",
8
+ "clearance",
9
+ "shorting_items",
10
+ "unconnected_items",
11
+ "unconnected",
12
+ "zones_intersect",
13
+ "zone_has_empty_net",
14
+ "invalid_outline",
15
+ "malformed_courtyard",
16
+ "duplicate_footprints",
17
+ "lib_footprint_mismatch",
18
+ "lib_footprint_issues",
19
+ "track_dangling",
20
+ "via_dangling",
21
+ }
22
+
23
+ # Cosmetic / documentation checks — downgrade KiCad warnings to info for release scoring.
24
+ DRC_COSMETIC_TYPES = {
25
+ "solder_mask_bridge",
26
+ "silk_overlap",
27
+ "silk_edge_clearance",
28
+ "silk_over_copper",
29
+ "text_thickness",
30
+ "text_height",
31
+ "gr_text",
32
+ "duplicate_silkscreen",
33
+ "silkscreen_over_copper",
34
+ }
35
+
36
+
37
+ def map_kicad_drc_severity(*, kicad_severity: str, violation_type: str) -> Severity:
38
+ normalized = (kicad_severity or "error").lower()
39
+ vtype = (violation_type or "").lower()
40
+
41
+ if normalized == "error":
42
+ if vtype in DRC_COSMETIC_TYPES:
43
+ return Severity.WARNING
44
+ return Severity.BLOCKING
45
+
46
+ if vtype in DRC_CRITICAL_TYPES:
47
+ return Severity.WARNING
48
+ if vtype in DRC_COSMETIC_TYPES:
49
+ return Severity.INFO
50
+ return Severity.WARNING
@@ -0,0 +1,92 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+ from pathlib import Path
5
+
6
+ from kitty.analyzers.base import Analyzer
7
+ from kitty.emcopilot_client import (
8
+ EMCOPILOT_INSTALL,
9
+ emcopilot_available,
10
+ emcopilot_finding_to_kitty,
11
+ run_emcopilot_review,
12
+ )
13
+ from kitty.models import AnalyzerResult, Finding, LayoutFormat, Severity
14
+
15
+
16
+ class EmcopilotAnalyzer(Analyzer):
17
+ """Physics-based EMC / SI / PI review via mcp-pcb-emcopilot."""
18
+
19
+ analyzer_id = "emcopilot"
20
+ analyzer_name = "EMC / SI / PI Physics Review"
21
+
22
+ def supports(self, layout_format: LayoutFormat) -> bool:
23
+ return layout_format in {LayoutFormat.KICAD, LayoutFormat.GERBER}
24
+
25
+ def run(self, layout_path: Path, layout_format: LayoutFormat) -> AnalyzerResult:
26
+ started = time.perf_counter()
27
+
28
+ if not emcopilot_available():
29
+ return AnalyzerResult(
30
+ analyzer_id=self.analyzer_id,
31
+ analyzer_name=self.analyzer_name,
32
+ status="not_installed",
33
+ findings=[
34
+ Finding(
35
+ id="emcopilot-not-installed",
36
+ category="emc",
37
+ severity=Severity.INFO,
38
+ title="Deep physics review not enabled",
39
+ message="mcp-pcb-emcopilot is not installed in this environment.",
40
+ recommendation=EMCOPILOT_INSTALL,
41
+ )
42
+ ],
43
+ duration_ms=int((time.perf_counter() - started) * 1000),
44
+ )
45
+
46
+ session_id = f"kitty-{int(time.time())}"
47
+ try:
48
+ review = run_emcopilot_review(layout_path, layout_format, session_id)
49
+ except Exception as exc:
50
+ return AnalyzerResult(
51
+ analyzer_id=self.analyzer_id,
52
+ analyzer_name=self.analyzer_name,
53
+ status="error",
54
+ error=str(exc),
55
+ findings=[
56
+ Finding(
57
+ id="emcopilot-error",
58
+ category="emc",
59
+ severity=Severity.WARNING,
60
+ title="Emcopilot review failed",
61
+ message=str(exc),
62
+ recommendation="Verify the layout file is a valid KiCad PCB or Gerber copper layer.",
63
+ )
64
+ ],
65
+ duration_ms=int((time.perf_counter() - started) * 1000),
66
+ )
67
+
68
+ findings: list[Finding] = []
69
+ index = 0
70
+ for domain in review.domain_results:
71
+ for finding in domain.findings:
72
+ index += 1
73
+ findings.append(emcopilot_finding_to_kitty(finding, index))
74
+
75
+ status = "issues_found" if findings else "clean"
76
+ return AnalyzerResult(
77
+ analyzer_id=self.analyzer_id,
78
+ analyzer_name=self.analyzer_name,
79
+ status=status,
80
+ findings=findings,
81
+ metadata={
82
+ "executive_summary": review.executive_summary,
83
+ "detected_interfaces": review.detected_interfaces,
84
+ "design_classification": review.design_classification,
85
+ "recommendations": review.recommendations,
86
+ "domain_count": len(review.domain_results),
87
+ "finding_count": len(findings),
88
+ "schematic_sheets_loaded": getattr(review, "schematic_sheets_loaded", 0),
89
+ "schematic_warnings": getattr(review, "schematic_warnings", []),
90
+ },
91
+ duration_ms=int((time.perf_counter() - started) * 1000),
92
+ )
@@ -0,0 +1,112 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+ from pathlib import Path
5
+
6
+ from kitty.analyzers.base import Analyzer
7
+ from kitty.ingest import classify_gerber_files
8
+ from kitty.models import AnalyzerResult, Finding, LayoutFormat, Severity
9
+
10
+
11
+ class GerberDfmAnalyzer(Analyzer):
12
+ analyzer_id = "gerber_dfm"
13
+ analyzer_name = "Gerber Fab Readiness"
14
+
15
+ def supports(self, layout_format: LayoutFormat) -> bool:
16
+ return layout_format == LayoutFormat.GERBER
17
+
18
+ def run(self, layout_path: Path, layout_format: LayoutFormat) -> AnalyzerResult:
19
+ started = time.perf_counter()
20
+ gerber_dir = layout_path if layout_path.is_dir() else layout_path.parent
21
+ layers = classify_gerber_files(gerber_dir)
22
+ findings: list[Finding] = []
23
+
24
+ if not layers["all_files"]:
25
+ return AnalyzerResult(
26
+ analyzer_id=self.analyzer_id,
27
+ analyzer_name=self.analyzer_name,
28
+ status="error",
29
+ error=f"No Gerber files found in {gerber_dir}",
30
+ duration_ms=int((time.perf_counter() - started) * 1000),
31
+ )
32
+
33
+ if not layers["copper_top"] and not layers["copper_bottom"]:
34
+ findings.append(
35
+ Finding(
36
+ id="gerber-no-copper",
37
+ category="dfm",
38
+ severity=Severity.BLOCKING,
39
+ title="No copper layers in Gerber package",
40
+ message="Could not find top or bottom copper files.",
41
+ recommendation="Include F_Cu/GTL and/or B_Cu/GBL in the fab upload.",
42
+ )
43
+ )
44
+
45
+ if not layers["outline"]:
46
+ findings.append(
47
+ Finding(
48
+ id="gerber-no-outline",
49
+ category="dfm",
50
+ severity=Severity.BLOCKING,
51
+ title="No board outline in Gerber package",
52
+ message="Could not find Edge_Cuts/GKO/GM1 outline layer.",
53
+ recommendation="Export the board outline layer for CAM processing.",
54
+ )
55
+ )
56
+
57
+ if not layers["drill"]:
58
+ findings.append(
59
+ Finding(
60
+ id="gerber-no-drill",
61
+ category="dfm",
62
+ severity=Severity.WARNING,
63
+ title="No drill files detected",
64
+ message="No Excellon/NC drill files found.",
65
+ recommendation="Include drill files if the board has plated holes.",
66
+ )
67
+ )
68
+
69
+ if not layers["mask_top"] and not layers["mask_bottom"]:
70
+ findings.append(
71
+ Finding(
72
+ id="gerber-no-mask",
73
+ category="dfm",
74
+ severity=Severity.WARNING,
75
+ title="No solder mask layers",
76
+ message="Soldermask layers were not found.",
77
+ recommendation="Export F/B soldermask for standard fab flows.",
78
+ )
79
+ )
80
+
81
+ if not layers["silk_top"] and not layers["silk_bottom"]:
82
+ findings.append(
83
+ Finding(
84
+ id="gerber-no-silk",
85
+ category="dfm",
86
+ severity=Severity.INFO,
87
+ title="No silkscreen layers",
88
+ message="Silkscreen layers were not found.",
89
+ recommendation="Add silkscreen if component reference designators are needed.",
90
+ )
91
+ )
92
+
93
+ if len(layers["all_files"]) < 4:
94
+ findings.append(
95
+ Finding(
96
+ id="gerber-thin-package",
97
+ category="dfm",
98
+ severity=Severity.INFO,
99
+ title="Minimal Gerber package",
100
+ message=f"Only {len(layers['all_files'])} Gerber/drill file(s) detected.",
101
+ recommendation="Verify the full fab package (copper, mask, silk, outline, drill).",
102
+ )
103
+ )
104
+
105
+ status = "issues_found" if findings else "clean"
106
+ return AnalyzerResult(
107
+ analyzer_id=self.analyzer_id,
108
+ analyzer_name=self.analyzer_name,
109
+ status=status,
110
+ findings=findings,
111
+ duration_ms=int((time.perf_counter() - started) * 1000),
112
+ )