monomind 1.17.0 → 1.17.2

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.
Files changed (94) hide show
  1. package/.claude/agents/engineering/engineering-security-engineer.md +1 -1
  2. package/.claude/commands/mastermind/_repeat.md +4 -0
  3. package/.claude/commands/mastermind/master.md +52 -1
  4. package/.claude/scheduled_tasks.lock +1 -1
  5. package/.claude/skills/mastermind/_repeat.md +2 -0
  6. package/package.json +1 -1
  7. package/packages/@monomind/cli/.claude/agents/engineering/engineering-security-engineer.md +1 -1
  8. package/packages/@monomind/cli/.claude/commands/mastermind/_repeat.md +4 -0
  9. package/packages/@monomind/cli/.claude/commands/mastermind/master.md +52 -1
  10. package/packages/@monomind/cli/.claude/skills/mastermind/_repeat.md +2 -0
  11. package/packages/@monomind/cli/dist/src/__tests__/browse-analyzer.test.js +42 -59
  12. package/packages/@monomind/cli/dist/src/agents/registry-builder.d.ts +8 -0
  13. package/packages/@monomind/cli/dist/src/agents/registry-builder.js +22 -0
  14. package/packages/@monomind/cli/dist/src/browser/dashboard/server.js +18 -0
  15. package/packages/@monomind/cli/dist/src/browser/dashboard/ui.html +37 -125
  16. package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.d.ts +17 -0
  17. package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.js +320 -0
  18. package/packages/@monomind/cli/dist/src/commands/agent-ops.d.ts +9 -0
  19. package/packages/@monomind/cli/dist/src/commands/agent-ops.js +329 -0
  20. package/packages/@monomind/cli/dist/src/commands/agent.js +5 -907
  21. package/packages/@monomind/cli/dist/src/commands/analyze-ast.d.ts +26 -0
  22. package/packages/@monomind/cli/dist/src/commands/analyze-ast.js +284 -0
  23. package/packages/@monomind/cli/dist/src/commands/analyze-boundaries.d.ts +14 -0
  24. package/packages/@monomind/cli/dist/src/commands/analyze-boundaries.js +295 -0
  25. package/packages/@monomind/cli/dist/src/commands/analyze-diff.d.ts +8 -0
  26. package/packages/@monomind/cli/dist/src/commands/analyze-diff.js +395 -0
  27. package/packages/@monomind/cli/dist/src/commands/analyze-graph.d.ts +14 -0
  28. package/packages/@monomind/cli/dist/src/commands/analyze-graph.js +304 -0
  29. package/packages/@monomind/cli/dist/src/commands/analyze-imports.d.ts +11 -0
  30. package/packages/@monomind/cli/dist/src/commands/analyze-imports.js +287 -0
  31. package/packages/@monomind/cli/dist/src/commands/analyze-symbols.d.ts +14 -0
  32. package/packages/@monomind/cli/dist/src/commands/analyze-symbols.js +302 -0
  33. package/packages/@monomind/cli/dist/src/commands/analyze.d.ts +38 -0
  34. package/packages/@monomind/cli/dist/src/commands/analyze.js +12 -1827
  35. package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.d.ts +26 -0
  36. package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.js +189 -0
  37. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.d.ts +20 -0
  38. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.js +432 -0
  39. package/packages/@monomind/cli/dist/src/commands/doctor.js +54 -943
  40. package/packages/@monomind/cli/dist/src/commands/hive-mind-comms.d.ts +11 -0
  41. package/packages/@monomind/cli/dist/src/commands/hive-mind-comms.js +242 -0
  42. package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.d.ts +35 -0
  43. package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.js +203 -0
  44. package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.d.ts +8 -0
  45. package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.js +233 -0
  46. package/packages/@monomind/cli/dist/src/commands/hive-mind-spawn.d.ts +12 -0
  47. package/packages/@monomind/cli/dist/src/commands/hive-mind-spawn.js +274 -0
  48. package/packages/@monomind/cli/dist/src/commands/hive-mind.js +10 -1129
  49. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.d.ts +4 -4
  50. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.js +19 -819
  51. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.d.ts +7 -0
  52. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.js +334 -0
  53. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.d.ts +7 -0
  54. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.js +399 -0
  55. package/packages/@monomind/cli/dist/src/commands/init-subcommands.d.ts +8 -0
  56. package/packages/@monomind/cli/dist/src/commands/init-subcommands.js +156 -0
  57. package/packages/@monomind/cli/dist/src/commands/init-upgrade.d.ts +6 -0
  58. package/packages/@monomind/cli/dist/src/commands/init-upgrade.js +203 -0
  59. package/packages/@monomind/cli/dist/src/commands/init-wizard.d.ts +6 -0
  60. package/packages/@monomind/cli/dist/src/commands/init-wizard.js +246 -0
  61. package/packages/@monomind/cli/dist/src/commands/init.js +6 -623
  62. package/packages/@monomind/cli/dist/src/commands/memory-admin.d.ts +10 -0
  63. package/packages/@monomind/cli/dist/src/commands/memory-admin.js +433 -0
  64. package/packages/@monomind/cli/dist/src/commands/memory-crud.d.ts +9 -0
  65. package/packages/@monomind/cli/dist/src/commands/memory-crud.js +342 -0
  66. package/packages/@monomind/cli/dist/src/commands/memory-list.d.ts +10 -0
  67. package/packages/@monomind/cli/dist/src/commands/memory-list.js +321 -0
  68. package/packages/@monomind/cli/dist/src/commands/memory-transfer.d.ts +9 -0
  69. package/packages/@monomind/cli/dist/src/commands/memory-transfer.js +372 -0
  70. package/packages/@monomind/cli/dist/src/commands/memory.d.ts +6 -0
  71. package/packages/@monomind/cli/dist/src/commands/memory.js +10 -1441
  72. package/packages/@monomind/cli/dist/src/commands/neural-core.d.ts +8 -0
  73. package/packages/@monomind/cli/dist/src/commands/neural-core.js +274 -0
  74. package/packages/@monomind/cli/dist/src/commands/neural-optimize.d.ts +7 -0
  75. package/packages/@monomind/cli/dist/src/commands/neural-optimize.js +332 -0
  76. package/packages/@monomind/cli/dist/src/commands/neural-registry.d.ts +7 -0
  77. package/packages/@monomind/cli/dist/src/commands/neural-registry.js +290 -0
  78. package/packages/@monomind/cli/dist/src/commands/neural.js +3 -974
  79. package/packages/@monomind/cli/dist/src/commands/platforms.js +327 -7
  80. package/packages/@monomind/cli/dist/src/commands/security-cve.d.ts +6 -0
  81. package/packages/@monomind/cli/dist/src/commands/security-cve.js +310 -0
  82. package/packages/@monomind/cli/dist/src/commands/security-misc.d.ts +9 -0
  83. package/packages/@monomind/cli/dist/src/commands/security-misc.js +293 -0
  84. package/packages/@monomind/cli/dist/src/commands/security-scan.d.ts +18 -0
  85. package/packages/@monomind/cli/dist/src/commands/security-scan.js +328 -0
  86. package/packages/@monomind/cli/dist/src/commands/security.js +3 -958
  87. package/packages/@monomind/cli/dist/src/commands/session.js +1 -1
  88. package/packages/@monomind/cli/dist/src/commands/swarm.js +23 -17
  89. package/packages/@monomind/cli/dist/src/index.js +8 -37
  90. package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +77 -0
  91. package/packages/@monomind/cli/dist/src/parser.js +11 -6
  92. package/packages/@monomind/cli/dist/src/routing/llm-caller.js +1 -2
  93. package/packages/@monomind/cli/package.json +2 -3
  94. package/packages/@monomind/cli/scripts/understand-analyze.mjs +1 -1
@@ -572,7 +572,7 @@ const importCommand = {
572
572
  : path.join(ctx.cwd, filePath);
573
573
  // Path traversal protection: resolved path must stay within cwd or home
574
574
  const resolvedPath = path.resolve(absolutePath);
575
- const cwd = process.cwd();
575
+ const cwd = ctx.cwd || process.cwd();
576
576
  const home = process.env.HOME || '';
577
577
  const underCwd = resolvedPath === cwd || resolvedPath.startsWith(cwd + path.sep);
578
578
  const underHome = home && (resolvedPath === home || resolvedPath.startsWith(home + path.sep));
@@ -635,30 +635,36 @@ const scaleCommand = {
635
635
  output.printError('Swarm ID is required');
636
636
  return { success: false, exitCode: 1 };
637
637
  }
638
- if (!targetAgents) {
638
+ // 0 is a valid target (scale a swarm down to no agents) — check for
639
+ // presence, not truthiness.
640
+ if (targetAgents === undefined || Number.isNaN(targetAgents)) {
639
641
  output.printError('Target agent count required. Use --agents or -a');
640
642
  return { success: false, exitCode: 1 };
641
643
  }
642
644
  output.printInfo(`Scaling swarm ${swarmId} to ${targetAgents} agents...`);
643
- // Calculate scaling delta — fetch actual count instead of hardcoded 8 (#1425)
644
- let currentAgents = 0;
645
645
  try {
646
- const statusResult = await callMCPTool('swarm_status', { swarmId });
647
- const statusData = typeof statusResult === 'string' ? JSON.parse(statusResult) : statusResult;
648
- currentAgents = statusData?.agentCount ?? statusData?.agents?.length ?? 0;
649
- }
650
- catch {
651
- // If MCP unavailable, fall back to 0 (will spawn all requested agents)
652
- currentAgents = 0;
646
+ const result = await callMCPTool('swarm_scale', { swarmId, targetAgents, agentType });
647
+ if (!result.success) {
648
+ output.printError(result.error || 'Failed to scale swarm');
649
+ return { success: false, exitCode: 1 };
650
+ }
651
+ if (result.spawned.length === 0 && result.terminated.length === 0) {
652
+ output.printInfo('Swarm already at target size');
653
+ return { success: true, data: result };
654
+ }
655
+ if (result.spawned.length > 0) {
656
+ output.printSuccess(`Spawned ${result.spawned.length} agent(s): ${result.spawned.join(', ')}`);
657
+ }
658
+ if (result.terminated.length > 0) {
659
+ output.printSuccess(`Terminated ${result.terminated.length} agent(s): ${result.terminated.join(', ')}`);
660
+ }
661
+ output.writeln(output.dim(` ${result.previousCount} → ${result.currentCount} agents`));
662
+ return { success: true, data: result };
653
663
  }
654
- const delta = targetAgents - currentAgents;
655
- if (delta === 0) {
656
- output.printInfo('Swarm already at target size');
657
- return { success: true };
664
+ catch (error) {
665
+ output.printError(`Scale error: ${error instanceof MCPClientError ? error.message : String(error)}`);
666
+ return { success: false, exitCode: 1 };
658
667
  }
659
- // No swarm_scale MCP tool is available — report the computed delta but do not pretend to act
660
- output.printWarning('Swarm scaling is not yet implemented. The target count was computed but no agents were spawned or stopped.');
661
- return { success: false, message: 'Scaling not implemented', exitCode: 1 };
662
668
  }
663
669
  };
664
670
  // Coordinate command (v1 specific)
@@ -439,50 +439,21 @@ export class CLI {
439
439
  // Extra paths are read from MONOMIND_EXTRA_AGENT_PATHS env var (colon-separated)
440
440
  // or fall back to the known local path when available.
441
441
  try {
442
- const { buildUnifiedRegistry } = await import('./agents/registry-builder.js');
442
+ const { buildUnifiedRegistry, computeAgentRoots } = await import('./agents/registry-builder.js');
443
443
  const { mkdirSync } = await import('fs');
444
444
  const { join } = await import('path');
445
- const devAgentsRoot = join(process.cwd(), '.claude', 'agents');
446
- const extraPaths = process.env.MONOMIND_EXTRA_AGENT_PATHS
447
- ? process.env.MONOMIND_EXTRA_AGENT_PATHS.split(':').filter(Boolean)
448
- : [];
449
- // Fallback: well-known sibling path relative to project root (no hardcoded dev paths)
450
- const { existsSync } = await import('fs');
451
- const siblingExtraPath = join(process.cwd(), '..', 'agency-agents');
452
- if (extraPaths.length === 0 && existsSync(siblingExtraPath)) {
453
- extraPaths.push(siblingExtraPath);
454
- }
455
- // extras-first so they win deduplication; dev agents fill in the rest
456
- const roots = [...extraPaths, devAgentsRoot];
445
+ const roots = computeAgentRoots(process.cwd());
457
446
  const outDir = join(process.cwd(), '.monomind');
458
447
  mkdirSync(outDir, { recursive: true });
459
448
  buildUnifiedRegistry(roots, join(outDir, 'registry.json'));
460
449
  }
461
450
  catch { /* optional — registry build failures must never block startup */ }
462
- // Task 04: CapabilityMetadata validate agent registry at startup
463
- try {
464
- const { readFileSync, existsSync, statSync: statSyncReg } = await import('fs');
465
- const { join: pathJoin } = await import('path');
466
- const registryPath = pathJoin(process.cwd(), '.monomind', 'registry.json');
467
- const MAX_REGISTRY_BYTES = 10 * 1024 * 1024; // 10 MB
468
- if (existsSync(registryPath) && statSyncReg(registryPath).size <= MAX_REGISTRY_BYTES) {
469
- const registry = JSON.parse(readFileSync(registryPath, 'utf-8'));
470
- const entries = registry.agents ?? [];
471
- const issues = [];
472
- for (const agent of entries) {
473
- if (!agent.slug)
474
- issues.push(`Agent missing 'slug'`);
475
- if (!agent.name)
476
- issues.push(`Agent ${String(agent.slug ?? '?')} missing 'name'`);
477
- if (!agent.description)
478
- issues.push(`Agent ${String(agent.slug ?? '?')} missing 'description'`);
479
- }
480
- if (issues.length > 0) {
481
- console.warn(`[CapabilityMetadata] ${issues.length} agent metadata issue(s) in registry — run 'monomind doctor' to review`);
482
- }
483
- }
484
- }
485
- catch { /* optional */ }
451
+ // Task 04: CapabilityMetadata validation moved to `monomind doctor -c registry`
452
+ // (see doctor-project-checks.ts:checkAgentRegistry). Printing this from a
453
+ // fire-and-forget startup task raced process exit short-lived commands
454
+ // could skip the warning even when the underlying issue was present. Doctor
455
+ // runs it synchronously within its own check pass instead, so it's always
456
+ // visible and itemized when you actually look for it.
486
457
  // NOTE: Semantic routing (@monomind/routing) is constructed on-demand by
487
458
  // its consumers — `monomind route` and `monomind agent --task` (see
488
459
  // commands/route.ts and commands/agent.ts). It is intentionally NOT
@@ -8,6 +8,7 @@ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, statSyn
8
8
  import { join } from 'node:path';
9
9
  import { randomBytes } from 'node:crypto';
10
10
  import { getProjectCwd } from './types.js';
11
+ import { agentTools } from './agent-tools.js';
11
12
  // Swarm state persistence
12
13
  const SWARM_DIR = '.monomind/swarm';
13
14
  const SWARM_STATE_FILE = 'swarm-state.json';
@@ -185,6 +186,82 @@ export const swarmTools = [
185
186
  };
186
187
  },
187
188
  },
189
+ {
190
+ name: 'swarm_scale',
191
+ description: 'Scale a swarm to a target agent count by spawning or terminating agents',
192
+ category: 'swarm',
193
+ inputSchema: {
194
+ type: 'object',
195
+ properties: {
196
+ swarmId: { type: 'string', description: 'Swarm ID to scale' },
197
+ targetAgents: { type: 'number', description: 'Target number of agents' },
198
+ agentType: { type: 'string', description: 'Agent type for newly spawned agents (default: worker)' },
199
+ },
200
+ required: ['swarmId', 'targetAgents'],
201
+ },
202
+ handler: async (input) => {
203
+ const swarmId = input.swarmId;
204
+ const targetAgents = input.targetAgents;
205
+ const agentType = input.agentType || 'worker';
206
+ const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
207
+ if (!swarmId || FORBIDDEN_KEYS.has(swarmId)) {
208
+ return { success: false, error: 'Invalid swarm ID' };
209
+ }
210
+ if (!Number.isFinite(targetAgents) || targetAgents < 0 || !Number.isInteger(targetAgents)) {
211
+ return { success: false, error: 'targetAgents must be a non-negative integer' };
212
+ }
213
+ const store = loadSwarmStore();
214
+ if (!Object.hasOwn(store.swarms, swarmId)) {
215
+ return { success: false, error: `Swarm ${swarmId} not found` };
216
+ }
217
+ const swarm = store.swarms[swarmId];
218
+ const currentCount = swarm.agents.length;
219
+ const delta = targetAgents - currentCount;
220
+ const spawnTool = agentTools.find(t => t.name === 'agent_spawn');
221
+ const terminateTool = agentTools.find(t => t.name === 'agent_terminate');
222
+ const spawned = [];
223
+ const terminated = [];
224
+ if (delta > 0) {
225
+ for (let i = 0; i < delta; i++) {
226
+ const result = await spawnTool.handler({ agentType });
227
+ if (result.success && result.agentId) {
228
+ swarm.agents.push(result.agentId);
229
+ spawned.push(result.agentId);
230
+ }
231
+ }
232
+ }
233
+ else if (delta < 0) {
234
+ const toRemove = swarm.agents.slice(0, -delta);
235
+ for (const agentId of toRemove) {
236
+ const result = await terminateTool.handler({ agentId });
237
+ if (result.success) {
238
+ terminated.push(agentId);
239
+ }
240
+ }
241
+ swarm.agents = swarm.agents.filter(id => !terminated.includes(id));
242
+ }
243
+ swarm.maxAgents = Math.max(swarm.maxAgents, swarm.agents.length);
244
+ swarm.updatedAt = new Date().toISOString();
245
+ saveSwarmStore(store);
246
+ // Individual agent_spawn/agent_terminate calls can fail silently (e.g. a
247
+ // stale agent ID already evicted from the agent store) — report success
248
+ // only if the swarm actually reached the requested count, so callers
249
+ // can't mistake a no-op failure for "already at target size".
250
+ const targetReached = swarm.agents.length === targetAgents;
251
+ return {
252
+ success: targetReached,
253
+ error: targetReached
254
+ ? undefined
255
+ : `Reached ${swarm.agents.length}/${targetAgents} agents — some spawn/terminate operations failed`,
256
+ swarmId,
257
+ previousCount: currentCount,
258
+ currentCount: swarm.agents.length,
259
+ targetAgents,
260
+ spawned,
261
+ terminated,
262
+ };
263
+ },
264
+ },
188
265
  {
189
266
  name: 'swarm_shutdown',
190
267
  description: 'Shutdown a swarm and update persistent state',
@@ -296,12 +296,9 @@ export class CommandParser {
296
296
  }
297
297
  buildAliases() {
298
298
  const aliases = {};
299
- for (const opt of this.globalOptions) {
300
- if (opt.short) {
301
- aliases[opt.short] = opt.name;
302
- }
303
- }
304
- // Add aliases from all commands and subcommands
299
+ // Add aliases from all commands and subcommands first (lowest priority)
300
+ // any command's own options may still be re-applied by buildScopedAliases()
301
+ // once the resolved command is known.
305
302
  for (const cmd of this.commands.values()) {
306
303
  if (cmd.options) {
307
304
  for (const opt of cmd.options) {
@@ -323,6 +320,14 @@ export class CommandParser {
323
320
  }
324
321
  }
325
322
  }
323
+ // Global options are applied last so an unrelated command's short flag
324
+ // (e.g. "security scan --quick, -Q") can't silently shadow a global flag
325
+ // of the same letter (e.g. global "-Q, --quiet") for every other command.
326
+ for (const opt of this.globalOptions) {
327
+ if (opt.short) {
328
+ aliases[opt.short] = opt.name;
329
+ }
330
+ }
326
331
  return { ...aliases, ...this.options.aliases };
327
332
  }
328
333
  /**
@@ -4,8 +4,7 @@
4
4
  * Monomind always runs on top of Claude Code, so low-confidence route
5
5
  * classification is delegated to the local `claude` CLI in headless print
6
6
  * mode — NOT to the Anthropic API with a managed key. There is no
7
- * `@anthropic-ai/sdk` dependency and no `ANTHROPIC_API_KEY` requirement: the
8
- * host's existing Claude Code auth is reused.
7
+ * No API key required: the host's existing Claude Code auth is reused.
9
8
  *
10
9
  * The returned function matches `LLMFallbackConfig.llmCaller` from
11
10
  * `@monomind/routing` — `(prompt: string) => Promise<string>`. When the
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monoes/monomindcli",
3
- "version": "1.17.0",
3
+ "version": "1.17.2",
4
4
  "type": "module",
5
5
  "description": "Monomind CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
6
6
  "main": "dist/src/index.js",
@@ -81,8 +81,7 @@
81
81
  },
82
82
  "devDependencies": {
83
83
  "typescript": "^5.3.0",
84
- "vitest": "^4.1.4",
85
- "@anthropic-ai/sdk": "^0.39.0"
84
+ "vitest": "^4.1.4"
86
85
  },
87
86
  "dependencies": {
88
87
  "ws": "^8.21.0",
@@ -391,7 +391,7 @@ const FRAMEWORK_SIGNATURES = [
391
391
  ['Vite', 'package.json', ['"vite"']],
392
392
  ['Webpack', 'package.json', ['"webpack"']],
393
393
  ['TypeScript', 'package.json', ['"typescript"']],
394
- ['Anthropic SDK','package.json', ['"@anthropic-ai/sdk"']],
394
+ ['Claude Code', 'package.json', ['"@anthropic-ai/claude-code"']],
395
395
  ['Django', 'requirements.txt', ['django']],
396
396
  ['Flask', 'requirements.txt', ['flask']],
397
397
  ['FastAPI', 'requirements.txt', ['fastapi']],