monomind 1.10.28 → 1.10.29

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.
@@ -199,12 +199,14 @@ function _injectCompactGraphMap() {
199
199
  }
200
200
 
201
201
  // 2. Fill remaining slots (up to 8 total) with god nodes (high centrality).
202
+ // Exclude node_modules paths (external typings like `Path [Interface]` skew rankings).
202
203
  if (anchors.length < 8) {
203
204
  var gods = db.prepare(
204
205
  "SELECT n.name, n.label, n.file_path, " +
205
206
  "(SELECT COUNT(*) FROM edges WHERE source_id=n.id OR target_id=n.id) AS deg " +
206
207
  "FROM nodes n " +
207
208
  "WHERE n.label NOT IN ('Concept') AND n.file_path IS NOT NULL AND n.file_path != '' " +
209
+ "AND n.file_path NOT LIKE '%/node_modules/%' AND n.file_path NOT LIKE '%node_modules%' " +
208
210
  "AND n.name NOT LIKE '(%' AND n.name NOT LIKE '%=>%' AND length(n.name) >= 3 " +
209
211
  "ORDER BY deg DESC LIMIT 15"
210
212
  ).all();
@@ -1730,13 +1732,37 @@ const handlers = {
1730
1732
  "FROM nodes n " +
1731
1733
  "WHERE n.label NOT IN ('Concept') " +
1732
1734
  "AND n.file_path IS NOT NULL AND n.file_path != '' " +
1735
+ "AND n.file_path NOT LIKE '%/node_modules/%' AND n.file_path NOT LIKE '%node_modules%' " +
1733
1736
  "ORDER BY deg DESC LIMIT 12"
1734
1737
  ).all();
1738
+
1739
+ // Check graph staleness: compare stored commit hash with current HEAD.
1740
+ var mgStaleIndicator = '';
1741
+ try {
1742
+ var mgLastCommitRow = null;
1743
+ try { mgLastCommitRow = mgDb.prepare("SELECT value FROM index_meta WHERE key='ua_last_commit'").get(); } catch (_) {}
1744
+ if (mgLastCommitRow && mgLastCommitRow.value) {
1745
+ var { execFileSync: mgExec } = require('child_process');
1746
+ var currentHead = '';
1747
+ try { currentHead = mgExec('git', ['rev-parse', 'HEAD'], { cwd: CWD, encoding: 'utf-8' }).trim(); } catch (_) {}
1748
+ if (currentHead && currentHead !== mgLastCommitRow.value) {
1749
+ var commitsBehind = 0;
1750
+ try {
1751
+ var revList = mgExec('git', ['rev-list', '--count', mgLastCommitRow.value + '..' + currentHead], { cwd: CWD, encoding: 'utf-8' }).trim();
1752
+ commitsBehind = parseInt(revList, 10) || 0;
1753
+ } catch (_) {}
1754
+ if (commitsBehind > 0) {
1755
+ mgStaleIndicator = ' [⚡ graph ' + commitsBehind + ' commit' + (commitsBehind === 1 ? '' : 's') + ' behind — run: npx monomind monograph build]';
1756
+ }
1757
+ }
1758
+ }
1759
+ } catch (_) {}
1760
+
1735
1761
  if (mgGodNodes.length > 0) {
1736
1762
  var mgGodStr = mgGodNodes.slice(0, 8).map(function(n) {
1737
1763
  return n.name + ' (' + n.label + ', ' + n.deg + ' links)';
1738
1764
  }).join(', ');
1739
- console.log('[MONOGRAPH_CONTEXT] ' + mgNodeCount + ' nodes · ' + mgEdgeCount + ' edges. Key nodes: ' + mgGodStr);
1765
+ console.log('[MONOGRAPH_CONTEXT] ' + mgNodeCount + ' nodes · ' + mgEdgeCount + ' edges. Key nodes: ' + mgGodStr + mgStaleIndicator);
1740
1766
  // Write god nodes into knowledge chunks so semantic search finds them
1741
1767
  var mgKnowledgeDir = path.join(CWD, '.monomind', 'knowledge');
1742
1768
  var mgChunksFile = path.join(mgKnowledgeDir, 'chunks.jsonl');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monomind",
3
- "version": "1.10.28",
3
+ "version": "1.10.29",
4
4
  "description": "Monomind - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -689,8 +689,29 @@ const upgradeCommand = {
689
689
  output.writeln();
690
690
  let succeeded = 0;
691
691
  let failed = 0;
692
+ // Try to read control URL for dashboard progress events (best-effort)
693
+ let controlUrl = 'http://localhost:4242';
694
+ try {
695
+ const ctrlCfg = JSON.parse(fs.readFileSync(path.join(process.cwd(), '.monomind', 'control.json'), 'utf-8'));
696
+ if (ctrlCfg.url)
697
+ controlUrl = ctrlCfg.url;
698
+ }
699
+ catch { }
700
+ const emitUpgradeProgress = async (projDir, status, current, total) => {
701
+ try {
702
+ const { default: http } = await import('http');
703
+ const payload = JSON.stringify({ type: 'upgrade:progress', project: projDir, status, current, total, ts: Date.now() });
704
+ const url = new URL(controlUrl + '/api/mastermind/event');
705
+ const req = http.request({ hostname: url.hostname, port: parseInt(url.port || '4242'), path: url.pathname, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) } });
706
+ req.write(payload);
707
+ req.end();
708
+ req.on('error', () => { });
709
+ }
710
+ catch { }
711
+ };
692
712
  for (const projDir of projects) {
693
- const spinner = output.createSpinner({ text: projDir });
713
+ const projIdx = projects.indexOf(projDir) + 1;
714
+ const spinner = output.createSpinner({ text: `[${projIdx}/${projects.length}] ${projDir}` });
694
715
  spinner.start();
695
716
  try {
696
717
  const res = addMissing
@@ -699,15 +720,18 @@ const upgradeCommand = {
699
720
  if (res.success) {
700
721
  spinner.succeed(projDir + ' (' + res.updated.length + ' updated)');
701
722
  succeeded++;
723
+ emitUpgradeProgress(projDir, 'success', projIdx, projects.length);
702
724
  }
703
725
  else {
704
726
  spinner.fail(projDir + ' — ' + (res.errors[0] || 'unknown error'));
705
727
  failed++;
728
+ emitUpgradeProgress(projDir, 'failed', projIdx, projects.length);
706
729
  }
707
730
  }
708
731
  catch (e) {
709
732
  spinner.fail(projDir + ' — ' + (e instanceof Error ? e.message : String(e)));
710
733
  failed++;
734
+ emitUpgradeProgress(projDir, 'failed', projIdx, projects.length);
711
735
  }
712
736
  }
713
737
  output.writeln();
@@ -342,6 +342,8 @@ export async function executeInit(options) {
342
342
  await startDaemonBackground(targetDir, result);
343
343
  // Run doctor auto-fix (non-blocking, best-effort)
344
344
  await runDoctorFix(targetDir, result);
345
+ // Register this project in ~/.monomind-projects.json so upgrade --all finds it
346
+ _registerMonomindProject(targetDir);
345
347
  }
346
348
  catch (error) {
347
349
  result.success = false;
@@ -2168,6 +2170,31 @@ function countEnabledHooks(options) {
2168
2170
  count++;
2169
2171
  return count;
2170
2172
  }
2173
+ /**
2174
+ * Register a project directory in ~/.monomind-projects.json so that
2175
+ * `monomind init upgrade --all` can find it without doing a directory scan.
2176
+ * Best-effort: failures are silently swallowed.
2177
+ */
2178
+ function _registerMonomindProject(dir) {
2179
+ try {
2180
+ const esmReq = createRequire(import.meta.url);
2181
+ const os = esmReq('os');
2182
+ const registryPath = path.join(os.homedir(), '.monomind-projects.json');
2183
+ let reg = { projects: [] };
2184
+ try {
2185
+ reg = JSON.parse(fs.readFileSync(registryPath, 'utf-8'));
2186
+ }
2187
+ catch { }
2188
+ if (!Array.isArray(reg.projects))
2189
+ reg.projects = [];
2190
+ const abs = path.resolve(dir);
2191
+ if (!reg.projects.includes(abs)) {
2192
+ reg.projects.push(abs);
2193
+ fs.writeFileSync(registryPath, JSON.stringify(reg, null, 2), 'utf-8');
2194
+ }
2195
+ }
2196
+ catch { /* non-fatal */ }
2197
+ }
2171
2198
  /**
2172
2199
  * Scan common locations for directories that have monomind installed
2173
2200
  * (presence of .claude/helpers/hook-handler.cjs is the definitive signal).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monoes/monomindcli",
3
- "version": "1.10.28",
3
+ "version": "1.10.29",
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",
@@ -698,8 +698,21 @@ async function main() {
698
698
  tx();
699
699
  // Rebuild FTS so summaries are immediately searchable
700
700
  try { db.prepare(`INSERT INTO nodes_fts(nodes_fts) VALUES('rebuild')`).run(); } catch {}
701
- mg.closeDb(db);
701
+
702
+ // Validate write-back: count nodes that now have a readable summary in properties
703
+ let enrichedCount = 0;
704
+ try {
705
+ const row = db.prepare(
706
+ `SELECT COUNT(*) AS c FROM nodes WHERE json_extract(properties, '$.summary') IS NOT NULL AND length(json_extract(properties, '$.summary')) > 5`
707
+ ).get();
708
+ enrichedCount = row ? row.c : 0;
709
+ } catch (_) {}
702
710
  console.log(`[understand] Imported ${written} analyses from stdin. FTS rebuilt.`);
711
+ console.log(`[understand] Validation: ${enrichedCount} node(s) now have LLM summaries readable via json_extract.`);
712
+ if (written > 0 && enrichedCount < written) {
713
+ console.warn(`[understand] WARNING: only ${enrichedCount} of ${written} imported analyses are queryable. Some properties may not have committed — check if properties column is TEXT.`);
714
+ }
715
+ mg.closeDb(db);
703
716
  return;
704
717
  }
705
718