firmwareloop 0.11.1__tar.gz → 0.11.2__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 (44) hide show
  1. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/PKG-INFO +14 -4
  2. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/README.md +13 -3
  3. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/firmwareloop.egg-info/PKG-INFO +14 -4
  4. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/firmwareloop.egg-info/SOURCES.txt +1 -0
  5. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/pyproject.toml +1 -1
  6. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/__init__.py +1 -1
  7. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/can.ps1 +2 -2
  8. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/flash.ps1 +1 -1
  9. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/fw_mcp_server.py +80 -30
  10. firmwareloop-0.11.2/tools/installer/README.md +44 -0
  11. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/lib/serial_assistant.py +11 -0
  12. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/logic_capture.ps1 +7 -7
  13. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/logic_decode.ps1 +5 -2
  14. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/setup-agent-mcp.ps1 +2 -2
  15. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/LICENSE +0 -0
  16. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/firmwareloop.egg-info/dependency_links.txt +0 -0
  17. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/firmwareloop.egg-info/entry_points.txt +0 -0
  18. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/firmwareloop.egg-info/requires.txt +0 -0
  19. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/firmwareloop.egg-info/top_level.txt +0 -0
  20. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/setup.cfg +0 -0
  21. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/acceptance-scenario.ps1 +0 -0
  22. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/build.ps1 +0 -0
  23. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/check-qoder-mcp.ps1 +0 -0
  24. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/common/build-backends.psm1 +0 -0
  25. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/common/fw.psm1 +0 -0
  26. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/common/uart_probe.py +0 -0
  27. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/doctor.ps1 +0 -0
  28. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/instrument_cli.py +0 -0
  29. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/lib/__init__.py +0 -0
  30. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/lib/doctor_summary.py +0 -0
  31. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/lib/instruments.py +0 -0
  32. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/lib/ndtdbg.py +0 -0
  33. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/lib/session_run.py +0 -0
  34. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/logic_capture_summary.py +0 -0
  35. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/ndtdbg_bridge.ps1 +0 -0
  36. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/ndtdbg_cli.py +0 -0
  37. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/reset.ps1 +0 -0
  38. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/serial_cli.py +0 -0
  39. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/sigrok_csv_to_fwloop.py +0 -0
  40. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/templates/lab.example.yaml +0 -0
  41. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/templates/skill-firmwareloop.md +0 -0
  42. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/templates/skill-fwloop-adapter.md +0 -0
  43. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/test-backends.ps1 +0 -0
  44. {firmwareloop-0.11.1 → firmwareloop-0.11.2}/tools/test.ps1 +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firmwareloop
3
- Version: 0.11.1
3
+ Version: 0.11.2
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
@@ -234,7 +234,17 @@ fwloop setup
234
234
  | DeepSeek Harness (DSH) | `~/.dsh/profiles/<已派生 profile>/cordis.patch.yml` |
235
235
  | ZCode IDE | `~/.zcode/cli/config.json` |
236
236
 
237
- 2. **同步技能包**(`firmwareloop`、`fwloop-adapter`)到 Antigravity 与 Claude Code 的全局 Skill 目录。
237
+ 2. **同步技能包**(`firmwareloop`、`fwloop-adapter`)到各 Agent 的全局 Skill 目录(探测式:Agent 主目录存在才写入,`skills/` 子目录自动创建):
238
+
239
+ | Agent | Skill 写入位置 |
240
+ |---|---|
241
+ | Google Antigravity / Gemini CLI | `~/.gemini/antigravity-cli/skills/` |
242
+ | Claude Code CLI | `~/.claude/skills/` |
243
+ | Qoder / Qoder CN | `~/.qoder/skills/`、`~/.qoder-cn/skills/` |
244
+ | CodeBuddy IDE | `~/.codebuddy/skills/` |
245
+ | DeepSeek Harness (DSH) | `~/.dsh/skills/` |
246
+ | ZCode IDE | `~/.zcode/skills/` |
247
+ | 通用(跨 Agent 工具链) | `~/.agents/skills/`(特殊:无"未安装"概念,机器上不存在时直接创建) |
238
248
  3. **生成机器级全局配置** `%APPDATA%\FirmwareLoop\lab.yaml`(NdtBox 配置模板,已存在则不覆盖)。
239
249
 
240
250
  > 手动注册(可选):Claude Code 也可逐条注册,效果相同:
@@ -439,7 +449,7 @@ claude mcp remove --scope user agentic-hil
439
449
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
440
450
  ├── demo-make/ 示例固件(Make;构建测试载体)
441
451
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
442
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.11.1)
452
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.11.2)
443
453
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
444
454
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
445
455
  ├── CLAUDE.md Claude Code CLI 指南
@@ -449,7 +459,7 @@ claude mcp remove --scope user agentic-hil
449
459
 
450
460
  ---
451
461
 
452
- ## 能力验证状态(v0.11.1)
462
+ ## 能力验证状态(v0.11.2)
453
463
 
454
464
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
455
465
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -204,7 +204,17 @@ fwloop setup
204
204
  | DeepSeek Harness (DSH) | `~/.dsh/profiles/<已派生 profile>/cordis.patch.yml` |
205
205
  | ZCode IDE | `~/.zcode/cli/config.json` |
206
206
 
207
- 2. **同步技能包**(`firmwareloop`、`fwloop-adapter`)到 Antigravity 与 Claude Code 的全局 Skill 目录。
207
+ 2. **同步技能包**(`firmwareloop`、`fwloop-adapter`)到各 Agent 的全局 Skill 目录(探测式:Agent 主目录存在才写入,`skills/` 子目录自动创建):
208
+
209
+ | Agent | Skill 写入位置 |
210
+ |---|---|
211
+ | Google Antigravity / Gemini CLI | `~/.gemini/antigravity-cli/skills/` |
212
+ | Claude Code CLI | `~/.claude/skills/` |
213
+ | Qoder / Qoder CN | `~/.qoder/skills/`、`~/.qoder-cn/skills/` |
214
+ | CodeBuddy IDE | `~/.codebuddy/skills/` |
215
+ | DeepSeek Harness (DSH) | `~/.dsh/skills/` |
216
+ | ZCode IDE | `~/.zcode/skills/` |
217
+ | 通用(跨 Agent 工具链) | `~/.agents/skills/`(特殊:无"未安装"概念,机器上不存在时直接创建) |
208
218
  3. **生成机器级全局配置** `%APPDATA%\FirmwareLoop\lab.yaml`(NdtBox 配置模板,已存在则不覆盖)。
209
219
 
210
220
  > 手动注册(可选):Claude Code 也可逐条注册,效果相同:
@@ -409,7 +419,7 @@ claude mcp remove --scope user agentic-hil
409
419
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
410
420
  ├── demo-make/ 示例固件(Make;构建测试载体)
411
421
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
412
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.11.1)
422
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.11.2)
413
423
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
414
424
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
415
425
  ├── CLAUDE.md Claude Code CLI 指南
@@ -419,7 +429,7 @@ claude mcp remove --scope user agentic-hil
419
429
 
420
430
  ---
421
431
 
422
- ## 能力验证状态(v0.11.1)
432
+ ## 能力验证状态(v0.11.2)
423
433
 
424
434
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
425
435
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firmwareloop
3
- Version: 0.11.1
3
+ Version: 0.11.2
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
@@ -234,7 +234,17 @@ fwloop setup
234
234
  | DeepSeek Harness (DSH) | `~/.dsh/profiles/<已派生 profile>/cordis.patch.yml` |
235
235
  | ZCode IDE | `~/.zcode/cli/config.json` |
236
236
 
237
- 2. **同步技能包**(`firmwareloop`、`fwloop-adapter`)到 Antigravity 与 Claude Code 的全局 Skill 目录。
237
+ 2. **同步技能包**(`firmwareloop`、`fwloop-adapter`)到各 Agent 的全局 Skill 目录(探测式:Agent 主目录存在才写入,`skills/` 子目录自动创建):
238
+
239
+ | Agent | Skill 写入位置 |
240
+ |---|---|
241
+ | Google Antigravity / Gemini CLI | `~/.gemini/antigravity-cli/skills/` |
242
+ | Claude Code CLI | `~/.claude/skills/` |
243
+ | Qoder / Qoder CN | `~/.qoder/skills/`、`~/.qoder-cn/skills/` |
244
+ | CodeBuddy IDE | `~/.codebuddy/skills/` |
245
+ | DeepSeek Harness (DSH) | `~/.dsh/skills/` |
246
+ | ZCode IDE | `~/.zcode/skills/` |
247
+ | 通用(跨 Agent 工具链) | `~/.agents/skills/`(特殊:无"未安装"概念,机器上不存在时直接创建) |
238
248
  3. **生成机器级全局配置** `%APPDATA%\FirmwareLoop\lab.yaml`(NdtBox 配置模板,已存在则不覆盖)。
239
249
 
240
250
  > 手动注册(可选):Claude Code 也可逐条注册,效果相同:
@@ -439,7 +449,7 @@ claude mcp remove --scope user agentic-hil
439
449
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
440
450
  ├── demo-make/ 示例固件(Make;构建测试载体)
441
451
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
442
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.11.1)
452
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.11.2)
443
453
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
444
454
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
445
455
  ├── CLAUDE.md Claude Code CLI 指南
@@ -449,7 +459,7 @@ claude mcp remove --scope user agentic-hil
449
459
 
450
460
  ---
451
461
 
452
- ## 能力验证状态(v0.11.1)
462
+ ## 能力验证状态(v0.11.2)
453
463
 
454
464
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
455
465
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -30,6 +30,7 @@ tools/test.ps1
30
30
  tools/common/build-backends.psm1
31
31
  tools/common/fw.psm1
32
32
  tools/common/uart_probe.py
33
+ tools/installer/README.md
33
34
  tools/lib/__init__.py
34
35
  tools/lib/doctor_summary.py
35
36
  tools/lib/instruments.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "firmwareloop"
7
- version = "0.11.1"
7
+ version = "0.11.2"
8
8
  description = "AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -2,4 +2,4 @@
2
2
  FirmwareLoop - AI Agent Firmware Development and Lab Automation Platform.
3
3
  """
4
4
 
5
- __version__ = "0.11.1"
5
+ __version__ = "0.11.2"
@@ -61,8 +61,8 @@ if ($Backend -eq 'agentic-hil' -and -not $tool) {
61
61
  }
62
62
 
63
63
  # Resolve lab config for adapter/channel/bitrate defaults (never hardcoded)
64
- $labCfg = Join-Path $repoRoot 'lab\lab.yaml'
65
- if (-not (Test-Path -LiteralPath $labCfg)) { $labCfg = Join-Path $repoRoot 'lab\lab.example.yaml' }
64
+ $labCfg = Join-Path (Join-Path $repoRoot 'lab') 'lab.yaml'
65
+ if (-not (Test-Path -LiteralPath $labCfg)) { $labCfg = Join-Path (Join-Path $repoRoot 'lab') 'lab.example.yaml' }
66
66
  $canCfg = @{}
67
67
  if (Test-Path -LiteralPath $labCfg) {
68
68
  try {
@@ -87,7 +87,7 @@ switch ($Backend) {
87
87
  Exit-WithError -Class 'TOOLCHAIN_NOT_FOUND' -Message 'pyocd 未找到。请在 Python 环境中安装 pyocd (`uv pip install pyocd`)。' -Detail 'pyOCD 用于通过 ST-LINK / CMSIS-DAP 烧录 STM32 芯片。'
88
88
  }
89
89
  $targetChip = 'stm32f103rc'
90
- $labYaml = Join-Path $repoRoot 'lab\lab.yaml'
90
+ $labYaml = Join-Path (Join-Path $repoRoot 'lab') 'lab.yaml'
91
91
  if (Test-Path -LiteralPath $labYaml) {
92
92
  $labContent = Get-Content -LiteralPath $labYaml -Raw
93
93
  if ($labContent -match 'target_chip:\s*["'']?([^"''\r\n]+)') {
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.11.1).
3
+ fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.11.2).
4
4
 
5
5
  Exposes high-level firmware engineering and hardware management tools to AI Coding
6
6
  Agents (Antigravity CLI, Claude Code CLI, Qoder IDE, CodeBuddy IDE, DeepSeek Harness,
@@ -2610,7 +2610,7 @@ def process_request(req: Dict[str, Any]) -> Optional[Dict[str, Any]]:
2610
2610
  },
2611
2611
  "serverInfo": {
2612
2612
  "name": "firmwareloop",
2613
- "version": "0.11.1"
2613
+ "version": "0.11.2"
2614
2614
  }
2615
2615
  }
2616
2616
  }
@@ -2745,7 +2745,7 @@ def _settle_stashed_entrypoints(stashed) -> None:
2745
2745
  def handle_cli_update() -> int:
2746
2746
  """Handle `firmwareloop update` command."""
2747
2747
  print("============================================================")
2748
- print(" FirmwareLoop Auto-Updater (v0.11.1)")
2748
+ print(" FirmwareLoop Auto-Updater (v0.11.2)")
2749
2749
  print("============================================================")
2750
2750
 
2751
2751
  is_git_repo = os.path.exists(os.path.join(REPO_ROOT, ".git"))
@@ -3224,6 +3224,67 @@ def configure_codebuddy_user_mcp(user_home: str) -> Dict[str, Any]:
3224
3224
  return {"ok": False, "path": mcp_file, "reason": str(exc)}
3225
3225
 
3226
3226
 
3227
+ # setup [7] Skill 同步目标: 与 MCP 注册列表对齐 (MCP 支持哪个 Agent, Skill 就配哪个),
3228
+ # 另含 .agents 跨 Agent 通用约定。顺序对齐 setup 的 MCP 段编号。
3229
+ # 形状均为 <agent主目录>/<skills相对路径>/<skill>/<name>/SKILL.md; 探测判据 = agent
3230
+ # 主目录存在 (与各 MCP 段的 not_installed 语义一致; skills/ 子目录不存在时自动创建)。
3231
+ # 例外: .agents 是跨 Agent 通用约定, 无"未安装"概念 -> install_dir=None 免探测,
3232
+ # 机器上不存在时直接创建 ~/.agents 写入。
3233
+ SKILL_SYNC_TARGETS = [
3234
+ # (显示名, agent 主目录[安装探测判据; None=通用免探测], 全局 skills 目录相对 user_home)
3235
+ ("Antigravity", ".gemini", os.path.join(".gemini", "antigravity-cli", "skills")),
3236
+ ("Claude Code", ".claude", os.path.join(".claude", "skills")),
3237
+ ("Qoder", ".qoder", os.path.join(".qoder", "skills")),
3238
+ ("Qoder CN", ".qoder-cn", os.path.join(".qoder-cn", "skills")),
3239
+ ("CodeBuddy", ".codebuddy", os.path.join(".codebuddy", "skills")),
3240
+ ("DSH", ".dsh", os.path.join(".dsh", "skills")),
3241
+ ("ZCode", ".zcode", os.path.join(".zcode", "skills")),
3242
+ (".agents (cross-agent)", None, os.path.join(".agents", "skills")),
3243
+ ]
3244
+
3245
+ GLOBAL_SKILL_NAMES = ("firmwareloop", "fwloop-adapter")
3246
+
3247
+
3248
+ def sync_global_skills(user_home: str) -> List[Dict[str, Any]]:
3249
+ """把 GLOBAL_SKILL_NAMES 中的 skill 同步到各 Agent 全局 skills 目录 (表驱动)。
3250
+
3251
+ - 目标来自 SKILL_SYNC_TARGETS (与 setup 的 MCP 注册面对齐);
3252
+ - 探测语义与 MCP 段一致: agent 主目录不存在 -> not_installed 跳过, 不创建;
3253
+ install_dir=None 的通用目标 (.agents) 免探测, 不存在时直接创建;
3254
+ - 已存在的 SKILL.md 无条件覆盖 (与既有 Antigravity/Claude 行为一致, 顺带
3255
+ 消除 skills-marketplace/手工安装造成的版本漂移);
3256
+ - 源解析走 _skill_template_path(): 仓库 skills/ 优先, 安装态回退包内 templates。
3257
+ 返回 per-agent 结果: {"agent", "ok", "path", "synced"/"reason"/"warnings"}。
3258
+ """
3259
+ results: List[Dict[str, Any]] = []
3260
+ for label, install_dir, skills_rel in SKILL_SYNC_TARGETS:
3261
+ skills_dir = os.path.join(user_home, skills_rel)
3262
+ if install_dir is not None and not os.path.isdir(os.path.join(user_home, install_dir)):
3263
+ results.append({"agent": label, "ok": False, "path": skills_dir,
3264
+ "reason": "not_installed"})
3265
+ continue
3266
+ synced: List[str] = []
3267
+ warnings: List[str] = []
3268
+ for sk in GLOBAL_SKILL_NAMES:
3269
+ sk_src = _skill_template_path(sk)
3270
+ if not sk_src:
3271
+ warnings.append(f"{sk}: 源缺失 (仓库 skills/ 与包内 templates/ 均未找到)")
3272
+ continue
3273
+ try:
3274
+ target = os.path.join(skills_dir, sk)
3275
+ os.makedirs(target, exist_ok=True)
3276
+ shutil.copyfile(sk_src, os.path.join(target, "SKILL.md"))
3277
+ synced.append(sk)
3278
+ except OSError as exc:
3279
+ warnings.append(f"{sk}: {exc}")
3280
+ entry: Dict[str, Any] = {"agent": label, "ok": bool(synced),
3281
+ "path": skills_dir, "synced": synced}
3282
+ if warnings:
3283
+ entry["warnings"] = warnings
3284
+ results.append(entry)
3285
+ return results
3286
+
3287
+
3227
3288
  DSH_MCP_CLIENT_PLUGIN = "@deepseek-ai/dsh-mcp-client"
3228
3289
 
3229
3290
  # DSH (DeepSeek Harness) profile patch entries. Tools surface as
@@ -3498,7 +3559,7 @@ def set_ndtdbg_dlldir(dll_path: str) -> str:
3498
3559
  def handle_cli_setup() -> int:
3499
3560
  """Handle `firmwareloop setup` command: simultaneously configure Antigravity CLI, Claude Code CLI, Qoder IDE, CodeBuddy IDE, DeepSeek Harness (DSH), and ZCode IDE."""
3500
3561
  print("============================================================")
3501
- print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.11.1)")
3562
+ print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.11.2)")
3502
3563
  print("============================================================")
3503
3564
  print("")
3504
3565
 
@@ -3612,30 +3673,19 @@ def handle_cli_setup() -> int:
3612
3673
  else:
3613
3674
  print(f" - User MCP: [Warning] Could not write {zc_result['path']}: {zc_result.get('reason')}")
3614
3675
 
3615
- # 7. Global Skills Sync for Antigravity and Claude Code
3616
- # 源解析 (v0.9.2): 源码仓库 skills/<name>/SKILL.md 优先, 安装态回退包内
3617
- # tools/templates/skill-<name>.md (skills/ 不随 wheel 分发, 此前安装态静默 0 同步)。
3676
+ # 7. Global Skills Sync — 目标表驱动 (SKILL_SYNC_TARGETS), 与 MCP 注册面全量对齐
3677
+ # (外加 .agents 跨 Agent 通用约定); 探测式 (agent 主目录存在才写, not_installed
3678
+ # 跳过)。源解析 (v0.9.2): 仓库 skills/<name>/SKILL.md 优先, 安装态回退包内
3679
+ # tools/templates/skill-<name>.md (skills/ 不随 wheel 分发)。
3618
3680
  print(f"\n[7] Global Skills:")
3619
- ag_skills_dir = os.path.join(user_home, ".gemini", "antigravity-cli", "skills")
3620
- claude_skills_dir = os.path.join(user_home, ".claude", "skills")
3621
- skills_synced = 0
3622
- for sk in ["firmwareloop", "fwloop-adapter"]:
3623
- sk_src = _skill_template_path(sk)
3624
- if not sk_src:
3625
- print(f" - {sk}: [Warning] skill 源缺失 (仓库 skills/ 与包内 templates/ 均未找到)")
3626
- continue
3627
- try:
3628
- ag_target = os.path.join(ag_skills_dir, sk)
3629
- os.makedirs(ag_target, exist_ok=True)
3630
- shutil.copyfile(sk_src, os.path.join(ag_target, "SKILL.md"))
3631
-
3632
- cl_target = os.path.join(claude_skills_dir, sk)
3633
- os.makedirs(cl_target, exist_ok=True)
3634
- shutil.copyfile(sk_src, os.path.join(cl_target, "SKILL.md"))
3635
- skills_synced += 1
3636
- except Exception as exc: # noqa: BLE001
3637
- print(f" - {sk}: [Warning] {exc}")
3638
- print(f" - Synchronized: [OK] {skills_synced} skills (firmwareloop, fwloop-adapter) to Antigravity & Claude Code")
3681
+ for item in sync_global_skills(user_home):
3682
+ if item["ok"]:
3683
+ print(f" - {item['agent']}: [OK] {', '.join(item['synced'])} -> {item['path']}")
3684
+ elif item.get("reason") == "not_installed":
3685
+ print(f" - {item['agent']}: agent 主目录不存在, 跳过 (not_installed)")
3686
+ else:
3687
+ for warn in item.get("warnings") or [item.get("reason") or "unknown"]:
3688
+ print(f" - {item['agent']}: [Warning] {warn}")
3639
3689
 
3640
3690
  # 8. Machine-level global lab.yaml (ndtdbg config for the globally installed tool)
3641
3691
  global_cfg = ensure_global_lab_yaml()
@@ -3654,7 +3704,7 @@ def handle_cli_setup() -> int:
3654
3704
  def handle_cli_init(chip: Optional[str] = None, upgrade: bool = False) -> int:
3655
3705
  """Handle `firmwareloop init [target_chip]` command."""
3656
3706
  print("============================================================")
3657
- print(" FirmwareLoop Multi-Agent Project Initializer (v0.11.1)")
3707
+ print(" FirmwareLoop Multi-Agent Project Initializer (v0.11.2)")
3658
3708
  print("============================================================")
3659
3709
  cwd = os.getcwd()
3660
3710
  print(f"[*] Initializing multi-agent guidelines & bench config in:\n {cwd}\n")
@@ -3687,7 +3737,7 @@ def handle_cli_init(chip: Optional[str] = None, upgrade: bool = False) -> int:
3687
3737
 
3688
3738
 
3689
3739
  def print_cli_help() -> None:
3690
- print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.11.1)
3740
+ print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.11.2)
3691
3741
 
3692
3742
  Usage:
3693
3743
  fwloop [command] (or: firmwareloop [command])
@@ -3737,7 +3787,7 @@ def main() -> None:
3737
3787
  elif cmd in ["describe", "contract", "tools"]:
3738
3788
  sys.exit(handle_cli_describe(args[1] if len(args) > 1 else None))
3739
3789
  elif cmd in ["version", "-v", "--version"]:
3740
- print("FirmwareLoop v0.11.1")
3790
+ print("FirmwareLoop v0.11.2")
3741
3791
  sys.exit(0)
3742
3792
  elif cmd in ["help", "-h", "--help"]:
3743
3793
  print_cli_help()
@@ -0,0 +1,44 @@
1
+ # 离线交付包安装器(NSIS 源码)
2
+
3
+ 这份目录收纳 `Fwloop_setup_pack` 一键安装器的 **NSIS 源码**(此前只存在于构建机的临时目录,
4
+ 丢失后无法重编 —— 2026-09-14 收纳入库)。
5
+
6
+ | 文件 | 产物 | 用途 |
7
+ | :--- | :--- | :--- |
8
+ | `deploy_setup.nsi` | `Fwloop_setup_pack\fwloop-deploy-setup.exe` | 一键部署:fwloop 离线安装 + Agent 注册 + NdtBox 配置 + Saleae 固件 + sigrok-cli |
9
+ | `install_firmware.nsi` | `Fwloop_setup_pack\assets\saleae-logic16-firmware-setup.exe` | Saleae Logic16 固件落位 `%LOCALAPPDATA%\sigrok-firmware`(支持 `/S`) |
10
+
11
+ ## 什么时候需要重编译
12
+
13
+ **只需要同步 firmwareloop 版本时 —— 不需要**。安装器**不内嵌** wheels/python:它在目标机上从
14
+ `$EXEDIR\assets\wheels` 离线安装(`uv tool install --find-links "$EXEDIR\assets\wheels" --offline ...`)。
15
+ 同步固件包版本的步骤:
16
+
17
+ 1. `uv build` 生成新 wheel;
18
+ 2. 用新 wheel 替换 `Fwloop_setup_pack\assets\wheels\firmwareloop-<旧>.whl`(依赖 wheel 不变则不动);
19
+ 3. 更新 `Fwloop_setup_pack\README.md` 里的版本引用;
20
+ 4. 离线冒烟:`uv pip install --offline --find-links Fwloop_setup_pack\assets\wheels "firmwareloop==<新版本>"`
21
+ (装进临时 venv,验证 `fwloop --version`)。
22
+
23
+ **改了安装器逻辑 / 升级内嵌 uv.exe 时 —— 需要**(见下)。
24
+
25
+ ## 如何编译
26
+
27
+ 1. 工具链:NSIS 3.08(https://nsis.sourceforge.io/download/ ,本机历史构建放在 `.tmp\nsis-build\nsis-3.08\`,
28
+ 该目录易失,丢了重新下载解压即可)。
29
+ 2. 在**含 nsis-3.08 的目录**下执行(nsi 里的 `OutFile` 与资源相对路径按当时布局写死):
30
+
31
+ ```powershell
32
+ cd <含 nsis-3.08 的目录> # 例: .tmp\nsis-build
33
+ .\nsis-3.08\makensis.exe deploy_setup.nsi
34
+ ```
35
+
36
+ 3. `deploy_setup.nsi` 的 `OutFile` 是**绝对路径**(指向 `Fwloop_setup_pack\fwloop-deploy-setup.exe`),
37
+ 换机器/换布局时先改这一行;资源引用形如 `..\..\Fwloop_setup_pack\assets\uv\uv.exe`(内嵌的只有 uv.exe)。
38
+
39
+ ## 交付包同步清单(每次发版)
40
+
41
+ 1. `uv build` + 替换 `assets\wheels\firmwareloop-*.whl`;
42
+ 2. 更新 `Fwloop_setup_pack\README.md` 的版本引用(`版本要求` / `wheels` 描述 / `fwloop version` 注释);
43
+ 3. 离线冒烟(上面的第 4 步);
44
+ 4. **不必**重编译 `fwloop-deploy-setup.exe`(除非改了安装器逻辑)。
@@ -1123,6 +1123,17 @@ def pid_alive(pid: int | None) -> bool:
1123
1123
  out = subprocess.run(["tasklist", "/FI", f"PID eq {int(pid)}", "/NH"],
1124
1124
  capture_output=True, text=True, timeout=10)
1125
1125
  return str(int(pid)) in (out.stdout or "")
1126
+ # POSIX: 已退出但未被父进程收割的僵尸进程, os.kill(pid, 0) 依然报存活
1127
+ # -> wait_pid_exit 永远超时 (CI Linux 实测)。/proc 可读时以进程状态为准。
1128
+ stat_path = f"/proc/{int(pid)}/stat"
1129
+ if os.path.exists(stat_path):
1130
+ try:
1131
+ with open(stat_path, encoding="utf-8") as fh:
1132
+ state = fh.read().rsplit(")", 1)[-1].strip()[:1]
1133
+ if state:
1134
+ return state != "Z"
1135
+ except OSError:
1136
+ pass # /proc 读失败 (非 Linux) -> 回退 os.kill 探测
1126
1137
  os.kill(int(pid), 0)
1127
1138
  return True
1128
1139
  except Exception: # noqa: BLE001
@@ -67,11 +67,11 @@ if ($Backend -eq 'sigrok') {
67
67
  # ---- output layout ------------------------------------------------------------
68
68
  $stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
69
69
  $runId = Get-FwRunId
70
- if (-not $OutDir) { $OutDir = Join-Path $repoRoot "artifacts\captures\$runId" }
70
+ if (-not $OutDir) { $OutDir = Join-Path (Join-Path (Join-Path $repoRoot 'artifacts') 'captures') $runId }
71
71
  New-Item -ItemType Directory -Force -Path $OutDir | Out-Null
72
72
 
73
73
  # decoder config snapshot (read from lab/protocol-decode.yaml if present)
74
- $decodeCfg = Join-Path $repoRoot 'lab\protocol-decode.yaml'
74
+ $decodeCfg = Join-Path (Join-Path $repoRoot 'lab') 'protocol-decode.yaml'
75
75
  $configOut = Join-Path $OutDir 'decoder-config.yaml'
76
76
  if (Test-Path -LiteralPath $decodeCfg) {
77
77
  Copy-Item -LiteralPath $decodeCfg -Destination $configOut -Force
@@ -265,8 +265,8 @@ else {
265
265
  if ($deriveRes.exit_code -ne 0 -or -not (Test-Path -LiteralPath $rawSigrok)) {
266
266
  Exit-WithError -Class 'LOGIC_CAPTURE_ERROR' -Message 'sigrok-cli CSV export from capture.sr failed.' -Detail ($deriveRes.stdout + $deriveRes.stderr)
267
267
  }
268
- $convScript = Join-Path $repoRoot 'tools\sigrok_csv_to_fwloop.py'
269
- $py = Resolve-FwPython
268
+ $convScript = Join-Path (Join-Path $repoRoot 'tools') 'sigrok_csv_to_fwloop.py'
269
+ $py = Resolve-FwPython -RepoRoot $repoRoot
270
270
  $convRes = Invoke-FwProcess -FilePath $py -Arguments @($convScript, $rawSigrok, $rawFile, $SampleRateHz) `
271
271
  -WorkingDirectory $repoRoot -TimeoutMs 120000
272
272
  if ($convRes.exit_code -ne 0 -or -not (Test-Path -LiteralPath $rawFile)) {
@@ -281,12 +281,12 @@ else {
281
281
  # ---- 摘要: 实际时长/截断 + 每通道活动 + 接线判定 (v0.9.2) ------------------------
282
282
  $summary = $null
283
283
  $summaryPath = Join-Path $OutDir 'capture-summary.json'
284
- $sumScript = Join-Path $repoRoot 'tools\logic_capture_summary.py'
285
- $sumPy = Resolve-FwPython
284
+ $sumScript = Join-Path (Join-Path $repoRoot 'tools') 'logic_capture_summary.py'
285
+ $sumPy = Resolve-FwPython -RepoRoot $repoRoot
286
286
  if ((Test-Path -LiteralPath $sumScript) -and $sumPy) {
287
287
  $sumArgs = @($sumScript, $rawFile, '--protocol', $Protocol, '--out', $summaryPath)
288
288
  if ($Backend -eq 'sigrok') { $sumArgs += @('--requested-s', "$DurationSec") }
289
- $cfgPath = Join-Path $repoRoot 'lab\protocol-decode.yaml'
289
+ $cfgPath = Join-Path (Join-Path $repoRoot 'lab') 'protocol-decode.yaml'
290
290
  if (Test-Path -LiteralPath $cfgPath) { $sumArgs += @('--config', $cfgPath) }
291
291
  $sumRes = Invoke-FwProcess -FilePath $sumPy -Arguments $sumArgs -WorkingDirectory $repoRoot -TimeoutMs 60000
292
292
  if ($sumRes.exit_code -eq 0) {
@@ -96,7 +96,9 @@ if (-not (Test-Path -LiteralPath $rawFile)) {
96
96
 
97
97
  # ---- protocol/config resolution ------------------------------------------------
98
98
  $cfg = @{}
99
- $cfgPath = Join-Path $repoRoot 'lab\protocol-decode.yaml'
99
+ # 跨平台注意: 子路径分段 Join-Path (字面量 'lab\protocol-decode.yaml' 在 Linux pwsh
100
+ # 会变成文件名含反斜杠的单段路径, Test-Path 恒 False -> 通道映射静默回落 builtin-default)
101
+ $cfgPath = Join-Path (Join-Path $repoRoot 'lab') 'protocol-decode.yaml'
100
102
  # YAML is not natively parseable in PowerShell; the venv python + PyYAML does it.
101
103
  if ($meta -and $meta.protocol) { $reqProtocol = [string]$meta.protocol } else { $reqProtocol = $null }
102
104
  if ($Protocol) { $reqProtocol = $Protocol }
@@ -110,7 +112,8 @@ $signalMap = [ordered]@{}
110
112
  $channelMapSource = 'builtin-default'
111
113
  $cfgBaud = 0
112
114
  if (Test-Path -LiteralPath $cfgPath) {
113
- $pyCfg = Resolve-FwPython
115
+ # -RepoRoot 必传: 裸调用只找 PATH python, CI 上是没装 pyyaml 的系统解释器 -> 解析失败
116
+ $pyCfg = Resolve-FwPython -RepoRoot $repoRoot
114
117
  if ($pyCfg) {
115
118
  $pyScript = "import json,sys;sys.stdout.reconfigure(encoding='utf-8',errors='replace');" +
116
119
  "import yaml;d=(yaml.safe_load(open(sys.argv[1],encoding='utf-8')) or {});" +
@@ -1,6 +1,6 @@
1
1
  <#
2
2
  .SYNOPSIS
3
- Dual-Tier MCP setup and registration helper (v0.11.1).
3
+ Dual-Tier MCP setup and registration helper (v0.11.2).
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.11.1)" -ForegroundColor Green
245
+ Write-Host " FirmwareLoop Dual-Tier MCP & Agent Setup Helper (v0.11.2)" -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