@hybridlabor-api/bdb-hardware-pcb 0.1.0
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.
- package/README.md +116 -0
- package/config/mcp/antigravity.json +22 -0
- package/config/mcp/claude.json +22 -0
- package/config/mcp/codex.toml +25 -0
- package/docs/adr/ADR-001-KICAD-OPENSCAD-MCP-STRATEGY.md +334 -0
- package/docs/review_documentation.md +121 -0
- package/installer.js +358 -0
- package/mcp_servers/kicad-mcp-server/.env.example +22 -0
- package/mcp_servers/kicad-mcp-server/.github/workflows/ci.yml +36 -0
- package/mcp_servers/kicad-mcp-server/CLAUDE.md +487 -0
- package/mcp_servers/kicad-mcp-server/README.md +316 -0
- package/mcp_servers/kicad-mcp-server/docs/DEVICE_TREE.md +416 -0
- package/mcp_servers/kicad-mcp-server/docs/INSTALLATION.md +332 -0
- package/mcp_servers/kicad-mcp-server/docs/PIN_ANALYSIS.md +332 -0
- package/mcp_servers/kicad-mcp-server/docs/README.md +240 -0
- package/mcp_servers/kicad-mcp-server/docs/TESTING.md +613 -0
- package/mcp_servers/kicad-mcp-server/docs/VALIDATION.md +268 -0
- package/mcp_servers/kicad-mcp-server/pyproject.toml +96 -0
- package/mcp_servers/kicad-mcp-server/requirements-dev.txt +16 -0
- package/mcp_servers/kicad-mcp-server/requirements-test.txt +24 -0
- package/mcp_servers/kicad-mcp-server/requirements.txt +13 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/__init__.py +3 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/__main__.py +17 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/config.py +46 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/models/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/models/types.py +87 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/netlist_parser.py +234 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/pcb_parser.py +375 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/pcb_parser_kicad.py +327 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/parsers/schematic_parser.py +902 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/server.py +71 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/arduino/connectivity_test.cpp.j2 +189 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/atmega.dts.j2 +77 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/esp32.dts.j2 +77 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/nrf52.dts.j2 +77 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/device_tree/stm32f4.dts.j2 +89 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/esp_idf/test_suite.c.j2 +340 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/pytest/test_connectivity.py.j2 +147 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/st_hal/hal_test.c.j2 +313 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_gpio_test.py.j2 +99 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_i2c_test.py.j2 +117 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_pinmux_test.py.j2 +43 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/pytest_spi_test.py.j2 +94 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/unity_gpio_test.c.j2 +113 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/unity_i2c_test.c.j2 +101 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/tests/unity_spi_test.c.j2 +94 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/templates/unittest/test_schematic.py.j2 +172 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/__init__.py +36 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/device_tree.py +1187 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/hierarchical_analysis.py +211 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/netlist.py +320 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/parts_registry.py +142 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/pcb.py +955 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/pcb_layout.py +308 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/pin_analysis.py +765 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/project.py +196 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/schematic.py +319 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/schematic_editor.py +674 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/schematic_search.py +158 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/validation.py +866 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/tools/visualization.py +225 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/file_handlers.py +65 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/kicad_cli.py +103 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/kicad_version.py +103 -0
- package/mcp_servers/kicad-mcp-server/src/kicad_mcp_server/utils/parts_registry.py +197 -0
- package/mcp_servers/kicad-mcp-server/tests/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/tests/examples/ESP32S3_TEST.md +219 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/README.md +65 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/example_pcb.kicad_pcb +177 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/example_schematic.kicad_sch +145 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/hier/child.kicad_sch +24 -0
- package/mcp_servers/kicad-mcp-server/tests/fixtures/hier/root.kicad_sch +38 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/__init__.py +1 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_hierarchical_labels.py +195 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_kicad_cli.py +116 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_netlist_cache_path.py +29 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_schematic.py +189 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_schematic_hierarchy.py +69 -0
- package/mcp_servers/kicad-mcp-server/tests/test_tools/test_visualization.py +136 -0
- package/mcp_servers/kicad-mcp-server/uv.lock +2873 -0
- package/mcp_servers/openscad-mcp-server/.dockerignore +9 -0
- package/mcp_servers/openscad-mcp-server/.github/workflows/test.yml +40 -0
- package/mcp_servers/openscad-mcp-server/Dockerfile +29 -0
- package/mcp_servers/openscad-mcp-server/LICENSE +21 -0
- package/mcp_servers/openscad-mcp-server/README.md +154 -0
- package/mcp_servers/openscad-mcp-server/docs/audit.md +56 -0
- package/mcp_servers/openscad-mcp-server/docs/docker.md +66 -0
- package/mcp_servers/openscad-mcp-server/docs/issue-followup.md +19 -0
- package/mcp_servers/openscad-mcp-server/docs/jetson.md +17 -0
- package/mcp_servers/openscad-mcp-server/glama.json +4 -0
- package/mcp_servers/openscad-mcp-server/legacy/README.md +15 -0
- package/mcp_servers/openscad-mcp-server/legacy/README.original.md +294 -0
- package/mcp_servers/openscad-mcp-server/legacy/implementation_plan.md +100 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/download_sam2_checkpoint.py +115 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/src/ai/sam_segmentation.py +209 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/src/models/threestudio_generator.py +231 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/src/workflow/image_to_model_pipeline.py +260 -0
- package/mcp_servers/openscad-mcp-server/legacy/old/test_sam2_segmentation.py +96 -0
- package/mcp_servers/openscad-mcp-server/legacy/requirements.txt +57 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/README.md +39 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/decisions/ai-driven-code-generation.md +122 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/decisions/export-formats.md +76 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/ai/ai_service.py.md +51 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/main.py.md +63 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/models/code_generator.py.md +63 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/files/src/nlp/parameter_extractor.py.md +63 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/ai/natural-language-processing.md +78 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/nlp/parameter-extraction.md +173 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/openscad/export-formats.md +91 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/openscad/openscad-basics.md +66 -0
- package/mcp_servers/openscad-mcp-server/legacy/rtfmd/knowledge/openscad/primitive-testing.md +79 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/ai/ai_service.py +257 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/ai/gemini_api.py +161 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/ai/venice_api.py +203 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/config.py +121 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/main.py +1456 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/main.py.new +404 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/main_remote.py +401 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/models/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/models/code_generator.py +321 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/models/cuda_mvs.py +209 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/models/scad_templates/basic_shapes.scad +144 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/nlp/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/nlp/parameter_extractor.py +388 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/openscad_wrapper/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/openscad_wrapper/wrapper.py +418 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/printer_discovery/__init__.py +1 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/printer_discovery/printer_discovery.py +471 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/remote/connection_manager.py +537 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/remote/cuda_mvs_client.py +435 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/remote/cuda_mvs_server.py +787 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/remote/error_handling.py +415 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/testing/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/testing/primitive_tester.py +203 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/testing/test_primitives.py +98 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/__init__.py +1 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/cad_exporter.py +241 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/format_validator.py +206 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/stl_exporter.py +140 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/stl_repair.py +91 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/utils/stl_validator.py +123 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/visualization/__init__.py +0 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/visualization/headless_renderer.py +52 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/visualization/renderer.py +177 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/visualization/web_interface.py +639 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/workflow/image_approval.py +148 -0
- package/mcp_servers/openscad-mcp-server/legacy/src/workflow/multi_view_to_model_pipeline.py +338 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_complete_workflow.py +374 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_cuda_mvs.py +191 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_gemini_api.py +168 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_image_approval.py +192 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_image_approval_workflow.py +251 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_image_to_model_pipeline.py +145 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_model_selection.py +41 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_multi_view_pipeline.py +290 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_primitives.sh +13 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_rabbit_direct.py +71 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_remote_cuda_mvs.py +283 -0
- package/mcp_servers/openscad-mcp-server/legacy/test_venice_example.py +69 -0
- package/mcp_servers/openscad-mcp-server/pyproject.toml +33 -0
- package/mcp_servers/openscad-mcp-server/requirements.txt +2 -0
- package/mcp_servers/openscad-mcp-server/scad/simple_cube.scad +2 -0
- package/mcp_servers/openscad-mcp-server/scripts/test_docker.py +220 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/__init__.py +3 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/__main__.py +3 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/engine.py +94 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/geometry.py +242 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/server.py +245 -0
- package/mcp_servers/openscad-mcp-server/src/openscad_mcp/service.py +190 -0
- package/mcp_servers/openscad-mcp-server/tests/conftest.py +17 -0
- package/mcp_servers/openscad-mcp-server/tests/test_engine.py +37 -0
- package/mcp_servers/openscad-mcp-server/tests/test_geometry.py +106 -0
- package/mcp_servers/openscad-mcp-server/tests/test_integration.py +172 -0
- package/mcp_servers/openscad-mcp-server/tests/test_transports.py +314 -0
- package/mcp_servers/openscad-mcp-server/uv.lock +1123 -0
- package/package.json +44 -0
- package/scripts/install_mcps.sh +86 -0
- package/scripts/openscad_wrapper.sh +62 -0
- package/scripts/run_kicad_mcp.sh +25 -0
- package/scripts/run_openscad_mcp.sh +41 -0
- package/scripts/test_mcp_connection.py +626 -0
- package/scripts/test_mcp_connection.sh +168 -0
- package/skills/code-first-hardware-design/SKILL.md +260 -0
- package/skills/pcb-constraint-definition/SKILL.md +236 -0
- package/skills/pcb-layout-routing-automation/SKILL.md +153 -0
- package/skills/pcb-validation-dfm-signoff/SKILL.md +194 -0
- package/skills/schematic-datasheet-analysis/SKILL.md +202 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ==============================================================================
|
|
3
|
+
# AOS MCP Verification Test Suite Runner
|
|
4
|
+
# ==============================================================================
|
|
5
|
+
# Companion bash script to execute scripts/test_mcp_connection.py against
|
|
6
|
+
# KiCad and OpenSCAD MCP servers, individual configs, and harnesses.
|
|
7
|
+
# ==============================================================================
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
12
|
+
REPO_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
13
|
+
PYTHON="${PYTHON:-python3}"
|
|
14
|
+
VERIFIER="${SCRIPT_DIR}/test_mcp_connection.py"
|
|
15
|
+
|
|
16
|
+
# Ensure all scripts have executable permissions
|
|
17
|
+
chmod +x "${SCRIPT_DIR}/"*.sh 2>/dev/null || true
|
|
18
|
+
|
|
19
|
+
print_usage() {
|
|
20
|
+
echo "Usage: $0 [OPTIONS]"
|
|
21
|
+
echo ""
|
|
22
|
+
echo "Options:"
|
|
23
|
+
echo " --all Run complete test suite across runners and all config files"
|
|
24
|
+
echo " --kicad Test KiCad MCP server runner only"
|
|
25
|
+
echo " --openscad Test OpenSCAD MCP server runner only"
|
|
26
|
+
echo " --antigravity Test config/mcp/antigravity.json"
|
|
27
|
+
echo " --claude Test config/mcp/claude.json"
|
|
28
|
+
echo " --codex Test config/mcp/codex.toml"
|
|
29
|
+
echo " --configs Test all three multi-harness config files"
|
|
30
|
+
echo " --export-schemas Export Antigravity lazy schemas into ~/.gemini/antigravity-cli/mcp/"
|
|
31
|
+
echo " --report PATH Generate a machine-readable JSON verification report"
|
|
32
|
+
echo " --help Show this help message"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
REPORT_FILE=""
|
|
36
|
+
MODE="default"
|
|
37
|
+
|
|
38
|
+
while [[ $# -gt 0 ]]; do
|
|
39
|
+
case "$1" in
|
|
40
|
+
--all)
|
|
41
|
+
MODE="all"
|
|
42
|
+
shift
|
|
43
|
+
;;
|
|
44
|
+
--kicad)
|
|
45
|
+
MODE="kicad"
|
|
46
|
+
shift
|
|
47
|
+
;;
|
|
48
|
+
--openscad)
|
|
49
|
+
MODE="openscad"
|
|
50
|
+
shift
|
|
51
|
+
;;
|
|
52
|
+
--antigravity)
|
|
53
|
+
MODE="antigravity"
|
|
54
|
+
shift
|
|
55
|
+
;;
|
|
56
|
+
--claude)
|
|
57
|
+
MODE="claude"
|
|
58
|
+
shift
|
|
59
|
+
;;
|
|
60
|
+
--codex)
|
|
61
|
+
MODE="codex"
|
|
62
|
+
shift
|
|
63
|
+
;;
|
|
64
|
+
--configs)
|
|
65
|
+
MODE="configs"
|
|
66
|
+
shift
|
|
67
|
+
;;
|
|
68
|
+
--export-schemas)
|
|
69
|
+
MODE="export"
|
|
70
|
+
shift
|
|
71
|
+
;;
|
|
72
|
+
--report)
|
|
73
|
+
REPORT_FILE="$2"
|
|
74
|
+
shift 2
|
|
75
|
+
;;
|
|
76
|
+
--help|-h)
|
|
77
|
+
print_usage
|
|
78
|
+
exit 0
|
|
79
|
+
;;
|
|
80
|
+
*)
|
|
81
|
+
echo "Unknown option: $1" >&2
|
|
82
|
+
print_usage
|
|
83
|
+
exit 1
|
|
84
|
+
;;
|
|
85
|
+
esac
|
|
86
|
+
done
|
|
87
|
+
|
|
88
|
+
EXTRA_ARGS=()
|
|
89
|
+
if [[ -n "${REPORT_FILE}" ]]; then
|
|
90
|
+
EXTRA_ARGS+=("--json-report" "${REPORT_FILE}")
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# config/mcp/*.json|.toml are portable reference templates (placeholder
|
|
94
|
+
# __INSTALL_DIR__, no machine-specific path baked in — see their header
|
|
95
|
+
# comments). installer.js never reads them; it generates real configs at
|
|
96
|
+
# install time. For local verification only, resolve the placeholder to this
|
|
97
|
+
# checkout's actual path in a throwaway temp copy.
|
|
98
|
+
RESOLVED_TMP_FILES=()
|
|
99
|
+
cleanup_resolved_configs() {
|
|
100
|
+
for f in "${RESOLVED_TMP_FILES[@]+"${RESOLVED_TMP_FILES[@]}"}"; do
|
|
101
|
+
rm -f "$f"
|
|
102
|
+
done
|
|
103
|
+
}
|
|
104
|
+
trap cleanup_resolved_configs EXIT
|
|
105
|
+
|
|
106
|
+
resolve_config() {
|
|
107
|
+
local src="$1"
|
|
108
|
+
local ext="${src##*.}"
|
|
109
|
+
local tmp
|
|
110
|
+
tmp="$(mktemp "${TMPDIR:-/tmp}/mcp_config.XXXXXX")"
|
|
111
|
+
mv "${tmp}" "${tmp}.${ext}"
|
|
112
|
+
tmp="${tmp}.${ext}"
|
|
113
|
+
sed "s#__INSTALL_DIR__#${REPO_DIR}#g" "${src}" > "${tmp}"
|
|
114
|
+
RESOLVED_TMP_FILES+=("${tmp}")
|
|
115
|
+
echo "${tmp}"
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
case "${MODE}" in
|
|
119
|
+
default)
|
|
120
|
+
echo "Running default MCP connection verification..."
|
|
121
|
+
"${PYTHON}" "${VERIFIER}" ${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"}
|
|
122
|
+
;;
|
|
123
|
+
kicad)
|
|
124
|
+
echo "Testing KiCad MCP Server Runner..."
|
|
125
|
+
"${PYTHON}" "${VERIFIER}" --command "${SCRIPT_DIR}/run_kicad_mcp.sh" ${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"}
|
|
126
|
+
;;
|
|
127
|
+
openscad)
|
|
128
|
+
echo "Testing OpenSCAD MCP Server Runner..."
|
|
129
|
+
"${PYTHON}" "${VERIFIER}" --command "${SCRIPT_DIR}/run_openscad_mcp.sh" ${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"}
|
|
130
|
+
;;
|
|
131
|
+
antigravity)
|
|
132
|
+
echo "Testing Antigravity MCP Config (config/mcp/antigravity.json)..."
|
|
133
|
+
"${PYTHON}" "${VERIFIER}" --config "$(resolve_config "${REPO_DIR}/config/mcp/antigravity.json")" ${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"}
|
|
134
|
+
;;
|
|
135
|
+
claude)
|
|
136
|
+
echo "Testing Claude Code MCP Config (config/mcp/claude.json)..."
|
|
137
|
+
"${PYTHON}" "${VERIFIER}" --config "$(resolve_config "${REPO_DIR}/config/mcp/claude.json")" ${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"}
|
|
138
|
+
;;
|
|
139
|
+
codex)
|
|
140
|
+
echo "Testing Codex MCP Config (config/mcp/codex.toml)..."
|
|
141
|
+
"${PYTHON}" "${VERIFIER}" --config "$(resolve_config "${REPO_DIR}/config/mcp/codex.toml")" ${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"}
|
|
142
|
+
;;
|
|
143
|
+
configs)
|
|
144
|
+
echo "Testing all multi-harness configuration files..."
|
|
145
|
+
echo "--- 1. Testing Antigravity Configuration ---"
|
|
146
|
+
"${PYTHON}" "${VERIFIER}" --config "$(resolve_config "${REPO_DIR}/config/mcp/antigravity.json")"
|
|
147
|
+
echo "--- 2. Testing Claude Code Configuration ---"
|
|
148
|
+
"${PYTHON}" "${VERIFIER}" --config "$(resolve_config "${REPO_DIR}/config/mcp/claude.json")"
|
|
149
|
+
echo "--- 3. Testing OpenAI Codex Configuration ---"
|
|
150
|
+
"${PYTHON}" "${VERIFIER}" --config "$(resolve_config "${REPO_DIR}/config/mcp/codex.toml")" ${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"}
|
|
151
|
+
;;
|
|
152
|
+
export)
|
|
153
|
+
TARGET_DIR="${HOME}/.gemini/antigravity-cli/mcp"
|
|
154
|
+
echo "Exporting lazy tool JSON schemas to ${TARGET_DIR}..."
|
|
155
|
+
"${PYTHON}" "${VERIFIER}" --export-antigravity "${TARGET_DIR}" ${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"}
|
|
156
|
+
;;
|
|
157
|
+
all)
|
|
158
|
+
echo "Executing Full MCP Verification Suite..."
|
|
159
|
+
TARGET_DIR="${HOME}/.gemini/antigravity-cli/mcp"
|
|
160
|
+
"${PYTHON}" "${VERIFIER}" --export-antigravity "${TARGET_DIR}"
|
|
161
|
+
echo "--- Testing Antigravity Config ---"
|
|
162
|
+
"${PYTHON}" "${VERIFIER}" --config "$(resolve_config "${REPO_DIR}/config/mcp/antigravity.json")"
|
|
163
|
+
echo "--- Testing Claude Code Config ---"
|
|
164
|
+
"${PYTHON}" "${VERIFIER}" --config "$(resolve_config "${REPO_DIR}/config/mcp/claude.json")"
|
|
165
|
+
echo "--- Testing OpenAI Codex Config ---"
|
|
166
|
+
"${PYTHON}" "${VERIFIER}" --config "$(resolve_config "${REPO_DIR}/config/mcp/codex.toml")" ${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"}
|
|
167
|
+
;;
|
|
168
|
+
esac
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-first-hardware-design
|
|
3
|
+
description: "Programmatic schematic capture, circuit synthesis (SKiDL, text netlists, S-expressions), and parametric 3D CAD enclosure co-design (OpenSCAD/BOSL2). Use when generating circuits in code, exporting netlists, scripting KiCad schematics, or designing 3D enclosures."
|
|
4
|
+
category: engineering-hardware
|
|
5
|
+
compatibility: "Python 3.10+, SKiDL, OpenSCAD 2024+, BOSL2, mcp:openscad"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Code-First Hardware & Circuit Design
|
|
9
|
+
|
|
10
|
+
## 1. Overview and Core Philosophy
|
|
11
|
+
|
|
12
|
+
In the AOS autonomous engineering architecture, hardware design is treated as code. Graphical schematic and mechanical CAD entry are prone to hallucinated coordinates, misaligned pins, and drift between PCB and enclosure models.
|
|
13
|
+
|
|
14
|
+
This skill governs two tightly integrated code-first workflows:
|
|
15
|
+
1. **Programmatic Circuit Synthesis (SKiDL / S-Expressions)**: Generating electronic schematics, hierarchical sheets, and netlists via type-safe, reviewable Python code with built-in Electrical Rules Checks (ERC).
|
|
16
|
+
2. **Parametric Mechanical Co-Design (OpenSCAD / BOSL2)**: Generating production-ready 3D enclosures driven directly by exported PCB physical outlines, mounting hole centroids, and connector coordinates.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 2. Programmatic Circuit Synthesis via SKiDL
|
|
21
|
+
|
|
22
|
+
SKiDL allows circuits to be designed as Python programs. Components are instantiated from KiCad symbol libraries, connected via pythonic operator overloading, and compiled to netlists or KiCad schematic files.
|
|
23
|
+
|
|
24
|
+
### 2.1 The SKiDL Connection Paradigm
|
|
25
|
+
- **Nets**: Created as `Net('NAME')`.
|
|
26
|
+
- **Buses**: Created as `Bus('DATA', 8)`.
|
|
27
|
+
- **Connections**: Handled using the `+=` operator or list indexing:
|
|
28
|
+
```python
|
|
29
|
+
vcc = Net('VCC')
|
|
30
|
+
gnd = Net('GND')
|
|
31
|
+
r1 = Part('Device', 'R', value='10k', footprint='Resistor_SMD:R_0603_1608Metric')
|
|
32
|
+
c1 = Part('Device', 'C', value='100nF', footprint='Capacitor_SMD:C_0603_1608Metric')
|
|
33
|
+
# Connect in parallel across power rail
|
|
34
|
+
vcc += r1[1], c1[1]
|
|
35
|
+
gnd += r1[2], c1[2]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 2.2 Production Reference Circuit: Microcontroller Node with Power & USB
|
|
39
|
+
Below is a complete, executable SKiDL circuit module (`hardware_design.py`) that instantiates power regulation, an RP2040 MCU, crystal oscillator, decoupling, and USB-C protection:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
#!/usr/bin/env python3
|
|
43
|
+
"""
|
|
44
|
+
Production-grade Code-First Hardware Circuit Synthesis using SKiDL.
|
|
45
|
+
Generates KiCad netlist with built-in ERC validation.
|
|
46
|
+
"""
|
|
47
|
+
from skidl import *
|
|
48
|
+
|
|
49
|
+
# Set target EDA tool to KiCad
|
|
50
|
+
set_default_tool(KICAD)
|
|
51
|
+
|
|
52
|
+
# 1. Global Power & Ground Nets
|
|
53
|
+
vbus = Net('VBUS')
|
|
54
|
+
v3v3 = Net('+3V3')
|
|
55
|
+
gnd = Net('GND')
|
|
56
|
+
|
|
57
|
+
# 2. USB-C Input & ESD Protection
|
|
58
|
+
usbc = Part('Connector', 'USB_C_Receptacle_USB2.0', footprint='Connector_USB:USB_C_Receptacle_GCT_USB4105')
|
|
59
|
+
tvs = Part('Power_Protection', 'USBLC6-2SC6', footprint='Package_TO_SOT_SMD:SOT-23-6')
|
|
60
|
+
|
|
61
|
+
# Ground receptacle shield and GND pins
|
|
62
|
+
gnd += usbc['GND*'], usbc['SHIELD'], tvs['GND']
|
|
63
|
+
vbus += usbc['VBUS*'], tvs['VBUS']
|
|
64
|
+
|
|
65
|
+
# CC Pull-Down Resistors (5.1k for standard 5V/3A UFP mode)
|
|
66
|
+
r_cc1 = Part('Device', 'R', value='5.1k', footprint='Resistor_SMD:R_0402_1005Metric')
|
|
67
|
+
r_cc2 = Part('Device', 'R', value='5.1k', footprint='Resistor_SMD:R_0402_1005Metric')
|
|
68
|
+
usbc['CC1'] += r_cc1[1]
|
|
69
|
+
usbc['CC2'] += r_cc2[1]
|
|
70
|
+
gnd += r_cc1[2], r_cc2[2]
|
|
71
|
+
|
|
72
|
+
# USB Data Lines through TVS
|
|
73
|
+
usb_dp = Net('USB_DP')
|
|
74
|
+
usb_dn = Net('USB_DN')
|
|
75
|
+
usbc['DP*'] += tvs['I/O1']
|
|
76
|
+
tvs['I/O1'] += usb_dp
|
|
77
|
+
usbc['DN*'] += tvs['I/O2']
|
|
78
|
+
tvs['I/O2'] += usb_dn
|
|
79
|
+
|
|
80
|
+
# 3. LDO Voltage Regulator (5V -> 3.3V, AP2112K-3.3)
|
|
81
|
+
ldo = Part('Regulator_Linear', 'AP2112K-3.3', footprint='Package_TO_SOT_SMD:SOT-23-5')
|
|
82
|
+
cin = Part('Device', 'C', value='4.7uF', footprint='Capacitor_SMD:C_0603_1608Metric')
|
|
83
|
+
cout = Part('Device', 'C', value='4.7uF', footprint='Capacitor_SMD:C_0603_1608Metric')
|
|
84
|
+
|
|
85
|
+
vbus += ldo['VIN'], ldo['EN'], cin[1]
|
|
86
|
+
gnd += ldo['GND'], cin[2], cout[2]
|
|
87
|
+
v3v3 += ldo['VOUT'], cout[1]
|
|
88
|
+
|
|
89
|
+
# 4. RP2040 Microcontroller
|
|
90
|
+
mcu = Part('MCU_RaspberryPi_RP2040', 'RP2040', footprint='Package_DFN_QFN:QFN-56-1EP_7x7mm_P0.4mm_EP3.2x3.2mm')
|
|
91
|
+
gnd += mcu['GND*'], mcu['EP']
|
|
92
|
+
v3v3 += mcu['IOVDD*'], mcu['USB_VDD'], mcu['VREG_IN']
|
|
93
|
+
|
|
94
|
+
# Connect USB Data
|
|
95
|
+
mcu['USB_DP'] += usb_dp
|
|
96
|
+
mcu['USB_DM'] += usb_dn
|
|
97
|
+
|
|
98
|
+
# Decoupling Array: 100nF per IOVDD pin
|
|
99
|
+
for pin in mcu.get_pins():
|
|
100
|
+
if 'IOVDD' in pin.name or 'VREG_IN' in pin.name:
|
|
101
|
+
c_dec = Part('Device', 'C', value='100nF', footprint='Capacitor_SMD:C_0402_1005Metric')
|
|
102
|
+
v3v3 += c_dec[1]
|
|
103
|
+
gnd += c_dec[2]
|
|
104
|
+
|
|
105
|
+
# 5. Execute Electrical Rules Check (ERC)
|
|
106
|
+
print("--> Running SKiDL Electrical Rules Check (ERC)...")
|
|
107
|
+
ERC()
|
|
108
|
+
|
|
109
|
+
# 6. Generate Netlist for KiCad
|
|
110
|
+
print("--> Compiling KiCad Netlist: board.net")
|
|
111
|
+
generate_netlist(file_='board.net')
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 3. Parametric Mechanical Enclosure Co-Design (OpenSCAD / BOSL2)
|
|
117
|
+
|
|
118
|
+
Hardware enclosure design must strictly depend on exported PCB physical measurements:
|
|
119
|
+
1. **Board Outline**: Ingested via `kicad-cli pcb export dxf --layers Edge.Cuts`.
|
|
120
|
+
2. **Mounting Hole Coordinates**: Ingested from the Centroid placement file (`board_positions.csv`).
|
|
121
|
+
3. **Connector Boundaries**: Aligned to exact component coordinates with manufacturing tolerances.
|
|
122
|
+
|
|
123
|
+
### 3.1 Tolerance Standards for Enclosure Fit
|
|
124
|
+
- **FDM 3D Printing (PLA / PETG)**:
|
|
125
|
+
- Internal cavity clearance around PCB perimeter: $+0.4\text{mm}$ per side.
|
|
126
|
+
- Connector cutouts (USB-C, HDMI): $+0.4\text{mm}$ height and width.
|
|
127
|
+
- Screw hole clearance: $+0.3\text{mm}$ (e.g., $3.3\text{mm}$ hole for M3 screw).
|
|
128
|
+
- Minimum wall thickness: $2.0\text{mm}$ for structural rigidity.
|
|
129
|
+
- **Heat-Set Threaded Inserts (Brass)**:
|
|
130
|
+
- M2 Insert: Hole diameter $3.2\text{mm}$, depth $4.0\text{mm}$, boss outer diameter $\ge 6.0\text{mm}$.
|
|
131
|
+
- M3 Insert: Hole diameter $4.0\text{mm}$, depth $5.7\text{mm}$, boss outer diameter $\ge 7.5\text{mm}$.
|
|
132
|
+
|
|
133
|
+
### 3.2 Production BOSL2 Enclosure Code (`enclosure.scad`)
|
|
134
|
+
The following script utilizes the **BOSL2** library for analytical rounding (avoiding `minkowski()`) and builds a parametric snap-together / screw-down enclosure with standoff bosses and port cutouts:
|
|
135
|
+
|
|
136
|
+
```openscad
|
|
137
|
+
// Production Parametric PCB Enclosure using BOSL2
|
|
138
|
+
// Run with: openscad -o enclosure.stl --backend=Manifold enclosure.scad
|
|
139
|
+
|
|
140
|
+
include <BOSL2/std.scad>
|
|
141
|
+
|
|
142
|
+
$fn = 64;
|
|
143
|
+
|
|
144
|
+
// --- Parametric Dimensions (Derived from PCB constraints.yaml) ---
|
|
145
|
+
pcb_w = 75.0; // PCB width in X
|
|
146
|
+
pcb_l = 45.0; // PCB length in Y
|
|
147
|
+
pcb_t = 1.6; // PCB thickness
|
|
148
|
+
xy_clearance = 0.4; // Tolerance per side
|
|
149
|
+
wall_t = 2.0; // Outer wall thickness
|
|
150
|
+
standoff_h = 5.0; // Clearance below PCB
|
|
151
|
+
ceiling_h = 12.0; // Component height ceiling above PCB
|
|
152
|
+
|
|
153
|
+
// Computed internal dimensions
|
|
154
|
+
int_w = pcb_w + (2 * xy_clearance);
|
|
155
|
+
int_l = pcb_l + (2 * xy_clearance);
|
|
156
|
+
int_h = standoff_h + pcb_t + ceiling_h;
|
|
157
|
+
|
|
158
|
+
// Outer dimensions
|
|
159
|
+
out_w = int_w + (2 * wall_t);
|
|
160
|
+
out_l = int_l + (2 * wall_t);
|
|
161
|
+
out_h = int_h + (2 * wall_t);
|
|
162
|
+
|
|
163
|
+
// Mounting Hole Locations relative to PCB center [X, Y]
|
|
164
|
+
mounting_holes = [
|
|
165
|
+
[-34.0, -19.0],
|
|
166
|
+
[ 34.0, -19.0],
|
|
167
|
+
[-34.0, 19.0],
|
|
168
|
+
[ 34.0, 19.0]
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
// --- Subassembly: Lower Enclosure Half ---
|
|
172
|
+
module bottom_case() {
|
|
173
|
+
difference() {
|
|
174
|
+
// Outer rounded shell
|
|
175
|
+
cuboid([out_w, out_l, out_h/2], rounding=3, edges="Z", anchor=BOTTOM) {
|
|
176
|
+
// Internal cavity cutout
|
|
177
|
+
attach(TOP, TOP, inside=true)
|
|
178
|
+
cuboid([int_w, int_l, (out_h/2) - wall_t], anchor=TOP);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// USB-C Connector Cutout (centered at X = -out_w/2, Z = standoff_h + pcb_t)
|
|
182
|
+
translate([-out_w/2, 0, standoff_h + pcb_t + 1.6])
|
|
183
|
+
cube([wall_t * 2, 9.6, 3.8], center=true);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Standoff Bosses with M3 Heat-Set Insert Pockets
|
|
187
|
+
for (pos = mounting_holes) {
|
|
188
|
+
translate([pos[0], pos[1], wall_t]) {
|
|
189
|
+
difference() {
|
|
190
|
+
// Cylindrical standoff boss
|
|
191
|
+
cylinder(h=standoff_h, r=3.8, center=false);
|
|
192
|
+
// Heat-set brass insert pocket (M3: dia 4.0mm, depth 5.0mm)
|
|
193
|
+
translate([0, 0, standoff_h - 4.8])
|
|
194
|
+
cylinder(h=5.0, r=2.0, center=false);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// --- Subassembly: Top Lid ---
|
|
201
|
+
module top_case() {
|
|
202
|
+
translate([0, out_l + 15, 0]) {
|
|
203
|
+
difference() {
|
|
204
|
+
cuboid([out_w, out_l, out_h/2], rounding=3, edges="Z", anchor=BOTTOM) {
|
|
205
|
+
attach(TOP, TOP, inside=true)
|
|
206
|
+
cuboid([int_w, int_l, (out_h/2) - wall_t], anchor=TOP);
|
|
207
|
+
}
|
|
208
|
+
// Ventilation slots
|
|
209
|
+
for (i = [-3:3]) {
|
|
210
|
+
translate([i * 6, 0, 0])
|
|
211
|
+
cube([2.5, int_l - 10, wall_t * 3], center=true);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Render complete assembly for 3D printing
|
|
218
|
+
bottom_case();
|
|
219
|
+
top_case();
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## 4. Automated Execution & Verification CLI Workflow
|
|
225
|
+
|
|
226
|
+
1. **Synthesize Circuit Netlist via SKiDL**:
|
|
227
|
+
```bash
|
|
228
|
+
python3 hardware_design.py
|
|
229
|
+
# Confirms ERC passes with 0 errors and writes board.net
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
2. **Ingest Physical Features from PCB via `kicad-cli`**:
|
|
233
|
+
```bash
|
|
234
|
+
# Export board outline DXF
|
|
235
|
+
kicad-cli pcb export dxf -o cad/board_outline.dxf --layers Edge.Cuts board.kicad_pcb
|
|
236
|
+
# Export mounting hole centroids
|
|
237
|
+
kicad-cli pcb export pos --format csv -o cad/board_positions.csv board.kicad_pcb
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
3. **Validate and Compile 3D Enclosure via OpenSCAD Manifold**:
|
|
241
|
+
```bash
|
|
242
|
+
# Fast syntax validation
|
|
243
|
+
openscad -o /dev/null --check-parameters true cad/enclosure.scad
|
|
244
|
+
|
|
245
|
+
# High-speed mesh compilation using the Manifold C++ engine
|
|
246
|
+
openscad -o cad/enclosure.stl --backend=Manifold cad/enclosure.scad
|
|
247
|
+
|
|
248
|
+
# Generate high-resolution perspective preview PNG
|
|
249
|
+
openscad -o cad/enclosure_preview.png --camera=0,0,0,55,0,25,180 --imgsize=1024,768 cad/enclosure.scad
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## 5. Negative Constraints (Anti-Slop Directives)
|
|
255
|
+
|
|
256
|
+
- **DO NOT** use OpenSCAD's `minkowski()` function to generate rounded edges on production enclosures. It is computationally intractable and will cause agent timeouts. Always use BOSL2's analytical `cuboid(..., rounding=..., edges=...)`.
|
|
257
|
+
- **DO NOT** guess mounting hole or connector positions. Coordinates must be read directly from `constraints.yaml` or exported from `kicad-cli pcb export pos`.
|
|
258
|
+
- **DO NOT** generate SKiDL circuits without running `ERC()` before netlist export. An unverified netlist is prohibited from passing to layout.
|
|
259
|
+
- **DO NOT** design 3D printable enclosures with wall thickness $<1.6\text{mm}$ or standoff bosses with wall thickness $<1.5\text{mm}$ around heat-set insert pockets (causes layer splitting upon insert press).
|
|
260
|
+
- **DO NOT** omit the $+0.4\text{mm}$ mechanical tolerance margin around PCB board edges when modeling internal enclosure cavities.
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pcb-constraint-definition
|
|
3
|
+
description: "Translates high-level hardware requirements into formal engineering constraints, layer stackup calculations, netclasses, and custom DRC rules for KiCad. Use when defining board constraints, stackup, impedance matching, power budgeting, or netclasses."
|
|
4
|
+
category: engineering-hardware
|
|
5
|
+
compatibility: "Python 3.10+, kicad-cli 8+, mcp:kicad"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# PCB Constraint & Specification Definition
|
|
9
|
+
|
|
10
|
+
## 1. Overview and Core Philosophy
|
|
11
|
+
|
|
12
|
+
In the AOS hardware engineering pipeline, constraints are not informal recommendations; they are formal, machine-executable boundary conditions. An AI hardware agent must never begin schematic capture or board layout with unconstrained nets or default 0.25mm trace widths.
|
|
13
|
+
|
|
14
|
+
This skill provides the mathematical models, layer stackup architectures, netclass definitions, and custom Design Rule Check (DRC) constraint files required to translate product specifications into production-ready physical parameters.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 2. Mathematical and Physical Foundations
|
|
19
|
+
|
|
20
|
+
All physical trace geometry and thermal boundaries must be derived from first principles and IPC standards:
|
|
21
|
+
|
|
22
|
+
### 2.1 Trace Current Capacity (IPC-2152)
|
|
23
|
+
The current carrying capacity $I$ (Amperes) for a given allowable temperature rise $\Delta T$ ($^\circ\text{C}$) and conductor cross-sectional area $A$ ($\text{mils}^2$) is calculated as:
|
|
24
|
+
|
|
25
|
+
$$I = k \cdot \Delta T^{0.44} \cdot A^{0.725}$$
|
|
26
|
+
|
|
27
|
+
Where:
|
|
28
|
+
- $k = 0.048$ for external surface microstrip traces (convective cooling).
|
|
29
|
+
- $k = 0.024$ for internal stripline traces (conductive cooling through dielectric only).
|
|
30
|
+
- $A = w \cdot t$, with trace width $w$ ($\text{mils}$) and copper thickness $t$ ($1\text{ oz} \approx 1.37\text{ mils} = 35\mu\text{m}$, $2\text{ oz} \approx 2.74\text{ mils} = 70\mu\text{m}$).
|
|
31
|
+
|
|
32
|
+
**Minimum Trace Width Calculation for DC Power Rails:**
|
|
33
|
+
To support a continuous current of $2.5\text{A}$ with $\Delta T = 10^\circ\text{C}$ on $1\text{ oz}$ external copper:
|
|
34
|
+
$$A = \left( \frac{I}{0.048 \cdot \Delta T^{0.44}} \right)^{\frac{1}{0.725}} = \left( \frac{2.5}{0.048 \cdot 10^{0.44}} \right)^{1.379} \approx 42.5\text{ mils}^2$$
|
|
35
|
+
$$w = \frac{A}{t} = \frac{42.5}{1.37} \approx 31.0\text{ mils} \approx 0.79\text{ mm}$$
|
|
36
|
+
|
|
37
|
+
### 2.2 Controlled Impedance Modeling (IPC-2141)
|
|
38
|
+
|
|
39
|
+
#### Single-Ended Microstrip (Surface Layer over Solid GND Plane)
|
|
40
|
+
Characteristic impedance $Z_0$ ($\Omega$):
|
|
41
|
+
$$Z_0 = \frac{87}{\sqrt{\varepsilon_r + 1.41}} \ln\left( \frac{5.98 h}{0.8 w + t} \right)$$
|
|
42
|
+
Valid for $0.1 < \frac{w}{h} < 3.0$ and $1 < \varepsilon_r < 15$.
|
|
43
|
+
- Standard FR-4 dielectric constant: $\varepsilon_r \approx 4.3 - 4.5$.
|
|
44
|
+
- For standard $h = 0.2\text{mm}$ (7.87 mils), $t = 35\mu\text{m}$ (1.37 mils), target $Z_0 = 50\Omega \implies w \approx 0.36\text{mm}$ (14.2 mils).
|
|
45
|
+
|
|
46
|
+
#### Edge-Coupled Differential Microstrip (USB 90Ω, Ethernet/PCIe 100Ω)
|
|
47
|
+
Differential impedance $Z_{diff}$ ($\Omega$):
|
|
48
|
+
$$Z_{diff} \approx 2 Z_0 \left( 1 - 0.48 e^{-0.96 \frac{s}{h}} \right)$$
|
|
49
|
+
Where $s$ is the edge-to-edge separation between the two complementary conductors, and $h$ is the dielectric height to the nearest solid reference plane.
|
|
50
|
+
|
|
51
|
+
### 2.3 Thermal Budgeting & Junction Temperature
|
|
52
|
+
For any active linear regulator or power switch:
|
|
53
|
+
$$T_J = T_A + P_D \cdot \theta_{JA}$$
|
|
54
|
+
$$P_D = (V_{in} - V_{out}) \cdot I_{load} + V_{in} \cdot I_Q$$
|
|
55
|
+
If $T_J > 105^\circ\text{C}$ at $T_A = 40^\circ\text{C}$ (maximum ambient), the agent must constrain:
|
|
56
|
+
1. Addition of a dedicated copper thermal pad connected via an array of thermal vias ($0.3\text{mm}$ drill, $0.6\text{mm}$ pitch).
|
|
57
|
+
2. Minimum copper plane area: $A_{Cu} \ge \frac{P_D \cdot 1000}{35}\text{ mm}^2$.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 3. Standard Layer Stackups
|
|
62
|
+
|
|
63
|
+
The agent must select one of the following industry-standard stackups based on circuit frequency and density:
|
|
64
|
+
|
|
65
|
+
### 3.1 4-Layer Standard Controlled-Impedance Stackup (JLC04161H-7628)
|
|
66
|
+
Total nominal thickness: $1.6\text{mm}$.
|
|
67
|
+
- **Layer 1 (Top Signal / High-Speed)**: $35\mu\text{m}$ Copper ($1\text{ oz}$)
|
|
68
|
+
- *Prepreg 7628*: $0.2104\text{mm}$, $\varepsilon_r = 4.6$
|
|
69
|
+
- **Layer 2 (Internal GND Plane)**: $17.5\mu\text{m}$ Copper ($0.5\text{ oz}$) - Continuous reference
|
|
70
|
+
- *Core FR-4*: $1.065\text{mm}$, $\varepsilon_r = 4.6$
|
|
71
|
+
- **Layer 3 (Internal Power Plane)**: $17.5\mu\text{m}$ Copper ($0.5\text{ oz}$) - Power split planes
|
|
72
|
+
- *Prepreg 7628*: $0.2104\text{mm}$, $\varepsilon_r = 4.6$
|
|
73
|
+
- **Layer 4 (Bottom Signal / Power Return)**: $35\mu\text{m}$ Copper ($1\text{ oz}$)
|
|
74
|
+
|
|
75
|
+
### 3.2 6-Layer Advanced High-Density Stackup
|
|
76
|
+
For dense microcontrollers (BGA/QFN) with mixed RF and high-speed memory:
|
|
77
|
+
- **L1 (Top Signal)**: $35\mu\text{m}$ - Microstrip signals & RF
|
|
78
|
+
- **L2 (GND 1)**: $17.5\mu\text{m}$ - Solid ground plane directly below L1
|
|
79
|
+
- **L3 (Inner Signal 1)**: $17.5\mu\text{m}$ - Stripline high-speed routing
|
|
80
|
+
- **L4 (Power / GND 2)**: $17.5\mu\text{m}$ - Power distribution
|
|
81
|
+
- **L5 (GND 3)**: $17.5\mu\text{m}$ - Solid ground plane directly above L6
|
|
82
|
+
- **L6 (Bottom Signal)**: $35\mu\text{m}$ - Low-speed signals, testpoints, connectors
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 4. Formal Constraint Manifest Schema (`constraints.yaml`)
|
|
87
|
+
|
|
88
|
+
Every hardware project must emit a validated `constraints.yaml` prior to schematic or PCB routing. The schema is specified below:
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
schema_version: "1.0.0"
|
|
92
|
+
project_name: "iot-telemetry-node"
|
|
93
|
+
target_fabricator: "JLCPCB"
|
|
94
|
+
|
|
95
|
+
operating_conditions:
|
|
96
|
+
ambient_temp_min_c: -20
|
|
97
|
+
ambient_temp_max_c: 65
|
|
98
|
+
max_allowable_temp_rise_c: 15
|
|
99
|
+
v_in_nominal: 5.0
|
|
100
|
+
v_in_max: 5.5
|
|
101
|
+
peak_current_a: 2.2
|
|
102
|
+
|
|
103
|
+
board_envelope:
|
|
104
|
+
outline_type: "rectangular"
|
|
105
|
+
width_mm: 75.0
|
|
106
|
+
length_mm: 45.0
|
|
107
|
+
corner_radius_mm: 2.5
|
|
108
|
+
pcb_thickness_mm: 1.6
|
|
109
|
+
copper_layers: 4
|
|
110
|
+
mounting_holes:
|
|
111
|
+
diameter_mm: 3.2 # M3 screw clearance
|
|
112
|
+
keepout_diameter_mm: 6.5 # Screw head + washer clearance
|
|
113
|
+
locations_mm:
|
|
114
|
+
- [3.5, 3.5]
|
|
115
|
+
- [71.5, 3.5]
|
|
116
|
+
- [3.5, 41.5]
|
|
117
|
+
- [71.5, 41.5]
|
|
118
|
+
|
|
119
|
+
stackup:
|
|
120
|
+
profile: "JLC04161H-7628"
|
|
121
|
+
dielectric_er: 4.6
|
|
122
|
+
copper_outer_oz: 1.0
|
|
123
|
+
copper_inner_oz: 0.5
|
|
124
|
+
layer_assignments:
|
|
125
|
+
1: "TOP_SIGNAL"
|
|
126
|
+
2: "GND_PLANE"
|
|
127
|
+
3: "PWR_PLANE"
|
|
128
|
+
4: "BOTTOM_SIGNAL"
|
|
129
|
+
|
|
130
|
+
netclasses:
|
|
131
|
+
Default:
|
|
132
|
+
track_width_mm: 0.20
|
|
133
|
+
clearance_mm: 0.20
|
|
134
|
+
via_drill_mm: 0.30
|
|
135
|
+
via_size_mm: 0.60
|
|
136
|
+
description: "Standard low-speed digital GPIO and logic nets"
|
|
137
|
+
|
|
138
|
+
PWR_HIGH_CURRENT:
|
|
139
|
+
track_width_mm: 0.80 # Sized via IPC-2152 for 2.5A, 10C rise
|
|
140
|
+
clearance_mm: 0.30
|
|
141
|
+
via_drill_mm: 0.40
|
|
142
|
+
via_size_mm: 0.80
|
|
143
|
+
nets: ["+5V", "VBUS", "+3V3_REG"]
|
|
144
|
+
|
|
145
|
+
GND:
|
|
146
|
+
track_width_mm: 0.40
|
|
147
|
+
clearance_mm: 0.25
|
|
148
|
+
via_drill_mm: 0.30
|
|
149
|
+
via_size_mm: 0.60
|
|
150
|
+
nets: ["GND", "GND_PWR"]
|
|
151
|
+
|
|
152
|
+
USB_DIFF_90:
|
|
153
|
+
impedance_target_ohms: 90
|
|
154
|
+
impedance_tolerance_pct: 10
|
|
155
|
+
track_width_mm: 0.38
|
|
156
|
+
diff_pair_gap_mm: 0.18
|
|
157
|
+
clearance_mm: 0.30
|
|
158
|
+
max_unmatched_length_mm: 0.10
|
|
159
|
+
nets: ["USB_DP", "USB_DN"]
|
|
160
|
+
|
|
161
|
+
ANALOG_SENSITIVE:
|
|
162
|
+
track_width_mm: 0.25
|
|
163
|
+
clearance_mm: 0.35
|
|
164
|
+
guard_ring: true
|
|
165
|
+
nets: ["ADC_IN0", "ADC_IN1", "VREF"]
|
|
166
|
+
|
|
167
|
+
manufacturing_limits:
|
|
168
|
+
min_track_width_mm: 0.127 # 5 mil
|
|
169
|
+
min_clearance_mm: 0.127 # 5 mil
|
|
170
|
+
min_drill_diameter_mm: 0.20 # 8 mil
|
|
171
|
+
min_annular_ring_mm: 0.15
|
|
172
|
+
min_solder_mask_bridge_mm: 0.10
|
|
173
|
+
board_edge_clearance_mm: 0.35
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 5. KiCad Custom Design Rules (`.kicad_dru`) Generation
|
|
179
|
+
|
|
180
|
+
The agent must translate the netclasses and clearance constraints into KiCad's native custom rules syntax (`project.kicad_dru`):
|
|
181
|
+
|
|
182
|
+
```lisp
|
|
183
|
+
(version 1)
|
|
184
|
+
|
|
185
|
+
# Ensure high voltage nets have adequate physical clearance
|
|
186
|
+
(rule "High_Voltage_Clearance"
|
|
187
|
+
(constraint clearance (min 1.2mm))
|
|
188
|
+
(condition "A.NetClass == 'MAINS_AC' && B.NetClass != 'MAINS_AC'"))
|
|
189
|
+
|
|
190
|
+
# Prevent high-speed signals from getting close to board edges
|
|
191
|
+
(rule "Board_Edge_Clearance_HighSpeed"
|
|
192
|
+
(constraint edge_clearance (min 1.0mm))
|
|
193
|
+
(condition "A.NetClass == 'USB_DIFF_90' || A.NetClass == 'RF_50'"))
|
|
194
|
+
|
|
195
|
+
# Enforce minimum drill hole-to-hole clearance to prevent drill wander shorts
|
|
196
|
+
(rule "Hole_To_Hole_Clearance"
|
|
197
|
+
(constraint hole_to_hole (min 0.25mm)))
|
|
198
|
+
|
|
199
|
+
# Guard sensitive analog nets from digital switching noise
|
|
200
|
+
(rule "Analog_Clearance_To_Digital"
|
|
201
|
+
(constraint clearance (min 0.40mm))
|
|
202
|
+
(condition "A.NetClass == 'ANALOG_SENSITIVE' && B.NetClass == 'Default'"))
|
|
203
|
+
|
|
204
|
+
# Require thermal reliefs on ground plane connection
|
|
205
|
+
(rule "Plane_Thermal_Reliefs"
|
|
206
|
+
(constraint thermal_spoke_width (min 0.35mm))
|
|
207
|
+
(condition "A.NetClass == 'GND'"))
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## 6. Execution Workflow & Tool Invocations
|
|
213
|
+
|
|
214
|
+
1. **Parameter Ingestion**:
|
|
215
|
+
- Extract power requirements, communication interfaces, and mechanical form factors from the user brief.
|
|
216
|
+
2. **IPC-2152 & IPC-2141 Synthesis**:
|
|
217
|
+
- Calculate trace widths for every power net based on peak expected current.
|
|
218
|
+
- Calculate trace width ($W$) and differential gap ($S$) based on stackup dielectric height ($h$).
|
|
219
|
+
3. **Artifact Generation**:
|
|
220
|
+
- Write `pcb_constraints.yaml` in the project root.
|
|
221
|
+
- Write `board.kicad_dru` in the project root.
|
|
222
|
+
4. **Validation via `kicad-cli`**:
|
|
223
|
+
- Verify that the generated rule syntax compiles cleanly against `kicad-cli`:
|
|
224
|
+
```bash
|
|
225
|
+
kicad-cli pcb drc --exit-code-violations --rules board.kicad_dru board.kicad_pcb
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 7. Negative Constraints (Anti-Slop Directives)
|
|
231
|
+
|
|
232
|
+
- **DO NOT** use default KiCad trace widths (0.25mm) for power rails carrying $>0.5\text{A}$. Every power rail must be sized using the IPC-2152 formula.
|
|
233
|
+
- **DO NOT** specify 2-layer stackups for designs containing high-speed USB (480 Mbps+), Ethernet, or microcontrollers running $>100\text{ MHz}$ core clocks without an explicit solid ground flood on Layer 2.
|
|
234
|
+
- **DO NOT** define mounting hole clearances that only cover the drill hole. Mounting keepouts must encompass the bolt head plus standard socket tool clearance ($\ge 6.5\text{mm}$ for M3).
|
|
235
|
+
- **DO NOT** place annular rings below $0.15\text{mm}$ ($6\text{ mils}$) unless the project explicitly targets advanced laser micro-via processes ($>10\times$ fabrication cost).
|
|
236
|
+
- **DO NOT** define differential pairs without an explicit intra-pair skew tolerance (maximum allowable length mismatch $\le 0.1\text{mm}$).
|