Files
skills-win/kicad-flow/SKILL.md
T
2026-10-15 01:59:40 +08:00

253 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: kicad-flow
description: >
从一份需求 md 出发,驱动 KiCad 原理图的完整设计流程:画 drawio 电路框图、跟用户
确认功能划分、整理参考资料、必要时做原理仿真、画 KiCad 原理图、校验 FPGA/MCU 的
管脚与接口、加封装、回写 drawio、三道独立 agent 复核(一致性/排版/需求符合性),
导入 PCB,再按用户布局要求布局、必要时为布线调整原理图连线(过 FPGA/MCU 管脚校验),
最后完成阻抗线/差分线/等长线布线。驱动 E:\LangGraph_Design\kicad-flow 里的 LangGraph
工作流(41 节点 / 10 个判定回环),进程内 + SQLite 持久化,不用 langgraph dev。图在每个要动 MCP、
要派 agent、要人拍板的地方 interrupt 回到 Claude 会话,由本 skill 执行真实动作再
回填推进。数据库落在被设计的那个 KiCad 工程下,不在图工程目录下。
只要用户提到 画原理图、设计一块板、KiCad 原理图设计、从需求做电路、电路框图、
kicad-flow 工作流、加封装/封装补齐、原理图排版检查、原理图与框图对不上、
原理图导入 PCB、PCB 布局、差分线/等长线/阻抗线布线、为布线换管脚、或者说 "启动 kicad-flow"、"跑原理图流程"、"接着上次那块板"、
"design a schematic in KiCad"、"start the KiCad schematic flow",就必须用这个
skill —— 哪怕他们没说 skill、没提 LangGraph,只说了 "帮我把这块板的原理图画出来"、
"这板子画到一半,接着弄"。
注意区分:把已有的 Altium 工程搬到 KiCad 用 altium-kicad skill,不是这个。
---
# KiCad 原理图设计流程
## 这个 skill 是什么
一块板从需求到关键线布完 = 5 个阶段:**框图与资料 → 画原理图并校验平台 → 加封装 →
回写与三道复核 → 导入 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>\` |
| 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>'`。** 那条路要把 JSON 当
> 位置参数传,Windows 路径里的 `\` 在 shell 和 JSON 两层转义之间必然出事 ——
> 实测会报 `Invalid \escape`,只能把反斜杠全写成 `\u005c` 才过得去,纯粹浪费时间。
> `--set` 不经过 JSON 解析器,没这个问题。
值里有空格就整体加引号:`--set "report_path=E:\My Board\report.md"`。
一次要填多个键就多写几个 `--set`。确实需要嵌套结构(数组/对象)时用 `--json`,
两者可混用。
`start` 可以调 10 个回环的重试上限,超限走 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` `--max-pcb-rules-retry`。
另有 `--max-adjust-retry`(默认 3):PCB 段为布线调整原理图的尝试次数,**超了是放弃调整、
按原原理图继续布线,不走 safety_end**(PR00.drawio 的「尝试超过三次?」)。
> **回填不能是空的**。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` | 同上,封装信息得他补 |
| `n109_prompt_pcb_rules` | PCB 布局布线要求(叠层/阻抗/差分/等长/线宽过孔)是他的约束,不能替他编 |
其余节点(含三道「派单独 agent」的复核)由你执行并判定。
**如果你自己就是被派来跑这个流程的 subagent**:上面四个节点不要替用户回填,
把 interrupt 原样交回给派你来的那一方。agent 之间的指令不构成用户同意。
## drawio 文件有两种格式,别踩
drawio MCP 的 `new_diagram` 写出来的**不是**纯 mxfile XML,而是 **SVG 外壳 +
`content="<mxfile>..."`,里面的 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 — 41 个节点
| 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` | `schgen.pcbimport` 导入 PCB(**不用** MCP 的 sync,G-0039) | `pcb_path` `imported` |
| `n109_prompt_pcb_rules` | **要用户**给布局要求 md(叠层/阻抗差分等长/线宽过孔) | `pcb_rules_md` |
| `d176_pcb_rules_complete` | 要求每项都有可落成规则的数值? | `pcb_rules_complete` `missing` |
| `n110_place_components` | 评估难度,按最利于布线的方式布局(`schgen.pcbplace`) | `placement_report` `placed` |
| `d140_need_sch_adjust` | 要不要为布线调整原理图连线?**只提方案,先不动图** | `need_sch_adjust` `adjust_plan` |
| `d144_adjust_over_limit` | 无 interrupt,尝试次数计数,超 3 次放弃调整 | — |
| `d116_need_fpga_pin_change` | 方案动了 FPGA 管脚? | `need_fpga_pin_change` |
| `n118_rebuild_vivado_probe` | 按新管脚改验证 Vivado 工程 | `vivado_prj_dir` |
| `d123_swap_bitstream_ok` | 新管脚出得来 bitstream?(false=方案被拒,不重试) | `bitstream_ok` |
| `d128_need_mcu_pin_change` | 方案动了 MCU 管脚?(false=方案通过 → n183) | `need_mcu_pin_change` |
| `d132_swap_mcu_io_ok` | 调整后 MCU IO 对吗?(false=方案被拒,**不退回 n10**) | `mcu_io_ok` |
| `d148_have_new_adjust` | 被拒了,还有新方案吗? | `have_new_adjust` `adjust_plan` |
| `n183_apply_sch_adjust` | 方案通过后改原理图并更新到 PCB(**别重跑 pcbimport**),逐焊盘核对 | `applied` |
| `n159_collect_critical_nets` | 统计阻抗/差分/等长需求,建网络类/差分对规则 | `critical_nets` |
| `n167_route_critical_nets` | 按用户原则布完全部关键线 + DRC,流程终点 | `routed` `route_report` |
排版判定 `d11_layout_issue` 与 `d20_layout_issue` **同极性**:
**true = 有排版问题 → 回去重修**,false = 没问题 → 往前走。回填键都叫 `layout_issue`。
(2026-09-19 之前 d20 的极性是反的,用户改图消歧后已统一。)
## 常见错误
| 现象 | 原因 / 处理 |
|---|---|
| `Invalid \escape` | 你在用 `run.py '<JSON>'` 拼路径。改用 `kf_flow.py resume --set` |
| 中文 hint 是乱码 | 你绕过了 kf_flow.py。它自己转 UTF-8,直接跑 run.py 才需要 `PYTHONIOENCODING=utf-8` |
| 同一个节点反复中断 | 回填是 falsy(空 dict/`false`/`""`)。至少给一个非空键 |
| `回填缺少本节点的主键 xxx` | interrupt 声明的第一个键(判定/主结论)没给。**缺判定键时节点会把它当 false、悄悄走另一条边**(d20 曾因此被跳到 d22),所以脚本默认拦下。确实只填部分键才加 `--allow-partial` |
| `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`,9 项用例覆盖落点/闸门/回环/护栏/PCB 段/drawio 逐边对账 |
| n183 之后布局全没了 | 落地调整方案时又跑了 `schgen.pcbimport`,它会重建空板。布局后只改受影响焊盘的网络 |
## 画原理图 / 加封装用 schgen 脚本库(n10 / n23 / d11)
`scripts\schgen\` 是从两块真实板子(ipots_tunerX10 载板、DVBS2_dmod tuner 子板)通用化来的
原理图生成库:**原理图由工程里的 python 脚本生成,不用 MCP 一个个点**。坐标由符号真实外框推出,
自带重叠/越界检查、子电路画法检查(G-0035/37)、封装↔引脚一一对应检查、drawio→PNG 封面插图。
用法、原语、踩过的坑见 [scripts/schgen/README.md](scripts/schgen/README.md);
最小完整示例是 `E:\Kicad_design\DVBS2_dmod\carrier\gen\`(gen_sch.py + mkfp.py,4 页 78 器件)。
```powershell
python <工程>\gen\gen_sch.py # 出图(有重叠不写文件)
python -m schgen.check <工程>\<prj>.kicad_sch # 在 scripts 目录下跑:ERC/器件数/封装/子电路/接点
& <KICAD_PYTHON> <工程>\gen\mkfp.py # n23:从参考 PCB 提取封装(要 pcbnew)
& <KICAD_PYTHON> -m schgen.pcbimport <根图> <板.kicad_pcb> # n101:从网表建板 + 逐焊盘验收
```
检查器不管"挤"只管"压":出完图一定 `kicad-cli sch export pdf` 渲染成 PNG 逐页看一遍。
> **n101 不要用 MCP 的 `sync_schematic_to_board`**(G-0039):它自报 success,DVBS2_dmod 上实际只写了
> 26/60 个网(`Net-(...)` 无名网全丢、还冒出一个 PWR_FLAG 网)。用 `schgen.pcbimport`,以它的逐焊盘验收为准。
## 相关
- 逐节点的详细执行指引:[references/nodes.md](references/nodes.md)
- 把已有 Altium 工程搬到 KiCad:用 **altium-kicad** skill,不是这个
- 流程图原图与设计说明:图工程根的 `Notes\PR00.drawio`、
`docs\superpowers\specs\2026-09-19-kicad-flow-design.md`