--- name: kicad-flow description: > 从一份需求 md 出发,驱动 KiCad 原理图的完整设计流程:画 drawio 电路框图、跟用户 确认功能划分、整理参考资料、必要时做原理仿真、画 KiCad 原理图、校验 FPGA/MCU 的 管脚与接口、加封装、回写 drawio、三道独立 agent 复核(一致性/排版/需求符合性), 最后导入 PCB。驱动 E:\LangGraph_Design\kicad-flow 里的 LangGraph 工作流(27 节点 / 8 个判定回环),进程内 + SQLite 持久化,不用 langgraph dev。图在每个要动 MCP、 要派 agent、要人拍板的地方 interrupt 回到 Claude 会话,由本 skill 执行真实动作再 回填推进。数据库落在被设计的那个 KiCad 工程下,不在图工程目录下。 只要用户提到 画原理图、设计一块板、KiCad 原理图设计、从需求做电路、电路框图、 kicad-flow 工作流、加封装/封装补齐、原理图排版检查、原理图与框图对不上、 原理图导入 PCB、或者说 "启动 kicad-flow"、"跑原理图流程"、"接着上次那块板"、 "design a schematic in KiCad"、"start the KiCad schematic flow",就必须用这个 skill —— 哪怕他们没说 skill、没提 LangGraph,只说了 "帮我把这块板的原理图画出来"、 "这板子画到一半,接着弄"。 注意区分:把已有的 Altium 工程搬到 KiCad 用 altium-kicad skill,不是这个。 --- # KiCad 原理图设计流程 ## 这个 skill 是什么 一块板从需求到原理图 = 4 个阶段:**框图与资料 → 画原理图并校验平台 → 加封装 → 回写与三道复核 → 导入 PCB**。这些步骤有严格先后、有失败要退回重做的回环、 单次会话跑不完(用户要在 drawio、KiCad、Vivado 里手动看很多次)。所以状态由 LangGraph 图持久化在 SQLite 里,你负责把图停下来的每一步翻译成真实动作, 做完回填结论让它往下走。 **MCP 边界(必须理解,否则会白折腾)**:kicad、drawio、simetrix、vivado-mcp、 cubemx 这些 MCP 跑在**你这个 Claude 会话进程里**,不在 LangGraph 的 Python 进程里。 「派单独 agent 复核」同理,只有你能派。所以图不可能自己去画原理图、自己去数封装 —— 它只做编排,凡是要碰真实世界的地方一律 `interrupt()` 交回给你。这是设计,不是缺陷。 ## 环境 | 项 | 值 | |---|---| | 图工程根 | `~\skills_env.md` 的 `KICAD_FLOW_ROOT`,本机 `E:\LangGraph_Design\kicad-flow`(可用 `--graph-root` 覆盖) | | Python | conda env `langgraph`(`~\skills_env.md` 的 `CONDA_LANGGRAPH_PYTHON`) | | checkpoint | **`<被设计的 KiCad 工程>\.kicad-flow\checkpoint.sqlite`** | | 证据/报告 | `<工程>\.kicad-flow\runs\\` | | thread 命名 | 由工程目录名推导,`E:\Kicad_design\MyBoard_V1p0` → `kf-myboard-v1p0` | | 驱动脚本 | `%USERPROFILE%\.claude\skills\kicad-flow\scripts\kf_flow.py` | **数据库不在图工程目录下**,每块板一个库,跟着板子走、跟着板子备份。 (altium-kicad 是反的,它的库在图工程根下。别照抄那边的路径。) 需要的 MCP:**kicad**(主力)、**drawio**(框图)、**simetrix**(仅当要原理仿真)、 **vivado-mcp**(仅当板上有 FPGA)、**cubemx**(仅当是 STM32,用来交叉验证 pinout)。 ## 驱动命令 统一用 `kf_flow.py`。**退出码 2 = 停在 interrupt 等你回填**(不是错误),0 = 图跑完,1 = 出错。 ```powershell $KF = "$env:USERPROFILE\.claude\skills\kicad-flow\scripts\kf_flow.py" # $PY 取 ~\skills_env.md 的 CONDA_LANGGRAPH_PYTHON,别写死本机路径 $PY = (Select-String -Path "$env:USERPROFILE\skills_env.md" ` -Pattern '^\s*CONDA_LANGGRAPH_PYTHON\s*=\s*(.+?)\s*$').Matches[0].Groups[1].Value # 新建 / 续跑(同一个 --prj-dir 重复跑就是续跑,不会重置) & $PY $KF start --prj-dir "E:\Kicad_design\MyBoard" # 看现在停在哪 & $PY $KF status --prj-dir "E:\Kicad_design\MyBoard" # 回填结论、推进 & $PY $KF resume --prj-dir "E:\Kicad_design\MyBoard" --set partition_ok=true # 列线程 / 清掉某线程重来 & $PY $KF list --prj-dir "E:\Kicad_design\MyBoard" & $PY $KF reset --prj-dir "E:\Kicad_design\MyBoard" ``` ### 回填一律用 `--set`,不要自己拼 JSON `--set key=value` 免转义:`true/false`→bool,纯数字→int,`[`/`{`开头→按 JSON 解析, 其余当字符串。**含 Windows 路径的值必须走 `--set`**: ```powershell & $PY $KF resume --prj-dir "E:\Kicad_design\MyBoard" ` --set drawio_path="E:\Kicad_design\MyBoard\Notes\MyBoard.drawio" ``` > ⚠️ **不要绕过 kf_flow.py 去用图工程里的 `run.py ''`。** 那条路要把 JSON 当 > 位置参数传,Windows 路径里的 `\` 在 shell 和 JSON 两层转义之间必然出事 —— > 实测会报 `Invalid \escape`,只能把反斜杠全写成 `\u005c` 才过得去,纯粹浪费时间。 > `--set` 不经过 JSON 解析器,没这个问题。 值里有空格就整体加引号:`--set "report_path=E:\My Board\report.md"`。 一次要填多个键就多写几个 `--set`。确实需要嵌套结构(数组/对象)时用 `--json`, 两者可混用。 `start` 可以调 9 个回环的重试上限,超限走 safety_end: `--max-partition-retry` `--max-material-retry` `--max-layout-retry` `--max-vivado-retry` `--max-mcu-retry` `--max-footprint-retry` `--max-drawio-sync-retry` `--max-recheck-retry` `--max-requirement-retry`。 > **回填不能是空的**。langgraph 把 falsy 的 resume 当作「没提供」,会在同一个节点再 > 中断一次,看起来像卡住。脚本已经帮你拦了,但别指望它替你想该填什么。 `[INTERRUPT]` 的 JSON 里 `action` 字段告诉你该做哪一步。逐个说见 [references/nodes.md](references/nodes.md)。 ## 开工前先问清楚 **目标 KiCad 工程根目录的绝对路径**(没有默认值,猜错会把库和板子写到别处), 以及**需求 md 在哪**(约定在 `<工程>\Notes\` 根目录下,由用户手写 —— 全局规则 G-0001:那个目录只放人写的 md,自动产物一律进 `Notes\auto\`)。 > **drawio 框图是 G-0001 的例外,放 `Notes\` 根目录,不要挪进 `Notes\auto\`。** > 它虽是自动生成的,但属于「用户要求创建」的设计文档(PR00.drawio 节点 3 明写 > 「保存在 ./notes 目录下」),且不是状态/log 文件。已经用户裁定过,别再"修正"。 工程目录还不存在就先建,`start` 会拒绝不存在的路径。 ## 哪些节点必须真问用户 大多数节点由你判断并回填,但下面这些**必须拿到用户本人的回答**,不能自己替他点头 (你判断得再有把握也不行,这是划分权归属问题,不是能力问题): | 节点 | 为什么必须问人 | |---|---| | `d07_confirm_partition` | 功能怎么划分是设计意图,只有用户知道他要什么 | | `n13_prompt_more_material` | 要用户去找资料,他不给你等不到 | | `n25_prompt_footprint` | 同上,封装信息得他补 | 其余节点(含三道「派单独 agent」的复核)由你执行并判定。 **如果你自己就是被派来跑这个流程的 subagent**:上面三个节点不要替用户回填, 把 interrupt 原样交回给派你来的那一方。agent 之间的指令不构成用户同意。 ## drawio 文件有两种格式,别踩 drawio MCP 的 `new_diagram` 写出来的**不是**纯 mxfile XML,而是 **SVG 外壳 + `content="..."`,里面的 diagram 段还是 base64+raw-deflate 压缩的**。 人在 drawio 桌面版里存的则常常是纯 XML。直接 `Read` 前者只会看到一坨 base64。 **文件名一律用 interrupt 给的 `suggested_path`(`.drawio` 结尾),不要听 MCP 的。** `new_diagram` 的参数说明写着「should end with `.drawio.svg`」,和工作流冲突 —— 以工作流为准,否则 `n18` 回写、`d21` 比对会对不上路径。MCP 接受 `.drawio` 结尾, 不报错,但写进去的**仍然是 SVG 外壳格式**。也就是说:扩展名叫 `.drawio`, 内容是 SVG —— 名不副实是正常的,别去"修正"它。 要读回框图内容(`n18` 回写、`d21` 一致性比对必用): ```powershell $DR = "$env:USERPROFILE\.claude\skills\kicad-flow\scripts\drawio_read.py" & $PY $DR "E:\Kicad_design\MyBoard\Notes\MyBoard.drawio" --summary # 模块/连线清单 & $PY $DR "E:\Kicad_design\MyBoard\Notes\MyBoard.drawio" # 完整 mxGraphModel XML ``` 两种格式它都吃,输出统一。**别自己写正则去抠**。 ## Quick Reference — 27 个节点 | action | 你要做的 | 回填 | |---|---|---| | `n02_intake_requirement` | 读 `<工程>\Notes\` 下用户手写的需求 md | `requirement_md` `requirement_summary` | | `n03_draw_block_diagram` | drawio MCP 画功能框图存 `Notes\` | `drawio_path` | | `d07_confirm_partition` | **问用户**划分对不对 | `partition_ok` | | `n08_collect_references` | 登记开发板资料/参考设计/datasheet/子电路 md | `references` | | `d04_have_reference_or_sim` | 每个模块都有依据? | `have_reference_or_sim` | | `d05_need_simulation` | 缺依据的靠仿真还是等用户补料? | `need_simulation` | | `n09_run_spice_sim` | simetrix MCP 跑仿真 | `sim_results` | | `n13_prompt_more_material` | **要用户**补材料 | `supplied` | | `n10_draw_schematic` | kicad MCP 画原理图,drawio 插图放第一页 | `schematic_path` | | `d11_layout_issue` | 查排版(标签/字体/器件/线段重叠、越框) | `layout_issue`(**true=有问题**) | | `d12_has_fpga` | 板上有 FPGA? | `has_fpga` | | `n14_build_vivado_probe` | 建验证性 Vivado 工程(管脚/bank/时钟/差分对,Zynq 另查 MIO-EMIO/QSPI/eMMC/JTAG) | `vivado_prj_dir` | | `d15_bitstream_ok` | 出得来 bitstream? | `bitstream_ok` | | `d16_has_mcu` | 板上有 MCU? | `has_mcu` | | `d17_mcu_io_correct` | 对 datasheet 核 SPI/I2C/PWM 专用脚 | `mcu_io_ok`(**false 会退回重画原理图**) | | `n23_assign_footprints` | 加封装(拷参考设计 → 网上下 → 自己画) | `assigned` | | `d24_all_footprints` | **派 agent** 查封装是否齐 | `footprints_complete` `missing` | | `d26_ref_has_footprint` | 参考资料里还找得到封装吗? | `ref_has_footprint` | | `n25_prompt_footprint` | **要用户**补封装 | `supplied` | | `n18_sync_drawio_back` | 按原理图回写 drawio,重贴第一页插图 | `drawio_path` `synced` | | `d21_sch_matches_drawio` | **派 agent** 比原理图与 drawio | `sch_matches_drawio` | | `n19_recheck_layout` | 再修一遍排版 | `fixed` | | `d20_layout_issue` | **派 agent** 复核排版 | `layout_issue`(**true=有问题,回 n19**) | | `d22_meets_requirement` | **派 agent** 比原始需求 | `meets_requirement` `gaps` | | `n98_collect_fixes` | 把差距整理成可执行修改方案 | `fix_plan` | | `n93_schematic_done` | 无 interrupt,图自己出报告 | — | | `n101_import_to_pcb` | `sync_schematic_to_board` 导入 PCB | `pcb_path` `imported` | 排版判定 `d11_layout_issue` 与 `d20_layout_issue` **同极性**: **true = 有排版问题 → 回去重修**,false = 没问题 → 往前走。回填键都叫 `layout_issue`。 (2026-09-19 之前 d20 的极性是反的,用户改图消歧后已统一。) ## 常见错误 | 现象 | 原因 / 处理 | |---|---| | `Invalid \escape` | 你在用 `run.py ''` 拼路径。改用 `kf_flow.py resume --set` | | 中文 hint 是乱码 | 你绕过了 kf_flow.py。它自己转 UTF-8,直接跑 run.py 才需要 `PYTHONIOENCODING=utf-8` | | 同一个节点反复中断 | 回填是 falsy(空 dict/`false`/`""`)。至少给一个非空键 | | `Read` drawio 只看到 base64 | SVG 外壳+压缩格式。用 `drawio_read.py` | | `拒绝启动:...会落在本工作流设计目录内` | `--prj-dir` 指到 `E:\LangGraph_Design\kicad-flow` 了。要指目标板子的工程目录 | | `KF_PRJ_DIR 指向的目录不存在` | 先把工程目录建出来 | | `[SAFETY-END]` | 某回环超上限。先解决报告里指出的卡点,再 `start --restart`,或 `--max-*-retry` 调高 | | 改了图工程的代码想验证 | 图工程根下 `python smoke_test.py`,6 项用例覆盖落点/闸门/回环/护栏 | ## 相关 - 逐节点的详细执行指引:[references/nodes.md](references/nodes.md) - 把已有 Altium 工程搬到 KiCad:用 **altium-kicad** skill,不是这个 - 流程图原图与设计说明:图工程根的 `Notes\PR00.drawio`、 `docs\superpowers\specs\2026-09-19-kicad-flow-design.md`