@sparkleideas/claude-flow-patch 3.1.0-alpha.44.patch.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.
- package/AGENTS.md +162 -0
- package/CLAUDE.md +458 -0
- package/README.md +306 -0
- package/bin/claude-flow-patch.mjs +148 -0
- package/check-patches.sh +176 -0
- package/lib/categories.json +15 -0
- package/lib/common.py +92 -0
- package/lib/discover.mjs +181 -0
- package/package.json +85 -0
- package/patch/010-CF-001-doctor-yaml/README.md +11 -0
- package/patch/010-CF-001-doctor-yaml/fix.py +20 -0
- package/patch/010-CF-001-doctor-yaml/sentinel +1 -0
- package/patch/020-CF-002-config-export-yaml/README.md +11 -0
- package/patch/020-CF-002-config-export-yaml/fix.py +130 -0
- package/patch/020-CF-002-config-export-yaml/sentinel +1 -0
- package/patch/030-DM-001-daemon-log-zero/README.md +12 -0
- package/patch/030-DM-001-daemon-log-zero/fix.py +37 -0
- package/patch/030-DM-001-daemon-log-zero/sentinel +1 -0
- package/patch/040-DM-002-cpu-load-threshold/README.md +11 -0
- package/patch/040-DM-002-cpu-load-threshold/fix.py +6 -0
- package/patch/040-DM-002-cpu-load-threshold/sentinel +1 -0
- package/patch/050-DM-003-macos-freemem/README.md +11 -0
- package/patch/050-DM-003-macos-freemem/fix.py +7 -0
- package/patch/050-DM-003-macos-freemem/sentinel +1 -0
- package/patch/060-DM-004-preload-worker-stub/README.md +11 -0
- package/patch/060-DM-004-preload-worker-stub/fix.py +34 -0
- package/patch/060-DM-004-preload-worker-stub/sentinel +1 -0
- package/patch/070-DM-005-consolidation-worker-stub/README.md +11 -0
- package/patch/070-DM-005-consolidation-worker-stub/fix.py +46 -0
- package/patch/070-DM-005-consolidation-worker-stub/sentinel +1 -0
- package/patch/080-EM-001-embedding-ignores-config/README.md +11 -0
- package/patch/080-EM-001-embedding-ignores-config/fix.py +111 -0
- package/patch/080-EM-001-embedding-ignores-config/sentinel +1 -0
- package/patch/090-EM-002-transformers-cache-eacces/README.md +11 -0
- package/patch/090-EM-002-transformers-cache-eacces/fix.sh +12 -0
- package/patch/090-EM-002-transformers-cache-eacces/sentinel +1 -0
- package/patch/100-GV-001-hnsw-ghost-vectors/README.md +11 -0
- package/patch/100-GV-001-hnsw-ghost-vectors/fix.py +34 -0
- package/patch/100-GV-001-hnsw-ghost-vectors/sentinel +1 -0
- package/patch/110-HK-001-post-edit-file-path/README.md +44 -0
- package/patch/110-HK-001-post-edit-file-path/fix.py +23 -0
- package/patch/110-HK-001-post-edit-file-path/sentinel +1 -0
- package/patch/120-HK-002-hooks-tools-stub/README.md +36 -0
- package/patch/120-HK-002-hooks-tools-stub/fix.py +155 -0
- package/patch/120-HK-002-hooks-tools-stub/sentinel +1 -0
- package/patch/130-HK-003-metrics-hardcoded/README.md +30 -0
- package/patch/130-HK-003-metrics-hardcoded/fix.py +82 -0
- package/patch/130-HK-003-metrics-hardcoded/sentinel +1 -0
- package/patch/140-HW-001-stdin-hang/README.md +11 -0
- package/patch/140-HW-001-stdin-hang/fix.py +6 -0
- package/patch/140-HW-001-stdin-hang/sentinel +1 -0
- package/patch/150-HW-002-failures-swallowed/README.md +11 -0
- package/patch/150-HW-002-failures-swallowed/fix.py +42 -0
- package/patch/150-HW-002-failures-swallowed/sentinel +1 -0
- package/patch/160-HW-003-aggressive-intervals/README.md +11 -0
- package/patch/160-HW-003-aggressive-intervals/fix.py +16 -0
- package/patch/160-HW-003-aggressive-intervals/sentinel +1 -0
- package/patch/170-IN-001-intelligence-stub/README.md +64 -0
- package/patch/170-IN-001-intelligence-stub/fix.py +70 -0
- package/patch/170-IN-001-intelligence-stub/sentinel +1 -0
- package/patch/180-MM-001-memory-persist-path/README.md +27 -0
- package/patch/180-MM-001-memory-persist-path/fix.py +54 -0
- package/patch/180-MM-001-memory-persist-path/sentinel +1 -0
- package/patch/190-NS-001-discovery-default-namespace/README.md +16 -0
- package/patch/190-NS-001-discovery-default-namespace/fix.py +68 -0
- package/patch/190-NS-001-discovery-default-namespace/sentinel +2 -0
- package/patch/200-NS-002-targeted-require-namespace/README.md +19 -0
- package/patch/200-NS-002-targeted-require-namespace/fix.py +158 -0
- package/patch/200-NS-002-targeted-require-namespace/sentinel +2 -0
- package/patch/210-NS-003-namespace-typo-pattern/README.md +15 -0
- package/patch/210-NS-003-namespace-typo-pattern/fix.py +23 -0
- package/patch/210-NS-003-namespace-typo-pattern/sentinel +1 -0
- package/patch/220-RS-001-better-sqlite3-node24/README.md +54 -0
- package/patch/220-RS-001-better-sqlite3-node24/fix.py +22 -0
- package/patch/220-RS-001-better-sqlite3-node24/rebuild.sh +31 -0
- package/patch/220-RS-001-better-sqlite3-node24/sentinel +2 -0
- package/patch/230-RV-001-force-learn-tick/README.md +31 -0
- package/patch/230-RV-001-force-learn-tick/fix.py +14 -0
- package/patch/230-RV-001-force-learn-tick/sentinel +2 -0
- package/patch/240-RV-002-trajectory-load/README.md +28 -0
- package/patch/240-RV-002-trajectory-load/fix.py +14 -0
- package/patch/240-RV-002-trajectory-load/sentinel +2 -0
- package/patch/250-RV-003-trajectory-stats-sync/README.md +31 -0
- package/patch/250-RV-003-trajectory-stats-sync/fix.py +18 -0
- package/patch/250-RV-003-trajectory-stats-sync/sentinel +2 -0
- package/patch/260-SG-001-init-settings/README.md +29 -0
- package/patch/260-SG-001-init-settings/fix.py +143 -0
- package/patch/260-SG-001-init-settings/sentinel +4 -0
- package/patch/270-SG-003-init-helpers-all-paths/README.md +60 -0
- package/patch/270-SG-003-init-helpers-all-paths/fix.py +164 -0
- package/patch/270-SG-003-init-helpers-all-paths/sentinel +3 -0
- package/patch/280-UI-001-intelligence-stats-crash/README.md +11 -0
- package/patch/280-UI-001-intelligence-stats-crash/fix.py +57 -0
- package/patch/280-UI-001-intelligence-stats-crash/sentinel +1 -0
- package/patch/290-UI-002-neural-status-not-loaded/README.md +11 -0
- package/patch/290-UI-002-neural-status-not-loaded/fix.py +19 -0
- package/patch/290-UI-002-neural-status-not-loaded/sentinel +1 -0
- package/patch/300-DM-006-log-rotation/README.md +11 -0
- package/patch/300-DM-006-log-rotation/fix.py +58 -0
- package/patch/300-DM-006-log-rotation/sentinel +1 -0
- package/patch/310-HW-004-runwithtimeout-orphan/README.md +11 -0
- package/patch/310-HW-004-runwithtimeout-orphan/fix.py +10 -0
- package/patch/310-HW-004-runwithtimeout-orphan/sentinel +1 -0
- package/patch-all.sh +203 -0
- package/repair-post-init.sh +245 -0
- package/scripts/update-docs.mjs +208 -0
- package/scripts/upstream-log.mjs +257 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# NS-002: Targeted ops (store/delete/retrieve) accept wrong namespace
|
|
2
|
+
# GitHub: #581
|
|
3
|
+
# Rule: Require explicit namespace, block 'all'
|
|
4
|
+
# 14 ops: 20a-i (store/delete) + 21a,b,e,f,h (retrieve)
|
|
5
|
+
|
|
6
|
+
# ── Store ops (from old Patch 20) ──
|
|
7
|
+
|
|
8
|
+
# 20a: MCP store — add 'namespace' to required fields in schema
|
|
9
|
+
patch("20a: MCP store require namespace",
|
|
10
|
+
MCP_MEMORY,
|
|
11
|
+
"required: ['key', 'value'],",
|
|
12
|
+
"required: ['key', 'value', 'namespace'],")
|
|
13
|
+
|
|
14
|
+
# 20b: MCP store — remove || 'default' fallback + add runtime throw
|
|
15
|
+
patch("20b: MCP store namespace no fallback",
|
|
16
|
+
MCP_MEMORY,
|
|
17
|
+
"const namespace = input.namespace || 'default';\n const value = typeof",
|
|
18
|
+
"const namespace = input.namespace;\n if (!namespace || namespace === 'all') {\n throw new Error('Namespace is required (cannot be \"all\"). Use namespace: \"patterns\", \"solutions\", or \"tasks\"');\n }\n const value = typeof")
|
|
19
|
+
|
|
20
|
+
# 20c: MCP delete — add 'namespace' to required + update description
|
|
21
|
+
patch("20c: MCP delete require namespace",
|
|
22
|
+
MCP_MEMORY,
|
|
23
|
+
""" description: 'Delete a memory entry by key',
|
|
24
|
+
category: 'memory',
|
|
25
|
+
inputSchema: {
|
|
26
|
+
type: 'object',
|
|
27
|
+
properties: {
|
|
28
|
+
key: { type: 'string', description: 'Memory key' },
|
|
29
|
+
namespace: { type: 'string', description: 'Namespace (default: "default")' },
|
|
30
|
+
},
|
|
31
|
+
required: ['key'],""",
|
|
32
|
+
""" description: 'Delete a memory entry by key',
|
|
33
|
+
category: 'memory',
|
|
34
|
+
inputSchema: {
|
|
35
|
+
type: 'object',
|
|
36
|
+
properties: {
|
|
37
|
+
key: { type: 'string', description: 'Memory key' },
|
|
38
|
+
namespace: { type: 'string', description: 'Namespace (e.g. "patterns", "solutions", "tasks")' },
|
|
39
|
+
},
|
|
40
|
+
required: ['key', 'namespace'],""")
|
|
41
|
+
|
|
42
|
+
# 20d: MCP delete — remove || 'default' fallback + add runtime throw
|
|
43
|
+
patch("20d: MCP delete namespace no fallback",
|
|
44
|
+
MCP_MEMORY,
|
|
45
|
+
"const { deleteEntry } = await getMemoryFunctions();\n const key = input.key;\n const namespace = input.namespace || 'default';",
|
|
46
|
+
"const { deleteEntry } = await getMemoryFunctions();\n const key = input.key;\n const namespace = input.namespace;\n if (!namespace || namespace === 'all') {\n throw new Error('Namespace is required (cannot be \"all\"). Use namespace: \"patterns\", \"solutions\", or \"tasks\"');\n }")
|
|
47
|
+
|
|
48
|
+
# 20e: CLI store — add namespace-required check after key check
|
|
49
|
+
patch("20e: CLI store require namespace",
|
|
50
|
+
CLI_MEMORY,
|
|
51
|
+
""" if (!key) {
|
|
52
|
+
output.printError('Key is required. Use --key or -k');
|
|
53
|
+
return { success: false, exitCode: 1 };
|
|
54
|
+
}
|
|
55
|
+
if (!value && ctx.interactive) {""",
|
|
56
|
+
""" if (!key) {
|
|
57
|
+
output.printError('Key is required. Use --key or -k');
|
|
58
|
+
return { success: false, exitCode: 1 };
|
|
59
|
+
}
|
|
60
|
+
if (!namespace || namespace === 'all') {
|
|
61
|
+
output.printError('Namespace is required (cannot be "all"). Use --namespace or -n (e.g. "patterns", "solutions", "tasks")');
|
|
62
|
+
return { success: false, exitCode: 1 };
|
|
63
|
+
}
|
|
64
|
+
if (!value && ctx.interactive) {""")
|
|
65
|
+
|
|
66
|
+
# 20f: CLI delete — remove || 'default' fallback and fix error message
|
|
67
|
+
patch("20f: CLI delete namespace no fallback",
|
|
68
|
+
CLI_MEMORY,
|
|
69
|
+
"const namespace = ctx.flags.namespace || 'default';\n const force = ctx.flags.force;\n if (!key) {\n output.printError('Key is required. Use: memory delete -k \"key\" [-n \"namespace\"]');",
|
|
70
|
+
"const namespace = ctx.flags.namespace;\n const force = ctx.flags.force;\n if (!key) {\n output.printError('Key is required. Use: memory delete -k \"key\" -n \"namespace\"');")
|
|
71
|
+
|
|
72
|
+
# 20g: CLI delete — add namespace-required check
|
|
73
|
+
patch("20g: CLI delete namespace check",
|
|
74
|
+
CLI_MEMORY,
|
|
75
|
+
""" output.printError('Key is required. Use: memory delete -k "key" -n "namespace"');
|
|
76
|
+
return { success: false, exitCode: 1 };
|
|
77
|
+
}
|
|
78
|
+
if (!force && ctx.interactive) {""",
|
|
79
|
+
""" output.printError('Key is required. Use: memory delete -k "key" -n "namespace"');
|
|
80
|
+
return { success: false, exitCode: 1 };
|
|
81
|
+
}
|
|
82
|
+
if (!namespace || namespace === 'all') {
|
|
83
|
+
output.printError('Namespace is required (cannot be "all"). Use: memory delete -k "key" -n "namespace" (e.g. "patterns", "solutions", "tasks")');
|
|
84
|
+
return { success: false, exitCode: 1 };
|
|
85
|
+
}
|
|
86
|
+
if (!force && ctx.interactive) {""")
|
|
87
|
+
|
|
88
|
+
# 20h: Core storeEntry() — remove dead 'default' parameter default + throw
|
|
89
|
+
patch("20h: storeEntry no default namespace",
|
|
90
|
+
MI,
|
|
91
|
+
"const { key, value, namespace = 'default', generateEmbeddingFlag = true, tags = [], ttl, dbPath: customPath, upsert = false } = options;",
|
|
92
|
+
"const { key, value, namespace, generateEmbeddingFlag = true, tags = [], ttl, dbPath: customPath, upsert = false } = options;\n if (!namespace || namespace === 'all') throw new Error('storeEntry: namespace is required (cannot be \"all\")');")
|
|
93
|
+
|
|
94
|
+
# 20i: Core deleteEntry() — remove dead 'default' parameter default + throw
|
|
95
|
+
patch("20i: deleteEntry no default namespace",
|
|
96
|
+
MI,
|
|
97
|
+
"export async function deleteEntry(options) {\n const { key, namespace = 'default', dbPath: customPath } = options;\n const swarmDir = path.join(process.cwd(), '.swarm');\n const dbPath = customPath || path.join(swarmDir, 'memory.db');",
|
|
98
|
+
"export async function deleteEntry(options) {\n const { key, namespace, dbPath: customPath } = options;\n if (!namespace || namespace === 'all') throw new Error('deleteEntry: namespace is required (cannot be \"all\")');\n const swarmDir = path.join(process.cwd(), '.swarm');\n const dbPath = customPath || path.join(swarmDir, 'memory.db');")
|
|
99
|
+
|
|
100
|
+
# ── Retrieve ops (from old Patch 21) ──
|
|
101
|
+
|
|
102
|
+
# 21a: MCP retrieve — add 'namespace' to required + update description
|
|
103
|
+
patch("21a: MCP retrieve require namespace",
|
|
104
|
+
MCP_MEMORY,
|
|
105
|
+
""" description: 'Retrieve a value from memory by key',
|
|
106
|
+
category: 'memory',
|
|
107
|
+
inputSchema: {
|
|
108
|
+
type: 'object',
|
|
109
|
+
properties: {
|
|
110
|
+
key: { type: 'string', description: 'Memory key' },
|
|
111
|
+
namespace: { type: 'string', description: 'Namespace (default: "default")' },
|
|
112
|
+
},
|
|
113
|
+
required: ['key'],""",
|
|
114
|
+
""" description: 'Retrieve a value from memory by key',
|
|
115
|
+
category: 'memory',
|
|
116
|
+
inputSchema: {
|
|
117
|
+
type: 'object',
|
|
118
|
+
properties: {
|
|
119
|
+
key: { type: 'string', description: 'Memory key' },
|
|
120
|
+
namespace: { type: 'string', description: 'Namespace (e.g. "patterns", "solutions", "tasks")' },
|
|
121
|
+
},
|
|
122
|
+
required: ['key', 'namespace'],""")
|
|
123
|
+
|
|
124
|
+
# 21b: MCP retrieve — remove || 'default' fallback + add runtime throw
|
|
125
|
+
patch("21b: MCP retrieve namespace no fallback",
|
|
126
|
+
MCP_MEMORY,
|
|
127
|
+
"const { getEntry } = await getMemoryFunctions();\n const key = input.key;\n const namespace = input.namespace || 'default';",
|
|
128
|
+
"const { getEntry } = await getMemoryFunctions();\n const key = input.key;\n const namespace = input.namespace;\n if (!namespace || namespace === 'all') {\n throw new Error('Namespace is required (cannot be \"all\"). Use namespace: \"patterns\", \"solutions\", or \"tasks\"');\n }")
|
|
129
|
+
|
|
130
|
+
# 21e: CLI retrieve — remove default: 'default' from flag definition
|
|
131
|
+
patch("21e: CLI retrieve remove default",
|
|
132
|
+
CLI_MEMORY,
|
|
133
|
+
" type: 'string',\n default: 'default'\n }\n ],\n action: async (ctx) => {\n const key = ctx.flags.key || ctx.args[0];\n const namespace = ctx.flags.namespace;\n if (!key) {\n output.printError('Key is required');",
|
|
134
|
+
" type: 'string'\n }\n ],\n action: async (ctx) => {\n const key = ctx.flags.key || ctx.args[0];\n const namespace = ctx.flags.namespace;\n if (!key) {\n output.printError('Key is required');")
|
|
135
|
+
|
|
136
|
+
# 21f: CLI retrieve — add namespace-required check
|
|
137
|
+
patch("21f: CLI retrieve namespace check",
|
|
138
|
+
CLI_MEMORY,
|
|
139
|
+
""" if (!key) {
|
|
140
|
+
output.printError('Key is required');
|
|
141
|
+
return { success: false, exitCode: 1 };
|
|
142
|
+
}
|
|
143
|
+
// Use sql.js directly for consistent data access""",
|
|
144
|
+
""" if (!key) {
|
|
145
|
+
output.printError('Key is required');
|
|
146
|
+
return { success: false, exitCode: 1 };
|
|
147
|
+
}
|
|
148
|
+
if (!namespace || namespace === 'all') {
|
|
149
|
+
output.printError('Namespace is required (cannot be "all"). Use --namespace or -n (e.g. "patterns", "solutions", "tasks")');
|
|
150
|
+
return { success: false, exitCode: 1 };
|
|
151
|
+
}
|
|
152
|
+
// Use sql.js directly for consistent data access""")
|
|
153
|
+
|
|
154
|
+
# 21h: Core getEntry() — remove dead 'default' parameter default + throw
|
|
155
|
+
patch("21h: getEntry no default namespace",
|
|
156
|
+
MI,
|
|
157
|
+
"const { key, namespace = 'default', dbPath: customPath } = options;\n const swarmDir = path.join(process.cwd(), '.swarm');\n const dbPath = customPath || path.join(swarmDir, 'memory.db');",
|
|
158
|
+
"const { key, namespace, dbPath: customPath } = options;\n if (!namespace || namespace === 'all') throw new Error('getEntry: namespace is required (cannot be \"all\")');\n const swarmDir = path.join(process.cwd(), '.swarm');\n const dbPath = customPath || path.join(swarmDir, 'memory.db');")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# NS-003: Namespace typo 'pattern' vs 'patterns'
|
|
2
|
+
**Severity**: Medium
|
|
3
|
+
**GitHub**: [#1136](https://github.com/ruvnet/claude-flow/issues/1136)
|
|
4
|
+
## Root Cause
|
|
5
|
+
hooks-tools.js used singular 'pattern' in 4 locations while every other file (memory-tools.js, CLI, README) uses 'patterns' (plural). Patterns stored via hooks were invisible to search.
|
|
6
|
+
## Fix
|
|
7
|
+
Replace all 4 occurrences of 'pattern' with 'patterns' in hooks-tools.js.
|
|
8
|
+
## Files Patched
|
|
9
|
+
- mcp-tools/hooks-tools.js
|
|
10
|
+
## Dependencies
|
|
11
|
+
|
|
12
|
+
Depends on NS-002 (200) — NS-003 fixes typos in code paths that NS-002 modifies.
|
|
13
|
+
|
|
14
|
+
## Ops
|
|
15
|
+
4 ops in fix.py (22a-d)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# NS-003: Namespace typo 'pattern' vs 'patterns'
|
|
2
|
+
# GitHub: #1136
|
|
3
|
+
# 4 ops: 22a-d
|
|
4
|
+
|
|
5
|
+
patch("22a: hooks pattern-store namespace",
|
|
6
|
+
MCP_HOOKS,
|
|
7
|
+
"namespace: 'pattern',",
|
|
8
|
+
"namespace: 'patterns',")
|
|
9
|
+
|
|
10
|
+
patch("22b: hooks pattern-search default",
|
|
11
|
+
MCP_HOOKS,
|
|
12
|
+
"const namespace = params.namespace || 'pattern';",
|
|
13
|
+
"const namespace = params.namespace || 'patterns';")
|
|
14
|
+
|
|
15
|
+
patch("22c: hooks pattern-search description",
|
|
16
|
+
MCP_HOOKS,
|
|
17
|
+
"description: 'Namespace to search (default: pattern)'",
|
|
18
|
+
"description: 'Namespace to search (default: patterns)'")
|
|
19
|
+
|
|
20
|
+
patch("22d: hooks pattern-search note",
|
|
21
|
+
MCP_HOOKS,
|
|
22
|
+
'namespace "pattern".',
|
|
23
|
+
'namespace "patterns".')
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
grep "|| 'patterns'" mcp-tools/hooks-tools.js
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# RS-001: ruv-swarm MCP fails on Node 24 — better-sqlite3 missing native bindings
|
|
2
|
+
|
|
3
|
+
**Severity**: Critical
|
|
4
|
+
**Package**: `ruv-swarm@1.0.20`
|
|
5
|
+
**GitHub**: [ruv-FANN#185](https://github.com/ruvnet/ruv-FANN/issues/185)
|
|
6
|
+
|
|
7
|
+
## Symptoms
|
|
8
|
+
|
|
9
|
+
`ruv-swarm mcp start` crashes immediately with:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Could not locate the bindings file. Tried:
|
|
13
|
+
→ .../better-sqlite3/lib/binding/node-v137-linux-x64/better_sqlite3.node
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The MCP server never starts. All ruv-swarm MCP tools are unavailable.
|
|
17
|
+
|
|
18
|
+
## Root Cause
|
|
19
|
+
|
|
20
|
+
`ruv-swarm@1.0.20` declares `"better-sqlite3": "^11.6.0"` in `package.json`.
|
|
21
|
+
When installed via `npx`, npm resolves this to `better-sqlite3@11.10.0`.
|
|
22
|
+
|
|
23
|
+
`better-sqlite3` 11.x does **not** ship prebuilt binaries for Node 24
|
|
24
|
+
(ABI version `node-v137`). The native addon compilation fails silently
|
|
25
|
+
during `npx` install — `build/Release/` contains intermediate `obj/`
|
|
26
|
+
directories but no `better_sqlite3.node` binary.
|
|
27
|
+
|
|
28
|
+
`better-sqlite3` 12.x (`^12.0.0`) added Node 24 to its supported engines
|
|
29
|
+
and ships prebuilt binaries for `node-v137-linux-x64`.
|
|
30
|
+
|
|
31
|
+
## Why @claude-flow/cli is unaffected
|
|
32
|
+
|
|
33
|
+
`@claude-flow/cli` uses `sql.js` (pure WASM SQLite) instead of `better-sqlite3`.
|
|
34
|
+
WASM has no native bindings and works on any Node version.
|
|
35
|
+
|
|
36
|
+
## Fix
|
|
37
|
+
|
|
38
|
+
Bump the dependency from `^11.6.0` to `^12.0.0` in `ruv-swarm/package.json`.
|
|
39
|
+
|
|
40
|
+
## Files Patched
|
|
41
|
+
|
|
42
|
+
- `ruv-swarm` `package.json` (in npx cache)
|
|
43
|
+
|
|
44
|
+
## Ops
|
|
45
|
+
|
|
46
|
+
1 op in fix.py (JSON string replacement in package.json)
|
|
47
|
+
1 op: `npm rebuild better-sqlite3` in the npx cache directory
|
|
48
|
+
|
|
49
|
+
## Verification
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npx -y ruv-swarm --version
|
|
53
|
+
# Should print version without crashing
|
|
54
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# RS-001: ruv-swarm better-sqlite3 Node 24 compatibility
|
|
2
|
+
# GitHub: ruvnet/ruv-FANN#185
|
|
3
|
+
#
|
|
4
|
+
# ruv-swarm@1.0.20 pins better-sqlite3@^11.6.0 which lacks Node 24
|
|
5
|
+
# prebuilt binaries. Bump to ^12.0.0 which supports Node 24 (v137 ABI).
|
|
6
|
+
#
|
|
7
|
+
# This patch targets the ruv-swarm package.json in the npx cache,
|
|
8
|
+
# NOT @claude-flow/cli. It uses the same patch() infrastructure but
|
|
9
|
+
# finds its own target path.
|
|
10
|
+
|
|
11
|
+
import glob
|
|
12
|
+
|
|
13
|
+
# Find ruv-swarm package.json in npx cache
|
|
14
|
+
rs_pkg_candidates = glob.glob(os.path.expanduser(
|
|
15
|
+
"~/.npm/_npx/*/node_modules/ruv-swarm/package.json"
|
|
16
|
+
))
|
|
17
|
+
rs_pkg = rs_pkg_candidates[0] if rs_pkg_candidates else ""
|
|
18
|
+
|
|
19
|
+
patch("RS-001: better-sqlite3 ^11 -> ^12 (Node 24)",
|
|
20
|
+
rs_pkg,
|
|
21
|
+
'"better-sqlite3": "^11.6.0"',
|
|
22
|
+
'"better-sqlite3": "^12.0.0"')
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# RS-001: After patching package.json, reinstall better-sqlite3 with
|
|
3
|
+
# correct prebuilt binaries for Node 24.
|
|
4
|
+
#
|
|
5
|
+
# Usage: bash rebuild.sh
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
RS_DIR=$(find ~/.npm/_npx -path "*/node_modules/ruv-swarm" -type d 2>/dev/null | head -1)
|
|
10
|
+
|
|
11
|
+
if [ -z "$RS_DIR" ]; then
|
|
12
|
+
echo "[RS-001] ruv-swarm not found in npx cache, skipping rebuild"
|
|
13
|
+
exit 0
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
# Install at the npx cache root (where better-sqlite3 is hoisted),
|
|
17
|
+
# not inside ruv-swarm's own node_modules
|
|
18
|
+
NPX_ROOT=$(echo "$RS_DIR" | sed 's|/node_modules/ruv-swarm$||')
|
|
19
|
+
|
|
20
|
+
echo "[RS-001] Reinstalling better-sqlite3@^12.0.0 in: $NPX_ROOT"
|
|
21
|
+
|
|
22
|
+
cd "$NPX_ROOT"
|
|
23
|
+
npm install better-sqlite3@"^12.0.0" --no-save 2>&1
|
|
24
|
+
|
|
25
|
+
echo "[RS-001] Verifying..."
|
|
26
|
+
if npx -y ruv-swarm --version 2>/dev/null; then
|
|
27
|
+
echo "[RS-001] OK: ruv-swarm starts successfully"
|
|
28
|
+
else
|
|
29
|
+
echo "[RS-001] WARN: ruv-swarm still failing — may need full cache clear"
|
|
30
|
+
echo " Try: rm -rf ~/.npm/_npx/$(basename $(dirname $RS_DIR)) && npx -y ruv-swarm --version"
|
|
31
|
+
fi
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# RV-001: force-learn command calls intel.tick() which doesn't exist
|
|
2
|
+
|
|
3
|
+
**Severity**: Medium
|
|
4
|
+
**GitHub**: [#1156](https://github.com/ruvnet/claude-flow/issues/1156)
|
|
5
|
+
|
|
6
|
+
## Root Cause
|
|
7
|
+
|
|
8
|
+
The `hooks force-learn` command (line 4224) creates an Intelligence instance with
|
|
9
|
+
`skipEngine: true` (fast mode), then calls `intel.tick()`. The `tick()` method
|
|
10
|
+
exists on the engine object (`eng.tick()`), not on the Intelligence class itself.
|
|
11
|
+
With `skipEngine: true`, no engine is created, so the call crashes.
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
// Line 4224-4226
|
|
15
|
+
const intel = new Intelligence({ skipEngine: true }); // Fast mode
|
|
16
|
+
intel.tick(); // BUG: tick() doesn't exist on Intelligence
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Fix
|
|
20
|
+
|
|
21
|
+
1. Remove `skipEngine: true` so the engine can initialize
|
|
22
|
+
2. Call `intel.engine.tick()` instead of `intel.tick()`
|
|
23
|
+
3. Add null check for when engine fails to load
|
|
24
|
+
|
|
25
|
+
## Files Patched
|
|
26
|
+
|
|
27
|
+
- `ruvector/bin/cli.js`
|
|
28
|
+
|
|
29
|
+
## Ops
|
|
30
|
+
|
|
31
|
+
2 ops in fix.py
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# RV-001: force-learn calls intel.tick() which doesn't exist
|
|
2
|
+
# The tick() method is on the engine, not the Intelligence class
|
|
3
|
+
|
|
4
|
+
# Fix 1: Remove skipEngine: true so engine can initialize
|
|
5
|
+
patch("RV-001a: remove skipEngine from force-learn",
|
|
6
|
+
ruvector_cli,
|
|
7
|
+
"const intel = new Intelligence({ skipEngine: true }); // Fast mode\n intel.tick();",
|
|
8
|
+
"const intel = new Intelligence(); // Need engine for tick()\n const eng = intel.engine;\n if (eng) { eng.tick(); }")
|
|
9
|
+
|
|
10
|
+
# Fix 2: Update the success message to handle no-engine case
|
|
11
|
+
patch("RV-001b: handle no-engine case in force-learn",
|
|
12
|
+
ruvector_cli,
|
|
13
|
+
"if (eng) { eng.tick(); }\n console.log(JSON.stringify({ success: true, result: 'Learning cycle triggered', stats: intel.stats() }));",
|
|
14
|
+
"if (eng) { eng.tick(); }\n console.log(JSON.stringify({ success: true, result: eng ? 'Learning cycle triggered' : 'Engine not available', stats: intel.stats() }));")
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# RV-002: activeTrajectories not loaded from saved file
|
|
2
|
+
|
|
3
|
+
**Severity**: High
|
|
4
|
+
**GitHub**: [#1157](https://github.com/ruvnet/claude-flow/issues/1157)
|
|
5
|
+
|
|
6
|
+
## Root Cause
|
|
7
|
+
|
|
8
|
+
The `load()` method in the Intelligence class (line ~2721) doesn't include
|
|
9
|
+
`activeTrajectories` in the returned object. When `trajectory-begin` saves an
|
|
10
|
+
active trajectory, it's written to the file, but the next command
|
|
11
|
+
(`trajectory-step`) creates a new Intelligence instance that doesn't load
|
|
12
|
+
`activeTrajectories` back from the file.
|
|
13
|
+
|
|
14
|
+
This causes `trajectory-step` and `trajectory-end` to fail with
|
|
15
|
+
"No active trajectory" error.
|
|
16
|
+
|
|
17
|
+
## Fix
|
|
18
|
+
|
|
19
|
+
1. Add `activeTrajectories: {}` to the defaults object
|
|
20
|
+
2. Add `activeTrajectories: data.activeTrajectories || {}` to the loaded data return
|
|
21
|
+
|
|
22
|
+
## Files Patched
|
|
23
|
+
|
|
24
|
+
- `ruvector/bin/cli.js`
|
|
25
|
+
|
|
26
|
+
## Ops
|
|
27
|
+
|
|
28
|
+
2 ops in fix.py
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# RV-002: activeTrajectories not loaded from saved file
|
|
2
|
+
# The load() method doesn't include activeTrajectories in the return object
|
|
3
|
+
|
|
4
|
+
# Fix 1: Add activeTrajectories to defaults
|
|
5
|
+
patch("RV-002a: add activeTrajectories to defaults",
|
|
6
|
+
ruvector_cli,
|
|
7
|
+
"stats: { total_patterns: 0, total_memories: 0, total_trajectories: 0, total_errors: 0, session_count: 0, last_session: 0 }\n };",
|
|
8
|
+
"stats: { total_patterns: 0, total_memories: 0, total_trajectories: 0, total_errors: 0, session_count: 0, last_session: 0 },\n activeTrajectories: {}\n };")
|
|
9
|
+
|
|
10
|
+
# Fix 2: Add activeTrajectories to loaded data return
|
|
11
|
+
patch("RV-002b: load activeTrajectories from file",
|
|
12
|
+
ruvector_cli,
|
|
13
|
+
"// Preserve learning data if present\n learning: data.learning || undefined",
|
|
14
|
+
"// Preserve learning data if present\n learning: data.learning || undefined,\n // Preserve active trajectories for cross-command persistence\n activeTrajectories: data.activeTrajectories || {}")
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# RV-003: trajectory-end does not update stats counters
|
|
2
|
+
|
|
3
|
+
**Severity**: Medium
|
|
4
|
+
**GitHub**: [ruv-FANN#186](https://github.com/ruvnet/ruv-FANN/issues/186)
|
|
5
|
+
|
|
6
|
+
## Root Cause
|
|
7
|
+
|
|
8
|
+
The `hooks trajectory-end` command pushes completed trajectories to
|
|
9
|
+
`data.trajectories[]` and calls `intel.save()`, but never syncs the
|
|
10
|
+
`data.stats.total_trajectories` counter. The `hooks stats` command reads
|
|
11
|
+
the stale counter and reports 0 trajectories even when the array has entries.
|
|
12
|
+
|
|
13
|
+
Compare with `learn()` which correctly does:
|
|
14
|
+
```javascript
|
|
15
|
+
this.data.stats.total_trajectories = this.data.trajectories.length;
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Fix
|
|
19
|
+
|
|
20
|
+
Add stats counter sync before `intel.save()` in the `trajectory-end` handler:
|
|
21
|
+
- `total_trajectories` from `trajectories.length`
|
|
22
|
+
- `total_patterns` from `Object.keys(patterns).length`
|
|
23
|
+
- `total_memories` from `memories.length`
|
|
24
|
+
|
|
25
|
+
## Files Patched
|
|
26
|
+
|
|
27
|
+
- `bin/cli.js` (ruvector)
|
|
28
|
+
|
|
29
|
+
## Ops
|
|
30
|
+
|
|
31
|
+
1 op in fix.py
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# RV-003: trajectory-end does not update stats counters
|
|
2
|
+
# GitHub: #186 (ruv-FANN)
|
|
3
|
+
|
|
4
|
+
patch("RV-003a: sync stats counters before save in trajectory-end",
|
|
5
|
+
ruvector_cli,
|
|
6
|
+
""" if (!intel.data.trajectories) intel.data.trajectories = [];
|
|
7
|
+
intel.data.trajectories.push(traj);
|
|
8
|
+
delete trajectories[latestTrajId];
|
|
9
|
+
intel.save();""",
|
|
10
|
+
""" if (!intel.data.trajectories) intel.data.trajectories = [];
|
|
11
|
+
intel.data.trajectories.push(traj);
|
|
12
|
+
delete trajectories[latestTrajId];
|
|
13
|
+
// RV-003: sync stats counters from actual data before saving
|
|
14
|
+
if (!intel.data.stats) intel.data.stats = {};
|
|
15
|
+
intel.data.stats.total_trajectories = intel.data.trajectories.length;
|
|
16
|
+
intel.data.stats.total_patterns = Object.keys(intel.data.patterns || {}).length;
|
|
17
|
+
intel.data.stats.total_memories = (intel.data.memories || []).length;
|
|
18
|
+
intel.save();""")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# SG-001: Init generates invalid settings
|
|
2
|
+
|
|
3
|
+
**Severity**: High
|
|
4
|
+
**GitHub**: [#1150](https://github.com/ruvnet/claude-flow/issues/1150)
|
|
5
|
+
|
|
6
|
+
## Root Cause
|
|
7
|
+
|
|
8
|
+
1. **Invalid hook events**: `TeammateIdle` and `TaskCompleted` are not valid Claude Code hooks
|
|
9
|
+
2. **Overly broad permissions**: Glob patterns like `Bash(npx @claude-flow*)` match unintended commands
|
|
10
|
+
3. **Relative hook paths**: `node .claude/helpers/` breaks when running from subdirectories
|
|
11
|
+
4. **Phantom statusLine config**: `--minimal` and `init hooks` emit `statusLine` config
|
|
12
|
+
referencing `statusline.cjs` but the file is never generated (`components.statusline: false`)
|
|
13
|
+
5. **MINIMAL statusline inconsistency**: `MINIMAL_INIT_OPTIONS` inherits
|
|
14
|
+
`statusline.enabled: true` from DEFAULT but sets `components.statusline: false`
|
|
15
|
+
|
|
16
|
+
## Fix
|
|
17
|
+
|
|
18
|
+
Replace invalid hooks with `SubagentStop` (valid event), fix permission patterns, use
|
|
19
|
+
`$CLAUDE_PROJECT_DIR` for all hook paths, gate statusLine config emission on
|
|
20
|
+
`components.statusline`, and override `statusline.enabled` to `false` in MINIMAL preset.
|
|
21
|
+
|
|
22
|
+
## Files Patched
|
|
23
|
+
|
|
24
|
+
- `init/settings-generator.js`
|
|
25
|
+
- `init/types.js`
|
|
26
|
+
|
|
27
|
+
## Ops
|
|
28
|
+
|
|
29
|
+
5 ops in fix.py (SG-001a: replace invalid hooks, SG-001b: fix permissions, SG-001c: CLAUDE_PROJECT_DIR paths, SG-001d: gate statusLine on component flag, SG-001e: MINIMAL statusline.enabled=false)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# SG-001: Init generates invalid settings
|
|
2
|
+
# GitHub: #1150
|
|
3
|
+
#
|
|
4
|
+
# Problems:
|
|
5
|
+
# 1. TeammateIdle and TaskCompleted are not valid Claude Code hook events
|
|
6
|
+
# 2. Permission patterns are too broad (glob wildcards)
|
|
7
|
+
# 3. Hook paths use relative .claude/helpers/ which breaks from subdirectories
|
|
8
|
+
#
|
|
9
|
+
# Fix: Replace invalid hooks with SubagentStop, fix permissions, use $CLAUDE_PROJECT_DIR
|
|
10
|
+
|
|
11
|
+
# SG-001a: Replace invalid hooks with SubagentStop (with correct $CLAUDE_PROJECT_DIR paths)
|
|
12
|
+
patch("SG-001a: replace invalid hooks with SubagentStop",
|
|
13
|
+
SETTINGS_GEN,
|
|
14
|
+
""" // SubagentStart — status update
|
|
15
|
+
hooks.SubagentStart = [
|
|
16
|
+
{
|
|
17
|
+
hooks: [
|
|
18
|
+
{
|
|
19
|
+
type: 'command',
|
|
20
|
+
command: 'node .claude/helpers/hook-handler.cjs status',
|
|
21
|
+
timeout: 3000,
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
// TeammateIdle — auto-assign pending tasks to idle teammates
|
|
27
|
+
hooks.TeammateIdle = [
|
|
28
|
+
{
|
|
29
|
+
hooks: [
|
|
30
|
+
{
|
|
31
|
+
type: 'command',
|
|
32
|
+
command: 'node .claude/helpers/hook-handler.cjs post-task',
|
|
33
|
+
timeout: 5000,
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
// TaskCompleted — train patterns and record completion
|
|
39
|
+
hooks.TaskCompleted = [
|
|
40
|
+
{
|
|
41
|
+
hooks: [
|
|
42
|
+
{
|
|
43
|
+
type: 'command',
|
|
44
|
+
command: 'node .claude/helpers/hook-handler.cjs post-task',
|
|
45
|
+
timeout: 5000,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
return hooks;""",
|
|
51
|
+
""" // SubagentStart — status update
|
|
52
|
+
hooks.SubagentStart = [
|
|
53
|
+
{
|
|
54
|
+
hooks: [
|
|
55
|
+
{
|
|
56
|
+
type: 'command',
|
|
57
|
+
command: 'node "$CLAUDE_PROJECT_DIR"/.claude/helpers/hook-handler.cjs status',
|
|
58
|
+
timeout: 3000,
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
// SubagentStop — task completion + teammate idle (replaces invalid TeammateIdle/TaskCompleted)
|
|
64
|
+
hooks.SubagentStop = [
|
|
65
|
+
{
|
|
66
|
+
hooks: [
|
|
67
|
+
{
|
|
68
|
+
type: 'command',
|
|
69
|
+
command: 'node "$CLAUDE_PROJECT_DIR"/.claude/helpers/hook-handler.cjs post-task',
|
|
70
|
+
timeout: 5000,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
type: 'command',
|
|
74
|
+
command: 'npx @claude-flow/cli@latest hooks teammate-idle',
|
|
75
|
+
timeout: 5000,
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
// TeammateIdle removed — not a valid Claude Code hook event (see #1150)
|
|
81
|
+
// TaskCompleted removed — not a valid Claude Code hook event (see #1150)
|
|
82
|
+
return hooks;""")
|
|
83
|
+
|
|
84
|
+
# SG-001b: Fix permission patterns (too broad) and add $CLAUDE_PROJECT_DIR
|
|
85
|
+
patch("SG-001b: fix permissions",
|
|
86
|
+
SETTINGS_GEN,
|
|
87
|
+
""" settings.permissions = {
|
|
88
|
+
allow: [
|
|
89
|
+
'Bash(npx @claude-flow*)',
|
|
90
|
+
'Bash(npx claude-flow*)',
|
|
91
|
+
'Bash(node .claude/*)',
|
|
92
|
+
'mcp__claude-flow__:*',
|
|
93
|
+
],""",
|
|
94
|
+
""" settings.permissions = {
|
|
95
|
+
allow: [
|
|
96
|
+
'Bash(npx @claude-flow/cli:*)',
|
|
97
|
+
'Bash(npx claude-flow:*)',
|
|
98
|
+
'Bash(node "$CLAUDE_PROJECT_DIR"/.claude/*)',
|
|
99
|
+
'mcp__claude-flow__:*',
|
|
100
|
+
],""")
|
|
101
|
+
|
|
102
|
+
# SG-001c: Fix all other hook paths to use $CLAUDE_PROJECT_DIR
|
|
103
|
+
# (catches statusline, pre-bash, post-edit, route, session hooks, etc.)
|
|
104
|
+
patch_all("SG-001c: use CLAUDE_PROJECT_DIR for all hook paths",
|
|
105
|
+
SETTINGS_GEN,
|
|
106
|
+
"command: 'node .claude/helpers/",
|
|
107
|
+
'command: \'node "$CLAUDE_PROJECT_DIR"/.claude/helpers/')
|
|
108
|
+
|
|
109
|
+
# SG-001d: statusLine config emitted even when statusline component is off
|
|
110
|
+
# MINIMAL_INIT_OPTIONS has components.statusline=false but statusline.enabled=true.
|
|
111
|
+
# Settings-generator checks statusline.enabled, emitting statusLine config for a
|
|
112
|
+
# file that won't exist. Gate on components.statusline too.
|
|
113
|
+
patch("SG-001d: only emit statusLine when statusline component is generated",
|
|
114
|
+
SETTINGS_GEN,
|
|
115
|
+
""" if (options.statusline.enabled) {""",
|
|
116
|
+
""" // SG-001: Only emit statusLine config if the component will actually be generated
|
|
117
|
+
if (options.components.statusline && options.statusline.enabled) {""")
|
|
118
|
+
|
|
119
|
+
# SG-001e: MINIMAL_INIT_OPTIONS inherits statusline.enabled=true from DEFAULT
|
|
120
|
+
# but sets components.statusline=false. Override to prevent inconsistency.
|
|
121
|
+
# (SG-001d guards at the consumer; this fixes the producer for MINIMAL)
|
|
122
|
+
patch("SG-001e: MINIMAL statusline.enabled matches components.statusline",
|
|
123
|
+
TYPES,
|
|
124
|
+
""" hooks: {
|
|
125
|
+
...DEFAULT_INIT_OPTIONS.hooks,
|
|
126
|
+
userPromptSubmit: false,
|
|
127
|
+
stop: false,
|
|
128
|
+
notification: false,
|
|
129
|
+
},
|
|
130
|
+
skills: {""",
|
|
131
|
+
""" hooks: {
|
|
132
|
+
...DEFAULT_INIT_OPTIONS.hooks,
|
|
133
|
+
userPromptSubmit: false,
|
|
134
|
+
stop: false,
|
|
135
|
+
notification: false,
|
|
136
|
+
},
|
|
137
|
+
// SG-001: statusline file not generated (components.statusline: false)
|
|
138
|
+
// so disable the feature flag to prevent dangling settings.json references
|
|
139
|
+
statusline: {
|
|
140
|
+
...DEFAULT_INIT_OPTIONS.statusline,
|
|
141
|
+
enabled: false,
|
|
142
|
+
},
|
|
143
|
+
skills: {""")
|