firmwareloop 0.7.3__tar.gz → 0.8.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/PKG-INFO +9 -6
  2. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/README.md +7 -4
  3. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/firmwareloop.egg-info/PKG-INFO +9 -6
  4. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/firmwareloop.egg-info/requires.txt +1 -1
  5. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/pyproject.toml +2 -2
  6. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/__init__.py +1 -1
  7. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/fw_mcp_server.py +282 -14
  8. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/lib/ndtdbg.py +6 -6
  9. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/setup-agent-mcp.ps1 +2 -2
  10. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/LICENSE +0 -0
  11. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/firmwareloop.egg-info/SOURCES.txt +0 -0
  12. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/firmwareloop.egg-info/dependency_links.txt +0 -0
  13. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/firmwareloop.egg-info/entry_points.txt +0 -0
  14. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/firmwareloop.egg-info/top_level.txt +0 -0
  15. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/setup.cfg +0 -0
  16. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/acceptance-scenario.ps1 +0 -0
  17. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/build.ps1 +0 -0
  18. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/can.ps1 +0 -0
  19. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/check-qoder-mcp.ps1 +0 -0
  20. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/common/build-backends.psm1 +0 -0
  21. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/common/fw.psm1 +0 -0
  22. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/common/uart_probe.py +0 -0
  23. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/doctor.ps1 +0 -0
  24. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/flash.ps1 +0 -0
  25. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/instrument_cli.py +0 -0
  26. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/lib/__init__.py +0 -0
  27. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/lib/instruments.py +0 -0
  28. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/lib/serial_assistant.py +0 -0
  29. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/logic_capture.ps1 +0 -0
  30. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/logic_decode.ps1 +0 -0
  31. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/ndtdbg_bridge.ps1 +0 -0
  32. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/ndtdbg_cli.py +0 -0
  33. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/reset.ps1 +0 -0
  34. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/serial_cli.py +0 -0
  35. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/sigrok_csv_to_fwloop.py +0 -0
  36. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/test-backends.ps1 +0 -0
  37. {firmwareloop-0.7.3 → firmwareloop-0.8.0}/tools/test.ps1 +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firmwareloop
3
- Version: 0.7.3
3
+ Version: 0.8.0
4
4
  Summary: AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)
5
5
  Author-email: WeilinZhang <19523330249@163.com>
6
6
  License: MIT
@@ -18,7 +18,7 @@ Requires-Python: >=3.10
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
20
  Requires-Dist: pyvisa>=1.14.0
21
- Requires-Dist: pyvisa-py>=0.7.3
21
+ Requires-Dist: pyvisa-py>=0.7.4
22
22
  Requires-Dist: pyserial>=3.5
23
23
  Requires-Dist: pytest>=8.0.0
24
24
  Requires-Dist: pyocd>=0.36.0
@@ -177,6 +177,8 @@ fwloop setup
177
177
  | Claude Code CLI | `~/.claude.json` |
178
178
  | Qoder / Qoder CN | `~/.qoder/mcp.json`、`~/.qoder-cn/mcp.json` |
179
179
  | CodeBuddy IDE | `~/.codebuddy/mcp.json` |
180
+ | DeepSeek Harness (DSH) | `~/.dsh/profiles/<已派生 profile>/cordis.patch.yml` |
181
+ | ZCode IDE | `~/.zcode/cli/config.json` |
180
182
 
181
183
  2. **同步技能包**(`firmwareloop`、`fwloop-adapter`)到 Antigravity 与 Claude Code 的全局 Skill 目录。
182
184
  3. **生成机器级全局配置** `%APPDATA%\FirmwareLoop\lab.yaml`(NdtBox 配置模板,已存在则不覆盖)。
@@ -383,7 +385,7 @@ claude mcp remove --scope user agentic-hil
383
385
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
384
386
  ├── demo-make/ 示例固件(Make;构建测试载体)
385
387
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
386
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.7.3)
388
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.8.0)
387
389
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
388
390
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
389
391
  ├── CLAUDE.md Claude Code CLI 指南
@@ -393,7 +395,7 @@ claude mcp remove --scope user agentic-hil
393
395
 
394
396
  ---
395
397
 
396
- ## 能力验证状态(v0.7.3
398
+ ## 能力验证状态(v0.8.0
397
399
 
398
400
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
399
401
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -401,6 +403,7 @@ claude mcp remove --scope user agentic-hil
401
403
  | 能力 | 状态 |
402
404
  |---|---|
403
405
  | 双层 MCP 服务(13 个工作流与硬件工具) | Implemented + Protocol Validated(31/31 测试通过) |
406
+ | fwloop setup 一键注册(7 Agent:Antigravity / Claude Code / Qoder(+CN) / CodeBuddy / DeepSeek Harness / ZCode) | Implemented + Multi-Agent Validated(DSH / ZCode 真机写入验证) |
404
407
  | 串口助手工具族(fw_serial_* 七工具, 长驻会话/发送序列/帧解析/窗口采集) | Implemented + Simulator Validated(55 例单测: 含残留 serve 自动清理 / close 进程回收 / UTF-8 线路 / 失败落 JSONL)-> Real Hardware Validated 待 DUT |
405
408
  | 一键多 Agent 脚手架(fwloop init / fw_init_project) | Implemented + Multi-Agent Validated |
406
409
  | 自定义/私有调试工具接入 Skill(fwloop-adapter) | Implemented + Multi-Skill Validated |
@@ -437,10 +440,10 @@ claude mcp remove --scope user agentic-hil
437
440
  | 串口 `SERIAL_PORT_ERROR: ... PermissionError(13)` | 端口被 GUI 上位机独占(NDT Debug Tool / STDataCollection.exe、串口助手)→ 关闭占用方后 `fw_serial_open`;残留会话用 `fw_serial_close`(已自动等待/强杀进程,端口释放可验证) |
438
441
  | `fw_serial_status` 的 `error_class` 为 `UART_BUSY` | 会话未打开或已被占用 → 先 `fw_serial_open`;残留会话 `fw_serial_close` 清理 |
439
442
  | `fw_serial_*` 报 `PermissionError(13)` / `rx_bytes: 0` | 串口被独占:**退出 NDT Debug Tool GUI(STDataCollection.exe)**——它打开时会同时占住 Box 串口与 USB-IIC 通道;失败信封/`fw_serial_status` 的 `suspected_holders` 会直接列出嫌疑进程(注意别杀 MCP server 的 python) |
440
- | 烧录"擦除生效(probe 从非 00 变 00)但校验读回全 FF"、`pages_written` 已发出 | v0.7.1 及更早的逐笔 serve 路径问题 → v0.7.3 起默认走 `flash_engine: bridge`(桥内单体,与 GUI 同进程模型);要复现/排查旧行为用 `flash_engine: "serve"` |
443
+ | 烧录"擦除生效(probe 从非 00 变 00)但校验读回全 FF"、`pages_written` 已发出 | v0.7.1 及更早的逐笔 serve 路径问题 → v0.7.4 起默认走 `flash_engine: bridge`(桥内单体,与 GUI 同进程模型);要复现/排查旧行为用 `flash_engine: "serve"` |
441
444
  | 长调用(capture/measure)客户端超时 | MCP stdio 循环是**单线程**的:长调用会让同会话其它调用排队(含 3s 的小调用)→ 缩短窗口,或用 `fw_ndtdbg_stream_start` job 模式 |
442
445
  | 烧录报 `INCOMPLETE_FLASH` | 桥内 flash 连续 30s 无进度(疑似卡在写入中途)→ **芯片处于半擦写态,勿直接使用,必须重新完整烧录**;信封带 `chip_state: partially_erased` 与 `post_kill_power_cycle`(已尝试复位) |
443
- | 烧录报 `COLD_BOOT_VERIFY_FAILED` | **Flash 字节已通过逐窗校验,但断电重上电后目标没有有效应答/与期望不符**(现场 `.18` 类问题:GUI 报成功、当场可读,冷启动 `Fw_ver = -1`)→ 按固件冷启动路径排查(看门狗/时钟/外设初始化);或用 `cold_boot_expect` 指定期望值、`cold_boot_check: false` 关闭 |
446
+ | 烧录报 `COLD_BOOT_VERIFY_FAILED` | **Flash 字节已通过逐窗校验,但断电重上电后目标没有有效应答/与期望不符**(现场失败形态:烧录工具报成功、当场可读,冷启动后却读不到版本)→ 按固件冷启动路径排查(看门狗/时钟/外设初始化);或用 `cold_boot_expect` 指定期望值、`cold_boot_check: false` 关闭 |
444
447
  | `fw_serial_status` 的 `port_probe.openable = false` | 端口当前**无法独占打开**(硬结论)→ 看 `holder_candidates`(`source: cmdline` 比 `name` 准,候选≠持有者)确认占用方 |
445
448
 
446
449
  完整速查表与手工部署细节见 [`Fwloop_setup_pack/README.md`](Fwloop_setup_pack/README.md)。
@@ -149,6 +149,8 @@ fwloop setup
149
149
  | Claude Code CLI | `~/.claude.json` |
150
150
  | Qoder / Qoder CN | `~/.qoder/mcp.json`、`~/.qoder-cn/mcp.json` |
151
151
  | CodeBuddy IDE | `~/.codebuddy/mcp.json` |
152
+ | DeepSeek Harness (DSH) | `~/.dsh/profiles/<已派生 profile>/cordis.patch.yml` |
153
+ | ZCode IDE | `~/.zcode/cli/config.json` |
152
154
 
153
155
  2. **同步技能包**(`firmwareloop`、`fwloop-adapter`)到 Antigravity 与 Claude Code 的全局 Skill 目录。
154
156
  3. **生成机器级全局配置** `%APPDATA%\FirmwareLoop\lab.yaml`(NdtBox 配置模板,已存在则不覆盖)。
@@ -355,7 +357,7 @@ claude mcp remove --scope user agentic-hil
355
357
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
356
358
  ├── demo-make/ 示例固件(Make;构建测试载体)
357
359
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
358
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.7.3)
360
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.8.0)
359
361
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
360
362
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
361
363
  ├── CLAUDE.md Claude Code CLI 指南
@@ -365,7 +367,7 @@ claude mcp remove --scope user agentic-hil
365
367
 
366
368
  ---
367
369
 
368
- ## 能力验证状态(v0.7.3
370
+ ## 能力验证状态(v0.8.0
369
371
 
370
372
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
371
373
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -373,6 +375,7 @@ claude mcp remove --scope user agentic-hil
373
375
  | 能力 | 状态 |
374
376
  |---|---|
375
377
  | 双层 MCP 服务(13 个工作流与硬件工具) | Implemented + Protocol Validated(31/31 测试通过) |
378
+ | fwloop setup 一键注册(7 Agent:Antigravity / Claude Code / Qoder(+CN) / CodeBuddy / DeepSeek Harness / ZCode) | Implemented + Multi-Agent Validated(DSH / ZCode 真机写入验证) |
376
379
  | 串口助手工具族(fw_serial_* 七工具, 长驻会话/发送序列/帧解析/窗口采集) | Implemented + Simulator Validated(55 例单测: 含残留 serve 自动清理 / close 进程回收 / UTF-8 线路 / 失败落 JSONL)-> Real Hardware Validated 待 DUT |
377
380
  | 一键多 Agent 脚手架(fwloop init / fw_init_project) | Implemented + Multi-Agent Validated |
378
381
  | 自定义/私有调试工具接入 Skill(fwloop-adapter) | Implemented + Multi-Skill Validated |
@@ -409,10 +412,10 @@ claude mcp remove --scope user agentic-hil
409
412
  | 串口 `SERIAL_PORT_ERROR: ... PermissionError(13)` | 端口被 GUI 上位机独占(NDT Debug Tool / STDataCollection.exe、串口助手)→ 关闭占用方后 `fw_serial_open`;残留会话用 `fw_serial_close`(已自动等待/强杀进程,端口释放可验证) |
410
413
  | `fw_serial_status` 的 `error_class` 为 `UART_BUSY` | 会话未打开或已被占用 → 先 `fw_serial_open`;残留会话 `fw_serial_close` 清理 |
411
414
  | `fw_serial_*` 报 `PermissionError(13)` / `rx_bytes: 0` | 串口被独占:**退出 NDT Debug Tool GUI(STDataCollection.exe)**——它打开时会同时占住 Box 串口与 USB-IIC 通道;失败信封/`fw_serial_status` 的 `suspected_holders` 会直接列出嫌疑进程(注意别杀 MCP server 的 python) |
412
- | 烧录"擦除生效(probe 从非 00 变 00)但校验读回全 FF"、`pages_written` 已发出 | v0.7.1 及更早的逐笔 serve 路径问题 → v0.7.3 起默认走 `flash_engine: bridge`(桥内单体,与 GUI 同进程模型);要复现/排查旧行为用 `flash_engine: "serve"` |
415
+ | 烧录"擦除生效(probe 从非 00 变 00)但校验读回全 FF"、`pages_written` 已发出 | v0.7.1 及更早的逐笔 serve 路径问题 → v0.7.4 起默认走 `flash_engine: bridge`(桥内单体,与 GUI 同进程模型);要复现/排查旧行为用 `flash_engine: "serve"` |
413
416
  | 长调用(capture/measure)客户端超时 | MCP stdio 循环是**单线程**的:长调用会让同会话其它调用排队(含 3s 的小调用)→ 缩短窗口,或用 `fw_ndtdbg_stream_start` job 模式 |
414
417
  | 烧录报 `INCOMPLETE_FLASH` | 桥内 flash 连续 30s 无进度(疑似卡在写入中途)→ **芯片处于半擦写态,勿直接使用,必须重新完整烧录**;信封带 `chip_state: partially_erased` 与 `post_kill_power_cycle`(已尝试复位) |
415
- | 烧录报 `COLD_BOOT_VERIFY_FAILED` | **Flash 字节已通过逐窗校验,但断电重上电后目标没有有效应答/与期望不符**(现场 `.18` 类问题:GUI 报成功、当场可读,冷启动 `Fw_ver = -1`)→ 按固件冷启动路径排查(看门狗/时钟/外设初始化);或用 `cold_boot_expect` 指定期望值、`cold_boot_check: false` 关闭 |
418
+ | 烧录报 `COLD_BOOT_VERIFY_FAILED` | **Flash 字节已通过逐窗校验,但断电重上电后目标没有有效应答/与期望不符**(现场失败形态:烧录工具报成功、当场可读,冷启动后却读不到版本)→ 按固件冷启动路径排查(看门狗/时钟/外设初始化);或用 `cold_boot_expect` 指定期望值、`cold_boot_check: false` 关闭 |
416
419
  | `fw_serial_status` 的 `port_probe.openable = false` | 端口当前**无法独占打开**(硬结论)→ 看 `holder_candidates`(`source: cmdline` 比 `name` 准,候选≠持有者)确认占用方 |
417
420
 
418
421
  完整速查表与手工部署细节见 [`Fwloop_setup_pack/README.md`](Fwloop_setup_pack/README.md)。
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firmwareloop
3
- Version: 0.7.3
3
+ Version: 0.8.0
4
4
  Summary: AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)
5
5
  Author-email: WeilinZhang <19523330249@163.com>
6
6
  License: MIT
@@ -18,7 +18,7 @@ Requires-Python: >=3.10
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
20
  Requires-Dist: pyvisa>=1.14.0
21
- Requires-Dist: pyvisa-py>=0.7.3
21
+ Requires-Dist: pyvisa-py>=0.7.4
22
22
  Requires-Dist: pyserial>=3.5
23
23
  Requires-Dist: pytest>=8.0.0
24
24
  Requires-Dist: pyocd>=0.36.0
@@ -177,6 +177,8 @@ fwloop setup
177
177
  | Claude Code CLI | `~/.claude.json` |
178
178
  | Qoder / Qoder CN | `~/.qoder/mcp.json`、`~/.qoder-cn/mcp.json` |
179
179
  | CodeBuddy IDE | `~/.codebuddy/mcp.json` |
180
+ | DeepSeek Harness (DSH) | `~/.dsh/profiles/<已派生 profile>/cordis.patch.yml` |
181
+ | ZCode IDE | `~/.zcode/cli/config.json` |
180
182
 
181
183
  2. **同步技能包**(`firmwareloop`、`fwloop-adapter`)到 Antigravity 与 Claude Code 的全局 Skill 目录。
182
184
  3. **生成机器级全局配置** `%APPDATA%\FirmwareLoop\lab.yaml`(NdtBox 配置模板,已存在则不覆盖)。
@@ -383,7 +385,7 @@ claude mcp remove --scope user agentic-hil
383
385
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
384
386
  ├── demo-make/ 示例固件(Make;构建测试载体)
385
387
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
386
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.7.3)
388
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.8.0)
387
389
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
388
390
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
389
391
  ├── CLAUDE.md Claude Code CLI 指南
@@ -393,7 +395,7 @@ claude mcp remove --scope user agentic-hil
393
395
 
394
396
  ---
395
397
 
396
- ## 能力验证状态(v0.7.3
398
+ ## 能力验证状态(v0.8.0
397
399
 
398
400
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
399
401
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -401,6 +403,7 @@ claude mcp remove --scope user agentic-hil
401
403
  | 能力 | 状态 |
402
404
  |---|---|
403
405
  | 双层 MCP 服务(13 个工作流与硬件工具) | Implemented + Protocol Validated(31/31 测试通过) |
406
+ | fwloop setup 一键注册(7 Agent:Antigravity / Claude Code / Qoder(+CN) / CodeBuddy / DeepSeek Harness / ZCode) | Implemented + Multi-Agent Validated(DSH / ZCode 真机写入验证) |
404
407
  | 串口助手工具族(fw_serial_* 七工具, 长驻会话/发送序列/帧解析/窗口采集) | Implemented + Simulator Validated(55 例单测: 含残留 serve 自动清理 / close 进程回收 / UTF-8 线路 / 失败落 JSONL)-> Real Hardware Validated 待 DUT |
405
408
  | 一键多 Agent 脚手架(fwloop init / fw_init_project) | Implemented + Multi-Agent Validated |
406
409
  | 自定义/私有调试工具接入 Skill(fwloop-adapter) | Implemented + Multi-Skill Validated |
@@ -437,10 +440,10 @@ claude mcp remove --scope user agentic-hil
437
440
  | 串口 `SERIAL_PORT_ERROR: ... PermissionError(13)` | 端口被 GUI 上位机独占(NDT Debug Tool / STDataCollection.exe、串口助手)→ 关闭占用方后 `fw_serial_open`;残留会话用 `fw_serial_close`(已自动等待/强杀进程,端口释放可验证) |
438
441
  | `fw_serial_status` 的 `error_class` 为 `UART_BUSY` | 会话未打开或已被占用 → 先 `fw_serial_open`;残留会话 `fw_serial_close` 清理 |
439
442
  | `fw_serial_*` 报 `PermissionError(13)` / `rx_bytes: 0` | 串口被独占:**退出 NDT Debug Tool GUI(STDataCollection.exe)**——它打开时会同时占住 Box 串口与 USB-IIC 通道;失败信封/`fw_serial_status` 的 `suspected_holders` 会直接列出嫌疑进程(注意别杀 MCP server 的 python) |
440
- | 烧录"擦除生效(probe 从非 00 变 00)但校验读回全 FF"、`pages_written` 已发出 | v0.7.1 及更早的逐笔 serve 路径问题 → v0.7.3 起默认走 `flash_engine: bridge`(桥内单体,与 GUI 同进程模型);要复现/排查旧行为用 `flash_engine: "serve"` |
443
+ | 烧录"擦除生效(probe 从非 00 变 00)但校验读回全 FF"、`pages_written` 已发出 | v0.7.1 及更早的逐笔 serve 路径问题 → v0.7.4 起默认走 `flash_engine: bridge`(桥内单体,与 GUI 同进程模型);要复现/排查旧行为用 `flash_engine: "serve"` |
441
444
  | 长调用(capture/measure)客户端超时 | MCP stdio 循环是**单线程**的:长调用会让同会话其它调用排队(含 3s 的小调用)→ 缩短窗口,或用 `fw_ndtdbg_stream_start` job 模式 |
442
445
  | 烧录报 `INCOMPLETE_FLASH` | 桥内 flash 连续 30s 无进度(疑似卡在写入中途)→ **芯片处于半擦写态,勿直接使用,必须重新完整烧录**;信封带 `chip_state: partially_erased` 与 `post_kill_power_cycle`(已尝试复位) |
443
- | 烧录报 `COLD_BOOT_VERIFY_FAILED` | **Flash 字节已通过逐窗校验,但断电重上电后目标没有有效应答/与期望不符**(现场 `.18` 类问题:GUI 报成功、当场可读,冷启动 `Fw_ver = -1`)→ 按固件冷启动路径排查(看门狗/时钟/外设初始化);或用 `cold_boot_expect` 指定期望值、`cold_boot_check: false` 关闭 |
446
+ | 烧录报 `COLD_BOOT_VERIFY_FAILED` | **Flash 字节已通过逐窗校验,但断电重上电后目标没有有效应答/与期望不符**(现场失败形态:烧录工具报成功、当场可读,冷启动后却读不到版本)→ 按固件冷启动路径排查(看门狗/时钟/外设初始化);或用 `cold_boot_expect` 指定期望值、`cold_boot_check: false` 关闭 |
444
447
  | `fw_serial_status` 的 `port_probe.openable = false` | 端口当前**无法独占打开**(硬结论)→ 看 `holder_candidates`(`source: cmdline` 比 `name` 准,候选≠持有者)确认占用方 |
445
448
 
446
449
  完整速查表与手工部署细节见 [`Fwloop_setup_pack/README.md`](Fwloop_setup_pack/README.md)。
@@ -1,5 +1,5 @@
1
1
  pyvisa>=1.14.0
2
- pyvisa-py>=0.7.3
2
+ pyvisa-py>=0.7.4
3
3
  pyserial>=3.5
4
4
  pytest>=8.0.0
5
5
  pyocd>=0.36.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "firmwareloop"
7
- version = "0.7.3"
7
+ version = "0.8.0"
8
8
  description = "AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -14,7 +14,7 @@ license = { text = "MIT" }
14
14
  requires-python = ">=3.10"
15
15
  dependencies = [
16
16
  "pyvisa>=1.14.0",
17
- "pyvisa-py>=0.7.3",
17
+ "pyvisa-py>=0.7.4",
18
18
  "pyserial>=3.5",
19
19
  "pytest>=8.0.0",
20
20
  "pyocd>=0.36.0",
@@ -2,4 +2,4 @@
2
2
  FirmwareLoop - AI Agent Firmware Development and Lab Automation Platform.
3
3
  """
4
4
 
5
- __version__ = "0.7.3"
5
+ __version__ = "0.8.0"
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.7.3).
3
+ fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.8.0).
4
4
 
5
5
  Exposes high-level firmware engineering and hardware management tools to AI Coding
6
- Agents (Antigravity CLI, Claude Code CLI, Qoder IDE, CodeBuddy IDE, Cursor) via the Model Context
6
+ Agents (Antigravity CLI, Claude Code CLI, Qoder IDE, CodeBuddy IDE, DeepSeek Harness,
7
+ ZCode IDE, Cursor) via the Model Context
7
8
  Protocol (JSON-RPC 2.0 stdio).
8
9
 
9
10
  Tools provided:
@@ -332,7 +333,7 @@ def handle_fw_ndtdbg_write_reg(args: Dict[str, Any]) -> Dict[str, Any]:
332
333
  def handle_fw_ndtdbg_flash(args: Dict[str, Any]) -> Dict[str, Any]:
333
334
  """Erase + flash a .bin/.nfw image onto the NdtBox target chip (ChipSea Fxx) over IIC.
334
335
 
335
- P1-3 (0.7.3): 去掉按签名重试 —— "TARGET_MISMATCH @0x0000" 正是"根本没进 boot"的
336
+ P1-3 (0.7.4): 去掉按签名重试 —— "TARGET_MISMATCH @0x0000" 正是"根本没进 boot"的
336
337
  特征签名 (旧 boot 判据假阳的同一条错误路径), 盲目重试只会重复同一失败路径。
337
338
  整片重写 (<= rewrite_times) 现由 flash_exec 内部完成, 结果带 rewrite_count;
338
339
  BOOT_NOT_ENTERED 直接返回指引 (需断电重启, 重试无意义)。
@@ -1156,6 +1157,57 @@ custom_tools:
1156
1157
  向用户展示配置位置,并说明后续在对话中可以直接使用自然语言调度:
1157
1158
  - “*使用我们公司的烧录工具把固件刷入芯片*”
1158
1159
  - “*启动自研抓包工具采集 5 秒串口日志*”
1160
+
1161
+ ---
1162
+
1163
+ ## 可选手法:目标侧"只读诊断插桩"(通用模式)
1164
+
1165
+ **适用**:目标固件"挂死 / 反复重启",没有可用串口输出(或写通道不可用),但工具族能读寄存器。
1166
+ 思路:让固件把**运行痕迹暴露成只读寄存器**,Agent 一次读回即可定位阶段与崩溃现场,
1167
+ 不必"改一处 → 烧一次 → 猜一次"。
1168
+
1169
+ > **⚠️ 归属规则(先看这条)**:本 skill 会**随包分发**(`fwloop init` / `fwloop setup` 会把它
1170
+ > 复制到用户工程与各 Agent 的 skills 目录),因此**这里只放与具体项目、具体芯片无关的通用内容**。
1171
+ > 每个项目的**地址约定、寄存器含义、现场案例属于项目资产**,请记录到:
1172
+ > - 该项目仓库内的 `docs/<project>-probe-convention.md`,或该项目自建的 project skill;
1173
+ >
1174
+ > 本 skill 负责教你**怎么设计**这套插桩、以及**记录到哪里**,不承载任何单一项目的约定。
1175
+
1176
+ ### 通用模式(由粗到细四件套)
1177
+
1178
+ 1. **阶段编号**:最后到达的启动边界;
1179
+ 2. **阶段追踪环**:最近 N 步的环形缓冲(看清"路径",而不只是终点);
1180
+ 3. **计数器组**:主循环迭代数、可疑等待循环的自旋计数、崩溃现场(fault 状态字 / PC / LR / xPSR);
1181
+ 4. **运行时可调"停靠级别"**:写后断电即可逐级二分崩溃点。
1182
+
1183
+ ### 通用约束(与芯片无关,都是踩出来的)
1184
+
1185
+ 1. 插桩数组放 **NOINIT** 段:复位/软复位不清零,才看得到"重启前最后执行到哪";
1186
+ 2. 尽量**只读注册**,不要占用可写寄存器语义;
1187
+ 3. 注册表必须按**地址升序**:乱序会导致从机自检失败 / 初始化提前 `return`
1188
+ ⇒ 通信通道根本没起来,现象与"目标掉电"完全一样(极易误判);
1189
+ 4. **避开厂商协议占用的地址**:例——烧录工具会往某个固定地址写擦除/完成魔数,
1190
+ 插桩变量放在那里会污染工具的判据;
1191
+ 5. 采集遵守工具族的协议约束(升序读、单次长度上限、关键字节双读校验——见各工具描述);
1192
+ 6. 插桩代码用 `#if` 开关包裹:关闭时零成本、零 RAM。
1193
+
1194
+ ### 固件侧两条"已知良方"(与芯片无关)
1195
+
1196
+ 1. **"通道先行"**:把"能被工具读到的通道"(I2C 从机 / 串口)初始化提到所有可疑初始化**之前**
1197
+ ⇒ 之后无论哪里崩,设备仍然可读(把它写在最后,往往会被插桩本身锁死);
1198
+ 2. **fault handler 禁止裸自旋**(`B .`):其优先级高于一切可配置中断,死等会饿死通信中断,
1199
+ 目标"从总线上消失"(工具侧表现为 `BUS_TIMEOUT`)⇒ 应"记录现场 + 复位"。
1200
+ (进阶手法"改写异常返回地址 → 恢复函数 → 重建通道 → 停靠"与芯片强相关,换目标需复测。)
1201
+
1202
+ ### 最小闭环(通用)
1203
+
1204
+ ```text
1205
+ fw_ndtdbg_power_cycle(off_ms=500) # 复位(不需 write_allowed)
1206
+ fw_ndtdbg_status # 分级结论 + 判据表
1207
+ fw_ndtdbg_read_reg(reg=..., len=...) # 读"项目约定文档"里定义的诊断寄存器
1208
+ fw_ndtdbg_flash(...) # 改完固件自助烧录(含烧后冷启动冒烟)
1209
+ fw_serial_capture(power_cycle_off_ms=500) # 抓开机日志(窗口内自动复位)
1210
+ ```
1159
1211
  """
1160
1212
  if not os.path.exists(adapter_skill_path) or overwrite:
1161
1213
  with open(adapter_skill_path, "w", encoding="utf-8") as fh:
@@ -2335,7 +2387,7 @@ def process_request(req: Dict[str, Any]) -> Optional[Dict[str, Any]]:
2335
2387
  },
2336
2388
  "serverInfo": {
2337
2389
  "name": "firmwareloop",
2338
- "version": "0.7.3"
2390
+ "version": "0.8.0"
2339
2391
  }
2340
2392
  }
2341
2393
  }
@@ -2470,7 +2522,7 @@ def _settle_stashed_entrypoints(stashed) -> None:
2470
2522
  def handle_cli_update() -> int:
2471
2523
  """Handle `firmwareloop update` command."""
2472
2524
  print("============================================================")
2473
- print(" FirmwareLoop Auto-Updater (v0.7.3)")
2525
+ print(" FirmwareLoop Auto-Updater (v0.8.0)")
2474
2526
  print("============================================================")
2475
2527
 
2476
2528
  is_git_repo = os.path.exists(os.path.join(REPO_ROOT, ".git"))
@@ -2813,6 +2865,192 @@ def configure_codebuddy_user_mcp(user_home: str) -> Dict[str, Any]:
2813
2865
  return {"ok": False, "path": mcp_file, "reason": str(exc)}
2814
2866
 
2815
2867
 
2868
+ DSH_MCP_CLIENT_PLUGIN = "@deepseek-ai/dsh-mcp-client"
2869
+
2870
+ # DSH (DeepSeek Harness) profile patch entries. Tools surface as
2871
+ # mcp__<serverName>__<tool> (same shape as Claude Code / Codex), e.g.
2872
+ # mcp__fwloop__fw_build. Bare command names resolve via PATH: the DSH
2873
+ # stdio transport only scrubs credential-shaped / DSH_* env vars, so the
2874
+ # parent PATH survives (same convention as the Qoder / Claude entries).
2875
+ DSH_MCP_SERVER_ENTRIES = (
2876
+ ("mcp-fwloop", "fwloop", {"command": "fwloop", "args": []}),
2877
+ ("mcp-agentic-hil", "agentic-hil", {"command": "agentic-hil", "args": ["mcp-stdio"]}),
2878
+ )
2879
+
2880
+ DSH_PATCH_HEADER = (
2881
+ "# FirmwareLoop dual-tier MCP (added by fwloop setup).\n"
2882
+ "# Bridged by @deepseek-ai/dsh-mcp-client; tools surface as mcp__<serverName>__<tool>.\n"
2883
+ )
2884
+
2885
+
2886
+ def resolve_dsh_home(user_home: str) -> str:
2887
+ """Resolve the DeepSeek Harness home: non-blank $DSH_HOME wins, else ~/.dsh.
2888
+
2889
+ Mirrors @deepseek-ai/dsh-home-paths precedence (an in-harness configured
2890
+ home override is invisible to external tools and therefore not honored).
2891
+ """
2892
+ env_home = (os.environ.get("DSH_HOME") or "").strip()
2893
+ return env_home if env_home else os.path.join(user_home, ".dsh")
2894
+
2895
+
2896
+ def discover_dsh_profiles(dsh_home: str) -> List[str]:
2897
+ """List derived DSH profile names under <home>/profiles.
2898
+
2899
+ A directory counts as a profile only when it has a profile-root cordis.yml,
2900
+ which excludes the shared <home>/profiles/node_modules dependency tree.
2901
+ Built-in profiles (web/tui/headless) appear here once the user has booted
2902
+ or derived them; never-derived ones do not exist on disk and are skipped.
2903
+ """
2904
+ profiles_dir = os.path.join(dsh_home, "profiles")
2905
+ found: List[str] = []
2906
+ if os.path.isdir(profiles_dir):
2907
+ for name in sorted(os.listdir(profiles_dir)):
2908
+ cand = os.path.join(profiles_dir, name)
2909
+ if os.path.isdir(cand) and os.path.isfile(os.path.join(cand, "cordis.yml")):
2910
+ found.append(name)
2911
+ return found
2912
+
2913
+
2914
+ def _dsh_entry_yaml(entry_id: str, server_name: str, spec: Dict[str, Any]) -> str:
2915
+ args_repr = ", ".join(f"'{a}'" for a in spec.get("args", []))
2916
+ return (
2917
+ f" - id: {entry_id}\n"
2918
+ f" name: '{DSH_MCP_CLIENT_PLUGIN}'\n"
2919
+ f" config:\n"
2920
+ f" serverName: {server_name}\n"
2921
+ f" transport: stdio\n"
2922
+ f" command: {spec['command']}\n"
2923
+ f" args: [{args_repr}]\n"
2924
+ )
2925
+
2926
+
2927
+ def upsert_dsh_patch_file(patch_path: str) -> str:
2928
+ """Idempotently add the FirmwareLoop MCP entries to a profile's cordis.patch.yml.
2929
+
2930
+ Returns "written" or "already_configured". Text-level upsert on purpose:
2931
+ a yaml.safe_dump round-trip would strip the user's guide comments, so an
2932
+ existing file is only ever appended to. Membership is decided by a plain
2933
+ substring check on our fixed ids (fail-safe side: a false positive merely
2934
+ skips the write), and entries that already exist are never rewritten so
2935
+ user overrides (e.g. a custom command) survive setup re-runs.
2936
+ """
2937
+ present = ""
2938
+ if os.path.exists(patch_path):
2939
+ with open(patch_path, "r", encoding="utf-8-sig") as f:
2940
+ present = f.read()
2941
+ missing = [eid for eid, _, _ in DSH_MCP_SERVER_ENTRIES if f"id: {eid}" not in present]
2942
+ if present and not missing:
2943
+ return "already_configured"
2944
+ # Single "- insert:" block holding the missing entries, matching the shape
2945
+ # of the official dsh-mcp-client sample (one block, several entries).
2946
+ new_text = "- insert:\n" + "".join(
2947
+ _dsh_entry_yaml(eid, name, spec)
2948
+ for eid, name, spec in DSH_MCP_SERVER_ENTRIES
2949
+ if eid in missing
2950
+ )
2951
+ parent = os.path.dirname(patch_path)
2952
+ if parent:
2953
+ os.makedirs(parent, exist_ok=True)
2954
+ if not present:
2955
+ with open(patch_path, "w", encoding="utf-8", newline="\n") as f:
2956
+ f.write(DSH_PATCH_HEADER)
2957
+ f.write(new_text)
2958
+ return "written"
2959
+ stripped = present.strip()
2960
+ with open(patch_path, "w", encoding="utf-8", newline="\n") as f:
2961
+ if not stripped or stripped == "[]":
2962
+ # Empty document (blank or literal []): keep leading comment lines,
2963
+ # then start the entries array.
2964
+ comments = "\n".join(
2965
+ line for line in present.splitlines() if line.strip().startswith("#")
2966
+ )
2967
+ if comments:
2968
+ f.write(comments + "\n")
2969
+ f.write(new_text)
2970
+ else:
2971
+ f.write(present)
2972
+ if not present.endswith("\n"):
2973
+ f.write("\n")
2974
+ f.write("\n" + new_text)
2975
+ return "written"
2976
+
2977
+
2978
+ def configure_dsh_profiles(user_home: str) -> List[Dict[str, Any]]:
2979
+ """Add FirmwareLoop MCP entries to every derived DSH profile's cordis.patch.yml."""
2980
+ dsh_home = resolve_dsh_home(user_home)
2981
+ results: List[Dict[str, Any]] = []
2982
+ for profile in discover_dsh_profiles(dsh_home):
2983
+ patch_path = os.path.join(dsh_home, "profiles", profile, "cordis.patch.yml")
2984
+ try:
2985
+ status = upsert_dsh_patch_file(patch_path)
2986
+ results.append({"profile": profile, "ok": True, "path": patch_path, "status": status})
2987
+ except Exception as exc:
2988
+ results.append({"profile": profile, "ok": False, "path": patch_path, "reason": str(exc)})
2989
+ return results
2990
+
2991
+
2992
+ ZCODE_MCP_SERVERS = {
2993
+ "fwloop": {"command": "fwloop", "type": "stdio"},
2994
+ "agentic-hil": {"command": "agentic-hil", "args": ["mcp-stdio"], "type": "stdio"},
2995
+ }
2996
+
2997
+
2998
+ def upsert_zcode_mcp_json(mcp_path: str, servers: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
2999
+ """Merge MCP servers into ZCode's ~/.zcode/cli/config.json without dropping
3000
+ existing entries.
3001
+
3002
+ ZCode (GLM desktop IDE) nests its MCP registry under "mcp"."servers" —
3003
+ the per-entry shape (type/command/args) matches Qoder's mcpServers, so the
3004
+ same per-entry merge (keep user extras like env) applies.
3005
+ """
3006
+ payload = dict(servers or ZCODE_MCP_SERVERS)
3007
+ data: Dict[str, Any] = {}
3008
+ if os.path.exists(mcp_path):
3009
+ try:
3010
+ with open(mcp_path, "r", encoding="utf-8-sig") as f:
3011
+ loaded = json.load(f)
3012
+ if isinstance(loaded, dict):
3013
+ data = loaded
3014
+ except Exception:
3015
+ data = {}
3016
+ mcp_root = data.get("mcp")
3017
+ if not isinstance(mcp_root, dict):
3018
+ mcp_root = {}
3019
+ mcp_servers = mcp_root.get("servers")
3020
+ if not isinstance(mcp_servers, dict):
3021
+ mcp_servers = {}
3022
+ for name, entry in payload.items():
3023
+ old = mcp_servers.get(name)
3024
+ if isinstance(old, dict) and isinstance(entry, dict):
3025
+ merged = dict(old)
3026
+ merged.update(entry)
3027
+ mcp_servers[name] = merged
3028
+ else:
3029
+ mcp_servers[name] = entry
3030
+ mcp_root["servers"] = mcp_servers
3031
+ data["mcp"] = mcp_root
3032
+ parent = os.path.dirname(mcp_path)
3033
+ if parent:
3034
+ os.makedirs(parent, exist_ok=True)
3035
+ with open(mcp_path, "w", encoding="utf-8") as f:
3036
+ json.dump(data, f, indent=2)
3037
+ f.write("\n")
3038
+ return data
3039
+
3040
+
3041
+ def configure_zcode_user_mcp(user_home: str) -> Dict[str, Any]:
3042
+ """Write FirmwareLoop MCP entries into ZCode's ~/.zcode/cli/config.json."""
3043
+ zcode_dir = os.path.join(user_home, ".zcode")
3044
+ mcp_file = os.path.join(zcode_dir, "cli", "config.json")
3045
+ if not os.path.isdir(zcode_dir):
3046
+ return {"ok": False, "path": mcp_file, "reason": "not_installed"}
3047
+ try:
3048
+ upsert_zcode_mcp_json(mcp_file)
3049
+ return {"ok": True, "path": mcp_file}
3050
+ except Exception as exc:
3051
+ return {"ok": False, "path": mcp_file, "reason": str(exc)}
3052
+
3053
+
2816
3054
  def resolve_ndtdebugtool_lib(tool_root: str) -> str:
2817
3055
  """Resolve the NdtDebugTool lib directory (must contain USBIOX.DLL)."""
2818
3056
  if not tool_root or not os.path.isdir(tool_root):
@@ -2899,9 +3137,9 @@ def set_ndtdbg_dlldir(dll_path: str) -> str:
2899
3137
 
2900
3138
 
2901
3139
  def handle_cli_setup() -> int:
2902
- """Handle `firmwareloop setup` command: simultaneously configure Antigravity CLI, Claude Code CLI, Qoder IDE, and CodeBuddy IDE."""
3140
+ """Handle `firmwareloop setup` command: simultaneously configure Antigravity CLI, Claude Code CLI, Qoder IDE, CodeBuddy IDE, DeepSeek Harness (DSH), and ZCode IDE."""
2903
3141
  print("============================================================")
2904
- print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.7.3)")
3142
+ print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.8.0)")
2905
3143
  print("============================================================")
2906
3144
  print("")
2907
3145
 
@@ -2985,7 +3223,37 @@ def handle_cli_setup() -> int:
2985
3223
  else:
2986
3224
  print(f" - User MCP: [Warning] Could not write {cb_result['path']}: {cb_result.get('reason')}")
2987
3225
 
2988
- # 5. Global Skills Sync for Antigravity and Claude Code
3226
+ # 5. DeepSeek Harness (DSH) per-profile cordis.patch.yml upsert
3227
+ # Only profiles already derived under <home>/profiles (a booted or
3228
+ # --from-default-profile'd profile has a profile-root cordis.yml) are
3229
+ # configured; never-derived built-ins do not exist on disk and are skipped.
3230
+ print("\n[5] DeepSeek Harness (DSH):")
3231
+ dsh_results = configure_dsh_profiles(user_home)
3232
+ dsh_ok = [item for item in dsh_results if item.get("ok")]
3233
+ if dsh_ok:
3234
+ for item in dsh_ok:
3235
+ state = "already configured" if item["status"] == "already_configured" else "written"
3236
+ print(f" - profile {item['profile']}: [OK] {state}: {item['path']}")
3237
+ configured_agents.append("DeepSeek Harness (DSH)")
3238
+ else:
3239
+ print(" - ~/.dsh/profiles has no derived profile (DSH not installed, or no profile booted yet)")
3240
+ print(" - Boot/derive a profile in DSH first, then re-run: fwloop setup")
3241
+ for item in dsh_results:
3242
+ if not item.get("ok"):
3243
+ print(f" - profile {item['profile']}: [Warning] Could not write {item['path']}: {item.get('reason')}")
3244
+
3245
+ # 6. ZCode IDE user-level MCP (~/.zcode/cli/config.json, {"mcp": {"servers": ...}})
3246
+ print("\n[6] ZCode IDE:")
3247
+ zc_result = configure_zcode_user_mcp(user_home)
3248
+ if zc_result.get("ok"):
3249
+ print(f" - User MCP: [OK] Written to {zc_result['path']}")
3250
+ configured_agents.append("ZCode")
3251
+ elif zc_result.get("reason") == "not_installed":
3252
+ print(" - User MCP: ~/.zcode not found (Workspace .mcp.json still supported)")
3253
+ else:
3254
+ print(f" - User MCP: [Warning] Could not write {zc_result['path']}: {zc_result.get('reason')}")
3255
+
3256
+ # 7. Global Skills Sync for Antigravity and Claude Code
2989
3257
  ag_skills_dir = os.path.join(user_home, ".gemini", "antigravity-cli", "skills")
2990
3258
  claude_skills_dir = os.path.join(user_home, ".claude", "skills")
2991
3259
  source_skills_dir = os.path.join(REPO_ROOT, "skills")
@@ -3006,14 +3274,14 @@ def handle_cli_setup() -> int:
3006
3274
  except Exception:
3007
3275
  pass
3008
3276
 
3009
- print(f"\n[5] Global Skills:")
3277
+ print(f"\n[7] Global Skills:")
3010
3278
  print(f" - Synchronized: [OK] {skills_synced} skills (firmwareloop, fwloop-adapter) to Antigravity & Claude Code")
3011
3279
 
3012
- # 5. Machine-level global lab.yaml (ndtdbg config for the globally installed tool)
3280
+ # 8. Machine-level global lab.yaml (ndtdbg config for the globally installed tool)
3013
3281
  global_cfg = ensure_global_lab_yaml()
3014
3282
  if global_cfg:
3015
3283
  exists = " [已存在, 未覆盖]" if os.path.isfile(global_cfg) else " [已创建]"
3016
- print("\n[6] NdtBox 全局配置:")
3284
+ print("\n[8] NdtBox 全局配置:")
3017
3285
  print(f" - {global_cfg}{exists}")
3018
3286
  print(" - 若未配置, 请运行: fwloop ndtdebugtool \"<NdtDebugTool 根目录>\"")
3019
3287
 
@@ -3026,7 +3294,7 @@ def handle_cli_setup() -> int:
3026
3294
  def handle_cli_init(chip: Optional[str] = None, upgrade: bool = False) -> int:
3027
3295
  """Handle `firmwareloop init [target_chip]` command."""
3028
3296
  print("============================================================")
3029
- print(" FirmwareLoop Multi-Agent Project Initializer (v0.7.3)")
3297
+ print(" FirmwareLoop Multi-Agent Project Initializer (v0.8.0)")
3030
3298
  print("============================================================")
3031
3299
  cwd = os.getcwd()
3032
3300
  print(f"[*] Initializing multi-agent guidelines & bench config in:\n {cwd}\n")
@@ -3059,7 +3327,7 @@ def handle_cli_init(chip: Optional[str] = None, upgrade: bool = False) -> int:
3059
3327
 
3060
3328
 
3061
3329
  def print_cli_help() -> None:
3062
- print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.7.3)
3330
+ print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.8.0)
3063
3331
 
3064
3332
  Usage:
3065
3333
  fwloop [command] (or: firmwareloop [command])
@@ -3105,7 +3373,7 @@ def main() -> None:
3105
3373
  sys.exit(2)
3106
3374
  sys.exit(handle_cli_ndtdebugtool(args[1]))
3107
3375
  elif cmd in ["version", "-v", "--version"]:
3108
- print("FirmwareLoop v0.7.3")
3376
+ print("FirmwareLoop v0.8.0")
3109
3377
  sys.exit(0)
3110
3378
  elif cmd in ["help", "-h", "--help"]:
3111
3379
  print_cli_help()
@@ -828,7 +828,7 @@ class NdtBoxIo:
828
828
  """桥内单体 flash 引擎 (0.7.2 起为默认): 单进程内 USBIOX(0) 与 USB2IO(1) 句柄同持,
829
829
 
830
830
  帧经 stdin 一次性传入、全程连续无逐笔管道往返 —— 即原厂 GUI 的进程模型, 也是
831
- 现场 (2026-09-11 F72) 6/6 verify pass 的那条路径。校验失败 (桥报
831
+ 现场 (2026-09-11) 6/6 verify pass 的那条路径。校验失败 (桥报
832
832
  TARGET_MISMATCH "烧录校验失败") 时按 rewrite_times 整片重跑, 其余错误直接上抛。
833
833
  """
834
834
  import time
@@ -879,7 +879,7 @@ class NdtBoxIo:
879
879
  def flash_exec(self, plan: dict, timeout_ms: int | None = None) -> dict:
880
880
  """烧录引擎分派: "bridge" (默认, 桥内单体 flash) / "serve" (逐笔 Python 驱动)。
881
881
 
882
- 现场实证 (2026-09-11, F72, 同一批固件 + 同一台设备):
882
+ 现场实证 (2026-09-11, 同一批固件 + 同一台设备):
883
883
  桥内单体 flash (帧经 stdin 一次传入) -> 6/6 {"ok":true,"verify":"pass"}
884
884
  逐笔 serve 路径 (每页一笔 raw 事务) -> 100% "擦除生效但页写不落地"
885
885
  (probe FFFFFFFF -> 00000000 说明 7 字节擦除帧到达; 99 页 write_ms 7594ms
@@ -1428,8 +1428,8 @@ class ChipSeaFxx:
1428
1428
  expect: str | None = None) -> dict:
1429
1429
  """烧后冷启动冒烟 (评审 §4): 断电重上电 -> 读已知寄存器 -> 判定固件是否真的跑起来。
1430
1430
 
1431
- 只校验 Flash 字节的流程抓不到"镜像烧对了但跑不起来"——现场 `.18` 正是: GUI 报
1432
- `FW Upgrade Success` 且当场可读, 断电重上电后 `Fw_ver = -1`。这里 fail-closed:
1431
+ 只校验 Flash 字节的流程抓不到"镜像烧对了但跑不起来"——现场出现过: 烧录工具报成功
1432
+ 且当场可读, 断电重上电后版本寄存器却读不到。这里 fail-closed:
1433
1433
  expect 给定时逐字节比对; 未给定时判"有无效应答"(读不到或全 00/FF 都算失败)。
1434
1434
  """
1435
1435
  import time
@@ -1452,7 +1452,7 @@ class ChipSeaFxx:
1452
1452
  if raw is None:
1453
1453
  out["ok"] = False
1454
1454
  out["conclusion"] = ("冷启动后该寄存器无应答: 固件可能未起振/未使能 I2C 从机 "
1455
- "—— Flash 字节已验证, 但目标跑不起来 (现场 .18 类问题的特征)")
1455
+ "—— Flash 字节已验证, 但目标跑不起来 (冷启动失败的特征)")
1456
1456
  return out
1457
1457
  if want is not None:
1458
1458
  if raw[:len(want)] != want:
@@ -1530,7 +1530,7 @@ class ChipSeaFxx:
1530
1530
  "pages_written": len(pages), "window_verified": True,
1531
1531
  "cold_boot": cold,
1532
1532
  "hint": "①确认目标固件在本寄存器上确有可读内容 (否则用 cold_boot_expect 指定)"
1533
- "; ②按现场 .18 类问题排查冷启动路径 (看门狗/时钟/外设初始化); "
1533
+ "; ②按冷启动路径排查 (看门狗/时钟/外设初始化); "
1534
1534
  "③如确不需要该校验, 用 cold_boot_check=false / --no-cold-boot-check 关闭"})
1535
1535
  return {
1536
1536
  "file": file_path,
@@ -1,6 +1,6 @@
1
1
  <#
2
2
  .SYNOPSIS
3
- Dual-Tier MCP setup and registration helper (v0.7.3).
3
+ Dual-Tier MCP setup and registration helper (v0.8.0).
4
4
  Inspects installed AI coding agents (Qoder, Claude Code, Antigravity, Cursor)
5
5
  and configures global MCP / skills or prints exact registration commands.
6
6
 
@@ -242,7 +242,7 @@ if ($Json) {
242
242
  Write-FwJson ([pscustomobject]$report)
243
243
  } else {
244
244
  Write-Host "============================================================" -ForegroundColor Cyan
245
- Write-Host " FirmwareLoop Dual-Tier MCP & Agent Setup Helper (v0.7.3)" -ForegroundColor Green
245
+ Write-Host " FirmwareLoop Dual-Tier MCP & Agent Setup Helper (v0.8.0)" -ForegroundColor Green
246
246
  Write-Host "============================================================" -ForegroundColor Cyan
247
247
  Write-Host ""
248
248
  Write-Host "[1] Google Antigravity / Gemini CLI:" -ForegroundColor Yellow
File without changes
File without changes
File without changes