@sparkleideas/claude-flow-patch 3.1.0-alpha.44.patch.10

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 (120) hide show
  1. package/AGENTS.md +162 -0
  2. package/CLAUDE.md +506 -0
  3. package/README.md +351 -0
  4. package/bin/claude-flow-patch.mjs +148 -0
  5. package/check-patches.sh +195 -0
  6. package/lib/categories.json +15 -0
  7. package/lib/common.py +97 -0
  8. package/lib/discover.mjs +181 -0
  9. package/lib/discover.sh +160 -0
  10. package/package.json +86 -0
  11. package/patch/010-CF-001-doctor-yaml/README.md +11 -0
  12. package/patch/010-CF-001-doctor-yaml/fix.py +20 -0
  13. package/patch/010-CF-001-doctor-yaml/sentinel +1 -0
  14. package/patch/020-CF-002-config-export-yaml/README.md +11 -0
  15. package/patch/020-CF-002-config-export-yaml/fix.py +130 -0
  16. package/patch/020-CF-002-config-export-yaml/sentinel +1 -0
  17. package/patch/030-DM-001-daemon-log-zero/README.md +12 -0
  18. package/patch/030-DM-001-daemon-log-zero/fix.py +37 -0
  19. package/patch/030-DM-001-daemon-log-zero/sentinel +1 -0
  20. package/patch/040-DM-002-cpu-load-threshold/README.md +11 -0
  21. package/patch/040-DM-002-cpu-load-threshold/fix.py +6 -0
  22. package/patch/040-DM-002-cpu-load-threshold/sentinel +1 -0
  23. package/patch/050-DM-003-macos-freemem/README.md +11 -0
  24. package/patch/050-DM-003-macos-freemem/fix.py +7 -0
  25. package/patch/050-DM-003-macos-freemem/sentinel +1 -0
  26. package/patch/060-DM-004-preload-worker-stub/README.md +11 -0
  27. package/patch/060-DM-004-preload-worker-stub/fix.py +34 -0
  28. package/patch/060-DM-004-preload-worker-stub/sentinel +1 -0
  29. package/patch/070-DM-005-consolidation-worker-stub/README.md +11 -0
  30. package/patch/070-DM-005-consolidation-worker-stub/fix.py +46 -0
  31. package/patch/070-DM-005-consolidation-worker-stub/sentinel +1 -0
  32. package/patch/080-EM-001-embedding-ignores-config/README.md +11 -0
  33. package/patch/080-EM-001-embedding-ignores-config/fix.py +111 -0
  34. package/patch/080-EM-001-embedding-ignores-config/sentinel +1 -0
  35. package/patch/090-EM-002-transformers-cache-eacces/README.md +11 -0
  36. package/patch/090-EM-002-transformers-cache-eacces/fix.sh +12 -0
  37. package/patch/090-EM-002-transformers-cache-eacces/sentinel +1 -0
  38. package/patch/100-GV-001-hnsw-ghost-vectors/README.md +11 -0
  39. package/patch/100-GV-001-hnsw-ghost-vectors/fix.py +34 -0
  40. package/patch/100-GV-001-hnsw-ghost-vectors/sentinel +1 -0
  41. package/patch/110-HK-001-post-edit-file-path/README.md +44 -0
  42. package/patch/110-HK-001-post-edit-file-path/fix.py +23 -0
  43. package/patch/110-HK-001-post-edit-file-path/sentinel +1 -0
  44. package/patch/120-HK-002-hooks-tools-stub/README.md +36 -0
  45. package/patch/120-HK-002-hooks-tools-stub/fix.py +155 -0
  46. package/patch/120-HK-002-hooks-tools-stub/sentinel +1 -0
  47. package/patch/130-HK-003-metrics-hardcoded/README.md +30 -0
  48. package/patch/130-HK-003-metrics-hardcoded/fix.py +82 -0
  49. package/patch/130-HK-003-metrics-hardcoded/sentinel +1 -0
  50. package/patch/135-HK-004-respect-daemon-autostart/README.md +11 -0
  51. package/patch/135-HK-004-respect-daemon-autostart/fix.py +14 -0
  52. package/patch/135-HK-004-respect-daemon-autostart/sentinel +1 -0
  53. package/patch/137-HK-005-daemon-pid-guard/README.md +11 -0
  54. package/patch/137-HK-005-daemon-pid-guard/fix.py +53 -0
  55. package/patch/137-HK-005-daemon-pid-guard/sentinel +2 -0
  56. package/patch/140-HW-001-stdin-hang/README.md +11 -0
  57. package/patch/140-HW-001-stdin-hang/fix.py +6 -0
  58. package/patch/140-HW-001-stdin-hang/sentinel +1 -0
  59. package/patch/150-HW-002-failures-swallowed/README.md +11 -0
  60. package/patch/150-HW-002-failures-swallowed/fix.py +42 -0
  61. package/patch/150-HW-002-failures-swallowed/sentinel +1 -0
  62. package/patch/160-HW-003-aggressive-intervals/README.md +11 -0
  63. package/patch/160-HW-003-aggressive-intervals/fix.py +52 -0
  64. package/patch/160-HW-003-aggressive-intervals/sentinel +3 -0
  65. package/patch/170-IN-001-intelligence-stub/README.md +64 -0
  66. package/patch/170-IN-001-intelligence-stub/fix.py +63 -0
  67. package/patch/170-IN-001-intelligence-stub/sentinel +1 -0
  68. package/patch/180-MM-001-memory-persist-path/README.md +27 -0
  69. package/patch/180-MM-001-memory-persist-path/fix.py +54 -0
  70. package/patch/180-MM-001-memory-persist-path/sentinel +1 -0
  71. package/patch/190-NS-001-discovery-default-namespace/README.md +16 -0
  72. package/patch/190-NS-001-discovery-default-namespace/fix.py +68 -0
  73. package/patch/190-NS-001-discovery-default-namespace/sentinel +2 -0
  74. package/patch/200-NS-002-targeted-require-namespace/README.md +19 -0
  75. package/patch/200-NS-002-targeted-require-namespace/fix.py +158 -0
  76. package/patch/200-NS-002-targeted-require-namespace/sentinel +2 -0
  77. package/patch/210-NS-003-namespace-typo-pattern/README.md +15 -0
  78. package/patch/210-NS-003-namespace-typo-pattern/fix.py +23 -0
  79. package/patch/210-NS-003-namespace-typo-pattern/sentinel +1 -0
  80. package/patch/220-RS-001-better-sqlite3-node24/README.md +54 -0
  81. package/patch/220-RS-001-better-sqlite3-node24/fix.py +27 -0
  82. package/patch/220-RS-001-better-sqlite3-node24/rebuild.sh +31 -0
  83. package/patch/220-RS-001-better-sqlite3-node24/sentinel +2 -0
  84. package/patch/230-RV-001-force-learn-tick/README.md +31 -0
  85. package/patch/230-RV-001-force-learn-tick/fix.py +14 -0
  86. package/patch/230-RV-001-force-learn-tick/sentinel +2 -0
  87. package/patch/240-RV-002-trajectory-load/README.md +28 -0
  88. package/patch/240-RV-002-trajectory-load/fix.py +14 -0
  89. package/patch/240-RV-002-trajectory-load/sentinel +2 -0
  90. package/patch/250-RV-003-trajectory-stats-sync/README.md +31 -0
  91. package/patch/250-RV-003-trajectory-stats-sync/fix.py +18 -0
  92. package/patch/250-RV-003-trajectory-stats-sync/sentinel +2 -0
  93. package/patch/260-SG-001-init-settings/README.md +29 -0
  94. package/patch/260-SG-001-init-settings/fix.py +143 -0
  95. package/patch/260-SG-001-init-settings/sentinel +4 -0
  96. package/patch/270-SG-003-init-helpers-all-paths/README.md +60 -0
  97. package/patch/270-SG-003-init-helpers-all-paths/fix.py +165 -0
  98. package/patch/270-SG-003-init-helpers-all-paths/sentinel +3 -0
  99. package/patch/280-UI-001-intelligence-stats-crash/README.md +11 -0
  100. package/patch/280-UI-001-intelligence-stats-crash/fix.py +57 -0
  101. package/patch/280-UI-001-intelligence-stats-crash/sentinel +1 -0
  102. package/patch/290-UI-002-neural-status-not-loaded/README.md +11 -0
  103. package/patch/290-UI-002-neural-status-not-loaded/fix.py +19 -0
  104. package/patch/290-UI-002-neural-status-not-loaded/sentinel +1 -0
  105. package/patch/300-DM-006-log-rotation/README.md +12 -0
  106. package/patch/300-DM-006-log-rotation/fix.py +72 -0
  107. package/patch/300-DM-006-log-rotation/sentinel +2 -0
  108. package/patch/310-HW-004-runwithtimeout-orphan/README.md +11 -0
  109. package/patch/310-HW-004-runwithtimeout-orphan/fix.py +10 -0
  110. package/patch/310-HW-004-runwithtimeout-orphan/sentinel +1 -0
  111. package/patch/320-SG-004-wizard-parity/README.md +40 -0
  112. package/patch/320-SG-004-wizard-parity/fix.py +208 -0
  113. package/patch/320-SG-004-wizard-parity/sentinel +3 -0
  114. package/patch/330-SG-005-start-all-subcommand/README.md +32 -0
  115. package/patch/330-SG-005-start-all-subcommand/fix.py +58 -0
  116. package/patch/330-SG-005-start-all-subcommand/sentinel +1 -0
  117. package/patch-all.sh +199 -0
  118. package/repair-post-init.sh +263 -0
  119. package/scripts/preflight.mjs +249 -0
  120. package/scripts/upstream-log.mjs +257 -0
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "@sparkleideas/claude-flow-patch",
3
+ "version": "3.1.0-alpha.44.patch.10",
4
+ "description": "Patch toolkit for @claude-flow/cli init/runtime defects with verify and post-init repair commands",
5
+ "scripts": {
6
+ "preflight": "node scripts/preflight.mjs",
7
+ "preflight:check": "node scripts/preflight.mjs --check",
8
+ "prepublishOnly": "npm run preflight && npm test",
9
+ "test": "node --test tests/*.test.mjs",
10
+ "package": "bash npm/package.sh",
11
+ "package:dry": "bash npm/package.sh --dry-run",
12
+ "publish:npm": "bash npm/publish.sh",
13
+ "publish:dry": "bash npm/publish.sh --dry-run",
14
+ "upstream-log": "node scripts/upstream-log.mjs",
15
+ "guidance:analyze": "guidance analyze",
16
+ "guidance:optimize": "guidance autopilot --once --apply --source manual",
17
+ "guidance:autopilot:once": "guidance autopilot --once --source manual",
18
+ "guidance:autopilot:daemon": "guidance autopilot --daemon --apply --source daemon",
19
+ "guidance:ab-benchmark": "guidance benchmark",
20
+ "guidance:scaffold": "guidance scaffold",
21
+ "guidance:all": "guidance run all",
22
+ "guidance:status": "guidance run status",
23
+ "guidance:hooks": "guidance run hooks",
24
+ "guidance:trust": "guidance run trust",
25
+ "guidance:adversarial": "guidance run adversarial",
26
+ "guidance:proof": "guidance run proof",
27
+ "guidance:conformance": "guidance run conformance",
28
+ "guidance:evolution": "guidance run evolution",
29
+ "guidance:runtime": "guidance runtime demo",
30
+ "guidance:codex:status": "guidance codex status",
31
+ "guidance:codex:pre-command": "guidance codex pre-command",
32
+ "guidance:codex:pre-edit": "guidance codex pre-edit",
33
+ "guidance:codex:pre-task": "guidance codex pre-task",
34
+ "guidance:codex:post-edit": "guidance codex post-edit",
35
+ "guidance:codex:post-task": "guidance codex post-task",
36
+ "guidance:codex:session-start": "guidance codex session-start",
37
+ "guidance:codex:session-end": "guidance codex session-end"
38
+ },
39
+ "private": false,
40
+ "license": "MIT",
41
+ "type": "module",
42
+ "author": "Sparkling Ideas <henrik@sparklingideas.co.uk>",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/sparkling/claude-flow-patch.git"
46
+ },
47
+ "homepage": "https://sparklingideas.co.uk/patch/claude-flow",
48
+ "bugs": {
49
+ "url": "https://github.com/sparkling/claude-flow-patch/issues"
50
+ },
51
+ "engines": {
52
+ "node": ">=20"
53
+ },
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "bin": {
58
+ "claude-flow-patch": "bin/claude-flow-patch.mjs"
59
+ },
60
+ "files": [
61
+ "bin",
62
+ "lib",
63
+ "patch",
64
+ "scripts",
65
+ "patch-all.sh",
66
+ "check-patches.sh",
67
+ "repair-post-init.sh",
68
+ "README.md",
69
+ "AGENTS.md",
70
+ "CLAUDE.md"
71
+ ],
72
+ "keywords": [
73
+ "claude-flow",
74
+ "@claude-flow/cli",
75
+ "patch",
76
+ "hotfix",
77
+ "init",
78
+ "hook-handler",
79
+ "npm-cache",
80
+ "hooks",
81
+ "ruvector",
82
+ "ruv-swarm",
83
+ "automation"
84
+ ],
85
+ "packageManager": "npm@10"
86
+ }
@@ -0,0 +1,11 @@
1
+ # CF-001: Doctor ignores YAML config files
2
+ **Severity**: Low
3
+ **GitHub**: [#1141](https://github.com/ruvnet/claude-flow/issues/1141)
4
+ ## Root Cause
5
+ `checkConfigFile()` only checks `.json` paths, but `claude-flow init` generates `config.yaml`. Also, `JSON.parse()` runs on all config content, crashing on YAML.
6
+ ## Fix
7
+ Add `.claude-flow/config.yaml` and `.claude-flow/config.yml` to the config search paths. Skip `JSON.parse()` for non-JSON files.
8
+ ## Files Patched
9
+ - commands/doctor.js
10
+ ## Ops
11
+ 2 ops in fix.py
@@ -0,0 +1,20 @@
1
+ # CF-001: Doctor ignores YAML config files
2
+ patch("7: YAML config",
3
+ DOC,
4
+ """ const configPaths = [
5
+ '.claude-flow/config.json',
6
+ 'claude-flow.config.json',
7
+ '.claude-flow.json'
8
+ ];""",
9
+ """ const configPaths = [
10
+ '.claude-flow/config.json',
11
+ 'claude-flow.config.json',
12
+ '.claude-flow.json',
13
+ '.claude-flow/config.yaml',
14
+ '.claude-flow/config.yml'
15
+ ];""")
16
+
17
+ patch("7: YAML JSON.parse skip",
18
+ DOC,
19
+ " JSON.parse(content);",
20
+ " if (configPath.endsWith('.json')) { JSON.parse(content); }")
@@ -0,0 +1 @@
1
+ grep "config.yaml" commands/doctor.js
@@ -0,0 +1,11 @@
1
+ # CF-002: Config export shows hardcoded defaults
2
+ **Severity**: Medium
3
+ **GitHub**: [#1142](https://github.com/ruvnet/claude-flow/issues/1142)
4
+ ## Root Cause
5
+ `config export` and `config get` use hardcoded defaults (topology: 'hybrid', cacheSize: 256) instead of reading `.claude-flow/config.yaml`. The commands are misleading when the project has custom config.
6
+ ## Fix
7
+ Add `readYamlConfig()` helper function. Merge YAML config values over defaults in both `getCommand` and `exportCommand` actions.
8
+ ## Files Patched
9
+ - commands/config.js
10
+ ## Ops
11
+ 3 ops in fix.py
@@ -0,0 +1,130 @@
1
+ # CF-002: Config export shows hardcoded defaults instead of reading YAML
2
+ # Absorbed from old patch-16. Applied manually to npx cache.
3
+ # NOTE: This patch was originally applied via sed, not via patch().
4
+ # The patch() calls below replicate the same changes.
5
+
6
+ # Add fs/path imports after existing imports
7
+ patch("16a: config.js add readYamlConfig",
8
+ CONF,
9
+ "const getCommand = {",
10
+ """import { readFileSync, existsSync } from 'fs';
11
+ import { join } from 'path';
12
+
13
+ // Helper to read config.yaml if it exists
14
+ function readYamlConfig() {
15
+ const configPath = join(process.cwd(), '.claude-flow', 'config.yaml');
16
+ if (!existsSync(configPath)) { return {}; }
17
+ try {
18
+ const content = readFileSync(configPath, 'utf8');
19
+ const config = {};
20
+ const lines = content.split('\\n');
21
+ let currentSection = null;
22
+ for (const line of lines) {
23
+ const trimmed = line.trim();
24
+ if (!trimmed || trimmed.startsWith('#')) continue;
25
+ if (!trimmed.includes(':')) continue;
26
+ const indent = line.match(/^\\s*/)[0].length;
27
+ if (indent === 0) {
28
+ const [key, ...rest] = trimmed.split(':');
29
+ const value = rest.join(':').trim();
30
+ if (value && value !== '') {
31
+ config[key.trim()] = value.replace(/^["']|["']$/g, '');
32
+ } else {
33
+ currentSection = key.trim();
34
+ config[currentSection] = {};
35
+ }
36
+ } else if (currentSection && indent > 0) {
37
+ const [key, ...rest] = trimmed.split(':');
38
+ const value = rest.join(':').trim();
39
+ if (value && value !== '') {
40
+ config[currentSection][key.trim()] = value.replace(/^["']|["']$/g, '');
41
+ }
42
+ }
43
+ }
44
+ return config;
45
+ } catch (error) { return {}; }
46
+ }
47
+
48
+ const getCommand = {""")
49
+
50
+ # Update getCommand to merge YAML config
51
+ patch("16b: config get merge yaml",
52
+ CONF,
53
+ """const configValues = {
54
+ 'version': '3.0.0',
55
+ 'v3Mode': true,
56
+ 'swarm.topology': 'hybrid',
57
+ 'swarm.maxAgents': 15,
58
+ 'swarm.autoScale': true,
59
+ 'memory.backend': 'hybrid',
60
+ 'memory.cacheSize': 256,
61
+ 'mcp.transport': 'stdio',
62
+ 'agents.defaultType': 'coder',
63
+ 'agents.maxConcurrent': 15
64
+ };""",
65
+ """// Default config values
66
+ const defaults = {
67
+ 'version': '3.0.0',
68
+ 'v3Mode': true,
69
+ 'swarm.topology': 'hybrid',
70
+ 'swarm.maxAgents': 15,
71
+ 'swarm.autoScale': true,
72
+ 'memory.backend': 'hybrid',
73
+ 'memory.cacheSize': 256,
74
+ 'mcp.transport': 'stdio',
75
+ 'agents.defaultType': 'coder',
76
+ 'agents.maxConcurrent': 15
77
+ };
78
+ // Read YAML config and merge with defaults
79
+ const yamlConfig = readYamlConfig();
80
+ const configValues = { ...defaults };
81
+ if (yamlConfig.swarm) {
82
+ if (yamlConfig.swarm.topology) configValues['swarm.topology'] = yamlConfig.swarm.topology;
83
+ if (yamlConfig.swarm.maxAgents) configValues['swarm.maxAgents'] = parseInt(yamlConfig.swarm.maxAgents) || defaults['swarm.maxAgents'];
84
+ if (yamlConfig.swarm.autoScale !== undefined) configValues['swarm.autoScale'] = yamlConfig.swarm.autoScale === 'true' || yamlConfig.swarm.autoScale === true;
85
+ }
86
+ if (yamlConfig.memory) {
87
+ if (yamlConfig.memory.backend) configValues['memory.backend'] = yamlConfig.memory.backend;
88
+ if (yamlConfig.memory.cacheSize) configValues['memory.cacheSize'] = parseInt(yamlConfig.memory.cacheSize) || defaults['memory.cacheSize'];
89
+ }
90
+ if (yamlConfig.mcp && yamlConfig.mcp.transport) {
91
+ configValues['mcp.transport'] = yamlConfig.mcp.transport;
92
+ }
93
+ if (yamlConfig.version) {
94
+ configValues['version'] = yamlConfig.version;
95
+ }""")
96
+
97
+ # Update exportCommand to merge YAML config
98
+ patch("16c: config export merge yaml",
99
+ CONF,
100
+ """const config = {
101
+ version: '3.0.0',
102
+ exportedAt: new Date().toISOString(),
103
+ agents: { defaultType: 'coder', maxConcurrent: 15 },
104
+ swarm: { topology: 'hybrid', maxAgents: 15 },
105
+ memory: { backend: 'hybrid', cacheSize: 256 },
106
+ mcp: { transport: 'stdio', tools: 'all' }
107
+ };""",
108
+ """// Start with defaults
109
+ const config = {
110
+ version: '3.0.0',
111
+ exportedAt: new Date().toISOString(),
112
+ agents: { defaultType: 'coder', maxConcurrent: 15 },
113
+ swarm: { topology: 'hybrid', maxAgents: 15 },
114
+ memory: { backend: 'hybrid', cacheSize: 256 },
115
+ mcp: { transport: 'stdio', tools: 'all' }
116
+ };
117
+ // Read YAML config and merge
118
+ const yamlConfig = readYamlConfig();
119
+ if (yamlConfig.version) { config.version = yamlConfig.version; }
120
+ if (yamlConfig.swarm) {
121
+ if (yamlConfig.swarm.topology) config.swarm.topology = yamlConfig.swarm.topology;
122
+ if (yamlConfig.swarm.maxAgents) config.swarm.maxAgents = parseInt(yamlConfig.swarm.maxAgents) || 15;
123
+ }
124
+ if (yamlConfig.memory) {
125
+ if (yamlConfig.memory.backend) config.memory.backend = yamlConfig.memory.backend;
126
+ if (yamlConfig.memory.cacheSize) config.memory.cacheSize = parseInt(yamlConfig.memory.cacheSize) || 256;
127
+ }
128
+ if (yamlConfig.mcp && yamlConfig.mcp.transport) {
129
+ config.mcp.transport = yamlConfig.mcp.transport;
130
+ }""")
@@ -0,0 +1 @@
1
+ grep "readYamlConfig" commands/config.js
@@ -0,0 +1,12 @@
1
+ # DM-001: daemon.log always 0 bytes
2
+ **Severity**: Medium
3
+ **GitHub**: [#1116](https://github.com/ruvnet/claude-flow/issues/1116)
4
+ ## Root Cause
5
+ Two issues: (1) `log()` method uses `require('fs')` which is undefined in ESM modules — `appendFileSync` silently fails. (2) Path mismatch — daemon spawn writes to `.claude-flow/daemon.log` but `log()` targets `.claude-flow/logs/daemon.log`.
6
+ ## Fix
7
+ (A) Add `appendFileSync` to ESM import. (B) Replace `require('fs')` call with imported function. (C) Align spawn log path to `.claude-flow/logs/daemon.log`.
8
+ ## Files Patched
9
+ - services/worker-daemon.js (Parts A, B)
10
+ - commands/daemon.js (Part C)
11
+ ## Ops
12
+ 3 ops in fix.py
@@ -0,0 +1,37 @@
1
+ # DM-001: daemon.log always 0 bytes (ESM require + path mismatch)
2
+ # GitHub: #1116
3
+ patch("4A: appendFileSync import",
4
+ WD,
5
+ "import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';",
6
+ "import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync } from 'fs';")
7
+
8
+ patch("4B: remove require('fs')",
9
+ WD,
10
+ """ const fs = require('fs');
11
+ fs.appendFileSync(logFile, logMessage + '\\n');""",
12
+ " appendFileSync(logFile, logMessage + '\\n');")
13
+
14
+ patch("4C: daemon log path",
15
+ DJ,
16
+ """ const logFile = join(stateDir, 'daemon.log');
17
+ // Validate all paths
18
+ validatePath(stateDir, 'State directory');
19
+ validatePath(pidFile, 'PID file');
20
+ validatePath(logFile, 'Log file');
21
+ // Ensure state directory exists
22
+ if (!fs.existsSync(stateDir)) {
23
+ fs.mkdirSync(stateDir, { recursive: true });
24
+ }""",
25
+ """ const logsDir = join(stateDir, 'logs');
26
+ if (!fs.existsSync(logsDir)) {
27
+ fs.mkdirSync(logsDir, { recursive: true });
28
+ }
29
+ const logFile = join(logsDir, 'daemon.log');
30
+ // Validate all paths
31
+ validatePath(stateDir, 'State directory');
32
+ validatePath(pidFile, 'PID file');
33
+ validatePath(logFile, 'Log file');
34
+ // Ensure state directory exists
35
+ if (!fs.existsSync(stateDir)) {
36
+ fs.mkdirSync(stateDir, { recursive: true });
37
+ }""")
@@ -0,0 +1 @@
1
+ grep "appendFileSync" services/worker-daemon.js
@@ -0,0 +1,11 @@
1
+ # DM-002: maxCpuLoad=2.0 blocks all workers on multi-core
2
+ **Severity**: Critical
3
+ **GitHub**: [#1138](https://github.com/ruvnet/claude-flow/issues/1138)
4
+ ## Root Cause
5
+ `maxCpuLoad` defaults to 2.0, but load average reflects total system load across all cores. An 8-core Mac idles at 3-5. A 32-core server idles at 1-3 but spikes above 2.0 easily. No worker ever passes the resource gate.
6
+ ## Fix
7
+ Raise threshold to match hardware. Currently set to 28.0 for 32-core server. Adjust per machine (8-core Mac: 6.0).
8
+ ## Files Patched
9
+ - services/worker-daemon.js
10
+ ## Ops
11
+ 1 op in fix.py
@@ -0,0 +1,6 @@
1
+ # DM-002: maxCpuLoad=2.0 blocks all workers on multi-core
2
+ # NOTE: 32-core server uses 28.0. Adjust per machine (8-core Mac: 6.0).
3
+ patch("5: CPU load threshold",
4
+ WD,
5
+ "maxCpuLoad: 2.0",
6
+ "maxCpuLoad: 28.0")
@@ -0,0 +1 @@
1
+ grep "maxCpuLoad" services/worker-daemon.js
@@ -0,0 +1,11 @@
1
+ # DM-003: macOS freemem() always ~0% — workers blocked
2
+ **Severity**: Critical (macOS only)
3
+ **GitHub**: [#1077](https://github.com/ruvnet/claude-flow/issues/1077)
4
+ ## Root Cause
5
+ `os.freemem()` on macOS excludes file cache, always reporting ~0.3% free. macOS reclaims cache on demand, so the number is meaningless. The `minFreeMemoryPercent: 20` gate never passes.
6
+ ## Fix
7
+ Skip the free memory check on macOS (`os.platform() !== 'darwin'`).
8
+ ## Files Patched
9
+ - services/worker-daemon.js
10
+ ## Ops
11
+ 1 op in fix.py (skipped on Linux)
@@ -0,0 +1,7 @@
1
+ # DM-003: macOS freemem() always ~0% — workers blocked
2
+ # GitHub: #1077
3
+ # SKIPPED on Linux (only affects macOS)
4
+ patch("6: macOS memory",
5
+ WD,
6
+ "if (freePercent < this.config.resourceThresholds.minFreeMemoryPercent) {",
7
+ "if (os.platform() !== 'darwin' && freePercent < this.config.resourceThresholds.minFreeMemoryPercent) {")
@@ -0,0 +1 @@
1
+ grep "darwin" services/worker-daemon.js
@@ -0,0 +1,11 @@
1
+ # DM-004: Preload worker stub + missing from defaults
2
+ **Severity**: Enhancement
3
+ **GitHub**: [#1139](https://github.com/ruvnet/claude-flow/issues/1139)
4
+ ## Root Cause
5
+ The `preload` worker type exists in the switch statement but was missing from `DEFAULT_WORKERS` — never scheduled. The `runPreloadWorkerLocal()` was a stub returning `{resourcesPreloaded: 0}`. Also missing: ultralearn, deepdive, refactor, benchmark workers.
6
+ ## Fix
7
+ Add missing workers to DEFAULT_WORKERS. Implement real preload that calls `loadEmbeddingModel()` and `getHNSWIndex()` from memory-initializer.js.
8
+ ## Files Patched
9
+ - services/worker-daemon.js
10
+ ## Ops
11
+ 2 ops in fix.py
@@ -0,0 +1,34 @@
1
+ # DM-004: Preload worker stub + missing from defaults
2
+ # Adds missing workers to DEFAULT_WORKERS and implements real preload
3
+ patch("11: add missing workers to defaults",
4
+ WD,
5
+ " { type: 'document', intervalMs: 60 * 60 * 1000, offsetMs: 0, priority: 'low', description: 'Auto-documentation', enabled: false },\n];",
6
+ """ { type: 'document', intervalMs: 60 * 60 * 1000, offsetMs: 0, priority: 'low', description: 'Auto-documentation', enabled: false },
7
+ { type: 'ultralearn', intervalMs: 0, offsetMs: 0, priority: 'normal', description: 'Deep knowledge acquisition (headless, manual trigger)', enabled: false },
8
+ { type: 'deepdive', intervalMs: 4 * 60 * 60 * 1000, offsetMs: 0, priority: 'low', description: 'Deep code analysis', enabled: false },
9
+ { type: 'refactor', intervalMs: 4 * 60 * 60 * 1000, offsetMs: 0, priority: 'low', description: 'Refactoring suggestions', enabled: false },
10
+ { type: 'benchmark', intervalMs: 2 * 60 * 60 * 1000, offsetMs: 0, priority: 'low', description: 'Performance benchmarking', enabled: false },
11
+ { type: 'preload', intervalMs: 10 * 60 * 1000, offsetMs: 0, priority: 'high', description: 'Embedding model + HNSW preload', enabled: true },
12
+ ];""")
13
+
14
+ patch("11: real preload worker",
15
+ WD,
16
+ """ async runPreloadWorkerLocal() {
17
+ return {
18
+ timestamp: new Date().toISOString(),
19
+ mode: 'local',
20
+ resourcesPreloaded: 0,
21
+ cacheStatus: 'active',
22
+ };
23
+ }""",
24
+ """ async runPreloadWorkerLocal() {
25
+ const result = { timestamp: new Date().toISOString(), mode: 'local', resourcesPreloaded: 0, cacheStatus: 'active' };
26
+ try {
27
+ const mi = await import('../memory/memory-initializer.js');
28
+ const modelResult = await mi.loadEmbeddingModel({ verbose: false });
29
+ if (modelResult.success) { result.resourcesPreloaded++; result.embeddingModel = modelResult.modelName; }
30
+ const hnswResult = await mi.getHNSWIndex();
31
+ if (hnswResult) { result.resourcesPreloaded++; result.hnswEntries = hnswResult.entries?.size ?? 0; }
32
+ } catch (e) { result.error = e?.message || String(e); }
33
+ return result;
34
+ }""")
@@ -0,0 +1 @@
1
+ grep "loadEmbeddingModel" services/worker-daemon.js
@@ -0,0 +1,11 @@
1
+ # DM-005: Consolidation worker stub (no decay/rebuild)
2
+ **Severity**: Enhancement
3
+ **GitHub**: [#1140](https://github.com/ruvnet/claude-flow/issues/1140)
4
+ ## Root Cause
5
+ The consolidation worker was a stub writing `{patternsConsolidated: 0}` to a JSON file. No actual memory consolidation occurred.
6
+ ## Fix
7
+ Call `applyTemporalDecay()` to reduce confidence of stale patterns, then `clearHNSWIndex()` + `getHNSWIndex({ forceRebuild: true })` to rebuild the index with current data.
8
+ ## Files Patched
9
+ - services/worker-daemon.js
10
+ ## Ops
11
+ 1 op in fix.py
@@ -0,0 +1,46 @@
1
+ # DM-005: Consolidation worker stub (no decay/rebuild)
2
+ # Makes consolidate worker actually call pattern decay + HNSW rebuild
3
+ patch("12: real consolidate worker",
4
+ WD,
5
+ """ async runConsolidateWorker() {
6
+ // Memory consolidation - clean up old patterns
7
+ const consolidateFile = join(this.projectRoot, '.claude-flow', 'metrics', 'consolidation.json');
8
+ const metricsDir = join(this.projectRoot, '.claude-flow', 'metrics');
9
+ if (!existsSync(metricsDir)) {
10
+ mkdirSync(metricsDir, { recursive: true });
11
+ }
12
+ const result = {
13
+ timestamp: new Date().toISOString(),
14
+ patternsConsolidated: 0,
15
+ memoryCleaned: 0,
16
+ duplicatesRemoved: 0,
17
+ };
18
+ writeFileSync(consolidateFile, JSON.stringify(result, null, 2));
19
+ return result;
20
+ }""",
21
+ """ async runConsolidateWorker() {
22
+ const consolidateFile = join(this.projectRoot, '.claude-flow', 'metrics', 'consolidation.json');
23
+ const metricsDir = join(this.projectRoot, '.claude-flow', 'metrics');
24
+ if (!existsSync(metricsDir)) {
25
+ mkdirSync(metricsDir, { recursive: true });
26
+ }
27
+ const result = {
28
+ timestamp: new Date().toISOString(),
29
+ patternsConsolidated: 0,
30
+ memoryCleaned: 0,
31
+ duplicatesRemoved: 0,
32
+ };
33
+ try {
34
+ const mi = await import('../memory/memory-initializer.js');
35
+ // 1. Apply temporal decay (reduce confidence of stale patterns)
36
+ const decayResult = await mi.applyTemporalDecay();
37
+ if (decayResult?.success) result.patternsConsolidated = decayResult.patternsDecayed || 0;
38
+ // 2. Rebuild HNSW index with current data
39
+ mi.clearHNSWIndex();
40
+ const hnsw = await mi.getHNSWIndex({ forceRebuild: true });
41
+ if (hnsw) result.hnswRebuilt = hnsw.entries?.size ?? 0;
42
+ result.memoryCleaned = 1;
43
+ } catch (e) { result.error = e?.message || String(e); }
44
+ writeFileSync(consolidateFile, JSON.stringify(result, null, 2));
45
+ return result;
46
+ }""")
@@ -0,0 +1 @@
1
+ grep "applyTemporalDecay" services/worker-daemon.js
@@ -0,0 +1,11 @@
1
+ # EM-001: Embedding system ignores project config (model + HNSW dims)
2
+ **Severity**: High
3
+ **GitHub**: [#1143](https://github.com/ruvnet/claude-flow/issues/1143)
4
+ ## Root Cause
5
+ `loadEmbeddingModel()` hardcodes `Xenova/all-MiniLM-L6-v2` (384-dim). Projects configured with a different model via `embeddings.json` (e.g. `all-mpnet-base-v2` 768-dim) still get MiniLM 384-dim vectors. HNSW index also hardcodes 384 dimensions, causing dimension mismatch when the actual model produces 768-dim vectors. Every search falls back to brute-force SQLite.
6
+ ## Fix
7
+ Read model name and dimensions from `.claude-flow/embeddings.json` at load time. Fall back to all-MiniLM-L6-v2 (384-dim) if no config exists. Delete stale persistent HNSW files on forceRebuild. Guard metadata loading and early-return to skip on forceRebuild.
8
+ ## Files Patched
9
+ - memory/memory-initializer.js
10
+ ## Ops
11
+ 6 ops in fix.py (merged from old patches 8 + 9)
@@ -0,0 +1,111 @@
1
+ # EM-001: Embedding system ignores project config (model + HNSW dims)
2
+ # Merged from old patches 8 (config-driven model) + 9 (HNSW dimension fix)
3
+
4
+ # --- Old Patch 8: Config-driven embedding model loader ---
5
+ patch("8: config-driven model",
6
+ MI,
7
+ """ // Try to import @xenova/transformers for ONNX embeddings
8
+ const transformers = await import('@xenova/transformers').catch(() => null);
9
+ if (transformers) {
10
+ if (verbose) {
11
+ console.log('Loading ONNX embedding model (all-MiniLM-L6-v2)...');
12
+ }
13
+ // Use small, fast model for local embeddings
14
+ const { pipeline } = transformers;
15
+ const embedder = await pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');
16
+ embeddingModelState = {
17
+ loaded: true,
18
+ model: embedder,
19
+ tokenizer: null,
20
+ dimensions: 384 // MiniLM-L6 produces 384-dim vectors
21
+ };
22
+ return {
23
+ success: true,
24
+ dimensions: 384,
25
+ modelName: 'all-MiniLM-L6-v2',
26
+ loadTime: Date.now() - startTime
27
+ };
28
+ }""",
29
+ """ // Patch 8: Read embedding model from project config instead of hardcoding
30
+ let modelName = 'all-MiniLM-L6-v2';
31
+ let modelDimensions = 384;
32
+ try {
33
+ const embConfigPath = path.join(process.cwd(), '.claude-flow', 'embeddings.json');
34
+ if (fs.existsSync(embConfigPath)) {
35
+ const embConfig = JSON.parse(fs.readFileSync(embConfigPath, 'utf-8'));
36
+ if (embConfig.model) {
37
+ modelName = embConfig.model;
38
+ modelDimensions = embConfig.dimension || 768;
39
+ }
40
+ }
41
+ } catch { /* use defaults */ }
42
+ const xenovaModel = modelName.startsWith('Xenova/') ? modelName : `Xenova/${modelName}`;
43
+ // Try to import @xenova/transformers for ONNX embeddings
44
+ const transformers = await import('@xenova/transformers').catch(() => null);
45
+ if (transformers) {
46
+ if (verbose) {
47
+ console.log(`Loading ONNX embedding model (${modelName})...`);
48
+ }
49
+ const { pipeline } = transformers;
50
+ const embedder = await pipeline('feature-extraction', xenovaModel);
51
+ embeddingModelState = {
52
+ loaded: true,
53
+ model: embedder,
54
+ tokenizer: null,
55
+ dimensions: modelDimensions
56
+ };
57
+ return {
58
+ success: true,
59
+ dimensions: modelDimensions,
60
+ modelName: modelName,
61
+ loadTime: Date.now() - startTime
62
+ };
63
+ }""")
64
+
65
+ # --- Old Patch 9: HNSW dimension fix ---
66
+ patch("9: HNSW dim default",
67
+ MI,
68
+ " const dimensions = options?.dimensions ?? 384;",
69
+ """ // Patch 9: Read dims from embeddings.json
70
+ let dimensions = options?.dimensions;
71
+ if (!dimensions) {
72
+ try {
73
+ const embConfigPath = path.join(process.cwd(), '.claude-flow', 'embeddings.json');
74
+ if (fs.existsSync(embConfigPath)) {
75
+ const embConfig = JSON.parse(fs.readFileSync(embConfigPath, 'utf-8'));
76
+ dimensions = embConfig.dimension || 768;
77
+ }
78
+ } catch { /* ignore */ }
79
+ dimensions = dimensions || 768;
80
+ }""")
81
+
82
+ patch("9: HNSW stale cleanup",
83
+ MI,
84
+ """ const dbPath = options?.dbPath || path.join(swarmDir, 'memory.db');
85
+ // Create HNSW index with persistent storage""",
86
+ """ const dbPath = options?.dbPath || path.join(swarmDir, 'memory.db');
87
+ // Patch 9: delete stale persistent files on forceRebuild
88
+ if (options?.forceRebuild) {
89
+ try:
90
+ if (fs.existsSync(hnswPath)) fs.unlinkSync(hnswPath);
91
+ catch {}
92
+ try:
93
+ if (fs.existsSync(metadataPath)) fs.unlinkSync(metadataPath);
94
+ catch {}
95
+ }
96
+ // Create HNSW index with persistent storage""".replace("try:", "try {").replace("catch {}", "} catch {}"))
97
+
98
+ patch("9: HNSW metadata guard",
99
+ MI,
100
+ " if (fs.existsSync(metadataPath)) {",
101
+ " if (!options?.forceRebuild && fs.existsSync(metadataPath)) {")
102
+
103
+ patch("9: HNSW early-return guard",
104
+ MI,
105
+ " if (existingLen > 0 && entries.size > 0) {",
106
+ " if (existingLen > 0 && entries.size > 0 && !options?.forceRebuild) {")
107
+
108
+ patch("9: HNSW status default",
109
+ MI,
110
+ "dimensions: hnswIndex?.dimensions ?? 384",
111
+ "dimensions: hnswIndex?.dimensions ?? 768")
@@ -0,0 +1 @@
1
+ grep "embeddings.json" memory/memory-initializer.js
@@ -0,0 +1,11 @@
1
+ # EM-002: @xenova/transformers cache EACCES
2
+ **Severity**: Medium
3
+ **GitHub**: [#1144](https://github.com/ruvnet/claude-flow/issues/1144)
4
+ ## Root Cause
5
+ Global `npm install` creates root-owned directories. `@xenova/transformers` tries to write model cache next to its `package.json`, failing with EACCES.
6
+ ## Fix
7
+ Create `.cache` directory with open permissions. Alternative: set `TRANSFORMERS_CACHE` env var.
8
+ ## Files Patched
9
+ - N/A (filesystem permissions, not code)
10
+ ## Ops
11
+ fix.sh (chmod, not Python)
@@ -0,0 +1,12 @@
1
+ #!/bin/bash
2
+ # EM-002: @xenova/transformers cache EACCES on global install
3
+ # Global npm install creates root-owned dirs. Model cache write fails.
4
+
5
+ TRANSFORMERS_DIR=$(npm root -g)/claude-flow/node_modules/@xenova/transformers
6
+ if [ -d "$TRANSFORMERS_DIR" ]; then
7
+ sudo mkdir -p "$TRANSFORMERS_DIR/.cache"
8
+ sudo chmod 777 "$TRANSFORMERS_DIR/.cache"
9
+ echo " Applied: EM-002 transformers cache permissions"
10
+ else
11
+ echo " SKIP: EM-002 — @xenova/transformers not in global install"
12
+ fi