monomind 1.17.0 → 1.17.1

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 (91) 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/browser/dashboard/server.js +18 -0
  13. package/packages/@monomind/cli/dist/src/browser/dashboard/ui.html +37 -125
  14. package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.d.ts +17 -0
  15. package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.js +320 -0
  16. package/packages/@monomind/cli/dist/src/commands/agent-ops.d.ts +9 -0
  17. package/packages/@monomind/cli/dist/src/commands/agent-ops.js +329 -0
  18. package/packages/@monomind/cli/dist/src/commands/agent.js +5 -907
  19. package/packages/@monomind/cli/dist/src/commands/analyze-ast.d.ts +26 -0
  20. package/packages/@monomind/cli/dist/src/commands/analyze-ast.js +284 -0
  21. package/packages/@monomind/cli/dist/src/commands/analyze-boundaries.d.ts +14 -0
  22. package/packages/@monomind/cli/dist/src/commands/analyze-boundaries.js +295 -0
  23. package/packages/@monomind/cli/dist/src/commands/analyze-diff.d.ts +8 -0
  24. package/packages/@monomind/cli/dist/src/commands/analyze-diff.js +395 -0
  25. package/packages/@monomind/cli/dist/src/commands/analyze-graph.d.ts +14 -0
  26. package/packages/@monomind/cli/dist/src/commands/analyze-graph.js +304 -0
  27. package/packages/@monomind/cli/dist/src/commands/analyze-imports.d.ts +11 -0
  28. package/packages/@monomind/cli/dist/src/commands/analyze-imports.js +287 -0
  29. package/packages/@monomind/cli/dist/src/commands/analyze-symbols.d.ts +14 -0
  30. package/packages/@monomind/cli/dist/src/commands/analyze-symbols.js +302 -0
  31. package/packages/@monomind/cli/dist/src/commands/analyze.d.ts +38 -0
  32. package/packages/@monomind/cli/dist/src/commands/analyze.js +12 -1827
  33. package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.d.ts +26 -0
  34. package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.js +189 -0
  35. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.d.ts +19 -0
  36. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.js +388 -0
  37. package/packages/@monomind/cli/dist/src/commands/doctor.js +51 -942
  38. package/packages/@monomind/cli/dist/src/commands/hive-mind-comms.d.ts +11 -0
  39. package/packages/@monomind/cli/dist/src/commands/hive-mind-comms.js +242 -0
  40. package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.d.ts +35 -0
  41. package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.js +203 -0
  42. package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.d.ts +8 -0
  43. package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.js +233 -0
  44. package/packages/@monomind/cli/dist/src/commands/hive-mind-spawn.d.ts +12 -0
  45. package/packages/@monomind/cli/dist/src/commands/hive-mind-spawn.js +274 -0
  46. package/packages/@monomind/cli/dist/src/commands/hive-mind.js +10 -1129
  47. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.d.ts +4 -4
  48. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.js +19 -819
  49. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.d.ts +7 -0
  50. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.js +334 -0
  51. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.d.ts +7 -0
  52. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.js +399 -0
  53. package/packages/@monomind/cli/dist/src/commands/init-subcommands.d.ts +8 -0
  54. package/packages/@monomind/cli/dist/src/commands/init-subcommands.js +156 -0
  55. package/packages/@monomind/cli/dist/src/commands/init-upgrade.d.ts +6 -0
  56. package/packages/@monomind/cli/dist/src/commands/init-upgrade.js +203 -0
  57. package/packages/@monomind/cli/dist/src/commands/init-wizard.d.ts +6 -0
  58. package/packages/@monomind/cli/dist/src/commands/init-wizard.js +246 -0
  59. package/packages/@monomind/cli/dist/src/commands/init.js +6 -623
  60. package/packages/@monomind/cli/dist/src/commands/memory-admin.d.ts +10 -0
  61. package/packages/@monomind/cli/dist/src/commands/memory-admin.js +433 -0
  62. package/packages/@monomind/cli/dist/src/commands/memory-crud.d.ts +9 -0
  63. package/packages/@monomind/cli/dist/src/commands/memory-crud.js +342 -0
  64. package/packages/@monomind/cli/dist/src/commands/memory-list.d.ts +10 -0
  65. package/packages/@monomind/cli/dist/src/commands/memory-list.js +321 -0
  66. package/packages/@monomind/cli/dist/src/commands/memory-transfer.d.ts +9 -0
  67. package/packages/@monomind/cli/dist/src/commands/memory-transfer.js +372 -0
  68. package/packages/@monomind/cli/dist/src/commands/memory.d.ts +6 -0
  69. package/packages/@monomind/cli/dist/src/commands/memory.js +10 -1441
  70. package/packages/@monomind/cli/dist/src/commands/neural-core.d.ts +8 -0
  71. package/packages/@monomind/cli/dist/src/commands/neural-core.js +274 -0
  72. package/packages/@monomind/cli/dist/src/commands/neural-optimize.d.ts +7 -0
  73. package/packages/@monomind/cli/dist/src/commands/neural-optimize.js +332 -0
  74. package/packages/@monomind/cli/dist/src/commands/neural-registry.d.ts +7 -0
  75. package/packages/@monomind/cli/dist/src/commands/neural-registry.js +290 -0
  76. package/packages/@monomind/cli/dist/src/commands/neural.js +3 -974
  77. package/packages/@monomind/cli/dist/src/commands/platforms.js +327 -7
  78. package/packages/@monomind/cli/dist/src/commands/security-cve.d.ts +6 -0
  79. package/packages/@monomind/cli/dist/src/commands/security-cve.js +310 -0
  80. package/packages/@monomind/cli/dist/src/commands/security-misc.d.ts +9 -0
  81. package/packages/@monomind/cli/dist/src/commands/security-misc.js +293 -0
  82. package/packages/@monomind/cli/dist/src/commands/security-scan.d.ts +18 -0
  83. package/packages/@monomind/cli/dist/src/commands/security-scan.js +328 -0
  84. package/packages/@monomind/cli/dist/src/commands/security.js +3 -958
  85. package/packages/@monomind/cli/dist/src/commands/session.js +1 -1
  86. package/packages/@monomind/cli/dist/src/commands/swarm.js +23 -17
  87. package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +77 -0
  88. package/packages/@monomind/cli/dist/src/parser.js +11 -6
  89. package/packages/@monomind/cli/dist/src/routing/llm-caller.js +1 -2
  90. package/packages/@monomind/cli/package.json +2 -3
  91. package/packages/@monomind/cli/scripts/understand-analyze.mjs +1 -1
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Analyze complexity and symbols subcommands
3
+ * Complexity analysis and symbol extraction from code files
4
+ */
5
+ import { output } from '../output.js';
6
+ import * as fs from 'fs/promises';
7
+ import { resolve } from 'path';
8
+ import { getASTAnalyzer, safeWriteOutputFile, scanSourceFiles, fallbackAnalyze } from './analyze.js';
9
+ import { truncatePathAst, formatComplexityValueAst, getTypeMarkerAst } from './analyze-ast.js';
10
+ /**
11
+ * Complexity analysis subcommand
12
+ */
13
+ export const complexityAstCommand = {
14
+ name: 'complexity',
15
+ aliases: ['cx'],
16
+ description: 'Analyze code complexity metrics',
17
+ options: [
18
+ {
19
+ name: 'threshold',
20
+ short: 't',
21
+ description: 'Complexity threshold to flag (default: 10)',
22
+ type: 'number',
23
+ default: 10,
24
+ },
25
+ {
26
+ name: 'format',
27
+ short: 'f',
28
+ description: 'Output format (text, json)',
29
+ type: 'string',
30
+ default: 'text',
31
+ choices: ['text', 'json'],
32
+ },
33
+ {
34
+ name: 'output',
35
+ short: 'o',
36
+ description: 'Output file path',
37
+ type: 'string',
38
+ },
39
+ ],
40
+ examples: [
41
+ { command: 'monomind analyze complexity src/', description: 'Analyze complexity' },
42
+ { command: 'monomind analyze complexity src/ --threshold 15', description: 'Flag high complexity' },
43
+ ],
44
+ action: async (ctx) => {
45
+ const targetPath = ctx.args[0] || ctx.cwd;
46
+ const threshold = ctx.flags.threshold || 10;
47
+ const formatType = ctx.flags.format || 'text';
48
+ const outputFile = ctx.flags.output;
49
+ output.printInfo(`Analyzing complexity: ${output.highlight(targetPath)}`);
50
+ output.writeln();
51
+ const spinner = output.createSpinner({ text: 'Calculating complexity...', spinner: 'dots' });
52
+ spinner.start();
53
+ try {
54
+ const astModule = await getASTAnalyzer();
55
+ const resolvedPath = resolve(targetPath);
56
+ const stat = await fs.stat(resolvedPath);
57
+ const files = stat.isDirectory() ? await scanSourceFiles(resolvedPath) : [resolvedPath];
58
+ const results = [];
59
+ for (const file of files.slice(0, 100)) {
60
+ try {
61
+ const content = await fs.readFile(file, 'utf-8');
62
+ let analysis;
63
+ if (astModule) {
64
+ const analyzer = astModule.createASTAnalyzer();
65
+ analysis = analyzer.analyze(content, file);
66
+ }
67
+ else {
68
+ analysis = fallbackAnalyze(content, file);
69
+ }
70
+ const flagged = analysis.complexity.cyclomatic > threshold;
71
+ const rating = analysis.complexity.cyclomatic <= 5 ? 'Simple' :
72
+ analysis.complexity.cyclomatic <= 10 ? 'Moderate' :
73
+ analysis.complexity.cyclomatic <= 20 ? 'Complex' : 'Very Complex';
74
+ results.push({
75
+ file: file,
76
+ cyclomatic: analysis.complexity.cyclomatic,
77
+ cognitive: analysis.complexity.cognitive,
78
+ loc: analysis.complexity.loc,
79
+ commentDensity: analysis.complexity.commentDensity,
80
+ rating,
81
+ flagged,
82
+ });
83
+ }
84
+ catch {
85
+ // Skip files that can't be analyzed
86
+ }
87
+ }
88
+ spinner.stop();
89
+ // Sort by complexity descending
90
+ results.sort((a, b) => b.cyclomatic - a.cyclomatic);
91
+ const flaggedCount = results.filter(r => r.flagged).length;
92
+ const avgComplexity = results.length > 0
93
+ ? results.reduce((sum, r) => sum + r.cyclomatic, 0) / results.length
94
+ : 0;
95
+ if (formatType === 'json') {
96
+ const jsonOutput = { files: results, summary: { total: results.length, flagged: flaggedCount, avgComplexity, threshold } };
97
+ if (outputFile) {
98
+ await safeWriteOutputFile(outputFile, JSON.stringify(jsonOutput, null, 2));
99
+ output.printSuccess(`Results written to ${outputFile}`);
100
+ }
101
+ else {
102
+ output.printJson(jsonOutput);
103
+ }
104
+ return { success: true, data: jsonOutput };
105
+ }
106
+ // Summary
107
+ output.printBox([
108
+ `Files analyzed: ${results.length}`,
109
+ `Threshold: ${threshold}`,
110
+ `Flagged files: ${flaggedCount > 0 ? output.error(String(flaggedCount)) : output.success('0')}`,
111
+ `Average complexity: ${formatComplexityValueAst(Math.round(avgComplexity))}`,
112
+ ].join('\n'), 'Complexity Analysis');
113
+ // Show flagged files first
114
+ if (flaggedCount > 0) {
115
+ output.writeln();
116
+ output.writeln(output.bold(output.warning(`High Complexity Files (>${threshold})`)));
117
+ output.writeln(output.dim('-'.repeat(60)));
118
+ const flaggedFiles = results.filter(r => r.flagged).slice(0, 10);
119
+ output.printTable({
120
+ columns: [
121
+ { key: 'file', header: 'File', width: 40, format: (v) => truncatePathAst(v) },
122
+ { key: 'cyclomatic', header: 'Cyclo', width: 8, align: 'right', format: (v) => output.error(String(v)) },
123
+ { key: 'cognitive', header: 'Cogni', width: 8, align: 'right' },
124
+ { key: 'loc', header: 'LOC', width: 8, align: 'right' },
125
+ { key: 'rating', header: 'Rating', width: 15 },
126
+ ],
127
+ data: flaggedFiles,
128
+ });
129
+ }
130
+ // Show all files in table format
131
+ output.writeln();
132
+ output.writeln(output.bold('All Files'));
133
+ output.writeln(output.dim('-'.repeat(60)));
134
+ const displayFiles = results.slice(0, 15);
135
+ output.printTable({
136
+ columns: [
137
+ { key: 'file', header: 'File', width: 40, format: (v) => truncatePathAst(v) },
138
+ { key: 'cyclomatic', header: 'Cyclo', width: 8, align: 'right', format: (v) => formatComplexityValueAst(v) },
139
+ { key: 'cognitive', header: 'Cogni', width: 8, align: 'right' },
140
+ { key: 'loc', header: 'LOC', width: 8, align: 'right' },
141
+ ],
142
+ data: displayFiles,
143
+ });
144
+ if (results.length > 15) {
145
+ output.writeln(output.dim(` ... and ${results.length - 15} more files`));
146
+ }
147
+ if (outputFile) {
148
+ await safeWriteOutputFile(outputFile, JSON.stringify({ files: results, summary: { total: results.length, flagged: flaggedCount, avgComplexity, threshold } }, null, 2));
149
+ output.printSuccess(`Results written to ${outputFile}`);
150
+ }
151
+ return { success: true, data: { files: results, flaggedCount } };
152
+ }
153
+ catch (error) {
154
+ spinner.stop();
155
+ const message = error instanceof Error ? error.message : String(error);
156
+ output.printError(`Complexity analysis failed: ${message}`);
157
+ return { success: false, exitCode: 1 };
158
+ }
159
+ },
160
+ };
161
+ /**
162
+ * Symbol extraction subcommand
163
+ */
164
+ export const symbolsCommand = {
165
+ name: 'symbols',
166
+ aliases: ['sym'],
167
+ description: 'Extract and list code symbols (functions, classes, types)',
168
+ options: [
169
+ {
170
+ name: 'type',
171
+ short: 't',
172
+ description: 'Filter by symbol type (function, class, all)',
173
+ type: 'string',
174
+ default: 'all',
175
+ choices: ['function', 'class', 'all'],
176
+ },
177
+ {
178
+ name: 'format',
179
+ short: 'f',
180
+ description: 'Output format (text, json)',
181
+ type: 'string',
182
+ default: 'text',
183
+ choices: ['text', 'json'],
184
+ },
185
+ {
186
+ name: 'output',
187
+ short: 'o',
188
+ description: 'Output file path',
189
+ type: 'string',
190
+ },
191
+ ],
192
+ examples: [
193
+ { command: 'monomind analyze symbols src/', description: 'Extract all symbols' },
194
+ { command: 'monomind analyze symbols src/ --type function', description: 'Only functions' },
195
+ { command: 'monomind analyze symbols src/ --format json', description: 'JSON output' },
196
+ ],
197
+ action: async (ctx) => {
198
+ const targetPath = ctx.args[0] || ctx.cwd;
199
+ const symbolType = ctx.flags.type || 'all';
200
+ const formatType = ctx.flags.format || 'text';
201
+ const outputFile = ctx.flags.output;
202
+ output.printInfo(`Extracting symbols: ${output.highlight(targetPath)}`);
203
+ output.writeln();
204
+ const spinner = output.createSpinner({ text: 'Parsing code...', spinner: 'dots' });
205
+ spinner.start();
206
+ try {
207
+ const astModule = await getASTAnalyzer();
208
+ const resolvedPath = resolve(targetPath);
209
+ const stat = await fs.stat(resolvedPath);
210
+ const files = stat.isDirectory() ? await scanSourceFiles(resolvedPath) : [resolvedPath];
211
+ const symbols = [];
212
+ for (const file of files.slice(0, 100)) {
213
+ try {
214
+ const content = await fs.readFile(file, 'utf-8');
215
+ let analysis;
216
+ if (astModule) {
217
+ const analyzer = astModule.createASTAnalyzer();
218
+ analysis = analyzer.analyze(content, file);
219
+ }
220
+ else {
221
+ analysis = fallbackAnalyze(content, file);
222
+ }
223
+ if (symbolType === 'all' || symbolType === 'function') {
224
+ for (const fn of analysis.functions) {
225
+ symbols.push({
226
+ name: fn.name,
227
+ type: 'function',
228
+ file,
229
+ startLine: fn.startLine,
230
+ endLine: fn.endLine,
231
+ });
232
+ }
233
+ }
234
+ if (symbolType === 'all' || symbolType === 'class') {
235
+ for (const cls of analysis.classes) {
236
+ symbols.push({
237
+ name: cls.name,
238
+ type: 'class',
239
+ file,
240
+ startLine: cls.startLine,
241
+ endLine: cls.endLine,
242
+ });
243
+ }
244
+ }
245
+ }
246
+ catch {
247
+ // Skip files that can't be parsed
248
+ }
249
+ }
250
+ spinner.stop();
251
+ // Sort by file then name
252
+ symbols.sort((a, b) => a.file.localeCompare(b.file) || a.name.localeCompare(b.name));
253
+ if (formatType === 'json') {
254
+ if (outputFile) {
255
+ await safeWriteOutputFile(outputFile, JSON.stringify(symbols, null, 2));
256
+ output.printSuccess(`Results written to ${outputFile}`);
257
+ }
258
+ else {
259
+ output.printJson(symbols);
260
+ }
261
+ return { success: true, data: symbols };
262
+ }
263
+ // Summary
264
+ const functionCount = symbols.filter(s => s.type === 'function').length;
265
+ const classCount = symbols.filter(s => s.type === 'class').length;
266
+ output.printBox([
267
+ `Total symbols: ${symbols.length}`,
268
+ `Functions: ${functionCount}`,
269
+ `Classes: ${classCount}`,
270
+ `Files: ${files.length}`,
271
+ ].join('\n'), 'Symbol Extraction');
272
+ output.writeln();
273
+ output.writeln(output.bold('Symbols'));
274
+ output.writeln(output.dim('-'.repeat(60)));
275
+ const displaySymbols = symbols.slice(0, 30);
276
+ output.printTable({
277
+ columns: [
278
+ { key: 'type', header: 'Type', width: 10, format: (v) => getTypeMarkerAst(v) },
279
+ { key: 'name', header: 'Name', width: 30 },
280
+ { key: 'file', header: 'File', width: 35, format: (v) => truncatePathAst(v, 33) },
281
+ { key: 'startLine', header: 'Line', width: 8, align: 'right' },
282
+ ],
283
+ data: displaySymbols,
284
+ });
285
+ if (symbols.length > 30) {
286
+ output.writeln(output.dim(` ... and ${symbols.length - 30} more symbols`));
287
+ }
288
+ if (outputFile) {
289
+ await safeWriteOutputFile(outputFile, JSON.stringify(symbols, null, 2));
290
+ output.printSuccess(`Results written to ${outputFile}`);
291
+ }
292
+ return { success: true, data: symbols };
293
+ }
294
+ catch (error) {
295
+ spinner.stop();
296
+ const message = error instanceof Error ? error.message : String(error);
297
+ output.printError(`Symbol extraction failed: ${message}`);
298
+ return { success: false, exitCode: 1 };
299
+ }
300
+ },
301
+ };
302
+ //# sourceMappingURL=analyze-symbols.js.map
@@ -14,6 +14,44 @@
14
14
  * github.com/monoes/monomind
15
15
  */
16
16
  import type { Command } from '../types.js';
17
+ type AnalyzerModule = any;
18
+ export declare function getASTAnalyzer(): Promise<AnalyzerModule | null>;
19
+ export declare function getGraphAnalyzer(): Promise<AnalyzerModule | null>;
20
+ /**
21
+ * Write analysis output to a file, constraining the path to the current working
22
+ * directory to prevent path traversal attacks via --output /etc/cron.d/x or
23
+ * similar. Throws if the resolved path escapes cwd.
24
+ */
25
+ export declare function safeWriteOutputFile(outputFile: string, data: string): Promise<void>;
26
+ /**
27
+ * Helper: Scan directory for source files
28
+ */
29
+ export declare function scanSourceFiles(dir: string, maxDepth?: number): Promise<string[]>;
30
+ /**
31
+ * Fallback analysis when monovector is not available
32
+ */
33
+ export declare function fallbackAnalyze(code: string, filePath: string): {
34
+ filePath: string;
35
+ language: string;
36
+ functions: {
37
+ name: string;
38
+ startLine: number;
39
+ endLine: number;
40
+ }[];
41
+ classes: {
42
+ name: string;
43
+ startLine: number;
44
+ endLine: number;
45
+ }[];
46
+ imports: string[];
47
+ exports: string[];
48
+ complexity: {
49
+ cyclomatic: number;
50
+ cognitive: number;
51
+ loc: number;
52
+ commentDensity: number;
53
+ };
54
+ };
17
55
  export declare const analyzeCommand: Command;
18
56
  export default analyzeCommand;
19
57
  //# sourceMappingURL=analyze.d.ts.map