@yemi33/minions 0.1.1824 → 0.1.1825

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.1825 (2026-05-09)
4
+
5
+ ### Fixes
6
+ - isolate test artifacts under MINIONS_TEST_DIR + dashboard TEST badge
7
+
3
8
  ## 0.1.1824 (2026-05-09)
4
9
 
5
10
  ### Other
@@ -516,6 +516,12 @@
516
516
  .engine-badge.running { background: rgba(63,185,80,0.15); color: var(--green); border: 1px solid var(--green); }
517
517
  .engine-badge.paused { background: rgba(210,153,34,0.15); color: var(--yellow); border: 1px solid var(--yellow); }
518
518
  .engine-badge.stopped { background: rgba(248,81,73,0.15); color: var(--red); border: 1px solid var(--red); }
519
+ .test-mode-badge {
520
+ display: inline-block; margin-left: var(--space-6); padding: var(--space-1) var(--space-5);
521
+ background: var(--orange); color: #1a1a1a; font-size: var(--text-md); font-weight: 700;
522
+ letter-spacing: 0.5px; border-radius: var(--radius-sm); vertical-align: middle;
523
+ }
524
+ body.minions-test-mode > header { box-shadow: inset 0 -3px 0 var(--orange); }
519
525
  .engine-alert {
520
526
  display: none; margin: 8px 24px 0; padding: 8px 10px; border: 1px solid rgba(248,81,73,0.45);
521
527
  background: rgba(248,81,73,0.1); border-radius: var(--radius-sm); font-size: 11px; color: var(--text);
package/dashboard.js CHANGED
@@ -805,9 +805,25 @@ function resolvePlanPath(file) {
805
805
  return active;
806
806
  }
807
807
 
808
- // Assemble dashboard HTML from fragments (canonical source: dashboard/)
808
+ // Test-mode banner: surfaced in <title> + <h1> + body class when the dashboard
809
+ // is started under MINIONS_TEST_DIR or on a non-default port. Makes it visually
810
+ // obvious that the user is looking at a sandboxed instance, not their live
811
+ // fleet — prevents acting on test fixtures by mistake.
812
+ function _isTestMode() {
813
+ return !!process.env.MINIONS_TEST_DIR || (typeof PORT === 'number' && PORT !== 7331);
814
+ }
815
+
816
+ function _testBadgeLabel() {
817
+ if (process.env.MINIONS_TEST_DIR) return 'TEST';
818
+ if (typeof PORT === 'number' && PORT !== 7331) return `TEST :${PORT}`;
819
+ return '';
820
+ }
821
+
822
+ // Assemble dashboard HTML from fragments (canonical source: dashboard/).
823
+ // Resolves dashboard/ relative to __dirname (the checkout root) so test
824
+ // invocations under MINIONS_TEST_DIR still find the static layout/CSS/JS.
809
825
  function buildDashboardHtml() {
810
- const dashDir = path.join(MINIONS_DIR, 'dashboard');
826
+ const dashDir = path.join(__dirname, 'dashboard');
811
827
  const layoutPath = path.join(dashDir, 'layout.html');
812
828
 
813
829
  if (!fs.existsSync(layoutPath)) {
@@ -854,10 +870,22 @@ function buildDashboardHtml() {
854
870
 
855
871
  const featuresBootstrap = `window.MINIONS_FEATURES = ${JSON.stringify(featuresBoot)};\n`;
856
872
 
857
- return layout
873
+ let assembled = layout
858
874
  .replace('/* __CSS__ */', () => css)
859
875
  .replace('<!-- __PAGES__ -->', () => pageHtml)
860
876
  .replace('/* __JS__ */', () => `window.__MINIONS_HOME = ${JSON.stringify(os.homedir())};\n${featuresBootstrap}${jsHtml}`);
877
+
878
+ if (_isTestMode()) {
879
+ const label = _testBadgeLabel();
880
+ assembled = assembled
881
+ .replace('<title>Minions Mission Control</title>',
882
+ `<title>[${label}] Minions Mission Control</title>`)
883
+ .replace('<h1>Minions Mission Control</h1>',
884
+ `<h1>Minions Mission Control <span class="test-mode-badge">${label}</span></h1>`)
885
+ .replace('<body>',
886
+ '<body class="minions-test-mode">');
887
+ }
888
+ return assembled;
861
889
  }
862
890
 
863
891
  let HTML_RAW = buildDashboardHtml();
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-09T18:23:44.280Z"
4
+ "cachedAt": "2026-05-09T20:04:56.707Z"
5
5
  }
@@ -28,10 +28,11 @@
28
28
  const fs = require('fs');
29
29
  const os = require('os');
30
30
  const path = require('path');
31
- const { FAILURE_CLASS, safeWrite, ts } = require('../shared');
31
+ const { FAILURE_CLASS, safeWrite, ts, resolveEngineCacheDir } = require('../shared');
32
32
 
33
33
  const ENGINE_DIR = __dirname.replace(/[\\/]runtimes$/, '');
34
34
  const MINIONS_DIR = path.resolve(ENGINE_DIR, '..');
35
+ const _CACHE_DIR = resolveEngineCacheDir(ENGINE_DIR);
35
36
 
36
37
  const isWin = process.platform === 'win32';
37
38
 
@@ -40,7 +41,7 @@ const isWin = process.platform === 'win32';
40
41
  // repeated path-probe (PATH / npm-global / npm-root-g) only happens once per
41
42
  // install.
42
43
 
43
- const CAPS_FILE = path.join(ENGINE_DIR, 'claude-caps.json');
44
+ const CAPS_FILE = path.join(_CACHE_DIR, 'claude-caps.json');
44
45
 
45
46
  function _safeJson(p) {
46
47
  try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return null; }
@@ -185,7 +186,7 @@ function listModels() {
185
186
  return null;
186
187
  }
187
188
 
188
- const MODELS_CACHE = path.join(ENGINE_DIR, 'claude-models.json');
189
+ const MODELS_CACHE = path.join(_CACHE_DIR, 'claude-models.json');
189
190
 
190
191
  // ── Argument Construction ────────────────────────────────────────────────────
191
192
 
@@ -32,9 +32,10 @@ const https = require('https');
32
32
  const os = require('os');
33
33
  const path = require('path');
34
34
  const { execSync } = require('child_process');
35
- const { FAILURE_CLASS, safeWrite, ts } = require('../shared');
35
+ const { FAILURE_CLASS, safeWrite, ts, resolveEngineCacheDir } = require('../shared');
36
36
 
37
37
  const ENGINE_DIR = __dirname.replace(/[\\/]runtimes$/, '');
38
+ const _CACHE_DIR = resolveEngineCacheDir(ENGINE_DIR);
38
39
  const isWin = process.platform === 'win32';
39
40
 
40
41
  // ── Binary Resolution ───────────────────────────────────────────────────────
@@ -51,8 +52,8 @@ const isWin = process.platform === 'win32';
51
52
  // We deliberately do NOT npm-probe — Copilot is not an npm package. Doing so
52
53
  // would be confusing dead code that suggests an install path that doesn't exist.
53
54
 
54
- const CAPS_FILE = path.join(ENGINE_DIR, 'copilot-caps.json');
55
- const MODELS_CACHE = path.join(ENGINE_DIR, 'copilot-models.json');
55
+ const CAPS_FILE = path.join(_CACHE_DIR, 'copilot-caps.json');
56
+ const MODELS_CACHE = path.join(_CACHE_DIR, 'copilot-models.json');
56
57
 
57
58
  function _safeJson(p) {
58
59
  try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return null; }
package/engine/shared.js CHANGED
@@ -240,6 +240,17 @@ function _currentLogPath() {
240
240
  return path.join(root, 'engine', 'log.json');
241
241
  }
242
242
 
243
+ // MINIONS_TEST_DIR-aware engine dir for cache files (runtime caps, models,
244
+ // spawn-debug.log). Returns `<MINIONS_TEST_DIR>/engine` under tests; otherwise
245
+ // the caller's source-adjacent fallback (typically `__dirname`-derived). Never
246
+ // consults MINIONS_HOME — tests must not leak into the install root.
247
+ function resolveEngineCacheDir(fallbackEngineDir) {
248
+ if (process.env.MINIONS_TEST_DIR) {
249
+ return path.join(path.resolve(process.env.MINIONS_TEST_DIR), 'engine');
250
+ }
251
+ return fallbackEngineDir;
252
+ }
253
+
243
254
  function _flushLogBuffer() {
244
255
  if (_logBuffer.length === 0) return;
245
256
  const drained = _logBuffer.splice(0);
@@ -3368,6 +3379,7 @@ function createThrottleTracker({ label, baseBackoffMs = 60000, maxBackoffMs = 32
3368
3379
  module.exports = {
3369
3380
  MINIONS_DIR,
3370
3381
  ENGINE_DIR,
3382
+ resolveEngineCacheDir,
3371
3383
  CONTROL_PATH,
3372
3384
  COOLDOWNS_PATH,
3373
3385
  PR_LINKS_PATH,
@@ -35,7 +35,7 @@
35
35
  const fs = require('fs');
36
36
  const os = require('os');
37
37
  const path = require('path');
38
- const { runFile, cleanChildEnv, killGracefully, killImmediate, ts } = require('./shared');
38
+ const { runFile, cleanChildEnv, killGracefully, killImmediate, ts, resolveEngineCacheDir } = require('./shared');
39
39
  const { resolveRuntime } = require('./runtimes');
40
40
  const { acquireAdoTokenSync, isLikelyAdoToken } = require('./ado-token');
41
41
 
@@ -321,8 +321,8 @@ function main() {
321
321
  opts, passthrough, addDirs,
322
322
  });
323
323
 
324
- // Debug log (async — not on critical path)
325
- const tmpDir = path.join(__dirname, 'tmp');
324
+ // Debug log (async — not on critical path).
325
+ const tmpDir = path.join(resolveEngineCacheDir(__dirname), 'tmp');
326
326
  if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir, { recursive: true });
327
327
  const debugPath = path.join(tmpDir, 'spawn-debug.log');
328
328
  fs.writeFile(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1824",
3
+ "version": "0.1.1825",
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"