@monoes/monomindcli 1.6.9 → 1.8.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 +75 -113
- package/.claude/commands/monomind-do.md +227 -115
- package/.claude/commands/monomind-idea.md +30 -104
- package/.claude/commands/monomind-improve.md +31 -103
- package/.claude/helpers/graphify-freshen.cjs +12 -97
- package/.claude/helpers/hook-handler.cjs +16 -0
- package/.claude/helpers/learning-service.mjs +0 -0
- package/.claude/helpers/metrics-db.mjs +0 -0
- package/.claude/helpers/statusline.cjs +89 -65
- package/.claude/helpers/swarm-hooks.sh +0 -0
- package/.claude/skills/monomind-task-engine/SKILL.md +358 -0
- package/LICENSE +21 -0
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +36 -9
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +99 -28
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/helpers-generator.js +14 -14
- package/dist/src/init/helpers-generator.js.map +1 -1
- package/dist/src/init/shared-instructions-generator.d.ts +38 -0
- package/dist/src/init/shared-instructions-generator.d.ts.map +1 -0
- package/dist/src/init/shared-instructions-generator.js +571 -0
- package/dist/src/init/shared-instructions-generator.js.map +1 -0
- package/dist/src/init/types.d.ts +1 -1
- package/dist/src/init/types.d.ts.map +1 -1
- package/dist/src/mcp-client.d.ts.map +1 -1
- package/dist/src/mcp-client.js +5 -2
- package/dist/src/mcp-client.js.map +1 -1
- package/dist/src/mcp-tools/graphify-tools.d.ts +4 -67
- package/dist/src/mcp-tools/graphify-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/graphify-tools.js +40 -1226
- package/dist/src/mcp-tools/graphify-tools.js.map +1 -1
- package/dist/src/mcp-tools/index.d.ts +1 -0
- package/dist/src/mcp-tools/index.d.ts.map +1 -1
- package/dist/src/mcp-tools/index.js +1 -0
- package/dist/src/mcp-tools/index.js.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.d.ts +9 -0
- package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/monograph-tools.js +495 -0
- package/dist/src/mcp-tools/monograph-tools.js.map +1 -0
- package/dist/src/ui/dashboard.html +219 -45
- package/dist/src/ui/server.mjs +202 -16
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -11
|
@@ -53,7 +53,7 @@ Collect ALL of the following in parallel (skip any that error):
|
|
|
53
53
|
|
|
54
54
|
3. **Package manifest**: Read whichever exists first: `package.json`, `Cargo.toml`, `pyproject.toml`, `go.mod`. Extract name, description, and keywords/tags.
|
|
55
55
|
|
|
56
|
-
4. **Knowledge graph**: Call `
|
|
56
|
+
4. **Knowledge graph**: Call `mcp__monomind__monograph_suggest` with the user's prompt (`$ARGUMENTS`). Skip if it errors or returns empty.
|
|
57
57
|
|
|
58
58
|
5. **Memory search**: Call `mcp__monomind__memory_search` with the user's prompt (`$ARGUMENTS`). Use the top 5 results.
|
|
59
59
|
|
|
@@ -71,8 +71,8 @@ Spawn 2 agents in parallel via the Agent tool:
|
|
|
71
71
|
|
|
72
72
|
Provide it with `$ARGUMENTS` and `PROJECT_CONTEXT`. It must:
|
|
73
73
|
|
|
74
|
-
1. **Trace the component** — find all files, functions, classes, and modules related to the target. Use `
|
|
75
|
-
2. **Map dependencies** — what does the component depend on? What depends on it? Use `
|
|
74
|
+
1. **Trace the component** — find all files, functions, classes, and modules related to the target. Use `mcp__monomind__monograph_query` for each key term found.
|
|
75
|
+
2. **Map dependencies** — what does the component depend on? What depends on it? Use `mcp__monomind__monograph_shortest_path` for key relationships.
|
|
76
76
|
3. **Identify pain points** — look for:
|
|
77
77
|
- Code smells (large files, deep nesting, god objects, duplicated logic)
|
|
78
78
|
- Missing tests or low coverage areas
|
|
@@ -267,112 +267,43 @@ Also move any `skipElaboration: true` ideas directly to `Approved`.
|
|
|
267
267
|
|
|
268
268
|
## Step 7: Task Decomposer — Break Improvements into Subtasks
|
|
269
269
|
|
|
270
|
-
###
|
|
271
|
-
- Check if a `monomind-task` board exists in the space (same lookup method as Step 3).
|
|
272
|
-
- If not, create it with these columns:
|
|
273
|
-
- `Backlog`
|
|
274
|
-
- `Todo`
|
|
275
|
-
- `In Progress`
|
|
276
|
-
- `Review`
|
|
277
|
-
- `Human in Loop`
|
|
278
|
-
- `Done`
|
|
279
|
-
- Store column IDs.
|
|
280
|
-
|
|
281
|
-
### Decomposition into Professional Task Cards
|
|
270
|
+
### Generate the TASKS Array
|
|
282
271
|
|
|
283
272
|
Spawn a single `Software Architect` agent via the Agent tool. Provide it with:
|
|
284
273
|
- All ideas in the `Approved` column (titles, descriptions, and all comments including implementation paths and research)
|
|
285
274
|
- The `COMPONENT_ANALYSIS` from Step 2
|
|
286
275
|
- The `PROJECT_CONTEXT`
|
|
276
|
+
- **The Task Grouping Rules and Card Format from `monomind-task-engine` skill (Sections 1 & 2)** — include them verbatim in the agent prompt so it produces correctly structured tasks
|
|
287
277
|
|
|
288
|
-
For each approved improvement,
|
|
289
|
-
|
|
290
|
-
1. **Analyze and decompose** into 2-6 subtasks. Each subtask must be a professional task card:
|
|
291
|
-
|
|
292
|
-
```json
|
|
293
|
-
{
|
|
294
|
-
"title": "Action-oriented title (verb + noun + context)",
|
|
295
|
-
"description": "## What\nExact deliverable (new file, modified function, endpoint, etc.).\n\n## Why\nBusiness or technical motivation — what breaks without this?\n\n## Where\nFile paths, module boundaries, related components.\n\n## Patterns\nExisting conventions to follow (naming, error handling, test style).",
|
|
296
|
-
"definition_of_done": [
|
|
297
|
-
"Specific, binary, verifiable condition (include HTTP codes, error shapes, edge cases)",
|
|
298
|
-
"Quantified thresholds where applicable (rate limits, timeouts, sizes)"
|
|
299
|
-
],
|
|
300
|
-
"testing_criteria": {
|
|
301
|
-
"unit_tests": ["function(input) → expected outcome"],
|
|
302
|
-
"integration_tests": ["endpoint + method → status + response shape"],
|
|
303
|
-
"edge_cases": ["boundary condition → expected behavior"]
|
|
304
|
-
},
|
|
305
|
-
"checklist": [
|
|
306
|
-
"Write failing test for [specific behavior]",
|
|
307
|
-
"Implement [function/class] in [file path]",
|
|
308
|
-
"Run tests — verify green",
|
|
309
|
-
"Commit: '[type]: [description]'"
|
|
310
|
-
],
|
|
311
|
-
"agent_type": "best-fit agent from 230+ roster",
|
|
312
|
-
"priority": "critical | high | medium | low",
|
|
313
|
-
"effort": "1-10 (1=trivial, 10=full day)",
|
|
314
|
-
"dependencies": ["titles of prerequisite tasks, or empty"]
|
|
315
|
-
}
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
**Task generation rules:**
|
|
319
|
-
- Tasks MUST be ordered so dependencies come first
|
|
320
|
-
- Each task: 5-30 minutes for a single agent
|
|
321
|
-
- Split anything larger
|
|
322
|
-
- Every task starts with writing a test (TDD)
|
|
323
|
-
- DOD items must be binary (pass/fail, not "looks good")
|
|
324
|
-
- Testing criteria must name specific functions, endpoints, inputs
|
|
325
|
-
|
|
326
|
-
2. **Create each subtask** as a card in `Backlog` (has deps) or `Todo` (no deps):
|
|
327
|
-
```bash
|
|
328
|
-
monotask card create $TASK_BOARD_ID $COLUMN_ID "<title>" --json
|
|
329
|
-
monotask card tag add $TASK_BOARD_ID $CARD_ID "monomind-improve"
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
3. **Set description** with full context block:
|
|
333
|
-
```bash
|
|
334
|
-
monotask card set-description $TASK_BOARD_ID $CARD_ID "<description with What/Why/Where/Patterns>"
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
4. **Add DOD comment**:
|
|
338
|
-
```bash
|
|
339
|
-
monotask card comment add $TASK_BOARD_ID $CARD_ID "## Definition of Done\n- [ ] <condition 1>\n- [ ] <condition 2>\n..."
|
|
340
|
-
```
|
|
278
|
+
The agent MUST produce a `TASKS` array following the `monomind-task-engine` card format (Section 2). Each task must comply with all 7 grouping rules (Section 1). For each approved improvement, decompose into 2-6 subtasks.
|
|
341
279
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
6. **Add agent assignment + metadata**:
|
|
348
|
-
```bash
|
|
349
|
-
monotask card comment add $TASK_BOARD_ID $CARD_ID "Assigned agent: <agent_type>\nPriority: <priority>\nEffort: <effort>/10\nDependencies: <dep titles or none>\nSource: monomind-improve"
|
|
350
|
-
```
|
|
280
|
+
**If the architect has doubts** about decomposing an improvement (unclear scope, missing info):
|
|
281
|
+
- Add a comment with the question
|
|
282
|
+
- Move the improvement to `Deferred` instead of `Tasked`
|
|
351
283
|
|
|
352
|
-
|
|
284
|
+
Store the result as `TASKS` array.
|
|
353
285
|
|
|
354
|
-
|
|
355
|
-
```bash
|
|
356
|
-
monotask checklist add $TASK_BOARD_ID $CARD_ID "Implementation Steps" --json
|
|
357
|
-
```
|
|
358
|
-
Then for each step:
|
|
359
|
-
```bash
|
|
360
|
-
monotask checklist item-add $TASK_BOARD_ID $CARD_ID $CHECKLIST_ID "<step>"
|
|
361
|
-
```
|
|
286
|
+
### Invoke the Unified Task Engine
|
|
362
287
|
|
|
363
|
-
|
|
364
|
-
```bash
|
|
365
|
-
monotask card comment add $BOARD_ID $IMPROVE_CARD_ID "Subtasks created:\n- <title> (agent: <type>, effort: <N>/10)\n- <title> (agent: <type>, effort: <N>/10)\n..."
|
|
366
|
-
```
|
|
288
|
+
Invoke the `monomind-task-engine` skill (Sections 3-7) with these parameters:
|
|
367
289
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
290
|
+
| Parameter | Value |
|
|
291
|
+
|-----------|-------|
|
|
292
|
+
| `TASKS` | The array from the architect agent |
|
|
293
|
+
| `TASK_BOARD_ID` | From Step 3 (or let the engine set up the board) |
|
|
294
|
+
| `REPO_NAME` | From Step 1 |
|
|
295
|
+
| `SOURCE_TAG` | `"monomind-improve"` |
|
|
296
|
+
| `SOURCE_SUMMARY` | First 100 chars of `$ARGUMENTS` |
|
|
297
|
+
| `PARENT_CARD_ID` | Each `IMPROVE_CARD_ID` in the Approved column |
|
|
298
|
+
| `PARENT_BOARD_ID` | `$BOARD_ID` (the monomind-improve board) |
|
|
299
|
+
| `PARENT_DONE_COLUMN` | `$COL_TASKED` |
|
|
372
300
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
301
|
+
The engine will:
|
|
302
|
+
1. Create all cards on the monotask board (Section 4)
|
|
303
|
+
2. Store execution strategy in session memory (Section 5)
|
|
304
|
+
3. Run the **Final Dependency & Critical Path Review** (Section 6) — a fresh Code Reviewer agent validates prerequisites, context groups, critical path, parallel safety, and agent assignments
|
|
305
|
+
4. Fix any blocker issues automatically, present warnings to user
|
|
306
|
+
5. Present execution offer with mode recommendation (Section 7)
|
|
376
307
|
|
|
377
308
|
---
|
|
378
309
|
|
|
@@ -412,13 +343,10 @@ Output board references:
|
|
|
412
343
|
|
|
413
344
|
## Step 9: Offer to Execute Tasks
|
|
414
345
|
|
|
415
|
-
|
|
346
|
+
The `monomind-task-engine` (Section 7) already presents the execution offer after the final review passes. If the user picks a mode there, it invokes `monomind-do` automatically.
|
|
416
347
|
|
|
417
|
-
|
|
418
|
-
>
|
|
419
|
-
> Say **yes** to launch `/monomind:do` — it will pick up tasks one by one, execute them with the assigned agent, review for bugs, and loop until the queue is empty.
|
|
348
|
+
If the engine's execution offer was skipped or the user deferred, and there are tasks in Todo, offer:
|
|
420
349
|
|
|
421
|
-
If the user says yes, invoke:
|
|
422
350
|
```
|
|
423
|
-
Skill("monomind-do", "--space $SPACE_ID --board $TASK_BOARD_ID")
|
|
351
|
+
Skill("monomind-do", "--space $SPACE_ID --board $TASK_BOARD_ID --mode <parallel|minimal|sequential>")
|
|
424
352
|
```
|
|
@@ -1,118 +1,33 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
// Runs at SessionStart — rebuilds the knowledge graph
|
|
2
|
+
// Runs at SessionStart — rebuilds the knowledge graph using graphify (Python) in the background.
|
|
3
3
|
// Fire-and-forget: spawns detached child, logs start, exits immediately without blocking session.
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
|
+
const { spawn, execSync } = require('child_process');
|
|
6
7
|
|
|
7
8
|
const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
8
9
|
const graphDir = path.join(projectDir, '.monomind', 'graph');
|
|
9
|
-
const statsFile = path.join(graphDir, 'stats.json');
|
|
10
10
|
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
path.join(base, 'packages', '@monomind', 'graph', 'dist', 'src', 'index.js'),
|
|
17
|
-
];
|
|
18
|
-
// Check global npm install paths (monomind umbrella ships bundled-graph)
|
|
19
|
-
try {
|
|
20
|
-
const globalRoot = require('child_process').execSync('npm root -g', { encoding: 'utf-8' }).trim();
|
|
21
|
-
candidates.push(
|
|
22
|
-
path.join(globalRoot, 'monomind', 'packages', '@monomind', 'cli', 'bundled-graph', 'dist', 'src', 'index.js'),
|
|
23
|
-
path.join(globalRoot, 'monomind', 'node_modules', '@monoes', 'monomindcli', 'bundled-graph', 'dist', 'src', 'index.js'),
|
|
24
|
-
);
|
|
25
|
-
} catch {}
|
|
26
|
-
for (const c of candidates) {
|
|
27
|
-
if (fs.existsSync(c)) return c;
|
|
28
|
-
}
|
|
29
|
-
// pnpm: glob for @monomind+graph in .pnpm
|
|
30
|
-
const pnpmDir = path.join(base, 'node_modules', '.pnpm');
|
|
31
|
-
if (fs.existsSync(pnpmDir)) {
|
|
32
|
-
for (const entry of fs.readdirSync(pnpmDir)) {
|
|
33
|
-
if (entry.startsWith('@monomind+graph')) {
|
|
34
|
-
const p = path.join(pnpmDir, entry, 'node_modules', '@monomind', 'graph', 'dist', 'src', 'index.js');
|
|
35
|
-
if (fs.existsSync(p)) return p;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const graphPkg = findGraphPkg(projectDir);
|
|
43
|
-
|
|
44
|
-
if (!graphPkg) {
|
|
45
|
-
console.log('[graph] skip: @monomind/graph not found');
|
|
11
|
+
// Check if graphify CLI is available
|
|
12
|
+
try {
|
|
13
|
+
execSync('graphify --help', { encoding: 'utf-8', stdio: 'ignore' });
|
|
14
|
+
} catch {
|
|
15
|
+
console.log('[graph] skip: graphify not installed (run: uv tool install graphifyy)');
|
|
46
16
|
process.exit(0);
|
|
47
17
|
}
|
|
48
18
|
|
|
49
19
|
fs.mkdirSync(graphDir, { recursive: true });
|
|
50
20
|
|
|
51
|
-
// Locate the enricher script — works for both monorepo layout and npm-install layout
|
|
52
|
-
const enricherCandidates = [
|
|
53
|
-
path.join(projectDir, 'packages', '@monomind', 'cli', 'dist', 'src', 'graph', 'enrich.mjs'),
|
|
54
|
-
path.join(projectDir, 'node_modules', '@monomind', 'cli', 'dist', 'src', 'graph', 'enrich.mjs'),
|
|
55
|
-
];
|
|
56
|
-
const enricherPath = enricherCandidates.find(p => fs.existsSync(p)) ?? null;
|
|
57
|
-
const hasEnricher = enricherPath !== null;
|
|
58
|
-
|
|
59
|
-
const { spawn } = require('child_process');
|
|
60
|
-
const script = [
|
|
61
|
-
`import { buildGraph } from ${JSON.stringify('file://' + graphPkg)};`,
|
|
62
|
-
`import fs from 'fs';`,
|
|
63
|
-
`import path from 'path';`,
|
|
64
|
-
`const projectDir = ${JSON.stringify(projectDir)};`,
|
|
65
|
-
`const graphDir = ${JSON.stringify(graphDir)};`,
|
|
66
|
-
`const statsFile = ${JSON.stringify(statsFile)};`,
|
|
67
|
-
`buildGraph(projectDir, { codeOnly: true, outputDir: graphDir })`,
|
|
68
|
-
`.then(async r => {`,
|
|
69
|
-
` fs.writeFileSync(statsFile, JSON.stringify({ nodes: r.analysis?.stats?.nodes, edges: r.analysis?.stats?.edges, files: r.filesProcessed, builtAt: Date.now() }));`,
|
|
70
|
-
` console.log('[graph] built: ' + r.filesProcessed + ' files, ' + (r.analysis?.stats?.nodes ?? '?') + ' nodes');`,
|
|
71
|
-
hasEnricher ? [
|
|
72
|
-
` try {`,
|
|
73
|
-
` const { enrichGraph } = await import(${JSON.stringify('file://' + enricherPath)});`,
|
|
74
|
-
` const er = await enrichGraph(projectDir, { graphDir });`,
|
|
75
|
-
` console.log('[graph] enriched: ' + er.metrics.enrichedNodes + '/' + er.metrics.totalNodes + ' nodes');`,
|
|
76
|
-
` } catch (ee) { console.error('[graph] enrichment failed:', ee.message); }`,
|
|
77
|
-
].join('\n') : '',
|
|
78
|
-
// Normalize graph.json: add snake_case field aliases expected by the MCP tools
|
|
79
|
-
` try {`,
|
|
80
|
-
` const graphPath = path.join(graphDir, 'graph.json');`,
|
|
81
|
-
` const raw = JSON.parse(fs.readFileSync(graphPath, 'utf-8'));`,
|
|
82
|
-
` if (Array.isArray(raw.nodes)) {`,
|
|
83
|
-
` for (const n of raw.nodes) {`,
|
|
84
|
-
` n.source_file = n.sourceFile || '';`,
|
|
85
|
-
` n.source_location = n.sourceLocation || '';`,
|
|
86
|
-
` n.file_type = n.fileType || '';`,
|
|
87
|
-
` // Zero out degree for external symbols so they don't dominate god_nodes results`,
|
|
88
|
-
` if (!n.source_file) n.degree = 0;`,
|
|
89
|
-
` }`,
|
|
90
|
-
` fs.writeFileSync(graphPath, JSON.stringify(raw));`,
|
|
91
|
-
` console.log('[graph] normalized: added MCP field aliases to ' + raw.nodes.length + ' nodes');`,
|
|
92
|
-
` }`,
|
|
93
|
-
` } catch (ne) { console.error('[graph] normalize failed:', ne.message); }`,
|
|
94
|
-
// Ensure .monomind/graph symlink exists so the MCP server can locate the graph
|
|
95
|
-
` try {`,
|
|
96
|
-
` const monomindDir = path.join(projectDir, '.monomind');`,
|
|
97
|
-
` fs.mkdirSync(monomindDir, { recursive: true });`,
|
|
98
|
-
` const symlinkTarget = path.join(monomindDir, 'graph');`,
|
|
99
|
-
` let exists = false;`,
|
|
100
|
-
` try { fs.lstatSync(symlinkTarget); exists = true; } catch {}`,
|
|
101
|
-
` if (!exists) { fs.symlinkSync(graphDir, symlinkTarget); console.log('[graph] created .monomind/graph symlink'); }`,
|
|
102
|
-
` } catch (se) { console.error('[graph] symlink setup failed:', se.message); }`,
|
|
103
|
-
`})`,
|
|
104
|
-
`.catch(e => console.error('[graph] build failed:', e.message));`,
|
|
105
|
-
].join('\n');
|
|
106
|
-
|
|
107
21
|
const logPath = path.join(graphDir, 'build.log');
|
|
108
22
|
let logFd;
|
|
109
23
|
try { logFd = fs.openSync(logPath, 'a'); } catch { logFd = 'ignore'; }
|
|
110
|
-
|
|
24
|
+
|
|
25
|
+
// graphify update <path> — re-extracts code files and rebuilds graph.json
|
|
26
|
+
const child = spawn('graphify', ['update', projectDir], {
|
|
111
27
|
detached: true,
|
|
112
|
-
stdio: ['
|
|
28
|
+
stdio: ['ignore', logFd, logFd],
|
|
29
|
+
cwd: projectDir,
|
|
113
30
|
});
|
|
114
|
-
child.stdin.write(script);
|
|
115
|
-
child.stdin.end();
|
|
116
31
|
child.unref();
|
|
117
32
|
|
|
118
33
|
console.log('[graph] background build started for ' + projectDir);
|
|
@@ -961,6 +961,22 @@ const handlers = {
|
|
|
961
961
|
}
|
|
962
962
|
} catch (e) { /* non-fatal */ }
|
|
963
963
|
|
|
964
|
+
// ── Monomind Control UI Status ────────────────────────────────────────
|
|
965
|
+
try {
|
|
966
|
+
var http = require('http');
|
|
967
|
+
var controlPort = 4242;
|
|
968
|
+
var req = http.get('http://localhost:' + controlPort + '/', function(res) {
|
|
969
|
+
if (res.statusCode === 200) {
|
|
970
|
+
console.log('[CONTROL_UI] UP — http://localhost:' + controlPort);
|
|
971
|
+
}
|
|
972
|
+
res.resume();
|
|
973
|
+
});
|
|
974
|
+
req.on('error', function() {
|
|
975
|
+
console.log('[CONTROL_UI] offline — run: npx monomind mcp start');
|
|
976
|
+
});
|
|
977
|
+
req.setTimeout(800, function() { req.destroy(); });
|
|
978
|
+
} catch (e) { /* non-fatal */ }
|
|
979
|
+
|
|
964
980
|
// ── Worker Queue Resume (SR-003) ────────────────────────────────────
|
|
965
981
|
try {
|
|
966
982
|
var dispatchDir = path.join(CWD, '.monomind', 'worker-dispatch');
|
|
File without changes
|
|
File without changes
|
|
@@ -104,6 +104,18 @@ function safeStat(filePath) {
|
|
|
104
104
|
return null;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
// Project identifier — github owner/repo from git remote, else folder name
|
|
108
|
+
function getProjectName() {
|
|
109
|
+
try {
|
|
110
|
+
const remote = safeExec('git remote get-url origin 2>/dev/null', 2000).trim();
|
|
111
|
+
if (remote) {
|
|
112
|
+
const m = remote.match(/[/:]([\w.-]+)\/([\w.-]+?)(?:\.git)?$/);
|
|
113
|
+
if (m) return `${m[1]}/${m[2]}`;
|
|
114
|
+
}
|
|
115
|
+
} catch { /* ignore */ }
|
|
116
|
+
return path.basename(CWD);
|
|
117
|
+
}
|
|
118
|
+
|
|
107
119
|
// Shared settings cache — read once, used by multiple functions
|
|
108
120
|
let _settingsCache = undefined;
|
|
109
121
|
function getSettings() {
|
|
@@ -565,37 +577,56 @@ function getAgentDBStats() {
|
|
|
565
577
|
let namespaces = 0;
|
|
566
578
|
let hasHnsw = false;
|
|
567
579
|
|
|
568
|
-
//
|
|
580
|
+
// Count all memory entries across sources (sum, not max)
|
|
581
|
+
// 0. Palace drawers
|
|
569
582
|
const drawersPath = path.join(CWD, '.monomind', 'palace', 'drawers.jsonl');
|
|
570
583
|
const drawersStat = safeStat(drawersPath);
|
|
571
584
|
if (drawersStat) {
|
|
572
585
|
dbSizeKB += drawersStat.size / 1024;
|
|
573
586
|
try {
|
|
574
|
-
|
|
575
|
-
|
|
587
|
+
vectorCount += fs.readFileSync(drawersPath, 'utf-8').split('\n').filter(Boolean).length;
|
|
588
|
+
} catch { /* ignore */ }
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// 1. Palace closets
|
|
592
|
+
const closetsPath = path.join(CWD, '.monomind', 'palace', 'closets.jsonl');
|
|
593
|
+
const closetsStat = safeStat(closetsPath);
|
|
594
|
+
if (closetsStat) {
|
|
595
|
+
dbSizeKB += closetsStat.size / 1024;
|
|
596
|
+
try {
|
|
597
|
+
vectorCount += fs.readFileSync(closetsPath, 'utf-8').split('\n').filter(Boolean).length;
|
|
576
598
|
} catch { /* ignore */ }
|
|
577
599
|
}
|
|
578
600
|
|
|
579
|
-
//
|
|
601
|
+
// 2. Knowledge chunks
|
|
602
|
+
const chunksPath = path.join(CWD, '.monomind', 'knowledge', 'chunks.jsonl');
|
|
603
|
+
const chunksStat = safeStat(chunksPath);
|
|
604
|
+
if (chunksStat) {
|
|
605
|
+
dbSizeKB += chunksStat.size / 1024;
|
|
606
|
+
try {
|
|
607
|
+
vectorCount += fs.readFileSync(chunksPath, 'utf-8').split('\n').filter(Boolean).length;
|
|
608
|
+
} catch { /* ignore */ }
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// 3. Auto-memory store (intelligence layer)
|
|
580
612
|
const storePath = path.join(CWD, '.monomind', 'data', 'auto-memory-store.json');
|
|
581
613
|
const storeStat = safeStat(storePath);
|
|
582
614
|
if (storeStat) {
|
|
583
615
|
dbSizeKB += storeStat.size / 1024;
|
|
584
616
|
try {
|
|
585
617
|
const store = JSON.parse(fs.readFileSync(storePath, 'utf-8'));
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
} catch { /* fall back to size estimate */ }
|
|
618
|
+
vectorCount += Array.isArray(store) ? store.length : (store?.entries?.length || 0);
|
|
619
|
+
} catch { /* ignore */ }
|
|
589
620
|
}
|
|
590
621
|
|
|
591
|
-
//
|
|
622
|
+
// 4. Ranked context
|
|
592
623
|
const rankedPath = path.join(CWD, '.monomind', 'data', 'ranked-context.json');
|
|
593
624
|
try {
|
|
594
625
|
const ranked = readJSON(rankedPath);
|
|
595
|
-
if (ranked?.entries?.length
|
|
626
|
+
if (ranked?.entries?.length) vectorCount += ranked.entries.length;
|
|
596
627
|
} catch { /* ignore */ }
|
|
597
628
|
|
|
598
|
-
//
|
|
629
|
+
// 5. DB file sizes
|
|
599
630
|
const dbFiles = [
|
|
600
631
|
path.join(CWD, 'data', 'memory.db'),
|
|
601
632
|
path.join(CWD, '.monomind', 'memory.db'),
|
|
@@ -603,31 +634,17 @@ function getAgentDBStats() {
|
|
|
603
634
|
];
|
|
604
635
|
for (const f of dbFiles) {
|
|
605
636
|
const stat = safeStat(f);
|
|
606
|
-
if (stat) {
|
|
607
|
-
dbSizeKB += stat.size / 1024;
|
|
608
|
-
namespaces++;
|
|
609
|
-
}
|
|
637
|
+
if (stat) { dbSizeKB += stat.size / 1024; namespaces++; }
|
|
610
638
|
}
|
|
611
639
|
|
|
612
|
-
//
|
|
613
|
-
const graphPath = path.join(CWD, 'data', 'memory.graph');
|
|
614
|
-
const graphStat = safeStat(graphPath);
|
|
615
|
-
if (graphStat) dbSizeKB += graphStat.size / 1024;
|
|
616
|
-
|
|
617
|
-
// 5. HNSW index
|
|
640
|
+
// 6. HNSW index
|
|
618
641
|
const hnswPaths = [
|
|
619
642
|
path.join(CWD, '.swarm', 'hnsw.index'),
|
|
620
643
|
path.join(CWD, '.monomind', 'hnsw.index'),
|
|
621
644
|
];
|
|
622
645
|
for (const p of hnswPaths) {
|
|
623
|
-
|
|
624
|
-
if (stat) {
|
|
625
|
-
hasHnsw = true;
|
|
626
|
-
break;
|
|
627
|
-
}
|
|
646
|
+
if (safeStat(p)) { hasHnsw = true; break; }
|
|
628
647
|
}
|
|
629
|
-
|
|
630
|
-
// HNSW is available if memory package is present
|
|
631
648
|
if (!hasHnsw) {
|
|
632
649
|
const memPkgPaths = [
|
|
633
650
|
path.join(CWD, 'packages', '@monomind', 'memory', 'dist'),
|
|
@@ -641,6 +658,26 @@ function getAgentDBStats() {
|
|
|
641
658
|
return { vectorCount, dbSizeKB: Math.floor(dbSizeKB), namespaces, hasHnsw };
|
|
642
659
|
}
|
|
643
660
|
|
|
661
|
+
// Graphify knowledge graph stats
|
|
662
|
+
function getGraphifyStats() {
|
|
663
|
+
const statsPath = path.join(CWD, '.monomind', 'graph', 'stats.json');
|
|
664
|
+
const graphPath = path.join(CWD, '.monomind', 'graph', 'graph.json');
|
|
665
|
+
try {
|
|
666
|
+
const s = readJSON(statsPath);
|
|
667
|
+
if (s && s.nodes !== undefined) return { nodes: s.nodes, edges: s.edges || 0, exists: true };
|
|
668
|
+
} catch { /* ignore */ }
|
|
669
|
+
try {
|
|
670
|
+
const stat = safeStat(graphPath);
|
|
671
|
+
if (stat && stat.size < 10 * 1024 * 1024) {
|
|
672
|
+
const g = JSON.parse(fs.readFileSync(graphPath, 'utf-8'));
|
|
673
|
+
const nodes = Array.isArray(g.nodes) ? g.nodes.length : 0;
|
|
674
|
+
const edges = (Array.isArray(g.edges) ? g.edges : (Array.isArray(g.links) ? g.links : [])).length;
|
|
675
|
+
return { nodes, edges, exists: true };
|
|
676
|
+
}
|
|
677
|
+
} catch { /* ignore */ }
|
|
678
|
+
return { nodes: 0, edges: 0, exists: false };
|
|
679
|
+
}
|
|
680
|
+
|
|
644
681
|
// Memory Palace stats — drawers.jsonl + kg.json (the real persistent memory)
|
|
645
682
|
function getMemoryPalaceStats() {
|
|
646
683
|
const palaceDir = path.join(CWD, '.monomind', 'palace');
|
|
@@ -907,9 +944,10 @@ function generateStatusline() {
|
|
|
907
944
|
const tokens = getTokenStats();
|
|
908
945
|
const parts = [];
|
|
909
946
|
|
|
910
|
-
// Brand + swarm dot
|
|
947
|
+
// Brand + project + swarm dot
|
|
911
948
|
const swarmDot = swarm.coordinationActive ? `${x.green}●${x.reset}` : `${x.slate}○${x.reset}`;
|
|
912
|
-
|
|
949
|
+
const projName = getProjectName();
|
|
950
|
+
parts.push(`${x.bold}${x.purple}▊ MonoMind${x.reset} ${x.teal}${projName}${x.reset} ${swarmDot}`);
|
|
913
951
|
|
|
914
952
|
// Git branch + changes (compact)
|
|
915
953
|
if (git.gitBranch) {
|
|
@@ -958,12 +996,18 @@ function generateStatusline() {
|
|
|
958
996
|
parts.push(`${x.purple}🧠 ${autoMemCompact.count}m${x.reset}${typeSuffix}`);
|
|
959
997
|
}
|
|
960
998
|
|
|
961
|
-
// Knowledge chunks
|
|
999
|
+
// Knowledge chunks — show when populated
|
|
962
1000
|
if (knowledge.chunks > 0) {
|
|
963
1001
|
parts.push(`${x.teal}📚 ${knowledge.chunks}k${x.reset}`);
|
|
964
1002
|
}
|
|
965
1003
|
|
|
966
|
-
//
|
|
1004
|
+
// Graphify code graph
|
|
1005
|
+
const gfCompact = getGraphifyStats();
|
|
1006
|
+
if (gfCompact.exists) {
|
|
1007
|
+
parts.push(`${x.sky}🔗 ${gfCompact.nodes}n ${gfCompact.edges}e${x.reset}`);
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
// Triggers — show when populated
|
|
967
1011
|
if (triggers.triggers > 0) {
|
|
968
1012
|
parts.push(`${x.mint}🎯 ${triggers.triggers}t${x.reset}`);
|
|
969
1013
|
}
|
|
@@ -997,7 +1041,7 @@ function generateDashboard() {
|
|
|
997
1041
|
const security = getSecurityStatus();
|
|
998
1042
|
const swarm = getSwarmStatus();
|
|
999
1043
|
const system = getSystemMetrics();
|
|
1000
|
-
|
|
1044
|
+
// adrs removed — internal dev metric
|
|
1001
1045
|
const hooks = getHooksStatus();
|
|
1002
1046
|
const agentdb = getAgentDBStats();
|
|
1003
1047
|
const tests = getTestStats();
|
|
@@ -1015,7 +1059,8 @@ function generateDashboard() {
|
|
|
1015
1059
|
|
|
1016
1060
|
// ── Header: brand + git + model + session ────────────────────
|
|
1017
1061
|
const swarmDot = swarm.coordinationActive ? `${x.green}● LIVE${x.reset}` : `${x.slate}○ IDLE${x.reset}`;
|
|
1018
|
-
|
|
1062
|
+
const projName = getProjectName();
|
|
1063
|
+
let hdr = `${x.bold}${x.purple}▊ MonoMind${x.reset} ${x.dim}${VERSION}${x.reset} ${swarmDot} ${x.teal}${x.bold}${projName}${x.reset}`;
|
|
1019
1064
|
|
|
1020
1065
|
if (git.gitBranch) {
|
|
1021
1066
|
hdr += ` ${DIV} ${x.sky}⎇ ${x.bold}${git.gitBranch}${x.reset}`;
|
|
@@ -1036,30 +1081,29 @@ function generateDashboard() {
|
|
|
1036
1081
|
lines.push(hdr);
|
|
1037
1082
|
lines.push(SEP);
|
|
1038
1083
|
|
|
1039
|
-
// ── Row 1:
|
|
1040
|
-
const intellCol = pctColor(system.intelligencePct);
|
|
1041
|
-
const intellBar = blockBar(system.intelligencePct, 100, 6);
|
|
1042
|
-
|
|
1043
|
-
// Knowledge (Task 28)
|
|
1084
|
+
// ── Row 1: Knowledge & Graphify ──────────────────────────────
|
|
1044
1085
|
const knowStr = knowledge.chunks > 0
|
|
1045
1086
|
? `${x.teal}📚 ${x.bold}${knowledge.chunks}${x.reset}${x.slate} chunks${x.reset}`
|
|
1046
1087
|
: `${x.slate}📚 no chunks${x.reset}`;
|
|
1047
1088
|
|
|
1048
|
-
// Skills (Task 45)
|
|
1049
1089
|
const skillStr = knowledge.skills > 0
|
|
1050
1090
|
? ` ${x.mint}✦ ${knowledge.skills} skills${x.reset}`
|
|
1051
1091
|
: '';
|
|
1052
1092
|
|
|
1053
|
-
// Patterns
|
|
1054
1093
|
const patStr = progress.patternsLearned > 0
|
|
1055
1094
|
? `${x.gold}${progress.patternsLearned >= 1000 ? (progress.patternsLearned / 1000).toFixed(1) + 'k' : progress.patternsLearned} patterns${x.reset}`
|
|
1056
1095
|
: `${x.slate}0 patterns${x.reset}`;
|
|
1057
1096
|
|
|
1097
|
+
const gf = getGraphifyStats();
|
|
1098
|
+
const gfStr = gf.exists
|
|
1099
|
+
? `${x.sky}🔗 ${x.bold}${gf.nodes}${x.reset}${x.slate} nodes · ${x.reset}${x.sky}${x.bold}${gf.edges}${x.reset}${x.slate} edges${x.reset}`
|
|
1100
|
+
: `${x.slate}🔗 no graph${x.reset}`;
|
|
1101
|
+
|
|
1058
1102
|
lines.push(
|
|
1059
1103
|
`${x.purple}💡 INTEL${x.reset} ` +
|
|
1060
|
-
`${intellCol}${intellBar} ${x.bold}${system.intelligencePct}%${x.reset} ${DIV} ` +
|
|
1061
1104
|
`${knowStr}${skillStr} ${DIV} ` +
|
|
1062
|
-
patStr
|
|
1105
|
+
`${patStr} ${DIV} ` +
|
|
1106
|
+
gfStr
|
|
1063
1107
|
);
|
|
1064
1108
|
lines.push(SEP);
|
|
1065
1109
|
|
|
@@ -1112,26 +1156,14 @@ function generateDashboard() {
|
|
|
1112
1156
|
);
|
|
1113
1157
|
lines.push(SEP);
|
|
1114
1158
|
|
|
1115
|
-
// ── Row 3:
|
|
1116
|
-
const adrCol = adrs.count > 0
|
|
1117
|
-
? (adrs.implemented >= adrs.count ? x.green : x.gold)
|
|
1118
|
-
: x.slate;
|
|
1119
|
-
const adrStr = adrs.count > 0
|
|
1120
|
-
? `${adrCol}${x.bold}${adrs.implemented}${x.reset}${x.slate}/${x.reset}${x.white}${adrs.count}${x.reset} ADRs`
|
|
1121
|
-
: `${x.slate}no ADRs${x.reset}`;
|
|
1122
|
-
|
|
1123
|
-
const dddCol = pctColor(progress.dddProgress);
|
|
1124
|
-
const dddBar = blockBar(progress.dddProgress, 100, 5);
|
|
1125
|
-
|
|
1159
|
+
// ── Row 3: Security ──────────────────────────────────────────
|
|
1126
1160
|
const cveStatus = security.totalCves === 0
|
|
1127
1161
|
? (security.status === 'NONE' ? `${x.slate}not scanned${x.reset}` : `${x.green}✔ clean${x.reset}`)
|
|
1128
1162
|
: `${x.coral}${security.cvesFixed}/${security.totalCves} fixed${x.reset}`;
|
|
1129
1163
|
|
|
1130
1164
|
lines.push(
|
|
1131
|
-
`${x.purple}
|
|
1132
|
-
`${
|
|
1133
|
-
`DDD ${dddBar} ${dddCol}${x.bold}${progress.dddProgress}%${x.reset} ${DIV} ` +
|
|
1134
|
-
`🛡️ ${sec.col}${sec.label}${x.reset} ${DIV} ` +
|
|
1165
|
+
`${x.purple}🛡️ SECURITY${x.reset} ` +
|
|
1166
|
+
`${sec.col}${sec.label}${x.reset} ${DIV} ` +
|
|
1135
1167
|
`CVE ${cveStatus}`
|
|
1136
1168
|
);
|
|
1137
1169
|
lines.push(SEP);
|
|
@@ -1190,13 +1222,6 @@ function generateDashboard() {
|
|
|
1190
1222
|
siStr = `${x.slate}📄 no shared instructions${x.reset}`;
|
|
1191
1223
|
}
|
|
1192
1224
|
|
|
1193
|
-
// Domains
|
|
1194
|
-
const domCol = progress.domainsCompleted >= 4 ? x.green
|
|
1195
|
-
: progress.domainsCompleted >= 2 ? x.gold
|
|
1196
|
-
: progress.domainsCompleted >= 1 ? x.orange
|
|
1197
|
-
: x.slate;
|
|
1198
|
-
const domBar = blockBar(progress.domainsCompleted, progress.totalDomains);
|
|
1199
|
-
|
|
1200
1225
|
let monthStr = '';
|
|
1201
1226
|
if (tokens) {
|
|
1202
1227
|
const mFmt = tokens.monthCost >= 100 ? `$${tokens.monthCost.toFixed(2)}` : tokens.monthCost >= 1 ? `$${tokens.monthCost.toFixed(3)}` : `$${tokens.monthCost.toFixed(4)}`;
|
|
@@ -1205,7 +1230,6 @@ function generateDashboard() {
|
|
|
1205
1230
|
lines.push(
|
|
1206
1231
|
`${x.slate}📋 CONTEXT${x.reset} ` +
|
|
1207
1232
|
`${siStr} ${DIV} ` +
|
|
1208
|
-
`${x.teal}🏗 ${domBar} ${domCol}${x.bold}${progress.domainsCompleted}${x.reset}${x.slate}/${x.reset}${x.white}${progress.totalDomains}${x.reset} domains ${DIV} ` +
|
|
1209
1233
|
`${x.dim}💾 ${system.memoryMB} MB RAM${x.reset}` +
|
|
1210
1234
|
monthStr
|
|
1211
1235
|
);
|
|
File without changes
|