@sparkleideas/claude-flow-patch 3.1.0-alpha.44.patch.4 → 3.1.0-alpha.44.patch.6
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 +2 -2
- package/CLAUDE.md +35 -8
- package/README.md +83 -302
- package/check-patches.sh +6 -2
- package/package.json +4 -3
- package/patch/135-HK-004-respect-daemon-autostart/README.md +11 -0
- package/patch/135-HK-004-respect-daemon-autostart/fix.py +14 -0
- package/patch/135-HK-004-respect-daemon-autostart/sentinel +1 -0
- package/patch/160-HW-003-aggressive-intervals/README.md +4 -4
- package/patch/160-HW-003-aggressive-intervals/fix.py +36 -0
- package/patch/160-HW-003-aggressive-intervals/sentinel +3 -1
- package/patch/170-IN-001-intelligence-stub/fix.py +3 -10
- package/patch/270-SG-003-init-helpers-all-paths/fix.py +2 -1
- package/patch/300-DM-006-log-rotation/README.md +5 -4
- package/patch/300-DM-006-log-rotation/fix.py +14 -0
- package/patch/300-DM-006-log-rotation/sentinel +1 -0
- package/scripts/{update-docs.mjs → preflight.mjs} +74 -33
package/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @sparkleideas/claude-flow-patch
|
|
2
2
|
|
|
3
|
-
> Runtime patches for `@claude-flow/cli` v3.1.0-alpha.
|
|
3
|
+
> Runtime patches for `@claude-flow/cli` v3.1.0-alpha.41, `ruvector`, and `ruv-swarm` v1.0.20
|
|
4
4
|
|
|
5
5
|
**Claude Code instructions are in [CLAUDE.md](CLAUDE.md). Project-specific instructions (defect index, workflows, policies) are in [README.md](README.md).**
|
|
6
6
|
|
|
@@ -95,7 +95,7 @@ Use `$skill-name` syntax to invoke:
|
|
|
95
95
|
|
|
96
96
|
[optional body]
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
Sparkling Ideas <henrik@sparklingideas.co.uk>
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`
|
package/CLAUDE.md
CHANGED
|
@@ -24,6 +24,7 @@ Runtime patches for `@claude-flow/cli` **v3.1.0-alpha.41**, `ruvector`, and `ruv
|
|
|
24
24
|
- NEVER reuse a defect ID that was previously assigned to a different GitHub issue
|
|
25
25
|
- ONE defect directory and ONE fix.py per GitHub issue -- do not combine multiple GitHub issues into one defect or split one GitHub issue across multiple defects
|
|
26
26
|
- ALWAYS verify with `bash check-patches.sh` after applying
|
|
27
|
+
- ALWAYS run `npm run preflight` before staging — the pre-commit hook (`hooks/pre-commit`) enforces this via `--check` mode
|
|
27
28
|
- ALWAYS update ALL listing files when adding/removing a defect (see checklist)
|
|
28
29
|
- Execution order is determined by the numeric prefix on each defect directory name. Dependencies between defects are expressed by assigning lower numbers to prerequisites.
|
|
29
30
|
|
|
@@ -38,7 +39,7 @@ lib/
|
|
|
38
39
|
discover.mjs # Dynamic discovery: scans patch/*/ → structured JSON
|
|
39
40
|
categories.json # Prefix-to-label mapping (one line per category)
|
|
40
41
|
scripts/
|
|
41
|
-
|
|
42
|
+
preflight.mjs # Pre-commit sync: doc tables, versions, config (npm run preflight)
|
|
42
43
|
upstream-log.mjs # Show recent upstream releases (npm run upstream-log [count])
|
|
43
44
|
patch/
|
|
44
45
|
{NNN}-{PREFIX}-{NNN}-{slug}/ # NNN = 3-digit execution order
|
|
@@ -135,7 +136,7 @@ Save the returned GitHub issue number for the defect README.md.
|
|
|
135
136
|
| DM | Daemon & Workers | 6 |
|
|
136
137
|
| EM | Embeddings & HNSW | 2 |
|
|
137
138
|
| GV | Ghost Vectors | 1 |
|
|
138
|
-
| HK | Hooks |
|
|
139
|
+
| HK | Hooks | 4 |
|
|
139
140
|
| HW | Headless Worker | 4 |
|
|
140
141
|
| IN | Intelligence | 1 |
|
|
141
142
|
| MM | Memory Management | 1 |
|
|
@@ -145,7 +146,7 @@ Save the returned GitHub issue number for the defect README.md.
|
|
|
145
146
|
| SG | Settings Generator | 2 |
|
|
146
147
|
| UI | Display & Cosmetic | 2 |
|
|
147
148
|
|
|
148
|
-
## All
|
|
149
|
+
## All 32 Defects
|
|
149
150
|
|
|
150
151
|
| ID | GitHub Issue | Severity |
|
|
151
152
|
|----|-------------|----------|
|
|
@@ -162,9 +163,10 @@ Save the returned GitHub issue number for the defect README.md.
|
|
|
162
163
|
| HK-001 | [#1155 post-edit hook records file_path as "unknown"](https://github.com/ruvnet/claude-flow/issues/1155) | Medium |
|
|
163
164
|
| HK-002 | [#1058 MCP hook handlers are stubs that don't persist data](https://github.com/ruvnet/claude-flow/issues/1058) | High |
|
|
164
165
|
| HK-003 | [#1158 hooks_metrics MCP handler returns hardcoded fake data](https://github.com/ruvnet/claude-flow/issues/1158) | High |
|
|
166
|
+
| HK-004 | [#1175 hooks_session-start ignores daemon.autoStart from settings.json](https://github.com/ruvnet/claude-flow/issues/1175) | High |
|
|
165
167
|
| HW-001 | [#1111 Headless workers hang — stdin pipe never closed](https://github.com/ruvnet/claude-flow/issues/1111) | Critical |
|
|
166
168
|
| HW-002 | [#1112 Headless failures silently swallowed as success](https://github.com/ruvnet/claude-flow/issues/1112) | High |
|
|
167
|
-
| HW-003 | [#1113 Worker scheduling intervals too aggressive](https://github.com/ruvnet/claude-flow/issues/1113) | High |
|
|
169
|
+
| HW-003 | [#1113 Worker scheduling intervals too aggressive + settings ignored](https://github.com/ruvnet/claude-flow/issues/1113) | High |
|
|
168
170
|
| IN-001 | [#1154 intelligence.cjs is a stub that doesn't actually learn](https://github.com/ruvnet/claude-flow/issues/1154) | Critical |
|
|
169
171
|
| MM-001 | [#1152 Remove dead persistPath config option](https://github.com/ruvnet/claude-flow/issues/1152) | Low |
|
|
170
172
|
| NS-001 | [#1123 Discovery ops default to wrong namespace](https://github.com/ruvnet/claude-flow/issues/1123) | Critical |
|
|
@@ -178,7 +180,7 @@ Save the returned GitHub issue number for the defect README.md.
|
|
|
178
180
|
| SG-003 | [#1169 Init missing helpers for --dual, --minimal, hooks, and upgrade paths](https://github.com/ruvnet/claude-flow/issues/1169) | Critical |
|
|
179
181
|
| UI-001 | [#1145 intelligence stats crashes on .toFixed()](https://github.com/ruvnet/claude-flow/issues/1145) | Critical |
|
|
180
182
|
| UI-002 | [#1146 neural status shows "Not loaded"](https://github.com/ruvnet/claude-flow/issues/1146) | Low |
|
|
181
|
-
| DM-006 | [#1114 No log rotation —
|
|
183
|
+
| DM-006 | [#1114 No log rotation — logs grow unbounded](https://github.com/ruvnet/claude-flow/issues/1114) | Medium |
|
|
182
184
|
| HW-004 | [#1117 runWithTimeout rejects but does not kill child process](https://github.com/ruvnet/claude-flow/issues/1117) | Medium |
|
|
183
185
|
<!-- GENERATED:defect-tables:end -->
|
|
184
186
|
|
|
@@ -313,7 +315,7 @@ To target a new file, add a variable to `lib/common.py` following the existing p
|
|
|
313
315
|
|
|
314
316
|
```bash
|
|
315
317
|
# Regenerate all documentation from dynamic discovery
|
|
316
|
-
npm run
|
|
318
|
+
npm run preflight
|
|
317
319
|
|
|
318
320
|
# Apply -- should show "Applied: ..."
|
|
319
321
|
bash patch-all.sh --global
|
|
@@ -339,7 +341,7 @@ npm test
|
|
|
339
341
|
- [ ] `patch/{PREFIX}-{NNN}-{slug}/sentinel` created with verification directives
|
|
340
342
|
- [ ] Path variable added to `lib/common.py` (if targeting a new file)
|
|
341
343
|
- [ ] If new category prefix: add one line to `lib/categories.json`
|
|
342
|
-
- [ ] `npm run
|
|
344
|
+
- [ ] `npm run preflight` regenerates all doc tables
|
|
343
345
|
- [ ] `bash patch-all.sh` applies successfully
|
|
344
346
|
- [ ] `bash patch-all.sh` is idempotent (0 applied on re-run)
|
|
345
347
|
- [ ] `bash check-patches.sh` shows OK
|
|
@@ -355,7 +357,7 @@ Before removing any defect:
|
|
|
355
357
|
1. Confirm the bug is genuinely fixed upstream or the patch is truly unreachable.
|
|
356
358
|
2. Do NOT remove a defect just because a local workaround exists -- the MCP-level patch may still be needed.
|
|
357
359
|
3. If removing, retire the defect ID permanently. Never reassign a deleted ID to a different GitHub issue.
|
|
358
|
-
4. Run `npm run
|
|
360
|
+
4. Run `npm run preflight` to regenerate all documentation.
|
|
359
361
|
|
|
360
362
|
---
|
|
361
363
|
|
|
@@ -450,6 +452,31 @@ Two dependency chains exist:
|
|
|
450
452
|
|
|
451
453
|
All other patches are independent.
|
|
452
454
|
|
|
455
|
+
## Preflight & Pre-Commit Hook
|
|
456
|
+
|
|
457
|
+
A git pre-commit hook at `hooks/pre-commit` runs automatically on every commit. It calls `npm run preflight:check` (read-only) and `npm test`. If anything is stale or tests fail, the commit is blocked.
|
|
458
|
+
|
|
459
|
+
**Setup** (one-time, already done for this clone):
|
|
460
|
+
```bash
|
|
461
|
+
git config core.hooksPath hooks
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**Before staging**, run:
|
|
465
|
+
```bash
|
|
466
|
+
npm run preflight # Syncs doc tables, defect counts, version strings, config
|
|
467
|
+
npm test # Runs all tests
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Then `git add -u` to stage the regenerated files.
|
|
471
|
+
|
|
472
|
+
**What `preflight` syncs**:
|
|
473
|
+
- Defect tables in README.md, CLAUDE.md, npm/README.md (from `patch/*/README.md`)
|
|
474
|
+
- Defect counts in `npm/config.json` (from discovery)
|
|
475
|
+
- `npm/config.json` version.current (from `package.json`)
|
|
476
|
+
- Upstream baseline version in prose (from `npm/config.json` targets)
|
|
477
|
+
|
|
478
|
+
Manual edits to generated sections (`<!-- GENERATED:*:begin/end -->`) will be overwritten.
|
|
479
|
+
|
|
453
480
|
## Key Design Decisions
|
|
454
481
|
|
|
455
482
|
- **Idempotent**: `patch()` checks if `new` string is already present before replacing.
|
package/README.md
CHANGED
|
@@ -1,42 +1,71 @@
|
|
|
1
1
|
# @sparkleideas/claude-flow-patch
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
3
|
+
Patch toolkit for `@claude-flow/cli` runtime and init-script defects.
|
|
4
|
+
|
|
5
|
+
This package applies verified, idempotent patches to your local CLI source in the npm cache or local `node_modules`, then verifies sentinels and can repair projects initialized before patching.
|
|
6
|
+
|
|
7
|
+
## What This Solves
|
|
8
|
+
|
|
9
|
+
`claude-flow init` can generate incomplete or broken project helpers when upstream defects are present. This toolkit addresses known defects in:
|
|
10
|
+
|
|
11
|
+
- `@claude-flow/cli`
|
|
12
|
+
- `ruvector`
|
|
13
|
+
- `ruv-swarm`
|
|
14
|
+
|
|
15
|
+
<!-- GENERATED:npm-defects:begin -->
|
|
16
|
+
32 tracked defects across 13 categories.
|
|
17
|
+
|
|
18
|
+
| Defect | Description | GitHub Issue |
|
|
19
|
+
|--------|-------------|-------------|
|
|
20
|
+
| [CF-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/010-CF-001-doctor-yaml) | Doctor ignores YAML config files | [#1141](https://github.com/ruvnet/claude-flow/issues/1141) |
|
|
21
|
+
| [CF-002](https://github.com/sparkling/claude-flow-patch/tree/master/patch/020-CF-002-config-export-yaml) | Config export shows hardcoded defaults | [#1142](https://github.com/ruvnet/claude-flow/issues/1142) |
|
|
22
|
+
| [DM-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/030-DM-001-daemon-log-zero) | daemon.log always 0 bytes | [#1116](https://github.com/ruvnet/claude-flow/issues/1116) |
|
|
23
|
+
| [DM-002](https://github.com/sparkling/claude-flow-patch/tree/master/patch/040-DM-002-cpu-load-threshold) | maxCpuLoad=2.0 blocks all workers on multi-core | [#1138](https://github.com/ruvnet/claude-flow/issues/1138) |
|
|
24
|
+
| [DM-003](https://github.com/sparkling/claude-flow-patch/tree/master/patch/050-DM-003-macos-freemem) | macOS freemem() always ~0% — workers blocked | [#1077](https://github.com/ruvnet/claude-flow/issues/1077) |
|
|
25
|
+
| [DM-004](https://github.com/sparkling/claude-flow-patch/tree/master/patch/060-DM-004-preload-worker-stub) | Preload worker stub + missing from defaults | [#1139](https://github.com/ruvnet/claude-flow/issues/1139) |
|
|
26
|
+
| [DM-005](https://github.com/sparkling/claude-flow-patch/tree/master/patch/070-DM-005-consolidation-worker-stub) | Consolidation worker stub (no decay/rebuild) | [#1140](https://github.com/ruvnet/claude-flow/issues/1140) |
|
|
27
|
+
| [DM-006](https://github.com/sparkling/claude-flow-patch/tree/master/patch/300-DM-006-log-rotation) | No log rotation — logs grow unbounded | [#1114](https://github.com/ruvnet/claude-flow/issues/1114) |
|
|
28
|
+
| [EM-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/080-EM-001-embedding-ignores-config) | Embedding system ignores project config (model + HNSW dims) | [#1143](https://github.com/ruvnet/claude-flow/issues/1143) |
|
|
29
|
+
| [EM-002](https://github.com/sparkling/claude-flow-patch/tree/master/patch/090-EM-002-transformers-cache-eacces) | @xenova/transformers cache EACCES | [#1144](https://github.com/ruvnet/claude-flow/issues/1144) |
|
|
30
|
+
| [GV-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/100-GV-001-hnsw-ghost-vectors) | HNSW ghost vectors persist after memory delete | [#1122](https://github.com/ruvnet/claude-flow/issues/1122) |
|
|
31
|
+
| [HK-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/110-HK-001-post-edit-file-path) | post-edit hook records file_path as "unknown" | [#1155](https://github.com/ruvnet/claude-flow/issues/1155) |
|
|
32
|
+
| [HK-002](https://github.com/sparkling/claude-flow-patch/tree/master/patch/120-HK-002-hooks-tools-stub) | MCP hook handlers are stubs that don't persist data | [#1058](https://github.com/ruvnet/claude-flow/issues/1058) |
|
|
33
|
+
| [HK-003](https://github.com/sparkling/claude-flow-patch/tree/master/patch/130-HK-003-metrics-hardcoded) | hooks_metrics MCP handler returns hardcoded fake data | [#1158](https://github.com/ruvnet/claude-flow/issues/1158) |
|
|
34
|
+
| [HK-004](https://github.com/sparkling/claude-flow-patch/tree/master/patch/135-HK-004-respect-daemon-autostart) | hooks_session-start ignores daemon.autoStart from settings.json | [#1175](https://github.com/ruvnet/claude-flow/issues/1175) |
|
|
35
|
+
| [HW-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/140-HW-001-stdin-hang) | Headless workers hang — stdin pipe never closed | [#1111](https://github.com/ruvnet/claude-flow/issues/1111) |
|
|
36
|
+
| [HW-002](https://github.com/sparkling/claude-flow-patch/tree/master/patch/150-HW-002-failures-swallowed) | Headless failures silently swallowed as success | [#1112](https://github.com/ruvnet/claude-flow/issues/1112) |
|
|
37
|
+
| [HW-003](https://github.com/sparkling/claude-flow-patch/tree/master/patch/160-HW-003-aggressive-intervals) | Worker scheduling intervals too aggressive + settings ignored | [#1113](https://github.com/ruvnet/claude-flow/issues/1113) |
|
|
38
|
+
| [HW-004](https://github.com/sparkling/claude-flow-patch/tree/master/patch/310-HW-004-runwithtimeout-orphan) | runWithTimeout rejects but does not kill child process | [#1117](https://github.com/ruvnet/claude-flow/issues/1117) |
|
|
39
|
+
| [IN-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/170-IN-001-intelligence-stub) | intelligence.cjs is a stub that doesn't actually learn | [#1154](https://github.com/ruvnet/claude-flow/issues/1154) |
|
|
40
|
+
| [MM-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/180-MM-001-memory-persist-path) | Remove dead persistPath config option | [#1152](https://github.com/ruvnet/claude-flow/issues/1152) |
|
|
41
|
+
| [NS-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/190-NS-001-discovery-default-namespace) | Discovery ops default to wrong namespace | [#1123](https://github.com/ruvnet/claude-flow/issues/1123) |
|
|
42
|
+
| [NS-002](https://github.com/sparkling/claude-flow-patch/tree/master/patch/200-NS-002-targeted-require-namespace) | Store/delete/retrieve fall back to 'default' + accept 'all' | [#581](https://github.com/ruvnet/claude-flow/issues/581) |
|
|
43
|
+
| [NS-003](https://github.com/sparkling/claude-flow-patch/tree/master/patch/210-NS-003-namespace-typo-pattern) | Namespace typo 'pattern' vs 'patterns' | [#1136](https://github.com/ruvnet/claude-flow/issues/1136) |
|
|
44
|
+
| [RS-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/220-RS-001-better-sqlite3-node24) | ruv-swarm MCP fails on Node 24 — better-sqlite3 missing native bindings | [ruv-FANN#185](https://github.com/ruvnet/ruv-FANN/issues/185) |
|
|
45
|
+
| [RV-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/230-RV-001-force-learn-tick) | force-learn command calls intel.tick() which doesn't exist | [#1156](https://github.com/ruvnet/claude-flow/issues/1156) |
|
|
46
|
+
| [RV-002](https://github.com/sparkling/claude-flow-patch/tree/master/patch/240-RV-002-trajectory-load) | activeTrajectories not loaded from saved file | [#1157](https://github.com/ruvnet/claude-flow/issues/1157) |
|
|
47
|
+
| [RV-003](https://github.com/sparkling/claude-flow-patch/tree/master/patch/250-RV-003-trajectory-stats-sync) | trajectory-end does not update stats counters | [ruv-FANN#186](https://github.com/ruvnet/ruv-FANN/issues/186) |
|
|
48
|
+
| [SG-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/260-SG-001-init-settings) | Init generates invalid settings | [#1150](https://github.com/ruvnet/claude-flow/issues/1150) |
|
|
49
|
+
| [SG-003](https://github.com/sparkling/claude-flow-patch/tree/master/patch/270-SG-003-init-helpers-all-paths) | Init missing helpers for --dual, --minimal, hooks, and upgrade paths | [#1169](https://github.com/ruvnet/claude-flow/issues/1169) |
|
|
50
|
+
| [UI-001](https://github.com/sparkling/claude-flow-patch/tree/master/patch/280-UI-001-intelligence-stats-crash) | intelligence stats crashes on .toFixed() | [#1145](https://github.com/ruvnet/claude-flow/issues/1145) |
|
|
51
|
+
| [UI-002](https://github.com/sparkling/claude-flow-patch/tree/master/patch/290-UI-002-neural-status-not-loaded) | neural status shows "Not loaded" | [#1146](https://github.com/ruvnet/claude-flow/issues/1146) |
|
|
52
|
+
<!-- GENERATED:npm-defects:end -->
|
|
25
53
|
|
|
26
54
|
## Quick Start
|
|
27
55
|
|
|
28
|
-
|
|
56
|
+
Patch first, then initialize projects.
|
|
29
57
|
|
|
30
58
|
```bash
|
|
31
|
-
# 1
|
|
59
|
+
# 1) apply patches (global npx cache)
|
|
32
60
|
npx --yes @sparkleideas/claude-flow-patch --global
|
|
33
61
|
|
|
34
|
-
# 2
|
|
35
|
-
npx @claude-flow/cli@latest init # fresh project
|
|
36
|
-
npx @claude-flow/cli@latest init upgrade # existing project
|
|
37
|
-
|
|
38
|
-
# 3. Verify
|
|
62
|
+
# 2) verify sentinels
|
|
39
63
|
npx --yes @sparkleideas/claude-flow-patch check
|
|
64
|
+
|
|
65
|
+
# 3) now initialize or upgrade project
|
|
66
|
+
npx @claude-flow/cli@latest init
|
|
67
|
+
# or
|
|
68
|
+
npx @claude-flow/cli@latest init upgrade
|
|
40
69
|
```
|
|
41
70
|
|
|
42
71
|
If you already initialized before patching:
|
|
@@ -45,19 +74,6 @@ If you already initialized before patching:
|
|
|
45
74
|
npx --yes @sparkleideas/claude-flow-patch repair --target /path/to/project
|
|
46
75
|
```
|
|
47
76
|
|
|
48
|
-
### Target Options
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
npx --yes @sparkleideas/claude-flow-patch # global npx cache (default)
|
|
52
|
-
npx --yes @sparkleideas/claude-flow-patch --global # explicit global
|
|
53
|
-
npx --yes @sparkleideas/claude-flow-patch --target ~/my-project # project's node_modules
|
|
54
|
-
npx --yes @sparkleideas/claude-flow-patch --global --target ~/my-project # both
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
`npx @claude-flow/cli` uses local `node_modules` if present, otherwise the global npx cache. Use `--target` to patch a project's local install.
|
|
58
|
-
|
|
59
|
-
<a id="cli-commands"></a>
|
|
60
|
-
|
|
61
77
|
## CLI Commands
|
|
62
78
|
|
|
63
79
|
| Command | Purpose |
|
|
@@ -67,281 +83,46 @@ npx --yes @sparkleideas/claude-flow-patch --global --target ~/my-project # bot
|
|
|
67
83
|
| `claude-flow-patch check` | Verify patch sentinels and auto-detect drift |
|
|
68
84
|
| `claude-flow-patch repair --target <dir> [--source auto\|local\|global] [--dry-run]` | Rehydrate `.claude/helpers` in projects initialized before patching |
|
|
69
85
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
## How It Works
|
|
73
|
-
|
|
74
|
-
1. `patch-all.sh` locates the `@claude-flow/cli` dist files in the npm/npx cache
|
|
75
|
-
2. Globs `patch/*/fix.py` (numeric prefixes on directories ensure correct execution order)
|
|
76
|
-
3. Concatenates `lib/common.py` with each `fix.py` and runs as a single Python process
|
|
77
|
-
4. Each patch is idempotent: skips if already applied, warns if source changed
|
|
78
|
-
|
|
79
|
-
The `check-patches.sh` sentinel runs on session start to detect npx cache wipes and auto-reapply. It reads `sentinel` files from each patch directory — no hardcoded patch list.
|
|
80
|
-
|
|
81
|
-
<a id="sentinel-files"></a>
|
|
82
|
-
|
|
83
|
-
### Sentinel Files
|
|
84
|
-
|
|
85
|
-
Each patch directory contains a `sentinel` file that declares how to verify the patch is applied:
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
grep "pattern to find" relative/path/to/file.js
|
|
89
|
-
absent "pattern that should NOT exist" relative/path.js
|
|
90
|
-
none
|
|
91
|
-
package: ruvector
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
| Directive | Meaning |
|
|
95
|
-
|-----------|---------|
|
|
96
|
-
| `grep "..." file` | Pass if pattern is found in file (standard check) |
|
|
97
|
-
| `absent "..." file` | Pass if pattern is **not** found (removal check) |
|
|
98
|
-
| `none` | No sentinel — skip verification |
|
|
99
|
-
| `package: X` | Target package (default: `@claude-flow/cli`). Skipped if package not installed |
|
|
100
|
-
|
|
101
|
-
`check-patches.sh` and `lib/discover.mjs` both read these files dynamically. Adding a new patch requires no edits to any script — just create the `sentinel` file in the new patch directory.
|
|
102
|
-
|
|
103
|
-
<a id="target-packages"></a>
|
|
104
|
-
|
|
105
|
-
### Target Packages
|
|
106
|
-
|
|
107
|
-
| Package | Version | Location | Env var |
|
|
108
|
-
|---------|---------|----------|---------|
|
|
109
|
-
| `@claude-flow/cli` | `3.1.0-alpha.41` | `~/.npm/_npx/*/node_modules/@claude-flow/cli/dist/src/` | `BASE` |
|
|
110
|
-
| `ruvector` | (bundled) | `~/.npm/_npx/*/node_modules/ruvector/bin/cli.js` | `RUVECTOR_CLI` |
|
|
111
|
-
| `ruv-swarm` | `1.0.20` | `~/.npm/_npx/*/node_modules/ruv-swarm/` | (found via glob) |
|
|
112
|
-
|
|
113
|
-
`BASE` is set by `patch-all.sh`. All path variables in `lib/common.py` derive from it.
|
|
114
|
-
`RUVECTOR_CLI` is set by `patch-all.sh` to the ruvector CLI entry point.
|
|
115
|
-
RS-001 locates its own target via `find`.
|
|
116
|
-
|
|
117
|
-
<a id="dependency-order"></a>
|
|
118
|
-
|
|
119
|
-
### Dependency Order
|
|
120
|
-
|
|
121
|
-
Execution order is controlled by 3-digit numeric prefixes on directory names (e.g. `010-CF-001-*`,
|
|
122
|
-
`170-IN-001-*`). `patch-all.sh` globs `patch/*/fix.py`, which sorts lexicographically — numeric
|
|
123
|
-
prefixes guarantee correct order.
|
|
124
|
-
|
|
125
|
-
Two dependency chains exist:
|
|
126
|
-
|
|
127
|
-
| Chain | Directories | Reason |
|
|
128
|
-
|-------|-------------|--------|
|
|
129
|
-
| IN-001 -> SG-003 | `170-IN-001-*` before `270-SG-003-*` | SG-003's patch targets code introduced by IN-001 |
|
|
130
|
-
| NS-001 -> NS-002 -> NS-003 | `190-NS-001-*` before `200-NS-002-*` before `210-NS-003-*` | Sequential namespace fixes |
|
|
131
|
-
|
|
132
|
-
All other patches are independent.
|
|
133
|
-
|
|
134
|
-
<a id="key-design-decisions"></a>
|
|
135
|
-
|
|
136
|
-
### Key Design Decisions
|
|
137
|
-
|
|
138
|
-
- **Zero-maintenance discovery**: `patch-all.sh`, `check-patches.sh`, and doc generation all discover patches dynamically — no hardcoded lists.
|
|
139
|
-
- **Idempotent**: `patch()` checks if `new` string is already present before replacing.
|
|
140
|
-
- **Non-destructive**: patches only modify the npx cache, never the npm registry package.
|
|
141
|
-
- **Platform-aware**: DM-003 is macOS-only (auto-skipped on Linux).
|
|
142
|
-
- **Sentinel-guarded**: `check-patches.sh` reads `sentinel` files from each patch directory to detect cache wipes and auto-reapply.
|
|
143
|
-
|
|
144
|
-
<a id="repository-structure"></a>
|
|
145
|
-
|
|
146
|
-
### Repository Structure
|
|
147
|
-
|
|
148
|
-
```
|
|
149
|
-
claude-flow-patch/
|
|
150
|
-
README.md # This file
|
|
151
|
-
CLAUDE.md # Claude Code instructions (defect workflow, policies)
|
|
152
|
-
AGENTS.md # Codex agent configuration
|
|
153
|
-
patch-all.sh # Apply all patches (globs patch/*/fix.py dynamically)
|
|
154
|
-
check-patches.sh # Sentinel: reads patch/*/sentinel files dynamically
|
|
155
|
-
repair-post-init.sh # Post-init helper repair
|
|
156
|
-
lib/
|
|
157
|
-
common.py # Shared patch()/patch_all() helpers + path variables
|
|
158
|
-
discover.mjs # Dynamic patch discovery — single source of truth
|
|
159
|
-
categories.json # Prefix-to-label mapping (e.g. HW → Headless Worker)
|
|
160
|
-
scripts/
|
|
161
|
-
update-docs.mjs # Regenerate doc tables from discover() output
|
|
162
|
-
patch/
|
|
163
|
-
{NNN}-{PREFIX}-{NNN}-{slug}/ # NNN = 3-digit execution order
|
|
164
|
-
README.md # Defect report: title, severity, root cause, fix
|
|
165
|
-
fix.py # Idempotent patch script
|
|
166
|
-
fix.sh # Shell-based patch script (EM-002 only)
|
|
167
|
-
sentinel # Verification directives for check-patches.sh
|
|
168
|
-
(29 defect directories total)
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
<a id="defect-index"></a>
|
|
172
|
-
|
|
173
|
-
## Defect Index
|
|
174
|
-
|
|
175
|
-
<!-- GENERATED:defect-index:begin -->
|
|
176
|
-
31 defects across 13 categories.
|
|
177
|
-
|
|
178
|
-
### CF -- Config & Doctor
|
|
179
|
-
|
|
180
|
-
| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |
|
|
181
|
-
|----|-------------|----------|--------------|
|
|
182
|
-
| [CF‑001](patch/010-CF-001-doctor-yaml/) | Doctor ignores YAML config files | Low | [#1141](https://github.com/ruvnet/claude-flow/issues/1141) |
|
|
183
|
-
| [CF‑002](patch/020-CF-002-config-export-yaml/) | Config export shows hardcoded defaults | Medium | [#1142](https://github.com/ruvnet/claude-flow/issues/1142) |
|
|
86
|
+
## Target Behavior
|
|
184
87
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
|
188
|
-
|
|
189
|
-
|
|
|
190
|
-
|
|
|
191
|
-
| [DM‑003](patch/050-DM-003-macos-freemem/) | macOS freemem() always ~0% — workers blocked | Critical | [#1077](https://github.com/ruvnet/claude-flow/issues/1077) |
|
|
192
|
-
| [DM‑004](patch/060-DM-004-preload-worker-stub/) | Preload worker stub + missing from defaults | Enhancement | [#1139](https://github.com/ruvnet/claude-flow/issues/1139) |
|
|
193
|
-
| [DM‑005](patch/070-DM-005-consolidation-worker-stub/) | Consolidation worker stub (no decay/rebuild) | Enhancement | [#1140](https://github.com/ruvnet/claude-flow/issues/1140) |
|
|
194
|
-
| [DM‑006](patch/300-DM-006-log-rotation/) | No log rotation — headless execution logs grow unbounded | Medium | [#1114](https://github.com/ruvnet/claude-flow/issues/1114) |
|
|
195
|
-
|
|
196
|
-
### EM -- Embeddings & HNSW
|
|
197
|
-
|
|
198
|
-
| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |
|
|
199
|
-
|----|-------------|----------|--------------|
|
|
200
|
-
| [EM‑001](patch/080-EM-001-embedding-ignores-config/) | Embedding system ignores project config (model + HNSW dims) | High | [#1143](https://github.com/ruvnet/claude-flow/issues/1143) |
|
|
201
|
-
| [EM‑002](patch/090-EM-002-transformers-cache-eacces/) | @xenova/transformers cache EACCES | Medium | [#1144](https://github.com/ruvnet/claude-flow/issues/1144) |
|
|
202
|
-
|
|
203
|
-
### GV -- Ghost Vectors
|
|
204
|
-
|
|
205
|
-
| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |
|
|
206
|
-
|----|-------------|----------|--------------|
|
|
207
|
-
| [GV‑001](patch/100-GV-001-hnsw-ghost-vectors/) | HNSW ghost vectors persist after memory delete | Medium | [#1122](https://github.com/ruvnet/claude-flow/issues/1122) |
|
|
208
|
-
|
|
209
|
-
### HK -- Hooks
|
|
210
|
-
|
|
211
|
-
| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |
|
|
212
|
-
|----|-------------|----------|--------------|
|
|
213
|
-
| [HK‑001](patch/110-HK-001-post-edit-file-path/) | post-edit hook records file_path as "unknown" | Medium | [#1155](https://github.com/ruvnet/claude-flow/issues/1155) |
|
|
214
|
-
| [HK‑002](patch/120-HK-002-hooks-tools-stub/) | MCP hook handlers are stubs that don't persist data | High | [#1058](https://github.com/ruvnet/claude-flow/issues/1058) |
|
|
215
|
-
| [HK‑003](patch/130-HK-003-metrics-hardcoded/) | hooks_metrics MCP handler returns hardcoded fake data | High | [#1158](https://github.com/ruvnet/claude-flow/issues/1158) |
|
|
216
|
-
|
|
217
|
-
### HW -- Headless Worker
|
|
218
|
-
|
|
219
|
-
| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |
|
|
220
|
-
|----|-------------|----------|--------------|
|
|
221
|
-
| [HW‑001](patch/140-HW-001-stdin-hang/) | Headless workers hang — stdin pipe never closed | Critical | [#1111](https://github.com/ruvnet/claude-flow/issues/1111) |
|
|
222
|
-
| [HW‑002](patch/150-HW-002-failures-swallowed/) | Headless failures silently swallowed as success | High | [#1112](https://github.com/ruvnet/claude-flow/issues/1112) |
|
|
223
|
-
| [HW‑003](patch/160-HW-003-aggressive-intervals/) | Worker scheduling intervals too aggressive | High | [#1113](https://github.com/ruvnet/claude-flow/issues/1113) |
|
|
224
|
-
| [HW‑004](patch/310-HW-004-runwithtimeout-orphan/) | runWithTimeout rejects but does not kill child process | Medium | [#1117](https://github.com/ruvnet/claude-flow/issues/1117) |
|
|
225
|
-
|
|
226
|
-
### IN -- Intelligence
|
|
227
|
-
|
|
228
|
-
| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |
|
|
229
|
-
|----|-------------|----------|--------------|
|
|
230
|
-
| [IN‑001](patch/170-IN-001-intelligence-stub/) | intelligence.cjs is a stub that doesn't actually learn | Critical | [#1154](https://github.com/ruvnet/claude-flow/issues/1154) |
|
|
231
|
-
|
|
232
|
-
### MM -- Memory Management
|
|
233
|
-
|
|
234
|
-
| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |
|
|
235
|
-
|----|-------------|----------|--------------|
|
|
236
|
-
| [MM‑001](patch/180-MM-001-memory-persist-path/) | Remove dead persistPath config option | Low | [#1152](https://github.com/ruvnet/claude-flow/issues/1152) |
|
|
237
|
-
|
|
238
|
-
### NS -- Memory Namespace
|
|
239
|
-
|
|
240
|
-
| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |
|
|
241
|
-
|----|-------------|----------|--------------|
|
|
242
|
-
| [NS‑001](patch/190-NS-001-discovery-default-namespace/) | Discovery ops default to wrong namespace | Critical | [#1123](https://github.com/ruvnet/claude-flow/issues/1123) |
|
|
243
|
-
| [NS‑002](patch/200-NS-002-targeted-require-namespace/) | Store/delete/retrieve fall back to 'default' + accept 'all' | Critical | [#581](https://github.com/ruvnet/claude-flow/issues/581) |
|
|
244
|
-
| [NS‑003](patch/210-NS-003-namespace-typo-pattern/) | Namespace typo 'pattern' vs 'patterns' | Medium | [#1136](https://github.com/ruvnet/claude-flow/issues/1136) |
|
|
245
|
-
|
|
246
|
-
### RS -- ruv-swarm
|
|
247
|
-
|
|
248
|
-
| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |
|
|
249
|
-
|----|-------------|----------|--------------|
|
|
250
|
-
| [RS‑001](patch/220-RS-001-better-sqlite3-node24/) | ruv-swarm MCP fails on Node 24 — better-sqlite3 missing native bindings | Critical | [ruv-FANN#185](https://github.com/ruvnet/ruv-FANN/issues/185) |
|
|
251
|
-
|
|
252
|
-
### RV -- RuVector Intelligence
|
|
253
|
-
|
|
254
|
-
| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |
|
|
255
|
-
|----|-------------|----------|--------------|
|
|
256
|
-
| [RV‑001](patch/230-RV-001-force-learn-tick/) | force-learn command calls intel.tick() which doesn't exist | Medium | [#1156](https://github.com/ruvnet/claude-flow/issues/1156) |
|
|
257
|
-
| [RV‑002](patch/240-RV-002-trajectory-load/) | activeTrajectories not loaded from saved file | High | [#1157](https://github.com/ruvnet/claude-flow/issues/1157) |
|
|
258
|
-
| [RV‑003](patch/250-RV-003-trajectory-stats-sync/) | trajectory-end does not update stats counters | Medium | [ruv-FANN#186](https://github.com/ruvnet/ruv-FANN/issues/186) |
|
|
259
|
-
|
|
260
|
-
### SG -- Settings Generator
|
|
261
|
-
|
|
262
|
-
| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |
|
|
263
|
-
|----|-------------|----------|--------------|
|
|
264
|
-
| [SG‑001](patch/260-SG-001-init-settings/) | Init generates invalid settings | High | [#1150](https://github.com/ruvnet/claude-flow/issues/1150) |
|
|
265
|
-
| [SG‑003](patch/270-SG-003-init-helpers-all-paths/) | Init missing helpers for --dual, --minimal, hooks, and upgrade paths | Critical | [#1169](https://github.com/ruvnet/claude-flow/issues/1169) |
|
|
266
|
-
|
|
267
|
-
### UI -- Display & Cosmetic
|
|
268
|
-
|
|
269
|
-
| ID | Description <img width="500" height="1" /> | Severity | GitHub Issue |
|
|
270
|
-
|----|-------------|----------|--------------|
|
|
271
|
-
| [UI‑001](patch/280-UI-001-intelligence-stats-crash/) | intelligence stats crashes on .toFixed() | Critical | [#1145](https://github.com/ruvnet/claude-flow/issues/1145) |
|
|
272
|
-
| [UI‑002](patch/290-UI-002-neural-status-not-loaded/) | neural status shows "Not loaded" | Low | [#1146](https://github.com/ruvnet/claude-flow/issues/1146) |
|
|
273
|
-
<!-- GENERATED:defect-index:end -->
|
|
274
|
-
|
|
275
|
-
<a id="init-script-patches"></a>
|
|
276
|
-
|
|
277
|
-
## Init-Script Patches (Local Project Action Required)
|
|
278
|
-
|
|
279
|
-
Five patches target the **init/generator scripts** (`executor.js`, `settings-generator.js`, `helpers-generator.js`). These fix the code that *generates* your `.claude/` project files -- but applying patches does **not** update files already generated in your project. You must take one additional step.
|
|
280
|
-
|
|
281
|
-
### Affected Defects
|
|
282
|
-
|
|
283
|
-
| ID | Generator patched | Local file affected | Problem if not refreshed |
|
|
284
|
-
|----|-------------------|---------------------|--------------------------|
|
|
285
|
-
| IN-001 | `init/executor.js` | `.claude/helpers/intelligence.cjs` | 197-line stub: no PageRank, no graph, `feedback()` is a no-op, no learning |
|
|
286
|
-
| HK-001 | `init/helpers-generator.js` | `.claude/helpers/hook-handler.cjs` | Reads env vars instead of stdin JSON; post-edit logs `file: "unknown"` |
|
|
287
|
-
| SG-001 | `init/settings-generator.js` | `.claude/settings.json` | May contain invalid hook events, broad permissions, relative paths |
|
|
288
|
-
| SG-002 | `init/executor.js` | `.claude/helpers/*.js` / `*.cjs` | Missing .js/.cjs compat copies; `hook-handler.cjs` require() calls fail silently |
|
|
289
|
-
| MM-001 | `init/executor.js` | `.claude-flow/config.yaml` | Misleading `persistPath` setting that nothing reads |
|
|
290
|
-
|
|
291
|
-
### How to Fix
|
|
292
|
-
|
|
293
|
-
**Option A: Run `repair`** (recommended)
|
|
294
|
-
|
|
295
|
-
```bash
|
|
296
|
-
npx --yes @sparkleideas/claude-flow-patch --global
|
|
297
|
-
npx --yes @sparkleideas/claude-flow-patch repair --target .
|
|
298
|
-
npx --yes @sparkleideas/claude-flow-patch apply SG-002 # apply a single patch
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
This copies patched helper files into your project and creates any missing .js/.cjs compat copies.
|
|
88
|
+
| Flag | Patched location |
|
|
89
|
+
|---|---|
|
|
90
|
+
| (none) | Global npx cache (default) |
|
|
91
|
+
| `--global` | `~/.npm/_npx/*/node_modules/...` |
|
|
92
|
+
| `--target <dir>` | `<dir>/node_modules/...` |
|
|
93
|
+
| `--global --target <dir>` | Both locations |
|
|
302
94
|
|
|
303
|
-
|
|
95
|
+
Use `--target` when your project has a local `@claude-flow/cli` install.
|
|
304
96
|
|
|
305
|
-
|
|
306
|
-
npx --yes @sparkleideas/claude-flow-patch --global
|
|
307
|
-
SRC=$(find ~/.npm/_npx -path '*/@claude-flow/cli/.claude/helpers' -type d 2>/dev/null | head -1)
|
|
308
|
-
for f in intelligence.cjs hook-handler.cjs session.js learning-service.mjs metrics-db.mjs statusline.cjs; do
|
|
309
|
-
[ -f "$SRC/$f" ] && cp "$SRC/$f" .claude/helpers/ && echo "Copied: $f"
|
|
310
|
-
done
|
|
311
|
-
```
|
|
97
|
+
## Why `repair` Exists
|
|
312
98
|
|
|
313
|
-
|
|
99
|
+
Some fixes patch generator code (`init/executor.js`, `init/settings-generator.js`, `init/helpers-generator.js`). Those fixes affect future generated files only.
|
|
314
100
|
|
|
315
|
-
|
|
316
|
-
npx --yes @sparkleideas/claude-flow-patch --global
|
|
317
|
-
npx @claude-flow/cli@latest init upgrade --force
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
Caution: Option C may overwrite other customizations in `.claude/`.
|
|
101
|
+
If your repo was initialized before patching, existing `.claude/helpers/*` can remain stale. `repair` copies patched helper files into the target repo and creates .js/.cjs compatibility copies where needed.
|
|
321
102
|
|
|
322
|
-
|
|
103
|
+
## How Patching Works
|
|
323
104
|
|
|
324
|
-
|
|
105
|
+
1. Locate CLI/package targets.
|
|
106
|
+
2. Concatenate shared helpers (`lib/common.py`) with each defect `fix.py`.
|
|
107
|
+
3. Apply string-based replacements with idempotency guards.
|
|
108
|
+
4. Validate with sentinel checks.
|
|
325
109
|
|
|
326
|
-
|
|
110
|
+
Design guarantees:
|
|
327
111
|
|
|
328
|
-
|
|
112
|
+
- **Idempotent**: safe to re-run
|
|
113
|
+
- **Non-destructive**: modifies local cache/install only
|
|
114
|
+
- **Ordered**: dependent patches applied in sequence (e.g. NS-001 -> NS-002 -> NS-003)
|
|
115
|
+
- **Platform-aware**: macOS-specific patches auto-skip on Linux
|
|
329
116
|
|
|
330
117
|
## Compatibility
|
|
331
118
|
|
|
332
|
-
- Tested
|
|
333
|
-
-
|
|
334
|
-
-
|
|
335
|
-
|
|
336
|
-
<a id="links"></a>
|
|
119
|
+
- Tested with `@claude-flow/cli@3.1.0-alpha.41`
|
|
120
|
+
- Tested with `ruv-swarm@1.0.20`
|
|
121
|
+
- Requires Bash + Python 3.6+
|
|
122
|
+
- Linux and macOS supported
|
|
337
123
|
|
|
338
124
|
## Links
|
|
339
125
|
|
|
340
126
|
- Homepage: https://sparklingideas.co.uk/claude-flow/patch
|
|
341
|
-
- Package: https://www.npmjs.com/package/@sparkleideas/claude-flow-patch
|
|
342
127
|
- GitHub: https://github.com/sparkling/claude-flow-patch
|
|
343
128
|
- Issues: https://github.com/sparkling/claude-flow-patch/issues
|
|
344
|
-
|
|
345
|
-
## License
|
|
346
|
-
|
|
347
|
-
MIT
|
package/check-patches.sh
CHANGED
|
@@ -165,10 +165,14 @@ if [ -x "$SCRIPT_DIR/patch-all.sh" ]; then
|
|
|
165
165
|
if [[ -n "$TARGET_DIR" ]]; then REAPPLY_ARGS+=(--target "$TARGET_DIR"); fi
|
|
166
166
|
bash "$SCRIPT_DIR/patch-all.sh" "${REAPPLY_ARGS[@]}"
|
|
167
167
|
echo ""
|
|
168
|
-
echo "[PATCHES] Auto-reapplied.
|
|
168
|
+
echo "[PATCHES] Auto-reapplied. Stopping existing daemons..."
|
|
169
169
|
npx @claude-flow/cli@latest daemon stop 2>/dev/null
|
|
170
|
+
# Fallback: kill by PID file if daemon stop missed an orphan (project-scoped, not global)
|
|
171
|
+
_pid=$(cat .claude-flow/daemon.pid 2>/dev/null)
|
|
172
|
+
if [ -n "$_pid" ]; then kill "$_pid" 2>/dev/null || true; rm -f .claude-flow/daemon.pid; fi
|
|
173
|
+
sleep 1
|
|
170
174
|
npx @claude-flow/cli@latest daemon start 2>/dev/null
|
|
171
|
-
echo "[PATCHES] Daemon restarted
|
|
175
|
+
echo "[PATCHES] Daemon restarted in background (PID: $(cat .claude-flow/daemon.pid 2>/dev/null || echo 'unknown'))"
|
|
172
176
|
echo ""
|
|
173
177
|
else
|
|
174
178
|
echo "[PATCHES] ERROR: patch-all.sh not found at $SCRIPT_DIR"
|
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sparkleideas/claude-flow-patch",
|
|
3
|
-
"version": "3.1.0-alpha.44.patch.
|
|
3
|
+
"version": "3.1.0-alpha.44.patch.6",
|
|
4
4
|
"description": "Patch toolkit for @claude-flow/cli init/runtime defects with verify and post-init repair commands",
|
|
5
5
|
"scripts": {
|
|
6
|
+
"preflight": "node scripts/preflight.mjs",
|
|
7
|
+
"preflight:check": "node scripts/preflight.mjs --check",
|
|
8
|
+
"prepublishOnly": "npm run preflight && npm test",
|
|
6
9
|
"test": "node --test tests/*.test.mjs",
|
|
7
10
|
"package": "bash npm/package.sh",
|
|
8
11
|
"package:dry": "bash npm/package.sh --dry-run",
|
|
9
12
|
"publish:npm": "bash npm/publish.sh",
|
|
10
13
|
"publish:dry": "bash npm/publish.sh --dry-run",
|
|
11
|
-
"update-docs": "node scripts/update-docs.mjs",
|
|
12
|
-
"update-docs:check": "node scripts/update-docs.mjs --check",
|
|
13
14
|
"upstream-log": "node scripts/upstream-log.mjs",
|
|
14
15
|
"guidance:analyze": "guidance analyze",
|
|
15
16
|
"guidance:optimize": "guidance autopilot --once --apply --source manual",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# HK-004: hooks_session-start ignores daemon.autoStart from settings.json
|
|
2
|
+
**Severity**: High
|
|
3
|
+
**GitHub**: [#1175](https://github.com/ruvnet/claude-flow/issues/1175)
|
|
4
|
+
## Root Cause
|
|
5
|
+
`hooks_session-start` handler in `hooks-tools.js` (line ~1216) determines daemon auto-start solely from the MCP call parameter: `const shouldStartDaemon = params.startDaemon !== false;`. It never reads `claudeFlow.daemon.autoStart` from `.claude/settings.json`. Setting `autoStart: false` in settings.json has no effect — the daemon always starts on session-start.
|
|
6
|
+
## Fix
|
|
7
|
+
Wrap the `shouldStartDaemon` assignment in an IIFE that first checks the MCP parameter, then reads settings.json. If `claudeFlow.daemon.autoStart === false`, returns false. Falls back to true on any read/parse error.
|
|
8
|
+
## Files Patched
|
|
9
|
+
- mcp-tools/hooks-tools.js
|
|
10
|
+
## Ops
|
|
11
|
+
1 op in fix.py
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# HK-004: hooks_session-start ignores daemon.autoStart from settings.json
|
|
2
|
+
# GitHub: #1175
|
|
3
|
+
patch("HK-004: respect daemon autoStart setting",
|
|
4
|
+
MCP_HOOKS,
|
|
5
|
+
" const shouldStartDaemon = params.startDaemon !== false;",
|
|
6
|
+
""" const shouldStartDaemon = (() => {
|
|
7
|
+
if (params.startDaemon === false) return false;
|
|
8
|
+
try {
|
|
9
|
+
const sp = join(process.cwd(), '.claude', 'settings.json');
|
|
10
|
+
const s = JSON.parse(readFileSync(sp, 'utf-8'));
|
|
11
|
+
if (s?.claudeFlow?.daemon?.autoStart === false) return false;
|
|
12
|
+
} catch { /* no settings or unreadable — default to true */ }
|
|
13
|
+
return true;
|
|
14
|
+
})();""")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
grep "claudeFlow?.daemon?.autoStart" mcp-tools/hooks-tools.js
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# HW-003: Worker scheduling intervals too aggressive
|
|
1
|
+
# HW-003: Worker scheduling intervals too aggressive + settings ignored
|
|
2
2
|
**Severity**: High
|
|
3
3
|
**GitHub**: [#1113](https://github.com/ruvnet/claude-flow/issues/1113)
|
|
4
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.
|
|
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. Additionally, `daemon.schedules` from `.claude/settings.json` is never read — user-configured intervals are completely ignored.
|
|
6
6
|
## Fix
|
|
7
|
-
Align intervals to ADR-020: audit 30m, optimize 60m, testgaps 60m.
|
|
7
|
+
(A) Align hardcoded intervals to ADR-020: audit 30m, optimize 60m, testgaps 60m. (B) After setting default workers, read `claudeFlow.daemon.schedules` from `.claude/settings.json` and merge user-configured intervals/enabled flags into matching workers. Supports string formats ("1h", "30m", "10s") and raw milliseconds.
|
|
8
8
|
## Files Patched
|
|
9
9
|
- services/worker-daemon.js
|
|
10
10
|
## Ops
|
|
11
|
-
|
|
11
|
+
4 ops in fix.py
|
|
@@ -14,3 +14,39 @@ patch("3: testgaps 60m",
|
|
|
14
14
|
WD,
|
|
15
15
|
"type: 'testgaps', intervalMs: 20 * 60 * 1000",
|
|
16
16
|
"type: 'testgaps', intervalMs: 60 * 60 * 1000")
|
|
17
|
+
|
|
18
|
+
# HW-003 extension: Read daemon.schedules from .claude/settings.json
|
|
19
|
+
# and merge user-configured intervals into worker defaults
|
|
20
|
+
patch("3: settings-driven intervals",
|
|
21
|
+
WD,
|
|
22
|
+
" workers: config?.workers ?? DEFAULT_WORKERS,",
|
|
23
|
+
""" workers: (() => {
|
|
24
|
+
const base = config?.workers ?? DEFAULT_WORKERS;
|
|
25
|
+
try {
|
|
26
|
+
const sp = join(projectRoot, '.claude', 'settings.json');
|
|
27
|
+
const s = JSON.parse(readFileSync(sp, 'utf-8'));
|
|
28
|
+
const schedules = s?.claudeFlow?.daemon?.schedules;
|
|
29
|
+
if (!schedules || typeof schedules !== 'object') return base;
|
|
30
|
+
const parseInterval = (v) => {
|
|
31
|
+
if (typeof v === 'number') return v;
|
|
32
|
+
if (typeof v !== 'string') return null;
|
|
33
|
+
const m = v.match(/^(\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h)$/i);
|
|
34
|
+
if (!m) return null;
|
|
35
|
+
const n = parseFloat(m[1]);
|
|
36
|
+
switch (m[2].toLowerCase()) {
|
|
37
|
+
case 'ms': return n;
|
|
38
|
+
case 's': return n * 1000;
|
|
39
|
+
case 'm': return n * 60 * 1000;
|
|
40
|
+
case 'h': return n * 3600 * 1000;
|
|
41
|
+
default: return null;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
return base.map(w => {
|
|
45
|
+
const sched = schedules[w.type];
|
|
46
|
+
if (!sched) return w;
|
|
47
|
+
const iv = parseInterval(sched.interval ?? sched.intervalMs);
|
|
48
|
+
const en = typeof sched.enabled === 'boolean' ? sched.enabled : w.enabled;
|
|
49
|
+
return { ...w, ...(iv !== null ? { intervalMs: iv } : {}), enabled: en };
|
|
50
|
+
});
|
|
51
|
+
} catch { return base; }
|
|
52
|
+
})(),""")
|
|
@@ -10,15 +10,12 @@
|
|
|
10
10
|
# 2 ops: upgrade path (line ~398) + writeHelpers path (line ~943)
|
|
11
11
|
|
|
12
12
|
# Op 1: Upgrade path — when findSourceHelpersDir() returns null
|
|
13
|
+
# old/new strings stop BEFORE generatedCritical to avoid overlap with SG-003j
|
|
13
14
|
patch("IN-001a: upgrade fallback reads real intelligence.cjs",
|
|
14
15
|
EXECUTOR,
|
|
15
16
|
""" else {
|
|
16
17
|
// 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
|
-
};""",
|
|
18
|
+
const generatedCritical = {""",
|
|
22
19
|
""" else {
|
|
23
20
|
// Source not found (npx with broken paths) — use generated fallbacks
|
|
24
21
|
// IN-001: Try reading real intelligence.cjs from package before using stub
|
|
@@ -29,11 +26,7 @@ patch("IN-001a: upgrade fallback reads real intelligence.cjs",
|
|
|
29
26
|
intelligenceContent = fs.readFileSync(realPath, 'utf-8');
|
|
30
27
|
}
|
|
31
28
|
} catch { /* use stub */ }
|
|
32
|
-
const generatedCritical = {
|
|
33
|
-
'hook-handler.cjs': generateHookHandler(),
|
|
34
|
-
'intelligence.cjs': intelligenceContent,
|
|
35
|
-
'auto-memory-hook.mjs': generateAutoMemoryHook(),
|
|
36
|
-
};""")
|
|
29
|
+
const generatedCritical = {""")
|
|
37
30
|
|
|
38
31
|
# Op 2: writeHelpers path — fresh init when source dir not found
|
|
39
32
|
patch("IN-001b: writeHelpers fallback reads real intelligence.cjs",
|
|
@@ -122,11 +122,12 @@ patch_all("SG-003i: source hook-handler requires memory.cjs",
|
|
|
122
122
|
|
|
123
123
|
# Op 6: Fix executeUpgrade() fallback — generatedCritical missing router/session/memory
|
|
124
124
|
# When source helpers aren't found, only 3 files were generated but hook-handler.cjs needs 6
|
|
125
|
+
# Also replaces generateIntelligenceStub() → intelligenceContent (set by IN-001a above)
|
|
125
126
|
patch("SG-003j: upgrade fallback generates router/session/memory",
|
|
126
127
|
EXECUTOR,
|
|
127
128
|
""" const generatedCritical = {
|
|
128
129
|
'hook-handler.cjs': generateHookHandler(),
|
|
129
|
-
'intelligence.cjs':
|
|
130
|
+
'intelligence.cjs': generateIntelligenceStub(),
|
|
130
131
|
'auto-memory-hook.mjs': generateAutoMemoryHook(),
|
|
131
132
|
};""",
|
|
132
133
|
""" const generatedCritical = {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
# DM-006: No log rotation —
|
|
1
|
+
# DM-006: No log rotation — logs grow unbounded
|
|
2
2
|
**Severity**: Medium
|
|
3
3
|
**GitHub**: [#1114](https://github.com/ruvnet/claude-flow/issues/1114)
|
|
4
4
|
## Root Cause
|
|
5
|
-
`logExecution()` in `headless-worker-executor.js` creates 2-3 log files per worker run (~75 KB each) but has zero cleanup. No rotation, no max file count, no TTL. At current daemon intervals this accumulates ~23 MB/day, ~702 MB/month.
|
|
5
|
+
(Headless) `logExecution()` in `headless-worker-executor.js` creates 2-3 log files per worker run (~75 KB each) but has zero cleanup. No rotation, no max file count, no TTL. At current daemon intervals this accumulates ~23 MB/day, ~702 MB/month. (Main) `startBackgroundDaemon()` in `daemon.js` opens `daemon.log` in append mode and never truncates. A single long-running daemon can grow daemon.log to 100+ GB.
|
|
6
6
|
## Fix
|
|
7
|
-
(A) Add `unlinkSync` and `statSync` to the ESM import. (B) Call `cleanupOldLogs()` from `ensureLogDir()` so cleanup runs on each execution cycle. (C) Add `cleanupOldLogs()` method: removes `.log` files older than 7 days or beyond a 500-file cap, keeping newest files.
|
|
7
|
+
(A) Add `unlinkSync` and `statSync` to the headless executor ESM import. (B) Call `cleanupOldLogs()` from `ensureLogDir()` so cleanup runs on each headless execution cycle. (C) Add `cleanupOldLogs()` method: removes `.log` files older than 7 days or beyond a 500-file cap, keeping newest files. (D) In `daemon.js`, before opening `daemon.log` for append, check its size with `fs.statSync()` and rotate to `daemon.log.1` if > 50MB.
|
|
8
8
|
## Files Patched
|
|
9
9
|
- services/headless-worker-executor.js
|
|
10
|
+
- commands/daemon.js
|
|
10
11
|
## Ops
|
|
11
|
-
|
|
12
|
+
4 ops in fix.py
|
|
@@ -56,3 +56,17 @@ patch("DM-006c: add cleanupOldLogs method",
|
|
|
56
56
|
catch { /* ignore cleanup errors */ }
|
|
57
57
|
}
|
|
58
58
|
logExecution(executionId, type, content) {""")
|
|
59
|
+
|
|
60
|
+
# DM-006 extension: Main daemon.log rotation in daemon.js
|
|
61
|
+
# Before opening daemon.log for append, check size and rotate if > 50MB
|
|
62
|
+
patch("DM-006d: main daemon.log rotation",
|
|
63
|
+
DJ,
|
|
64
|
+
" const logFile = join(logsDir, 'daemon.log');",
|
|
65
|
+
""" const logFile = join(logsDir, 'daemon.log');
|
|
66
|
+
// Rotate main daemon.log if > 50MB
|
|
67
|
+
try {
|
|
68
|
+
const logStat = fs.statSync(logFile);
|
|
69
|
+
if (logStat.size > 50 * 1024 * 1024) {
|
|
70
|
+
fs.renameSync(logFile, logFile + '.1');
|
|
71
|
+
}
|
|
72
|
+
} catch { /* file doesn't exist yet or stat failed — ignore */ }""")
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// scripts/
|
|
3
|
-
//
|
|
2
|
+
// scripts/preflight.mjs — Pre-commit/pre-publish consistency check.
|
|
3
|
+
// Syncs: doc tables, defect counts, version strings across all files.
|
|
4
|
+
// Source of truth: package.json (version), npm/config.json (targets), patch/*/ (defects).
|
|
4
5
|
//
|
|
5
|
-
// Usage: node scripts/
|
|
6
|
-
// --check Exit 1 if
|
|
6
|
+
// Usage: node scripts/preflight.mjs [--check]
|
|
7
|
+
// --check Exit 1 if anything is out of date (for hooks/CI), don't write.
|
|
7
8
|
|
|
8
9
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
9
10
|
import { resolve, dirname } from 'node:path';
|
|
@@ -17,6 +18,14 @@ const checkOnly = process.argv.includes('--check');
|
|
|
17
18
|
const data = discover();
|
|
18
19
|
const { patches, categories, stats } = data;
|
|
19
20
|
|
|
21
|
+
// ── Sources of truth ──
|
|
22
|
+
|
|
23
|
+
const pkgJson = JSON.parse(readFileSync(resolve(ROOT, 'package.json'), 'utf-8'));
|
|
24
|
+
const configJson = JSON.parse(readFileSync(resolve(ROOT, 'npm', 'config.json'), 'utf-8'));
|
|
25
|
+
const pkgVersion = pkgJson.version;
|
|
26
|
+
const cliTarget = configJson.targets['@claude-flow/cli'];
|
|
27
|
+
const swarmTarget = configJson.targets['ruv-swarm'];
|
|
28
|
+
|
|
20
29
|
// ── Helpers ──
|
|
21
30
|
|
|
22
31
|
/** Group patches by prefix, preserving sort order. */
|
|
@@ -57,6 +66,20 @@ function replaceMarkerSection(filePath, markerName, newContent) {
|
|
|
57
66
|
return true;
|
|
58
67
|
}
|
|
59
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Replace all occurrences of a version string in a file.
|
|
71
|
+
* Returns true if content changed.
|
|
72
|
+
*/
|
|
73
|
+
function syncVersionInFile(filePath, oldVersion, newVersion, label) {
|
|
74
|
+
if (oldVersion === newVersion) return false;
|
|
75
|
+
const text = readFileSync(filePath, 'utf-8');
|
|
76
|
+
if (!text.includes(oldVersion)) return false;
|
|
77
|
+
const updated = text.replaceAll(oldVersion, newVersion);
|
|
78
|
+
if (updated === text) return false;
|
|
79
|
+
if (!checkOnly) writeFileSync(filePath, updated);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
60
83
|
// ── Generate README.md defect index ──
|
|
61
84
|
|
|
62
85
|
function generateReadmeIndex() {
|
|
@@ -142,13 +165,21 @@ function updateNpmReadme() {
|
|
|
142
165
|
);
|
|
143
166
|
}
|
|
144
167
|
|
|
145
|
-
// ──
|
|
168
|
+
// ── Sync npm/config.json (version + defect counts) ──
|
|
146
169
|
|
|
147
170
|
function updateNpmConfig() {
|
|
148
171
|
const filePath = resolve(ROOT, 'npm', 'config.json');
|
|
149
172
|
const config = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
150
173
|
|
|
151
174
|
let changed = false;
|
|
175
|
+
|
|
176
|
+
// Sync version.current from package.json
|
|
177
|
+
if (config.version?.current !== pkgVersion) {
|
|
178
|
+
config.version.current = pkgVersion;
|
|
179
|
+
changed = true;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Sync defect counts from discovery
|
|
152
183
|
if (config.defects?.total !== stats.total) {
|
|
153
184
|
config.defects.total = stats.total;
|
|
154
185
|
changed = true;
|
|
@@ -168,41 +199,51 @@ function updateNpmConfig() {
|
|
|
168
199
|
|
|
169
200
|
let anyChanged = false;
|
|
170
201
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
'defect-index',
|
|
174
|
-
generateReadmeIndex()
|
|
175
|
-
);
|
|
176
|
-
if (readmeChanged) {
|
|
202
|
+
function report(changed, label) {
|
|
203
|
+
if (!changed) return;
|
|
177
204
|
anyChanged = true;
|
|
178
|
-
console.log(checkOnly ?
|
|
205
|
+
console.log(checkOnly ? `STALE: ${label}` : `Updated: ${label}`);
|
|
179
206
|
}
|
|
180
207
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
'defect-
|
|
184
|
-
|
|
208
|
+
// 1. Doc tables (marker-based sections)
|
|
209
|
+
report(
|
|
210
|
+
replaceMarkerSection(resolve(ROOT, 'README.md'), 'defect-index', generateReadmeIndex()),
|
|
211
|
+
'README.md (defect index)'
|
|
185
212
|
);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
213
|
+
report(
|
|
214
|
+
replaceMarkerSection(resolve(ROOT, 'CLAUDE.md'), 'defect-tables', generateClaudeTables()),
|
|
215
|
+
'CLAUDE.md (defect tables)'
|
|
216
|
+
);
|
|
217
|
+
report(updateNpmReadme(), 'npm/README.md (defect list)');
|
|
218
|
+
|
|
219
|
+
// 2. Config sync (version + counts)
|
|
220
|
+
report(updateNpmConfig(), 'npm/config.json (version/counts)');
|
|
221
|
+
|
|
222
|
+
// 3. Upstream baseline version in prose (sync from npm/config.json targets)
|
|
223
|
+
// Find any stale version strings and replace with current targets.
|
|
224
|
+
// We scan for the pattern v?X.Y.Z-alpha.N and replace if it doesn't match config.
|
|
225
|
+
const versionFiles = ['README.md', 'CLAUDE.md', 'npm/README.md', 'AGENTS.md'];
|
|
226
|
+
for (const file of versionFiles) {
|
|
227
|
+
const filePath = resolve(ROOT, file);
|
|
228
|
+
let text;
|
|
229
|
+
try { text = readFileSync(filePath, 'utf-8'); } catch { continue; }
|
|
230
|
+
|
|
231
|
+
let updated = text;
|
|
232
|
+
|
|
233
|
+
// Sync @claude-flow/cli version references
|
|
234
|
+
// Match patterns like **v3.1.0-alpha.NN** or `3.1.0-alpha.NN` or @3.1.0-alpha.NN
|
|
235
|
+
const cliRe = /(?<=[@`*v])3\.1\.0-alpha\.\d+/g;
|
|
236
|
+
updated = updated.replace(cliRe, cliTarget);
|
|
237
|
+
|
|
238
|
+
if (updated !== text) {
|
|
239
|
+
if (!checkOnly) writeFileSync(filePath, updated);
|
|
240
|
+
report(true, `${file} (upstream baseline)`);
|
|
241
|
+
}
|
|
201
242
|
}
|
|
202
243
|
|
|
203
244
|
if (!anyChanged) {
|
|
204
|
-
console.log('All
|
|
245
|
+
console.log('All files are up to date.');
|
|
205
246
|
} else if (checkOnly) {
|
|
206
|
-
console.log('\
|
|
247
|
+
console.log('\nFiles are out of date. Run: npm run preflight');
|
|
207
248
|
process.exit(1);
|
|
208
249
|
}
|