monomind 2.1.3 → 2.1.5

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 (27) hide show
  1. package/README.md +18 -17
  2. package/package.json +1 -1
  3. package/packages/@monomind/cli/.claude/commands/mastermind/createorg.md +8 -9
  4. package/packages/@monomind/cli/.claude/helpers/handlers/capture-handler.cjs +32 -15
  5. package/packages/@monomind/cli/.claude/helpers/handlers/gates-handler.cjs +238 -23
  6. package/packages/@monomind/cli/.claude/helpers/handlers/route-handler.cjs +74 -1
  7. package/packages/@monomind/cli/.claude/helpers/hook-handler.cjs +14 -12
  8. package/packages/@monomind/cli/.claude/helpers/router.cjs +12 -2
  9. package/packages/@monomind/cli/.claude/skills/mastermind-skills/createorg.md +91 -701
  10. package/packages/@monomind/cli/.claude/skills/mastermind-skills/org-settings.md +46 -47
  11. package/packages/@monomind/cli/.claude/skills/mastermind-skills/runorg.md +12 -1
  12. package/packages/@monomind/cli/README.md +18 -17
  13. package/packages/@monomind/cli/dist/src/orgrt/daemon.d.ts +18 -0
  14. package/packages/@monomind/cli/dist/src/orgrt/daemon.js +76 -1
  15. package/packages/@monomind/cli/dist/src/orgrt/forwarder.js +7 -3
  16. package/packages/@monomind/cli/dist/src/orgrt/server.js +24 -0
  17. package/packages/@monomind/cli/dist/src/orgrt/session.d.ts +1 -0
  18. package/packages/@monomind/cli/dist/src/orgrt/session.js +8 -0
  19. package/packages/@monomind/cli/dist/src/orgrt/types.d.ts +1 -1
  20. package/packages/@monomind/cli/dist/src/pricing/model-pricing.d.ts +1 -1
  21. package/packages/@monomind/cli/dist/src/ui/collector.mjs +20 -5
  22. package/packages/@monomind/cli/dist/src/ui/dashboard.html +270 -499
  23. package/packages/@monomind/cli/dist/src/ui/orgs-files.js +1 -1
  24. package/packages/@monomind/cli/dist/src/ui/server.mjs +132 -158
  25. package/packages/@monomind/cli/package.json +3 -3
  26. package/packages/@monomind/cli/scripts/publish.sh +6 -0
  27. package/scripts/generate-agent-avatars.mjs +3 -3
@@ -18,6 +18,38 @@
18
18
  const path = require('path');
19
19
  const fs = require('fs');
20
20
 
21
+ // ── Intelligence read-path bridge ───────────────────────────────────────────
22
+ // route-handler.cjs runs as a fresh node subprocess per invocation, but a
23
+ // single process may call handle() more than once (e.g. tests, or a daemon
24
+ // wrapper) — cache the dynamic import of the CLI's compiled intelligence
25
+ // bridge (hooks-embedding.js -> suggestAgentsFromIntelligence) so repeat
26
+ // calls within the same process don't re-resolve/re-import the module.
27
+ // suggestAgentsFromIntelligence() reads the SONA/ReasoningBank embedding
28
+ // store populated by recordMemoryDecision() on every post-task — this is
29
+ // the module that makes stored embedding patterns affect live routing.
30
+ var _intelligenceModPromise = null;
31
+ function _loadIntelligenceModule(CWD) {
32
+ if (!_intelligenceModPromise) {
33
+ _intelligenceModPromise = (async function() {
34
+ var candidates = [
35
+ path.resolve(CWD, 'packages', '@monomind', 'cli', 'dist', 'src', 'mcp-tools', 'hooks-embedding.js'),
36
+ path.resolve(CWD, 'packages', '@monomind', 'cli', 'node_modules', '@monomind', 'cli', 'dist', 'src', 'mcp-tools', 'hooks-embedding.js'),
37
+ ];
38
+ for (var i = 0; i < candidates.length; i++) {
39
+ if (fs.existsSync(candidates[i])) {
40
+ try {
41
+ return await import(candidates[i]);
42
+ } catch (e) {
43
+ return null;
44
+ }
45
+ }
46
+ }
47
+ return null;
48
+ })();
49
+ }
50
+ return _intelligenceModPromise;
51
+ }
52
+
21
53
  module.exports = {
22
54
  handle: async function(hCtx) {
23
55
  var prompt = hCtx.prompt;
@@ -104,7 +136,7 @@ module.exports = {
104
136
  if (erRule.pattern && erRule.pattern.test(prompt)) {
105
137
  result.agent = erRule.routeName || erRule.agentSlug;
106
138
  result.agentSlug = erRule.agentSlug;
107
- result.confidence = 0.90;
139
+ result.confidence = erRule.score != null ? Math.min(0.98, Math.max(0.70, erRule.score)) : 0.85;
108
140
  result.reason = 'Enriched: ' + (erRule.description || erRule.routeName);
109
141
  result.enrichedFrom = 'routing-keyword-pre-filter';
110
142
  break;
@@ -115,6 +147,47 @@ module.exports = {
115
147
  } catch (e) { /* non-fatal — routing package may not be available */ }
116
148
  }
117
149
 
150
+ // ── Intelligence embedding suggestion (SONA/ReasoningBank read path) ──
151
+ // Wires the previously-write-only intelligence system into live routing:
152
+ // suggestAgentsFromIntelligence() runs an embedding similarity search
153
+ // over patterns stored by recordMemoryDecision() on every post-task.
154
+ // This ENHANCES the keyword route — it only overrides when the
155
+ // embedding match is meaningfully more confident, and never blocks or
156
+ // delays routing beyond a 2s budget (fails silently otherwise).
157
+ try {
158
+ var intelResult = await Promise.race([
159
+ (async function() {
160
+ var mod = await _loadIntelligenceModule(CWD);
161
+ if (!mod || !mod.suggestAgentsFromIntelligence) return null;
162
+ return await mod.suggestAgentsFromIntelligence(prompt);
163
+ })(),
164
+ new Promise(function(resolve) { setTimeout(function() { resolve(null); }, 2000); })
165
+ ]);
166
+ if (intelResult && intelResult.agents && intelResult.agents.length > 0) {
167
+ var topIntelAgent = intelResult.agents[0];
168
+ var intelConf = intelResult.confidence != null ? intelResult.confidence : 0;
169
+ result.intelligenceSuggestion = { agents: intelResult.agents, confidence: intelConf };
170
+
171
+ var curAgent = result.agentSlug || result.agent;
172
+ var curConf = result.confidence != null ? result.confidence : 0;
173
+ if (topIntelAgent !== curAgent) {
174
+ // Only override when the embedding match clearly beats the keyword
175
+ // route (0.1 margin) — otherwise just surface it as a signal.
176
+ 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) + ')');
178
+ result.keywordAgent = curAgent;
179
+ result.agent = topIntelAgent;
180
+ result.agentSlug = topIntelAgent;
181
+ result.confidence = intelConf;
182
+ result.reason = 'Intelligence embedding match (SONA/ReasoningBank)' + (result.reason ? '; keyword route was: ' + result.reason : '');
183
+ result.enrichedFrom = 'intelligence-embedding';
184
+ } else {
185
+ console.log('[INTELLIGENCE] Embedding suggestion: ' + topIntelAgent + ' (confidence ' + intelConf.toFixed(2) + ') — kept keyword route ' + curAgent);
186
+ }
187
+ }
188
+ }
189
+ } catch (e) { /* non-fatal — intelligence system unavailable or timed out */ }
190
+
118
191
  // ── Agent success pattern lookup ──────────────────────────
119
192
  try {
120
193
  var patternDb = hCtx._openMonographDb();
@@ -393,15 +393,16 @@ const handlers = {
393
393
  },
394
394
 
395
395
  'pre-bash': async () => {
396
- // SECURITY GATE FIRST — destructive-ops enforcement must never be
397
- // starved by the slower enrichment work below (monograph hint lookups).
398
- // Previously this ran LAST, after up to 10 monograph SQLite strategies,
399
- // AND was fired without awaiting its promise meaning the block
400
- // decision (process.exitCode) could still be unset when the process
401
- // exited under the global 5s safety timer (see main()'s
402
- // `process.exit(0)`), i.e. the gate could fail OPEN under time
403
- // pressure. Awaiting it first guarantees the block/allow decision is
404
- // computed and set before any enrichment work even starts.
396
+ // SECURITY GATE FIRST — destructive-ops + secrets enforcement must never
397
+ // be starved by the slower enrichment work below (monograph hint lookups,
398
+ // monofence-ai scan). Previously this ran LAST, after up to 10 monograph
399
+ // SQLite strategies and a 1.5s monofence budget; under load/slow disk the
400
+ // global 5s safety timer (see main()'s `process.exit(0)`) could fire
401
+ // before the gate ever printed its block decision — i.e. the gate could
402
+ // fail OPEN under time pressure. Computing it first guarantees the
403
+ // block/allow decision (process.exitCode) is set before any enrichment
404
+ // work even starts; enrichment output is still attached afterward if
405
+ // there's time left in the process's lifetime.
405
406
  var gates = require('./handlers/gates-handler.cjs');
406
407
  await gates.handlePreBash(hCtx);
407
408
  if (process.exitCode === 2) return; // blocked — skip enrichment entirely
@@ -661,10 +662,11 @@ const handlers = {
661
662
  }
662
663
  },
663
664
 
664
- 'pre-write': () => {
665
- // Enforcement gate: secrets detection before Write/Edit/MultiEdit lands on disk
665
+ 'pre-write': async () => {
666
+ // Enforcement gate: secrets detection + monofence-ai threat scan before
667
+ // Write/Edit/MultiEdit content lands on disk
666
668
  var gates = require('./handlers/gates-handler.cjs');
667
- gates.handlePreWrite(hCtx);
669
+ await gates.handlePreWrite(hCtx);
668
670
  },
669
671
 
670
672
  'pre-search': () => {
@@ -310,12 +310,22 @@ function routeTask(prompt) {
310
310
  if (slug === 'coder' && hasStrongSkill) continue;
311
311
  var pattern = _ROUTING_PATTERNS[slug];
312
312
  if (pattern && pattern.test(safePrompt)) {
313
- var confidence = applyFeedbackWeight(slug, TASK_CONFIDENCES[slug] || 0.75);
313
+ // Count how many distinct keywords from the pattern actually matched
314
+ // so confidence reflects real match quality, not just a static constant.
315
+ var caps = AGENT_CAPABILITIES[slug] || [];
316
+ var promptLower = safePrompt.toLowerCase();
317
+ var matchedKw = 0;
318
+ for (var ki = 0; ki < caps.length; ki++) {
319
+ if (promptLower.indexOf(caps[ki].toLowerCase()) !== -1) matchedKw++;
320
+ }
321
+ var baseConf = TASK_CONFIDENCES[slug] || 0.75;
322
+ var matchBonus = Math.min(0.10, matchedKw * 0.02);
323
+ var confidence = Math.min(0.98, applyFeedbackWeight(slug, baseConf + matchBonus));
314
324
  return {
315
325
  agent: TASK_AGENTS[slug],
316
326
  agentSlug: slug,
317
327
  confidence: confidence,
318
- reason: ('Keyword match: ' + slug).slice(0, 80),
328
+ reason: ('Keyword match: ' + slug + ' (' + matchedKw + ' kw)').slice(0, 80),
319
329
  semanticRouting: false,
320
330
  specificAgents: [{ slug: slug, name: TASK_AGENTS[slug], confidence: confidence }],
321
331
  skillMatches: skills,