@claude-flow/cli 3.38.6 → 3.38.7

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,13 +1,13 @@
1
1
  {
2
2
  "manifest": {
3
- "version": "3.38.6",
3
+ "version": "3.38.7",
4
4
  "files": {
5
5
  "auto-memory-hook.mjs": "85fe05c757421c52137c0bc8545a0896bab6b4714538c2a11d1d0835bfcc8c1c",
6
6
  "hook-handler.cjs": "dae295fb9ae2626b89899c19a20cc911541af82b52d2eeb9b214d618b96e9a86",
7
- "intelligence.cjs": "66d63fdeab5f2ce0546bff80e69144911508fa2bf88f7b167ba0905762ecb314",
7
+ "intelligence.cjs": "30e42ed7ec4ca5a94ac54fdb1330d2d47ac5f3fdeeef207753574723a9e77b5c",
8
8
  "statusline.cjs": "0457fe53f8cd2c56458ff178392536a5868efd1a573665fa43bc01d2d95ca677"
9
9
  }
10
10
  },
11
- "signature": "0u8qz9OxORssiGc4kWWJR9fL9OPo7GZj6K7Zhkq+40XkKCP7nxLHx8LPcUwxhRHzVnnBtnE34TvsoTueM2VIBA==",
11
+ "signature": "FgH/N1oH9kP+lac4BmyUWUmAamnyfQzYgIt3b/xGeL2PJgOLGvPbuKF1DTpnzRHONcsAViViVt0dWKF6Q3LqAw==",
12
12
  "algorithm": "ed25519"
13
13
  }
@@ -830,11 +830,16 @@ function consolidate() {
830
830
  pageRanks = computePageRank(nodes, edges, 0.85, 30);
831
831
  }
832
832
 
833
- // 6. Write updated graph
833
+ // 6. Write updated graph. #2920 follow-up: include contentFingerprint so
834
+ // init()'s cache-hit gate (line ~511) doesn't unconditionally miss on the
835
+ // very next init after a consolidate — without this, nodeCount alone
836
+ // matched but contentFingerprint was undefined here vs a real hash in
837
+ // init()'s own write, forcing a full rebuild every time.
834
838
  writeJSON(GRAPH_PATH, {
835
839
  version: 1,
836
840
  updatedAt: Date.now(),
837
841
  nodeCount: Object.keys(nodes).length,
842
+ contentFingerprint: storeFingerprint(store),
838
843
  nodes,
839
844
  edges,
840
845
  pageRanks,
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "generation": 4,
4
- "generatedAt": "2026-08-12T20:46:09.024Z",
5
- "gitSha": "f7672a10",
4
+ "generatedAt": "2026-08-12T21:44:13.365Z",
5
+ "gitSha": "57c0fcba",
6
6
  "catalog": {
7
7
  "agents": 164,
8
8
  "tools": 397,
@@ -203,6 +203,23 @@ async function getMemoryFunctions() {
203
203
  checkMemoryInitialization,
204
204
  };
205
205
  }
206
+ /**
207
+ * #2922: every `backend:` field in this file's tool responses used to be the
208
+ * hardcoded literal `'sql.js + HNSW'` regardless of which search path was
209
+ * actually active — most of the time that's the bridge doing a brute-force
210
+ * cosine scan, not HNSW. This reports the real algorithm via the same
211
+ * capability probe `getHNSWStatus()` already exposes.
212
+ */
213
+ async function describeBackend() {
214
+ try {
215
+ const { getHNSWStatus } = await import('../memory/memory-initializer.js');
216
+ const status = getHNSWStatus();
217
+ return status.algorithm === 'hnsw' ? 'sql.js + HNSW' : 'sqlite (bridge, brute-force cosine)';
218
+ }
219
+ catch {
220
+ return 'sqlite';
221
+ }
222
+ }
206
223
  /**
207
224
  * Ensure memory database is initialized and migrate legacy data if needed.
208
225
  * #1606: Wrapped in try/catch to prevent process-level crashes that kill
@@ -318,7 +335,7 @@ export const memoryTools = [
318
335
  hasEmbedding: !!result.embedding,
319
336
  embeddingDimensions: result.embedding?.dimensions || null,
320
337
  provenanceType: provenanceType || 'unknown',
321
- backend: 'sql.js + HNSW',
338
+ backend: await describeBackend(),
322
339
  storeTime: `${duration.toFixed(2)}ms`,
323
340
  error: result.error,
324
341
  };
@@ -371,7 +388,7 @@ export const memoryTools = [
371
388
  accessCount: result.entry.accessCount,
372
389
  hasEmbedding: result.entry.hasEmbedding,
373
390
  found: true,
374
- backend: 'sql.js + HNSW',
391
+ backend: await describeBackend(),
375
392
  };
376
393
  }
377
394
  return {
@@ -584,7 +601,7 @@ export const memoryTools = [
584
601
  namespace,
585
602
  deleted: result.deleted,
586
603
  hnswIndexInvalidated: result.deleted,
587
- backend: 'sql.js + HNSW',
604
+ backend: await describeBackend(),
588
605
  };
589
606
  }
590
607
  catch (error) {
@@ -641,7 +658,7 @@ export const memoryTools = [
641
658
  total: result.total,
642
659
  limit,
643
660
  offset,
644
- backend: 'sql.js + HNSW',
661
+ backend: await describeBackend(),
645
662
  };
646
663
  }
647
664
  catch (error) {
@@ -685,7 +702,7 @@ export const memoryTools = [
685
702
  ? `${((withEmbeddings / allEntries.total) * 100).toFixed(1)}%`
686
703
  : '0%',
687
704
  namespaces,
688
- backend: 'sql.js + HNSW',
705
+ backend: await describeBackend(),
689
706
  version: status.version || '3.0.0',
690
707
  features: status.features || {
691
708
  vectorEmbeddings: true,
@@ -736,7 +753,7 @@ export const memoryTools = [
736
753
  success: true,
737
754
  message: 'Migration completed',
738
755
  migrated: Object.keys(legacyStore.entries).length,
739
- backend: 'sql.js + HNSW',
756
+ backend: await describeBackend(),
740
757
  };
741
758
  },
742
759
  },
@@ -1149,7 +1166,7 @@ export const memoryTools = [
1149
1166
  bytes += e.size || 0;
1150
1167
  }
1151
1168
  return {
1152
- backend: 'sql.js + HNSW',
1169
+ backend: await describeBackend(),
1153
1170
  entries: all.total ?? all.entries.length,
1154
1171
  size: bytes,
1155
1172
  namespaces: Object.entries(nsCounts).map(([name, entries]) => ({ name, entries })),
@@ -209,21 +209,29 @@ export declare function bridgeLoadEmbeddingModel(dbPath?: string): Promise<{
209
209
  loadTime?: number;
210
210
  } | null>;
211
211
  /**
212
- * Get HNSW status from AgentDB v3's vector backend or HNSW index.
212
+ * Get vector search status from AgentDB v3's SQLite-backed store.
213
213
  * Returns null if unavailable.
214
- */
215
- export declare function bridgeGetHNSWStatus(dbPath?: string): Promise<{
214
+ *
215
+ * #2922: previously named `bridgeGetHNSWStatus` and unconditionally returned
216
+ * `available: true` whenever a DB connection succeeded — but the search this
217
+ * status describes (`bridgeSearchBruteForceCosine`, below) is a full-table
218
+ * SELECT + brute-force cosine scan, not an HNSW index lookup. Renamed and
219
+ * given an explicit `algorithm` field so callers can't mistake "vector
220
+ * search works" for "vector search is HNSW-accelerated".
221
+ */
222
+ export declare function bridgeGetVectorSearchStatus(dbPath?: string): Promise<{
216
223
  available: boolean;
217
224
  initialized: boolean;
218
225
  entryCount: number;
219
226
  dimensions: number;
227
+ algorithm: 'brute-force-cosine';
220
228
  } | null>;
221
229
  /**
222
- * Search using AgentDB v3's embedder + SQLite entries.
223
- * This is the HNSW-equivalent search through the bridge.
224
- * Returns null if unavailable.
230
+ * Search AgentDB v3's embedder + SQLite entries via a full-table scan and
231
+ * brute-force cosine similarity. NOT HNSW-accelerated see #2922. Returns
232
+ * null if unavailable.
225
233
  */
226
- export declare function bridgeSearchHNSW(queryEmbedding: number[], options?: {
234
+ export declare function bridgeSearchBruteForceCosine(queryEmbedding: number[], options?: {
227
235
  k?: number;
228
236
  namespace?: string;
229
237
  threshold?: number;
@@ -235,10 +243,11 @@ export declare function bridgeSearchHNSW(queryEmbedding: number[], options?: {
235
243
  namespace: string;
236
244
  }> | null>;
237
245
  /**
238
- * Add entry to the bridge's database with embedding.
239
- * Returns null if unavailable.
246
+ * Add entry to the bridge's database with embedding. No HNSW index is built
247
+ * or updated here — see #2922; the embedding is only stored for a later
248
+ * brute-force scan. Returns null if unavailable.
240
249
  */
241
- export declare function bridgeAddToHNSW(id: string, embedding: number[], entry: {
250
+ export declare function bridgeAddEmbedding(id: string, embedding: number[], entry: {
242
251
  id: string;
243
252
  key: string;
244
253
  namespace: string;
@@ -1478,10 +1478,17 @@ export async function bridgeLoadEmbeddingModel(dbPath) {
1478
1478
  }
1479
1479
  // ===== Phase 3: HNSW bridge =====
1480
1480
  /**
1481
- * Get HNSW status from AgentDB v3's vector backend or HNSW index.
1481
+ * Get vector search status from AgentDB v3's SQLite-backed store.
1482
1482
  * Returns null if unavailable.
1483
+ *
1484
+ * #2922: previously named `bridgeGetHNSWStatus` and unconditionally returned
1485
+ * `available: true` whenever a DB connection succeeded — but the search this
1486
+ * status describes (`bridgeSearchBruteForceCosine`, below) is a full-table
1487
+ * SELECT + brute-force cosine scan, not an HNSW index lookup. Renamed and
1488
+ * given an explicit `algorithm` field so callers can't mistake "vector
1489
+ * search works" for "vector search is HNSW-accelerated".
1483
1490
  */
1484
- export async function bridgeGetHNSWStatus(dbPath) {
1491
+ export async function bridgeGetVectorSearchStatus(dbPath) {
1485
1492
  const registry = await getRegistry(dbPath);
1486
1493
  if (!registry)
1487
1494
  return null;
@@ -1503,6 +1510,7 @@ export async function bridgeGetHNSWStatus(dbPath) {
1503
1510
  initialized: true,
1504
1511
  entryCount,
1505
1512
  dimensions: 384,
1513
+ algorithm: 'brute-force-cosine',
1506
1514
  };
1507
1515
  }
1508
1516
  catch {
@@ -1510,11 +1518,11 @@ export async function bridgeGetHNSWStatus(dbPath) {
1510
1518
  }
1511
1519
  }
1512
1520
  /**
1513
- * Search using AgentDB v3's embedder + SQLite entries.
1514
- * This is the HNSW-equivalent search through the bridge.
1515
- * Returns null if unavailable.
1521
+ * Search AgentDB v3's embedder + SQLite entries via a full-table scan and
1522
+ * brute-force cosine similarity. NOT HNSW-accelerated see #2922. Returns
1523
+ * null if unavailable.
1516
1524
  */
1517
- export async function bridgeSearchHNSW(queryEmbedding, options, dbPath) {
1525
+ export async function bridgeSearchBruteForceCosine(queryEmbedding, options, dbPath) {
1518
1526
  const registry = await getRegistry(dbPath);
1519
1527
  if (!registry)
1520
1528
  return null;
@@ -1576,10 +1584,11 @@ export async function bridgeSearchHNSW(queryEmbedding, options, dbPath) {
1576
1584
  }
1577
1585
  }
1578
1586
  /**
1579
- * Add entry to the bridge's database with embedding.
1580
- * Returns null if unavailable.
1587
+ * Add entry to the bridge's database with embedding. No HNSW index is built
1588
+ * or updated here — see #2922; the embedding is only stored for a later
1589
+ * brute-force scan. Returns null if unavailable.
1581
1590
  */
1582
- export async function bridgeAddToHNSW(id, embedding, entry, dbPath) {
1591
+ export async function bridgeAddEmbedding(id, embedding, entry, dbPath) {
1583
1592
  const registry = await getRegistry(dbPath);
1584
1593
  if (!registry)
1585
1594
  return null;
@@ -91,6 +91,7 @@ export declare function getHNSWStatus(): {
91
91
  initialized: boolean;
92
92
  entryCount: number;
93
93
  dimensions: number;
94
+ algorithm: 'hnsw' | 'brute-force-cosine';
94
95
  };
95
96
  /**
96
97
  * Clear the HNSW index (for rebuilding)
@@ -750,7 +750,7 @@ export async function addToHNSWIndex(id, embedding, entry) {
750
750
  // ADR-053: Try AgentDB v3 bridge first
751
751
  const bridge = await getBridge();
752
752
  if (bridge) {
753
- const bridgeResult = await bridge.bridgeAddToHNSW(id, embedding, entry);
753
+ const bridgeResult = await bridge.bridgeAddEmbedding(id, embedding, entry);
754
754
  if (bridgeResult === true)
755
755
  return true;
756
756
  }
@@ -780,7 +780,7 @@ export async function searchHNSWIndex(queryEmbedding, options) {
780
780
  // ADR-053: Try AgentDB v3 bridge first
781
781
  const bridge = await getBridge();
782
782
  if (bridge) {
783
- const bridgeResult = await bridge.bridgeSearchHNSW(queryEmbedding, options);
783
+ const bridgeResult = await bridge.bridgeSearchBruteForceCosine(queryEmbedding, options);
784
784
  if (bridgeResult)
785
785
  return bridgeResult;
786
786
  }
@@ -826,14 +826,23 @@ export async function searchHNSWIndex(queryEmbedding, options) {
826
826
  * Get HNSW index status
827
827
  */
828
828
  export function getHNSWStatus() {
829
- // ADR-053: If bridge was previously loaded, report availability
829
+ // #2922: this branch previously reported `available: true` whenever the
830
+ // bridge was loaded, on the theory that "AgentDB v3 is HNSW-equivalent" —
831
+ // but the bridge's actual search path (bridgeSearchBruteForceCosine, see
832
+ // memory-bridge.ts) does a full-table SELECT + brute-force cosine loop and
833
+ // never touches @ruvector/core or an HNSW index, regardless of whether
834
+ // ruvector-core itself is installed. `available` here means "an HNSW
835
+ // index is the one actually searched", matching what this function's own
836
+ // name promises — that's false while the bridge is the active path, so
837
+ // this no longer claims otherwise. Vector search itself still works via
838
+ // the bridge; `algorithm` tells callers it's brute-force, not HNSW.
830
839
  if (_bridge && _bridge !== null) {
831
- // Bridge is loaded — HNSW-equivalent is available via AgentDB v3
832
840
  return {
833
- available: true,
834
- initialized: true,
841
+ available: false,
842
+ initialized: false,
835
843
  entryCount: hnswIndex?.entries.size ?? 0,
836
- dimensions: hnswIndex?.dimensions ?? 384
844
+ dimensions: hnswIndex?.dimensions ?? 384,
845
+ algorithm: 'brute-force-cosine',
837
846
  };
838
847
  }
839
848
  // #2356: `available` now reflects real capability (index already loaded OR
@@ -845,7 +854,8 @@ export function getHNSWStatus() {
845
854
  available: hnswIndex !== null || isRuvectorCoreResolvable(),
846
855
  initialized: hnswIndex?.initialized ?? false,
847
856
  entryCount: hnswIndex?.entries.size ?? 0,
848
- dimensions: hnswIndex?.dimensions ?? 384
857
+ dimensions: hnswIndex?.dimensions ?? 384,
858
+ algorithm: 'hnsw',
849
859
  };
850
860
  }
851
861
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.38.6",
3
+ "version": "3.38.7",
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",