moflo 4.8.54 → 4.8.55
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/bin/session-start-launcher.mjs +15 -0
- package/package.json +2 -2
- package/src/modules/cli/dist/src/commands/doctor-checks-deep.js +5 -13
- package/src/modules/cli/dist/src/commands/doctor.js +5 -41
- package/src/modules/cli/dist/src/init/executor.js +4 -0
- package/src/modules/cli/dist/src/services/hook-wiring.js +81 -0
- package/src/modules/cli/dist/src/services/index.js +2 -0
- package/src/modules/cli/dist/src/version.js +1 -1
- package/src/modules/cli/package.json +1 -1
- package/src/modules/plugins/dist/index.js +0 -1
- package/src/modules/workflows/dist/core/runner.js +0 -1
|
@@ -300,6 +300,21 @@ try {
|
|
|
300
300
|
dirty = true;
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
+
// 3a-iv. Repair missing required hook wirings (same logic as doctor --fix
|
|
304
|
+
// and moflo upgrade — shared via hook-wiring.js to stay DRY)
|
|
305
|
+
try {
|
|
306
|
+
const hwPaths = [
|
|
307
|
+
resolve(projectRoot, 'node_modules/moflo/src/modules/cli/dist/src/services/hook-wiring.js'),
|
|
308
|
+
resolve(projectRoot, 'src/modules/cli/dist/src/services/hook-wiring.js'),
|
|
309
|
+
];
|
|
310
|
+
const hwPath = hwPaths.find(p => existsSync(p));
|
|
311
|
+
if (hwPath) {
|
|
312
|
+
const { repairHookWiring } = await import(`file://${hwPath.replace(/\\/g, '/')}`);
|
|
313
|
+
const { repaired } = repairHookWiring(settings);
|
|
314
|
+
if (repaired.length > 0) dirty = true;
|
|
315
|
+
}
|
|
316
|
+
} catch { /* non-fatal — doctor can still fix later */ }
|
|
317
|
+
|
|
303
318
|
if (dirty) {
|
|
304
319
|
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
305
320
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "moflo",
|
|
3
|
-
"version": "4.8.
|
|
3
|
+
"version": "4.8.55",
|
|
4
4
|
"description": "MoFlo — AI agent orchestration for Claude Code. Forked from ruflo/claude-flow with patches applied to source, plus feature-level orchestration.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"@types/js-yaml": "^4.0.9",
|
|
110
110
|
"@types/node": "^20.19.37",
|
|
111
111
|
"eslint": "^8.0.0",
|
|
112
|
-
"moflo": "^4.8.
|
|
112
|
+
"moflo": "^4.8.54",
|
|
113
113
|
"tsx": "^4.21.0",
|
|
114
114
|
"typescript": "^5.9.3",
|
|
115
115
|
"vitest": "^4.0.0"
|
|
@@ -426,19 +426,11 @@ const REQUIRED_GATE_CASES = [
|
|
|
426
426
|
'prompt-reminder',
|
|
427
427
|
'session-reset',
|
|
428
428
|
];
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
{ event: 'PreToolUse', pattern: 'check-before-pr' },
|
|
435
|
-
{ event: 'PostToolUse', pattern: 'record-task-created' },
|
|
436
|
-
{ event: 'PostToolUse', pattern: 'record-memory-searched' },
|
|
437
|
-
{ event: 'PostToolUse', pattern: 'check-task-transition' },
|
|
438
|
-
{ event: 'PostToolUse', pattern: 'record-learnings-stored' },
|
|
439
|
-
{ event: 'PostToolUse', pattern: 'check-bash-memory' },
|
|
440
|
-
{ event: 'UserPromptSubmit', pattern: 'prompt-reminder' },
|
|
441
|
-
];
|
|
429
|
+
// Import + re-export from the self-contained hook-wiring module (single source of truth).
|
|
430
|
+
// hook-wiring.ts has zero moflo imports so it can be dynamically imported by
|
|
431
|
+
// session-start-launcher.mjs in consumer projects without transitive failures.
|
|
432
|
+
import { REQUIRED_HOOK_WIRING } from '../services/hook-wiring.js';
|
|
433
|
+
export { REQUIRED_HOOK_WIRING };
|
|
442
434
|
/**
|
|
443
435
|
* Verify gate infrastructure health:
|
|
444
436
|
* 1. gate.cjs exists and contains all required cases
|
|
@@ -12,7 +12,8 @@ import { execSync, exec } from 'child_process';
|
|
|
12
12
|
import { promisify } from 'util';
|
|
13
13
|
import os from 'os';
|
|
14
14
|
import { getDaemonLockHolder, releaseDaemonLock, isDaemonProcess } from '../services/daemon-lock.js';
|
|
15
|
-
import { checkSubagentHealth, checkWorkflowExecution, checkMcpToolInvocation, checkHookExecution, checkMcpWorkflowIntegration, checkGateHealth, getMofloRoot,
|
|
15
|
+
import { checkSubagentHealth, checkWorkflowExecution, checkMcpToolInvocation, checkHookExecution, checkMcpWorkflowIntegration, checkGateHealth, getMofloRoot, } from './doctor-checks-deep.js';
|
|
16
|
+
import { repairHookWiring } from '../services/hook-wiring.js';
|
|
16
17
|
// Promisified exec with proper shell and env inheritance for cross-platform support
|
|
17
18
|
const execAsync = promisify(exec);
|
|
18
19
|
/**
|
|
@@ -663,25 +664,10 @@ async function runFixCommand(cmd) {
|
|
|
663
664
|
return false;
|
|
664
665
|
}
|
|
665
666
|
}
|
|
666
|
-
/**
|
|
667
|
-
* Map gate pattern → hook entry to add when missing from settings.json.
|
|
668
|
-
* Gate commands use node with $CLAUDE_PROJECT_DIR helpers for portability.
|
|
669
|
-
*/
|
|
670
|
-
const HOOK_ENTRY_MAP = {
|
|
671
|
-
'check-before-scan': { event: 'PreToolUse', matcher: '^(Glob|Grep)$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-before-scan', timeout: 3000 } },
|
|
672
|
-
'check-before-read': { event: 'PreToolUse', matcher: '^Read$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-before-read', timeout: 3000 } },
|
|
673
|
-
'check-dangerous-command': { event: 'PreToolUse', matcher: '^Bash$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-dangerous-command', timeout: 2000 } },
|
|
674
|
-
'check-before-pr': { event: 'PreToolUse', matcher: '^Bash$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-before-pr', timeout: 2000 } },
|
|
675
|
-
'record-task-created': { event: 'PostToolUse', matcher: '^TaskCreate$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" record-task-created', timeout: 2000 } },
|
|
676
|
-
'record-memory-searched': { event: 'PostToolUse', matcher: 'mcp__moflo__memory_', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" record-memory-searched', timeout: 3000 } },
|
|
677
|
-
'check-task-transition': { event: 'PostToolUse', matcher: '^TaskUpdate$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" check-task-transition', timeout: 2000 } },
|
|
678
|
-
'record-learnings-stored': { event: 'PostToolUse', matcher: '^mcp__moflo__memory_store$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" record-learnings-stored', timeout: 2000 } },
|
|
679
|
-
'check-bash-memory': { event: 'PostToolUse', matcher: '^Bash$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-bash-memory', timeout: 2000 } },
|
|
680
|
-
'prompt-reminder': { event: 'UserPromptSubmit', matcher: '', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" prompt-reminder', timeout: 3000 } },
|
|
681
|
-
};
|
|
682
667
|
/**
|
|
683
668
|
* Fix missing hook wiring in settings.json by patching in entries for
|
|
684
669
|
* any REQUIRED_HOOK_WIRING patterns that aren't present.
|
|
670
|
+
* Delegates to shared repairHookWiring() to stay DRY with the upgrade path.
|
|
685
671
|
*/
|
|
686
672
|
async function fixGateHealthHooks() {
|
|
687
673
|
const settingsPath = join(process.cwd(), '.claude', 'settings.json');
|
|
@@ -690,31 +676,9 @@ async function fixGateHealthHooks() {
|
|
|
690
676
|
try {
|
|
691
677
|
const raw = readFileSync(settingsPath, 'utf8');
|
|
692
678
|
const settings = JSON.parse(raw);
|
|
693
|
-
const
|
|
694
|
-
|
|
695
|
-
if (missingPatterns.length === 0)
|
|
679
|
+
const { repaired } = repairHookWiring(settings);
|
|
680
|
+
if (repaired.length === 0)
|
|
696
681
|
return true; // nothing to fix
|
|
697
|
-
for (const { pattern } of missingPatterns) {
|
|
698
|
-
const entry = HOOK_ENTRY_MAP[pattern];
|
|
699
|
-
if (!entry)
|
|
700
|
-
continue;
|
|
701
|
-
const eventArray = (hooks[entry.event] ?? []);
|
|
702
|
-
// If the matcher already has an entry, append the hook to it; otherwise add a new matcher block
|
|
703
|
-
const existing = eventArray.find((block) => block.matcher === entry.matcher);
|
|
704
|
-
if (existing) {
|
|
705
|
-
const blockHooks = (existing.hooks ?? []);
|
|
706
|
-
blockHooks.push(entry.hook);
|
|
707
|
-
existing.hooks = blockHooks;
|
|
708
|
-
}
|
|
709
|
-
else {
|
|
710
|
-
const newBlock = { hooks: [entry.hook] };
|
|
711
|
-
if (entry.matcher)
|
|
712
|
-
newBlock.matcher = entry.matcher;
|
|
713
|
-
eventArray.push(newBlock);
|
|
714
|
-
}
|
|
715
|
-
hooks[entry.event] = eventArray;
|
|
716
|
-
}
|
|
717
|
-
settings.hooks = hooks;
|
|
718
682
|
writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
|
|
719
683
|
return true;
|
|
720
684
|
}
|
|
@@ -17,6 +17,7 @@ import { generateStatuslineScript } from './statusline-generator.js';
|
|
|
17
17
|
import { generatePreCommitHook, generatePostCommitHook, generateAutoMemoryHook, generateGateScript, generateGateHookScript, generatePromptHookScript, generateHookHandlerScript, } from './helpers-generator.js';
|
|
18
18
|
import { generateClaudeMd } from './claudemd-generator.js';
|
|
19
19
|
import { writeEnvrc } from './envrc-generator.js';
|
|
20
|
+
import { repairHookWiring } from '../services/hook-wiring.js';
|
|
20
21
|
/**
|
|
21
22
|
* Skills to copy based on configuration
|
|
22
23
|
*/
|
|
@@ -328,6 +329,8 @@ function mergeSettingsForUpgrade(existing) {
|
|
|
328
329
|
agentScopes: existingMemory.agentScopes ?? { enabled: true },
|
|
329
330
|
},
|
|
330
331
|
};
|
|
332
|
+
// 5. Repair any missing required hook wirings (same logic doctor --fix uses)
|
|
333
|
+
repairHookWiring(merged);
|
|
331
334
|
return merged;
|
|
332
335
|
}
|
|
333
336
|
/**
|
|
@@ -632,6 +635,7 @@ export async function executeUpgrade(targetDir, _upgradeSettings = false) {
|
|
|
632
635
|
'hooks.SessionEnd (auto-memory sync)',
|
|
633
636
|
'hooks.TeammateIdle (removed — not a valid Claude Code hook)',
|
|
634
637
|
'hooks.TaskCompleted (removed — not a valid Claude Code hook)',
|
|
638
|
+
'hooks (repaired missing gate wirings)',
|
|
635
639
|
'claudeFlow.agentTeams',
|
|
636
640
|
'claudeFlow.memory (learningBridge, memoryGraph, agentScopes)',
|
|
637
641
|
'statusLine',
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared hook wiring repair logic.
|
|
3
|
+
*
|
|
4
|
+
* Used by `doctor --fix`, `mergeSettingsForUpgrade()`, and
|
|
5
|
+
* `session-start-launcher.mjs` so that all three paths stay DRY.
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT: This module must remain self-contained with ZERO imports
|
|
8
|
+
* from other moflo modules. It is dynamically imported at runtime by
|
|
9
|
+
* session-start-launcher.mjs in consumer projects, where transitive
|
|
10
|
+
* dependencies (project-root.js, etc.) may not resolve.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Required hook matchers that must exist in settings.json for gate enforcement.
|
|
14
|
+
* This is the single source of truth — doctor-checks-deep re-exports it.
|
|
15
|
+
*/
|
|
16
|
+
export const REQUIRED_HOOK_WIRING = [
|
|
17
|
+
{ event: 'PreToolUse', pattern: 'check-before-scan' },
|
|
18
|
+
{ event: 'PreToolUse', pattern: 'check-before-read' },
|
|
19
|
+
{ event: 'PreToolUse', pattern: 'check-dangerous-command' },
|
|
20
|
+
{ event: 'PreToolUse', pattern: 'check-before-pr' },
|
|
21
|
+
{ event: 'PostToolUse', pattern: 'record-task-created' },
|
|
22
|
+
{ event: 'PostToolUse', pattern: 'record-memory-searched' },
|
|
23
|
+
{ event: 'PostToolUse', pattern: 'check-task-transition' },
|
|
24
|
+
{ event: 'PostToolUse', pattern: 'record-learnings-stored' },
|
|
25
|
+
{ event: 'PostToolUse', pattern: 'check-bash-memory' },
|
|
26
|
+
{ event: 'UserPromptSubmit', pattern: 'prompt-reminder' },
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Map gate pattern → hook entry to add when missing from settings.json.
|
|
30
|
+
* Gate commands use node with $CLAUDE_PROJECT_DIR helpers for portability.
|
|
31
|
+
*/
|
|
32
|
+
export const HOOK_ENTRY_MAP = {
|
|
33
|
+
'check-before-scan': { event: 'PreToolUse', matcher: '^(Glob|Grep)$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-before-scan', timeout: 3000 } },
|
|
34
|
+
'check-before-read': { event: 'PreToolUse', matcher: '^Read$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-before-read', timeout: 3000 } },
|
|
35
|
+
'check-dangerous-command': { event: 'PreToolUse', matcher: '^Bash$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-dangerous-command', timeout: 2000 } },
|
|
36
|
+
'check-before-pr': { event: 'PreToolUse', matcher: '^Bash$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-before-pr', timeout: 2000 } },
|
|
37
|
+
'record-task-created': { event: 'PostToolUse', matcher: '^TaskCreate$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" record-task-created', timeout: 2000 } },
|
|
38
|
+
'record-memory-searched': { event: 'PostToolUse', matcher: 'mcp__moflo__memory_', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" record-memory-searched', timeout: 3000 } },
|
|
39
|
+
'check-task-transition': { event: 'PostToolUse', matcher: '^TaskUpdate$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" check-task-transition', timeout: 2000 } },
|
|
40
|
+
'record-learnings-stored': { event: 'PostToolUse', matcher: '^mcp__moflo__memory_store$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate.cjs" record-learnings-stored', timeout: 2000 } },
|
|
41
|
+
'check-bash-memory': { event: 'PostToolUse', matcher: '^Bash$', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" check-bash-memory', timeout: 2000 } },
|
|
42
|
+
'prompt-reminder': { event: 'UserPromptSubmit', matcher: '', hook: { type: 'command', command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/gate-hook.mjs" prompt-reminder', timeout: 3000 } },
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Inspect a parsed settings.json object for missing required hook wirings
|
|
46
|
+
* and patch them in. Pure logic — no file I/O.
|
|
47
|
+
*
|
|
48
|
+
* @returns The (potentially mutated) settings and a list of repaired pattern names.
|
|
49
|
+
*/
|
|
50
|
+
export function repairHookWiring(settings) {
|
|
51
|
+
const raw = JSON.stringify(settings);
|
|
52
|
+
const hooks = (settings.hooks ?? {});
|
|
53
|
+
const missingPatterns = REQUIRED_HOOK_WIRING.filter(h => !raw.includes(h.pattern));
|
|
54
|
+
if (missingPatterns.length === 0)
|
|
55
|
+
return { settings, repaired: [] };
|
|
56
|
+
const repaired = [];
|
|
57
|
+
for (const { pattern } of missingPatterns) {
|
|
58
|
+
const entry = HOOK_ENTRY_MAP[pattern];
|
|
59
|
+
if (!entry)
|
|
60
|
+
continue;
|
|
61
|
+
const eventArray = (hooks[entry.event] ?? []);
|
|
62
|
+
// If the matcher already has an entry, append the hook; otherwise add a new matcher block
|
|
63
|
+
const existing = eventArray.find((block) => block.matcher === entry.matcher);
|
|
64
|
+
if (existing) {
|
|
65
|
+
const blockHooks = (existing.hooks ?? []);
|
|
66
|
+
blockHooks.push(entry.hook);
|
|
67
|
+
existing.hooks = blockHooks;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const newBlock = { hooks: [entry.hook] };
|
|
71
|
+
if (entry.matcher)
|
|
72
|
+
newBlock.matcher = entry.matcher;
|
|
73
|
+
eventArray.push(newBlock);
|
|
74
|
+
}
|
|
75
|
+
hooks[entry.event] = eventArray;
|
|
76
|
+
repaired.push(pattern);
|
|
77
|
+
}
|
|
78
|
+
settings.hooks = hooks;
|
|
79
|
+
return { settings, repaired };
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=hook-wiring.js.map
|
|
@@ -13,4 +13,6 @@ export { LearningService, getLearningService, HNSWIndex, hashEmbed, cosineSimila
|
|
|
13
13
|
export { AgentRouter, getAgentRouter, routeTask, AGENT_CAPABILITIES, } from './agent-router.js';
|
|
14
14
|
// Dashboard
|
|
15
15
|
export { startDashboard, createDashboardMemoryAccessor, DEFAULT_DASHBOARD_PORT, } from './daemon-dashboard.js';
|
|
16
|
+
// Hook Wiring (shared between doctor, upgrade, and session-start)
|
|
17
|
+
export { repairHookWiring, HOOK_ENTRY_MAP, REQUIRED_HOOK_WIRING, } from './hook-wiring.js';
|
|
16
18
|
//# sourceMappingURL=index.js.map
|
|
@@ -100,7 +100,6 @@ export { Security, validateString, validateNumber, validateBoolean, validateArra
|
|
|
100
100
|
// ============================================================================
|
|
101
101
|
// Version
|
|
102
102
|
// ============================================================================
|
|
103
|
-
export const MODULE_ID = '@claude-flow/plugins';
|
|
104
103
|
export const VERSION = '3.0.0-alpha.1';
|
|
105
104
|
export const SDK_VERSION = '1.0.0';
|
|
106
105
|
// ============================================================================
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* delegating step execution, validation, loop iteration, rollback,
|
|
6
6
|
* credential masking, and timeout handling to focused modules.
|
|
7
7
|
*/
|
|
8
|
-
export const ENGINE_VERSION = '1.0.0';
|
|
9
8
|
import { ConnectorAccessorImpl } from './connector-accessor.js';
|
|
10
9
|
import { validateWorkflowDefinition, resolveArguments } from '../schema/validator.js';
|
|
11
10
|
import { compareMofloLevels } from './capability-validator.js';
|