@monoes/monomindcli 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/skills/monomind-task-engine/SKILL.md +358 -0
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +72 -10
- 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 +152 -24
- package/dist/src/init/executor.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-tools/graphify-tools.d.ts +4 -4
- package/dist/src/mcp-tools/graphify-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/graphify-tools.js +84 -60
- package/dist/src/mcp-tools/graphify-tools.js.map +1 -1
- package/dist/src/ui/dashboard.html +219 -45
- package/dist/src/ui/server.mjs +201 -16
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -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');
|
|
@@ -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
|
);
|