@monoes/monomindcli 1.10.29 → 1.10.30

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 (80) hide show
  1. package/.claude/helpers/auto-memory-hook.mjs +39 -4
  2. package/.claude/helpers/handlers/edit-handler.cjs +145 -0
  3. package/.claude/helpers/handlers/route-handler.cjs +393 -0
  4. package/.claude/helpers/handlers/session-handler.cjs +167 -0
  5. package/.claude/helpers/handlers/session-restore-handler.cjs +343 -0
  6. package/.claude/helpers/handlers/task-handler.cjs +329 -0
  7. package/.claude/helpers/hook-handler.cjs +114 -2273
  8. package/.claude/helpers/intelligence.cjs +21 -2
  9. package/.claude/helpers/learning-service.mjs +166 -8
  10. package/.claude/helpers/memory-palace.cjs +72 -12
  11. package/.claude/helpers/router.cjs +79 -5
  12. package/.claude/helpers/statusline.cjs +193 -399
  13. package/.claude/helpers/utils/micro-agents.cjs +338 -0
  14. package/.claude/helpers/utils/monograph.cjs +349 -0
  15. package/.claude/helpers/utils/telemetry.cjs +144 -0
  16. package/.claude/skills/agent-browser-testing/SKILL.md +3 -2
  17. package/.claude/skills/monomind/browse-agentcore.md +116 -0
  18. package/.claude/skills/monomind/browse-electron.md +189 -0
  19. package/.claude/skills/monomind/browse-qa.md +229 -0
  20. package/.claude/skills/monomind/browse-references/authentication.md +162 -0
  21. package/.claude/skills/monomind/browse-references/trust-boundaries.md +41 -0
  22. package/.claude/skills/monomind/browse-references/video-recording.md +84 -0
  23. package/.claude/skills/monomind/browse-slack.md +189 -0
  24. package/.claude/skills/monomind/browse-vercel.md +240 -0
  25. package/.claude/skills/monomind/browse.md +724 -0
  26. package/dist/src/browser/actions.d.ts +13 -0
  27. package/dist/src/browser/actions.d.ts.map +1 -0
  28. package/dist/src/browser/actions.js +201 -0
  29. package/dist/src/browser/actions.js.map +1 -0
  30. package/dist/src/browser/browser.d.ts +14 -0
  31. package/dist/src/browser/browser.d.ts.map +1 -0
  32. package/dist/src/browser/browser.js +198 -0
  33. package/dist/src/browser/browser.js.map +1 -0
  34. package/dist/src/browser/cdp.d.ts +17 -0
  35. package/dist/src/browser/cdp.d.ts.map +1 -0
  36. package/dist/src/browser/cdp.js +106 -0
  37. package/dist/src/browser/cdp.js.map +1 -0
  38. package/dist/src/browser/index.d.ts +11 -0
  39. package/dist/src/browser/index.d.ts.map +1 -0
  40. package/dist/src/browser/index.js +11 -0
  41. package/dist/src/browser/index.js.map +1 -0
  42. package/dist/src/browser/network.d.ts +11 -0
  43. package/dist/src/browser/network.d.ts.map +1 -0
  44. package/dist/src/browser/network.js +81 -0
  45. package/dist/src/browser/network.js.map +1 -0
  46. package/dist/src/browser/screenshot.d.ts +15 -0
  47. package/dist/src/browser/screenshot.d.ts.map +1 -0
  48. package/dist/src/browser/screenshot.js +36 -0
  49. package/dist/src/browser/screenshot.js.map +1 -0
  50. package/dist/src/browser/session.d.ts +8 -0
  51. package/dist/src/browser/session.d.ts.map +1 -0
  52. package/dist/src/browser/session.js +50 -0
  53. package/dist/src/browser/session.js.map +1 -0
  54. package/dist/src/browser/snapshot.d.ts +12 -0
  55. package/dist/src/browser/snapshot.d.ts.map +1 -0
  56. package/dist/src/browser/snapshot.js +147 -0
  57. package/dist/src/browser/snapshot.js.map +1 -0
  58. package/dist/src/browser/tabs.d.ts +8 -0
  59. package/dist/src/browser/tabs.d.ts.map +1 -0
  60. package/dist/src/browser/tabs.js +25 -0
  61. package/dist/src/browser/tabs.js.map +1 -0
  62. package/dist/src/browser/types.d.ts +109 -0
  63. package/dist/src/browser/types.d.ts.map +1 -0
  64. package/dist/src/browser/types.js +16 -0
  65. package/dist/src/browser/types.js.map +1 -0
  66. package/dist/src/browser/wait.d.ts +4 -0
  67. package/dist/src/browser/wait.d.ts.map +1 -0
  68. package/dist/src/browser/wait.js +122 -0
  69. package/dist/src/browser/wait.js.map +1 -0
  70. package/dist/src/commands/browse.d.ts +8 -0
  71. package/dist/src/commands/browse.d.ts.map +1 -0
  72. package/dist/src/commands/browse.js +573 -0
  73. package/dist/src/commands/browse.js.map +1 -0
  74. package/dist/src/commands/index.d.ts.map +1 -1
  75. package/dist/src/commands/index.js +2 -0
  76. package/dist/src/commands/index.js.map +1 -1
  77. package/dist/src/ui/dashboard-v2.html +1692 -0
  78. package/dist/src/ui/server.mjs +15 -1
  79. package/dist/tsconfig.tsbuildinfo +1 -1
  80. package/package.json +2 -1
@@ -0,0 +1,167 @@
1
+ 'use strict';
2
+ // Extracted from hook-handler.cjs — receives hCtx from dispatcher.
3
+ // Handles 'session-end' hook event.
4
+ // See route-handler.cjs for full hCtx field documentation.
5
+
6
+ const path = require('path');
7
+ const fs = require('fs');
8
+
9
+ module.exports = {
10
+ handleEnd: async function(hCtx) {
11
+ var hookInput = hCtx.hookInput;
12
+ var intelligence = hCtx.intelligence;
13
+ var session = hCtx.session;
14
+ var CWD = hCtx.CWD;
15
+
16
+ // Check if daemon is holding the consolidation lock — if so, skip synchronous consolidation
17
+ // to avoid duplicate work and potential index corruption
18
+ var consolidationLockPath = path.join(CWD, '.monomind', 'consolidation.lock');
19
+ var daemonHoldsLock = fs.existsSync(consolidationLockPath);
20
+
21
+ if (daemonHoldsLock) {
22
+ console.log('[SESSION] Skipping consolidation — daemon holds lock');
23
+ }
24
+
25
+ // Consolidate intelligence (with timeout — #1530)
26
+ if (!daemonHoldsLock && intelligence && intelligence.consolidate) {
27
+ var consResult = await hCtx.runWithTimeout(function() { return intelligence.consolidate(); }, 'intelligence.consolidate()');
28
+ if (consResult && consResult.entries > 0) {
29
+ var msg = '[INTELLIGENCE] Consolidated: ' + consResult.entries + ' entries, ' + consResult.edges + ' edges';
30
+ if (consResult.newEntries > 0) msg += ', ' + consResult.newEntries + ' new';
31
+ msg += ', PageRank recomputed';
32
+ console.log(msg);
33
+ }
34
+ }
35
+ try {
36
+ if (session && session.end) {
37
+ session.end();
38
+ } else {
39
+ console.log('[OK] Session ended');
40
+ }
41
+ } catch (e) { console.log('[WARN] Session end failed: ' + e.message); }
42
+
43
+ // ── Routing Feedback Loop (SE-001) ────────────────────────────────────
44
+ // Persist routing accuracy feedback so the router improves over sessions.
45
+ // sessionSuccess is derived from intelligence-outcomes.jsonl entries written
46
+ // during this session (last 30 minutes). A session is marked failed when the
47
+ // majority of feedback() calls carried success=false in that window.
48
+ try {
49
+ var feedbackPath = path.join(CWD, '.monomind', 'routing-feedback.jsonl');
50
+ var lastRoutePath = path.join(CWD, '.monomind', 'last-route.json');
51
+ if (fs.existsSync(lastRoutePath)) {
52
+ var lastRoute = JSON.parse(fs.readFileSync(lastRoutePath, 'utf-8'));
53
+
54
+ // Derive sessionSuccess from intelligence-outcomes.jsonl
55
+ var sessionSuccess = true; // optimistic default when no signal exists
56
+ try {
57
+ var outcomesPath = path.join(CWD, '.monomind', 'intelligence-outcomes.jsonl');
58
+ if (fs.existsSync(outcomesPath)) {
59
+ var windowMs = 30 * 60 * 1000; // 30-minute session window
60
+ var cutoff = Date.now() - windowMs;
61
+ var outcomeLines = fs.readFileSync(outcomesPath, 'utf-8').trim().split('\n').filter(Boolean);
62
+ var recent = outcomeLines.map(function(l) {
63
+ try { return JSON.parse(l); } catch { return null; }
64
+ }).filter(function(e) { return e && e.ts && e.ts >= cutoff; });
65
+ if (recent.length > 0) {
66
+ var failures = recent.filter(function(e) { return e.success === false; }).length;
67
+ // Majority-vote: session fails only if more than half the recent signals are failures
68
+ sessionSuccess = failures / recent.length < 0.5;
69
+ }
70
+ }
71
+ } catch (e) { /* non-critical — keep optimistic default */ }
72
+
73
+ if (intelligence && intelligence.feedback) {
74
+ try { intelligence.feedback(sessionSuccess); } catch (e) { /* non-fatal */ }
75
+ }
76
+ var feedbackEntry = {
77
+ timestamp: new Date().toISOString(),
78
+ suggestedAgent: lastRoute.agent,
79
+ confidence: lastRoute.confidence,
80
+ sessionId: hookInput.sessionId || hookInput.session_id || '',
81
+ intelligenceFeedback: sessionSuccess,
82
+ };
83
+ fs.appendFileSync(feedbackPath, JSON.stringify(feedbackEntry) + '\n', 'utf-8');
84
+ // Rotate: keep last 1000 lines to prevent unbounded growth
85
+ try {
86
+ var raw = fs.readFileSync(feedbackPath, 'utf-8');
87
+ var lines = raw.split('\n').filter(Boolean);
88
+ if (lines.length > 1000) {
89
+ fs.writeFileSync(feedbackPath, lines.slice(-1000).join('\n') + '\n', 'utf-8');
90
+ }
91
+ } catch (e2) { /* rotation is best-effort */ }
92
+ }
93
+ } catch (e) { /* non-fatal */ }
94
+
95
+ // Memory Palace tombstone writes removed — redundant with raw session JSONL
96
+
97
+ // ── Learning Service Auto-Consolidation ─────────────────────────────
98
+ // Consolidate learned patterns from short-term to long-term storage.
99
+ // Uses module-level singleton (getLearningService) so the DB is not
100
+ // reopened on every session-end — state accumulated during the session
101
+ // is preserved and consolidated in a single pass.
102
+ if (!daemonHoldsLock) {
103
+ try {
104
+ var ls = await hCtx.getLearningService();
105
+ if (ls && ls.consolidate) {
106
+ var lResult = await hCtx.runWithTimeout(function() { return ls.consolidate(); }, 'learning.consolidate()');
107
+ if (lResult && lResult.promoted > 0) {
108
+ console.log('[LEARNING] Consolidated: ' + lResult.promoted + ' patterns promoted to long-term');
109
+ }
110
+ }
111
+ if (ls && ls.promoteEpisodic) {
112
+ try {
113
+ var promResult = await hCtx.runWithTimeout(function() { return ls.promoteEpisodic(); }, 'learning.promoteEpisodic()');
114
+ if (promResult && promResult.promoted > 0) {
115
+ console.log('[LEARNING] Promoted ' + promResult.promoted + ' episodic patterns to semantic memory');
116
+ }
117
+ } catch (e) { /* non-fatal */ }
118
+ }
119
+ } catch (e) { /* non-fatal — learning-service may need better-sqlite3 */ }
120
+ }
121
+
122
+ // ── Context Persistence Auto-Archive ─────────────────────────────────
123
+ // Archive conversation context so it survives compaction and new sessions
124
+ try {
125
+ var cpHook = await import('file://' + path.join(__dirname, '..', 'context-persistence-hook.mjs'));
126
+ if (cpHook && cpHook.archive) {
127
+ await hCtx.runWithTimeout(function() { return cpHook.archive(); }, 'context-persistence.archive()');
128
+ console.log('[CONTEXT_PERSIST] Session transcript archived');
129
+ } else if (cpHook && cpHook.default && cpHook.default.archive) {
130
+ await hCtx.runWithTimeout(function() { return cpHook.default.archive(); }, 'context-persistence.archive()');
131
+ console.log('[CONTEXT_PERSIST] Session transcript archived');
132
+ }
133
+ } catch (e) { /* non-fatal — context-persistence may not export archive() */ }
134
+
135
+ // ── Worker Queue Cleanup ─────────────────────────────────────────────
136
+ // Process and clean up any pending worker dispatch files
137
+ try {
138
+ var dispatchDir = path.join(CWD, '.monomind', 'worker-dispatch');
139
+ if (fs.existsSync(dispatchDir)) {
140
+ var pending = fs.readdirSync(dispatchDir).filter(function(f) { return f.startsWith('pending-'); });
141
+ if (pending.length > 0) {
142
+ console.log('[WORKER_CLEANUP] ' + pending.length + ' worker dispatch(es) pending from this session');
143
+ }
144
+ // Move to processed
145
+ var processedDir = path.join(dispatchDir, 'processed');
146
+ fs.mkdirSync(processedDir, { recursive: true });
147
+ pending.forEach(function(f) {
148
+ try {
149
+ fs.renameSync(path.join(dispatchDir, f), path.join(processedDir, f));
150
+ } catch (e) { /* ignore */ }
151
+ });
152
+ // Trim processed/ to last 200 files to prevent unbounded growth
153
+ try {
154
+ var processedFiles = fs.readdirSync(processedDir)
155
+ .filter(function(f) { return f.startsWith('pending-'); })
156
+ .map(function(f) { var fp = path.join(processedDir, f); var mt = 0; try { mt = fs.statSync(fp).mtimeMs; } catch(e2){} return { f: f, mt: mt }; })
157
+ .sort(function(a, b) { return a.mt - b.mt; });
158
+ if (processedFiles.length > 200) {
159
+ processedFiles.slice(0, processedFiles.length - 200).forEach(function(item) {
160
+ try { fs.unlinkSync(path.join(processedDir, item.f)); } catch (e2) { /* ignore */ }
161
+ });
162
+ }
163
+ } catch (e2) { /* non-fatal */ }
164
+ }
165
+ } catch (e) { /* non-fatal */ }
166
+ }
167
+ };
@@ -0,0 +1,343 @@
1
+ 'use strict';
2
+ // Extracted from hook-handler.cjs — handles 'session-restore' hook event.
3
+ // Receives hCtx from dispatcher. See route-handler.cjs for hCtx field docs.
4
+
5
+ const path = require('path');
6
+ const fs = require('fs');
7
+ const { injectGodNodesContext } = require('../utils/monograph.cjs');
8
+
9
+ module.exports = {
10
+ handleRestore: async function(hCtx) {
11
+ var hookInput = hCtx.hookInput;
12
+ var session = hCtx.session;
13
+ var intelligence = hCtx.intelligence;
14
+ var CWD = hCtx.CWD;
15
+ var helpersDir = hCtx.helpersDir;
16
+ var runWithTimeout = hCtx.runWithTimeout;
17
+ var _autoIndexKnowledge = hCtx._autoIndexKnowledge;
18
+ var _buildKnowledgeSearchFn = hCtx._buildKnowledgeSearchFn;
19
+ var getMonographSuggestions = hCtx.getMonographSuggestions;
20
+
21
+ // Session restore / start
22
+ try {
23
+ if (session) {
24
+ var existing = session.restore && session.restore();
25
+ if (!existing) {
26
+ session.start && session.start();
27
+ }
28
+ } else {
29
+ console.log('[OK] Session restored: session-' + Date.now());
30
+ }
31
+ } catch (e) { console.log('[WARN] Session restore failed: ' + e.message); }
32
+
33
+ // Stale helper detection — warn when project helpers drift from the bundled npm copy.
34
+ try {
35
+ var crypto = require('crypto');
36
+ function _findBundledHelpers() {
37
+ var helperPaths = [
38
+ path.join(helpersDir),
39
+ path.join(CWD, 'node_modules', 'monomind', '.claude', 'helpers'),
40
+ path.join(CWD, 'node_modules', '@monoes', 'monomindcli', '.claude', 'helpers'),
41
+ ];
42
+ try {
43
+ var globalRoot = require('child_process')
44
+ .execSync('npm root -g 2>/dev/null', { encoding: 'utf-8', timeout: 2000 })
45
+ .trim();
46
+ if (globalRoot) {
47
+ helperPaths.push(path.join(globalRoot, 'monomind', '.claude', 'helpers'));
48
+ helperPaths.push(path.join(globalRoot, '@monoes', 'monomindcli', '.claude', 'helpers'));
49
+ }
50
+ } catch (_) {}
51
+ for (var i = 0; i < helperPaths.length; i++) {
52
+ if (fs.existsSync(path.join(helperPaths[i], 'hook-handler.cjs')) &&
53
+ helperPaths[i] !== path.join(CWD, '.claude', 'helpers')) {
54
+ return helperPaths[i];
55
+ }
56
+ }
57
+ return null;
58
+ }
59
+
60
+ var bundledDir = _findBundledHelpers();
61
+ if (bundledDir) {
62
+ var helpersToCheck = ['hook-handler.cjs', 'statusline.cjs'];
63
+ var stale = [];
64
+ for (var hi = 0; hi < helpersToCheck.length; hi++) {
65
+ var hName = helpersToCheck[hi];
66
+ var localF = path.join(CWD, '.claude', 'helpers', hName);
67
+ var bundledF = path.join(bundledDir, hName);
68
+ if (!fs.existsSync(localF) || !fs.existsSync(bundledF)) continue;
69
+ try {
70
+ var hashL = crypto.createHash('sha256').update(fs.readFileSync(localF)).digest('hex');
71
+ var hashB = crypto.createHash('sha256').update(fs.readFileSync(bundledF)).digest('hex');
72
+ if (hashL !== hashB) stale.push(hName);
73
+ } catch (_) {}
74
+ }
75
+ if (stale.length > 0) {
76
+ console.log('[STALE_HELPERS] Project helpers differ from bundled version: ' + stale.join(', '));
77
+ console.log(' Run `npx monomind@latest init upgrade` to refresh and pick up the latest features.');
78
+ }
79
+ }
80
+ } catch (e) { /* non-fatal */ }
81
+
82
+ // Initialize intelligence — respects monomind.neural.enabled kill switch.
83
+ var neuralEnabled = true;
84
+ try {
85
+ var settingsPath = path.join(CWD, '.claude', 'settings.json');
86
+ if (fs.existsSync(settingsPath)) {
87
+ var settingsData = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
88
+ if (settingsData.monomind && settingsData.monomind.neural && settingsData.monomind.neural.enabled === false) {
89
+ neuralEnabled = false;
90
+ console.log('[NEURAL] Disabled via monomind.neural.enabled=false');
91
+ }
92
+ }
93
+ } catch (e) { /* non-fatal */ }
94
+ if (neuralEnabled && intelligence && intelligence.init) {
95
+ var initResult = await runWithTimeout(function() { return intelligence.init(); }, 'intelligence.init()');
96
+ if (initResult && initResult.nodes > 0) {
97
+ console.log('[INTELLIGENCE] Loaded ' + initResult.nodes + ' patterns, ' + initResult.edges + ' edges');
98
+ }
99
+ }
100
+
101
+ // Bridge to @monomind/hooks compiled workers (GAP-001).
102
+ try {
103
+ var hooksModule = await import('@monomind/hooks');
104
+ if (hooksModule && hooksModule.initDefaultWorkers) {
105
+ await runWithTimeout(function() { return hooksModule.initDefaultWorkers(); }, '@monomind/hooks.initDefaultWorkers()');
106
+ hCtx._hooksModule = hooksModule;
107
+ console.log('[INFO] @monomind/hooks workers initialized');
108
+ }
109
+ } catch (e) { /* @monomind/hooks not compiled yet — skip */ }
110
+
111
+ // Context Persistence Auto-Restore
112
+ try {
113
+ var cpHook = await import('file://' + path.join(helpersDir, 'context-persistence-hook.mjs'));
114
+ var restoreFn = (cpHook && cpHook.restore) || (cpHook && cpHook.default && cpHook.default.restore);
115
+ if (restoreFn) {
116
+ var restored = await runWithTimeout(function() { return restoreFn(); }, 'context-persistence.restore()');
117
+ if (restored && restored.turns > 0) {
118
+ console.log('[CONTEXT_RESTORED] ' + restored.turns + ' turns from previous session');
119
+ }
120
+ }
121
+ } catch (e) { /* non-fatal */ }
122
+
123
+ // AgentKnowledgeBase — preload shared knowledge context on session restore.
124
+ try {
125
+ var knowledgeDir = path.join(CWD, '.monomind', 'knowledge');
126
+ var indexed = _autoIndexKnowledge(knowledgeDir);
127
+ if (indexed > 0) {
128
+ console.log('[KNOWLEDGE_INDEXED] ' + indexed + ' chunks written from project sources');
129
+ }
130
+
131
+ var kSearchFn = _buildKnowledgeSearchFn(knowledgeDir);
132
+ var sessionCtx = (hookInput && (hookInput.sessionId || hookInput.session_id))
133
+ ? 'session context: ' + (hookInput.sessionId || hookInput.session_id)
134
+ : 'project context general';
135
+
136
+ var memoryMod = null;
137
+ try { memoryMod = await import('@monomind/memory'); } catch (e) {}
138
+
139
+ if (memoryMod && memoryMod.KnowledgeStore && memoryMod.KnowledgeRetriever) {
140
+ var kStore = new memoryMod.KnowledgeStore(knowledgeDir);
141
+ var kRetriever = new memoryMod.KnowledgeRetriever(kSearchFn, kStore);
142
+ var kResult = await kRetriever.retrieveForTask('shared', sessionCtx, 5);
143
+ if (kResult.excerpts.length > 0) {
144
+ console.log('[KNOWLEDGE_PRELOADED] ' + kResult.excerpts.length + ' excerpts (KnowledgeRetriever)');
145
+ }
146
+ } else {
147
+ var directResults = await kSearchFn(sessionCtx, { namespace: 'knowledge:shared', limit: 5, minScore: 0.3 });
148
+ if (directResults.length > 0) {
149
+ console.log('[KNOWLEDGE_PRELOADED] ' + directResults.length + ' excerpts (direct keyword search)');
150
+ }
151
+ }
152
+ } catch (e) { /* non-fatal */ }
153
+
154
+ // Monograph Context Injection — delegates to shared helper in utils/monograph.cjs.
155
+ injectGodNodesContext(CWD);
156
+
157
+ // SharedInstructions — auto-load .agents/shared_instructions.md (hard limit: 1500 chars).
158
+ var SI_CHAR_LIMIT = 1500;
159
+ var applySharedInstrLimit = function(content, source) {
160
+ if (content.length > SI_CHAR_LIMIT) {
161
+ console.warn('[SHARED_INSTRUCTIONS_OVERLIMIT] ' + content.length + ' chars exceeds limit of ' + SI_CHAR_LIMIT +
162
+ ' — truncating. Edit ' + source + ' to stay under limit.');
163
+ return content.slice(0, SI_CHAR_LIMIT) + '\n… [truncated — file exceeds ' + SI_CHAR_LIMIT + ' char limit]';
164
+ }
165
+ return content;
166
+ };
167
+ try {
168
+ var siMod = await import('file://' + path.join(CWD, 'packages/@monomind/cli/dist/src/agents/shared-instructions-loader.js'));
169
+ var loader = siMod.sharedInstructionsLoader || (siMod.SharedInstructionsLoader ? new siMod.SharedInstructionsLoader() : null);
170
+ if (loader) {
171
+ var sharedInstr = loader.getSharedInstructions(CWD);
172
+ if (sharedInstr) {
173
+ var sharedInstrSafe = applySharedInstrLimit(sharedInstr, '.agents/shared_instructions.md');
174
+ console.log('[SHARED_INSTRUCTIONS] Loaded ' + sharedInstrSafe.length + ' chars from .agents/shared_instructions.md');
175
+ console.log(sharedInstrSafe);
176
+ }
177
+ }
178
+ } catch (e) {
179
+ try {
180
+ var siPath = path.join(CWD, '.agents', 'shared_instructions.md');
181
+ if (fs.existsSync(siPath)) {
182
+ var siContent = fs.readFileSync(siPath, 'utf-8');
183
+ var siContentSafe = applySharedInstrLimit(siContent, siPath);
184
+ console.log('[SHARED_INSTRUCTIONS] Loaded ' + siContentSafe.length + ' chars from .agents/shared_instructions.md');
185
+ console.log(siContentSafe);
186
+ }
187
+ } catch (e2) { /* non-fatal */ }
188
+ }
189
+
190
+ // Memory Palace — inject L0 (identity) + L1 (essential story) into session context.
191
+ try {
192
+ var palace = require(path.join(helpersDir, 'memory-palace.cjs'));
193
+ var palaceContext = palace.wakeUp(CWD);
194
+ if (palaceContext) {
195
+ console.log(palaceContext);
196
+ }
197
+ } catch (e) { /* non-fatal — palace not available */ }
198
+
199
+ // Periodic Update Check (once per day).
200
+ try {
201
+ var updateCheckFile = path.join(CWD, '.monomind', 'last-update-check.json');
202
+ var shouldCheck = true;
203
+ if (fs.existsSync(updateCheckFile)) {
204
+ var lastCheck = JSON.parse(fs.readFileSync(updateCheckFile, 'utf-8'));
205
+ var hoursSince = (Date.now() - new Date(lastCheck.timestamp).getTime()) / (1000 * 60 * 60);
206
+ if (hoursSince < 24) shouldCheck = false;
207
+ }
208
+ if (shouldCheck) {
209
+ fs.mkdirSync(path.join(CWD, '.monomind'), { recursive: true });
210
+ fs.writeFileSync(updateCheckFile, JSON.stringify({ timestamp: new Date().toISOString() }), 'utf-8');
211
+ try {
212
+ var localPkg = path.join(CWD, 'packages/@monomind/cli/package.json');
213
+ if (fs.existsSync(localPkg)) {
214
+ var localVer = JSON.parse(fs.readFileSync(localPkg, 'utf-8')).version;
215
+ if (localVer) {
216
+ var spawnFn = require('child_process').spawn;
217
+ var child = spawnFn('npm', ['view', '@monomind/cli', 'version'], {
218
+ stdio: ['ignore', 'pipe', 'ignore'],
219
+ shell: false,
220
+ });
221
+ child.on('error', function() {});
222
+ var out = '';
223
+ child.stdout.on('data', function(d) { out += d; });
224
+ child.on('close', function() {
225
+ var current = out.trim();
226
+ var pendingUpdatePath = path.join(CWD, '.monomind', 'pending-update.json');
227
+ if (current && current !== localVer) {
228
+ try {
229
+ fs.writeFileSync(
230
+ pendingUpdatePath,
231
+ JSON.stringify({ from: localVer, to: current, checkedAt: new Date().toISOString() }),
232
+ 'utf-8'
233
+ );
234
+ } catch (e2) {}
235
+ } else if (current) {
236
+ try { fs.unlinkSync(pendingUpdatePath); } catch (e2) {}
237
+ }
238
+ });
239
+ child.unref();
240
+ }
241
+ }
242
+ } catch (e) { /* npm not available */ }
243
+ }
244
+ try {
245
+ var pendingUpdate = path.join(CWD, '.monomind', 'pending-update.json');
246
+ if (fs.existsSync(pendingUpdate)) {
247
+ var upd = JSON.parse(fs.readFileSync(pendingUpdate, 'utf-8'));
248
+ if (upd && upd.from && upd.to && upd.from !== upd.to) {
249
+ console.log('[UPDATE_AVAILABLE] @monomind/cli ' + upd.from + ' → ' + upd.to + ' (run: npx monomind update)');
250
+ }
251
+ }
252
+ } catch (e) {}
253
+ } catch (e) { /* non-fatal */ }
254
+
255
+ // Daemon Auto-Start Check.
256
+ try {
257
+ var daemonPid = path.join(CWD, '.monomind', 'daemon.pid');
258
+ var daemonRunning = false;
259
+ if (fs.existsSync(daemonPid)) {
260
+ try {
261
+ var pid = parseInt(fs.readFileSync(daemonPid, 'utf-8').trim(), 10);
262
+ process.kill(pid, 0);
263
+ daemonRunning = true;
264
+ } catch (e) { /* pid stale */ }
265
+ }
266
+ if (!daemonRunning) {
267
+ var daemonCfg = {};
268
+ try {
269
+ var cfgPath = path.join(CWD, 'monomind.config.json');
270
+ if (fs.existsSync(cfgPath)) daemonCfg = JSON.parse(fs.readFileSync(cfgPath, 'utf-8')).daemon || {};
271
+ } catch (e) {}
272
+ if (daemonCfg.autoStart) {
273
+ var spawn = require('child_process').spawn;
274
+ var daemonChild = spawn('npx', ['monomind', 'daemon', 'start'], {
275
+ cwd: CWD, detached: true, stdio: 'ignore'
276
+ });
277
+ daemonChild.on('error', function() {});
278
+ daemonChild.unref();
279
+ console.log('[DAEMON_AUTOSTART] Background daemon started (pid ' + daemonChild.pid + ')');
280
+ } else {
281
+ console.log('[DAEMON_STOPPED] Background daemon is not running. To auto-start, set daemon.autoStart=true in monomind.config.json or run: npx monomind daemon start');
282
+ }
283
+ }
284
+ } catch (e) { /* non-fatal */ }
285
+
286
+ // Token Usage — inject daily/monthly cost summary.
287
+ try {
288
+ var tokenTracker = require(path.join(helpersDir, 'token-tracker.cjs'));
289
+ var tokenSummary = tokenTracker.quickSummary();
290
+ if (tokenSummary) {
291
+ console.log(tokenSummary);
292
+ }
293
+ try {
294
+ var tokenData = tokenTracker.quickSummaryData();
295
+ if (tokenData) {
296
+ var metricsDir = path.join(CWD, '.monomind', 'metrics');
297
+ if (!fs.existsSync(metricsDir)) fs.mkdirSync(metricsDir, { recursive: true });
298
+ tokenData.cachedAt = new Date().toISOString();
299
+ fs.writeFileSync(path.join(metricsDir, 'token-summary.json'), JSON.stringify(tokenData), 'utf-8');
300
+ }
301
+ } catch (_) { /* ignore cache write failure */ }
302
+ } catch (e) { /* non-fatal — token tracker not available */ }
303
+
304
+ // Registry Surfacing (SR-001) — show agent count.
305
+ try {
306
+ var regPath = path.join(CWD, '.monomind', 'registry.json');
307
+ if (fs.existsSync(regPath)) {
308
+ var reg = JSON.parse(fs.readFileSync(regPath, 'utf-8'));
309
+ var agentCount = (reg.agents || []).length;
310
+ if (agentCount > 0) {
311
+ console.log('[REGISTRY] ' + agentCount + ' agents available in registry');
312
+ }
313
+ }
314
+ } catch (e) { /* non-fatal */ }
315
+
316
+ // Monomind Control UI Status.
317
+ try {
318
+ var http = require('http');
319
+ var controlPort = 4242;
320
+ var req = http.get('http://localhost:' + controlPort + '/', function(res) {
321
+ if (res.statusCode === 200) {
322
+ console.log('[CONTROL_UI] UP — http://localhost:' + controlPort);
323
+ }
324
+ res.resume();
325
+ });
326
+ req.on('error', function() {
327
+ console.log('[CONTROL_UI] offline — run: npx monomind mcp start');
328
+ });
329
+ req.setTimeout(800, function() { req.destroy(); });
330
+ } catch (e) { /* non-fatal */ }
331
+
332
+ // Worker Queue Resume (SR-003).
333
+ try {
334
+ var dispatchDir = path.join(CWD, '.monomind', 'worker-dispatch');
335
+ if (fs.existsSync(dispatchDir)) {
336
+ var pendingFiles = fs.readdirSync(dispatchDir).filter(function(f) { return f.startsWith('pending-'); });
337
+ if (pendingFiles.length > 0) {
338
+ console.log('[WORKER_RESUME] ' + pendingFiles.length + ' worker dispatch(es) pending from prior session');
339
+ }
340
+ }
341
+ } catch (e) { /* non-fatal */ }
342
+ },
343
+ };