monomind 1.6.8 → 1.7.0
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/.claude/commands/monomind-createtask.md +73 -111
- package/.claude/commands/monomind-do.md +227 -115
- package/.claude/commands/monomind-idea.md +46 -109
- package/.claude/commands/monomind-improve.md +352 -0
- package/.claude/helpers/graphify-freshen.cjs +12 -97
- package/.claude/helpers/hook-handler.cjs +16 -0
- package/.claude/helpers/statusline.cjs +89 -65
- package/.claude/settings.local.json +2 -1
- package/.claude/skills/monomind-task-engine/SKILL.md +358 -0
- package/package.json +1 -1
- package/packages/@monomind/cli/dist/src/commands/doctor.js +72 -10
- package/packages/@monomind/cli/dist/src/init/executor.js +152 -24
- package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.d.ts +38 -0
- package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.js +571 -0
- package/packages/@monomind/cli/dist/src/init/types.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/graphify-tools.d.ts +4 -4
- package/packages/@monomind/cli/dist/src/mcp-tools/graphify-tools.js +84 -60
- package/packages/@monomind/cli/package.json +1 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Graphify MCP Tools
|
|
3
3
|
*
|
|
4
|
-
* Bridges
|
|
4
|
+
* Bridges graphify's (Python) knowledge graph into monomind's MCP tool surface.
|
|
5
5
|
* Agents can query the codebase knowledge graph without reading files —
|
|
6
6
|
* god_nodes(), query_graph(), shortest_path() give structural understanding
|
|
7
7
|
* in milliseconds vs. reading dozens of source files.
|
|
8
8
|
*
|
|
9
|
-
* Graph is built
|
|
10
|
-
* .monomind/graph/graph.json (legacy: graphify-out/graph.json).
|
|
11
|
-
*
|
|
9
|
+
* Graph is built by `graphify update` (Python CLI) on `monomind init` and
|
|
10
|
+
* stored at .monomind/graph/graph.json (legacy: graphify-out/graph.json).
|
|
11
|
+
* Install: uv tool install graphifyy
|
|
12
12
|
*/
|
|
13
13
|
import { existsSync, readFileSync } from 'fs';
|
|
14
14
|
import { join, resolve } from 'path';
|
|
@@ -29,25 +29,13 @@ function graphExists(cwd) {
|
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
31
|
* Load the knowledge graph.
|
|
32
|
-
*
|
|
32
|
+
* Parses the graph.json produced by graphify (Python).
|
|
33
33
|
*/
|
|
34
34
|
async function loadKnowledgeGraph(cwd) {
|
|
35
35
|
const graphPath = getGraphPath(cwd);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// Prefer @monomind/graph's loader which handles format normalization.
|
|
40
|
-
const { loadGraph } = await import('@monomind/graph');
|
|
41
|
-
const loaded = loadGraph(graphPath);
|
|
42
|
-
rawNodes = loaded.nodes;
|
|
43
|
-
rawEdges = loaded.edges;
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
// Fallback: parse JSON directly
|
|
47
|
-
const data = JSON.parse(readFileSync(graphPath, 'utf-8'));
|
|
48
|
-
rawNodes = data.nodes || [];
|
|
49
|
-
rawEdges = data.links || data.edges || [];
|
|
50
|
-
}
|
|
36
|
+
const data = JSON.parse(readFileSync(graphPath, 'utf-8'));
|
|
37
|
+
const rawNodes = data.nodes || [];
|
|
38
|
+
const rawEdges = data.links || data.edges || [];
|
|
51
39
|
// Build in-memory graph structures
|
|
52
40
|
const nodes = new Map();
|
|
53
41
|
for (const n of rawNodes) {
|
|
@@ -129,32 +117,46 @@ export const graphifyBuildTool = {
|
|
|
129
117
|
const cwd = getProjectCwd();
|
|
130
118
|
const targetPath = params.path || cwd;
|
|
131
119
|
try {
|
|
132
|
-
const {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
120
|
+
const { execSync } = await import('child_process');
|
|
121
|
+
execSync(`graphify update ${targetPath}`, {
|
|
122
|
+
encoding: 'utf8',
|
|
123
|
+
cwd: targetPath,
|
|
124
|
+
timeout: 300000,
|
|
125
|
+
stdio: 'pipe',
|
|
137
126
|
});
|
|
127
|
+
// graphify outputs to graphify-out/ by default
|
|
128
|
+
const graphPath = getGraphPath(targetPath);
|
|
129
|
+
const outputDir = join(targetPath, '.monomind', 'graph');
|
|
130
|
+
const statsPath = join(outputDir, 'stats.json');
|
|
131
|
+
let stats = { nodes: 0, edges: 0, communities: 0, files: 0 };
|
|
132
|
+
try {
|
|
133
|
+
stats = JSON.parse(readFileSync(statsPath, 'utf-8'));
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// Stats may not exist yet — read from graph directly
|
|
137
|
+
try {
|
|
138
|
+
const g = JSON.parse(readFileSync(graphPath, 'utf-8'));
|
|
139
|
+
stats.nodes = g.nodes?.length || 0;
|
|
140
|
+
stats.edges = (g.links || g.edges)?.length || 0;
|
|
141
|
+
}
|
|
142
|
+
catch { }
|
|
143
|
+
}
|
|
138
144
|
return {
|
|
139
145
|
success: true,
|
|
140
|
-
graphPath
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
graphQuality: result.graphQuality,
|
|
148
|
-
experimentStatus: result.experimentStatus,
|
|
149
|
-
corpusWarnings: result.corpusWarnings,
|
|
150
|
-
message: `[${result.experimentStatus}] Knowledge graph built — quality=${result.graphQuality.toFixed(4)} (${result.analysis.stats.nodes}n/${result.analysis.stats.edges}e/${result.analysis.stats.communities}c)`,
|
|
146
|
+
graphPath,
|
|
147
|
+
outputDir,
|
|
148
|
+
nodes: stats.nodes,
|
|
149
|
+
edges: stats.edges,
|
|
150
|
+
communities: stats.communities || 0,
|
|
151
|
+
filesProcessed: stats.files || 0,
|
|
152
|
+
message: `Knowledge graph built (${stats.nodes}n/${stats.edges}e)`,
|
|
151
153
|
};
|
|
152
154
|
}
|
|
153
155
|
catch (err) {
|
|
154
156
|
return {
|
|
155
157
|
error: true,
|
|
156
158
|
message: String(err),
|
|
157
|
-
hint: '
|
|
159
|
+
hint: 'graphify not installed — run: uv tool install graphifyy',
|
|
158
160
|
};
|
|
159
161
|
}
|
|
160
162
|
},
|
|
@@ -848,14 +850,20 @@ export const graphifyVisualizeTool = {
|
|
|
848
850
|
}
|
|
849
851
|
try {
|
|
850
852
|
const graphPath = getGraphPath(targetPath);
|
|
851
|
-
const {
|
|
852
|
-
const { join, dirname } = await import('path');
|
|
853
|
+
const { dirname } = await import('path');
|
|
853
854
|
const outputDir = dirname(graphPath);
|
|
854
|
-
const {
|
|
855
|
-
|
|
856
|
-
const
|
|
855
|
+
const { execSync, spawn } = await import('child_process');
|
|
856
|
+
// graphify doesn't have a visualize CLI command — generate a simple HTML viewer
|
|
857
|
+
const graphData = readFileSync(graphPath, 'utf-8');
|
|
858
|
+
const htmlContent = `<!DOCTYPE html><html><head><title>Knowledge Graph</title></head><body>
|
|
859
|
+
<h1>Knowledge Graph Visualization</h1>
|
|
860
|
+
<p>Nodes: ${JSON.parse(graphData).nodes?.length || 0}, Edges: ${(JSON.parse(graphData).links || JSON.parse(graphData).edges)?.length || 0}</p>
|
|
861
|
+
<pre style="max-height:80vh;overflow:auto">${graphData.slice(0, 50000)}</pre>
|
|
862
|
+
</body></html>`;
|
|
863
|
+
const { writeFileSync } = await import('fs');
|
|
864
|
+
const htmlPath = join(outputDir, 'graph.html');
|
|
865
|
+
writeFileSync(htmlPath, htmlContent);
|
|
857
866
|
if (params.open) {
|
|
858
|
-
const { spawn } = await import('child_process');
|
|
859
867
|
const opener = process.platform === 'darwin' ? 'open'
|
|
860
868
|
: process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
861
869
|
spawn(opener, [htmlPath], { detached: true, stdio: 'ignore' }).unref();
|
|
@@ -868,7 +876,7 @@ export const graphifyVisualizeTool = {
|
|
|
868
876
|
};
|
|
869
877
|
}
|
|
870
878
|
catch (err) {
|
|
871
|
-
return { error: true, message: String(err) };
|
|
879
|
+
return { error: true, message: String(err), hint: 'graphify not installed — run: uv tool install graphifyy' };
|
|
872
880
|
}
|
|
873
881
|
},
|
|
874
882
|
};
|
|
@@ -981,10 +989,10 @@ async function rebuild() {
|
|
|
981
989
|
const start = Date.now();
|
|
982
990
|
console.log('[graphify-watch] Change detected — rebuilding graph…');
|
|
983
991
|
try {
|
|
984
|
-
const {
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
992
|
+
const { execSync } = await import('child_process');
|
|
993
|
+
execSync('graphify update ' + TARGET, {
|
|
994
|
+
encoding: 'utf8', cwd: TARGET, timeout: 300000, stdio: 'pipe',
|
|
995
|
+
});
|
|
988
996
|
console.log('[graphify-watch] Done in', Date.now() - start, 'ms');
|
|
989
997
|
} catch (err) {
|
|
990
998
|
console.error('[graphify-watch] Build error:', err.message ?? err);
|
|
@@ -1158,14 +1166,18 @@ export const graphifySuggestTool = {
|
|
|
1158
1166
|
return { error: true, message: 'No graph found. Run graphify_build first.' };
|
|
1159
1167
|
}
|
|
1160
1168
|
try {
|
|
1161
|
-
const
|
|
1162
|
-
const
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
const
|
|
1169
|
+
const loaded = await loadKnowledgeGraph(targetPath);
|
|
1170
|
+
const godNodes = [...loaded.degree.entries()]
|
|
1171
|
+
.filter(([id]) => loaded.nodes.get(id)?.source_file)
|
|
1172
|
+
.sort((a, b) => b[1] - a[1])
|
|
1173
|
+
.slice(0, 10)
|
|
1174
|
+
.map(([id, deg]) => ({ node: id, degree: deg, file: loaded.nodes.get(id)?.source_file, question: `What role does ${id} play and why does it have ${deg} connections?` }));
|
|
1175
|
+
// Find isolated nodes (no connections)
|
|
1176
|
+
const isolated = [...loaded.degree.entries()]
|
|
1177
|
+
.filter(([id, d]) => d === 0 && loaded.nodes.get(id)?.source_file)
|
|
1178
|
+
.slice(0, 3)
|
|
1179
|
+
.map(([id]) => ({ node: id, degree: 0, file: loaded.nodes.get(id)?.source_file, question: `Why is ${id} isolated with no connections?` }));
|
|
1180
|
+
const questions = [...godNodes, ...isolated];
|
|
1169
1181
|
return { success: true, questions, total: questions.length };
|
|
1170
1182
|
}
|
|
1171
1183
|
catch (err) {
|
|
@@ -1196,12 +1208,24 @@ export const graphifyHealthTool = {
|
|
|
1196
1208
|
const cwd = getProjectCwd();
|
|
1197
1209
|
const targetPath = params.path || cwd;
|
|
1198
1210
|
try {
|
|
1199
|
-
const
|
|
1200
|
-
|
|
1201
|
-
|
|
1211
|
+
const warnings = [];
|
|
1212
|
+
let totalFiles = 0;
|
|
1213
|
+
if (!graphExists(targetPath)) {
|
|
1214
|
+
warnings.push('No graph found — run graphify_build first');
|
|
1215
|
+
}
|
|
1216
|
+
else {
|
|
1217
|
+
const loaded = await loadKnowledgeGraph(targetPath);
|
|
1218
|
+
totalFiles = new Set([...loaded.nodes.values()].map(n => n.source_file).filter(Boolean)).size;
|
|
1219
|
+
if (loaded.nodes.size === 0)
|
|
1220
|
+
warnings.push('Graph is empty — rebuild with graphify_build');
|
|
1221
|
+
if (totalFiles < 3)
|
|
1222
|
+
warnings.push('Very few source files — graph analysis may not be useful');
|
|
1223
|
+
if (loaded.edges.length === 0)
|
|
1224
|
+
warnings.push('No edges found — code may lack imports/calls');
|
|
1225
|
+
}
|
|
1202
1226
|
return {
|
|
1203
1227
|
success: true,
|
|
1204
|
-
totalFiles
|
|
1228
|
+
totalFiles,
|
|
1205
1229
|
warnings,
|
|
1206
1230
|
healthy: warnings.length === 0,
|
|
1207
1231
|
message: warnings.length === 0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monoes/monomindcli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
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",
|