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.
- fabgate-0.1.0/.gitignore +13 -0
- fabgate-0.1.0/LICENSE +21 -0
- fabgate-0.1.0/PKG-INFO +114 -0
- fabgate-0.1.0/README.md +80 -0
- fabgate-0.1.0/config/default_rules.yaml +36 -0
- fabgate-0.1.0/config/design_spec.example.yaml +24 -0
- fabgate-0.1.0/config/product.yaml +13 -0
- fabgate-0.1.0/pyproject.toml +64 -0
- fabgate-0.1.0/src/kitty/__init__.py +3 -0
- fabgate-0.1.0/src/kitty/__main__.py +3 -0
- fabgate-0.1.0/src/kitty/analyzers/__init__.py +29 -0
- fabgate-0.1.0/src/kitty/analyzers/base.py +19 -0
- fabgate-0.1.0/src/kitty/analyzers/drc_severity.py +50 -0
- fabgate-0.1.0/src/kitty/analyzers/emcopilot.py +92 -0
- fabgate-0.1.0/src/kitty/analyzers/gerber_dfm.py +112 -0
- fabgate-0.1.0/src/kitty/analyzers/kicad_drc.py +236 -0
- fabgate-0.1.0/src/kitty/analyzers/layout_rules.py +218 -0
- fabgate-0.1.0/src/kitty/analyzers/stub.py +41 -0
- fabgate-0.1.0/src/kitty/audit.py +97 -0
- fabgate-0.1.0/src/kitty/auto_fixers/__init__.py +3 -0
- fabgate-0.1.0/src/kitty/auto_fixers/pcb_mutations.py +242 -0
- fabgate-0.1.0/src/kitty/autonomous.py +182 -0
- fabgate-0.1.0/src/kitty/cli.py +564 -0
- fabgate-0.1.0/src/kitty/config/default_rules.yaml +36 -0
- fabgate-0.1.0/src/kitty/config/design_spec.example.yaml +24 -0
- fabgate-0.1.0/src/kitty/config/product.yaml +13 -0
- fabgate-0.1.0/src/kitty/design.py +303 -0
- fabgate-0.1.0/src/kitty/emcopilot_client.py +140 -0
- fabgate-0.1.0/src/kitty/evaluate.py +197 -0
- fabgate-0.1.0/src/kitty/export_bundle.py +57 -0
- fabgate-0.1.0/src/kitty/findings_triage.py +108 -0
- fabgate-0.1.0/src/kitty/ingest.py +116 -0
- fabgate-0.1.0/src/kitty/kicad_paths.py +127 -0
- fabgate-0.1.0/src/kitty/kicad_project.py +130 -0
- fabgate-0.1.0/src/kitty/models.py +103 -0
- fabgate-0.1.0/src/kitty/optimize.py +383 -0
- fabgate-0.1.0/src/kitty/pipeline.py +88 -0
- fabgate-0.1.0/src/kitty/pkg_paths.py +11 -0
- fabgate-0.1.0/src/kitty/product_config.py +71 -0
- fabgate-0.1.0/src/kitty/scoring.py +107 -0
- fabgate-0.1.0/src/kitty/visualization.py +91 -0
- fabgate-0.1.0/src/kitty/workflow.py +110 -0
- fabgate-0.1.0/test-board.kicad_pcb +1 -0
- fabgate-0.1.0/test-board.kicad_prl +105 -0
- fabgate-0.1.0/tests/fixtures/gerber-good/board-B_Cu.gbr +2 -0
- fabgate-0.1.0/tests/fixtures/gerber-good/board-Edge_Cuts.gbr +2 -0
- fabgate-0.1.0/tests/fixtures/gerber-good/board-F_Cu.gbr +2 -0
- fabgate-0.1.0/tests/fixtures/gerber-good/board-F_Mask.gbr +2 -0
- fabgate-0.1.0/tests/fixtures/gerber-good/board-PTH.drl +2 -0
- fabgate-0.1.0/tests/test_audit.py +23 -0
- fabgate-0.1.0/tests/test_autonomous.py +168 -0
- fabgate-0.1.0/tests/test_design_optimize.py +92 -0
- fabgate-0.1.0/tests/test_drc_severity.py +23 -0
- fabgate-0.1.0/tests/test_emcopilot_client.py +14 -0
- fabgate-0.1.0/tests/test_export.py +24 -0
- fabgate-0.1.0/tests/test_gerber.py +42 -0
- fabgate-0.1.0/tests/test_improvements.py +88 -0
- fabgate-0.1.0/tests/test_ingest.py +14 -0
- fabgate-0.1.0/tests/test_kicad_drc.py +50 -0
- fabgate-0.1.0/tests/test_kicad_project.py +33 -0
- fabgate-0.1.0/tests/test_layout_rules.py +64 -0
- fabgate-0.1.0/tests/test_scoring.py +53 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/.github/ISSUE_TEMPLATE/bug_report.yml +36 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/.github/PULL_REQUEST_TEMPLATE.md +12 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/.github/workflows/ci.yml +42 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/.github/workflows/release.yml +17 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/.gitignore +99 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/CHANGELOG.md +137 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/CONTRIBUTING.md +152 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/LICENSE +661 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/README.md +312 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/assets/logo-banner.svg +122 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/assets/logo.svg +134 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/CLAUDE_REVIEW_PLAYBOOK.md +301 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/MARKET_INTAKE_MATRIX.md +158 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/MCP_PCB_EMCopilot_Framework.docx +0 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/SELF_CRITIQUE_CHECKLIST.md +151 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/STANDARDS_COVERAGE_MATRIX.md +89 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/architecture.md +134 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagram_emc_test.svg +112 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagram_rf_chain.svg +130 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagram_stackup.svg +292 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/architecture.png +0 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/architecture.svg +110 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/emc_test.png +0 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/emc_test.svg +64 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/rf_analysis.png +0 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/rf_analysis.svg +63 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/stackup.png +0 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/stackup.svg +66 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/workflow.png +0 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/diagrams/workflow.svg +64 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/generate_framework_doc.py +1557 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/index.md +65 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/superpowers/plans/2026-03-12-v1-production-ready.md +702 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/superpowers/plans/2026-03-13-report-builder.md +1097 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/superpowers/specs/2026-03-13-report-builder-design.md +310 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/tools.md +150 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/docs/usage.md +125 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/examples/README.md +36 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/examples/cispr25_quick_scan.md +81 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/kicad_plugin/README.md +19 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/kicad_plugin/__init__.py +1 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/kicad_plugin/emcopilot_plugin.py +159 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/kicad_plugin/metadata.json +25 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/mkdocs.yml +82 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/pyproject.toml +117 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/__init__.py +3 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/__init__.py +119 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/antenna/__init__.py +23 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/antenna/cable_coupling.py +397 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/antenna/common_mode.py +413 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/antenna/slot_antenna.py +388 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/antenna/trace_antenna.py +424 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/comparison.py +261 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/dfm/__init__.py +22 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/dfm/assembly_check.py +677 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/dfm/component_placement.py +636 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/dfm/solder_paste.py +455 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/dfm/thermal_relief.py +435 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/dfm/tolerance_analysis.py +485 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/__init__.py +25 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/automotive_emc.py +279 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/clock_emi_analyzer.py +915 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/compliance_predictor.py +614 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/conducted_emissions.py +514 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/current_density.py +670 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/current_loop.py +354 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/emi_risk_scorer.py +1088 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/esd_assessment.py +511 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/filter_design.py +647 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/ground_island_analyzer.py +234 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/grounding.py +487 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/immunity.py +476 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/limits_provider.py +434 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/near_field.py +418 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/radiated_emissions.py +425 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/return_path_analyzer.py +820 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/rf_isolation_analyzer.py +213 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/shielding.py +425 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/emc/smps_loop_analyzer.py +302 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/__init__.py +52 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/ddr_analyzer.py +819 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/ddr_topology.py +603 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/emmc_analyzer.py +432 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/ethernet_analyzer.py +501 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/length_matching.py +328 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/pcie_analyzer.py +481 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/pcie_link_budget.py +299 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/sdio_analyzer.py +397 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/high_speed/usb_analyzer.py +545 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/__init__.py +44 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/cavity_resonance.py +182 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/current_profiler.py +1003 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/decap_adequacy_checker.py +191 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/decap_placement.py +578 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/pdn_analyzer.py +490 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/pdn_impedance.py +228 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/power_plane_analyzer.py +477 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/trace_current_validator.py +248 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/power_integrity/vrm_analyzer.py +481 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/__init__.py +21 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/coexistence_analyzer.py +445 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/crosstalk_analyzer.py +590 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/differential_pair.py +590 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/eye_diagram.py +330 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/gnss_analyzer.py +388 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/halow_analyzer.py +412 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/impedance_calculator.py +680 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/mode_conversion.py +295 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/rf_impedance_analyzer.py +256 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/rf_simulation_extractor.py +686 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/sparam_calculator.py +601 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/sparam_extractor.py +291 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/rf_si/via_modeler.py +566 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/__init__.py +26 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/_normalise.py +197 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/component_rating.py +149 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/decoupling_per_ic.py +152 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/power_topology.py +228 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/protection_circuits.py +237 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/schematic/signal_flow.py +287 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/signal_integrity/__init__.py +13 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/signal_integrity/crosstalk_analyzer.py +374 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/signal_integrity/diff_pair_width_checker.py +157 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/signal_integrity/ibis_eye.py +1393 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/signal_integrity/impedance_validator.py +576 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/signal_integrity/return_path_viz.py +598 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/stackup_optimizer.py +948 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/thermal/__init__.py +33 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/thermal/copper_spreading.py +310 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/thermal/hotspot_detector.py +299 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/thermal/power_dissipation.py +375 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/thermal/thermal_via.py +341 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/__init__.py +32 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/bom_cross_reference.py +278 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/bom_validator.py +147 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/copper_pour_checker.py +193 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/cross_validator.py +820 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/reference_design_db.py +135 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/revision_comparator.py +98 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/schematic_layout_validator.py +176 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/analyzers/validation/three_way_xref.py +344 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/classifiers/__init__.py +17 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/classifiers/design_classifier.py +473 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/classifiers/interface_detector.py +708 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/classifiers/net_classifier.py +651 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/errors.py +116 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/integrations/__init__.py +1 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/integrations/drawio_bridge.py +173 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/integrations/external_actions.py +167 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/integrations/nec2_bridge.py +144 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/integrations/openems_bridge.py +977 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/integrations/regulations_bridge.py +222 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/market_packs.py +502 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/models/__init__.py +17 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/models/common.py +37 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/models/pcb_data.py +225 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/orchestrator.py +2264 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/__init__.py +672 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/_pin_net_geometric.py +109 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/allegro_parser.py +755 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/altium_parser.py +2047 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/bom_parser.py +316 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/gerber_parser.py +1324 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/ibis_parser.py +694 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/ipc2581_parser.py +965 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/kicad_pcb_parser.py +916 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/netlist_parser.py +196 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/odb_models.py +374 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/odb_parser.py +1929 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/pdf_schematic_parser.py +395 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/schematic_dispatch.py +232 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/schematic_parser.py +566 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/stackup_parser.py +479 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/step_parser.py +931 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/parsers/touchstone_parser.py +665 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/py.typed +0 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/review_context.py +550 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/review_playbook.py +456 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/server.py +3669 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/session.py +176 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/standards/__init__.py +23 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/standards/coverage.py +335 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/standards/preflight.py +153 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/visualization/__init__.py +11 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/visualization/annotator.py +306 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/visualization/board_renderer.py +578 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/visualization/exporter.py +117 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/visualization/finding_annotator.py +304 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/visualization/stackup_renderer.py +265 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/web/__init__.py +1 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/web/app.py +415 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/src/mcp_pcb_emcopilot/web/cli.py +20 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/conftest.py +111 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/README.md +43 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/generate_schematic_pdf.py +96 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/mixed_signal_4layer.kicad_pcb +312 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/mixed_signal_4layer.kicad_prl +105 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample.SchDoc +0 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample.ibis +40 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample.s2p +8 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_2sheet.kicad_sch +83 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_allegro.txt +152 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_channel.s2p +29 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_design.xml +110 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_io.ibs +130 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_netlist.NET +31 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_schematic.pdf +67 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/sample_top_copper.gbr +42 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/simple_2layer.kicad_pcb +139 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/fixtures/simple_2layer.kicad_prl +105 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_all_tools_smoke.py +225 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_allegro_parser.py +574 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_altium_parameter_records.py +340 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_altium_parser_smoke.py +173 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_analysis_cache.py +30 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_automotive_emc.py +186 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_cavity_resonance.py +507 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_comparison.py +197 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_conducted_emissions.py +330 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_current_density_and_emi.py +629 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_drawio_bridge.py +106 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_end_to_end_review.py +110 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_errors.py +157 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_export_and_report.py +298 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_external_actions.py +176 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_eye_and_ddr.py +660 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_filter_design.py +390 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_format_detection.py +134 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_gerber_parser.py +183 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_html_report.py +773 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_ibis_eye.py +582 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_ibis_parser.py +458 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_immunity.py +387 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_integration_odb.py +395 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_ipc2581_parser.py +227 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_kicad_parser.py +397 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_kicad_plugin.py +48 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_kicad_schematic_parser.py +104 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_limits_provider.py +159 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_low_coverage_analyzers.py +147 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_low_coverage_parsers.py +168 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_more_coverage.py +246 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_near_field.py +511 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_nec2_bridge.py +108 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_netlist_parser.py +104 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_odb_synthetic_fixture.py +169 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_openems_attach_loop.py +201 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_openems_bridge.py +637 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_orchestrator.py +832 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_orchestrator_skip_branches.py +125 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_parser_errors.py +217 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_pcb_start_professional_review.py +141 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_pdf_schematic.py +825 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_pdn_and_pcie.py +517 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_phase3_mcp_tools.py +289 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_phase4_mcp_tools.py +185 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_phase4b_mcp_tools.py +163 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_preflight.py +119 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_regulations_bridge.py +115 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_report_builder.py +219 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_return_path_and_emi.py +474 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_return_path_viz.py +256 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_review_context_multi_market.py +159 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_review_finding_schema.py +89 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_review_playbook.py +267 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_schematic_analyzers.py +295 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_schematic_dispatch.py +93 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_section_registry.py +74 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_signal_flow.py +140 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_sparam_and_mode.py +403 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_specialty_analyzers_smoke.py +287 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_stackup_optimizer.py +356 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_standards_coverage.py +91 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_step_parser.py +918 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_test_plan.py +422 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_tool_validation.py +595 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_touchstone_parser.py +385 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_tracked_finding.py +192 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_visualization.py +674 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/tests/test_web_app.py +111 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/uv.lock +2240 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/README.md +33 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/package.json +43 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/postcss.config.js +6 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/__tests__/app.test.tsx +11 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/__tests__/smoke.test.tsx +3 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/api/client.ts +745 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/components/PCBViewer/LayerControls.tsx +95 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/components/PCBViewer/PCBCanvas.tsx +438 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/components/PCBViewer/PCBViewer.tsx +158 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/components/PCBViewer/ViewControls.tsx +76 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/components/PCBViewer/index.ts +2 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/components/ThermalMapViewer.tsx +579 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/main.tsx +78 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/AIReviewPage.tsx +444 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/AnalysisReportPage.tsx +600 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/FindingsViewerPage.tsx +1022 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/ProjectDetailPage.tsx +352 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/ProjectsPage.tsx +118 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/ResultsViewerPage.tsx +832 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/RuleEditorPage.tsx +815 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/RuleViolationsPage.tsx +576 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/SimulationConfigPage.tsx +503 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/pages/ViolationsPanel.tsx +638 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/src/styles.css +276 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/tailwind.config.js +8 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/tsconfig.json +19 -0
- fabgate-0.1.0/vendor/mcp-pcb-emcopilot/web-ui/vite.config.ts +3 -0
fabgate-0.1.0/.gitignore
ADDED
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
|
fabgate-0.1.0/README.md
ADDED
|
@@ -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,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
|
+
)
|