@claude-flow/cli 3.38.2 → 3.38.4

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "manifest": {
3
- "version": "3.38.2",
3
+ "version": "3.38.4",
4
4
  "files": {
5
5
  "auto-memory-hook.mjs": "85fe05c757421c52137c0bc8545a0896bab6b4714538c2a11d1d0835bfcc8c1c",
6
6
  "hook-handler.cjs": "dae295fb9ae2626b89899c19a20cc911541af82b52d2eeb9b214d618b96e9a86",
@@ -8,6 +8,6 @@
8
8
  "statusline.cjs": "0457fe53f8cd2c56458ff178392536a5868efd1a573665fa43bc01d2d95ca677"
9
9
  }
10
10
  },
11
- "signature": "aUyZD8VBc8slPjWIexWvx5vD6cF9ms5YKEDvLl+6WSX8Y0hrtXQgSs42Bmetyqj0LTRW5+W9GF3kUNB6zGiDBw==",
11
+ "signature": "pebcqTgxAwqxE5P2CeHtJGeddXdUluZcIkdlIrCo9NAjkNEFTiwV/PUltPtEvyYQ5uYu1AaZjbT/2qz3/YIhAg==",
12
12
  "algorithm": "ed25519"
13
13
  }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "generation": 4,
4
- "generatedAt": "2026-08-12T15:41:12.144Z",
5
- "gitSha": "87f4f8ab",
4
+ "generatedAt": "2026-08-12T18:43:20.202Z",
5
+ "gitSha": "d41af6e4",
6
6
  "catalog": {
7
7
  "agents": 164,
8
8
  "tools": 397,
@@ -2194,7 +2194,12 @@ const intelligenceCommand = {
2194
2194
  tokenReduction: 'N/A',
2195
2195
  sweBenchScore: 'N/A',
2196
2196
  },
2197
- lastTrainingMs: lastAdaptation ? Date.now() - lastAdaptation : undefined,
2197
+ // #2940: a training cycle that actually ran this invocation is "now"
2198
+ // — reading the pre-call `lastAdaptation` here would still show the
2199
+ // stale age (the exact "aged instead of reset" symptom reported).
2200
+ lastTrainingMs: mcpResult?.training?.trained
2201
+ ? 0
2202
+ : (lastAdaptation ? Date.now() - lastAdaptation : undefined),
2198
2203
  persistence: {
2199
2204
  dataDir: persistence.dataDir,
2200
2205
  patternsFile: persistence.patternsFile,
@@ -2206,10 +2211,34 @@ const intelligenceCommand = {
2206
2211
  trajectoriesFromDisk,
2207
2212
  },
2208
2213
  };
2214
+ // #2940: this block used to be a cosmetic 500ms sleep followed by an
2215
+ // unconditional "Training cycle completed" — no training ever ran and
2216
+ // `lastAdaptation` never moved, so `--status` could never report a
2217
+ // training cycle as recent no matter how many times `--train` was
2218
+ // invoked. `hooks_intelligence` now actually distills when asked
2219
+ // (see mcp-tools/hooks-tools.ts); report what it actually did instead
2220
+ // of a canned success message.
2221
+ const trainingResult = mcpResult?.training;
2209
2222
  if (forceTraining) {
2210
- spinner.setText('Running training cycle...');
2211
- await new Promise(resolve => setTimeout(resolve, 500));
2212
- spinner.succeed('Training cycle completed');
2223
+ if (trainingResult?.trained && trainingResult.patternsDistilled) {
2224
+ spinner.succeed(`Training cycle completed distilled ${trainingResult.patternsDistilled} pattern${trainingResult.patternsDistilled === 1 ? '' : 's'}`);
2225
+ }
2226
+ else if (trainingResult?.trained) {
2227
+ // Ran (SONA/EWC++ distillation pass executed, lastAdaptation
2228
+ // moved) but found zero new patterns — deliberately NOT the same
2229
+ // message as a real distillation, or this is exactly the "success
2230
+ // report with no state change behind it" the issue describes.
2231
+ spinner.stop();
2232
+ output.printWarning(`Training cycle ran — 0 new patterns to distill (${trainingResult.reason || 'nothing new since the last cycle'})`);
2233
+ }
2234
+ else if (trainingResult?.attempted) {
2235
+ spinner.stop();
2236
+ output.printWarning(`Training cycle ran with nothing to do — ${trainingResult.reason || 'no new trajectories to distill'}`);
2237
+ }
2238
+ else {
2239
+ spinner.stop();
2240
+ output.printWarning('Training cycle could not run — intelligence MCP tool unavailable');
2241
+ }
2213
2242
  }
2214
2243
  else {
2215
2244
  spinner.succeed(hasLocalData ? 'Intelligence system active (local data loaded)' : 'Intelligence system active');
@@ -496,8 +496,16 @@ const initClaudeAction = async (ctx) => {
496
496
  const force = ctx.flags.force;
497
497
  const minimal = ctx.flags.minimal;
498
498
  const full = ctx.flags.full;
499
- const skipClaude = ctx.flags['skip-claude'];
500
- const onlyClaude = ctx.flags['only-claude'];
499
+ // #2952 every long-flag write path in the parser goes through
500
+ // normalizeKey() (parser.ts:399-402), which converts kebab-case to
501
+ // camelCase before storing. `--skip-claude`/`--only-claude`/
502
+ // `--all-agents`/`--cloud-mcp` land as `flags.skipClaude`/`flags.onlyClaude`/
503
+ // `flags.allAgents`/`flags.cloudMcp` — there is no code path that ever
504
+ // stores the literal kebab-case key. Reading `ctx.flags['skip-claude']`
505
+ // etc. was always undefined, so all four flags were silent no-ops. Same
506
+ // bug class as #2098A below, just never applied to these siblings.
507
+ const skipClaude = ctx.flags.skipClaude;
508
+ const onlyClaude = ctx.flags.onlyClaude;
501
509
  // #2098A — the parser handles `--no-foo` by stripping the prefix and
502
510
  // storing `flags.foo = false` (parser.ts:291-294), not by storing
503
511
  // `flags['no-foo'] = true`. So `--no-global` lands as
@@ -505,8 +513,8 @@ const initClaudeAction = async (ctx) => {
505
513
  // was always undefined and silently no-op'd — every user with the flag
506
514
  // set still got `~/.claude/CLAUDE.md` modified. Read the real key.
507
515
  const noGlobal = ctx.flags['no-global'] === true || ctx.flags['global'] === false;
508
- const allAgents = ctx.flags['all-agents'];
509
- const cloudMcp = ctx.flags['cloud-mcp'];
516
+ const allAgents = ctx.flags.allAgents;
517
+ const cloudMcp = ctx.flags.cloudMcp;
510
518
  const cwd = ctx.cwd;
511
519
  // Check if already initialized
512
520
  const initialized = isInitialized(cwd);
@@ -1377,26 +1377,36 @@ export const hooksPostTask = {
1377
1377
  catch {
1378
1378
  // Intelligence module not available — non-fatal
1379
1379
  }
1380
- // ADR-130 Phase 3: fire-and-forget "reinforced-by" edge on task success
1380
+ // ADR-130 Phase 3: "reinforced-by" edge on task success.
1381
1381
  // Writes: context node → task pattern node (relation: "reinforced-by")
1382
+ //
1383
+ // #2961 — this used to be fire-and-forget (no `await` on the IIFE). That
1384
+ // was invisible from the long-running MCP server, where the process
1385
+ // stays alive long enough for the detached write to finish in the
1386
+ // background. But `hooks post-task` (CLI) is the exact same handler
1387
+ // invoked from a one-shot process that calls `process.exit(0)`
1388
+ // immediately after this action resolves (bin/cli.js, #1552) — the
1389
+ // still-pending dynamic `import(...)` + `insertGraphEdge()` call was
1390
+ // killed before its first tick, so the CLI form dropped this edge on
1391
+ // every single success, not intermittently. Await it — this is a
1392
+ // single fast DB write, not worth losing correctness on one call site
1393
+ // to save latency on the other.
1382
1394
  if (success) {
1383
- (async () => {
1384
- try {
1385
- const { insertGraphEdge } = await import('../memory/graph-edge-writer.js');
1386
- const sessionCtxId = `task:${taskId}`;
1387
- const patternId = `pattern:${taskId}`;
1388
- await insertGraphEdge({
1389
- sourceId: sessionCtxId,
1390
- targetId: patternId,
1391
- relation: 'reinforced-by',
1392
- weight: quality,
1393
- confidence: quality,
1394
- lastReinforced: new Date().toISOString(),
1395
- metadata: { success, agent, taskId },
1396
- });
1397
- }
1398
- catch { /* non-fatal */ }
1399
- })().catch(() => { });
1395
+ try {
1396
+ const { insertGraphEdge } = await import('../memory/graph-edge-writer.js');
1397
+ const sessionCtxId = `task:${taskId}`;
1398
+ const patternId = `pattern:${taskId}`;
1399
+ await insertGraphEdge({
1400
+ sourceId: sessionCtxId,
1401
+ targetId: patternId,
1402
+ relation: 'reinforced-by',
1403
+ weight: quality,
1404
+ confidence: quality,
1405
+ lastReinforced: new Date().toISOString(),
1406
+ metadata: { success, agent, taskId },
1407
+ });
1408
+ }
1409
+ catch { /* non-fatal */ }
1400
1410
  }
1401
1411
  // Persist routing outcome for runtime learning (file-based, always reliable)
1402
1412
  const taskText = params.task || '';
@@ -2360,7 +2370,39 @@ export const hooksIntelligence = {
2360
2370
  const flashAvailable = (await getFlashAttention()) !== null;
2361
2371
  const ewcAvailable = (await getEWCConsolidator()) !== null;
2362
2372
  const loraAvailable = (await getLoRAAdapter()) !== null;
2373
+ // #2940: `forceTraining` (CLI `hooks intelligence --train`) was declared
2374
+ // on this tool's input schema but never read — the handler always
2375
+ // returned the same read-only status dashboard, so `lastAdaptation`
2376
+ // (what `--status` reports as "Last Training") could never move no
2377
+ // matter how many times `--train` ran. Actually distill when asked,
2378
+ // and report honestly rather than always implying success:
2379
+ // `attempted: false` (flag not passed), `trained: true` (real work
2380
+ // happened, lastAdaptation now current), or `trained: false` with a
2381
+ // reason (nothing new to distill, or distillation unavailable).
2382
+ const training = { attempted: false, trained: false };
2383
+ if (params.forceTraining) {
2384
+ training.attempted = true;
2385
+ try {
2386
+ const { distillLearning } = await import('../memory/intelligence.js');
2387
+ const result = await distillLearning();
2388
+ if (result) {
2389
+ training.trained = true;
2390
+ training.patternsDistilled = result.patternsDistilled;
2391
+ training.ewcPenalty = result.ewcPenalty;
2392
+ if (result.patternsDistilled === 0) {
2393
+ training.reason = 'no new trajectories to distill since the last training cycle';
2394
+ }
2395
+ }
2396
+ else {
2397
+ training.reason = 'intelligence system unavailable — could not initialize SONA/ReasoningBank';
2398
+ }
2399
+ }
2400
+ catch (error) {
2401
+ training.reason = `distillation failed: ${error instanceof Error ? error.message : String(error)}`;
2402
+ }
2403
+ }
2363
2404
  return {
2405
+ training,
2364
2406
  mode,
2365
2407
  status: 'active',
2366
2408
  components: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.38.2",
3
+ "version": "3.38.4",
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",