monomind 1.18.15 → 1.19.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.
Files changed (183) hide show
  1. package/.claude/agents/core/researcher.md +29 -24
  2. package/.claude/agents/github/code-review-swarm.md +1 -1
  3. package/.claude/agents/github/github-modes.md +1 -1
  4. package/.claude/agents/github/issue-tracker.md +1 -1
  5. package/.claude/agents/github/multi-repo-swarm.md +1 -1
  6. package/.claude/agents/github/pr-manager.md +1 -1
  7. package/.claude/agents/github/project-board-sync.md +1 -1
  8. package/.claude/agents/github/release-manager.md +1 -1
  9. package/.claude/agents/github/repo-architect.md +1 -1
  10. package/.claude/agents/github/swarm-issue.md +1 -1
  11. package/.claude/agents/github/swarm-pr.md +1 -1
  12. package/.claude/agents/github/sync-coordinator.md +1 -1
  13. package/.claude/agents/github/workflow-automation.md +1 -1
  14. package/.claude/agents/goal/goal-planner.md +1 -1
  15. package/.claude/agents/specialized/specialized-workflow-architect.md +11 -14
  16. package/.claude/agents/testing/production-validator.md +8 -7
  17. package/.claude/agents/testing/testing-evidence-collector.md +3 -1
  18. package/.claude/commands/mastermind/code-review.md +4 -4
  19. package/.claude/commands/mastermind/help.md +2 -2
  20. package/.claude/commands/mastermind/okf-export.md +14 -0
  21. package/.claude/commands/mastermind/okf-import.md +15 -0
  22. package/.claude/helpers/handlers/agent-start-handler.cjs +11 -36
  23. package/.claude/helpers/handlers/capture-handler.cjs +110 -0
  24. package/.claude/helpers/handlers/route-handler.cjs +174 -247
  25. package/.claude/helpers/handlers/session-handler.cjs +139 -142
  26. package/.claude/helpers/handlers/session-restore-handler.cjs +15 -10
  27. package/.claude/helpers/handlers/task-handler.cjs +8 -155
  28. package/.claude/helpers/hook-handler.cjs +89 -5
  29. package/.claude/helpers/intelligence.cjs +164 -15
  30. package/.claude/helpers/learning-service.mjs +1 -0
  31. package/.claude/helpers/mastermind-activate.cjs +33 -51
  32. package/.claude/helpers/monolean-activate.cjs +13 -3
  33. package/.claude/helpers/monolean-propagate.cjs +7 -3
  34. package/.claude/helpers/router.cjs +47 -9
  35. package/.claude/settings.json +0 -20
  36. package/.claude/skills/mastermind-skills/architect.md +5 -6
  37. package/.claude/skills/mastermind-skills/autodev.md +8 -5
  38. package/.claude/skills/mastermind-skills/review.md +8 -5
  39. package/.claude/skills/mastermind-skills/techport.md +37 -3
  40. package/.claude/skills/monodesign/document.md +9 -6
  41. package/.claude/skills/monodesign/extract.md +1 -1
  42. package/.claude/skills/monodesign/reference/document.md +1 -1
  43. package/.claude/skills/monodesign/reference/live.md +1 -1
  44. package/.claude/skills/monolean/SKILL.md +1 -1
  45. package/package.json +1 -1
  46. package/packages/@monomind/cli/.claude/agents/core/researcher.md +29 -24
  47. package/packages/@monomind/cli/.claude/agents/github/code-review-swarm.md +1 -1
  48. package/packages/@monomind/cli/.claude/agents/github/github-modes.md +1 -1
  49. package/packages/@monomind/cli/.claude/agents/github/issue-tracker.md +1 -1
  50. package/packages/@monomind/cli/.claude/agents/github/multi-repo-swarm.md +1 -1
  51. package/packages/@monomind/cli/.claude/agents/github/pr-manager.md +1 -1
  52. package/packages/@monomind/cli/.claude/agents/github/project-board-sync.md +1 -1
  53. package/packages/@monomind/cli/.claude/agents/github/release-manager.md +1 -1
  54. package/packages/@monomind/cli/.claude/agents/github/repo-architect.md +1 -1
  55. package/packages/@monomind/cli/.claude/agents/github/swarm-issue.md +1 -1
  56. package/packages/@monomind/cli/.claude/agents/github/swarm-pr.md +1 -1
  57. package/packages/@monomind/cli/.claude/agents/github/sync-coordinator.md +1 -1
  58. package/packages/@monomind/cli/.claude/agents/github/workflow-automation.md +1 -1
  59. package/packages/@monomind/cli/.claude/agents/goal/goal-planner.md +1 -1
  60. package/packages/@monomind/cli/.claude/agents/specialized/specialized-workflow-architect.md +11 -14
  61. package/packages/@monomind/cli/.claude/agents/testing/production-validator.md +8 -7
  62. package/packages/@monomind/cli/.claude/agents/testing/testing-evidence-collector.md +3 -1
  63. package/packages/@monomind/cli/.claude/commands/mastermind/code-review.md +4 -4
  64. package/packages/@monomind/cli/.claude/commands/mastermind/help.md +2 -2
  65. package/packages/@monomind/cli/.claude/commands/mastermind/okf-export.md +14 -0
  66. package/packages/@monomind/cli/.claude/commands/mastermind/okf-import.md +15 -0
  67. package/packages/@monomind/cli/.claude/helpers/handlers/agent-start-handler.cjs +11 -36
  68. package/packages/@monomind/cli/.claude/helpers/handlers/capture-handler.cjs +110 -0
  69. package/packages/@monomind/cli/.claude/helpers/handlers/route-handler.cjs +174 -247
  70. package/packages/@monomind/cli/.claude/helpers/handlers/session-handler.cjs +139 -142
  71. package/packages/@monomind/cli/.claude/helpers/handlers/session-restore-handler.cjs +15 -10
  72. package/packages/@monomind/cli/.claude/helpers/handlers/task-handler.cjs +8 -155
  73. package/packages/@monomind/cli/.claude/helpers/hook-handler.cjs +89 -5
  74. package/packages/@monomind/cli/.claude/helpers/intelligence.cjs +164 -15
  75. package/packages/@monomind/cli/.claude/helpers/learning-service.mjs +1 -0
  76. package/packages/@monomind/cli/.claude/helpers/mastermind-activate.cjs +33 -51
  77. package/packages/@monomind/cli/.claude/helpers/monolean-activate.cjs +13 -3
  78. package/packages/@monomind/cli/.claude/helpers/monolean-propagate.cjs +7 -3
  79. package/packages/@monomind/cli/.claude/helpers/router.cjs +47 -9
  80. package/packages/@monomind/cli/.claude/skills/mastermind-skills/architect.md +5 -6
  81. package/packages/@monomind/cli/.claude/skills/mastermind-skills/autodev.md +8 -5
  82. package/packages/@monomind/cli/.claude/skills/mastermind-skills/review.md +8 -5
  83. package/packages/@monomind/cli/.claude/skills/mastermind-skills/techport.md +37 -3
  84. package/packages/@monomind/cli/.claude/skills/monodesign/document.md +9 -6
  85. package/packages/@monomind/cli/.claude/skills/monodesign/extract.md +1 -1
  86. package/packages/@monomind/cli/.claude/skills/monodesign/reference/document.md +1 -1
  87. package/packages/@monomind/cli/.claude/skills/monodesign/reference/live.md +1 -1
  88. package/packages/@monomind/cli/.claude/skills/monolean/SKILL.md +1 -1
  89. package/packages/@monomind/cli/bin/mcp-server.js +11 -1
  90. package/packages/@monomind/cli/dist/src/commands/agent-ops.d.ts +1 -2
  91. package/packages/@monomind/cli/dist/src/commands/agent-ops.js +1 -59
  92. package/packages/@monomind/cli/dist/src/commands/agent.js +2 -3
  93. package/packages/@monomind/cli/dist/src/commands/analyze-diff.js +1 -1
  94. package/packages/@monomind/cli/dist/src/commands/browse-action.js +94 -2
  95. package/packages/@monomind/cli/dist/src/commands/completions.js +11 -56
  96. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.d.ts +1 -1
  97. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.js +1 -1
  98. package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.js +2 -2
  99. package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.d.ts +1 -3
  100. package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.js +2 -116
  101. package/packages/@monomind/cli/dist/src/commands/hive-mind.js +2 -5
  102. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.js +8 -7
  103. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.js +1 -1
  104. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.js +2 -2
  105. package/packages/@monomind/cli/dist/src/commands/hooks-extended-commands.d.ts +0 -3
  106. package/packages/@monomind/cli/dist/src/commands/hooks-extended-commands.js +0 -307
  107. package/packages/@monomind/cli/dist/src/commands/hooks.js +1 -12
  108. package/packages/@monomind/cli/dist/src/commands/index.d.ts +3 -51
  109. package/packages/@monomind/cli/dist/src/commands/index.js +36 -184
  110. package/packages/@monomind/cli/dist/src/commands/init-wizard.js +2 -4
  111. package/packages/@monomind/cli/dist/src/commands/mcp.js +32 -4
  112. package/packages/@monomind/cli/dist/src/commands/memory-admin.d.ts +1 -2
  113. package/packages/@monomind/cli/dist/src/commands/memory-admin.js +1 -118
  114. package/packages/@monomind/cli/dist/src/commands/memory-transfer.d.ts +1 -2
  115. package/packages/@monomind/cli/dist/src/commands/memory-transfer.js +5 -171
  116. package/packages/@monomind/cli/dist/src/commands/memory.js +3 -6
  117. package/packages/@monomind/cli/dist/src/commands/neural-core.d.ts +3 -1
  118. package/packages/@monomind/cli/dist/src/commands/neural-core.js +145 -6
  119. package/packages/@monomind/cli/dist/src/commands/neural-optimize.js +4 -4
  120. package/packages/@monomind/cli/dist/src/commands/neural-registry.d.ts +1 -1
  121. package/packages/@monomind/cli/dist/src/commands/neural-registry.js +4 -4
  122. package/packages/@monomind/cli/dist/src/commands/neural.d.ts +1 -1
  123. package/packages/@monomind/cli/dist/src/commands/neural.js +6 -6
  124. package/packages/@monomind/cli/dist/src/commands/performance.js +68 -58
  125. package/packages/@monomind/cli/dist/src/commands/providers.js +2 -131
  126. package/packages/@monomind/cli/dist/src/commands/security-misc.d.ts +0 -1
  127. package/packages/@monomind/cli/dist/src/commands/security-misc.js +69 -45
  128. package/packages/@monomind/cli/dist/src/commands/security.js +2 -4
  129. package/packages/@monomind/cli/dist/src/commands/session.js +1 -285
  130. package/packages/@monomind/cli/dist/src/commands/start.js +2 -41
  131. package/packages/@monomind/cli/dist/src/commands/status.js +18 -29
  132. package/packages/@monomind/cli/dist/src/commands/swarm.js +1 -1
  133. package/packages/@monomind/cli/dist/src/commands/task.js +2 -49
  134. package/packages/@monomind/cli/dist/src/commands/workflow.js +2 -104
  135. package/packages/@monomind/cli/dist/src/index.js +7 -0
  136. package/packages/@monomind/cli/dist/src/init/executor.js +3 -14
  137. package/packages/@monomind/cli/dist/src/init/helpers-generator.js +2 -22
  138. package/packages/@monomind/cli/dist/src/init/settings-generator.js +0 -1
  139. package/packages/@monomind/cli/dist/src/init/types.d.ts +1 -3
  140. package/packages/@monomind/cli/dist/src/init/types.js +0 -2
  141. package/packages/@monomind/cli/dist/src/mcp-client.js +0 -6
  142. package/packages/@monomind/cli/dist/src/mcp-server.js +16 -0
  143. package/packages/@monomind/cli/dist/src/mcp-tools/agent-tools.js +0 -17
  144. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/causal-infer.d.ts +5 -5
  145. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/causal-infer.js +32 -46
  146. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/consensus-verify.d.ts +2 -3
  147. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/consensus-verify.js +22 -20
  148. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/memory-gate.d.ts +3 -2
  149. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/memory-gate.js +32 -19
  150. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/quantum-topology.d.ts +4 -4
  151. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/quantum-topology.js +11 -17
  152. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/spectral-analyze.d.ts +2 -3
  153. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/spectral-analyze.js +51 -32
  154. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/types.d.ts +5 -9
  155. package/packages/@monomind/cli/dist/src/mcp-tools/guidance-tools.js +2 -2
  156. package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.js +25 -3
  157. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-routing.d.ts +0 -3
  158. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-routing.js +45 -159
  159. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.js +1 -4
  160. package/packages/@monomind/cli/dist/src/mcp-tools/index.d.ts +0 -2
  161. package/packages/@monomind/cli/dist/src/mcp-tools/index.js +0 -3
  162. package/packages/@monomind/cli/dist/src/mcp-tools/memory-tools.js +24 -0
  163. package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +428 -11
  164. package/packages/@monomind/cli/dist/src/mcp-tools/neural-tools.d.ts +4 -10
  165. package/packages/@monomind/cli/dist/src/mcp-tools/neural-tools.js +28 -54
  166. package/packages/@monomind/cli/dist/src/mcp-tools/performance-tools.js +5 -17
  167. package/packages/@monomind/cli/dist/src/mcp-tools/quality/coverage-analysis/prioritize-gaps.js +2 -2
  168. package/packages/@monomind/cli/dist/src/mcp-tools/quality/security-compliance/detect-secrets.d.ts +4 -4
  169. package/packages/@monomind/cli/dist/src/mcp-tools/quality-tools.d.ts +7 -2
  170. package/packages/@monomind/cli/dist/src/mcp-tools/quality-tools.js +7 -257
  171. package/packages/@monomind/cli/dist/src/memory/intelligence.d.ts +7 -8
  172. package/packages/@monomind/cli/dist/src/memory/intelligence.js +15 -16
  173. package/packages/@monomind/cli/dist/src/memory/memory-bridge.d.ts +1 -0
  174. package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +37 -0
  175. package/packages/@monomind/cli/dist/src/services/worker-daemon.d.ts +3 -21
  176. package/packages/@monomind/cli/dist/src/services/worker-daemon.js +13 -80
  177. package/packages/@monomind/cli/dist/src/suggest.js +0 -5
  178. package/packages/@monomind/cli/package.json +1 -1
  179. package/packages/@monomind/guidance/package.json +1 -74
  180. package/.claude/helpers/auto-memory-hook.mjs +0 -503
  181. package/packages/@monomind/cli/.claude/helpers/auto-memory-hook.mjs +0 -503
  182. package/packages/@monomind/cli/dist/src/commands/deployment.d.ts +0 -10
  183. package/packages/@monomind/cli/dist/src/commands/deployment.js +0 -706
@@ -7,8 +7,10 @@
7
7
  import { join, resolve, sep } from 'path';
8
8
  import { execSync } from 'child_process';
9
9
  import { statSync } from 'fs';
10
+ import { randomUUID } from 'crypto';
10
11
  import { getProjectCwd } from './types.js';
11
12
  let _cachedDbPath;
13
+ let _cachedCwd;
12
14
  function _isValidDb(p) {
13
15
  try {
14
16
  return statSync(p).size >= 100;
@@ -18,15 +20,19 @@ function _isValidDb(p) {
18
20
  }
19
21
  }
20
22
  function getDbPath() {
21
- if (_cachedDbPath !== undefined)
22
- return _cachedDbPath ?? join(getProjectCwd(), '.monomind', 'monograph.db');
23
- const direct = join(getProjectCwd(), '.monomind', 'monograph.db');
23
+ const cwd = getProjectCwd();
24
+ // Invalidate cache when project root changes (e.g. MONOMIND_CWD set after initialize)
25
+ if (_cachedDbPath && _cachedCwd === cwd)
26
+ return _cachedDbPath;
27
+ _cachedCwd = cwd;
28
+ _cachedDbPath = undefined;
29
+ const direct = join(cwd, '.monomind', 'monograph.db');
24
30
  if (_isValidDb(direct)) {
25
31
  _cachedDbPath = direct;
26
32
  return direct;
27
33
  }
28
34
  try {
29
- const root = execSync('git rev-parse --show-toplevel', { cwd: getProjectCwd(), encoding: 'utf8' }).trim();
35
+ const root = execSync('git rev-parse --show-toplevel', { cwd, encoding: 'utf8' }).trim();
30
36
  const candidate = join(root, '.monomind', 'monograph.db');
31
37
  if (_isValidDb(candidate)) {
32
38
  _cachedDbPath = candidate;
@@ -34,12 +40,53 @@ function getDbPath() {
34
40
  }
35
41
  }
36
42
  catch { /* not in a git repo */ }
37
- _cachedDbPath = null;
43
+ // Don't cache failures — the DB may be created by a subsequent build
38
44
  return direct;
39
45
  }
40
46
  function text(t) {
41
47
  return { content: [{ type: 'text', text: t }] };
42
48
  }
49
+ // ── Active watcher registry ──────────────────────────────────────────────────
50
+ const _activeWatchers = new Map();
51
+ function applyPprRerank(db, seedNodes, damping, maxResults) {
52
+ const propagated = new Map();
53
+ for (const r of seedNodes) {
54
+ propagated.set(r.id, r.score);
55
+ }
56
+ const neighborStmt = db.prepare('SELECT target_id FROM edges WHERE source_id = @id');
57
+ for (const r of seedNodes) {
58
+ const neighbors = neighborStmt.all({ id: r.id });
59
+ for (const n of neighbors) {
60
+ const boost = r.score * damping;
61
+ const current = propagated.get(n.target_id) ?? 0;
62
+ propagated.set(n.target_id, Math.max(current, boost));
63
+ }
64
+ }
65
+ const seedIds = new Set(seedNodes.map(r => r.id));
66
+ const ranked = seedNodes.map(r => ({
67
+ ...r,
68
+ combinedScore: Math.max(r.score, propagated.get(r.id) ?? 0),
69
+ boostedByNeighbors: false,
70
+ }));
71
+ for (const [id, score] of propagated) {
72
+ if (!seedIds.has(id)) {
73
+ const node = db.prepare('SELECT id, name, label, file_path, start_line FROM nodes WHERE id = @id').get({ id });
74
+ if (node) {
75
+ ranked.push({
76
+ id: node.id, name: node.name, label: node.label,
77
+ filePath: node.file_path, startLine: node.start_line,
78
+ score: 0, combinedScore: score, boostedByNeighbors: true,
79
+ });
80
+ }
81
+ }
82
+ }
83
+ ranked.sort((a, b) => b.combinedScore - a.combinedScore);
84
+ return ranked.slice(0, maxResults).map(r => ({
85
+ id: r.id, name: r.name, label: r.label,
86
+ filePath: r.filePath, startLine: r.startLine,
87
+ score: r.combinedScore, boostedByNeighbors: r.boostedByNeighbors,
88
+ }));
89
+ }
43
90
  // ── monograph_build ───────────────────────────────────────────────────────────
44
91
  const monographBuildTool = {
45
92
  name: 'monograph_build',
@@ -78,6 +125,8 @@ const monographQueryTool = {
78
125
  query: { type: 'string', description: 'Search terms' },
79
126
  limit: { type: 'number', description: 'Max results (default 20)' },
80
127
  label: { type: 'string', description: 'Filter by node type: Class, Function, Method, etc.' },
128
+ rerank: { type: 'boolean', description: 'Apply HippoRAG-style PPR graph reranking to boost neighbors of top hits (default: true)' },
129
+ damping: { type: 'number', description: 'PPR damping factor when rerank=true (0-1, default 0.5)' },
81
130
  },
82
131
  required: ['query'],
83
132
  },
@@ -101,19 +150,49 @@ const monographQueryTool = {
101
150
  ? rawQuery.slice(0, MAX_MONOGRAPH_QUERY_LEN)
102
151
  : rawQuery;
103
152
  const label = input.label;
153
+ const rerank = input.rerank ?? true;
154
+ const damping = input.damping ?? 0.5;
104
155
  if (process.env['MONOGRAPH_EMBEDDINGS'] === 'true') {
105
- const results = await hybridQuery(db, query, { limit, label });
156
+ const results = await hybridQuery(db, query, { limit: rerank ? limit * 2 : limit, label });
106
157
  if (results.length === 0)
107
158
  return text('No results found.');
159
+ if (rerank) {
160
+ const seeds = results.map(r => ({
161
+ id: r.id, name: r.name ?? r.id, label: r.label ?? '?',
162
+ filePath: r.filePath ?? '', startLine: r.startLine ?? null,
163
+ score: r.score,
164
+ }));
165
+ const reranked = applyPprRerank(db, seeds, damping, limit);
166
+ const lines = reranked.map(r => {
167
+ const loc = r.filePath ? (r.startLine != null ? `${r.filePath}:${r.startLine}` : r.filePath) : '';
168
+ const tag = r.boostedByNeighbors ? ' [PPR-boosted]' : '';
169
+ return `[${r.label}] ${r.name} ${loc} (score: ${r.score.toFixed(4)})${tag}`;
170
+ });
171
+ return text(lines.join('\n'));
172
+ }
108
173
  const lines = results.map(r => {
109
174
  const loc = r.filePath ? (r.startLine != null ? `${r.filePath}:${r.startLine}` : r.filePath) : '';
110
175
  return `[${r.label ?? '?'}] ${r.name ?? r.id} ${loc} (score: ${r.score.toFixed(4)})`;
111
176
  });
112
177
  return text(lines.join('\n'));
113
178
  }
114
- const results = ftsSearch(db, query, limit, label);
179
+ const results = ftsSearch(db, query, rerank ? limit * 2 : limit, label);
115
180
  if (results.length === 0)
116
181
  return text('No results found.');
182
+ if (rerank) {
183
+ const seeds = results.map(r => ({
184
+ id: r.id, name: r.name, label: r.label,
185
+ filePath: r.filePath ?? '', startLine: r.startLine ?? null,
186
+ score: Math.abs(r.rank),
187
+ }));
188
+ const reranked = applyPprRerank(db, seeds, damping, limit);
189
+ const lines = reranked.map(r => {
190
+ const loc = r.filePath ? (r.startLine != null ? `${r.filePath}:${r.startLine}` : r.filePath) : '';
191
+ const tag = r.boostedByNeighbors ? ' [PPR-boosted]' : '';
192
+ return `[${r.label}] ${r.name} ${loc} (score: ${r.score.toFixed(3)})${tag}`;
193
+ });
194
+ return text(lines.join('\n'));
195
+ }
117
196
  const lines = results.map(r => {
118
197
  const loc = r.filePath ? (r.startLine != null ? `${r.filePath}:${r.startLine}` : r.filePath) : '';
119
198
  return `[${r.label}] ${r.name} ${loc} (score: ${r.rank.toFixed(3)})`;
@@ -521,11 +600,15 @@ const monographWatchTool = {
521
600
  handler: async (input) => {
522
601
  const { MonographWatcher } = await import('@monoes/monograph');
523
602
  const repoPath = input.path ?? getProjectCwd();
603
+ if (_activeWatchers.has(repoPath)) {
604
+ return text(`Monograph watcher already running for ${repoPath}.`);
605
+ }
524
606
  const watcher = new MonographWatcher(repoPath);
525
607
  watcher.on('monograph:updated', (_paths) => {
526
608
  import('@monoes/monograph').then(({ buildAsync }) => buildAsync(repoPath)).catch(() => { });
527
609
  });
528
610
  await watcher.start();
611
+ _activeWatchers.set(repoPath, watcher);
529
612
  return text(`Monograph watcher started for ${repoPath}. Watching for file changes...`);
530
613
  },
531
614
  };
@@ -533,9 +616,21 @@ const monographWatchTool = {
533
616
  const monographWatchStopTool = {
534
617
  name: 'monograph_watch_stop',
535
618
  description: 'Stop the Monograph file watcher.',
536
- inputSchema: { type: 'object', properties: {} },
537
- handler: async () => {
538
- return text('Watcher stop requested. (Restart MCP server to fully clear watchers.)');
619
+ inputSchema: {
620
+ type: 'object',
621
+ properties: {
622
+ path: { type: 'string', description: 'Repo path whose watcher to stop (defaults to project cwd)' },
623
+ },
624
+ },
625
+ handler: async (input) => {
626
+ const repoPath = input.path ?? getProjectCwd();
627
+ const watcher = _activeWatchers.get(repoPath);
628
+ if (!watcher) {
629
+ return text(`No active watcher found for ${repoPath}.`);
630
+ }
631
+ await watcher.stop();
632
+ _activeWatchers.delete(repoPath);
633
+ return text(`Monograph watcher stopped for ${repoPath}.`);
539
634
  },
540
635
  };
541
636
  // ── monograph_report ──────────────────────────────────────────────────────────
@@ -799,7 +894,7 @@ const monographExportTool = {
799
894
  required: ['format'],
800
895
  },
801
896
  handler: async (input) => {
802
- const { openDb, closeDb, toJson, toSvg, toGraphml, toCypher } = await import('@monoes/monograph');
897
+ const { openDb, closeDb, toJson, toSvg, toGraphml, toCypher, toObsidian, toCanvas } = await import('@monoes/monograph');
803
898
  const { writeFileSync, mkdirSync } = await import('fs');
804
899
  const db = openDb(getDbPath());
805
900
  try {
@@ -833,6 +928,15 @@ const monographExportTool = {
833
928
  writeFileSync(p, toCypher(nodes, edges));
834
929
  return text(`Exported Cypher to ${p}`);
835
930
  }
931
+ if (fmt === 'obsidian') {
932
+ toObsidian(nodes, edges, outDir);
933
+ return text(`Exported Obsidian vault to ${outDir}`);
934
+ }
935
+ if (fmt === 'canvas') {
936
+ const p = join(outDir, 'graph.canvas');
937
+ writeFileSync(p, toCanvas(nodes, edges));
938
+ return text(`Exported Canvas to ${p}`);
939
+ }
836
940
  return text(`Format ${fmt} export written to ${outDir}`);
837
941
  }
838
942
  finally {
@@ -2048,6 +2152,313 @@ function findStaleDist(repoPath) {
2048
2152
  findings,
2049
2153
  };
2050
2154
  }
2155
+ // ── monograph_agent_history ───────────────────────────────────────────────────
2156
+ const monographAgentHistoryTool = {
2157
+ name: 'monograph_agent_history',
2158
+ description: 'Query past agent interactions by org, type, session, or time range. Returns rows ordered by timestamp descending.',
2159
+ inputSchema: {
2160
+ type: 'object',
2161
+ properties: {
2162
+ org_name: { type: 'string', description: 'Filter by org name' },
2163
+ agent_type: { type: 'string', description: 'Filter by agent type' },
2164
+ session_id: { type: 'string', description: 'Filter by session id' },
2165
+ since: { type: 'number', description: 'Unix timestamp (ms) — only interactions after this time' },
2166
+ limit: { type: 'number', description: 'Max rows to return (default 50)' },
2167
+ },
2168
+ },
2169
+ handler: async (input) => {
2170
+ const { openDb, closeDb } = await import('@monoes/monograph');
2171
+ const db = openDb(getDbPath());
2172
+ try {
2173
+ const conditions = [];
2174
+ const params = {};
2175
+ if (typeof input.org_name === 'string') {
2176
+ conditions.push('org_name = @org_name');
2177
+ params.org_name = input.org_name;
2178
+ }
2179
+ if (typeof input.agent_type === 'string') {
2180
+ conditions.push('agent_type = @agent_type');
2181
+ params.agent_type = input.agent_type;
2182
+ }
2183
+ if (typeof input.session_id === 'string') {
2184
+ conditions.push('session_id = @session_id');
2185
+ params.session_id = input.session_id;
2186
+ }
2187
+ if (typeof input.since === 'number') {
2188
+ conditions.push('timestamp >= @since');
2189
+ params.since = input.since;
2190
+ }
2191
+ const MAX_LIMIT = 1_000;
2192
+ const rawLimit = input.limit ?? 50;
2193
+ const limit = Number.isFinite(rawLimit) && rawLimit > 0
2194
+ ? Math.min(Math.floor(rawLimit), MAX_LIMIT)
2195
+ : 50;
2196
+ params.limit = limit;
2197
+ const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
2198
+ const sql = `SELECT * FROM agent_interactions ${where} ORDER BY timestamp DESC LIMIT @limit`;
2199
+ const rows = db.prepare(sql).all(params);
2200
+ if (rows.length === 0)
2201
+ return text('No agent interactions found.');
2202
+ return text(JSON.stringify(rows, null, 2));
2203
+ }
2204
+ finally {
2205
+ closeDb(db);
2206
+ }
2207
+ },
2208
+ };
2209
+ // ── monograph_agent_patterns ──────────────────────────────────────────────────
2210
+ const monographAgentPatternsTool = {
2211
+ name: 'monograph_agent_patterns',
2212
+ description: 'Aggregate agent interaction patterns: success rates, costs, and token usage grouped by agent type, org, or session.',
2213
+ inputSchema: {
2214
+ type: 'object',
2215
+ properties: {
2216
+ group_by: {
2217
+ type: 'string',
2218
+ description: "Column to group by: 'agent_type' | 'org_name' | 'session_id'",
2219
+ },
2220
+ since: { type: 'number', description: 'Unix timestamp (ms) — only interactions after this time' },
2221
+ min_count: { type: 'number', description: 'Minimum interaction count to include in results (default 2)' },
2222
+ },
2223
+ required: ['group_by'],
2224
+ },
2225
+ handler: async (input) => {
2226
+ const groupBy = input.group_by;
2227
+ const ALLOWED_GROUP_COLUMNS = new Set(['agent_type', 'org_name', 'session_id']);
2228
+ if (!ALLOWED_GROUP_COLUMNS.has(groupBy)) {
2229
+ return text(`Invalid group_by: ${groupBy}. Must be one of: agent_type, org_name, session_id`);
2230
+ }
2231
+ const { openDb, closeDb } = await import('@monoes/monograph');
2232
+ const db = openDb(getDbPath());
2233
+ try {
2234
+ const params = {};
2235
+ const conditions = [];
2236
+ if (typeof input.since === 'number') {
2237
+ conditions.push('timestamp >= @since');
2238
+ params.since = input.since;
2239
+ }
2240
+ const minCount = typeof input.min_count === 'number' && input.min_count > 0
2241
+ ? Math.floor(input.min_count)
2242
+ : 2;
2243
+ params.min_count = minCount;
2244
+ const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
2245
+ const sql = `
2246
+ SELECT
2247
+ ${groupBy} AS group_key,
2248
+ COUNT(*) AS interaction_count,
2249
+ AVG(success) AS success_rate,
2250
+ SUM(tokens_in) AS total_tokens_in,
2251
+ SUM(tokens_out) AS total_tokens_out,
2252
+ SUM(cost_usd) AS total_cost_usd,
2253
+ AVG(duration_ms) AS avg_duration_ms
2254
+ FROM agent_interactions
2255
+ ${where}
2256
+ GROUP BY ${groupBy}
2257
+ HAVING COUNT(*) >= @min_count
2258
+ ORDER BY interaction_count DESC
2259
+ `;
2260
+ const rows = db.prepare(sql).all(params);
2261
+ if (rows.length === 0)
2262
+ return text('No agent interaction patterns found.');
2263
+ return text(JSON.stringify(rows, null, 2));
2264
+ }
2265
+ finally {
2266
+ closeDb(db);
2267
+ }
2268
+ },
2269
+ };
2270
+ // ── monograph_agent_record ────────────────────────────────────────────────────
2271
+ const monographAgentRecordTool = {
2272
+ name: 'monograph_agent_record',
2273
+ description: 'Record an agent interaction (called by capture hooks).',
2274
+ inputSchema: {
2275
+ type: 'object',
2276
+ properties: {
2277
+ session_id: { type: 'string', description: 'Session id' },
2278
+ agent_type: { type: 'string', description: 'Agent type' },
2279
+ org_name: { type: 'string', description: 'Org name' },
2280
+ parent_agent: { type: 'string', description: 'Parent agent name/type, if spawned by another agent' },
2281
+ prompt_summary: { type: 'string', description: 'Short summary of the prompt given to the agent' },
2282
+ result_summary: { type: 'string', description: 'Short summary of the agent result' },
2283
+ tokens_in: { type: 'number', description: 'Input tokens consumed (default 0)' },
2284
+ tokens_out: { type: 'number', description: 'Output tokens produced (default 0)' },
2285
+ cost_usd: { type: 'number', description: 'Cost in USD (default 0)' },
2286
+ success: { type: 'boolean', description: 'Whether the interaction succeeded (default true)' },
2287
+ duration_ms: { type: 'number', description: 'Duration in milliseconds (default 0)' },
2288
+ },
2289
+ required: ['session_id', 'agent_type'],
2290
+ },
2291
+ handler: async (input) => {
2292
+ const { openDb, closeDb } = await import('@monoes/monograph');
2293
+ const db = openDb(getDbPath());
2294
+ try {
2295
+ const id = randomUUID();
2296
+ const timestamp = Date.now();
2297
+ db.prepare(`
2298
+ INSERT INTO agent_interactions (
2299
+ id, session_id, org_name, agent_type, parent_agent,
2300
+ prompt_summary, result_summary, tokens_in, tokens_out,
2301
+ cost_usd, success, duration_ms, timestamp
2302
+ ) VALUES (
2303
+ @id, @session_id, @org_name, @agent_type, @parent_agent,
2304
+ @prompt_summary, @result_summary, @tokens_in, @tokens_out,
2305
+ @cost_usd, @success, @duration_ms, @timestamp
2306
+ )
2307
+ `).run({
2308
+ id,
2309
+ session_id: input.session_id,
2310
+ org_name: input.org_name ?? null,
2311
+ agent_type: input.agent_type,
2312
+ parent_agent: input.parent_agent ?? null,
2313
+ prompt_summary: input.prompt_summary ?? null,
2314
+ result_summary: input.result_summary ?? null,
2315
+ tokens_in: input.tokens_in ?? 0,
2316
+ tokens_out: input.tokens_out ?? 0,
2317
+ cost_usd: input.cost_usd ?? 0,
2318
+ success: input.success === false ? 0 : 1,
2319
+ duration_ms: input.duration_ms ?? 0,
2320
+ timestamp,
2321
+ });
2322
+ return text(`Recorded agent interaction ${id} for ${input.agent_type} at ${timestamp}`);
2323
+ }
2324
+ finally {
2325
+ closeDb(db);
2326
+ }
2327
+ },
2328
+ };
2329
+ // ── monograph_rank_with_graph (ported from MemoryGraph) ──────────────────────
2330
+ const monographRankWithGraphTool = {
2331
+ name: 'monograph_rank_with_graph',
2332
+ description: 'Blend BM25/vector search scores with PageRank for graph-aware ranking. Ported from MemoryGraph.rankWithGraph (HippoRAG-inspired).',
2333
+ inputSchema: {
2334
+ type: 'object',
2335
+ properties: {
2336
+ query: { type: 'string', description: 'Search query to run through monograph_query first' },
2337
+ alpha: { type: 'number', description: 'Weight for search score vs PageRank (0-1, default 0.7 = 70% search, 30% PageRank)' },
2338
+ limit: { type: 'number', description: 'Max results (default 20)' },
2339
+ },
2340
+ required: ['query'],
2341
+ },
2342
+ handler: async (input) => {
2343
+ const { openDb, closeDb, pageRank } = await import('@monoes/monograph');
2344
+ const db = openDb(getDbPath());
2345
+ try {
2346
+ const alpha = input.alpha ?? 0.7;
2347
+ const limit = input.limit ?? 20;
2348
+ const query = input.query;
2349
+ const searchResults = db.prepare(`
2350
+ SELECT n.id, n.name, n.label, n.file_path, n.start_line, n.community_id,
2351
+ bm25(nodes_fts) AS score
2352
+ FROM nodes_fts
2353
+ JOIN nodes n ON n.id = nodes_fts.rowid
2354
+ WHERE nodes_fts MATCH @query
2355
+ ORDER BY bm25(nodes_fts)
2356
+ LIMIT @limit
2357
+ `).all({ query, limit: limit * 2 });
2358
+ if (searchResults.length === 0)
2359
+ return text('No results found.');
2360
+ const ranks = pageRank(db);
2361
+ const N = ranks.size || 1;
2362
+ const ranked = searchResults.map(r => {
2363
+ const pr = ranks.get(r.id) ?? 0;
2364
+ return {
2365
+ ...r,
2366
+ pageRank: pr,
2367
+ combinedScore: alpha * Math.abs(r.score) + (1 - alpha) * (pr * N),
2368
+ };
2369
+ }).sort((a, b) => b.combinedScore - a.combinedScore).slice(0, limit);
2370
+ return text(JSON.stringify(ranked, null, 2));
2371
+ }
2372
+ finally {
2373
+ closeDb(db);
2374
+ }
2375
+ },
2376
+ };
2377
+ // ── monograph_community_summaries (ported from MemoryGraph) ──────────────────
2378
+ const monographCommunitySummariesTool = {
2379
+ name: 'monograph_community_summaries',
2380
+ description: 'GraphRAG-style community summaries: top-K communities by average PageRank with member counts and top nodes. Ported from MemoryGraph.getCommunitySummaries.',
2381
+ inputSchema: {
2382
+ type: 'object',
2383
+ properties: {
2384
+ top_k: { type: 'number', description: 'Number of top communities to return (default 5)' },
2385
+ },
2386
+ },
2387
+ handler: async (input) => {
2388
+ const { openDb, closeDb, pageRank } = await import('@monoes/monograph');
2389
+ const db = openDb(getDbPath());
2390
+ try {
2391
+ const topK = input.top_k ?? 5;
2392
+ const ranks = pageRank(db);
2393
+ const rows = db.prepare(`SELECT id, community_id FROM nodes WHERE community_id IS NOT NULL`).all();
2394
+ const communityMap = new Map();
2395
+ for (const row of rows) {
2396
+ const rank = ranks.get(row.id) ?? 0;
2397
+ const entry = communityMap.get(row.community_id) ?? { nodeIds: [], rankSum: 0 };
2398
+ entry.nodeIds.push(row.id);
2399
+ entry.rankSum += rank;
2400
+ communityMap.set(row.community_id, entry);
2401
+ }
2402
+ const summaries = [...communityMap.entries()]
2403
+ .map(([communityId, { nodeIds, rankSum }]) => ({
2404
+ communityId,
2405
+ nodeCount: nodeIds.length,
2406
+ topNodeIds: nodeIds.slice(0, 3),
2407
+ avgPageRank: nodeIds.length > 0 ? rankSum / nodeIds.length : 0,
2408
+ }))
2409
+ .sort((a, b) => b.avgPageRank - a.avgPageRank)
2410
+ .slice(0, topK);
2411
+ return text(JSON.stringify(summaries, null, 2));
2412
+ }
2413
+ finally {
2414
+ closeDb(db);
2415
+ }
2416
+ },
2417
+ };
2418
+ // ── monograph_ppr_rerank (ported from MemoryGraph) ───────────────────────────
2419
+ const monographPprRerankTool = {
2420
+ name: 'monograph_ppr_rerank',
2421
+ description: 'HippoRAG-style PPR re-ranking: search, then expand one hop through edges and boost neighbor scores. Ported from MemoryGraph.pprRerank (arXiv:2405.14831).',
2422
+ inputSchema: {
2423
+ type: 'object',
2424
+ properties: {
2425
+ query: { type: 'string', description: 'Search query' },
2426
+ damping: { type: 'number', description: 'Score propagation damping factor (default 0.5)' },
2427
+ limit: { type: 'number', description: 'Max results (default 20)' },
2428
+ },
2429
+ required: ['query'],
2430
+ },
2431
+ handler: async (input) => {
2432
+ const { openDb, closeDb } = await import('@monoes/monograph');
2433
+ const db = openDb(getDbPath());
2434
+ try {
2435
+ const damping = input.damping ?? 0.5;
2436
+ const limit = input.limit ?? 20;
2437
+ const query = input.query;
2438
+ const searchResults = db.prepare(`
2439
+ SELECT n.id, n.name, n.label, n.file_path, n.start_line,
2440
+ bm25(nodes_fts) AS score
2441
+ FROM nodes_fts
2442
+ JOIN nodes n ON n.id = nodes_fts.rowid
2443
+ WHERE nodes_fts MATCH @query
2444
+ ORDER BY bm25(nodes_fts)
2445
+ LIMIT @limit
2446
+ `).all({ query, limit: limit * 2 });
2447
+ if (searchResults.length === 0)
2448
+ return text('No results found.');
2449
+ const seeds = searchResults.map(r => ({
2450
+ id: r.id, name: r.name, label: r.label,
2451
+ filePath: r.file_path, startLine: r.start_line ?? null,
2452
+ score: Math.abs(r.score),
2453
+ }));
2454
+ const reranked = applyPprRerank(db, seeds, damping, limit);
2455
+ return text(JSON.stringify(reranked, null, 2));
2456
+ }
2457
+ finally {
2458
+ closeDb(db);
2459
+ }
2460
+ },
2461
+ };
2051
2462
  export const monographTools = [
2052
2463
  monographBuildTool,
2053
2464
  monographQueryTool,
@@ -2094,5 +2505,11 @@ export const monographTools = [
2094
2505
  monographGroupContractsTool,
2095
2506
  monographGroupStatusTool,
2096
2507
  monographDeadCodeTool,
2508
+ monographAgentHistoryTool,
2509
+ monographAgentPatternsTool,
2510
+ monographAgentRecordTool,
2511
+ monographRankWithGraphTool,
2512
+ monographCommunitySummariesTool,
2513
+ monographPprRerankTool,
2097
2514
  ];
2098
2515
  //# sourceMappingURL=monograph-tools.js.map
@@ -1,15 +1,9 @@
1
1
  /**
2
- * Neural MCP Tools for CLI
2
+ * Pattern Store MCP Tools
3
3
  *
4
- * V2 Compatibility - Neural network and ML tools
5
- *
6
- * HYBRID Implementation:
7
- * - Uses monovector ONNX embeddings when available
8
- * - Falls back to deterministic hash-based embeddings otherwise
9
- * - Pattern storage and search with cosine similarity (real math in all tiers)
10
- * - Training stores patterns as searchable embeddings (not simulated)
11
- *
12
- * Note: The lean build has no neural training. The full loop lives on monoes-full-loop.
4
+ * Embed text as vectors, store patterns, search by cosine similarity.
5
+ * Uses monovector ONNX embeddings when available, deterministic hash fallback otherwise.
6
+ * Tools are registered under the "neural" namespace for backwards compatibility.
13
7
  */
14
8
  import { type MCPTool } from './types.js';
15
9
  export declare const neuralTools: MCPTool[];