@yemi33/minions 0.1.519 → 0.1.521

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,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.521 (2026-04-07)
4
+
5
+ ### Features
6
+ - test isolation — tests no longer pollute production data
7
+
8
+ ### Other
9
+ - perf: reduce curl timeout to 5s, cache getDispatch() reads
10
+
3
11
  ## 0.1.519 (2026-04-07)
4
12
 
5
13
  ### Other
package/engine/ado.js CHANGED
@@ -495,7 +495,7 @@ function checkLiveReviewStatus(pr, project) {
495
495
  const orgBase = shared.getAdoOrgBase(project);
496
496
  const prNum = (pr.id || '').replace(/^PR-/, '');
497
497
  const url = `${orgBase}/${project.adoProject}/_apis/git/repositories/${project.repositoryId}/pullrequests/${prNum}?api-version=7.1`;
498
- const result = exec(`curl -s -H "Authorization: Bearer ${token}" "${url}"`, { encoding: 'utf-8', timeout: 15000, windowsHide: true });
498
+ const result = exec(`curl -s --max-time 4 -H "Authorization: Bearer ${token}" "${url}"`, { encoding: 'utf-8', timeout: 5000, windowsHide: true });
499
499
  const prData = JSON.parse(result);
500
500
  const votes = (prData.reviewers || []).map(r => r.vote).filter(v => v !== undefined);
501
501
  if (votes.length === 0) return 'pending';
@@ -24,12 +24,15 @@ function lifecycle() { if (!_lifecycle) _lifecycle = require('./lifecycle'); ret
24
24
 
25
25
  function mutateDispatch(mutator) {
26
26
  const defaultDispatch = { pending: [], active: [], completed: [] };
27
- return mutateJsonFileLocked(DISPATCH_PATH, (dispatch) => {
27
+ const result = mutateJsonFileLocked(DISPATCH_PATH, (dispatch) => {
28
28
  dispatch.pending = Array.isArray(dispatch.pending) ? dispatch.pending : [];
29
29
  dispatch.active = Array.isArray(dispatch.active) ? dispatch.active : [];
30
30
  dispatch.completed = Array.isArray(dispatch.completed) ? dispatch.completed : [];
31
31
  return mutator(dispatch) || dispatch;
32
32
  }, { defaultValue: defaultDispatch });
33
+ // Invalidate the read cache so next getDispatch() sees fresh data
34
+ try { require('./queries').invalidateDispatchCache(); } catch {}
35
+ return result;
33
36
  }
34
37
 
35
38
  // ─── Add to Dispatch ─────────────────────────────────────────────────────────
@@ -1012,6 +1012,7 @@ function createReviewFeedbackForAuthor(reviewerAgentId, pr, config) {
1012
1012
  }
1013
1013
 
1014
1014
  function updateMetrics(agentId, dispatchItem, result, taskUsage, prsCreatedCount, model) {
1015
+ if (!agentId || agentId.startsWith('temp-') || agentId === 'agent1' || agentId === 'reviewer' || agentId.startsWith('_test')) return;
1015
1016
 
1016
1017
  const metricsPath = path.join(ENGINE_DIR, 'metrics.json');
1017
1018
  mutateJsonFileLocked(metricsPath, metrics => {
package/engine/llm.js CHANGED
@@ -7,11 +7,12 @@ const path = require('path');
7
7
  const shared = require('./shared');
8
8
  const { safeWrite, safeUnlink, uid, runFile, cleanChildEnv, parseStreamJsonOutput, mutateJsonFileLocked } = shared;
9
9
 
10
- const MINIONS_DIR = path.resolve(__dirname, '..');
11
- const ENGINE_DIR = __dirname;
10
+ const MINIONS_DIR = shared.MINIONS_DIR;
11
+ const ENGINE_DIR = path.join(MINIONS_DIR, 'engine');
12
12
 
13
13
  function trackEngineUsage(category, usage) {
14
14
  if (!usage) return;
15
+ if (category && (category.startsWith('_test') || category.startsWith('test-'))) return;
15
16
  try {
16
17
  const metricsPath = path.join(ENGINE_DIR, 'metrics.json');
17
18
  mutateJsonFileLocked(metricsPath, (metrics) => {
package/engine/queries.js CHANGED
@@ -79,9 +79,17 @@ function getControl() {
79
79
  return safeJson(CONTROL_PATH) || { state: 'stopped', pid: null };
80
80
  }
81
81
 
82
+ let _dispatchCache = null;
83
+ let _dispatchCacheAt = 0;
82
84
  function getDispatch() {
83
- return safeJson(DISPATCH_PATH) || { pending: [], active: [], completed: [] };
85
+ // Short-lived cache dispatch.json is read 10+ times per tick but only changes on mutateDispatch
86
+ const now = Date.now();
87
+ if (_dispatchCache && (now - _dispatchCacheAt) < 2000) return _dispatchCache;
88
+ _dispatchCache = safeJson(DISPATCH_PATH) || { pending: [], active: [], completed: [] };
89
+ _dispatchCacheAt = now;
90
+ return _dispatchCache;
84
91
  }
92
+ function invalidateDispatchCache() { _dispatchCache = null; _dispatchCacheAt = 0; }
85
93
 
86
94
  function getDispatchQueue() {
87
95
  const d = getDispatch();
@@ -874,7 +882,7 @@ module.exports = {
874
882
  resetPrdInfoCache,
875
883
 
876
884
  // Core state
877
- getConfig, getControl, getDispatch, getDispatchQueue,
885
+ getConfig, getControl, getDispatch, getDispatchQueue, invalidateDispatchCache,
878
886
  getNotes, getNotesWithMeta, getEngineLog, getMetrics,
879
887
 
880
888
  // Inbox
package/engine/shared.js CHANGED
@@ -6,7 +6,7 @@
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
 
9
- const MINIONS_DIR = path.resolve(__dirname, '..');
9
+ const MINIONS_DIR = process.env.MINIONS_TEST_DIR || path.resolve(__dirname, '..');
10
10
  const PR_LINKS_PATH = path.join(MINIONS_DIR, 'engine', 'pr-links.json');
11
11
  const LOG_PATH = path.join(__dirname, 'log.json');
12
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.519",
3
+ "version": "0.1.521",
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"