@claude-flow/cli 3.32.33 → 3.32.34

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.32.33",
3
+ "version": "3.32.34",
4
4
  "files": {
5
5
  "auto-memory-hook.mjs": "68be7e9a9eba7bf9c4e8a230db7bf61a243b965639f8504842799d6c6ca28762",
6
6
  "hook-handler.cjs": "50ea92a72651bdc95634f7588d56a5870963168eef5226f66ed14af3b47c8d9a",
@@ -8,6 +8,6 @@
8
8
  "statusline.cjs": "d2a0eac56d1267d8dbed2d70b09feb592299469196ec4b215909f2b052144882"
9
9
  }
10
10
  },
11
- "signature": "cdCqQZfkjY3y+45Yuk0kKw2yV3CApVm21lmQcxZhYrxgAhhh2o6nAWbFnmNUJIMD/LBPmDjiy4zT9kjoRMMOCA==",
11
+ "signature": "i0qilACTabRlI6VORA0QyP0r4EuvJsrvtkucxia3TStgq/la250iesyKjlcHbLV/6fshZiGtPMLq1nmXLf+ZAw==",
12
12
  "algorithm": "ed25519"
13
13
  }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "generation": 3,
4
- "generatedAt": "2026-07-29T12:53:25.000Z",
5
- "gitSha": "c1957608",
4
+ "generatedAt": "2026-07-29T13:29:39.000Z",
5
+ "gitSha": "c3cf2d0e",
6
6
  "catalog": {
7
7
  "agents": 164,
8
8
  "tools": 395,
@@ -16,6 +16,29 @@
16
16
  *
17
17
  * @module v3/cli/memory-bridge
18
18
  */
19
+ /**
20
+ * Should this init-time log line be swallowed?
21
+ *
22
+ * A DEGRADATION notice never is. AgentDB logs "[AgentDB] better-sqlite3 not
23
+ * available, using sql.js WASM" when it falls back to WASM, and both the
24
+ * '[AgentDB]' and 'better-sqlite3' entries above match it — so the one line
25
+ * explaining why the native driver was not in use was being discarded as
26
+ * noise. Suppress the banners, keep the bad news.
27
+ */
28
+ export declare function shouldSuppressInitLog(msg: string): boolean;
29
+ /**
30
+ * Create/migrate the bridge's `memory_entries` table on `db`.
31
+ *
32
+ * Returns true when the schema is known-good, false when the database was not
33
+ * writable (caller then leaves it un-ensured so a later writable call retries).
34
+ *
35
+ * Exported so the ADR-323 column migration can be tested directly: the bug it
36
+ * fixes was invisible end-to-end, because the resulting error was swallowed and
37
+ * reported as an unrelated WAL-sidecar refusal.
38
+ */
39
+ export declare function ensureBridgeSchema(db: {
40
+ exec: (sql: string) => unknown;
41
+ }): boolean;
19
42
  /**
20
43
  * Store an entry via AgentDB v3.
21
44
  * Phase 2-5: Routes through MutationGuard → TieredCache → DB → AttestationLog.
@@ -239,8 +262,27 @@ export declare function isBridgeAvailable(dbPath?: string): Promise<boolean>;
239
262
  * Get the ControllerRegistry instance (for advanced consumers).
240
263
  */
241
264
  export declare function getControllerRegistry(dbPath?: string): Promise<any | null>;
265
+ /**
266
+ * Why the bridge last declined a write, or null when it has not.
267
+ *
268
+ * Deliberately NOT gated on `bridgeAvailable === false`. A bridge that
269
+ * initialised fine can still fail every write — a schema mismatch throws
270
+ * per-operation while the registry stays healthy — and that case is exactly
271
+ * the one worth reporting, since the caller then demotes to a fallback whose
272
+ * error message describes something else entirely.
273
+ *
274
+ * Callers that surface a degraded-path error should include this so the
275
+ * operator learns the cause instead of only the symptom.
276
+ */
277
+ export declare function getBridgeFailureReason(): string | null;
242
278
  /**
243
279
  * Shutdown the bridge and release resources.
280
+ *
281
+ * The cached state is cleared unconditionally. Previously the reset lived
282
+ * inside `if (registryInstance)`, so it could not clear a FAILED init — the
283
+ * one state that actually needs clearing, since `registryInstance` is null
284
+ * precisely when init failed. A process that latched `bridgeAvailable = false`
285
+ * therefore had no recovery path short of a restart.
244
286
  */
245
287
  export declare function shutdownBridge(): Promise<void>;
246
288
  /**
@@ -23,6 +23,17 @@ import { createRequire } from 'node:module';
23
23
  let registryPromise = null;
24
24
  let registryInstance = null;
25
25
  let bridgeAvailable = null;
26
+ /**
27
+ * Why the bridge is unavailable, when it is.
28
+ *
29
+ * `bridgeAvailable = false` latches for the life of the process, so a single
30
+ * transient init failure (a slow Xenova/ONNX fetch, a locked db) routes every
31
+ * later write to the sql.js whole-image fallback — which then refuses whenever
32
+ * -wal/-shm sidecars are present. Without this, that refusal is the only
33
+ * symptom the caller ever sees, and it names a cause ("restore the native
34
+ * better-sqlite3 bridge") the caller has no way to check.
35
+ */
36
+ let bridgeFailureReason = null;
26
37
  /**
27
38
  * ADR-323: reuse memory-initializer's provenance-type allowlist rather than
28
39
  * duplicating it (drift risk). Lazy CJS require for the same circular-ESM-
@@ -109,6 +120,31 @@ function getAgentDbPath() {
109
120
  function generateId(prefix) {
110
121
  return `${prefix}_${Date.now()}_${crypto.randomBytes(8).toString('hex')}`;
111
122
  }
123
+ /** Noisy init banners that carry no operational signal. */
124
+ const INIT_LOG_NOISE = [
125
+ 'Transformers.js',
126
+ 'better-sqlite3',
127
+ '[AgentDB]',
128
+ '[HNSWLibBackend]',
129
+ 'RuVector graph',
130
+ ];
131
+ /**
132
+ * Should this init-time log line be swallowed?
133
+ *
134
+ * A DEGRADATION notice never is. AgentDB logs "[AgentDB] better-sqlite3 not
135
+ * available, using sql.js WASM" when it falls back to WASM, and both the
136
+ * '[AgentDB]' and 'better-sqlite3' entries above match it — so the one line
137
+ * explaining why the native driver was not in use was being discarded as
138
+ * noise. Suppress the banners, keep the bad news.
139
+ */
140
+ export function shouldSuppressInitLog(msg) {
141
+ const degradation = msg.includes('not available')
142
+ || msg.includes('falling back')
143
+ || msg.includes('fallback');
144
+ if (degradation)
145
+ return false;
146
+ return INIT_LOG_NOISE.some((needle) => msg.includes(needle));
147
+ }
112
148
  /**
113
149
  * Lazily initialize the ControllerRegistry singleton.
114
150
  * Returns null if @claude-flow/memory is not available.
@@ -123,15 +159,12 @@ async function getRegistry(dbPath) {
123
159
  try {
124
160
  const { ControllerRegistry } = await import('@claude-flow/memory');
125
161
  const registry = new ControllerRegistry();
126
- // Suppress noisy console.log during init
162
+ // Suppress noisy console.log during init — but never suppress a
163
+ // DEGRADATION notice (see shouldSuppressInitLog).
127
164
  const origLog = console.log;
128
165
  console.log = (...args) => {
129
166
  const msg = String(args[0] ?? '');
130
- if (msg.includes('Transformers.js') ||
131
- msg.includes('better-sqlite3') ||
132
- msg.includes('[AgentDB]') ||
133
- msg.includes('[HNSWLibBackend]') ||
134
- msg.includes('RuVector graph'))
167
+ if (shouldSuppressInitLog(msg))
135
168
  return;
136
169
  origLog.apply(console, args);
137
170
  };
@@ -387,9 +420,14 @@ async function getRegistry(dbPath) {
387
420
  }
388
421
  registryInstance = registry;
389
422
  bridgeAvailable = true;
423
+ bridgeFailureReason = null;
390
424
  return registry;
391
425
  }
392
- catch {
426
+ catch (err) {
427
+ // Record WHY. This latches for the process lifetime (see the
428
+ // bridgeFailureReason doc comment), so discarding the error here
429
+ // makes the resulting sql.js-fallback refusal undiagnosable.
430
+ bridgeFailureReason = err instanceof Error ? err.message : String(err);
393
431
  bridgeAvailable = false;
394
432
  registryPromise = null;
395
433
  return null;
@@ -529,6 +567,70 @@ async function logAttestation(registry, operation, entryId, metadata) {
529
567
  // runs the CREATE…IF NOT EXISTS block at most once per handle instead of on
530
568
  // every bridge call. WeakSet so handles GC without leaking.
531
569
  const _schemaEnsuredDbs = new WeakSet();
570
+ /**
571
+ * Create/migrate the bridge's `memory_entries` table on `db`.
572
+ *
573
+ * Returns true when the schema is known-good, false when the database was not
574
+ * writable (caller then leaves it un-ensured so a later writable call retries).
575
+ *
576
+ * Exported so the ADR-323 column migration can be tested directly: the bug it
577
+ * fixes was invisible end-to-end, because the resulting error was swallowed and
578
+ * reported as an unrelated WAL-sidecar refusal.
579
+ */
580
+ export function ensureBridgeSchema(db) {
581
+ try {
582
+ db.exec(`CREATE TABLE IF NOT EXISTS memory_entries (
583
+ id TEXT PRIMARY KEY,
584
+ key TEXT NOT NULL,
585
+ namespace TEXT DEFAULT 'default',
586
+ content TEXT NOT NULL,
587
+ type TEXT DEFAULT 'semantic',
588
+ embedding TEXT,
589
+ embedding_model TEXT DEFAULT 'local',
590
+ embedding_dimensions INTEGER,
591
+ tags TEXT,
592
+ metadata TEXT,
593
+ owner_id TEXT,
594
+ created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),
595
+ updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),
596
+ expires_at INTEGER,
597
+ last_accessed_at INTEGER,
598
+ access_count INTEGER DEFAULT 0,
599
+ status TEXT DEFAULT 'active',
600
+ provenance_type TEXT DEFAULT 'unknown',
601
+ UNIQUE(namespace, key)
602
+ )`);
603
+ // ADR-323 added provenance_type to bridgeStoreEntry's INSERT, and
604
+ // ensureSchemaColumns() backfills it on the sql.js path — the bridge path
605
+ // had no equivalent. `CREATE TABLE IF NOT EXISTS` is a no-op on a table
606
+ // created before ADR-323, so on any pre-existing database every bridge
607
+ // write threw "table memory_entries has no column named provenance_type",
608
+ // was swallowed by the catch at the end of bridgeStoreEntry(), and demoted
609
+ // the caller to the sql.js whole-image path — which then refused with a
610
+ // WAL-sidecar error naming an unrelated cause. Silent, total write loss.
611
+ try {
612
+ db.exec(`ALTER TABLE memory_entries ADD COLUMN provenance_type TEXT DEFAULT 'unknown'`);
613
+ }
614
+ catch (err) {
615
+ // Already present is the common case. SQLite has no ADD COLUMN IF NOT
616
+ // EXISTS, so attempt-and-ignore only that exact condition. Treating a
617
+ // read-only, locked, or corrupt database as migrated would cache a
618
+ // schema that bridgeStoreEntry() still cannot use.
619
+ const msg = err instanceof Error ? err.message : String(err);
620
+ if (!/duplicate column name:\s*provenance_type/i.test(msg)) {
621
+ throw err;
622
+ }
623
+ }
624
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_bridge_ns ON memory_entries(namespace)`);
625
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_bridge_key ON memory_entries(key)`);
626
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_bridge_status ON memory_entries(status)`);
627
+ return true;
628
+ }
629
+ catch {
630
+ // Read-only database — leave it un-ensured so a writable call can retry.
631
+ return false;
632
+ }
633
+ }
532
634
  /**
533
635
  * Get the AgentDB database handle and ensure memory_entries table exists.
534
636
  * Returns null if not available.
@@ -543,37 +645,8 @@ function getDb(registry) {
543
645
  // call (store/search/get) was pure per-op overhead. Keyed by handle via a
544
646
  // WeakSet so a new db instance re-ensures without a stale global flag.
545
647
  if (!_schemaEnsuredDbs.has(db)) {
546
- try {
547
- db.exec(`CREATE TABLE IF NOT EXISTS memory_entries (
548
- id TEXT PRIMARY KEY,
549
- key TEXT NOT NULL,
550
- namespace TEXT DEFAULT 'default',
551
- content TEXT NOT NULL,
552
- type TEXT DEFAULT 'semantic',
553
- embedding TEXT,
554
- embedding_model TEXT DEFAULT 'local',
555
- embedding_dimensions INTEGER,
556
- tags TEXT,
557
- metadata TEXT,
558
- owner_id TEXT,
559
- created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),
560
- updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),
561
- expires_at INTEGER,
562
- last_accessed_at INTEGER,
563
- access_count INTEGER DEFAULT 0,
564
- status TEXT DEFAULT 'active',
565
- UNIQUE(namespace, key)
566
- )`);
567
- // Ensure indexes
568
- db.exec(`CREATE INDEX IF NOT EXISTS idx_bridge_ns ON memory_entries(namespace)`);
569
- db.exec(`CREATE INDEX IF NOT EXISTS idx_bridge_key ON memory_entries(key)`);
570
- db.exec(`CREATE INDEX IF NOT EXISTS idx_bridge_status ON memory_entries(status)`);
648
+ if (ensureBridgeSchema(db))
571
649
  _schemaEnsuredDbs.add(db);
572
- }
573
- catch {
574
- // Table already exists or db is read-only — that's fine. Don't mark
575
- // ensured on failure so a later writable call can retry.
576
- }
577
650
  }
578
651
  // ─── #2256-followup: rescue agentdb.embedder when its transformers.js
579
652
  // path fell through to mock embeddings.
@@ -785,6 +858,10 @@ export async function bridgeStoreEntry(options) {
785
858
  catch { /* vector_indexes may not exist on legacy DBs — fall through */ }
786
859
  const stmt = ctx.db.prepare(insertSql);
787
860
  const runResult = stmt.run(id, key, namespace, value, embeddingJson, dimensions || null, model, tags.length > 0 ? JSON.stringify(tags) : null, '{}', provenanceType, now, now, ttl ? now + (ttl * 1000) : null);
861
+ // A completed native write proves the bridge is currently healthy. Do not
862
+ // retain a diagnostic from an earlier transient failure and append it to a
863
+ // later, unrelated sql.js fallback refusal.
864
+ bridgeFailureReason = null;
788
865
  // #2775: strict insert against an ACTIVE existing row → changes === 0
789
866
  // (the ON CONFLICT WHERE clause above suppressed the update). Surface
790
867
  // this as a typed data-level error rather than a bridge failure —
@@ -858,6 +935,11 @@ export async function bridgeStoreEntry(options) {
858
935
  error: `key "${options.key}" already exists in namespace "${options.namespace ?? 'default'}" — pass upsert=true (--upsert on the CLI) to update it`,
859
936
  };
860
937
  }
938
+ // Returning null below demotes the caller to the sql.js whole-image path,
939
+ // whose WAL-sidecar guard then reports a cause that has nothing to do with
940
+ // what actually went wrong here. Record the real error so it can be
941
+ // surfaced alongside that guard's message.
942
+ bridgeFailureReason = msg;
861
943
  return null;
862
944
  }
863
945
  }
@@ -1562,8 +1644,29 @@ export async function isBridgeAvailable(dbPath) {
1562
1644
  export async function getControllerRegistry(dbPath) {
1563
1645
  return getRegistry(dbPath);
1564
1646
  }
1647
+ /**
1648
+ * Why the bridge last declined a write, or null when it has not.
1649
+ *
1650
+ * Deliberately NOT gated on `bridgeAvailable === false`. A bridge that
1651
+ * initialised fine can still fail every write — a schema mismatch throws
1652
+ * per-operation while the registry stays healthy — and that case is exactly
1653
+ * the one worth reporting, since the caller then demotes to a fallback whose
1654
+ * error message describes something else entirely.
1655
+ *
1656
+ * Callers that surface a degraded-path error should include this so the
1657
+ * operator learns the cause instead of only the symptom.
1658
+ */
1659
+ export function getBridgeFailureReason() {
1660
+ return bridgeFailureReason;
1661
+ }
1565
1662
  /**
1566
1663
  * Shutdown the bridge and release resources.
1664
+ *
1665
+ * The cached state is cleared unconditionally. Previously the reset lived
1666
+ * inside `if (registryInstance)`, so it could not clear a FAILED init — the
1667
+ * one state that actually needs clearing, since `registryInstance` is null
1668
+ * precisely when init failed. A process that latched `bridgeAvailable = false`
1669
+ * therefore had no recovery path short of a restart.
1567
1670
  */
1568
1671
  export async function shutdownBridge() {
1569
1672
  if (registryInstance) {
@@ -1573,10 +1676,11 @@ export async function shutdownBridge() {
1573
1676
  catch {
1574
1677
  // Best-effort
1575
1678
  }
1576
- registryInstance = null;
1577
- registryPromise = null;
1578
- bridgeAvailable = null;
1579
1679
  }
1680
+ registryInstance = null;
1681
+ registryPromise = null;
1682
+ bridgeAvailable = null;
1683
+ bridgeFailureReason = null;
1580
1684
  }
1581
1685
  // ===== Phase 3: ReasoningBank pattern operations =====
1582
1686
  /**
@@ -176,6 +176,32 @@ async function getBridge() {
176
176
  return null;
177
177
  }
178
178
  }
179
+ /**
180
+ * Build the WAL-sidecar refusal message, naming the bridge failure when one
181
+ * was recorded.
182
+ *
183
+ * The refusal tells the operator to "restore the native better-sqlite3
184
+ * bridge" but, on its own, gives them no way to discover why it is down —
185
+ * and the usual cause is a latched init failure inside the bridge, not a
186
+ * missing better-sqlite3. Appending the recorded reason turns an unactionable
187
+ * message into a diagnosis.
188
+ */
189
+ async function walRefusalError(operation) {
190
+ const base = 'memory database has an active native WAL connection '
191
+ + '(found -wal/-shm sidecar files) — refusing an unsafe sql.js '
192
+ + `whole-image ${operation}. Retry once the native writer completes, or `
193
+ + 'restore the native better-sqlite3 bridge.';
194
+ try {
195
+ const bridge = await getBridge();
196
+ const reason = bridge?.getBridgeFailureReason?.();
197
+ if (reason)
198
+ return `${base} Bridge unavailable: ${reason}`;
199
+ }
200
+ catch {
201
+ // Diagnostics must never mask the refusal they annotate.
202
+ }
203
+ return base;
204
+ }
179
205
  /**
180
206
  * Enhanced schema with pattern confidence, temporal decay, versioning
181
207
  * Vector embeddings enabled for semantic search
@@ -2382,10 +2408,7 @@ export async function storeEntry(options) {
2382
2408
  return {
2383
2409
  success: false,
2384
2410
  id: '',
2385
- error: 'memory database has an active native WAL connection ' +
2386
- '(found -wal/-shm sidecar files) — refusing an unsafe sql.js ' +
2387
- 'whole-image write. Retry once the native writer completes, or ' +
2388
- 'restore the native better-sqlite3 bridge.',
2411
+ error: await walRefusalError('write'),
2389
2412
  };
2390
2413
  }
2391
2414
  // Ensure schema has all required columns (migration for older DBs)
@@ -2868,10 +2891,7 @@ export async function getEntry(options) {
2868
2891
  return {
2869
2892
  success: false,
2870
2893
  found: false,
2871
- error: 'memory database has an active native WAL connection ' +
2872
- '(found -wal/-shm sidecar files) — refusing an unsafe sql.js ' +
2873
- 'whole-image read/write. Retry once the native writer completes, ' +
2874
- 'or restore the native better-sqlite3 bridge.',
2894
+ error: await walRefusalError('read/write'),
2875
2895
  };
2876
2896
  }
2877
2897
  // Ensure schema has all required columns (migration for older DBs)
@@ -2994,10 +3014,7 @@ export async function deleteEntry(options) {
2994
3014
  key,
2995
3015
  namespace,
2996
3016
  remainingEntries: 0,
2997
- error: 'memory database has an active native WAL connection ' +
2998
- '(found -wal/-shm sidecar files) — refusing an unsafe sql.js ' +
2999
- 'whole-image write. Retry once the native writer completes, or ' +
3000
- 'restore the native better-sqlite3 bridge.',
3017
+ error: await walRefusalError('write'),
3001
3018
  };
3002
3019
  }
3003
3020
  // Ensure schema has all required columns (migration for older DBs)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.32.33",
3
+ "version": "3.32.34",
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",