@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,82 @@
|
|
|
1
|
+
# HK-003: hooks_metrics MCP handler returns hardcoded fake data
|
|
2
|
+
# GitHub: #1158
|
|
3
|
+
|
|
4
|
+
patch("HK-003a: replace hardcoded metrics with real data reader",
|
|
5
|
+
MCP_HOOKS,
|
|
6
|
+
""" return {
|
|
7
|
+
period,
|
|
8
|
+
patterns: {
|
|
9
|
+
total: 15,
|
|
10
|
+
successful: 12,
|
|
11
|
+
failed: 3,
|
|
12
|
+
avgConfidence: 0.85,
|
|
13
|
+
},
|
|
14
|
+
agents: {
|
|
15
|
+
routingAccuracy: 0.87,
|
|
16
|
+
totalRoutes: 42,
|
|
17
|
+
topAgent: 'coder',
|
|
18
|
+
},
|
|
19
|
+
commands: {
|
|
20
|
+
totalExecuted: 128,
|
|
21
|
+
successRate: 0.94,
|
|
22
|
+
avgRiskScore: 0.15,
|
|
23
|
+
},
|
|
24
|
+
performance: {
|
|
25
|
+
flashAttention: '2.49x-7.47x speedup',
|
|
26
|
+
memoryReduction: '50-75% reduction',
|
|
27
|
+
searchImprovement: '150x-12,500x faster',
|
|
28
|
+
tokenReduction: '32.3% fewer tokens',
|
|
29
|
+
},
|
|
30
|
+
status: 'healthy',
|
|
31
|
+
lastUpdated: new Date().toISOString(),
|
|
32
|
+
};""",
|
|
33
|
+
""" // HK-003: read real metrics from persisted files instead of hardcoded values
|
|
34
|
+
const cwd = process.cwd();
|
|
35
|
+
let patterns = { total: 0, successful: 0, failed: 0, avgConfidence: 0 };
|
|
36
|
+
let agents = { routingAccuracy: 0, totalRoutes: 0, topAgent: 'none' };
|
|
37
|
+
let commands = { totalExecuted: 0, successRate: 0, avgRiskScore: 0 };
|
|
38
|
+
try {
|
|
39
|
+
const sonaPath = cwd + '/.swarm/sona-patterns.json';
|
|
40
|
+
if (existsSync(sonaPath)) {
|
|
41
|
+
const sona = JSON.parse(readFileSync(sonaPath, 'utf-8'));
|
|
42
|
+
const pats = Object.values(sona.patterns || {});
|
|
43
|
+
const successful = pats.filter(p => p.successCount > 0).length;
|
|
44
|
+
patterns = {
|
|
45
|
+
total: pats.length,
|
|
46
|
+
successful,
|
|
47
|
+
failed: pats.filter(p => p.failureCount > 0).length,
|
|
48
|
+
avgConfidence: pats.length > 0 ? pats.reduce((s, p) => s + (p.confidence || 0), 0) / pats.length : 0,
|
|
49
|
+
};
|
|
50
|
+
agents = {
|
|
51
|
+
routingAccuracy: (sona.stats || {}).successfulRoutings > 0 ? sona.stats.successfulRoutings / ((sona.stats.successfulRoutings || 0) + (sona.stats.failedRoutings || 0)) : 0,
|
|
52
|
+
totalRoutes: ((sona.stats || {}).successfulRoutings || 0) + ((sona.stats || {}).failedRoutings || 0),
|
|
53
|
+
topAgent: pats.length > 0 ? pats.sort((a, b) => (b.successCount || 0) - (a.successCount || 0))[0].agent || 'none' : 'none',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
} catch {}
|
|
57
|
+
try {
|
|
58
|
+
const rvPath = cwd + '/.ruvector/intelligence.json';
|
|
59
|
+
if (existsSync(rvPath)) {
|
|
60
|
+
const rv = JSON.parse(readFileSync(rvPath, 'utf-8'));
|
|
61
|
+
const s = rv.stats || {};
|
|
62
|
+
commands = {
|
|
63
|
+
totalExecuted: (s.session_count || 0) + (rv.trajectories || []).length,
|
|
64
|
+
successRate: (rv.trajectories || []).length > 0 ? (rv.trajectories || []).filter(t => t.success).length / (rv.trajectories || []).length : 0,
|
|
65
|
+
avgRiskScore: 0.15,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
} catch {}
|
|
69
|
+
return {
|
|
70
|
+
period,
|
|
71
|
+
patterns,
|
|
72
|
+
agents,
|
|
73
|
+
commands,
|
|
74
|
+
performance: {
|
|
75
|
+
flashAttention: '2.49x-7.47x speedup',
|
|
76
|
+
memoryReduction: '50-75% reduction',
|
|
77
|
+
searchImprovement: '150x-12,500x faster',
|
|
78
|
+
tokenReduction: '32.3% fewer tokens',
|
|
79
|
+
},
|
|
80
|
+
status: 'healthy',
|
|
81
|
+
lastUpdated: new Date().toISOString(),
|
|
82
|
+
};""")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
grep "HK-003" mcp-tools/hooks-tools.js
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# HW-001: Headless workers hang — stdin pipe never closed
|
|
2
|
+
**Severity**: Critical
|
|
3
|
+
**GitHub**: [#1111](https://github.com/ruvnet/claude-flow/issues/1111)
|
|
4
|
+
## Root Cause
|
|
5
|
+
`claude --print` is spawned with `stdio: ['pipe', 'pipe', 'pipe']`. The prompt is passed as a CLI argument, so stdin is never written to or closed. The child process hangs waiting for stdin EOF.
|
|
6
|
+
## Fix
|
|
7
|
+
Change stdin to `'ignore'` since it's unused.
|
|
8
|
+
## Files Patched
|
|
9
|
+
- services/headless-worker-executor.js
|
|
10
|
+
## Ops
|
|
11
|
+
1 op in fix.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
grep "'ignore', 'pipe', 'pipe'" services/headless-worker-executor.js
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# HW-002: Headless failures silently swallowed as success
|
|
2
|
+
**Severity**: High
|
|
3
|
+
**GitHub**: [#1112](https://github.com/ruvnet/claude-flow/issues/1112)
|
|
4
|
+
## Root Cause
|
|
5
|
+
`executeWorker()` hardcodes `success: true` for any non-throwing return. When headless execution fails (returns `{success: false}`), `runWorkerLogic()` catches the error and falls through to local stubs that fabricate data. Failures are never surfaced.
|
|
6
|
+
## Fix
|
|
7
|
+
Check `result.success` after headless execution. If false, throw with the error message instead of falling through.
|
|
8
|
+
## Files Patched
|
|
9
|
+
- services/worker-daemon.js
|
|
10
|
+
## Ops
|
|
11
|
+
1 op in fix.py
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# HW-002: Headless failures silently swallowed as success
|
|
2
|
+
# GitHub: #1112
|
|
3
|
+
patch("2: honest failures",
|
|
4
|
+
WD,
|
|
5
|
+
""" if (isHeadlessWorker(workerConfig.type) && this.headlessAvailable && this.headlessExecutor) {
|
|
6
|
+
try {
|
|
7
|
+
this.log('info', `Running ${workerConfig.type} in headless mode (Claude Code AI)`);
|
|
8
|
+
const result = await this.headlessExecutor.execute(workerConfig.type);
|
|
9
|
+
return {
|
|
10
|
+
mode: 'headless',
|
|
11
|
+
...result,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
this.log('warn', `Headless execution failed for ${workerConfig.type}, falling back to local mode`);
|
|
16
|
+
this.emit('headless:fallback', {
|
|
17
|
+
type: workerConfig.type,
|
|
18
|
+
error: error instanceof Error ? error.message : String(error),
|
|
19
|
+
});
|
|
20
|
+
// Fall through to local execution
|
|
21
|
+
}
|
|
22
|
+
}""",
|
|
23
|
+
""" if (isHeadlessWorker(workerConfig.type) && this.headlessAvailable && this.headlessExecutor) {
|
|
24
|
+
let result;
|
|
25
|
+
try {
|
|
26
|
+
this.log('info', `Running ${workerConfig.type} in headless mode (Claude Code AI)`);
|
|
27
|
+
result = await this.headlessExecutor.execute(workerConfig.type);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
31
|
+
this.log('warn', `Headless execution threw for ${workerConfig.type}: ${errorMsg}`);
|
|
32
|
+
this.emit('headless:fallback', { type: workerConfig.type, error: errorMsg });
|
|
33
|
+
throw error instanceof Error ? error : new Error(errorMsg);
|
|
34
|
+
}
|
|
35
|
+
if (result.success) {
|
|
36
|
+
return { mode: 'headless', ...result };
|
|
37
|
+
}
|
|
38
|
+
const errorMsg = result.error || 'Unknown headless failure';
|
|
39
|
+
this.log('warn', `Headless failed for ${workerConfig.type}: ${errorMsg}`);
|
|
40
|
+
this.emit('headless:fallback', { type: workerConfig.type, error: errorMsg });
|
|
41
|
+
throw new Error(`Headless execution failed for ${workerConfig.type}: ${errorMsg}`);
|
|
42
|
+
}""")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
grep "result.success" services/worker-daemon.js
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# HW-003: Worker scheduling intervals too aggressive
|
|
2
|
+
**Severity**: High
|
|
3
|
+
**GitHub**: [#1113](https://github.com/ruvnet/claude-flow/issues/1113)
|
|
4
|
+
## Root Cause
|
|
5
|
+
`DEFAULT_WORKERS` uses pre-headless intervals (audit: 10m, optimize: 15m, testgaps: 20m). ADR-020 specifies longer intervals (30/60/60m) for headless workers that invoke Claude.
|
|
6
|
+
## Fix
|
|
7
|
+
Align intervals to ADR-020: audit 30m, optimize 60m, testgaps 60m.
|
|
8
|
+
## Files Patched
|
|
9
|
+
- services/worker-daemon.js
|
|
10
|
+
## Ops
|
|
11
|
+
3 ops in fix.py
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# HW-003: Worker scheduling intervals too aggressive
|
|
2
|
+
# GitHub: #1113
|
|
3
|
+
patch("3: audit 30m",
|
|
4
|
+
WD,
|
|
5
|
+
"type: 'audit', intervalMs: 10 * 60 * 1000",
|
|
6
|
+
"type: 'audit', intervalMs: 30 * 60 * 1000")
|
|
7
|
+
|
|
8
|
+
patch("3: optimize 60m",
|
|
9
|
+
WD,
|
|
10
|
+
"type: 'optimize', intervalMs: 15 * 60 * 1000",
|
|
11
|
+
"type: 'optimize', intervalMs: 60 * 60 * 1000")
|
|
12
|
+
|
|
13
|
+
patch("3: testgaps 60m",
|
|
14
|
+
WD,
|
|
15
|
+
"type: 'testgaps', intervalMs: 20 * 60 * 1000",
|
|
16
|
+
"type: 'testgaps', intervalMs: 60 * 60 * 1000")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
grep "30 * 60 * 1000" services/worker-daemon.js
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# IN-001: intelligence.cjs is a stub that doesn't actually learn
|
|
2
|
+
|
|
3
|
+
**Severity**: Critical
|
|
4
|
+
**GitHub**: [#1154](https://github.com/ruvnet/claude-flow/issues/1154)
|
|
5
|
+
**Status**: RESOLVED
|
|
6
|
+
|
|
7
|
+
## Root Cause
|
|
8
|
+
|
|
9
|
+
`findSourceHelpersDir()` in `dist/src/init/executor.js` (line 855) fails to resolve the package's `.claude/helpers/` directory when running via npx. It tries 4 path strategies, all fail with npx-cached installs. The comment at line 395 says it explicitly: *"Source not found (npx with broken paths) — use generated fallbacks"*.
|
|
10
|
+
|
|
11
|
+
This causes `executeUpgrade()` to call `generateIntelligenceStub()` (from `helpers-generator.js` line 557) instead of copying the real file. The stub is 197 lines with:
|
|
12
|
+
- `feedback()` as a no-op
|
|
13
|
+
- `consolidate()` that counts lines and wipes the file
|
|
14
|
+
- `getContext()` using simple Jaccard word overlap with no learning
|
|
15
|
+
- No PageRank, no graph, no confidence tracking
|
|
16
|
+
|
|
17
|
+
## The Full Version Exists in the Package
|
|
18
|
+
|
|
19
|
+
The **916-line full `intelligence.cjs`** ships in the `@claude-flow/cli` package at:
|
|
20
|
+
```
|
|
21
|
+
node_modules/@claude-flow/cli/.claude/helpers/intelligence.cjs
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
It implements:
|
|
25
|
+
- PageRank-ranked memory graph (nodes, edges, power iteration with damping)
|
|
26
|
+
- Trigram matching with stop-word filtering
|
|
27
|
+
- Confidence feedback loop (boost on success, decay on failure)
|
|
28
|
+
- Consolidation: insight generation for hot files, confidence decay for stale entries, graph rebuild
|
|
29
|
+
- Snapshot-based trend tracking (up to 50 snapshots)
|
|
30
|
+
- Bootstrap from MEMORY.md files when store is empty
|
|
31
|
+
- Same 6-method API: `{ init, getContext, recordEdit, feedback, consolidate, stats }`
|
|
32
|
+
- Same data directory: `.claude-flow/data/`
|
|
33
|
+
|
|
34
|
+
## Fix
|
|
35
|
+
|
|
36
|
+
Copy the full `intelligence.cjs` from the package to replace the stub:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Find the package's helpers directory
|
|
40
|
+
SRC=$(find ~/.npm/_npx -path '*/@claude-flow/cli/.claude/helpers/intelligence.cjs' 2>/dev/null | head -1)
|
|
41
|
+
|
|
42
|
+
# Copy to project
|
|
43
|
+
cp "$SRC" .claude/helpers/intelligence.cjs
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This is a drop-in replacement — same export signature, same data files, additive new files (`graph-state.json`, `intelligence-snapshot.json`).
|
|
47
|
+
|
|
48
|
+
## Verification
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Should show nodes > 0, edges > 0 (stub always showed edges: 0)
|
|
52
|
+
node .claude/helpers/intelligence.cjs stats
|
|
53
|
+
|
|
54
|
+
# Should show PageRank sum ~1.0
|
|
55
|
+
node .claude/helpers/intelligence.cjs stats --json
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Files Patched
|
|
59
|
+
|
|
60
|
+
- `init/executor.js`
|
|
61
|
+
|
|
62
|
+
## Ops
|
|
63
|
+
|
|
64
|
+
2 ops in fix.py
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# IN-001: intelligence.cjs generated as stub instead of full version
|
|
2
|
+
# GitHub: #1154
|
|
3
|
+
#
|
|
4
|
+
# When findSourceHelpersDir() fails (npx broken paths), the fallback calls
|
|
5
|
+
# generateIntelligenceStub() — a 197-line no-op. The full 916-line version
|
|
6
|
+
# ships in the package at .claude/helpers/intelligence.cjs.
|
|
7
|
+
#
|
|
8
|
+
# Fix: In both fallback paths, try reading the real file from the package
|
|
9
|
+
# root (via __dirname) before falling back to the stub.
|
|
10
|
+
# 2 ops: upgrade path (line ~398) + writeHelpers path (line ~943)
|
|
11
|
+
|
|
12
|
+
# Op 1: Upgrade path — when findSourceHelpersDir() returns null
|
|
13
|
+
patch("IN-001a: upgrade fallback reads real intelligence.cjs",
|
|
14
|
+
EXECUTOR,
|
|
15
|
+
""" else {
|
|
16
|
+
// Source not found (npx with broken paths) — use generated fallbacks
|
|
17
|
+
const generatedCritical = {
|
|
18
|
+
'hook-handler.cjs': generateHookHandler(),
|
|
19
|
+
'intelligence.cjs': generateIntelligenceStub(),
|
|
20
|
+
'auto-memory-hook.mjs': generateAutoMemoryHook(),
|
|
21
|
+
};""",
|
|
22
|
+
""" else {
|
|
23
|
+
// Source not found (npx with broken paths) — use generated fallbacks
|
|
24
|
+
// IN-001: Try reading real intelligence.cjs from package before using stub
|
|
25
|
+
let intelligenceContent = generateIntelligenceStub();
|
|
26
|
+
try {
|
|
27
|
+
const realPath = path.resolve(__dirname, '..', '..', '..', '.claude', 'helpers', 'intelligence.cjs');
|
|
28
|
+
if (fs.existsSync(realPath)) {
|
|
29
|
+
intelligenceContent = fs.readFileSync(realPath, 'utf-8');
|
|
30
|
+
}
|
|
31
|
+
} catch { /* use stub */ }
|
|
32
|
+
const generatedCritical = {
|
|
33
|
+
'hook-handler.cjs': generateHookHandler(),
|
|
34
|
+
'intelligence.cjs': intelligenceContent,
|
|
35
|
+
'auto-memory-hook.mjs': generateAutoMemoryHook(),
|
|
36
|
+
};""")
|
|
37
|
+
|
|
38
|
+
# Op 2: writeHelpers path — fresh init when source dir not found
|
|
39
|
+
patch("IN-001b: writeHelpers fallback reads real intelligence.cjs",
|
|
40
|
+
EXECUTOR,
|
|
41
|
+
""" // Fall back to generating helpers if source not available
|
|
42
|
+
const helpers = {
|
|
43
|
+
'pre-commit': generatePreCommitHook(),
|
|
44
|
+
'post-commit': generatePostCommitHook(),
|
|
45
|
+
'session.js': generateSessionManager(),
|
|
46
|
+
'router.js': generateAgentRouter(),
|
|
47
|
+
'memory.js': generateMemoryHelper(),
|
|
48
|
+
'hook-handler.cjs': generateHookHandler(),
|
|
49
|
+
'intelligence.cjs': generateIntelligenceStub(),
|
|
50
|
+
'auto-memory-hook.mjs': generateAutoMemoryHook(),
|
|
51
|
+
};""",
|
|
52
|
+
""" // Fall back to generating helpers if source not available
|
|
53
|
+
// IN-001: Try reading real intelligence.cjs from package before using stub
|
|
54
|
+
let intelligenceForInit = generateIntelligenceStub();
|
|
55
|
+
try {
|
|
56
|
+
const realIntelPath = path.resolve(__dirname, '..', '..', '..', '.claude', 'helpers', 'intelligence.cjs');
|
|
57
|
+
if (fs.existsSync(realIntelPath)) {
|
|
58
|
+
intelligenceForInit = fs.readFileSync(realIntelPath, 'utf-8');
|
|
59
|
+
}
|
|
60
|
+
} catch { /* use stub */ }
|
|
61
|
+
const helpers = {
|
|
62
|
+
'pre-commit': generatePreCommitHook(),
|
|
63
|
+
'post-commit': generatePostCommitHook(),
|
|
64
|
+
'session.cjs': generateSessionManager(),
|
|
65
|
+
'router.cjs': generateAgentRouter(),
|
|
66
|
+
'memory.cjs': generateMemoryHelper(),
|
|
67
|
+
'hook-handler.cjs': generateHookHandler(),
|
|
68
|
+
'intelligence.cjs': intelligenceForInit,
|
|
69
|
+
'auto-memory-hook.mjs': generateAutoMemoryHook(),
|
|
70
|
+
};""")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
grep "intelligenceContent" init/executor.js
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# MM-001: Remove dead persistPath config option
|
|
2
|
+
|
|
3
|
+
**Severity**: Low
|
|
4
|
+
**GitHub**: [#1152](https://github.com/ruvnet/claude-flow/issues/1152)
|
|
5
|
+
|
|
6
|
+
## Root Cause
|
|
7
|
+
|
|
8
|
+
The `init` command generates a `persistPath: .claude-flow/data` setting in config.yaml, but **nothing reads it**. All memory storage code (15+ locations across memory-initializer.js and ruvector modules) uses hardcoded `.swarm/` paths.
|
|
9
|
+
|
|
10
|
+
This creates user confusion: the config suggests data goes to `.claude-flow/data/` but it actually goes to `.swarm/`.
|
|
11
|
+
|
|
12
|
+
## Fix
|
|
13
|
+
|
|
14
|
+
Rather than patching 15+ files to respect the config, we:
|
|
15
|
+
1. Remove the misleading `persistPath` line from the generated config.yaml
|
|
16
|
+
2. Revert any previous attempts to read this config (restore `.swarm/` hardcoding)
|
|
17
|
+
|
|
18
|
+
This aligns the config with actual behavior - all data lives in `.swarm/`.
|
|
19
|
+
|
|
20
|
+
## Files Patched
|
|
21
|
+
|
|
22
|
+
- init/executor.js (remove persistPath from config template)
|
|
23
|
+
- memory/memory-initializer.js (revert config-reading code if present)
|
|
24
|
+
|
|
25
|
+
## Ops
|
|
26
|
+
|
|
27
|
+
2 ops in fix.py
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# MM-001: Remove dead persistPath config from init command
|
|
2
|
+
# The persistPath setting is generated but never consumed - all code uses hardcoded .swarm/
|
|
3
|
+
# Rather than patching 15+ files to respect it, we remove the misleading config option.
|
|
4
|
+
|
|
5
|
+
# First: Revert any previous MM-001 patch that tried to read persistPath
|
|
6
|
+
patch("MM-001: revert config reading (restore .swarm/ hardcoding)",
|
|
7
|
+
MI,
|
|
8
|
+
""" // MM-001: Read persistPath from config instead of hardcoding .swarm/
|
|
9
|
+
let dataDir = path.join(process.cwd(), '.swarm'); // fallback
|
|
10
|
+
try {
|
|
11
|
+
const configJsonPath = path.join(process.cwd(), '.claude-flow', 'config.json');
|
|
12
|
+
const configYamlPath = path.join(process.cwd(), '.claude-flow', 'config.yaml');
|
|
13
|
+
if (fs.existsSync(configJsonPath)) {
|
|
14
|
+
const config = JSON.parse(fs.readFileSync(configJsonPath, 'utf-8'));
|
|
15
|
+
const persistPath = config.values?.['memory.persistPath'];
|
|
16
|
+
if (persistPath) {
|
|
17
|
+
dataDir = path.isAbsolute(persistPath) ? persistPath : path.join(process.cwd(), persistPath);
|
|
18
|
+
}
|
|
19
|
+
} else if (fs.existsSync(configYamlPath)) {
|
|
20
|
+
const yamlContent = fs.readFileSync(configYamlPath, 'utf-8');
|
|
21
|
+
const match = yamlContent.match(/persistPath:\\s*([^\\n]+)/);
|
|
22
|
+
if (match) {
|
|
23
|
+
const persistPath = match[1].trim();
|
|
24
|
+
dataDir = path.isAbsolute(persistPath) ? persistPath : path.join(process.cwd(), persistPath);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
} catch { /* use fallback */ }
|
|
28
|
+
if (!fs.existsSync(dataDir)) {
|
|
29
|
+
fs.mkdirSync(dataDir, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
const hnswPath = path.join(dataDir, 'hnsw.index');
|
|
32
|
+
const metadataPath = path.join(dataDir, 'hnsw.metadata.json');
|
|
33
|
+
const dbPath = options?.dbPath || path.join(dataDir, 'memory.db');""",
|
|
34
|
+
""" // Persistent storage paths
|
|
35
|
+
const swarmDir = path.join(process.cwd(), '.swarm');
|
|
36
|
+
if (!fs.existsSync(swarmDir)) {
|
|
37
|
+
fs.mkdirSync(swarmDir, { recursive: true });
|
|
38
|
+
}
|
|
39
|
+
const hnswPath = path.join(swarmDir, 'hnsw.index');
|
|
40
|
+
const metadataPath = path.join(swarmDir, 'hnsw.metadata.json');
|
|
41
|
+
const dbPath = options?.dbPath || path.join(swarmDir, 'memory.db');""")
|
|
42
|
+
|
|
43
|
+
# Second: Remove persistPath from generated config.yaml (init/executor.js)
|
|
44
|
+
patch("MM-001: remove persistPath from config.yaml template",
|
|
45
|
+
EXECUTOR,
|
|
46
|
+
"""memory:
|
|
47
|
+
backend: ${options.runtime.memoryBackend}
|
|
48
|
+
enableHNSW: ${options.runtime.enableHNSW}
|
|
49
|
+
persistPath: .claude-flow/data
|
|
50
|
+
cacheSize: 100""",
|
|
51
|
+
"""memory:
|
|
52
|
+
backend: ${options.runtime.memoryBackend}
|
|
53
|
+
enableHNSW: ${options.runtime.enableHNSW}
|
|
54
|
+
cacheSize: 100""")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
absent "persistPath: .claude-flow/data" init/executor.js
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# NS-001: Discovery ops default to wrong namespace
|
|
2
|
+
**Severity**: Critical
|
|
3
|
+
**GitHub**: [#1123](https://github.com/ruvnet/claude-flow/issues/1123)
|
|
4
|
+
## Root Cause
|
|
5
|
+
MCP `memory_search` defaulted to `namespace='default'`, but entries live in 'patterns', 'solutions', etc. Every MCP search returned 0 results. MCP `memory_list` had no 'all' support — truthiness check treated 'all' as truthy, generating `WHERE namespace = 'all'` which returns 0 results.
|
|
6
|
+
## Rule
|
|
7
|
+
Discovery ops (search, list) default to 'all' — search across all namespaces.
|
|
8
|
+
## Fix
|
|
9
|
+
MCP search, core searchEntries(), embeddings search, MCP list, CLI list all default to 'all'. Core listEntries() uses nsFilter variable to distinguish between 'all' sentinel and real namespace filtering.
|
|
10
|
+
## Files Patched
|
|
11
|
+
- mcp-tools/memory-tools.js (search + list)
|
|
12
|
+
- mcp-tools/embeddings-tools.js (search)
|
|
13
|
+
- memory/memory-initializer.js (searchEntries, listEntries)
|
|
14
|
+
- commands/memory.js (CLI list)
|
|
15
|
+
## Ops
|
|
16
|
+
10 ops in fix.py (19a-e + 21c,d,g,i,j)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# NS-001: Discovery ops (search + list) default to wrong namespace
|
|
2
|
+
# GitHub: #1123
|
|
3
|
+
# Rule: Default to 'all' (search across all namespaces)
|
|
4
|
+
# 10 ops: 19a-e (search) + 21c,d,g,i,j (list)
|
|
5
|
+
|
|
6
|
+
# ── Search ops (from old Patch 19) ──
|
|
7
|
+
|
|
8
|
+
# 19a: MCP search handler — change default from 'default' to 'all'
|
|
9
|
+
patch("19a: MCP search namespace default",
|
|
10
|
+
MCP_MEMORY,
|
|
11
|
+
"const query = input.query;\n const namespace = input.namespace || 'default';",
|
|
12
|
+
"const query = input.query;\n const namespace = input.namespace || 'all';")
|
|
13
|
+
|
|
14
|
+
# 19b: MCP search schema — update description to reflect 'all' default
|
|
15
|
+
patch("19b: MCP search namespace description",
|
|
16
|
+
MCP_MEMORY,
|
|
17
|
+
"""namespace: { type: 'string', description: 'Namespace to search (default: "default")' }""",
|
|
18
|
+
"""namespace: { type: 'string', description: 'Namespace to search (default: "all" = all namespaces)' }""")
|
|
19
|
+
|
|
20
|
+
# 19c: Core searchEntries() — change function default from 'default' to 'all'
|
|
21
|
+
patch("19c: searchEntries default all",
|
|
22
|
+
MI,
|
|
23
|
+
"const { query, namespace = 'default', limit = 10, threshold = 0.3, dbPath: customPath } = options;",
|
|
24
|
+
"const { query, namespace = 'all', limit = 10, threshold = 0.3, dbPath: customPath } = options;")
|
|
25
|
+
|
|
26
|
+
# 19d: Embeddings search — pass 'all' instead of 'default' to searchEntries
|
|
27
|
+
patch("19d: embeddings search namespace all",
|
|
28
|
+
EMB_TOOLS,
|
|
29
|
+
"namespace: namespace || 'default'\n });",
|
|
30
|
+
"namespace: namespace || 'all'\n });")
|
|
31
|
+
|
|
32
|
+
# 19e: Embeddings metadata — all occurrences of namespace fallback
|
|
33
|
+
patch_all("19e: embeddings metadata namespace all",
|
|
34
|
+
EMB_TOOLS,
|
|
35
|
+
"namespace: namespace || 'default',",
|
|
36
|
+
"namespace: namespace || 'all',")
|
|
37
|
+
|
|
38
|
+
# ── List ops (from old Patch 21) ──
|
|
39
|
+
|
|
40
|
+
# 21c: MCP list — update description to reflect 'all' default
|
|
41
|
+
patch("21c: MCP list namespace description",
|
|
42
|
+
MCP_MEMORY,
|
|
43
|
+
"namespace: { type: 'string', description: 'Filter by namespace' },",
|
|
44
|
+
"namespace: { type: 'string', description: 'Namespace to list (default: \"all\" = all namespaces)' },")
|
|
45
|
+
|
|
46
|
+
# 21d: MCP list — default to 'all' (read-only discovery, like search)
|
|
47
|
+
patch("21d: MCP list namespace default all",
|
|
48
|
+
MCP_MEMORY,
|
|
49
|
+
"const { listEntries } = await getMemoryFunctions();\n const namespace = input.namespace;\n const limit = input.limit || 50;",
|
|
50
|
+
"const { listEntries } = await getMemoryFunctions();\n const namespace = input.namespace || 'all';\n const limit = input.limit || 50;")
|
|
51
|
+
|
|
52
|
+
# 21g: CLI list — default to 'all' (read-only discovery, like search)
|
|
53
|
+
patch("21g: CLI list namespace default all",
|
|
54
|
+
CLI_MEMORY,
|
|
55
|
+
" const namespace = ctx.flags.namespace;\n const limit = ctx.flags.limit;\n // Use sql.js directly for consistent data access",
|
|
56
|
+
" const namespace = ctx.flags.namespace || 'all';\n const limit = ctx.flags.limit;\n // Use sql.js directly for consistent data access")
|
|
57
|
+
|
|
58
|
+
# 21i: Core listEntries() — use nsFilter variable instead of truthiness check
|
|
59
|
+
patch("21i: listEntries nsFilter variable",
|
|
60
|
+
MI,
|
|
61
|
+
" // Get total count\n const countQuery = namespace",
|
|
62
|
+
" // Get total count\n const nsFilter = namespace && namespace !== 'all';\n const countQuery = nsFilter")
|
|
63
|
+
|
|
64
|
+
# 21j: Core listEntries() — use nsFilter in list query too
|
|
65
|
+
patch("21j: listEntries listQuery all support",
|
|
66
|
+
MI,
|
|
67
|
+
" ${namespace ? `AND namespace",
|
|
68
|
+
" ${nsFilter ? `AND namespace")
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# NS-002: Store/delete/retrieve fall back to 'default' + accept 'all'
|
|
2
|
+
**Severity**: Critical
|
|
3
|
+
**GitHub**: [#581](https://github.com/ruvnet/claude-flow/issues/581)
|
|
4
|
+
## Root Cause
|
|
5
|
+
MCP/CLI/Core used `namespace || 'default'`, silently routing entries to wrong namespace. Also accepted 'all' (search/list sentinel) as a write namespace, creating invisible entries.
|
|
6
|
+
## Rule
|
|
7
|
+
Targeted ops (store, delete, retrieve) require explicit namespace. Block 'all' with clear error.
|
|
8
|
+
## Fix
|
|
9
|
+
Remove fallback. Add 'namespace' to MCP schema required fields. Add runtime throw for missing/invalid namespace. CLI commands check before executing. Core functions throw on missing namespace.
|
|
10
|
+
## Files Patched
|
|
11
|
+
- mcp-tools/memory-tools.js (store, delete, retrieve)
|
|
12
|
+
- commands/memory.js (store, delete, retrieve)
|
|
13
|
+
- memory/memory-initializer.js (storeEntry, deleteEntry, getEntry)
|
|
14
|
+
## Dependencies
|
|
15
|
+
|
|
16
|
+
Depends on NS-001 (190) — NS-002 builds on the namespace discovery changes from NS-001.
|
|
17
|
+
|
|
18
|
+
## Ops
|
|
19
|
+
14 ops in fix.py (20a-i + 21a,b,e,f,h)
|