moflo 4.8.3 → 4.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/helpers/gate.cjs +113 -25
- package/README.md +10 -2
- package/bin/index-guidance.mjs +899 -892
- package/package.json +2 -2
- package/src/@claude-flow/cli/dist/src/commands/doctor.js +39 -17
- package/src/@claude-flow/cli/package.json +106 -106
package/.claude/helpers/gate.cjs
CHANGED
|
@@ -39,21 +39,119 @@ function loadGateConfig() {
|
|
|
39
39
|
var config = loadGateConfig();
|
|
40
40
|
var command = process.argv[2];
|
|
41
41
|
|
|
42
|
-
var EXEMPT = ['.claude/', '.claude\\', 'CLAUDE.md', 'MEMORY.md', 'workflow-state', 'node_modules'];
|
|
43
42
|
var DANGEROUS = ['rm -rf /', 'format c:', 'del /s /q c:\\', ':(){:|:&};:', 'mkfs.', '> /dev/sda'];
|
|
44
43
|
var DIRECTIVE_RE = /^(yes|no|yeah|yep|nope|sure|ok|okay|correct|right|exactly|perfect)\b/i;
|
|
45
44
|
var TASK_RE = /\b(fix|bug|error|implement|add|create|build|write|refactor|debug|test|feature|issue|security|optimi)\b/i;
|
|
46
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
|
+
|
|
47
147
|
switch (command) {
|
|
48
148
|
case 'check-before-agent': {
|
|
49
149
|
var s = readState();
|
|
50
150
|
if (config.task_create_first && !s.tasksCreated) {
|
|
51
|
-
|
|
52
|
-
process.exit(1);
|
|
151
|
+
blockTool('Call TaskCreate before spawning agents. Task tool is blocked until then.');
|
|
53
152
|
}
|
|
54
153
|
if (config.memory_first && !s.memorySearched) {
|
|
55
|
-
|
|
56
|
-
process.exit(1);
|
|
154
|
+
blockTool('Search memory before spawning agents. Use mcp__claude-flow__memory_search first.');
|
|
57
155
|
}
|
|
58
156
|
break;
|
|
59
157
|
}
|
|
@@ -61,31 +159,21 @@ switch (command) {
|
|
|
61
159
|
if (!config.memory_first) break;
|
|
62
160
|
var s = readState();
|
|
63
161
|
if (s.memorySearched || !s.memoryRequired) break;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (now - last > 2000) {
|
|
69
|
-
s.lastBlockedAt = new Date(now).toISOString();
|
|
70
|
-
writeState(s);
|
|
71
|
-
console.log('BLOCKED: Search memory before exploring files.');
|
|
72
|
-
}
|
|
73
|
-
process.exit(1);
|
|
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".');
|
|
74
166
|
}
|
|
75
167
|
case 'check-before-read': {
|
|
76
168
|
if (!config.memory_first) break;
|
|
77
169
|
var s = readState();
|
|
78
170
|
if (s.memorySearched || !s.memoryRequired) break;
|
|
79
|
-
var fp = process.env.TOOL_INPUT_file_path || '';
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
writeState(s);
|
|
86
|
-
console.log('BLOCKED: Search memory before reading guidance files.');
|
|
87
|
-
}
|
|
88
|
-
process.exit(1);
|
|
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".');
|
|
89
177
|
}
|
|
90
178
|
case 'record-task-created': {
|
|
91
179
|
var s = readState();
|
package/README.md
CHANGED
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
# MoFlo
|
|
6
6
|
|
|
7
|
-
**⚠️ MoFlo is experimental software. APIs, commands, and behavior may change without notice.**
|
|
8
|
-
|
|
9
7
|
**An opinionated fork of [Ruflo/Claude Flow](https://github.com/ruvnet/ruflo), optimized for local development.**
|
|
10
8
|
|
|
11
9
|
MoFlo adds automatic code and guidance cataloging along with memory gating on top of the original Ruflo/Claude Flow orchestration engine. Where the upstream project provides raw building blocks, MoFlo ships opinionated defaults — workflow gates that enforce memory-first patterns, semantic indexing that runs at session start, and learned routing that improves over time — so you get a productive setup from `flo init` without manual tuning.
|
|
@@ -477,6 +475,16 @@ When `flo init` runs, it appends a workflow section to your CLAUDE.md that teach
|
|
|
477
475
|
|
|
478
476
|
MoFlo builds on top of the full [Ruflo/Claude Flow](https://github.com/ruvnet/ruflo) engine. For detailed documentation on the underlying capabilities — swarm topologies, hive-mind consensus, HNSW vector search, neural routing, MCP server internals, and more — check out the [Ruflo repository](https://github.com/ruvnet/ruflo).
|
|
479
477
|
|
|
478
|
+
## Why I Made This
|
|
479
|
+
|
|
480
|
+
[Ruflo/Claude Flow](https://github.com/ruvnet/ruflo) is an incredible piece of work. The engineering that [rUv](https://github.com/ruvnet) and the contributors have put into it — swarm topologies, hive-mind consensus, HNSW vector search, neural routing, and so much more — makes it one of the most comprehensive agent orchestration frameworks available. It's a massive, versatile toolbox built to support a wide range of scenarios: distributed systems, multi-agent swarms, enterprise orchestration, research workflows, and beyond.
|
|
481
|
+
|
|
482
|
+
My use case was just one of those many scenarios: day-to-day local coding, enhancing my normal Claude Code experience on a single project. Claude Flow absolutely supports this — it's all in there — but because the project serves so many different needs, I found myself spending time configuring and tailoring things for my specific workflow each time I pulled in updates. That's not a shortcoming of the project; it's the natural trade-off of a tool designed to be that flexible and powerful.
|
|
483
|
+
|
|
484
|
+
So I forked the excellent foundation and narrowed the focus to my particular corner of it. I baked in the defaults I kept setting manually, added automatic indexing and memory gating at session start, and tuned the out-of-box experience so that `npm install` and `flo init` gets you straight to coding.
|
|
485
|
+
|
|
486
|
+
If you're exploring the full breadth of what agent orchestration can do, go use [Ruflo/Claude Flow](https://github.com/ruvnet/ruflo) directly — it's the real deal. But if your needs are similar to mine — a focused, opinionated local dev setup that just works — then hopefully MoFlo saves you the same configuration time it saves me.
|
|
487
|
+
|
|
480
488
|
## License
|
|
481
489
|
|
|
482
490
|
MIT (inherited from [Ruflo/Claude Flow](https://github.com/ruvnet/ruflo))
|