@yemi33/minions 0.1.1841 → 0.1.1843

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1843 (2026-05-10)
4
+
5
+ ### Other
6
+ - refactor(test): extract test framework helpers into test/_helpers.js
7
+
8
+ ## 0.1.1842 (2026-05-10)
9
+
10
+ ### Fixes
11
+ - retry rename on Windows EPERM/EBUSY in removeProject archive
12
+
3
13
  ## 0.1.1841 (2026-05-10)
4
14
 
5
15
  ### Other
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-10T03:24:41.388Z"
4
+ "cachedAt": "2026-05-10T04:01:57.553Z"
5
5
  }
@@ -15,6 +15,23 @@ function _sameProjectName(a, b) {
15
15
  return String(a || '').toLowerCase() === String(b || '').toLowerCase();
16
16
  }
17
17
 
18
+ // Windows EPERM/EBUSY can hit fs.renameSync transiently when antivirus,
19
+ // indexer, or another scanner has the directory open. Retry with backoff
20
+ // before giving up — same pattern used by shared.safeWrite for atomic
21
+ // JSON writes (engine/shared.js:424).
22
+ function _renameWithRetry(src, dest) {
23
+ for (let attempt = 0; attempt < 5; attempt++) {
24
+ try {
25
+ fs.renameSync(src, dest);
26
+ return;
27
+ } catch (e) {
28
+ const transient = e.code === 'EPERM' || e.code === 'EBUSY' || e.code === 'ENOTEMPTY';
29
+ if (!transient || attempt === 4) throw e;
30
+ shared.sleepMs(50 * (attempt + 1)); // 50, 100, 150, 200ms
31
+ }
32
+ }
33
+ }
34
+
18
35
  function _projectRefMatches(projectRef, removedProject, projects) {
19
36
  if (!projectRef) return false;
20
37
  const refs = (projectRef && typeof projectRef === 'object')
@@ -267,9 +284,16 @@ function removeProject(target, options = {}) {
267
284
  let archived = path.join(archiveRoot, project.name + '-' + stamp);
268
285
  let n = 1;
269
286
  while (fs.existsSync(archived)) archived = path.join(archiveRoot, project.name + '-' + stamp + '-' + (++n));
270
- fs.renameSync(dataDir, archived);
287
+ _renameWithRetry(dataDir, archived);
271
288
  summary.archivedTo = path.relative(MINIONS_DIR, archived).replace(/\\/g, '/');
272
- } catch (e) { summary.warnings.push('archive data dir: ' + e.message); }
289
+ } catch (e) {
290
+ // Surface the failure: callers (CLI, dashboard, tests) need to know
291
+ // the data dir is still in place. Previously this was a silent warning
292
+ // and `archivedTo` stayed null, making flakes look like missing-set
293
+ // assertions instead of real archive failures.
294
+ summary.archiveError = e.code ? `${e.code}: ${e.message}` : e.message;
295
+ summary.warnings.push('archive data dir: ' + e.message);
296
+ }
273
297
  }
274
298
  }
275
299
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1841",
3
+ "version": "0.1.1843",
4
4
  "description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
5
5
  "bin": {
6
6
  "minions": "bin/minions.js"