monomind 1.6.9 → 1.8.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 (38) hide show
  1. package/.claude/commands/monomind-createtask.md +75 -113
  2. package/.claude/commands/monomind-do.md +227 -115
  3. package/.claude/commands/monomind-idea.md +30 -104
  4. package/.claude/commands/monomind-improve.md +31 -103
  5. package/.claude/helpers/graphify-freshen.cjs +12 -97
  6. package/.claude/helpers/hook-handler.cjs +16 -0
  7. package/.claude/helpers/learning-service.mjs +0 -0
  8. package/.claude/helpers/metrics-db.mjs +0 -0
  9. package/.claude/helpers/statusline.cjs +89 -65
  10. package/.claude/helpers/swarm-hooks.sh +0 -0
  11. package/.claude/settings.local.json +2 -1
  12. package/.claude/skills/monomind-task-engine/SKILL.md +358 -0
  13. package/.claude/statusline-command.sh +0 -0
  14. package/.claude/statusline.sh +0 -0
  15. package/.claude-plugin/scripts/install.sh +0 -0
  16. package/.claude-plugin/scripts/uninstall.sh +0 -0
  17. package/.claude-plugin/scripts/verify.sh +0 -0
  18. package/package.json +17 -17
  19. package/packages/@monomind/cli/bin/cli.js +0 -0
  20. package/packages/@monomind/cli/bin/mcp-server.js +0 -0
  21. package/packages/@monomind/cli/dist/src/commands/doctor.js +36 -9
  22. package/packages/@monomind/cli/dist/src/init/executor.js +99 -28
  23. package/packages/@monomind/cli/dist/src/init/helpers-generator.js +14 -14
  24. package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.d.ts +38 -0
  25. package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.js +571 -0
  26. package/packages/@monomind/cli/dist/src/init/types.d.ts +1 -1
  27. package/packages/@monomind/cli/dist/src/mcp-client.js +5 -2
  28. package/packages/@monomind/cli/dist/src/mcp-tools/graphify-tools.d.ts +4 -67
  29. package/packages/@monomind/cli/dist/src/mcp-tools/graphify-tools.js +40 -1226
  30. package/packages/@monomind/cli/dist/src/mcp-tools/index.d.ts +1 -0
  31. package/packages/@monomind/cli/dist/src/mcp-tools/index.js +1 -0
  32. package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.d.ts +9 -0
  33. package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +495 -0
  34. package/packages/@monomind/cli/package.json +2 -1
  35. package/packages/@monomind/cli/README.md +0 -441
  36. package/packages/@monomind/guidance/README.md +0 -1195
  37. package/packages/@monomind/shared/README.md +0 -323
  38. package/packages/README.md +0 -514
@@ -11,6 +11,7 @@ import { dirname } from 'path';
11
11
  const __filename = fileURLToPath(import.meta.url);
12
12
  const __dirname = dirname(__filename);
13
13
  import { detectPlatform, DEFAULT_INIT_OPTIONS } from './types.js';
14
+ import { writeSharedInstructions } from './shared-instructions-generator.js';
14
15
  import { generateSettingsJson, generateSettings } from './settings-generator.js';
15
16
  import { generateMCPJson } from './mcp-generator.js';
16
17
  import { generateStatuslineScript } from './statusline-generator.js';
@@ -66,7 +67,7 @@ const SKILLS_MAP = {
66
67
  const COMMANDS_MAP = {
67
68
  core: [
68
69
  'monomind-help.md', 'monomind-swarm.md', 'monomind-memory.md',
69
- 'monomind-do.md', 'monomind-idea.md', 'monomind-createtask.md', 'monomind-repeat.md',
70
+ 'monomind-do.md', 'monomind-idea.md', 'monomind-improve.md', 'monomind-createtask.md', 'monomind-repeat.md',
70
71
  'mastermind.md', 'list-agents.md', 'use-agent.md',
71
72
  'metrics.md', 'tokens.md', 'browse.md', 'sparc.md', 'ts.md',
72
73
  ],
@@ -281,12 +282,18 @@ export async function executeInit(options) {
281
282
  if (options.components.claudeMd) {
282
283
  await writeClaudeMd(targetDir, options, result);
283
284
  }
285
+ // Generate .agents/shared_instructions.md + seed project memory
286
+ writeSharedInstructions(targetDir, options.force, result);
284
287
  // Count enabled hooks
285
288
  result.summary.hooksEnabled = countEnabledHooks(options);
286
289
  // Build knowledge graph in background (non-blocking)
287
290
  if (options.components.graphify) {
288
291
  await initKnowledgeGraph(targetDir, result);
289
292
  }
293
+ // Start daemon with background workers (non-blocking)
294
+ await startDaemonBackground(targetDir, result);
295
+ // Run doctor auto-fix (non-blocking, best-effort)
296
+ await runDoctorFix(targetDir, result);
290
297
  }
291
298
  catch (error) {
292
299
  result.success = false;
@@ -295,39 +302,72 @@ export async function executeInit(options) {
295
302
  return result;
296
303
  }
297
304
  /**
298
- * Spawn a background process to build the @monomind/graph knowledge graph.
299
- * Fire-and-forget: init does not wait for the ~20s graph build to complete.
300
- * Non-fatal: if @monomind/graph is unavailable the step is simply skipped.
305
+ * Initialize the Monograph knowledge graph (native TypeScript, no Python required).
306
+ * Fire-and-forget build — init does not wait for it to complete.
301
307
  */
302
308
  async function initKnowledgeGraph(targetDir, result) {
309
+ const { mkdirSync } = await import('fs');
310
+ const outputDir = path.join(targetDir, '.monomind', 'graph');
311
+ mkdirSync(outputDir, { recursive: true });
303
312
  try {
304
- // Verify the package is resolvable before spawning — fast path to skip gracefully.
305
- await import('@monomind/graph');
306
- const outputDir = path.join(targetDir, '.monomind', 'graph');
307
- const { spawn } = await import('child_process');
308
- // Escape single quotes in path strings for the inline ES module script.
309
- const safePath = targetDir.replace(/'/g, "\\'");
310
- const safeOut = outputDir.replace(/'/g, "\\'");
311
- const script = `
312
- import('@monomind/graph').then(({ buildGraph }) =>
313
- buildGraph('${safePath}', { codeOnly: true, outputDir: '${safeOut}' })
314
- ).then(r => console.log('[graph] built: ' + r.filesProcessed + ' files, ' + r.analysis.stats.nodes + ' nodes'))
315
- .catch(e => console.error('[graph] build failed:', e.message));
316
- `;
317
- const child = spawn(process.execPath, ['--input-type=module'], {
318
- stdio: ['pipe', 'ignore', 'ignore'],
319
- detached: true,
313
+ const { buildAsync } = await import('@monoes/monograph');
314
+ buildAsync(targetDir, { codeOnly: false })
315
+ .then(() => { })
316
+ .catch((err) => {
317
+ console.warn('[monograph] Background build failed:', err);
318
+ });
319
+ result.created.files.push('.monomind/monograph.db (knowledge graph building in background)');
320
+ }
321
+ catch (err) {
322
+ result.skipped.push('knowledge graph: monograph package unavailable');
323
+ }
324
+ }
325
+ /**
326
+ * Start the monomind daemon with background workers.
327
+ * Non-fatal: if daemon fails to start, init continues.
328
+ */
329
+ async function startDaemonBackground(targetDir, result) {
330
+ try {
331
+ const { execSync } = await import('child_process');
332
+ // Check if daemon is already running
333
+ const pidFile = path.join(targetDir, '.monomind', 'daemon.pid');
334
+ const { existsSync, readFileSync } = await import('fs');
335
+ if (existsSync(pidFile)) {
336
+ const pid = parseInt(readFileSync(pidFile, 'utf8').trim(), 10);
337
+ try {
338
+ process.kill(pid, 0);
339
+ result.skipped.push('daemon: already running (PID ' + pid + ')');
340
+ return;
341
+ }
342
+ catch { /* stale PID, continue */ }
343
+ }
344
+ execSync('npx monomind@latest daemon start --background', {
345
+ cwd: targetDir,
346
+ stdio: 'ignore',
347
+ timeout: 15000,
348
+ });
349
+ result.created.files.push('monomind daemon (background workers started)');
350
+ }
351
+ catch {
352
+ result.skipped.push('daemon: could not auto-start (run: monomind daemon start)');
353
+ }
354
+ }
355
+ /**
356
+ * Run doctor --install to auto-fix any remaining issues.
357
+ * Non-fatal: best-effort health check and auto-install.
358
+ */
359
+ async function runDoctorFix(targetDir, result) {
360
+ try {
361
+ const { execSync } = await import('child_process');
362
+ execSync('npx monomind@latest doctor --install', {
320
363
  cwd: targetDir,
364
+ stdio: 'ignore',
365
+ timeout: 120000,
321
366
  });
322
- // Write the script to stdin then close so node processes it.
323
- child.stdin?.write(script);
324
- child.stdin?.end();
325
- child.unref();
326
- result.created.files.push('.monomind/graph/ (knowledge graph building in background)');
367
+ result.created.files.push('doctor --install (health check + auto-fix)');
327
368
  }
328
- catch (_err) {
329
- // Non-fatal @monomind/graph is an optional enhancement.
330
- result.skipped.push('knowledge graph: @monomind/graph not available');
369
+ catch {
370
+ result.skipped.push('doctor: auto-fix skipped (run: monomind doctor --install)');
331
371
  }
332
372
  }
333
373
  /**
@@ -1811,6 +1851,37 @@ async function writeClaudeMd(targetDir, options, result) {
1811
1851
  catch {
1812
1852
  // Non-critical — global CLAUDE.md is best-effort
1813
1853
  }
1854
+ // Also inject the token-display hook into ~/.claude/settings.json
1855
+ const globalSettingsPath = path.join(globalClaudeDir, 'settings.json');
1856
+ try {
1857
+ if (!fs.existsSync(globalClaudeDir)) {
1858
+ fs.mkdirSync(globalClaudeDir, { recursive: true });
1859
+ }
1860
+ let globalSettings = {};
1861
+ if (fs.existsSync(globalSettingsPath)) {
1862
+ try {
1863
+ globalSettings = JSON.parse(fs.readFileSync(globalSettingsPath, 'utf-8'));
1864
+ }
1865
+ catch { /* malformed JSON — start fresh */ }
1866
+ }
1867
+ // Inject SessionStart token hook if not already present
1868
+ const hooks = globalSettings.hooks ?? {};
1869
+ const sessionStartHooks = hooks['SessionStart'] ?? [];
1870
+ const tokenHookCommand = 'npx --yes monomind@latest tokens today';
1871
+ const alreadyPresent = sessionStartHooks.some(entry => Array.isArray(entry.hooks) && entry.hooks.some(h => h.command === tokenHookCommand));
1872
+ if (!alreadyPresent) {
1873
+ sessionStartHooks.push({
1874
+ hooks: [{ type: 'command', command: tokenHookCommand, timeout: 10000 }],
1875
+ });
1876
+ hooks['SessionStart'] = sessionStartHooks;
1877
+ globalSettings.hooks = hooks;
1878
+ fs.writeFileSync(globalSettingsPath, JSON.stringify(globalSettings, null, 2), 'utf-8');
1879
+ result.created.files.push('~/.claude/settings.json (added token hook)');
1880
+ }
1881
+ }
1882
+ catch {
1883
+ // Non-critical — global settings hook is best-effort
1884
+ }
1814
1885
  }
1815
1886
  }
1816
1887
  /**
@@ -22,7 +22,7 @@ STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
22
22
  for FILE in $STAGED_FILES; do
23
23
  if [[ "$FILE" =~ \\.(ts|js|tsx|jsx)$ ]]; then
24
24
  echo " Validating: $FILE"
25
- npx @monoes/cli hooks pre-edit --file "$FILE" --validate-syntax 2>/dev/null || true
25
+ npx @monomind/cli hooks pre-edit --file "$FILE" --validate-syntax 2>/dev/null || true
26
26
  fi
27
27
  done
28
28
 
@@ -451,21 +451,21 @@ export function generateHookHandler() {
451
451
  " var archKeywords = ['understand', 'architecture', 'how does', 'what calls', 'dependency', 'depends on', 'flow', 'how is', 'explain codebase', 'project structure', 'what is the relationship', 'graph', 'knowledge'];",
452
452
  ' var promptLower = prompt.toLowerCase();',
453
453
  ' var isArchQuery = archKeywords.some(function(k) { return promptLower.includes(k); });',
454
- " var graphJson = require('path').join(process.cwd(), 'graphify-out', 'graph.json');",
454
+ " var graphJson = require('path').join(process.cwd(), '.monomind', 'monograph.db');",
455
455
  " var hasGraph = require('fs').existsSync(graphJson);",
456
456
  ' if (isArchQuery) {',
457
457
  " var gfOutput = [];",
458
458
  " gfOutput.push('');",
459
- " gfOutput.push('+------- graphify | Knowledge Graph Available ----------------+');",
459
+ " gfOutput.push('+------- monograph | Knowledge Graph Available ---------------+');",
460
460
  ' if (hasGraph) {',
461
- " gfOutput.push('| Graph: graphify-out/graph.json |');",
462
- " gfOutput.push('| Use: mcp__monomind__graphify_god_nodes |');",
463
- " gfOutput.push('| mcp__monomind__graphify_query |');",
464
- " gfOutput.push('| mcp__monomind__graphify_shortest_path |');",
465
- " gfOutput.push('| Tip: Call graphify_god_nodes first for architecture overview|');",
461
+ " gfOutput.push('| Graph: .monomind/monograph.db |');",
462
+ " gfOutput.push('| Use: mcp__monomind__monograph_god_nodes |');",
463
+ " gfOutput.push('| mcp__monomind__monograph_query |');",
464
+ " gfOutput.push('| mcp__monomind__monograph_shortest_path |');",
465
+ " gfOutput.push('| Tip: Call monograph_god_nodes first for architecture overview|');",
466
466
  ' } else {',
467
467
  " gfOutput.push('| No graph found. Build with: |');",
468
- " gfOutput.push('| python -m graphify . (pip install graphifyy[mcp] first) |');",
468
+ " gfOutput.push('| mcp__monomind__monograph_build |');",
469
469
  ' }',
470
470
  " gfOutput.push('+--------------------------------------------------------------+');",
471
471
  " console.log(gfOutput.join('\\n'));",
@@ -842,7 +842,7 @@ export function generateIntelligenceStub() {
842
842
  /**
843
843
  * Generate a minimal auto-memory-hook.mjs fallback for fresh installs.
844
844
  * This ESM script handles import/sync/status commands gracefully when
845
- * @monoes/memory is not installed. Gets overwritten when source copy succeeds.
845
+ * @monomind/memory is not installed. Gets overwritten when source copy succeeds.
846
846
  */
847
847
  export function generateAutoMemoryHook() {
848
848
  return `#!/usr/bin/env node
@@ -879,17 +879,17 @@ async function loadMemoryPackage() {
879
879
  try {
880
880
  const { createRequire } = await import('module');
881
881
  const require = createRequire(join(PROJECT_ROOT, 'package.json'));
882
- return require('@monoes/memory');
882
+ return require('@monomind/memory');
883
883
  } catch { /* fall through */ }
884
884
 
885
- // Strategy 2: ESM import (works when @monoes/memory is a direct dependency)
886
- try { return await import('@monoes/memory'); } catch { /* fall through */ }
885
+ // Strategy 2: ESM import (works when @monomind/memory is a direct dependency)
886
+ try { return await import('@monomind/memory'); } catch { /* fall through */ }
887
887
 
888
888
  // Strategy 3: Walk up from PROJECT_ROOT looking for the package in any node_modules
889
889
  let searchDir = PROJECT_ROOT;
890
890
  const { parse } = await import('path');
891
891
  while (searchDir !== parse(searchDir).root) {
892
- const candidate = join(searchDir, 'node_modules', '@monoes', 'memory', 'dist', 'index.js');
892
+ const candidate = join(searchDir, 'node_modules', '@monomind', 'memory', 'dist', 'index.js');
893
893
  if (existsSync(candidate)) {
894
894
  try { return await import(\`file://\${candidate}\`); } catch { /* fall through */ }
895
895
  }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Shared Instructions Generator
3
+ *
4
+ * Auto-detects project profile and generates:
5
+ * 1. .agents/shared_instructions.md — prepended to every agent prompt
6
+ * 2. Memory seeds — pre-loaded into AgentDB so agents start with project best practices
7
+ */
8
+ import type { InitResult } from './types.js';
9
+ export interface ProjectProfile {
10
+ name: string;
11
+ description: string;
12
+ language: 'typescript' | 'javascript' | 'python' | 'go' | 'rust' | 'unknown';
13
+ framework: string[];
14
+ packageManager: 'pnpm' | 'npm' | 'yarn' | 'bun' | 'cargo' | 'poetry' | 'uv' | 'pip' | 'unknown';
15
+ testFramework: string[];
16
+ buildTool: string[];
17
+ isMonorepo: boolean;
18
+ monorepoTool: string;
19
+ database: string[];
20
+ hasDocker: boolean;
21
+ hasCi: boolean;
22
+ ciTool: string;
23
+ maxFileLines: number | null;
24
+ srcDir: string;
25
+ testDir: string;
26
+ version: string;
27
+ isPublicNpm: boolean;
28
+ }
29
+ export declare function detectProjectProfile(cwd: string): ProjectProfile;
30
+ export declare function generateSharedInstructions(profile: ProjectProfile): string;
31
+ export interface MemorySeed {
32
+ key: string;
33
+ value: string;
34
+ namespace: string;
35
+ }
36
+ export declare function generateMemorySeeds(profile: ProjectProfile): MemorySeed[];
37
+ export declare function writeSharedInstructions(cwd: string, force: boolean, result: InitResult): void;
38
+ //# sourceMappingURL=shared-instructions-generator.d.ts.map