@monoes/monomindcli 2.7.14 → 2.7.16

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 (93) hide show
  1. package/.claude/helpers/control-start.cjs +17 -3
  2. package/.claude/helpers/handlers/route-handler.cjs +41 -29
  3. package/.claude/helpers/handlers/session-restore-handler.cjs +3 -3
  4. package/.claude/helpers/hook-handler.cjs +2 -2
  5. package/.claude/helpers/mastermind-activate.cjs +4 -0
  6. package/.claude/helpers/statusline.cjs +83 -33
  7. package/.claude/helpers/utils/monograph.cjs +4 -2
  8. package/dist/src/capabilities/cap-documents.d.ts.map +1 -1
  9. package/dist/src/capabilities/cap-documents.js +263 -35
  10. package/dist/src/capabilities/cap-documents.js.map +1 -1
  11. package/dist/src/capabilities/scanner.js +1 -1
  12. package/dist/src/capabilities/scanner.js.map +1 -1
  13. package/dist/src/commands/doc.js +1 -1
  14. package/dist/src/commands/doc.js.map +1 -1
  15. package/dist/src/commands/org-observe.d.ts +4 -2
  16. package/dist/src/commands/org-observe.d.ts.map +1 -1
  17. package/dist/src/commands/org-observe.js +105 -4
  18. package/dist/src/commands/org-observe.js.map +1 -1
  19. package/dist/src/commands/org.d.ts +2 -0
  20. package/dist/src/commands/org.d.ts.map +1 -1
  21. package/dist/src/commands/org.js +120 -4
  22. package/dist/src/commands/org.js.map +1 -1
  23. package/dist/src/init/claudemd-generator.js +1 -1
  24. package/dist/src/init/settings-generator.d.ts.map +1 -1
  25. package/dist/src/init/settings-generator.js +23 -9
  26. package/dist/src/init/settings-generator.js.map +1 -1
  27. package/dist/src/init/statusline-generator.d.ts.map +1 -1
  28. package/dist/src/init/statusline-generator.js +45 -1
  29. package/dist/src/init/statusline-generator.js.map +1 -1
  30. package/dist/src/knowledge/eval/model-presence.d.ts +5 -0
  31. package/dist/src/knowledge/eval/model-presence.d.ts.map +1 -1
  32. package/dist/src/knowledge/eval/model-presence.js +52 -6
  33. package/dist/src/knowledge/eval/model-presence.js.map +1 -1
  34. package/dist/src/knowledge/eval/signals.d.ts.map +1 -1
  35. package/dist/src/knowledge/eval/signals.js +24 -0
  36. package/dist/src/knowledge/eval/signals.js.map +1 -1
  37. package/dist/src/mcp-client.d.ts +10 -0
  38. package/dist/src/mcp-client.d.ts.map +1 -1
  39. package/dist/src/mcp-client.js +86 -4
  40. package/dist/src/mcp-client.js.map +1 -1
  41. package/dist/src/mcp-tools/index.d.ts +1 -1
  42. package/dist/src/mcp-tools/index.d.ts.map +1 -1
  43. package/dist/src/mcp-tools/index.js +1 -1
  44. package/dist/src/mcp-tools/index.js.map +1 -1
  45. package/dist/src/mcp-tools/monomind-tools.d.ts +14 -0
  46. package/dist/src/mcp-tools/monomind-tools.d.ts.map +1 -0
  47. package/dist/src/mcp-tools/monomind-tools.js +54 -0
  48. package/dist/src/mcp-tools/monomind-tools.js.map +1 -0
  49. package/dist/src/memory/memory-bridge.d.ts.map +1 -1
  50. package/dist/src/memory/memory-bridge.js +27 -7
  51. package/dist/src/memory/memory-bridge.js.map +1 -1
  52. package/dist/src/orgrt/broker.d.ts +4 -2
  53. package/dist/src/orgrt/broker.d.ts.map +1 -1
  54. package/dist/src/orgrt/broker.js +8 -6
  55. package/dist/src/orgrt/broker.js.map +1 -1
  56. package/dist/src/orgrt/bus.d.ts +1 -0
  57. package/dist/src/orgrt/bus.d.ts.map +1 -1
  58. package/dist/src/orgrt/bus.js +5 -1
  59. package/dist/src/orgrt/bus.js.map +1 -1
  60. package/dist/src/orgrt/daemon.d.ts +17 -2
  61. package/dist/src/orgrt/daemon.d.ts.map +1 -1
  62. package/dist/src/orgrt/daemon.js +179 -44
  63. package/dist/src/orgrt/daemon.js.map +1 -1
  64. package/dist/src/orgrt/inbox.d.ts +1 -1
  65. package/dist/src/orgrt/inbox.d.ts.map +1 -1
  66. package/dist/src/orgrt/inbox.js +12 -3
  67. package/dist/src/orgrt/inbox.js.map +1 -1
  68. package/dist/src/orgrt/policy.d.ts.map +1 -1
  69. package/dist/src/orgrt/policy.js +84 -0
  70. package/dist/src/orgrt/policy.js.map +1 -1
  71. package/dist/src/orgrt/reporting.d.ts +2 -0
  72. package/dist/src/orgrt/reporting.d.ts.map +1 -1
  73. package/dist/src/orgrt/reporting.js +4 -1
  74. package/dist/src/orgrt/reporting.js.map +1 -1
  75. package/dist/src/orgrt/server.d.ts +4 -2
  76. package/dist/src/orgrt/server.d.ts.map +1 -1
  77. package/dist/src/orgrt/server.js +76 -73
  78. package/dist/src/orgrt/server.js.map +1 -1
  79. package/dist/src/orgrt/session.d.ts.map +1 -1
  80. package/dist/src/orgrt/session.js +63 -27
  81. package/dist/src/orgrt/session.js.map +1 -1
  82. package/dist/src/orgrt/test-loop.js +1 -1
  83. package/dist/src/orgrt/test-loop.js.map +1 -1
  84. package/dist/src/orgrt/types.d.ts +50 -1
  85. package/dist/src/orgrt/types.d.ts.map +1 -1
  86. package/dist/src/orgrt/types.js +33 -1
  87. package/dist/src/orgrt/types.js.map +1 -1
  88. package/dist/tsconfig.tsbuildinfo +1 -1
  89. package/package.json +2 -1
  90. package/dist/src/mcp-tools/neural-tools.d.ts +0 -15
  91. package/dist/src/mcp-tools/neural-tools.d.ts.map +0 -1
  92. package/dist/src/mcp-tools/neural-tools.js +0 -506
  93. package/dist/src/mcp-tools/neural-tools.js.map +0 -1
@@ -152,11 +152,25 @@ async function main() {
152
152
  }
153
153
  } catch { /* non-critical — proceed without check */ }
154
154
 
155
- // If already running, do nothing
155
+ // If already running, check if it's serving THIS project and a current build.
156
156
  const status = readStatus();
157
157
  if (status && status.pid && isPidAlive(status.pid)) {
158
- process.stdout.write(`[control] already running on port ${status.port} (pid ${status.pid})\n`);
159
- process.exit(0);
158
+ const live = await probeStatus(status.port);
159
+ const staleProject = live && live.dir && path.resolve(live.dir) !== path.resolve(CWD);
160
+ const startedMs = status.startedAt ? Date.now() - new Date(status.startedAt).getTime() : 0;
161
+ const staleBuild = startedMs > 7 * 24 * 3600_000; // older than 7 days
162
+ if (staleProject || staleBuild) {
163
+ const reason = staleProject
164
+ ? `rooted in ${live.dir}, not ${CWD}`
165
+ : `started ${Math.round(startedMs / 86400_000)}d ago`;
166
+ process.stdout.write(`[control] restarting stale server (${reason})\n`);
167
+ try { process.kill(status.pid, 'SIGTERM'); } catch { /* already gone */ }
168
+ // Give it a moment to release the port
169
+ await new Promise(r => setTimeout(r, 1000));
170
+ } else {
171
+ process.stdout.write(`[control] already running on port ${status.port} (pid ${status.pid})\n`);
172
+ process.exit(0);
173
+ }
160
174
  }
161
175
 
162
176
  // Adopt an already-listening server (e.g. started manually or by another session)
@@ -18,6 +18,17 @@
18
18
  const path = require('path');
19
19
  const fs = require('fs');
20
20
 
21
+ // ── Advisory output gate ────────────────────────────────────────────────────
22
+ // Set MONOMIND_HOOK_QUIET=1 to silence the per-prompt advisory blocks
23
+ // ([AUDIT], [CODEBASE], [MONOGRAPH], [INTELLIGENCE], [COST], etc.). Side-effects
24
+ // (file writes, telemetry counters, route mutations) are unchanged — only the
25
+ // stdout announcement is gated. Default (unset) keeps today's behavior.
26
+ var _HOOK_QUIET = String(process.env.MONOMIND_HOOK_QUIET || '').toLowerCase() === '1';
27
+ function advisoryLog() {
28
+ if (_HOOK_QUIET) return;
29
+ console.log.apply(console, arguments);
30
+ }
31
+
21
32
  // ── Intelligence read-path bridge ───────────────────────────────────────────
22
33
  // route-handler.cjs runs as a fresh node subprocess per invocation, but a
23
34
  // single process may call handle() more than once (e.g. tests, or a daemon
@@ -98,12 +109,12 @@ module.exports = {
98
109
  var bDb = hCtx._openMonographDb();
99
110
  if (bDb) {
100
111
  var bootstrapped = intelligence.bootstrapFromDb(bDb);
101
- if (bootstrapped > 0) console.log('[INTELLIGENCE] Bootstrapped ' + bootstrapped + ' hub nodes from knowledge graph');
112
+ if (bootstrapped > 0) advisoryLog('[INTELLIGENCE] Bootstrapped ' + bootstrapped + ' hub nodes from knowledge graph');
102
113
  }
103
114
  } catch (e) { /* non-fatal */ }
104
115
  }
105
116
  const ctx = intelligence.getContext(prompt);
106
- if (ctx) console.log(ctx);
117
+ if (ctx) advisoryLog(ctx);
107
118
  } catch (e) { /* non-fatal */ }
108
119
  }
109
120
  if (router && (router.routeTaskSemantic || router.routeTask)) {
@@ -174,7 +185,7 @@ module.exports = {
174
185
  // Only override when the embedding match clearly beats the keyword
175
186
  // route (0.1 margin) — otherwise just surface it as a signal.
176
187
  if (intelConf > curConf + 0.1) {
177
- console.log('[INTELLIGENCE] Embedding suggestion overrides keyword routing: ' + topIntelAgent + ' (confidence ' + intelConf.toFixed(2) + ') vs keyword ' + curAgent + ' (' + curConf.toFixed(2) + ')');
188
+ advisoryLog('[INTELLIGENCE] Embedding suggestion overrides keyword routing: ' + topIntelAgent + ' (confidence ' + intelConf.toFixed(2) + ') vs keyword ' + curAgent + ' (' + curConf.toFixed(2) + ')');
178
189
  result.keywordAgent = curAgent;
179
190
  result.agent = topIntelAgent;
180
191
  result.agentSlug = topIntelAgent;
@@ -182,7 +193,7 @@ module.exports = {
182
193
  result.reason = 'Intelligence embedding match (SONA/ReasoningBank)' + (result.reason ? '; keyword route was: ' + result.reason : '');
183
194
  result.enrichedFrom = 'intelligence-embedding';
184
195
  } else {
185
- console.log('[INTELLIGENCE] Embedding suggestion: ' + topIntelAgent + ' (confidence ' + intelConf.toFixed(2) + ') — kept keyword route ' + curAgent);
196
+ advisoryLog('[INTELLIGENCE] Embedding suggestion: ' + topIntelAgent + ' (confidence ' + intelConf.toFixed(2) + ') — kept keyword route ' + curAgent);
186
197
  }
187
198
  }
188
199
  }
@@ -210,7 +221,7 @@ module.exports = {
210
221
  if (routedPattern && routedPattern.successRate < 50) {
211
222
  var best = patterns.reduce(function(a, b) { return (b.wins/b.total) > (a.wins/a.total) ? b : a; });
212
223
  if (best.wins / best.total > 0.8 && best.agent_type !== routedAgent) {
213
- console.log('[AGENT_PATTERN] Historical: ' + best.agent_type + ' (' + Math.round(best.wins/best.total*100) + '% success, n=' + best.total + ') outperforms ' + routedAgent + ' (' + routedPattern.successRate + '%)');
224
+ advisoryLog('[AGENT_PATTERN] Historical: ' + best.agent_type + ' (' + Math.round(best.wins/best.total*100) + '% success, n=' + best.total + ') outperforms ' + routedAgent + ' (' + routedPattern.successRate + '%)');
214
225
  }
215
226
  }
216
227
  result.historicalPattern = patternMap;
@@ -240,7 +251,7 @@ module.exports = {
240
251
  var successes = agentFeedback.filter(function(f) { return f === true; }).length;
241
252
  var accuracy = Math.round(successes / agentFeedback.length * 100);
242
253
  if (accuracy < 60) {
243
- console.log('[ROUTING] Warning: ' + routedAgent + ' routing accuracy ' + accuracy + '% over last ' + agentFeedback.length + ' sessions');
254
+ advisoryLog('[ROUTING] Warning: ' + routedAgent + ' routing accuracy ' + accuracy + '% over last ' + agentFeedback.length + ' sessions');
244
255
  }
245
256
  result.routingAccuracy = accuracy;
246
257
  }
@@ -263,7 +274,7 @@ module.exports = {
263
274
  var dispatchAge = Date.now() - new Date(lastDispatch.dispatchedAt || 0).getTime();
264
275
  if (dispatchAge < 60000 && lastDispatch.agentType === (result.agentSlug || result.agent)) {
265
276
  result.recentlyDispatched = true;
266
- console.log('[DISPATCH_DEDUP] ' + lastDispatch.agentType + ' was dispatched ' + Math.round(dispatchAge / 1000) + 's ago — consider a different specialist or direct implementation');
277
+ advisoryLog('[DISPATCH_DEDUP] ' + lastDispatch.agentType + ' was dispatched ' + Math.round(dispatchAge / 1000) + 's ago — consider a different specialist or direct implementation');
267
278
  }
268
279
  }
269
280
  } catch (e) { /* non-fatal */ }
@@ -314,7 +325,8 @@ module.exports = {
314
325
  }
315
326
  }
316
327
 
317
- if (output.length > 0) console.log(output.join('\n'));
328
+ // Skill suggestions are opt-in (MONOMIND_SKILL_AUTO=1) and still respect QUIET.
329
+ if (output.length > 0 && String(process.env.MONOMIND_SKILL_AUTO || '') === '1' && !_HOOK_QUIET) console.log(output.join('\n'));
318
330
 
319
331
  // ── Second Brain: per-request knowledge injection ──────────────────
320
332
  // When the project has an indexed knowledge base, surface the most
@@ -483,7 +495,7 @@ module.exports = {
483
495
  sbLines.push(' • [' + sbSrc + (sbH.global ? ' · global' : '') + '] ' + sbText);
484
496
  }
485
497
  sbLines.push(' (deeper lookup: mcp__monomind__knowledge_search or `monomind doc search -q "..."`)');
486
- console.log(sbLines.join('\n'));
498
+ advisoryLog(sbLines.join('\n'));
487
499
  }
488
500
  }
489
501
  }
@@ -498,11 +510,11 @@ module.exports = {
498
510
  if (budget && budget.alert) {
499
511
  var tunedNote = budget.autoTuned ? ' (auto-tuned)' : '';
500
512
  if (budget.spike && !budget.breached) {
501
- console.log('[BUDGET_SPIKE] Today $' + budget.todayCost.toFixed(2) + ' is >2x your rolling daily avg. Unusual spend — review .monomind/metrics/token-summary.json.');
513
+ advisoryLog('[BUDGET_SPIKE] Today $' + budget.todayCost.toFixed(2) + ' is >2x your rolling daily avg. Unusual spend — review .monomind/metrics/token-summary.json.');
502
514
  } else if (budget.breached) {
503
- console.log('[BUDGET_BREACHED] Daily $' + budget.todayCost.toFixed(2) + '/$' + budget.dailyLimit + ' (' + budget.dailyPct + '%) · Monthly $' + budget.monthCost.toFixed(2) + '/$' + budget.monthlyLimit + ' (' + budget.monthlyPct + '%)' + tunedNote + '. Switch to Haiku with /model haiku or edit .monomind/budget.json.');
515
+ advisoryLog('[BUDGET_BREACHED] Daily $' + budget.todayCost.toFixed(2) + '/$' + budget.dailyLimit + ' (' + budget.dailyPct + '%) · Monthly $' + budget.monthCost.toFixed(2) + '/$' + budget.monthlyLimit + ' (' + budget.monthlyPct + '%)' + tunedNote + '. Switch to Haiku with /model haiku or edit .monomind/budget.json.');
504
516
  } else {
505
- console.log('[BUDGET_ALERT] Daily ' + budget.dailyPct + '% of $' + budget.dailyLimit + ' · Monthly ' + budget.monthlyPct + '% of $' + budget.monthlyLimit + tunedNote + '.');
517
+ advisoryLog('[BUDGET_ALERT] Daily ' + budget.dailyPct + '% of $' + budget.dailyLimit + ' · Monthly ' + budget.monthlyPct + '% of $' + budget.monthlyLimit + tunedNote + '.');
506
518
  }
507
519
  }
508
520
  } catch (e) {}
@@ -515,7 +527,7 @@ module.exports = {
515
527
  if (fs.existsSync(latencyFile) && fs.statSync(latencyFile).size < 32768) {
516
528
  var latencyData = JSON.parse(fs.readFileSync(latencyFile, 'utf-8'));
517
529
  if (latencyData && latencyData.avgMs > 500) {
518
- console.log('[PERF] Hook latency avg ' + Math.round(latencyData.avgMs) + 'ms (target <500ms). Slowest: ' + (latencyData.slowest || 'unknown'));
530
+ advisoryLog('[PERF] Hook latency avg ' + Math.round(latencyData.avgMs) + 'ms (target <500ms). Slowest: ' + (latencyData.slowest || 'unknown'));
519
531
  }
520
532
  }
521
533
  // Token usage check — surface only when spend is high
@@ -523,7 +535,7 @@ module.exports = {
523
535
  if (fs.existsSync(tokenFile) && fs.statSync(tokenFile).size < 32768) {
524
536
  var tokenData = JSON.parse(fs.readFileSync(tokenFile, 'utf-8'));
525
537
  if (tokenData && tokenData.todayCost > 50) {
526
- console.log('[COST] Today: $' + (tokenData.todayCost || 0).toFixed(2) + ' (' + (tokenData.todayCalls || 0) + ' calls)');
538
+ advisoryLog('[COST] Today: $' + (tokenData.todayCost || 0).toFixed(2) + ' (' + (tokenData.todayCalls || 0) + ' calls)');
527
539
  }
528
540
  }
529
541
  // Security audit findings
@@ -533,9 +545,9 @@ module.exports = {
533
545
  if (secData && secData.findings && secData.findings.length > 0) {
534
546
  var serious = secData.findings.filter(function (f) { return f && (f.severity === 'high' || f.severity === 'medium'); });
535
547
  if (serious.length > 0) {
536
- console.log('[SECURITY] ' + serious.length + ' finding(s) from background scan. Review .monomind/metrics/security-audit.json');
548
+ advisoryLog('[SECURITY] ' + serious.length + ' finding(s) from background scan. Review .monomind/metrics/security-audit.json');
537
549
  } else {
538
- console.log('[AUDIT] ' + secData.findings.length + ' low-severity note(s) (architecture heuristics, not vulnerabilities) — .monomind/metrics/security-audit.json');
550
+ advisoryLog('[AUDIT] ' + secData.findings.length + ' low-severity note(s) (architecture heuristics, not vulnerabilities) — .monomind/metrics/security-audit.json');
539
551
  }
540
552
  }
541
553
  }
@@ -544,10 +556,10 @@ module.exports = {
544
556
  if (fs.existsSync(mapFile) && fs.statSync(mapFile).size < 32768) {
545
557
  var mapData = JSON.parse(fs.readFileSync(mapFile, 'utf-8'));
546
558
  if (mapData && mapData.topFiles && mapData.topFiles.length > 0) {
547
- console.log('[CODEBASE] ' + mapData.topFiles.length + ' high-centrality files. Top: ' + (mapData.topFiles[0].ref || 'unknown') + ' (degree ' + (mapData.topFiles[0].degree || '?') + ')');
559
+ advisoryLog('[CODEBASE] ' + mapData.topFiles.length + ' high-centrality files. Top: ' + (mapData.topFiles[0].ref || 'unknown') + ' (degree ' + (mapData.topFiles[0].degree || '?') + ')');
548
560
  }
549
561
  if (mapData && mapData.graphStaleness && mapData.graphStaleness.commitsBehind > 10) {
550
- console.log('[CODEBASE] Graph index ' + mapData.graphStaleness.commitsBehind + ' commits behind HEAD — run monograph build');
562
+ advisoryLog('[CODEBASE] Graph index ' + mapData.graphStaleness.commitsBehind + ' commits behind HEAD — run monograph build');
551
563
  }
552
564
  }
553
565
  // Graph gate connectivity nudge — the pre-search/pre-bash gate
@@ -572,7 +584,7 @@ module.exports = {
572
584
  } catch (e) { /* corrupt — warn again to be safe */ }
573
585
  }
574
586
  if (!alreadyWarnedMcp) {
575
- console.log('[MCP] The graph gate blocked a search but no monograph_query/monograph_suggest call followed — the monomind MCP server is likely not connected this session. Run `claude mcp add monomind -- npx monomind@latest mcp start` (then restart), or approve the .mcp.json trust prompt if one is pending.');
587
+ advisoryLog('[MCP] The graph gate blocked a search but no monograph_query/monograph_suggest call followed — the monomind MCP server is likely not connected this session. Run `claude mcp add monomind -- npx monomind@latest mcp start` (then restart), or approve the .mcp.json trust prompt if one is pending.');
576
588
  try {
577
589
  fs.writeFileSync(mcpWarnFile, JSON.stringify({ sessionId: gateSessId, warnedAt: new Date().toISOString() }));
578
590
  } catch (e) { /* non-fatal */ }
@@ -588,7 +600,7 @@ module.exports = {
588
600
  var finding = ddData.findings[di];
589
601
  if (finding.category === 'god_nodes' && finding.items && finding.items.length > 0) {
590
602
  var topGod = finding.items[0];
591
- console.log('[DEEPDIVE] ' + finding.items.length + ' god nodes. Top: ' + (topGod.name || 'unknown') + ' (degree ' + (topGod.degree || '?') + ') in ' + (topGod.file || 'unknown'));
603
+ advisoryLog('[DEEPDIVE] ' + finding.items.length + ' god nodes. Top: ' + (topGod.name || 'unknown') + ' (degree ' + (topGod.degree || '?') + ') in ' + (topGod.file || 'unknown'));
592
604
  }
593
605
  }
594
606
  }
@@ -602,7 +614,7 @@ module.exports = {
602
614
  var insight = ulData.insightsGained[ui];
603
615
  if (insight.category === 'bridge_nodes' && insight.items && insight.items.length > 0) {
604
616
  var topBridge = insight.items[0];
605
- console.log('[ARCHITECTURE] ' + insight.items.length + ' bridge nodes crossing community boundaries. Top: ' + (topBridge.name || 'unknown') + ' (' + (topBridge.crossCommunityEdges || '?') + ' cross-edges) in ' + (topBridge.location || 'unknown'));
617
+ advisoryLog('[ARCHITECTURE] ' + insight.items.length + ' bridge nodes crossing community boundaries. Top: ' + (topBridge.name || 'unknown') + ' (' + (topBridge.crossCommunityEdges || '?') + ' cross-edges) in ' + (topBridge.location || 'unknown'));
606
618
  }
607
619
  }
608
620
  }
@@ -615,7 +627,7 @@ module.exports = {
615
627
  var rssBytes = perfData.workerProcessMemoryUsage.rss || 0;
616
628
  var rssMB = Math.round(rssBytes / (1024 * 1024));
617
629
  if (rssMB > 512) {
618
- console.log('[PERF] optimize worker RSS ' + rssMB + 'MB (>512MB threshold) at last run — reflects that one-shot process, not a persistent daemon');
630
+ advisoryLog('[PERF] optimize worker RSS ' + rssMB + 'MB (>512MB threshold) at last run — reflects that one-shot process, not a persistent daemon');
619
631
  }
620
632
  }
621
633
  }
@@ -624,7 +636,7 @@ module.exports = {
624
636
  if (fs.existsSync(consolFile) && fs.statSync(consolFile).size < 32768) {
625
637
  var consolData = JSON.parse(fs.readFileSync(consolFile, 'utf-8'));
626
638
  if (consolData && consolData.patternsConsolidated > 0) {
627
- console.log('[MEMORY] ' + consolData.patternsConsolidated + ' patterns consolidated into ' + consolData.clustersCreated + ' RAPTOR clusters');
639
+ advisoryLog('[MEMORY] ' + consolData.patternsConsolidated + ' patterns consolidated into ' + consolData.clustersCreated + ' RAPTOR clusters');
628
640
  }
629
641
  }
630
642
  // Benchmark worker RSS (manual-trigger `daemon trigger -w benchmark`)
@@ -634,7 +646,7 @@ module.exports = {
634
646
  if (benchData && benchData.benchmarks && benchData.benchmarks.memoryUsage) {
635
647
  var benchRssMB = Math.round((benchData.benchmarks.memoryUsage.rss || 0) / (1024 * 1024));
636
648
  if (benchRssMB > 512) {
637
- console.log('[PERF] Benchmark snapshot RSS ' + benchRssMB + 'MB (>512MB threshold) at last `daemon trigger -w benchmark` run');
649
+ advisoryLog('[PERF] Benchmark snapshot RSS ' + benchRssMB + 'MB (>512MB threshold) at last `daemon trigger -w benchmark` run');
638
650
  }
639
651
  }
640
652
  }
@@ -699,7 +711,7 @@ module.exports = {
699
711
  var ago = topMatches[mi].ts ? Math.round((Date.now() - topMatches[mi].ts) / 3600000) + 'h ago' : '';
700
712
  memLines.push(' ' + topMatches[mi].summary.replace(/\n/g, ' ').trim() + (ago ? ' (' + ago + ')' : ''));
701
713
  }
702
- console.log(memLines.join('\n'));
714
+ advisoryLog(memLines.join('\n'));
703
715
  }
704
716
  }
705
717
  }
@@ -775,10 +787,10 @@ module.exports = {
775
787
  if (fileLoc && s.startLine != null) fileLoc = fileLoc + ':' + s.startLine;
776
788
  return s.name + ' [' + s.label + '] — ' + fileLoc + editTag;
777
789
  });
778
- console.log('[MONOGRAPH] ' + nodeCount + ' nodes. Top files: ' + hintParts.join(' · '));
790
+ advisoryLog('[MONOGRAPH] ' + nodeCount + ' nodes. Top files: ' + hintParts.join(' · '));
779
791
  hCtx._recordGraphTelemetry('preresolve_hit');
780
792
  } else {
781
- console.log('[MONOGRAPH] ' + nodeCount + ' nodes. Call mcp__monomind__monograph_suggest to find relevant files.');
793
+ advisoryLog('[MONOGRAPH] ' + nodeCount + ' nodes. Call mcp__monomind__monograph_suggest to find relevant files.');
782
794
  hCtx._recordGraphTelemetry('preresolve_miss');
783
795
  }
784
796
  }
@@ -786,7 +798,7 @@ module.exports = {
786
798
 
787
799
  // Swarm mode selection is available on-demand via /mastermind slash command.
788
800
  } else {
789
- console.log('[INFO] Router not available, using default routing');
801
+ advisoryLog('[INFO] Router not available, using default routing');
790
802
  }
791
803
 
792
804
  // Task 22: TeamRoutingModes — only log when an explicit swarm config is present
@@ -796,7 +808,7 @@ module.exports = {
796
808
  var swarmCfgSt = fs.statSync(swarmCfgPath);
797
809
  var topology22 = swarmCfgSt.size <= 1024 * 1024 ? (JSON.parse(fs.readFileSync(swarmCfgPath, 'utf-8')).topology || 'mesh') : 'mesh';
798
810
  var mode22 = topology22 === 'hierarchical' ? 'route' : 'coordinate';
799
- console.log('[ROUTING_MODE] topology=' + topology22 + ' → mode=' + mode22);
811
+ advisoryLog('[ROUTING_MODE] topology=' + topology22 + ' → mode=' + mode22);
800
812
  }
801
813
  } catch (e) { /* non-fatal */ }
802
814
  }
@@ -333,12 +333,12 @@ module.exports = {
333
333
  var kRetriever = new memoryMod.KnowledgeRetriever(kSearchFn, kStore);
334
334
  var kResult = await kRetriever.retrieveForTask('shared', sessionCtx, 5);
335
335
  if (kResult.excerpts.length > 0) {
336
- console.log('[KNOWLEDGE_PRELOADED] ' + kResult.excerpts.length + ' excerpts (KnowledgeRetriever)');
336
+ if (String(process.env.MONOMIND_HOOK_QUIET || '') !== '1') console.log('[KNOWLEDGE_PRELOADED] ' + kResult.excerpts.length + ' excerpts (KnowledgeRetriever)');
337
337
  }
338
338
  } else {
339
339
  var directResults = await kSearchFn(sessionCtx, { namespace: 'knowledge:shared', limit: 5, minScore: 0.3 });
340
340
  if (directResults.length > 0) {
341
- console.log('[KNOWLEDGE_PRELOADED] ' + directResults.length + ' excerpts (direct keyword search)');
341
+ if (String(process.env.MONOMIND_HOOK_QUIET || '') !== '1') console.log('[KNOWLEDGE_PRELOADED] ' + directResults.length + ' excerpts (direct keyword search)');
342
342
  }
343
343
  }
344
344
  } catch (e) { /* non-fatal */ }
@@ -536,7 +536,7 @@ module.exports = {
536
536
  var tokenTracker = require(path.join(helpersDir, 'token-tracker.cjs'));
537
537
  var tokenSummary = tokenTracker.quickSummary();
538
538
  if (tokenSummary) {
539
- console.log(tokenSummary);
539
+ if (String(process.env.MONOMIND_HOOK_QUIET || '') !== '1') console.log(tokenSummary);
540
540
  }
541
541
  try {
542
542
  var tokenData = tokenTracker.quickSummaryData();
@@ -443,7 +443,7 @@ const handlers = {
443
443
  return;
444
444
  }
445
445
  if (gateResult === 'warn') {
446
- console.log('[MONOGRAPH_REMINDER] monograph_query/suggest not yet called this session — graph has ' + (_getNodeCount() || '20k+') + ' indexed nodes. Try monograph first for faster, more precise results.');
446
+ if (String(process.env.MONOMIND_HOOK_QUIET || '') !== '1') console.log('[MONOGRAPH_REMINDER] monograph_query/suggest not yet called this session — graph has ' + (_getNodeCount() || '20k+') + ' indexed nodes. Try monograph first for faster, more precise results.');
447
447
  }
448
448
  var graphAssisted = false;
449
449
  if (_isGraphFresh()) {
@@ -708,7 +708,7 @@ const handlers = {
708
708
  return;
709
709
  }
710
710
  if (gateResult === 'warn') {
711
- console.log('[MONOGRAPH_REMINDER] monograph_query/suggest not yet called this session — try monograph first for faster results.');
711
+ if (String(process.env.MONOMIND_HOOK_QUIET || '') !== '1') console.log('[MONOGRAPH_REMINDER] monograph_query/suggest not yet called this session — try monograph first for faster results.');
712
712
  }
713
713
  var graphResolved = false;
714
714
  try {
@@ -5,6 +5,9 @@
5
5
  // The routing table is the unique value — tells Claude which skill for which task.
6
6
  // Full protocol loads on-demand via /mastermind.
7
7
 
8
+ // Opt-in: only emit the routing table when MONOMIND_MASTERMIND=1.
9
+ // Off by default to cut ~1.5K tokens of per-session injection; load on-demand via /mastermind.
10
+ if (String(process.env.MONOMIND_MASTERMIND || '') === '1') {
8
11
  process.stdout.write(
9
12
  '## Mastermind Skill Router\n\n' +
10
13
  'Invoke the matching skill BEFORE responding. If unsure, check — invoking and finding it irrelevant costs less than skipping it.\n\n' +
@@ -33,3 +36,4 @@ process.stdout.write(
33
36
  'Process skills (debug, idea, architect, research) set the approach. Execution skills (build, review, release) carry it out.\n' +
34
37
  'Subagents with `<SUBAGENT-STOP>` gate skip this routing.\n'
35
38
  );
39
+ }
@@ -1028,6 +1028,38 @@ function getGraphifyStats() {
1028
1028
  return { nodes: 0, edges: 0, exists: false };
1029
1029
  }
1030
1030
 
1031
+ // Document / knowledge stats — docs indexed + chunks + memory entries
1032
+ function getDocStats() {
1033
+ const docPath = path.join(CWD, '.monomind', 'knowledge', 'doc-metadata.jsonl');
1034
+ const chunksPath = path.join(CWD, '.monomind', 'knowledge', 'chunks.jsonl');
1035
+ const memDbPath = path.join(CWD, '.monomind', 'memory', 'memory.db');
1036
+ let docs = 0, chunks = 0, memories = 0, exists = false;
1037
+ try {
1038
+ const ds = safeStat(docPath);
1039
+ if (ds && ds.size > 0) {
1040
+ const buf = fs.readFileSync(docPath, 'utf-8');
1041
+ docs = buf.split('\n').filter(Boolean).length;
1042
+ exists = true;
1043
+ }
1044
+ } catch { /* ignore */ }
1045
+ try {
1046
+ const cs = safeStat(chunksPath);
1047
+ if (cs && cs.size > 0) {
1048
+ const buf = fs.readFileSync(chunksPath, 'utf-8');
1049
+ chunks = buf.split('\n').filter(Boolean).length;
1050
+ exists = true;
1051
+ }
1052
+ } catch { /* ignore */ }
1053
+ try {
1054
+ if (fs.existsSync(memDbPath)) {
1055
+ const result = spawnSync('sqlite3', [memDbPath, 'SELECT COUNT(*) FROM memory_entries;'], { encoding: 'utf-8', timeout: 1000 });
1056
+ const n = parseInt((result.stdout || '').trim(), 10) || 0;
1057
+ if (n > 0) { memories = n; exists = true; }
1058
+ }
1059
+ } catch { /* ignore */ }
1060
+ return { docs, chunks, memories, exists };
1061
+ }
1062
+
1031
1063
  function getSIBudget() {
1032
1064
  const SI_LIMIT = 1500;
1033
1065
  const siPath = path.join(CWD, '.agents', 'shared_instructions.md');
@@ -1177,18 +1209,18 @@ function generateDashboard() {
1177
1209
  const swarmDot = swarm.coordinationActive ? `${x.green}● LIVE${x.reset}` : `${x.slate}○ IDLE${x.reset}`;
1178
1210
  const projName = getProjectName();
1179
1211
  const cwdName = path.basename(CWD);
1180
- let hdr = `${x.bold}${x.purple}▊ Monomind ${VERSION}${x.reset} ${swarmDot} ${x.teal}${x.bold}${projName}${x.reset} ${DIV} ${x.dim}◎ ${cwdName}${x.reset} ${DIV} ${x.violet}⬡ ${git.name}${x.reset}`;
1212
+ let hdr = `${x.bold}${x.purple}▊Monomind ${VERSION}${x.reset} ${swarmDot} ${x.teal}${x.bold}${projName}${x.reset} ${DIV} ${x.dim}◎${cwdName}${x.reset} ${DIV} ${x.violet}⬡${git.name}${x.reset}`;
1181
1213
 
1182
1214
  if (git.gitBranch) {
1183
- hdr += ` ${DIV} ${x.sky}⎇ ${x.bold}${git.gitBranch}${x.reset}`;
1184
- if (git.staged > 0) hdr += ` ${x.green}+${git.staged}${x.reset}`;
1185
- if (git.modified > 0) hdr += ` ${x.gold}~${git.modified} mod${x.reset}`;
1186
- if (git.untracked > 0) hdr += ` ${x.slate}?${git.untracked}${x.reset}`;
1187
- if (git.ahead > 0) hdr += ` ${x.green}↑${git.ahead}${x.reset}`;
1188
- if (git.behind > 0) hdr += ` ${x.coral}↓${git.behind}${x.reset}`;
1215
+ hdr += ` ${DIV} ${x.sky}⎇${x.bold}${git.gitBranch}${x.reset}`;
1216
+ if (git.staged > 0) hdr += ` ${x.green}+${git.staged}${x.reset}`;
1217
+ if (git.modified > 0) hdr += ` ${x.gold}~${git.modified}${x.reset}`;
1218
+ if (git.untracked > 0) hdr += ` ${x.slate}?${git.untracked}${x.reset}`;
1219
+ if (git.ahead > 0) hdr += ` ${x.green}↑${git.ahead}${x.reset}`;
1220
+ if (git.behind > 0) hdr += ` ${x.coral}↓${git.behind}${x.reset}`;
1189
1221
  }
1190
1222
 
1191
- if (session.duration) hdr += ` ${x.dim}⏱ ${session.duration}${x.reset}`;
1223
+ if (session.duration) hdr += ` ${x.dim}⏱${session.duration}${x.reset}`;
1192
1224
 
1193
1225
  lines.push(hdr);
1194
1226
  lines.push(SEP);
@@ -1226,15 +1258,15 @@ function generateDashboard() {
1226
1258
  const lat = getHookLatency();
1227
1259
  let latStr = '';
1228
1260
  if (lat && lat.perPromptMs > 500) {
1229
- latStr = ` ${DIV} ${x.coral}⚡ hooks ${lat.perPromptMs}ms${x.reset}`;
1261
+ latStr = ` ${DIV} ${x.coral}⚡${lat.perPromptMs}ms${x.reset}`;
1230
1262
  } else if (lat && lat.perPromptMs > 0) {
1231
- latStr = ` ${DIV} ${x.dim}⚡ ${lat.perPromptMs}ms${x.reset}`;
1263
+ latStr = ` ${DIV} ${x.dim}⚡${lat.perPromptMs}ms${x.reset}`;
1232
1264
  }
1233
1265
 
1234
- lines.push(`${x.purple}🤖 AGENT${x.reset} ${agentStr} ${DIV} ${loopStr}${latStr}`);
1266
+ lines.push(`${x.purple}🤖 AGENT${x.reset} ${agentStr} ${DIV} ${loopStr}${latStr}`);
1235
1267
  lines.push(SEP);
1236
1268
 
1237
- // ── Row 2: Graph freshness + Pending HIL ─────────────────────
1269
+ // ── Row 2: Graph ─────────────────────────────────────────────
1238
1270
  const gf = getGraphifyStats();
1239
1271
  const freshness = getGraphFreshness();
1240
1272
  let graphStr;
@@ -1242,54 +1274,72 @@ function generateDashboard() {
1242
1274
  const nodesFmt = gf.nodes >= 1000 ? `${(gf.nodes / 1000).toFixed(0)}k` : `${gf.nodes}`;
1243
1275
  const edgesFmt = gf.edges >= 1000 ? `${(gf.edges / 1000).toFixed(0)}k` : `${gf.edges}`;
1244
1276
  const freshTag = freshness.fresh
1245
- ? `${x.green}● fresh${x.reset}`
1277
+ ? `${x.green}●fresh${x.reset}`
1246
1278
  : freshness.stale
1247
- ? `${x.coral}● ${freshness.commitsBehind} commits stale${x.reset}`
1248
- : `${x.gold}● ${freshness.commitsBehind} behind${x.reset}`;
1249
- graphStr = `${x.sky}🔗 ${x.bold}${nodesFmt}${x.reset}${x.slate} nodes${x.reset} ${x.bold}${edgesFmt}${x.reset}${x.slate} edges${x.reset} ${freshTag}`;
1279
+ ? `${x.coral}●${freshness.commitsBehind}stale${x.reset}`
1280
+ : `${x.gold}●${freshness.commitsBehind}behind${x.reset}`;
1281
+ graphStr = `${x.sky}🔗${x.bold}${nodesFmt}${x.reset}${x.slate}n${x.reset} ${x.bold}${edgesFmt}${x.reset}${x.slate}e${x.reset} ${freshTag}`;
1250
1282
  } else {
1251
- graphStr = `${x.slate}🔗 no graph${x.reset}`;
1283
+ graphStr = `${x.slate}🔗no graph${x.reset}`;
1252
1284
  }
1253
1285
 
1254
1286
  const hil = getHILPending();
1255
- let contextLine = `${x.teal}🧠 CONTEXT${x.reset} ${graphStr}`;
1256
- if (hil.pending > 0) {
1257
- contextLine += ` ${DIV} ${x.coral}✨ ${x.bold}${hil.pending}${x.reset}${x.coral} HIL pending${x.reset}`;
1258
- }
1259
-
1260
- // Graph usage ratio + $ saved
1261
1287
  const usage = getGraphUsage();
1288
+ let contextLine = `${x.teal}🧠 CONTEXT${x.reset} ${graphStr}`;
1262
1289
  if (usage) {
1263
1290
  const col = usage.pct >= 40 ? x.green : usage.pct >= 15 ? x.gold : x.coral;
1264
1291
  const savedCol = usage.dollarsSaved >= 0.10 ? x.green : x.slate;
1265
- contextLine += ` ${DIV} ${col}📊 graph ${usage.pct}%${x.reset}${x.slate} · grep ${100 - usage.pct}%${x.reset} ${savedCol}💰 $${usage.dollarsSaved.toFixed(2)}${x.reset}`;
1292
+ contextLine += ` ${DIV} ${col}📊${usage.pct}%${x.reset}${x.slate}·${100 - usage.pct}%grep${x.reset} ${savedCol}💰$${usage.dollarsSaved.toFixed(2)}${x.reset}`;
1293
+ }
1294
+ if (hil.pending > 0) {
1295
+ contextLine += ` ${DIV} ${x.coral}✨${x.bold}${hil.pending}${x.reset}${x.coral}HIL${x.reset}`;
1266
1296
  }
1267
-
1268
- // Token cost
1269
1297
  const tokenCost = getTokenCostSummary();
1270
1298
  if (tokenCost) {
1271
1299
  if (tokenCost.isFresh && tokenCost.todayCost > 0) {
1272
1300
  const col = tokenCost.todayCost > 50 ? x.coral : tokenCost.todayCost > 10 ? x.gold : x.mint;
1273
- contextLine += ` ${DIV} ${col}${fmtCost(tokenCost.todayCost)} today${x.reset}${x.dim} · ${fmtCost(tokenCost.monthCost)} mo${x.reset}`;
1301
+ contextLine += ` ${DIV} ${col}${fmtCost(tokenCost.todayCost)}${x.reset}${x.dim}·${fmtCost(tokenCost.monthCost)}mo${x.reset}`;
1274
1302
  } else if (tokenCost.monthCost > 0) {
1275
- contextLine += ` ${DIV} ${x.slate}${fmtCost(tokenCost.monthCost)} mo${x.reset}`;
1303
+ contextLine += ` ${DIV} ${x.slate}${fmtCost(tokenCost.monthCost)}mo${x.reset}`;
1276
1304
  }
1277
1305
  }
1278
-
1279
1306
  lines.push(contextLine);
1280
1307
 
1281
- // ── Row 3: Active org runs ───────────────────────────────────
1308
+ // ── Row 3: Docs / knowledge ──────────────────────────────────
1309
+ const docStats = getDocStats();
1310
+ if (docStats.exists) {
1311
+ const parts = [];
1312
+ if (docStats.docs > 0) {
1313
+ const docFmt = docStats.docs >= 1000 ? `${(docStats.docs / 1000).toFixed(1)}k` : `${docStats.docs}`;
1314
+ parts.push(`${x.bold}${docFmt}${x.reset}${x.slate}docs${x.reset}`);
1315
+ }
1316
+ if (docStats.chunks > 0) parts.push(`${x.bold}${docStats.chunks}${x.reset}${x.slate}chunks${x.reset}`);
1317
+ if (docStats.memories > 0) parts.push(`${x.bold}${docStats.memories}${x.reset}${x.slate}mem${x.reset}`);
1318
+ // OKF export check
1319
+ const okfDir = path.join(CWD, '.monomind', 'exports');
1320
+ try {
1321
+ if (fs.existsSync(okfDir)) {
1322
+ const okfFiles = cleanEntries(okfDir, f => f.endsWith('.md') || f.endsWith('.json'));
1323
+ if (okfFiles.length > 0) parts.push(`${x.bold}${okfFiles.length}${x.reset}${x.slate}okf${x.reset}`);
1324
+ }
1325
+ } catch { /* ignore */ }
1326
+ if (parts.length) {
1327
+ lines.push(`${x.dim} 📄 ${parts.join(' ')}${x.reset}`);
1328
+ }
1329
+ }
1330
+
1331
+ // ── Row 4: Active org runs ───────────────────────────────────
1282
1332
  const orgStatus = getActiveOrgs();
1283
1333
  if (orgStatus.count > 0) {
1284
1334
  lines.push(SEP);
1285
1335
  const orgParts = orgStatus.orgs.slice(0, 5).map(o => {
1286
1336
  const ageMin = Math.floor(o.ageMs / 60000);
1287
- const ageFmt = ageMin < 1 ? 'just now' : ageMin < 60 ? `${ageMin}m ago` : `${Math.floor(ageMin / 60)}h ago`;
1337
+ const ageFmt = ageMin < 1 ? 'now' : ageMin < 60 ? `${ageMin}m` : `${Math.floor(ageMin / 60)}h`;
1288
1338
  const col = o.running ? x.green : x.slate;
1289
1339
  const dot2 = o.running ? `${x.green}●${x.reset}` : `${x.slate}◌${x.reset}`;
1290
- return `${dot2} ${col}${x.bold}${o.name}${x.reset} ${x.dim}${ageFmt}${x.reset}`;
1340
+ return `${dot2}${col}${x.bold}${o.name}${x.reset} ${x.dim}${ageFmt}${x.reset}`;
1291
1341
  });
1292
- lines.push(`${x.purple}🏛 ORGS${x.reset} ${orgParts.join(` ${DIV} `)}`);
1342
+ lines.push(`${x.purple}🏛 ORGS${x.reset} ${orgParts.join(` ${DIV} `)}`);
1293
1343
  }
1294
1344
 
1295
1345
  return lines.join('\n');
@@ -658,8 +658,10 @@ function injectGodNodesContext(CWD) {
658
658
  var godStr = godNodes.slice(0, 8).map(function(n) {
659
659
  return n.name + ' (' + n.label + ', ' + n.deg + ' links)';
660
660
  }).join(', ');
661
- console.log('[MONOGRAPH_CONTEXT] ' + nodeCount + ' nodes · ' + edgeCount + ' edges. Key nodes: ' + godStr + staleIndicator);
662
- console.log('[MONOGRAPH_ACTIVE] Indexed knowledge graph available — prefer monograph_query / monograph_suggest over grep/find for symbol and definition lookups.');
661
+ if (String(process.env.MONOMIND_HOOK_QUIET || '') !== '1') {
662
+ console.log('[MONOGRAPH_CONTEXT] ' + nodeCount + ' nodes · ' + edgeCount + ' edges. Key nodes: ' + godStr + staleIndicator);
663
+ console.log('[MONOGRAPH_ACTIVE] Indexed knowledge graph available — prefer monograph_query / monograph_suggest over grep/find for symbol and definition lookups.');
664
+ }
663
665
 
664
666
  // Write god nodes into knowledge/chunks.jsonl so semantic search finds them.
665
667
  var knowledgeDir = path.join(CWD, '.monomind', 'knowledge');
@@ -1 +1 @@
1
- {"version":3,"file":"cap-documents.d.ts","sourceRoot":"","sources":["../../../src/capabilities/cap-documents.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAEhB,SAAS,EAIV,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,cAAc,aAYzB,CAAC;AAMH,wBAAsB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAiClE;AAED,eAAO,MAAM,mBAAmB,EAAE,gBAkGjC,CAAC"}
1
+ {"version":3,"file":"cap-documents.d.ts","sourceRoot":"","sources":["../../../src/capabilities/cap-documents.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAEhB,SAAS,EAIV,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,cAAc,aASzB,CAAC;AA+GH,wBAAsB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CA8HlE;AAED,eAAO,MAAM,mBAAmB,EAAE,gBAsGjC,CAAC"}