From 73af90b5cc8dd49ce2b18af57aeaf0ef67558545 Mon Sep 17 00:00:00 2001 From: Raylan LIN Date: Fri, 2 Oct 2026 07:15:03 +0000 Subject: [PATCH] fix: wait for the sidecar to exit before removing its temp dir (EBUSY on the Windows build) On Windows kill() returns before the process is gone and a live process's working directory cannot be removed, so the sidecar-client test's cleanup failed with EBUSY and stopped the installer build. Wait for the exit, retry the delete, and only warn if a temp dir is left behind. App code unchanged. --- CHANGELOG.md | 11 +++++++++++ README.md | 4 ++-- README.zh-CN.md | 4 ++-- package.json | 2 +- tests/sidecar-client.test.mjs | 15 ++++++++++++++- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c69be07..ebc2e7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,17 @@ ## [Unreleased] +## [0.2.134] - 2026-10-02 + +### Fixed + +- **Windows build failed in `npm test`.** The `sidecar-client` test deleted its temp folder + right after stopping the Python sidecar. On Windows, `kill()` returns before the process + has exited, and a live process's working folder cannot be removed, so cleanup failed with + `EBUSY` and stopped the installer build. The test now waits for the process to exit. It + retries the delete, and a leftover temp folder only logs a warning. The app itself is + unchanged. + ## [0.2.133] - 2026-10-02 ### Fixed (P134 — material that never took, macros that could not fail) diff --git a/README.md b/README.md index 1d75fe7..d0f0175 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@

- version + version electron react typescript @@ -248,7 +248,7 @@ Contributions welcome — see [CONTRIBUTING.md](docs/CONTRIBUTING.md). We especi - [x] **v0.1** — MVP: Electron shell, LLM adapters, COM bridge, first tool set - [x] **v0.2** — Python sidecar, agentic tool loop, dual-engine fallback, vision feedback, confirmation cards, Apache-2.0 open source -- [x] **v0.2.4 → v0.2.133** — Extensive hardening against real SolidWorks installs ← *current*: the sketch → feature → cut → visual-verification loop now runs end to end on real hardware +- [x] **v0.2.4 → v0.2.134** — Extensive hardening against real SolidWorks installs ← *current*: the sketch → feature → cut → visual-verification loop now runs end to end on real hardware - [ ] **v0.3** — Streaming tool calls, sketching on model faces (not just reference planes), hole wizard, sheet metal, drawing annotations, remaining `#VERIFY` parameters confirmed - [ ] **v1.0** — MCP server, multi-CAD support diff --git a/README.zh-CN.md b/README.zh-CN.md index 0cfe97c..677e83f 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -27,7 +27,7 @@

- version + version electron react typescript @@ -247,7 +247,7 @@ SolidWorks - [x] **v0.1** — MVP:Electron 骨架、LLM 适配器、COM 桥接、首批工具 - [x] **v0.2** — Python 边车、agent 工具循环、双引擎降级、视觉反馈、确认卡片,Apache-2.0 开源 -- [x] **v0.2.4 → v0.2.133** — 大量真机加固 ← *当前*:草图 → 特征 → 切除 → 视觉核验的完整闭环已在真机上端到端跑通 +- [x] **v0.2.4 → v0.2.134** — 大量真机加固 ← *当前*:草图 → 特征 → 切除 → 视觉核验的完整闭环已在真机上端到端跑通 - [ ] **v0.3** — 流式工具调用、在模型面上画草图(而非仅基准面)、孔向导、钣金、工程图标注、剩余 `# VERIFY` 参数完成核验 - [ ] **v1.0** — MCP server、多 CAD 支持 diff --git a/package.json b/package.json index 5fc97d6..d9b2cc8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "millwright", - "version": "0.2.133", + "version": "0.2.134", "description": "Open-source AI automation for SolidWorks — talk to your CAD.", "keywords": [ "solidworks", diff --git a/tests/sidecar-client.test.mjs b/tests/sidecar-client.test.mjs index 28ab96a..1bcf22f 100644 --- a/tests/sidecar-client.test.mjs +++ b/tests/sidecar-client.test.mjs @@ -68,7 +68,20 @@ before(async () => { sc = new SWSidecar({ pythonPath: PY, cwd: tmp }); await sc.start(); }); -after(() => { sc?.stop(); fs.rmSync(tmp, { recursive: true, force: true }); }); +after(async () => { + const proc = sc?.proc; // private in TS, reachable from JS + sc?.stop(); + // Windows refuses to remove the working directory of a live process (EBUSY), and kill() + // returns before the process is gone: wait for the exit before cleaning up. + if (proc && proc.exitCode === null && proc.signalCode === null) { + await new Promise((r) => { proc.once('exit', r); setTimeout(r, 5000).unref(); }); + } + try { + fs.rmSync(tmp, { recursive: true, force: true, maxRetries: 10, retryDelay: 200 }); + } catch (e) { + console.warn(`# left ${tmp} behind: ${e.message}`); // a stray temp dir is not a test failure + } +}); const opts = { skip: !PY && 'python3 not available' };