@yemi33/minions 0.1.1765 → 0.1.1767

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,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1767 (2026-05-07)
4
+
5
+ ### Fixes
6
+ - stop test fixtures leaking into live engine/log.json (#2154)
7
+
3
8
  ## 0.1.1765 (2026-05-07)
4
9
 
5
10
  ### Features
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-07T03:29:49.996Z"
4
+ "cachedAt": "2026-05-07T15:01:54.451Z"
5
5
  }
package/engine/shared.js CHANGED
@@ -168,12 +168,26 @@ function log(level, msg, meta = {}) {
168
168
  * That leaked test pollution into the live engine log (e.g. `_test/backoff-*`,
169
169
  * `this-playbook-does-not-exist-xyz`, `TEST-EXT-*` meeting IDs).
170
170
  *
171
- * Lazy resolution honors the *current* `MINIONS_TEST_DIR` at flush time, so
172
- * even unbussed dependents write to the test dir while the test owns it.
171
+ * Resolution order:
172
+ * 1. `MINIONS_TEST_DIR` per-test isolation root (regression tests rely
173
+ * on this — log goes to `<tmpdir>/engine/log.json`).
174
+ * 2. `MINIONS_LOG_PATH` — default test log target. Set at the top of
175
+ * `test/unit.test.js` so tests that exercise log() without explicit
176
+ * isolation (e.g. github backoff helpers, cooldown helpers) still land
177
+ * in a benign tmp file instead of the live `D:/squad/engine/log.json`.
178
+ * 3. `MINIONS_HOME` / repo root fallback — production behavior.
179
+ *
180
+ * Lazy resolution honors the *current* env at flush time, so even unbussed
181
+ * dependents write to the test dir while the test owns it.
173
182
  */
174
183
  function _currentLogPath() {
175
- const root = process.env.MINIONS_TEST_DIR
176
- || (process.env.MINIONS_HOME ? path.resolve(process.env.MINIONS_HOME) : path.resolve(__dirname, '..'));
184
+ if (process.env.MINIONS_TEST_DIR) {
185
+ return path.join(path.resolve(process.env.MINIONS_TEST_DIR), 'engine', 'log.json');
186
+ }
187
+ if (process.env.MINIONS_LOG_PATH) {
188
+ return path.resolve(process.env.MINIONS_LOG_PATH);
189
+ }
190
+ const root = process.env.MINIONS_HOME ? path.resolve(process.env.MINIONS_HOME) : path.resolve(__dirname, '..');
177
191
  return path.join(root, 'engine', 'log.json');
178
192
  }
179
193
 
package/engine.js CHANGED
@@ -431,6 +431,45 @@ function resolveDependencyBranches(depIds, sourcePlan, project, config) {
431
431
  return results;
432
432
  }
433
433
 
434
+ /**
435
+ * Sync an existing worktree from origin on reuse: probe with
436
+ * `git ls-remote --exit-code --heads origin <branch>` first so that locally
437
+ * created branches whose first attempt died before push (agent timeout / orphan
438
+ * retry) skip fetch+pull silently instead of emitting a warn-level
439
+ * "couldn't find remote ref" pair on every reuse.
440
+ *
441
+ * Genuine fetch/pull failures (network, auth, conflict) still surface as warn.
442
+ * Never throws — the dispatch must continue regardless of sync outcome.
443
+ *
444
+ * Exported for testing; production callers ignore the return value.
445
+ *
446
+ * @returns {Promise<{skipped: boolean, reason?: string}>}
447
+ */
448
+ async function syncReusedWorktree(rootDir, worktreePath, branchName, gitOpts = {}) {
449
+ // ls-remote --exit-code returns 2 when no matching refs are found on the
450
+ // remote. The probe only lists refs (no object transfer), so it's cheap
451
+ // even on slow links.
452
+ let onOrigin = true;
453
+ try {
454
+ await execAsync(
455
+ `git ls-remote --exit-code --heads origin "${branchName}"`,
456
+ { ...gitOpts, cwd: rootDir, timeout: 5000 },
457
+ );
458
+ } catch (e) {
459
+ // Exit code 2 = ref not on remote (the noisy case we want to silence).
460
+ // Any other failure (network, auth, timeout) we let pass through so the
461
+ // subsequent fetch surfaces a real warn with its native error message.
462
+ if (e && e.code === 2) onOrigin = false;
463
+ }
464
+ if (!onOrigin) {
465
+ log('info', `Branch ${branchName} not on origin yet — first push pending; skipping fetch/pull`);
466
+ return { skipped: true, reason: 'no-upstream' };
467
+ }
468
+ try { await execAsync(`git fetch origin "${branchName}"`, { ...gitOpts, cwd: rootDir }); } catch (e) { log('warn', 'git: ' + e.message); }
469
+ try { await execAsync(`git pull origin "${branchName}"`, { ...gitOpts, cwd: worktreePath }); } catch (e) { log('warn', 'git: ' + e.message); }
470
+ return { skipped: false };
471
+ }
472
+
434
473
  // Find an existing worktree already checked out on a given branch
435
474
  async function findExistingWorktree(repoDir, branchName) {
436
475
  try {
@@ -592,8 +631,10 @@ async function spawnAgent(dispatchItem, config) {
592
631
  if (existingWt) {
593
632
  worktreePath = existingWt;
594
633
  log('info', `Reusing existing worktree for ${branchName}: ${existingWt}`);
595
- try { await execAsync(`git fetch origin "${branchName}"`, { ..._gitOpts, cwd: rootDir }); } catch (e) { log('warn', 'git: ' + e.message); }
596
- try { await execAsync(`git pull origin "${branchName}"`, { ..._gitOpts, cwd: existingWt }); } catch (e) { log('warn', 'git: ' + e.message); }
634
+ // Probe origin first locally-created branches that were never pushed
635
+ // (orphan/timeout retry before first push) would otherwise emit a
636
+ // "couldn't find remote ref" warn pair on every reuse.
637
+ await syncReusedWorktree(rootDir, existingWt, branchName, _gitOpts);
597
638
  } else if (['meeting', 'ask', 'explore', 'plan-to-prd', 'plan'].includes(type)) {
598
639
  // Read-only tasks — no worktree needed, run in rootDir
599
640
  log('info', `${type}: read-only task, no worktree needed — running in rootDir`);
@@ -4666,7 +4707,7 @@ module.exports = {
4666
4707
  // Shared helpers (used by lifecycle.js and tests)
4667
4708
  reconcileItemsWithPrs, detectDependencyCycles,
4668
4709
  parseConflictFiles, pruneAncestorDeps, preflightMergeSimulation, // exported for testing
4669
- isWorktreeRetryableError, removeStaleIndexLock, // exported for testing
4710
+ isWorktreeRetryableError, removeStaleIndexLock, syncReusedWorktree, // exported for testing
4670
4711
  _maxTurnsForType, buildProjectContext, normalizeAc, _buildAgentSpawnFlags, _classifyAgentFailure, // exported for testing
4671
4712
 
4672
4713
  // Playbooks
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1765",
3
+ "version": "0.1.1767",
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"