moflo 4.8.10 → 4.8.12

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 (182) hide show
  1. package/.claude/agents/browser/browser-agent.yaml +182 -0
  2. package/.claude/agents/core/coder.md +265 -265
  3. package/.claude/agents/core/planner.md +167 -167
  4. package/.claude/agents/core/researcher.md +189 -189
  5. package/.claude/agents/core/reviewer.md +325 -325
  6. package/.claude/agents/core/tester.md +318 -318
  7. package/.claude/agents/dual-mode/codex-coordinator.md +224 -224
  8. package/.claude/agents/dual-mode/codex-worker.md +211 -211
  9. package/.claude/agents/dual-mode/dual-orchestrator.md +291 -291
  10. package/.claude/agents/github/code-review-swarm.md +537 -537
  11. package/.claude/agents/github/github-modes.md +172 -172
  12. package/.claude/agents/github/issue-tracker.md +318 -318
  13. package/.claude/agents/github/multi-repo-swarm.md +552 -552
  14. package/.claude/agents/github/pr-manager.md +190 -190
  15. package/.claude/agents/github/project-board-sync.md +508 -508
  16. package/.claude/agents/github/release-manager.md +366 -366
  17. package/.claude/agents/github/release-swarm.md +582 -582
  18. package/.claude/agents/github/repo-architect.md +397 -397
  19. package/.claude/agents/github/swarm-issue.md +572 -572
  20. package/.claude/agents/github/swarm-pr.md +427 -427
  21. package/.claude/agents/github/sync-coordinator.md +451 -451
  22. package/.claude/agents/github/workflow-automation.md +634 -634
  23. package/.claude/agents/goal/code-goal-planner.md +445 -445
  24. package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +129 -129
  25. package/.claude/agents/hive-mind/queen-coordinator.md +202 -202
  26. package/.claude/agents/hive-mind/scout-explorer.md +241 -241
  27. package/.claude/agents/hive-mind/swarm-memory-manager.md +192 -192
  28. package/.claude/agents/hive-mind/worker-specialist.md +216 -216
  29. package/.claude/agents/neural/safla-neural.md +73 -73
  30. package/.claude/agents/reasoning/goal-planner.md +72 -72
  31. package/.claude/agents/swarm/adaptive-coordinator.md +395 -395
  32. package/.claude/agents/swarm/hierarchical-coordinator.md +326 -326
  33. package/.claude/agents/swarm/mesh-coordinator.md +391 -391
  34. package/.claude/agents/templates/migration-plan.md +745 -745
  35. package/.claude/commands/agents/agent-spawning.md +28 -28
  36. package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +53 -53
  37. package/.claude/commands/analysis/bottleneck-detect.md +162 -162
  38. package/.claude/commands/analysis/performance-bottlenecks.md +58 -58
  39. package/.claude/commands/analysis/token-efficiency.md +44 -44
  40. package/.claude/commands/automation/auto-agent.md +122 -122
  41. package/.claude/commands/automation/self-healing.md +105 -105
  42. package/.claude/commands/automation/session-memory.md +89 -89
  43. package/.claude/commands/automation/smart-agents.md +72 -72
  44. package/.claude/commands/coordination/init.md +44 -44
  45. package/.claude/commands/coordination/orchestrate.md +43 -43
  46. package/.claude/commands/coordination/spawn.md +45 -45
  47. package/.claude/commands/coordination/swarm-init.md +85 -85
  48. package/.claude/commands/github/github-modes.md +146 -146
  49. package/.claude/commands/github/github-swarm.md +121 -121
  50. package/.claude/commands/github/issue-tracker.md +291 -291
  51. package/.claude/commands/github/pr-manager.md +169 -169
  52. package/.claude/commands/github/release-manager.md +337 -337
  53. package/.claude/commands/github/repo-architect.md +366 -366
  54. package/.claude/commands/github/sync-coordinator.md +300 -300
  55. package/.claude/commands/memory/neural.md +47 -47
  56. package/.claude/commands/monitoring/agents.md +44 -44
  57. package/.claude/commands/monitoring/status.md +46 -46
  58. package/.claude/commands/optimization/auto-topology.md +61 -61
  59. package/.claude/commands/optimization/parallel-execution.md +49 -49
  60. package/.claude/commands/sparc/analyzer.md +51 -51
  61. package/.claude/commands/sparc/architect.md +53 -53
  62. package/.claude/commands/sparc/ask.md +97 -97
  63. package/.claude/commands/sparc/batch-executor.md +54 -54
  64. package/.claude/commands/sparc/code.md +89 -89
  65. package/.claude/commands/sparc/coder.md +54 -54
  66. package/.claude/commands/sparc/debug.md +83 -83
  67. package/.claude/commands/sparc/debugger.md +54 -54
  68. package/.claude/commands/sparc/designer.md +53 -53
  69. package/.claude/commands/sparc/devops.md +109 -109
  70. package/.claude/commands/sparc/docs-writer.md +80 -80
  71. package/.claude/commands/sparc/documenter.md +54 -54
  72. package/.claude/commands/sparc/innovator.md +54 -54
  73. package/.claude/commands/sparc/integration.md +83 -83
  74. package/.claude/commands/sparc/mcp.md +117 -117
  75. package/.claude/commands/sparc/memory-manager.md +54 -54
  76. package/.claude/commands/sparc/optimizer.md +54 -54
  77. package/.claude/commands/sparc/orchestrator.md +131 -131
  78. package/.claude/commands/sparc/post-deployment-monitoring-mode.md +83 -83
  79. package/.claude/commands/sparc/refinement-optimization-mode.md +83 -83
  80. package/.claude/commands/sparc/researcher.md +54 -54
  81. package/.claude/commands/sparc/reviewer.md +54 -54
  82. package/.claude/commands/sparc/security-review.md +80 -80
  83. package/.claude/commands/sparc/sparc-modes.md +174 -174
  84. package/.claude/commands/sparc/sparc.md +111 -111
  85. package/.claude/commands/sparc/spec-pseudocode.md +80 -80
  86. package/.claude/commands/sparc/supabase-admin.md +348 -348
  87. package/.claude/commands/sparc/swarm-coordinator.md +54 -54
  88. package/.claude/commands/sparc/tdd.md +54 -54
  89. package/.claude/commands/sparc/tester.md +54 -54
  90. package/.claude/commands/sparc/tutorial.md +79 -79
  91. package/.claude/commands/sparc/workflow-manager.md +54 -54
  92. package/.claude/commands/sparc.md +166 -166
  93. package/.claude/commands/swarm/analysis.md +95 -95
  94. package/.claude/commands/swarm/development.md +96 -96
  95. package/.claude/commands/swarm/examples.md +168 -168
  96. package/.claude/commands/swarm/maintenance.md +102 -102
  97. package/.claude/commands/swarm/optimization.md +117 -117
  98. package/.claude/commands/swarm/research.md +136 -136
  99. package/.claude/commands/swarm/testing.md +131 -131
  100. package/.claude/commands/training/neural-patterns.md +73 -73
  101. package/.claude/commands/training/specialization.md +62 -62
  102. package/.claude/commands/workflows/development.md +77 -77
  103. package/.claude/commands/workflows/research.md +62 -62
  104. package/.claude/guidance/moflo-bootstrap.md +129 -0
  105. package/.claude/guidance/{agent-bootstrap.md → shipped/agent-bootstrap.md} +126 -126
  106. package/.claude/guidance/{guidance-memory-strategy.md → shipped/guidance-memory-strategy.md} +262 -262
  107. package/.claude/guidance/{memory-strategy.md → shipped/memory-strategy.md} +204 -204
  108. package/.claude/guidance/{moflo.md → shipped/moflo.md} +45 -31
  109. package/.claude/guidance/{task-swarm-integration.md → shipped/task-swarm-integration.md} +441 -348
  110. package/.claude/helpers/gate-hook.mjs +50 -0
  111. package/.claude/helpers/gate.cjs +138 -236
  112. package/.claude/helpers/hook-handler.cjs +64 -326
  113. package/.claude/helpers/post-commit +16 -0
  114. package/.claude/helpers/pre-commit +26 -0
  115. package/.claude/helpers/prompt-hook.mjs +72 -0
  116. package/.claude/scripts/build-embeddings.mjs +549 -0
  117. package/.claude/scripts/generate-code-map.mjs +697 -0
  118. package/.claude/scripts/hooks.mjs +656 -0
  119. package/.claude/scripts/index-guidance.mjs +893 -0
  120. package/.claude/scripts/index-tests.mjs +710 -0
  121. package/.claude/scripts/semantic-search.mjs +473 -0
  122. package/.claude/scripts/session-start-launcher.mjs +226 -0
  123. package/.claude/settings.json +351 -290
  124. package/.claude/settings.local.json +4 -3
  125. package/.claude/skills/browser/SKILL.md +204 -0
  126. package/.claude/skills/fl/SKILL.md +29 -23
  127. package/.claude/skills/flo/SKILL.md +29 -23
  128. package/.claude/skills/github-code-review/SKILL.md +4 -4
  129. package/.claude/skills/github-multi-repo/SKILL.md +8 -8
  130. package/.claude/skills/github-project-management/SKILL.md +6 -6
  131. package/.claude/skills/github-release-management/SKILL.md +12 -12
  132. package/.claude/skills/github-workflow-automation/SKILL.md +6 -6
  133. package/.claude/skills/hooks-automation/SKILL.md +1201 -1201
  134. package/.claude/skills/performance-analysis/SKILL.md +563 -563
  135. package/.claude/skills/sparc-methodology/SKILL.md +64 -64
  136. package/.claude/skills/swarm-advanced/SKILL.md +77 -77
  137. package/.claude/workflow-state.json +9 -0
  138. package/.claude-plugin/README.md +3 -3
  139. package/.claude-plugin/docs/PLUGIN_SUMMARY.md +3 -3
  140. package/.claude-plugin/docs/QUICKSTART.md +4 -4
  141. package/.claude-plugin/marketplace.json +3 -3
  142. package/.claude-plugin/plugin.json +3 -3
  143. package/.claude-plugin/scripts/install.sh +9 -9
  144. package/.claude-plugin/scripts/verify.sh +7 -7
  145. package/README.md +311 -116
  146. package/bin/gate-hook.mjs +50 -0
  147. package/bin/gate.cjs +138 -0
  148. package/bin/hook-handler.cjs +83 -0
  149. package/bin/hooks.mjs +72 -12
  150. package/bin/index-guidance.mjs +29 -35
  151. package/bin/index-tests.mjs +710 -0
  152. package/bin/lib/process-manager.mjs +243 -0
  153. package/bin/lib/registry-cleanup.cjs +41 -0
  154. package/bin/prompt-hook.mjs +72 -0
  155. package/bin/semantic-search.mjs +472 -440
  156. package/bin/session-start-launcher.mjs +81 -31
  157. package/bin/setup-project.mjs +65 -65
  158. package/package.json +4 -2
  159. package/src/@claude-flow/cli/README.md +1 -1
  160. package/src/@claude-flow/cli/bin/cli.js +175 -175
  161. package/src/@claude-flow/cli/dist/src/commands/doctor.js +1091 -736
  162. package/src/@claude-flow/cli/dist/src/commands/github.d.ts +12 -0
  163. package/src/@claude-flow/cli/dist/src/commands/github.js +505 -0
  164. package/src/@claude-flow/cli/dist/src/commands/hive-mind.js +90 -90
  165. package/src/@claude-flow/cli/dist/src/commands/index.d.ts +1 -0
  166. package/src/@claude-flow/cli/dist/src/commands/index.js +7 -0
  167. package/src/@claude-flow/cli/dist/src/config-adapter.js +1 -1
  168. package/src/@claude-flow/cli/dist/src/init/claudemd-generator.d.ts +29 -24
  169. package/src/@claude-flow/cli/dist/src/init/claudemd-generator.js +73 -494
  170. package/src/@claude-flow/cli/dist/src/init/executor.js +109 -5
  171. package/src/@claude-flow/cli/dist/src/init/helpers-generator.d.ts +14 -0
  172. package/src/@claude-flow/cli/dist/src/init/helpers-generator.js +156 -24
  173. package/src/@claude-flow/cli/dist/src/init/mcp-generator.js +20 -20
  174. package/src/@claude-flow/cli/dist/src/init/moflo-init.d.ts +30 -23
  175. package/src/@claude-flow/cli/dist/src/init/moflo-init.js +727 -670
  176. package/src/@claude-flow/cli/dist/src/init/settings-generator.js +23 -14
  177. package/src/@claude-flow/cli/dist/src/mcp-server.js +3 -3
  178. package/src/@claude-flow/cli/dist/src/plugins/manager.js +9 -8
  179. package/src/@claude-flow/cli/dist/src/services/worker-daemon.d.ts +1 -0
  180. package/src/@claude-flow/cli/dist/src/services/worker-daemon.js +3 -1
  181. package/src/@claude-flow/cli/dist/src/services/workflow-gate.js +10 -10
  182. package/src/@claude-flow/cli/package.json +106 -106
@@ -14,7 +14,7 @@ import { detectPlatform, DEFAULT_INIT_OPTIONS } from './types.js';
14
14
  import { generateSettingsJson, generateSettings } from './settings-generator.js';
15
15
  import { generateMCPJson } from './mcp-generator.js';
16
16
  import { generateStatuslineScript } from './statusline-generator.js';
17
- import { generatePreCommitHook, generatePostCommitHook, generateAutoMemoryHook, generateGateScript, generateHookHandlerScript, } from './helpers-generator.js';
17
+ import { generatePreCommitHook, generatePostCommitHook, generateAutoMemoryHook, generateGateScript, generateGateHookScript, generatePromptHookScript, generateHookHandlerScript, } from './helpers-generator.js';
18
18
  import { generateClaudeMd } from './claudemd-generator.js';
19
19
  /**
20
20
  * Skills to copy based on configuration
@@ -377,6 +377,8 @@ export async function executeUpgrade(targetDir, upgradeSettings = false) {
377
377
  const generatedCritical = {
378
378
  'auto-memory-hook.mjs': generateAutoMemoryHook(),
379
379
  'gate.cjs': generateGateScript(),
380
+ 'gate-hook.mjs': generateGateHookScript(),
381
+ 'prompt-hook.mjs': generatePromptHookScript(),
380
382
  'hook-handler.cjs': generateHookHandlerScript(),
381
383
  };
382
384
  for (const [helperName, content] of Object.entries(generatedCritical)) {
@@ -463,6 +465,22 @@ export async function executeUpgrade(targetDir, upgradeSettings = false) {
463
465
  }
464
466
  }
465
467
  }
468
+ // 1c. Build manifest of files we're installing, clean up stale ones
469
+ const manifestPath = path.join(targetDir, '.claude-flow', 'installed-files.json');
470
+ let previousManifest = [];
471
+ try {
472
+ previousManifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
473
+ }
474
+ catch { /* ok */ }
475
+ const currentManifest = [];
476
+ // Collect everything we just synced into the manifest
477
+ for (const entry of [...result.created, ...result.updated]) {
478
+ // Strip annotations like " (removed, obsolete)" — keep only clean paths
479
+ const clean = entry.replace(/\s*\(.*\)$/, '');
480
+ if (clean.startsWith('.claude/') || clean.startsWith('.claude-flow/')) {
481
+ currentManifest.push(clean);
482
+ }
483
+ }
466
484
  // 2. Create MISSING metrics files only (preserve existing data)
467
485
  const metricsDir = path.join(targetDir, '.claude-flow', 'metrics');
468
486
  const securityDir = path.join(targetDir, '.claude-flow', 'security');
@@ -579,6 +597,39 @@ export async function executeUpgrade(targetDir, upgradeSettings = false) {
579
597
  result.settingsUpdated = ['Created new settings.json with Agent Teams'];
580
598
  }
581
599
  }
600
+ // ── Final: collect any additional generated files into manifest, then clean up stale ──
601
+ // Re-scan result arrays since metrics/security files were added after initial collection
602
+ for (const entry of [...result.created, ...result.updated]) {
603
+ const clean = entry.replace(/\s*\(.*\)$/, '');
604
+ if ((clean.startsWith('.claude/') || clean.startsWith('.claude-flow/')) && !currentManifest.includes(clean)) {
605
+ currentManifest.push(clean);
606
+ }
607
+ }
608
+ // Remove files that were in the OLD manifest but NOT in the new one.
609
+ // This only deletes files moflo previously installed — never user or runtime files.
610
+ if (previousManifest.length > 0) {
611
+ const currentSet = new Set(currentManifest);
612
+ for (const rel of previousManifest) {
613
+ if (!currentSet.has(rel)) {
614
+ const abs = path.join(targetDir, rel);
615
+ try {
616
+ if (fs.existsSync(abs)) {
617
+ fs.unlinkSync(abs);
618
+ result.updated.push(`${rel} (removed, no longer shipped)`);
619
+ }
620
+ }
621
+ catch { /* non-fatal */ }
622
+ }
623
+ }
624
+ }
625
+ // Write manifest for next upgrade
626
+ try {
627
+ const cfDir = path.join(targetDir, '.claude-flow');
628
+ if (!fs.existsSync(cfDir))
629
+ fs.mkdirSync(cfDir, { recursive: true });
630
+ fs.writeFileSync(manifestPath, JSON.stringify(currentManifest, null, 2), 'utf-8');
631
+ }
632
+ catch { /* non-fatal */ }
582
633
  }
583
634
  catch (error) {
584
635
  result.success = false;
@@ -713,12 +764,63 @@ async function writeSettings(targetDir, options, result) {
713
764
  }
714
765
  /**
715
766
  * Write .mcp.json
767
+ *
768
+ * If an existing config contains the legacy 'claude-flow' server key, prompt
769
+ * the user to migrate it to 'moflo', keep both side-by-side, or leave as-is.
716
770
  */
717
771
  async function writeMCPConfig(targetDir, options, result) {
718
772
  const mcpPath = path.join(targetDir, '.mcp.json');
719
- if (fs.existsSync(mcpPath) && !options.force) {
720
- result.skipped.push('.mcp.json');
721
- return;
773
+ if (fs.existsSync(mcpPath)) {
774
+ const existing = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));
775
+ const servers = existing?.mcpServers ?? {};
776
+ const hasLegacy = 'claude-flow' in servers;
777
+ const hasMoflo = 'moflo' in servers;
778
+ if (hasLegacy && !hasMoflo) {
779
+ // Interactive mode: prompt the user
780
+ if (process.stdin.isTTY && !options.force) {
781
+ const { select } = await import('../prompt.js');
782
+ const action = await select({
783
+ message: "Found existing 'claude-flow' MCP server. How should we handle it?",
784
+ options: [
785
+ { value: 'migrate', label: 'Migrate to moflo', hint: 'Rename claude-flow → moflo (recommended)' },
786
+ { value: 'side-by-side', label: 'Keep both', hint: 'Add moflo alongside existing claude-flow' },
787
+ { value: 'skip', label: 'Skip', hint: 'Leave .mcp.json unchanged' },
788
+ ],
789
+ default: 'migrate',
790
+ });
791
+ if (action === 'skip') {
792
+ result.skipped.push('.mcp.json');
793
+ return;
794
+ }
795
+ if (action === 'migrate') {
796
+ servers['moflo'] = servers['claude-flow'];
797
+ delete servers['claude-flow'];
798
+ existing.mcpServers = servers;
799
+ fs.writeFileSync(mcpPath, JSON.stringify(existing, null, 2), 'utf-8');
800
+ result.created.files.push('.mcp.json (migrated claude-flow → moflo)');
801
+ return;
802
+ }
803
+ // side-by-side: fall through to generate new config and merge
804
+ const newConfig = JSON.parse(generateMCPJson(options));
805
+ Object.assign(servers, newConfig.mcpServers ?? {});
806
+ existing.mcpServers = servers;
807
+ fs.writeFileSync(mcpPath, JSON.stringify(existing, null, 2), 'utf-8');
808
+ result.created.files.push('.mcp.json (added moflo alongside claude-flow)');
809
+ return;
810
+ }
811
+ // Non-interactive (CI/pipe): auto-migrate silently
812
+ servers['moflo'] = servers['claude-flow'];
813
+ delete servers['claude-flow'];
814
+ existing.mcpServers = servers;
815
+ fs.writeFileSync(mcpPath, JSON.stringify(existing, null, 2), 'utf-8');
816
+ result.created.files.push('.mcp.json (auto-migrated claude-flow → moflo)');
817
+ return;
818
+ }
819
+ // Already has moflo or no legacy key — skip unless forced
820
+ if (!options.force) {
821
+ result.skipped.push('.mcp.json');
822
+ return;
823
+ }
722
824
  }
723
825
  const content = generateMCPJson(options);
724
826
  fs.writeFileSync(mcpPath, content, 'utf-8');
@@ -1012,6 +1114,8 @@ async function writeHelpers(targetDir, options, result) {
1012
1114
  'post-commit': generatePostCommitHook(),
1013
1115
  'auto-memory-hook.mjs': generateAutoMemoryHook(),
1014
1116
  'gate.cjs': generateGateScript(),
1117
+ 'gate-hook.mjs': generateGateHookScript(),
1118
+ 'prompt-hook.mjs': generatePromptHookScript(),
1015
1119
  'hook-handler.cjs': generateHookHandlerScript(),
1016
1120
  };
1017
1121
  for (const [name, content] of Object.entries(helpers)) {
@@ -1653,7 +1757,7 @@ npx moflo hive-mind consensus --propose "task"
1653
1757
  ### MCP Server Setup
1654
1758
  \`\`\`bash
1655
1759
  # Add Claude Flow MCP
1656
- claude mcp add claude-flow -- npx -y moflo
1760
+ claude mcp add moflo -- npx -y moflo
1657
1761
 
1658
1762
  # Optional servers
1659
1763
  claude mcp add ruv-swarm -- npx -y ruv-swarm mcp start
@@ -28,6 +28,20 @@ export declare function generateHelpers(options: InitOptions): Record<string, st
28
28
  * on every tool call (~500ms npx overhead → ~20ms direct node).
29
29
  */
30
30
  export declare function generateGateScript(): string;
31
+ /**
32
+ * Generate gate-hook.mjs — ESM wrapper that reads Claude Code stdin JSON
33
+ * and passes tool_name + tool_input to gate.cjs via environment variables.
34
+ *
35
+ * Claude Code hooks receive context as JSON on stdin but don't set env vars
36
+ * for tool input. This script bridges that gap. It also translates exit code 1
37
+ * from gate.cjs into exit code 2 (which Claude Code requires to block tools).
38
+ */
39
+ export declare function generateGateHookScript(): string;
40
+ /**
41
+ * Generate prompt-hook.mjs — reads user prompt from Claude Code stdin JSON,
42
+ * runs prompt classification via gate.cjs, and appends namespace hints.
43
+ */
44
+ export declare function generatePromptHookScript(): string;
31
45
  /**
32
46
  * Generate lightweight hook-handler.cjs — hook dispatch without CLI bootstrap.
33
47
  * Handles routing, edit/task tracking, session lifecycle, and notifications.
@@ -178,6 +178,8 @@ export function generateHelpers(options) {
178
178
  helpers['pre-commit'] = generatePreCommitHook();
179
179
  helpers['post-commit'] = generatePostCommitHook();
180
180
  helpers['gate.cjs'] = generateGateScript();
181
+ helpers['gate-hook.mjs'] = generateGateHookScript();
182
+ helpers['prompt-hook.mjs'] = generatePromptHookScript();
181
183
  helpers['hook-handler.cjs'] = generateHookHandlerScript();
182
184
  }
183
185
  if (options.components.statusline) {
@@ -197,7 +199,7 @@ export function generateGateScript() {
197
199
  var fs = require('fs');
198
200
  var path = require('path');
199
201
 
200
- var PROJECT_DIR = process.env.CLAUDE_PROJECT_DIR || process.cwd();
202
+ var PROJECT_DIR = (process.env.CLAUDE_PROJECT_DIR || process.cwd()).replace(/^\\/([a-z])\\//i, '$1:/');
201
203
  var STATE_FILE = path.join(PROJECT_DIR, '.claude', 'workflow-state.json');
202
204
 
203
205
  function readState() {
@@ -241,13 +243,15 @@ var TASK_RE = /\\b(fix|bug|error|implement|add|create|build|write|refactor|debug
241
243
  switch (command) {
242
244
  case 'check-before-agent': {
243
245
  var s = readState();
244
- if (config.task_create_first && !s.tasksCreated) {
245
- console.log('BLOCKED: Call TaskCreate before spawning agents.');
246
- process.exit(1);
246
+ // Hard gate: memory must be searched
247
+ if (config.memory_first && s.memoryRequired && !s.memorySearched) {
248
+ process.stderr.write('BLOCKED: Search memory (mcp__moflo__memory_search) before spawning agents.\\n');
249
+ process.exit(2);
247
250
  }
248
- if (config.memory_first && !s.memorySearched) {
249
- console.log('BLOCKED: Search memory before spawning agents.');
250
- process.exit(1);
251
+ // Soft gate: TaskCreate recommended but not blocking
252
+ // (TaskCreate PostToolUse doesn't fire in Claude Code, so we can't track it reliably)
253
+ if (config.task_create_first && !s.tasksCreated) {
254
+ process.stdout.write('REMINDER: Use TaskCreate before spawning agents. Task tool is blocked until then.\\n');
251
255
  }
252
256
  break;
253
257
  }
@@ -257,14 +261,8 @@ switch (command) {
257
261
  if (s.memorySearched || !s.memoryRequired) break;
258
262
  var target = (process.env.TOOL_INPUT_pattern || '') + ' ' + (process.env.TOOL_INPUT_path || '');
259
263
  if (EXEMPT.some(function(p) { return target.indexOf(p) >= 0; })) break;
260
- var now = Date.now();
261
- var last = s.lastBlockedAt ? new Date(s.lastBlockedAt).getTime() : 0;
262
- if (now - last > 2000) {
263
- s.lastBlockedAt = new Date(now).toISOString();
264
- writeState(s);
265
- console.log('BLOCKED: Search memory before exploring files.');
266
- }
267
- process.exit(1);
264
+ process.stderr.write('BLOCKED: Search memory before exploring files. Use mcp__moflo__memory_search.\\n');
265
+ process.exit(2);
268
266
  }
269
267
  case 'check-before-read': {
270
268
  if (!config.memory_first) break;
@@ -272,14 +270,8 @@ switch (command) {
272
270
  if (s.memorySearched || !s.memoryRequired) break;
273
271
  var fp = process.env.TOOL_INPUT_file_path || '';
274
272
  if (fp.indexOf('.claude/guidance/') < 0 && fp.indexOf('.claude\\\\guidance\\\\') < 0) break;
275
- var now = Date.now();
276
- var last = s.lastBlockedAt ? new Date(s.lastBlockedAt).getTime() : 0;
277
- if (now - last > 2000) {
278
- s.lastBlockedAt = new Date(now).toISOString();
279
- writeState(s);
280
- console.log('BLOCKED: Search memory before reading guidance files.');
281
- }
282
- process.exit(1);
273
+ process.stderr.write('BLOCKED: Search memory before reading guidance files. Use mcp__moflo__memory_search.\\n');
274
+ process.exit(2);
283
275
  }
284
276
  case 'record-task-created': {
285
277
  var s = readState();
@@ -325,7 +317,7 @@ switch (command) {
325
317
  var ic = s.interactionCount;
326
318
  if (ic > 30) console.log('Context: CRITICAL. Commit, store learnings, suggest new session.');
327
319
  else if (ic > 20) console.log('Context: DEPLETED. Checkpoint progress. Recommend /compact or fresh session.');
328
- else if (ic > 10) console.log('Context: MODERATE. Re-state goal before architectural decisions.');
320
+ else if (ic > 10) console.log('Context: MODERATE. Re-state goal before architectural decisions. Use agents for >300 LOC.');
329
321
  }
330
322
  break;
331
323
  }
@@ -342,6 +334,146 @@ switch (command) {
342
334
  }
343
335
  `;
344
336
  }
337
+ /**
338
+ * Generate gate-hook.mjs — ESM wrapper that reads Claude Code stdin JSON
339
+ * and passes tool_name + tool_input to gate.cjs via environment variables.
340
+ *
341
+ * Claude Code hooks receive context as JSON on stdin but don't set env vars
342
+ * for tool input. This script bridges that gap. It also translates exit code 1
343
+ * from gate.cjs into exit code 2 (which Claude Code requires to block tools).
344
+ */
345
+ export function generateGateHookScript() {
346
+ return `#!/usr/bin/env node
347
+ import { execSync } from 'child_process';
348
+ import { resolve } from 'path';
349
+
350
+ var command = process.argv[2];
351
+ if (!command) process.exit(0);
352
+
353
+ // Read stdin JSON from Claude Code
354
+ var stdinData = '';
355
+ try {
356
+ stdinData = await new Promise(function(res) {
357
+ var data = '';
358
+ var timeout = setTimeout(function() { res(data); }, 500);
359
+ process.stdin.setEncoding('utf-8');
360
+ process.stdin.on('data', function(chunk) { data += chunk; });
361
+ process.stdin.on('end', function() { clearTimeout(timeout); res(data); });
362
+ process.stdin.on('error', function() { clearTimeout(timeout); res(''); });
363
+ if (process.stdin.isTTY) { clearTimeout(timeout); res(''); }
364
+ });
365
+ } catch (e) { /* no stdin */ }
366
+
367
+ var hookContext = {};
368
+ try { if (stdinData.trim()) hookContext = JSON.parse(stdinData); } catch (e) {}
369
+
370
+ // Pass tool info as env vars for gate.cjs
371
+ var env = Object.assign({}, process.env);
372
+ if (hookContext.tool_name) env.TOOL_NAME = hookContext.tool_name;
373
+ if (hookContext.tool_input && typeof hookContext.tool_input === 'object') {
374
+ Object.keys(hookContext.tool_input).forEach(function(key) {
375
+ if (typeof hookContext.tool_input[key] === 'string') {
376
+ env['TOOL_INPUT_' + key] = hookContext.tool_input[key];
377
+ }
378
+ });
379
+ }
380
+
381
+ // Run gate.cjs with the enriched environment
382
+ var projectDir = (env.CLAUDE_PROJECT_DIR || process.cwd()).replace(/^\\/([a-z])\\//i, '$1:/');
383
+ var gateScript = resolve(projectDir, '.claude/helpers/gate.cjs');
384
+ try {
385
+ var output = execSync('node "' + gateScript + '" ' + command, {
386
+ env: env, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe']
387
+ });
388
+ if (output.trim()) process.stdout.write(output);
389
+ process.exit(0);
390
+ } catch (err) {
391
+ // gate.cjs exit(2) = block, exit(1) = also block attempt — translate both to exit(2)
392
+ if (err.stderr) process.stderr.write(err.stderr);
393
+ if (err.stdout) process.stderr.write(err.stdout);
394
+ process.exit(err.status === 2 || err.status === 1 ? 2 : 0);
395
+ }
396
+ `;
397
+ }
398
+ /**
399
+ * Generate prompt-hook.mjs — reads user prompt from Claude Code stdin JSON,
400
+ * runs prompt classification via gate.cjs, and appends namespace hints.
401
+ */
402
+ export function generatePromptHookScript() {
403
+ return `#!/usr/bin/env node
404
+ import { execSync } from 'child_process';
405
+ import { resolve } from 'path';
406
+
407
+ // Read stdin JSON from Claude Code
408
+ var stdinData = '';
409
+ try {
410
+ stdinData = await new Promise(function(res) {
411
+ var data = '';
412
+ var timeout = setTimeout(function() { res(data); }, 500);
413
+ process.stdin.setEncoding('utf-8');
414
+ process.stdin.on('data', function(chunk) { data += chunk; });
415
+ process.stdin.on('end', function() { clearTimeout(timeout); res(data); });
416
+ process.stdin.on('error', function() { clearTimeout(timeout); res(''); });
417
+ if (process.stdin.isTTY) { clearTimeout(timeout); res(''); }
418
+ });
419
+ } catch (e) { /* no stdin */ }
420
+
421
+ var hookContext = {};
422
+ try { if (stdinData.trim()) hookContext = JSON.parse(stdinData); } catch (e) {}
423
+
424
+ var userPrompt = hookContext.user_prompt || hookContext.prompt || '';
425
+ var env = Object.assign({}, process.env, { CLAUDE_USER_PROMPT: userPrompt });
426
+
427
+ // Run prompt-reminder via gate.cjs
428
+ var projectDir = (env.CLAUDE_PROJECT_DIR || process.cwd()).replace(/^\\/([a-z])\\//i, '$1:/');
429
+ var gateScript = resolve(projectDir, '.claude/helpers/gate.cjs');
430
+ var output = '';
431
+ try {
432
+ output = execSync('node "' + gateScript + '" prompt-reminder', {
433
+ env: env, encoding: 'utf-8', timeout: 3000, stdio: ['pipe', 'pipe', 'pipe']
434
+ });
435
+ } catch (err) { output = (err && err.stdout) || ''; }
436
+
437
+ // Classify prompt for namespace hint
438
+ var lower = userPrompt.toLowerCase();
439
+
440
+ var KNOWLEDGE_ONLY = /\\b(knowledge|remember|recall)\\b|we (decid|agree|chose|said)/;
441
+ var EXPLICIT_NS = [
442
+ { pattern: /\\b(pattern|convention|best practice|style|coding rule)\\b/, ns: 'patterns', label: 'code patterns and conventions' },
443
+ { pattern: /\\b(code.?map|file structure|project structure|directory)\\b/, ns: 'code-map', label: 'codebase navigation' },
444
+ ];
445
+ var PATTERN_HINTS = [/\\b(template|example|similar to|how do we|how should)\\b/];
446
+ var DOMAIN_HINTS = [
447
+ /\\b(guidance|guide|docs|documentation|rules|how-to)\\b/,
448
+ /\\b(architecture|design|domain|tenant|migrat|schema|deploy)/,
449
+ /\\b(rule|requirement|constraint|compliance)\\b/,
450
+ ];
451
+ var NAV_PATTERNS = [
452
+ /\\b(find|where|which file|look up|locate|endpoint|route|url|path)\\b/,
453
+ /\\b(class|function|method|component|service|entity|module)\\b/,
454
+ ];
455
+
456
+ var nsHint = '';
457
+ if (KNOWLEDGE_ONLY.test(lower)) {
458
+ nsHint = 'Memory namespace hint: use "knowledge" for user-directed project decisions.';
459
+ } else {
460
+ var found = EXPLICIT_NS.find(function(e) { return e.pattern.test(lower); });
461
+ if (found) {
462
+ nsHint = 'Memory namespace hint: use "' + found.ns + '" for ' + found.label + '.';
463
+ } else if (DOMAIN_HINTS.some(function(p) { return p.test(lower); })) {
464
+ nsHint = 'Memory namespace hint: search "guidance" and "knowledge" for domain rules and project decisions.';
465
+ } else if (PATTERN_HINTS.some(function(p) { return p.test(lower); })) {
466
+ nsHint = 'Memory namespace hint: use "patterns" for code patterns and conventions.';
467
+ } else if (NAV_PATTERNS.some(function(p) { return p.test(lower); })) {
468
+ nsHint = 'Memory namespace hint: use "code-map" for codebase navigation.';
469
+ }
470
+ }
471
+
472
+ var parts = [output.trim(), nsHint].filter(Boolean);
473
+ if (parts.length) process.stdout.write(parts.join('\\n') + '\\n');
474
+ process.exit(0);
475
+ `;
476
+ }
345
477
  /**
346
478
  * Generate lightweight hook-handler.cjs — hook dispatch without CLI bootstrap.
347
479
  * Handles routing, edit/task tracking, session lifecycle, and notifications.
@@ -8,28 +8,25 @@
8
8
  */
9
9
  import { existsSync } from 'fs';
10
10
  import { join } from 'path';
11
+ const isWindows = process.platform === 'win32';
11
12
  /**
12
- * Generate MCP server entry using npx (for external packages)
13
+ * Generate MCP server entry using npx (for external packages).
14
+ * On Windows, wraps with `cmd /c` so Claude Code can spawn the process.
13
15
  */
14
16
  function createNpxServerEntry(npxArgs, env, additionalProps = {}) {
15
- return {
16
- command: 'npx',
17
- args: ['-y', ...npxArgs],
18
- env,
19
- ...additionalProps,
20
- };
17
+ return isWindows
18
+ ? { command: 'cmd', args: ['/c', 'npx', '-y', ...npxArgs], env, ...additionalProps }
19
+ : { command: 'npx', args: ['-y', ...npxArgs], env, ...additionalProps };
21
20
  }
22
21
  /**
23
22
  * Generate MCP server entry using direct node invocation (for local moflo).
24
23
  * Avoids npx overhead — faster startup, fewer intermediate processes.
24
+ * On Windows, wraps with `cmd /c` so Claude Code can spawn the process.
25
25
  */
26
26
  function createDirectServerEntry(cliPath, cliArgs, env, additionalProps = {}) {
27
- return {
28
- command: 'node',
29
- args: [cliPath, ...cliArgs],
30
- env,
31
- ...additionalProps,
32
- };
27
+ return isWindows
28
+ ? { command: 'cmd', args: ['/c', 'node', cliPath, ...cliArgs], env, ...additionalProps }
29
+ : { command: 'node', args: [cliPath, ...cliArgs], env, ...additionalProps };
33
30
  }
34
31
  /**
35
32
  * Find the moflo CLI entry point relative to the project root.
@@ -73,10 +70,10 @@ export function generateMCPConfig(options) {
73
70
  const projectRoot = options.targetDir ?? process.cwd();
74
71
  const localCli = findMofloCli(projectRoot);
75
72
  if (localCli) {
76
- mcpServers['claude-flow'] = createDirectServerEntry(localCli, ['mcp', 'start'], mcpEnv, { autoStart: config.autoStart, ...deferProps });
73
+ mcpServers['moflo'] = createDirectServerEntry(localCli, ['mcp', 'start'], mcpEnv, { autoStart: config.autoStart, ...deferProps });
77
74
  }
78
75
  else {
79
- mcpServers['claude-flow'] = createNpxServerEntry(['moflo', 'mcp', 'start'], mcpEnv, { autoStart: config.autoStart, ...deferProps });
76
+ mcpServers['moflo'] = createNpxServerEntry(['moflo', 'mcp', 'start'], mcpEnv, { autoStart: config.autoStart, ...deferProps });
80
77
  }
81
78
  }
82
79
  // Ruv-Swarm MCP server (enhanced coordination) — always npx (external package)
@@ -102,21 +99,22 @@ export function generateMCPJson(options) {
102
99
  export function generateMCPCommands(options) {
103
100
  const commands = [];
104
101
  const config = options.mcp;
102
+ const cmdPrefix = isWindows ? 'cmd /c ' : '';
105
103
  if (config.claudeFlow) {
106
104
  const projectRoot = options.targetDir ?? process.cwd();
107
105
  const localCli = findMofloCli(projectRoot);
108
106
  if (localCli) {
109
- commands.push(`claude mcp add claude-flow -- node ${localCli} mcp start`);
107
+ commands.push(`claude mcp add moflo -- ${cmdPrefix}node ${localCli} mcp start`);
110
108
  }
111
109
  else {
112
- commands.push('claude mcp add claude-flow -- npx -y moflo mcp start');
110
+ commands.push(`claude mcp add moflo -- ${cmdPrefix}npx -y moflo mcp start`);
113
111
  }
114
112
  }
115
113
  if (config.ruvSwarm) {
116
- commands.push('claude mcp add ruv-swarm -- npx -y ruv-swarm mcp start');
114
+ commands.push(`claude mcp add ruv-swarm -- ${cmdPrefix}npx -y ruv-swarm mcp start`);
117
115
  }
118
116
  if (config.flowNexus) {
119
- commands.push('claude mcp add flow-nexus -- npx -y flow-nexus@latest mcp start');
117
+ commands.push(`claude mcp add flow-nexus -- ${cmdPrefix}npx -y flow-nexus@latest mcp start`);
120
118
  }
121
119
  return commands;
122
120
  }
@@ -129,7 +127,9 @@ export function getPlatformInstructions() {
129
127
  : process.platform === 'darwin' ? 'macOS' : 'Linux';
130
128
  return {
131
129
  platform,
132
- note: 'MCP configuration uses npx directly.',
130
+ note: isWindows
131
+ ? 'MCP configuration uses cmd /c wrapper for Windows compatibility.'
132
+ : 'MCP configuration uses npx directly.',
133
133
  };
134
134
  }
135
135
  //# sourceMappingURL=mcp-generator.js.map
@@ -1,24 +1,31 @@
1
- export interface MofloInitOptions {
2
- projectRoot: string;
3
- force?: boolean;
4
- skipIndex?: boolean;
5
- interactive?: boolean;
6
- minimal?: boolean;
7
- }
8
- export interface MofloInitAnswers {
9
- guidance: boolean;
10
- guidanceDirs: string[];
11
- codeMap: boolean;
12
- srcDirs: string[];
13
- gates: boolean;
14
- stopHook: boolean;
15
- }
16
- export interface MofloInitResult {
17
- steps: {
18
- name: string;
19
- status: 'created' | 'updated' | 'skipped' | 'error';
20
- detail?: string;
21
- }[];
22
- }
23
- export declare function initMoflo(options: MofloInitOptions): Promise<MofloInitResult>;
1
+ export interface MofloInitOptions {
2
+ projectRoot: string;
3
+ force?: boolean;
4
+ skipIndex?: boolean;
5
+ interactive?: boolean;
6
+ minimal?: boolean;
7
+ }
8
+ export interface MofloInitAnswers {
9
+ guidance: boolean;
10
+ guidanceDirs: string[];
11
+ codeMap: boolean;
12
+ srcDirs: string[];
13
+ tests: boolean;
14
+ testDirs: string[];
15
+ gates: boolean;
16
+ stopHook: boolean;
17
+ }
18
+ export interface MofloInitResult {
19
+ steps: {
20
+ name: string;
21
+ status: 'created' | 'updated' | 'skipped' | 'error';
22
+ detail?: string;
23
+ }[];
24
+ }
25
+ /**
26
+ * Discover test directories by checking common locations and walking for
27
+ * colocated __tests__ dirs. Returns relative paths.
28
+ */
29
+ export declare function discoverTestDirs(root: string): string[];
30
+ export declare function initMoflo(options: MofloInitOptions): Promise<MofloInitResult>;
24
31
  //# sourceMappingURL=moflo-init.d.ts.map