claude-flow 3.21.1 → 3.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.claude/helpers/.helpers-version +1 -0
  2. package/.claude/helpers/auto-memory-hook.mjs +59 -274
  3. package/.claude/helpers/helpers.manifest.json +12 -0
  4. package/.claude/helpers/hook-handler.cjs +132 -112
  5. package/.claude/helpers/intelligence.cjs +992 -196
  6. package/package.json +1 -1
  7. package/v3/@claude-flow/cli/dist/src/commands/daemon.js +23 -2
  8. package/v3/@claude-flow/cli/dist/src/commands/memory-backup.d.ts +11 -0
  9. package/v3/@claude-flow/cli/dist/src/commands/memory-backup.js +46 -0
  10. package/v3/@claude-flow/cli/dist/src/commands/memory-distill.d.ts +27 -0
  11. package/v3/@claude-flow/cli/dist/src/commands/memory-distill.js +374 -0
  12. package/v3/@claude-flow/cli/dist/src/commands/memory.js +5 -2
  13. package/v3/@claude-flow/cli/dist/src/index.d.ts +1 -1
  14. package/v3/@claude-flow/cli/dist/src/index.js +22 -1
  15. package/v3/@claude-flow/cli/dist/src/init/executor.js +20 -0
  16. package/v3/@claude-flow/cli/dist/src/init/helper-refresh.d.ts +19 -0
  17. package/v3/@claude-flow/cli/dist/src/init/helper-refresh.js +175 -0
  18. package/v3/@claude-flow/cli/dist/src/init/helper-signing.d.ts +30 -0
  19. package/v3/@claude-flow/cli/dist/src/init/helper-signing.js +60 -0
  20. package/v3/@claude-flow/cli/dist/src/init/helpers-generator.d.ts +16 -0
  21. package/v3/@claude-flow/cli/dist/src/init/helpers-generator.js +63 -6
  22. package/v3/@claude-flow/cli/dist/src/init/statusline-generator.js +18 -7
  23. package/v3/@claude-flow/cli/dist/src/mcp-client.js +13 -0
  24. package/v3/@claude-flow/cli/dist/src/mcp-tools/agenticow-speculate-tools.js +9 -2
  25. package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-intent-tools.d.ts +162 -0
  26. package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-intent-tools.js +548 -0
  27. package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-tools.d.ts +9 -1
  28. package/v3/@claude-flow/cli/dist/src/mcp-tools/browser-tools.js +4 -1
  29. package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +67 -47
  30. package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.d.ts +71 -0
  31. package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.js +330 -2
  32. package/v3/@claude-flow/cli/dist/src/services/distill-tuning.d.ts +111 -0
  33. package/v3/@claude-flow/cli/dist/src/services/distill-tuning.js +510 -0
  34. package/v3/@claude-flow/cli/dist/src/services/memory-backup.d.ts +24 -0
  35. package/v3/@claude-flow/cli/dist/src/services/memory-backup.js +94 -0
  36. package/v3/@claude-flow/cli/dist/src/services/memory-distillation.d.ts +41 -0
  37. package/v3/@claude-flow/cli/dist/src/services/memory-distillation.js +277 -0
  38. package/v3/@claude-flow/cli/dist/src/services/worker-daemon.d.ts +31 -2
  39. package/v3/@claude-flow/cli/dist/src/services/worker-daemon.js +159 -6
  40. package/v3/@claude-flow/cli/package.json +5 -2
@@ -6,7 +6,8 @@
6
6
  * - map: Codebase mapping (5 min interval)
7
7
  * - audit: Security analysis (10 min interval)
8
8
  * - optimize: Performance optimization (15 min interval)
9
- * - consolidate: Memory consolidation (30 min interval)
9
+ * - consolidate: Memory distillation memory_entries -> episodes/reasoning_patterns/
10
+ * causal_edges (30 min interval, ADR-174; RUFLO_DAEMON_NO_DISTILL=1 / --no-distill to skip)
10
11
  * - testgaps: Test coverage analysis (20 min interval)
11
12
  */
12
13
  import { EventEmitter } from 'events';
@@ -14,19 +15,48 @@ import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync, unl
14
15
  import { cpus } from 'os';
15
16
  import { join } from 'path';
16
17
  import { HeadlessWorkerExecutor, isHeadlessWorker, } from './headless-worker-executor.js';
18
+ // ADR-174 M3: the consolidate worker below drives the real DISTILL/CONSOLIDATE
19
+ // pass instead of writing a hardcoded { patternsConsolidated: 0 } stub. The
20
+ // service itself is owned/frozen elsewhere (memory-distillation.ts) — it is
21
+ // incremental (rowid cursor), non-destructive, transactional, and
22
+ // quick_check-gated, so it's safe to call unconditionally on every tick.
23
+ import { runDistillation, defaultMemoryDbPath } from './memory-distillation.js';
24
+ import { backupMemoryDb } from './memory-backup.js';
17
25
  // Default worker configurations with improved intervals (P0 fix: map 5min -> 15min)
18
26
  const DEFAULT_WORKERS = [
19
27
  { type: 'map', intervalMs: 15 * 60 * 1000, offsetMs: 0, priority: 'normal', description: 'Codebase mapping', enabled: true },
20
28
  { type: 'audit', intervalMs: 10 * 60 * 1000, offsetMs: 2 * 60 * 1000, priority: 'critical', description: 'Security analysis', enabled: true },
21
29
  { type: 'optimize', intervalMs: 15 * 60 * 1000, offsetMs: 4 * 60 * 1000, priority: 'high', description: 'Performance optimization', enabled: true },
22
- { type: 'consolidate', intervalMs: 30 * 60 * 1000, offsetMs: 6 * 60 * 1000, priority: 'low', description: 'Memory consolidation', enabled: true },
30
+ { type: 'consolidate', intervalMs: 30 * 60 * 1000, offsetMs: 6 * 60 * 1000, priority: 'low', description: 'Memory distillation (ADR-174)', enabled: true },
23
31
  { type: 'testgaps', intervalMs: 20 * 60 * 1000, offsetMs: 8 * 60 * 1000, priority: 'normal', description: 'Test coverage analysis', enabled: true },
32
+ { type: 'backup', intervalMs: 24 * 60 * 60 * 1000, offsetMs: 10 * 60 * 1000, priority: 'low', description: 'Nightly memory DB backup (WAL-safe, rotated)', enabled: true },
24
33
  { type: 'predict', intervalMs: 10 * 60 * 1000, offsetMs: 0, priority: 'low', description: 'Predictive preloading', enabled: false },
25
34
  { type: 'document', intervalMs: 60 * 60 * 1000, offsetMs: 0, priority: 'low', description: 'Auto-documentation', enabled: false },
26
35
  ];
27
36
  // Worker timeout — must exceed the longest per-worker headless timeout (15 min for audit/refactor).
28
37
  // Previously 5 min, which caused orphan processes when daemon timeout fired before executor timeout (#1117).
29
38
  const DEFAULT_WORKER_TIMEOUT_MS = 16 * 60 * 1000;
39
+ // ADR-174 M3: hard cap on rows the `consolidate` worker distills in a single
40
+ // tick. The distillation service is cursor-driven (per-namespace rowid) and
41
+ // batches in transactions of `batchSize`, so a capped `maxEntries` guarantees
42
+ // this worker returns well within DEFAULT_WORKER_TIMEOUT_MS even against a
43
+ // large backlog — the cursor just picks up where it left off next tick
44
+ // (every 30 min per DEFAULT_WORKERS), draining an arbitrarily large backlog
45
+ // over several ticks instead of blocking on one.
46
+ const CONSOLIDATE_MAX_ENTRIES_PER_TICK = 1000;
47
+ const CONSOLIDATE_BATCH_SIZE = 200;
48
+ // ADR-174 M5: platform-default distillation config, chosen by the M4 self-
49
+ // optimization grid-search (scripts/tune-distill.mjs) on the real ~7.9k-entry
50
+ // corpus. Winner: batchSize=200, dedupDistance=0.2 (held-out MRR@10 0.753 vs
51
+ // 0.749 baseline — measured on-par, not a large uplift; the payoff is the
52
+ // populated substrate + trainable model). Override per-run via `memory distill`.
53
+ const CONSOLIDATE_DEDUP_DISTANCE = 0.2;
54
+ // ADR-174 M3 opt-out: set to skip the real distillation pass entirely (e.g.
55
+ // constrained CI hosts, or a user who wants the daemon's other workers but
56
+ // not this one without touching persisted worker-enabled state). Mirrors the
57
+ // `--no-distill` flag on `daemon start` (see commands/daemon.ts), which sets
58
+ // this env var on the forked/foreground daemon process.
59
+ const NO_DISTILL_ENV = 'RUFLO_DAEMON_NO_DISTILL';
30
60
  // #2356 — Self-terminating lifecycle defaults. A background daemon with no
31
61
  // upper bound on its lifetime runs until the box reboots; in the field this
32
62
  // leaked tens of thousands of headless `claude --print` sweeps over many days
@@ -1130,6 +1160,8 @@ export class WorkerDaemon extends EventEmitter {
1130
1160
  return this.runOptimizeWorkerLocal();
1131
1161
  case 'consolidate':
1132
1162
  return this.runConsolidateWorker();
1163
+ case 'backup':
1164
+ return this.runBackupWorker();
1133
1165
  case 'testgaps':
1134
1166
  return this.runTestGapsWorkerLocal();
1135
1167
  case 'predict':
@@ -1268,22 +1300,143 @@ export class WorkerDaemon extends EventEmitter {
1268
1300
  writeFileSync(optimizeFile, JSON.stringify(perf, null, 2));
1269
1301
  return perf;
1270
1302
  }
1303
+ /**
1304
+ * ADR-174 M3: memory consolidation — runs the real DISTILL/CONSOLIDATE pass
1305
+ * (memory-distillation.ts) against `.swarm/memory.db`, turning raw
1306
+ * `memory_entries` into `episodes` / `reasoning_patterns` /
1307
+ * `pattern_embeddings` / `causal_edges`. Previously this wrote a hardcoded
1308
+ * `{ patternsConsolidated: 0 }` stub and touched no database — the root
1309
+ * cause of the intelligence tables staying empty.
1310
+ *
1311
+ * Kept as `runConsolidateWorker` / worker type `'consolidate'` for
1312
+ * back-compat with existing `-w consolidate` scripts and docs.
1313
+ *
1314
+ * Safety:
1315
+ * - Bounded via CONSOLIDATE_MAX_ENTRIES_PER_TICK so a large backlog can
1316
+ * never approach DEFAULT_WORKER_TIMEOUT_MS — the incremental cursor in
1317
+ * runDistillation() drains a bounded slice per tick and picks up where
1318
+ * it left off on the next scheduled run.
1319
+ * - runDistillation() never throws (it catches internally and returns
1320
+ * `{ skipped }` / `{ corrupt: true }`), but this worker still wraps the
1321
+ * call defensively — a background worker must never crash the daemon.
1322
+ */
1271
1323
  async runConsolidateWorker() {
1272
- // Memory consolidation - clean up old patterns
1273
1324
  const consolidateFile = join(this.projectRoot, '.claude-flow', 'metrics', 'consolidation.json');
1274
1325
  const metricsDir = join(this.projectRoot, '.claude-flow', 'metrics');
1275
1326
  if (!existsSync(metricsDir)) {
1276
1327
  mkdirSync(metricsDir, { recursive: true });
1277
1328
  }
1329
+ // Opt-out: RUFLO_DAEMON_NO_DISTILL=1 (or `daemon start --no-distill`)
1330
+ // skips the real distillation pass entirely without touching persisted
1331
+ // worker-enabled state (see also: `daemon enable -w consolidate --disable`,
1332
+ // which disables the worker's schedule altogether).
1333
+ if (process.env[NO_DISTILL_ENV] === '1') {
1334
+ const disabledResult = {
1335
+ timestamp: new Date().toISOString(),
1336
+ distillationEnabled: false,
1337
+ note: `Distillation disabled via ${NO_DISTILL_ENV}=1 / --no-distill`,
1338
+ patternsConsolidated: 0,
1339
+ memoryCleaned: 0,
1340
+ duplicatesRemoved: 0,
1341
+ };
1342
+ writeFileSync(consolidateFile, JSON.stringify(disabledResult, null, 2));
1343
+ return disabledResult;
1344
+ }
1345
+ let report;
1346
+ try {
1347
+ report = await runDistillation({
1348
+ dbPath: defaultMemoryDbPath(this.projectRoot),
1349
+ maxEntries: CONSOLIDATE_MAX_ENTRIES_PER_TICK,
1350
+ batchSize: CONSOLIDATE_BATCH_SIZE,
1351
+ dedupDistance: CONSOLIDATE_DEDUP_DISTANCE,
1352
+ });
1353
+ }
1354
+ catch (error) {
1355
+ // Defensive only — runDistillation() is internally try/catch'd and
1356
+ // should never reach here. A worker must never crash the daemon.
1357
+ const message = error instanceof Error ? error.message : String(error);
1358
+ this.log('warn', `Consolidate worker: distillation threw unexpectedly: ${message}`);
1359
+ const errorResult = {
1360
+ timestamp: new Date().toISOString(),
1361
+ distillationEnabled: true,
1362
+ error: message,
1363
+ patternsConsolidated: 0,
1364
+ memoryCleaned: 0,
1365
+ duplicatesRemoved: 0,
1366
+ };
1367
+ writeFileSync(consolidateFile, JSON.stringify(errorResult, null, 2));
1368
+ return errorResult;
1369
+ }
1370
+ if (report.corrupt) {
1371
+ this.log('warn', `Consolidate worker: memory DB reports corruption — ${report.skipped ?? 'skipped'}`);
1372
+ }
1373
+ else if (report.skipped) {
1374
+ this.log('info', `Consolidate worker: distillation skipped (${report.skipped})`);
1375
+ }
1278
1376
  const result = {
1279
1377
  timestamp: new Date().toISOString(),
1280
- patternsConsolidated: 0,
1281
- memoryCleaned: 0,
1282
- duplicatesRemoved: 0,
1378
+ distillationEnabled: true,
1379
+ // Mapping onto the pre-existing metrics shape (ADR-174 M3):
1380
+ patternsConsolidated: report.patterns,
1381
+ // rows drained from the incremental cursor this tick — distillation is
1382
+ // non-destructive (never mutates/deletes memory_entries), so "cleaned"
1383
+ // here means "processed into the intelligence tables", not removed.
1384
+ memoryCleaned: report.processed,
1385
+ // clustering collapses near-duplicate entries into a single pattern
1386
+ // rather than deleting them; this is the count that got merged away
1387
+ // instead of becoming their own distinct pattern.
1388
+ duplicatesRemoved: Math.max(0, report.processed - report.patterns),
1389
+ episodes: report.episodes,
1390
+ patternEmbeddings: report.patternEmbeddings,
1391
+ causalEdges: report.causalEdges,
1392
+ promoted: report.promoted,
1393
+ byProvenance: report.byProvenance,
1394
+ namespaces: report.namespaces,
1395
+ dryRun: report.dryRun,
1396
+ corrupt: report.corrupt ?? false,
1397
+ skipped: report.skipped,
1283
1398
  };
1284
1399
  writeFileSync(consolidateFile, JSON.stringify(result, null, 2));
1285
1400
  return result;
1286
1401
  }
1402
+ /**
1403
+ * Nightly memory-DB backup worker (24h interval). Takes a WAL-safe, consistent
1404
+ * snapshot of .swarm/memory.db with rotation (keep last N). Never throws — a
1405
+ * worker must not crash the daemon; a skip/error is written to the metrics
1406
+ * file. Opt-out by omitting `backup` from `-w`; offsite GCS is opt-in via
1407
+ * RUFLO_BACKUP_GCS (a gs:// prefix), retention via RUFLO_BACKUP_KEEP.
1408
+ */
1409
+ async runBackupWorker() {
1410
+ const metricsDir = join(this.projectRoot, '.claude-flow', 'metrics');
1411
+ if (!existsSync(metricsDir))
1412
+ mkdirSync(metricsDir, { recursive: true });
1413
+ const backupFile = join(metricsDir, 'backup.json');
1414
+ let result;
1415
+ try {
1416
+ const keepEnv = Number(process.env.RUFLO_BACKUP_KEEP);
1417
+ const r = await backupMemoryDb({
1418
+ dbPath: defaultMemoryDbPath(this.projectRoot),
1419
+ keep: Number.isFinite(keepEnv) && keepEnv > 0 ? keepEnv : 7,
1420
+ gcs: process.env.RUFLO_BACKUP_GCS || undefined,
1421
+ });
1422
+ result = {
1423
+ timestamp: new Date().toISOString(),
1424
+ backedUp: r.backedUp,
1425
+ path: r.path,
1426
+ sizeBytes: r.sizeBytes ?? 0,
1427
+ rotatedAway: r.rotatedAway?.length ?? 0,
1428
+ gcsUri: r.gcsUri,
1429
+ skipped: r.skipped,
1430
+ };
1431
+ }
1432
+ catch (error) {
1433
+ const message = error instanceof Error ? error.message : String(error);
1434
+ this.log('warn', `Backup worker failed: ${message}`);
1435
+ result = { timestamp: new Date().toISOString(), backedUp: false, error: message };
1436
+ }
1437
+ writeFileSync(backupFile, JSON.stringify(result, null, 2));
1438
+ return result;
1439
+ }
1287
1440
  /**
1288
1441
  * Local testgaps worker (fallback when headless unavailable)
1289
1442
  */
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.21.1",
3
+ "version": "3.23.0",
4
4
  "type": "module",
5
5
  "description": "Ruflo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
6
6
  "main": "dist/src/index.js",
@@ -75,8 +75,10 @@
75
75
  },
76
76
  "files": [
77
77
  "dist",
78
+ "!dist/**/*.map",
79
+ "!dist/**/*.tsbuildinfo",
78
80
  "bin",
79
- "scripts",
81
+ "scripts/postinstall.cjs",
80
82
  ".claude",
81
83
  "plugins",
82
84
  "README.md"
@@ -132,6 +134,7 @@
132
134
  "agentic-flow": "^3.0.0-alpha.1",
133
135
  "agenticow": "~0.2.4",
134
136
  "metaharness": "~0.2.8",
137
+ "page-agent": "~1.11.0",
135
138
  "ruvector": "^0.2.27"
136
139
  },
137
140
  "publishConfig": {