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
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ import { execSync } from 'child_process';
3
+ import { resolve } from 'path';
4
+
5
+ var command = process.argv[2];
6
+ if (!command) process.exit(0);
7
+
8
+ // Read stdin JSON from Claude Code
9
+ var stdinData = '';
10
+ try {
11
+ stdinData = await new Promise(function(res) {
12
+ var data = '';
13
+ var timeout = setTimeout(function() { res(data); }, 500);
14
+ process.stdin.setEncoding('utf-8');
15
+ process.stdin.on('data', function(chunk) { data += chunk; });
16
+ process.stdin.on('end', function() { clearTimeout(timeout); res(data); });
17
+ process.stdin.on('error', function() { clearTimeout(timeout); res(''); });
18
+ if (process.stdin.isTTY) { clearTimeout(timeout); res(''); }
19
+ });
20
+ } catch (e) { /* no stdin */ }
21
+
22
+ var hookContext = {};
23
+ try { if (stdinData.trim()) hookContext = JSON.parse(stdinData); } catch (e) {}
24
+
25
+ // Pass tool info as env vars for gate.cjs
26
+ var env = Object.assign({}, process.env);
27
+ if (hookContext.tool_name) env.TOOL_NAME = hookContext.tool_name;
28
+ if (hookContext.tool_input && typeof hookContext.tool_input === 'object') {
29
+ Object.keys(hookContext.tool_input).forEach(function(key) {
30
+ if (typeof hookContext.tool_input[key] === 'string') {
31
+ env['TOOL_INPUT_' + key] = hookContext.tool_input[key];
32
+ }
33
+ });
34
+ }
35
+
36
+ // Run gate.cjs with the enriched environment
37
+ var projectDir = (env.CLAUDE_PROJECT_DIR || process.cwd()).replace(/^\/([a-z])\//i, '$1:/');
38
+ var gateScript = resolve(projectDir, '.claude/helpers/gate.cjs');
39
+ try {
40
+ var output = execSync('node "' + gateScript + '" ' + command, {
41
+ env: env, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe']
42
+ });
43
+ if (output.trim()) process.stdout.write(output);
44
+ process.exit(0);
45
+ } catch (err) {
46
+ // gate.cjs exit(2) = block, exit(1) = also block attempt — translate both to exit(2)
47
+ if (err.stderr) process.stderr.write(err.stderr);
48
+ if (err.stdout) process.stderr.write(err.stdout);
49
+ process.exit(err.status === 2 || err.status === 1 ? 2 : 0);
50
+ }
@@ -1,236 +1,138 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
- var fs = require('fs');
4
- var path = require('path');
5
-
6
- var PROJECT_DIR = process.env.CLAUDE_PROJECT_DIR || process.cwd();
7
- var STATE_FILE = path.join(PROJECT_DIR, '.claude', 'workflow-state.json');
8
-
9
- function readState() {
10
- try {
11
- if (fs.existsSync(STATE_FILE)) return JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
12
- } catch (e) { /* reset on corruption */ }
13
- return { tasksCreated: false, taskCount: 0, memorySearched: false, memoryRequired: true, interactionCount: 0, sessionStart: null, lastBlockedAt: null };
14
- }
15
-
16
- function writeState(s) {
17
- try {
18
- var dir = path.dirname(STATE_FILE);
19
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
20
- fs.writeFileSync(STATE_FILE, JSON.stringify(s, null, 2));
21
- } catch (e) { /* non-fatal */ }
22
- }
23
-
24
- // Load moflo.yaml gate config (defaults: all enabled)
25
- function loadGateConfig() {
26
- var defaults = { memory_first: true, task_create_first: true, context_tracking: true };
27
- try {
28
- var yamlPath = path.join(PROJECT_DIR, 'moflo.yaml');
29
- if (fs.existsSync(yamlPath)) {
30
- var content = fs.readFileSync(yamlPath, 'utf-8');
31
- if (/memory_first:\s*false/i.test(content)) defaults.memory_first = false;
32
- if (/task_create_first:\s*false/i.test(content)) defaults.task_create_first = false;
33
- if (/context_tracking:\s*false/i.test(content)) defaults.context_tracking = false;
34
- }
35
- } catch (e) { /* use defaults */ }
36
- return defaults;
37
- }
38
-
39
- var config = loadGateConfig();
40
- var command = process.argv[2];
41
-
42
- var DANGEROUS = ['rm -rf /', 'format c:', 'del /s /q c:\\', ':(){:|:&};:', 'mkfs.', '> /dev/sda'];
43
- var DIRECTIVE_RE = /^(yes|no|yeah|yep|nope|sure|ok|okay|correct|right|exactly|perfect)\b/i;
44
- var TASK_RE = /\b(fix|bug|error|implement|add|create|build|write|refactor|debug|test|feature|issue|security|optimi)\b/i;
45
-
46
- // Deny a tool call cleanly via structured JSON (no "hook error" noise).
47
- // Exit 0 + permissionDecision:"deny" is the Claude Code way to block a tool.
48
- function blockTool(reason) {
49
- console.log(JSON.stringify({
50
- hookSpecificOutput: {
51
- hookEventName: 'PreToolUse',
52
- permissionDecision: 'deny',
53
- permissionDecisionReason: reason
54
- }
55
- }));
56
- process.exit(0);
57
- }
58
-
59
- // Determine if a Grep/Glob target is a mechanical/administrative search
60
- // that should bypass the memory-first gate. The idea: if memory/guidance
61
- // wouldn't improve the search outcome, don't block it.
62
- //
63
- // Strategy: path is the strongest signal. When a path clearly points to
64
- // tooling/deps/tests, allow it. When it points to source/docs/scripts,
65
- // block it (require memory). Pattern-based rules only kick in when there's
66
- // no path or when the path is neutral.
67
- function isMechanicalSearch() {
68
- var searchPath = (process.env.TOOL_INPUT_path || '').replace(/\\/g, '/').toLowerCase();
69
- var pattern = (process.env.TOOL_INPUT_pattern || '').toLowerCase();
70
- var filePath = (process.env.TOOL_INPUT_file_path || '').replace(/\\/g, '/').toLowerCase();
71
- var anyPath = searchPath || filePath;
72
-
73
- // --- PATH-BASED RULES (strongest signal, checked first) ---
74
-
75
- if (anyPath) {
76
- // Always mechanical: dependencies, tooling internals, CI, test dirs
77
- var mechanicalPaths = [
78
- 'node_modules/', '.claude/', '.claude-flow/', '.swarm/', '.github/',
79
- 'tests/', 'test/', 'config/', 'examples/',
80
- ];
81
- for (var i = 0; i < mechanicalPaths.length; i++) {
82
- if (anyPath.indexOf(mechanicalPaths[i]) >= 0) return true;
83
- }
84
-
85
- // Targeting a specific config/meta file by path extension
86
- if (/\.(json|yaml|yml|toml|lock|env|cjs|mjs)$/i.test(anyPath)) return true;
87
-
88
- // If path points to source, docs, or scripts — these are knowledge-rich.
89
- // Do NOT fall through to pattern-based exemptions; the path is authoritative.
90
- // (Still allow test-file glob patterns even within source dirs.)
91
- var knowledgePaths = [
92
- 'src/', 'back-office/', 'front-office/', 'docs/', 'scripts/', 'lib/',
93
- ];
94
- var inKnowledgePath = false;
95
- for (var k = 0; k < knowledgePaths.length; k++) {
96
- if (anyPath.indexOf(knowledgePaths[k]) >= 0) { inKnowledgePath = true; break; }
97
- }
98
- if (inKnowledgePath) {
99
- // Exception: searching for test/spec files within source is structural
100
- if (/\*\*?[/\\]?\*?\.(test|spec)\.(ts|js|tsx|jsx)\b/i.test(pattern)) return true;
101
- // Everything else in a knowledge path requires memory
102
- return false;
103
- }
104
- }
105
-
106
- // --- PATTERN-BASED RULES (no path, or path is neutral) ---
107
-
108
- // Glob patterns looking for config/build/tooling files by extension
109
- if (/\*\*?[/\\]?\*?\.(json|yaml|yml|toml|lock|env|config|cjs|mjs)\b/i.test(pattern)) return true;
110
-
111
- // Glob patterns for specific config filenames (eslintrc, Dockerfile, etc.)
112
- if (/\*\*?[/\\]?\*?\.?(eslint|prettier|babel|stylelint|editor|git|docker|nginx|jest|vitest|vite|webpack|rollup|esbuild|tsconfig|browserslist)/i.test(pattern)) return true;
113
-
114
- // Glob patterns for lock files and test files (structural lookups)
115
- if (/\*\*?[/\\]?\*?[\w-]*[-.]lock\b/i.test(pattern)) return true;
116
- if (/\*\*?[/\\]?\*?\.(test|spec)\.(ts|js|tsx|jsx)\b/i.test(pattern)) return true;
117
-
118
- // Config/tooling name searches (bare names without a path).
119
- // Only exempt if ALL tokens in a pipe-separated pattern are config names.
120
- // "webpack|vite" = exempt. "webpack|merchant" = NOT exempt.
121
- var CONFIG_NAME = /^\.?(eslint|prettier|babel|stylelint|editor|gitignore|gitattributes|dockerignore|dockerfile|docker-compose|nginx|jest|vitest|vite|webpack|rollup|esbuild|tsconfig|changelog|license|makefile|procfile|browserslist|commitlint|husky|lint-staged)\b/i;
122
- var tokens = pattern.split(/[|,\s]+/).filter(function(t) { return t.length > 0; });
123
- if (tokens.length > 0 && tokens.every(function(t) { return CONFIG_NAME.test(t.trim()); })) return true;
124
-
125
- // Known tooling/meta file names as substrings (but avoid false matches like "process.env")
126
- var toolingNames = [
127
- 'claude.md', 'memory.md', 'workflow-state', '.mcp.json',
128
- 'package.json', 'package-lock', 'daemon.lock', 'moflo.yaml',
129
- ];
130
- var target = pattern + ' ' + anyPath;
131
- for (var j = 0; j < toolingNames.length; j++) {
132
- if (target.indexOf(toolingNames[j]) >= 0) return true;
133
- }
134
-
135
- // Env file lookups (but NOT "process.env" which is source code searching)
136
- if (/^\.env\b/.test(pattern) || /\*\*?[/\\]?\.env/.test(pattern)) return true;
137
-
138
- // Git/process/system-level pattern searches
139
- if (/^(git\b|pid|daemon|lock|wmic|tasklist|powershell|ps\s)/i.test(pattern)) return true;
140
-
141
- // CI/CD folder exploration
142
- if (/\.github/i.test(pattern)) return true;
143
-
144
- return false;
145
- }
146
-
147
- switch (command) {
148
- case 'check-before-agent': {
149
- var s = readState();
150
- if (config.task_create_first && !s.tasksCreated) {
151
- blockTool('Call TaskCreate before spawning agents. Task tool is blocked until then.');
152
- }
153
- if (config.memory_first && !s.memorySearched) {
154
- blockTool('Search memory before spawning agents. Use mcp__claude-flow__memory_search first.');
155
- }
156
- break;
157
- }
158
- case 'check-before-scan': {
159
- if (!config.memory_first) break;
160
- var s = readState();
161
- if (s.memorySearched || !s.memoryRequired) break;
162
- if (isMechanicalSearch()) break;
163
- s.lastBlockedAt = new Date().toISOString();
164
- writeState(s);
165
- blockTool('Search memory before exploring files. Use mcp__claude-flow__memory_search with namespace "code-map", "patterns", "knowledge", or "guidance".');
166
- }
167
- case 'check-before-read': {
168
- if (!config.memory_first) break;
169
- var s = readState();
170
- if (s.memorySearched || !s.memoryRequired) break;
171
- var fp = (process.env.TOOL_INPUT_file_path || '').replace(/\\/g, '/');
172
- // Block reads of guidance files (that's exactly what memory indexes)
173
- if (fp.indexOf('.claude/guidance/') < 0) break;
174
- s.lastBlockedAt = new Date().toISOString();
175
- writeState(s);
176
- blockTool('Search memory before reading guidance files. Use mcp__claude-flow__memory_search with namespace "guidance".');
177
- }
178
- case 'record-task-created': {
179
- var s = readState();
180
- s.tasksCreated = true;
181
- s.taskCount = (s.taskCount || 0) + 1;
182
- writeState(s);
183
- break;
184
- }
185
- case 'record-memory-searched': {
186
- var s = readState();
187
- s.memorySearched = true;
188
- writeState(s);
189
- break;
190
- }
191
- case 'check-bash-memory': {
192
- var cmd = process.env.TOOL_INPUT_command || '';
193
- if (/semantic-search|memory search|memory retrieve|memory-search/.test(cmd)) {
194
- var s = readState();
195
- s.memorySearched = true;
196
- writeState(s);
197
- }
198
- break;
199
- }
200
- case 'check-dangerous-command': {
201
- var cmd = (process.env.TOOL_INPUT_command || '').toLowerCase();
202
- for (var i = 0; i < DANGEROUS.length; i++) {
203
- if (cmd.indexOf(DANGEROUS[i]) >= 0) {
204
- console.log('[BLOCKED] Dangerous command: ' + DANGEROUS[i]);
205
- process.exit(2);
206
- }
207
- }
208
- break;
209
- }
210
- case 'prompt-reminder': {
211
- var s = readState();
212
- s.memorySearched = false;
213
- var prompt = process.env.CLAUDE_USER_PROMPT || '';
214
- s.memoryRequired = prompt.length >= 4 && !DIRECTIVE_RE.test(prompt) && (TASK_RE.test(prompt) || prompt.length > 80);
215
- s.interactionCount = (s.interactionCount || 0) + 1;
216
- writeState(s);
217
- if (!s.tasksCreated) console.log('REMINDER: Use TaskCreate before spawning agents. Task tool is blocked until then.');
218
- if (config.context_tracking) {
219
- var ic = s.interactionCount;
220
- if (ic > 30) console.log('Context: CRITICAL. Commit, store learnings, suggest new session.');
221
- else if (ic > 20) console.log('Context: DEPLETED. Checkpoint progress. Recommend /compact or fresh session.');
222
- else if (ic > 10) console.log('Context: MODERATE. Re-state goal before architectural decisions.');
223
- }
224
- break;
225
- }
226
- case 'compact-guidance': {
227
- console.log('Pre-Compact: Check CLAUDE.md for rules. Use memory search to recover context after compact.');
228
- break;
229
- }
230
- case 'session-reset': {
231
- writeState({ tasksCreated: false, taskCount: 0, memorySearched: false, memoryRequired: true, interactionCount: 0, sessionStart: new Date().toISOString(), lastBlockedAt: null });
232
- break;
233
- }
234
- default:
235
- break;
236
- }
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ var fs = require('fs');
4
+ var path = require('path');
5
+
6
+ var PROJECT_DIR = (process.env.CLAUDE_PROJECT_DIR || process.cwd()).replace(/^\/([a-z])\//i, '$1:/');
7
+ var STATE_FILE = path.join(PROJECT_DIR, '.claude', 'workflow-state.json');
8
+
9
+ function readState() {
10
+ try {
11
+ if (fs.existsSync(STATE_FILE)) return JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
12
+ } catch (e) { /* reset on corruption */ }
13
+ return { tasksCreated: false, taskCount: 0, memorySearched: false, memoryRequired: true, interactionCount: 0, sessionStart: null, lastBlockedAt: null };
14
+ }
15
+
16
+ function writeState(s) {
17
+ try {
18
+ var dir = path.dirname(STATE_FILE);
19
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
20
+ fs.writeFileSync(STATE_FILE, JSON.stringify(s, null, 2));
21
+ } catch (e) { /* non-fatal */ }
22
+ }
23
+
24
+ // Load moflo.yaml gate config (defaults: all enabled)
25
+ function loadGateConfig() {
26
+ var defaults = { memory_first: true, task_create_first: true, context_tracking: true };
27
+ try {
28
+ var yamlPath = path.join(PROJECT_DIR, 'moflo.yaml');
29
+ if (fs.existsSync(yamlPath)) {
30
+ var content = fs.readFileSync(yamlPath, 'utf-8');
31
+ if (/memory_first:\s*false/i.test(content)) defaults.memory_first = false;
32
+ if (/task_create_first:\s*false/i.test(content)) defaults.task_create_first = false;
33
+ if (/context_tracking:\s*false/i.test(content)) defaults.context_tracking = false;
34
+ }
35
+ } catch (e) { /* use defaults */ }
36
+ return defaults;
37
+ }
38
+
39
+ var config = loadGateConfig();
40
+ var command = process.argv[2];
41
+
42
+ var EXEMPT = ['.claude/', '.claude\\', 'CLAUDE.md', 'MEMORY.md', 'workflow-state', 'node_modules'];
43
+ var DANGEROUS = ['rm -rf /', 'format c:', 'del /s /q c:\\', ':(){:|:&};:', 'mkfs.', '> /dev/sda'];
44
+ var DIRECTIVE_RE = /^(yes|no|yeah|yep|nope|sure|ok|okay|correct|right|exactly|perfect)\b/i;
45
+ var TASK_RE = /\b(fix|bug|error|implement|add|create|build|write|refactor|debug|test|feature|issue|security|optimi)\b/i;
46
+
47
+ switch (command) {
48
+ case 'check-before-agent': {
49
+ var s = readState();
50
+ // Hard gate: memory must be searched
51
+ if (config.memory_first && s.memoryRequired && !s.memorySearched) {
52
+ process.stderr.write('BLOCKED: Search memory (mcp__moflo__memory_search) before spawning agents.\n');
53
+ process.exit(2);
54
+ }
55
+ // Soft gate: TaskCreate recommended but not blocking
56
+ // (TaskCreate PostToolUse doesn't fire in Claude Code, so we can't track it reliably)
57
+ if (config.task_create_first && !s.tasksCreated) {
58
+ process.stdout.write('REMINDER: Use TaskCreate before spawning agents. Task tool is blocked until then.\n');
59
+ }
60
+ break;
61
+ }
62
+ case 'check-before-scan': {
63
+ if (!config.memory_first) break;
64
+ var s = readState();
65
+ if (s.memorySearched || !s.memoryRequired) break;
66
+ var target = (process.env.TOOL_INPUT_pattern || '') + ' ' + (process.env.TOOL_INPUT_path || '');
67
+ if (EXEMPT.some(function(p) { return target.indexOf(p) >= 0; })) break;
68
+ process.stderr.write('BLOCKED: Search memory before exploring files. Use mcp__moflo__memory_search.\n');
69
+ process.exit(2);
70
+ }
71
+ case 'check-before-read': {
72
+ if (!config.memory_first) break;
73
+ var s = readState();
74
+ if (s.memorySearched || !s.memoryRequired) break;
75
+ var fp = process.env.TOOL_INPUT_file_path || '';
76
+ if (fp.indexOf('.claude/guidance/') < 0 && fp.indexOf('.claude\\guidance\\') < 0) break;
77
+ process.stderr.write('BLOCKED: Search memory before reading guidance files. Use mcp__moflo__memory_search.\n');
78
+ process.exit(2);
79
+ }
80
+ case 'record-task-created': {
81
+ var s = readState();
82
+ s.tasksCreated = true;
83
+ s.taskCount = (s.taskCount || 0) + 1;
84
+ writeState(s);
85
+ break;
86
+ }
87
+ case 'record-memory-searched': {
88
+ var s = readState();
89
+ s.memorySearched = true;
90
+ writeState(s);
91
+ break;
92
+ }
93
+ case 'check-bash-memory': {
94
+ var cmd = process.env.TOOL_INPUT_command || '';
95
+ if (/semantic-search|memory search|memory retrieve|memory-search/.test(cmd)) {
96
+ var s = readState();
97
+ s.memorySearched = true;
98
+ writeState(s);
99
+ }
100
+ break;
101
+ }
102
+ case 'check-dangerous-command': {
103
+ var cmd = (process.env.TOOL_INPUT_command || '').toLowerCase();
104
+ for (var i = 0; i < DANGEROUS.length; i++) {
105
+ if (cmd.indexOf(DANGEROUS[i]) >= 0) {
106
+ console.log('[BLOCKED] Dangerous command: ' + DANGEROUS[i]);
107
+ process.exit(2);
108
+ }
109
+ }
110
+ break;
111
+ }
112
+ case 'prompt-reminder': {
113
+ var s = readState();
114
+ s.memorySearched = false;
115
+ var prompt = process.env.CLAUDE_USER_PROMPT || '';
116
+ s.memoryRequired = prompt.length >= 4 && !DIRECTIVE_RE.test(prompt) && (TASK_RE.test(prompt) || prompt.length > 80);
117
+ s.interactionCount = (s.interactionCount || 0) + 1;
118
+ writeState(s);
119
+ if (!s.tasksCreated) console.log('REMINDER: Use TaskCreate before spawning agents. Task tool is blocked until then.');
120
+ if (config.context_tracking) {
121
+ var ic = s.interactionCount;
122
+ if (ic > 30) console.log('Context: CRITICAL. Commit, store learnings, suggest new session.');
123
+ else if (ic > 20) console.log('Context: DEPLETED. Checkpoint progress. Recommend /compact or fresh session.');
124
+ else if (ic > 10) console.log('Context: MODERATE. Re-state goal before architectural decisions. Use agents for >300 LOC.');
125
+ }
126
+ break;
127
+ }
128
+ case 'compact-guidance': {
129
+ console.log('Pre-Compact: Check CLAUDE.md for rules. Use memory search to recover context after compact.');
130
+ break;
131
+ }
132
+ case 'session-reset': {
133
+ writeState({ tasksCreated: false, taskCount: 0, memorySearched: false, memoryRequired: true, interactionCount: 0, sessionStart: new Date().toISOString(), lastBlockedAt: null });
134
+ break;
135
+ }
136
+ default:
137
+ break;
138
+ }