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.
@@ -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.54",
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.53",
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
- /** Required hook matchers that must exist in settings.json for gate enforcement. */
430
- export const REQUIRED_HOOK_WIRING = [
431
- { event: 'PreToolUse', pattern: 'check-before-scan' },
432
- { event: 'PreToolUse', pattern: 'check-before-read' },
433
- { event: 'PreToolUse', pattern: 'check-dangerous-command' },
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, REQUIRED_HOOK_WIRING, } from './doctor-checks-deep.js';
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 hooks = (settings.hooks ?? {});
694
- const missingPatterns = REQUIRED_HOOK_WIRING.filter(h => !raw.includes(h.pattern));
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
@@ -2,5 +2,5 @@
2
2
  * Auto-generated by build. Do not edit manually.
3
3
  * Source of truth: root package.json → scripts/sync-version.mjs
4
4
  */
5
- export const VERSION = '4.8.54';
5
+ export const VERSION = '4.8.55';
6
6
  //# sourceMappingURL=version.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moflo/cli",
3
- "version": "4.8.54",
3
+ "version": "4.8.55",
4
4
  "type": "module",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -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';