moflo 4.7.1 โ†’ 4.7.3

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.
@@ -7,54 +7,54 @@ import { generateStatuslineScript } from './statusline-generator.js';
7
7
  * Generate pre-commit hook script
8
8
  */
9
9
  export function generatePreCommitHook() {
10
- return `#!/bin/bash
11
- # Claude Flow Pre-Commit Hook
12
- # Validates code quality before commit
13
-
14
- set -e
15
-
16
- echo "๐Ÿ” Running Claude Flow pre-commit checks..."
17
-
18
- # Get staged files
19
- STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
20
-
21
- # Run validation for each staged file
22
- for FILE in $STAGED_FILES; do
23
- if [[ "$FILE" =~ \\.(ts|js|tsx|jsx)$ ]]; then
24
- echo " Validating: $FILE"
25
- npx moflo hooks pre-edit --file "$FILE" --validate-syntax 2>/dev/null || true
26
- fi
27
- done
28
-
29
- # Run tests if available
30
- if [ -f "package.json" ] && grep -q '"test"' package.json; then
31
- echo "๐Ÿงช Running tests..."
32
- npm test --if-present 2>/dev/null || echo " Tests skipped or failed"
33
- fi
34
-
35
- echo "โœ… Pre-commit checks complete"
10
+ return `#!/bin/bash
11
+ # Claude Flow Pre-Commit Hook
12
+ # Validates code quality before commit
13
+
14
+ set -e
15
+
16
+ echo "๐Ÿ” Running Claude Flow pre-commit checks..."
17
+
18
+ # Get staged files
19
+ STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
20
+
21
+ # Run validation for each staged file
22
+ for FILE in $STAGED_FILES; do
23
+ if [[ "$FILE" =~ \\.(ts|js|tsx|jsx)$ ]]; then
24
+ echo " Validating: $FILE"
25
+ npx moflo hooks pre-edit --file "$FILE" --validate-syntax 2>/dev/null || true
26
+ fi
27
+ done
28
+
29
+ # Run tests if available
30
+ if [ -f "package.json" ] && grep -q '"test"' package.json; then
31
+ echo "๐Ÿงช Running tests..."
32
+ npm test --if-present 2>/dev/null || echo " Tests skipped or failed"
33
+ fi
34
+
35
+ echo "โœ… Pre-commit checks complete"
36
36
  `;
37
37
  }
38
38
  /**
39
39
  * Generate post-commit hook script
40
40
  */
41
41
  export function generatePostCommitHook() {
42
- return `#!/bin/bash
43
- # Claude Flow Post-Commit Hook
44
- # Records commit metrics and trains patterns
45
-
46
- COMMIT_HASH=$(git rev-parse HEAD)
47
- COMMIT_MSG=$(git log -1 --pretty=%B)
48
-
49
- echo "๐Ÿ“Š Recording commit metrics..."
50
-
51
- # Notify claude-flow of commit
52
- npx moflo hooks notify \\
53
- --message "Commit: $COMMIT_MSG" \\
54
- --level info \\
55
- --metadata '{"hash": "'$COMMIT_HASH'"}' 2>/dev/null || true
56
-
57
- echo "โœ… Commit recorded"
42
+ return `#!/bin/bash
43
+ # Claude Flow Post-Commit Hook
44
+ # Records commit metrics and trains patterns
45
+
46
+ COMMIT_HASH=$(git rev-parse HEAD)
47
+ COMMIT_MSG=$(git log -1 --pretty=%B)
48
+
49
+ echo "๐Ÿ“Š Recording commit metrics..."
50
+
51
+ # Notify claude-flow of commit
52
+ npx moflo hooks notify \\
53
+ --message "Commit: $COMMIT_MSG" \\
54
+ --level info \\
55
+ --metadata '{"hash": "'$COMMIT_HASH'"}' 2>/dev/null || true
56
+
57
+ echo "โœ… Commit recorded"
58
58
  `;
59
59
  }
60
60
  /**
@@ -63,110 +63,110 @@ echo "โœ… Commit recorded"
63
63
  * @claude-flow/memory is not installed. Gets overwritten when source copy succeeds.
64
64
  */
65
65
  export function generateAutoMemoryHook() {
66
- return `#!/usr/bin/env node
67
- /**
68
- * Auto Memory Bridge Hook (ADR-048/049) โ€” Minimal Fallback
69
- * Full version is copied from package source when available.
70
- *
71
- * Usage:
72
- * node auto-memory-hook.mjs import # SessionStart
73
- * node auto-memory-hook.mjs sync # SessionEnd / Stop
74
- * node auto-memory-hook.mjs status # Show bridge status
75
- */
76
-
77
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
78
- import { join, dirname } from 'path';
79
- import { fileURLToPath } from 'url';
80
-
81
- const __filename = fileURLToPath(import.meta.url);
82
- const __dirname = dirname(__filename);
83
- const PROJECT_ROOT = join(__dirname, '../..');
84
- const DATA_DIR = join(PROJECT_ROOT, '.claude-flow', 'data');
85
- const STORE_PATH = join(DATA_DIR, 'auto-memory-store.json');
86
-
87
- const DIM = '\\x1b[2m';
88
- const RESET = '\\x1b[0m';
89
- const dim = (msg) => console.log(\` \${DIM}\${msg}\${RESET}\`);
90
-
91
- // Ensure data dir
92
- if (!existsSync(DATA_DIR)) mkdirSync(DATA_DIR, { recursive: true });
93
-
94
- async function loadMemoryPackage() {
95
- // Strategy 1: Use createRequire for CJS-style resolution (handles nested node_modules
96
- // when installed as a transitive dependency via npx ruflo / npx claude-flow)
97
- try {
98
- const { createRequire } = await import('module');
99
- const require = createRequire(join(PROJECT_ROOT, 'package.json'));
100
- return require('@claude-flow/memory');
101
- } catch { /* fall through */ }
102
-
103
- // Strategy 2: ESM import (works when @claude-flow/memory is a direct dependency)
104
- try { return await import('@claude-flow/memory'); } catch { /* fall through */ }
105
-
106
- // Strategy 3: Walk up from PROJECT_ROOT looking for the package in any node_modules
107
- let searchDir = PROJECT_ROOT;
108
- const { parse } = await import('path');
109
- while (searchDir !== parse(searchDir).root) {
110
- const candidate = join(searchDir, 'node_modules', '@claude-flow', 'memory', 'dist', 'index.js');
111
- if (existsSync(candidate)) {
112
- try { return await import(\`file://\${candidate}\`); } catch { /* fall through */ }
113
- }
114
- searchDir = dirname(searchDir);
115
- }
116
-
117
- return null;
118
- }
119
-
120
- async function doImport() {
121
- const memPkg = await loadMemoryPackage();
122
-
123
- if (!memPkg || !memPkg.AutoMemoryBridge) {
124
- dim('Memory package not available โ€” auto memory import skipped (non-critical)');
125
- return;
126
- }
127
-
128
- // Full implementation deferred to copied version
129
- dim('Auto memory import available โ€” run init --upgrade for full support');
130
- }
131
-
132
- async function doSync() {
133
- if (!existsSync(STORE_PATH)) {
134
- dim('No entries to sync');
135
- return;
136
- }
137
-
138
- const memPkg = await loadMemoryPackage();
139
-
140
- if (!memPkg || !memPkg.AutoMemoryBridge) {
141
- dim('Memory package not available โ€” sync skipped (non-critical)');
142
- return;
143
- }
144
-
145
- dim('Auto memory sync available โ€” run init --upgrade for full support');
146
- }
147
-
148
- function doStatus() {
149
- console.log('\\n=== Auto Memory Bridge Status ===\\n');
150
- console.log(' Package: Fallback mode (run init --upgrade for full)');
151
- console.log(\` Store: \${existsSync(STORE_PATH) ? 'Initialized' : 'Not initialized'}\`);
152
- console.log('');
153
- }
154
-
155
- const command = process.argv[2] || 'status';
156
-
157
- try {
158
- switch (command) {
159
- case 'import': await doImport(); break;
160
- case 'sync': await doSync(); break;
161
- case 'status': doStatus(); break;
162
- default:
163
- console.log('Usage: auto-memory-hook.mjs <import|sync|status>');
164
- process.exit(1);
165
- }
166
- } catch (err) {
167
- // Hooks must never crash Claude Code - fail silently
168
- dim(\`Error (non-critical): \${err.message}\`);
169
- }
66
+ return `#!/usr/bin/env node
67
+ /**
68
+ * Auto Memory Bridge Hook (ADR-048/049) โ€” Minimal Fallback
69
+ * Full version is copied from package source when available.
70
+ *
71
+ * Usage:
72
+ * node auto-memory-hook.mjs import # SessionStart
73
+ * node auto-memory-hook.mjs sync # SessionEnd / Stop
74
+ * node auto-memory-hook.mjs status # Show bridge status
75
+ */
76
+
77
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
78
+ import { join, dirname } from 'path';
79
+ import { fileURLToPath } from 'url';
80
+
81
+ const __filename = fileURLToPath(import.meta.url);
82
+ const __dirname = dirname(__filename);
83
+ const PROJECT_ROOT = join(__dirname, '../..');
84
+ const DATA_DIR = join(PROJECT_ROOT, '.claude-flow', 'data');
85
+ const STORE_PATH = join(DATA_DIR, 'auto-memory-store.json');
86
+
87
+ const DIM = '\\x1b[2m';
88
+ const RESET = '\\x1b[0m';
89
+ const dim = (msg) => console.log(\` \${DIM}\${msg}\${RESET}\`);
90
+
91
+ // Ensure data dir
92
+ if (!existsSync(DATA_DIR)) mkdirSync(DATA_DIR, { recursive: true });
93
+
94
+ async function loadMemoryPackage() {
95
+ // Strategy 1: Use createRequire for CJS-style resolution (handles nested node_modules
96
+ // when installed as a transitive dependency via npx ruflo / npx claude-flow)
97
+ try {
98
+ const { createRequire } = await import('module');
99
+ const require = createRequire(join(PROJECT_ROOT, 'package.json'));
100
+ return require('@claude-flow/memory');
101
+ } catch { /* fall through */ }
102
+
103
+ // Strategy 2: ESM import (works when @claude-flow/memory is a direct dependency)
104
+ try { return await import('@claude-flow/memory'); } catch { /* fall through */ }
105
+
106
+ // Strategy 3: Walk up from PROJECT_ROOT looking for the package in any node_modules
107
+ let searchDir = PROJECT_ROOT;
108
+ const { parse } = await import('path');
109
+ while (searchDir !== parse(searchDir).root) {
110
+ const candidate = join(searchDir, 'node_modules', '@claude-flow', 'memory', 'dist', 'index.js');
111
+ if (existsSync(candidate)) {
112
+ try { return await import(\`file://\${candidate}\`); } catch { /* fall through */ }
113
+ }
114
+ searchDir = dirname(searchDir);
115
+ }
116
+
117
+ return null;
118
+ }
119
+
120
+ async function doImport() {
121
+ const memPkg = await loadMemoryPackage();
122
+
123
+ if (!memPkg || !memPkg.AutoMemoryBridge) {
124
+ dim('Memory package not available โ€” auto memory import skipped (non-critical)');
125
+ return;
126
+ }
127
+
128
+ // Full implementation deferred to copied version
129
+ dim('Auto memory import available โ€” run init --upgrade for full support');
130
+ }
131
+
132
+ async function doSync() {
133
+ if (!existsSync(STORE_PATH)) {
134
+ dim('No entries to sync');
135
+ return;
136
+ }
137
+
138
+ const memPkg = await loadMemoryPackage();
139
+
140
+ if (!memPkg || !memPkg.AutoMemoryBridge) {
141
+ dim('Memory package not available โ€” sync skipped (non-critical)');
142
+ return;
143
+ }
144
+
145
+ dim('Auto memory sync available โ€” run init --upgrade for full support');
146
+ }
147
+
148
+ function doStatus() {
149
+ console.log('\\n=== Auto Memory Bridge Status ===\\n');
150
+ console.log(' Package: Fallback mode (run init --upgrade for full)');
151
+ console.log(\` Store: \${existsSync(STORE_PATH) ? 'Initialized' : 'Not initialized'}\`);
152
+ console.log('');
153
+ }
154
+
155
+ const command = process.argv[2] || 'status';
156
+
157
+ try {
158
+ switch (command) {
159
+ case 'import': await doImport(); break;
160
+ case 'sync': await doSync(); break;
161
+ case 'status': doStatus(); break;
162
+ default:
163
+ console.log('Usage: auto-memory-hook.mjs <import|sync|status>');
164
+ process.exit(1);
165
+ }
166
+ } catch (err) {
167
+ // Hooks must never crash Claude Code - fail silently
168
+ dim(\`Error (non-critical): \${err.message}\`);
169
+ }
170
170
  `;
171
171
  }
172
172
  /**
@@ -11,6 +11,7 @@
11
11
  */
12
12
  import * as fs from 'fs';
13
13
  import * as path from 'path';
14
+ import { fileURLToPath } from 'url';
14
15
  // ============================================================================
15
16
  // Init
16
17
  // ============================================================================
@@ -429,17 +430,29 @@ function generateSkill(root, force) {
429
430
  }
430
431
  // Copy static SKILL.md from moflo package instead of generating it
431
432
  let skillContent = '';
433
+ // Resolve this file's directory in ESM-safe way
434
+ let thisDir;
435
+ try {
436
+ thisDir = path.dirname(fileURLToPath(import.meta.url));
437
+ }
438
+ catch {
439
+ // Fallback for CJS or environments where import.meta.url is unavailable
440
+ thisDir = typeof __dirname !== 'undefined' ? __dirname : '';
441
+ }
432
442
  const staticSkillCandidates = [
433
- // Installed via npm
443
+ // Installed via npm (most common)
434
444
  path.join(root, 'node_modules', 'moflo', '.claude', 'skills', 'flo', 'SKILL.md'),
435
- // Running from moflo repo itself
436
- path.join(path.dirname(path.dirname(path.dirname(path.dirname(path.dirname(__dirname))))), '.claude', 'skills', 'flo', 'SKILL.md'),
445
+ // Running from moflo repo itself (dev)
446
+ ...(thisDir ? [path.join(thisDir, '..', '..', '..', '..', '.claude', 'skills', 'flo', 'SKILL.md')] : []),
437
447
  ];
438
448
  for (const candidate of staticSkillCandidates) {
439
- if (fs.existsSync(candidate)) {
440
- skillContent = fs.readFileSync(candidate, 'utf-8');
441
- break;
449
+ try {
450
+ if (fs.existsSync(candidate)) {
451
+ skillContent = fs.readFileSync(candidate, 'utf-8');
452
+ break;
453
+ }
442
454
  }
455
+ catch { /* skip inaccessible paths */ }
443
456
  }
444
457
  if (!skillContent) {
445
458
  return { name: '.claude/skills/flo/', status: 'error', detail: 'Could not find SKILL.md in moflo package' };
@@ -567,12 +580,24 @@ function syncScripts(root, force) {
567
580
  fs.mkdirSync(scriptsDir, { recursive: true });
568
581
  }
569
582
  // Find moflo bin/ directory
583
+ let syncThisDir;
584
+ try {
585
+ syncThisDir = path.dirname(fileURLToPath(import.meta.url));
586
+ }
587
+ catch {
588
+ syncThisDir = typeof __dirname !== 'undefined' ? __dirname : '';
589
+ }
570
590
  const candidates = [
571
591
  path.join(root, 'node_modules', 'moflo', 'bin'),
572
592
  // When running from moflo repo itself
573
- path.join(path.dirname(path.dirname(path.dirname(path.dirname(path.dirname(__dirname))))), 'bin'),
593
+ ...(syncThisDir ? [path.join(syncThisDir, '..', '..', '..', '..', 'bin')] : []),
574
594
  ];
575
- const binDir = candidates.find(d => fs.existsSync(d));
595
+ const binDir = candidates.find(d => { try {
596
+ return fs.existsSync(d);
597
+ }
598
+ catch {
599
+ return false;
600
+ } });
576
601
  if (!binDir) {
577
602
  return { name: '.claude/scripts/', status: 'skipped', detail: 'moflo bin/ not found' };
578
603
  }
@@ -608,8 +633,11 @@ function updateGitignore(root) {
608
633
  const gitignorePath = path.join(root, '.gitignore');
609
634
  const entries = ['.claude-orc/', '.swarm/', '.moflo/'];
610
635
  if (!fs.existsSync(gitignorePath)) {
611
- fs.writeFileSync(gitignorePath, entries.join('\n') + '\n', 'utf-8');
612
- return { name: '.gitignore', status: 'created', detail: entries.join(', ') };
636
+ // Create .gitignore with common defaults + MoFlo entries
637
+ const defaultEntries = ['node_modules/', 'dist/', '.env', '.env.*', ''];
638
+ const content = '# Dependencies\n' + defaultEntries.join('\n') + '\n# MoFlo state\n' + entries.join('\n') + '\n';
639
+ fs.writeFileSync(gitignorePath, content, 'utf-8');
640
+ return { name: '.gitignore', status: 'created', detail: 'Created with node_modules, .env, and MoFlo entries' };
613
641
  }
614
642
  const existing = fs.readFileSync(gitignorePath, 'utf-8');
615
643
  const toAdd = entries.filter(e => !existing.includes(e));
@@ -289,8 +289,9 @@ function getSecurityStatus() {
289
289
  function getSwarmStatus() {
290
290
  const activityData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'swarm-activity.json'));
291
291
  if (activityData && activityData.swarm) {
292
+ const count = activityData.swarm.agent_count || 0;
292
293
  return {
293
- activeAgents: activityData.swarm.agent_count || 0,
294
+ activeAgents: Math.min(count, CONFIG.maxAgents),
294
295
  maxAgents: CONFIG.maxAgents,
295
296
  coordinationActive: activityData.swarm.coordination_active || activityData.swarm.active || false,
296
297
  };
@@ -298,10 +299,12 @@ function getSwarmStatus() {
298
299
 
299
300
  const progressData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'v3-progress.json'));
300
301
  if (progressData && progressData.swarm) {
302
+ const count = progressData.swarm.activeAgents || progressData.swarm.agent_count || 0;
303
+ const max = progressData.swarm.totalAgents || CONFIG.maxAgents;
301
304
  return {
302
- activeAgents: progressData.swarm.activeAgents || progressData.swarm.agent_count || 0,
303
- maxAgents: progressData.swarm.totalAgents || CONFIG.maxAgents,
304
- coordinationActive: progressData.swarm.active || (progressData.swarm.activeAgents > 0),
305
+ activeAgents: Math.min(count, max),
306
+ maxAgents: max,
307
+ coordinationActive: progressData.swarm.active || (count > 0),
305
308
  };
306
309
  }
307
310
 
@@ -62,34 +62,34 @@ function parseArgs() {
62
62
  * Show help message
63
63
  */
64
64
  function showHelp() {
65
- console.log(`
66
- Headless Runtime for MoFlo V4
67
-
68
- Usage:
69
- headless --worker <type> Run a specific worker
70
- headless --daemon Start background daemon
71
- headless --benchmark Run performance benchmarks
72
- headless --status Show system status
73
-
74
- Workers: ${HEADLESS_WORKER_TYPES.join(', ')}
75
-
76
- Options:
77
- -w, --worker <type> Worker type to run
78
- -d, --daemon Run as daemon
79
- -b, --benchmark Run benchmarks
80
- -s, --status Show status
81
- -t, --timeout <ms> Execution timeout (default: 60000)
82
- -v, --verbose Verbose output
83
- -h, --help Show help
84
-
85
- Environment:
86
- CLAUDE_FLOW_HEADLESS=true Enable headless mode
87
- CLAUDE_CODE_HEADLESS=true Enable Claude Code headless
88
-
89
- Examples:
90
- headless --worker audit --timeout 120000
91
- headless --daemon
92
- headless --benchmark
65
+ console.log(`
66
+ Headless Runtime for MoFlo V4
67
+
68
+ Usage:
69
+ headless --worker <type> Run a specific worker
70
+ headless --daemon Start background daemon
71
+ headless --benchmark Run performance benchmarks
72
+ headless --status Show system status
73
+
74
+ Workers: ${HEADLESS_WORKER_TYPES.join(', ')}
75
+
76
+ Options:
77
+ -w, --worker <type> Worker type to run
78
+ -d, --daemon Run as daemon
79
+ -b, --benchmark Run benchmarks
80
+ -s, --status Show status
81
+ -t, --timeout <ms> Execution timeout (default: 60000)
82
+ -v, --verbose Verbose output
83
+ -h, --help Show help
84
+
85
+ Environment:
86
+ CLAUDE_FLOW_HEADLESS=true Enable headless mode
87
+ CLAUDE_CODE_HEADLESS=true Enable Claude Code headless
88
+
89
+ Examples:
90
+ headless --worker audit --timeout 120000
91
+ headless --daemon
92
+ headless --benchmark
93
93
  `);
94
94
  }
95
95
  /**