@cleocode/core 2026.4.38 → 2026.4.39

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/dist/index.js CHANGED
@@ -42360,6 +42360,390 @@ var init_brain_consolidator = __esm({
42360
42360
  }
42361
42361
  });
42362
42362
 
42363
+ // packages/core/src/memory/graph-memory-bridge.ts
42364
+ var graph_memory_bridge_exports = {};
42365
+ __export(graph_memory_bridge_exports, {
42366
+ autoLinkMemories: () => autoLinkMemories,
42367
+ linkMemoryToCode: () => linkMemoryToCode,
42368
+ listCodeLinks: () => listCodeLinks,
42369
+ queryCodeForMemory: () => queryCodeForMemory,
42370
+ queryMemoriesForCode: () => queryMemoriesForCode
42371
+ });
42372
+ function extractFilePaths(text3) {
42373
+ const paths = /* @__PURE__ */ new Set();
42374
+ for (const m of text3.matchAll(FILE_PATH_PATTERN)) {
42375
+ const p = m[1];
42376
+ if (p) paths.add(p);
42377
+ }
42378
+ return Array.from(paths);
42379
+ }
42380
+ function extractSymbolCandidates(text3) {
42381
+ const syms = /* @__PURE__ */ new Set();
42382
+ for (const m of text3.matchAll(SYMBOL_PATTERN)) {
42383
+ const s = m[1];
42384
+ if (s && s.length >= 4 && !SYMBOL_STOP_WORDS.has(s.toLowerCase())) {
42385
+ syms.add(s);
42386
+ }
42387
+ }
42388
+ return Array.from(syms);
42389
+ }
42390
+ function metadataText(metaJson) {
42391
+ if (!metaJson) return "";
42392
+ try {
42393
+ const obj = JSON.parse(metaJson);
42394
+ return Object.values(obj).filter((v) => typeof v === "string").join(" ");
42395
+ } catch {
42396
+ return "";
42397
+ }
42398
+ }
42399
+ async function linkMemoryToCode(projectRoot, memoryId, codeSymbol) {
42400
+ try {
42401
+ const brainDb = await getBrainDb(projectRoot);
42402
+ await getNexusDb();
42403
+ const nexusNative = getNexusNativeDb();
42404
+ if (!nexusNative) return false;
42405
+ const nexusNode = nexusNative.prepare("SELECT id, label, file_path, kind FROM nexus_nodes WHERE id = ? LIMIT 1").get(codeSymbol);
42406
+ if (!nexusNode) return false;
42407
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
42408
+ const idParts = memoryId.split(":");
42409
+ const nodeType = idParts[0] ?? "observation";
42410
+ await brainDb.insert(brainPageNodes).values({
42411
+ id: memoryId,
42412
+ nodeType,
42413
+ label: memoryId,
42414
+ qualityScore: 0.5,
42415
+ contentHash: null,
42416
+ lastActivityAt: now,
42417
+ createdAt: now,
42418
+ updatedAt: now
42419
+ }).onConflictDoUpdate({
42420
+ target: brainPageNodes.id,
42421
+ set: { lastActivityAt: now, updatedAt: now }
42422
+ });
42423
+ await brainDb.insert(brainPageEdges).values({
42424
+ fromId: memoryId,
42425
+ toId: codeSymbol,
42426
+ edgeType: "code_reference",
42427
+ weight: 1,
42428
+ provenance: "manual",
42429
+ createdAt: now
42430
+ }).onConflictDoNothing();
42431
+ return true;
42432
+ } catch (err) {
42433
+ console.warn("[graph-memory-bridge] linkMemoryToCode failed:", err);
42434
+ return false;
42435
+ }
42436
+ }
42437
+ async function autoLinkMemories(projectRoot) {
42438
+ const result = { scanned: 0, linked: 0, alreadyLinked: 0, links: [] };
42439
+ try {
42440
+ await getBrainDb(projectRoot);
42441
+ const brainNative = getBrainNativeDb();
42442
+ await getNexusDb();
42443
+ const nexusNative = getNexusNativeDb();
42444
+ if (!brainNative || !nexusNative) return result;
42445
+ const brainNodes = typedAll(
42446
+ brainNative.prepare(`
42447
+ SELECT id, node_type, label, quality_score, metadata_json
42448
+ FROM brain_page_nodes
42449
+ WHERE node_type IN ('observation', 'decision', 'pattern', 'learning')
42450
+ AND quality_score >= 0.3
42451
+ ORDER BY quality_score DESC
42452
+ LIMIT 500
42453
+ `)
42454
+ );
42455
+ result.scanned = brainNodes.length;
42456
+ if (brainNodes.length === 0) return result;
42457
+ const nexusNodes2 = typedAll(
42458
+ nexusNative.prepare(`
42459
+ SELECT id, label, name, file_path, kind
42460
+ FROM nexus_nodes
42461
+ WHERE kind NOT IN ('community', 'process', 'folder')
42462
+ LIMIT 20000
42463
+ `)
42464
+ );
42465
+ if (nexusNodes2.length === 0) return result;
42466
+ const byFilePath = /* @__PURE__ */ new Map();
42467
+ const byNameExact = /* @__PURE__ */ new Map();
42468
+ const byNameLower = /* @__PURE__ */ new Map();
42469
+ for (const node of nexusNodes2) {
42470
+ if (node.file_path) {
42471
+ const fp = node.file_path.toLowerCase();
42472
+ const existing = byFilePath.get(fp) ?? [];
42473
+ existing.push(node);
42474
+ byFilePath.set(fp, existing);
42475
+ }
42476
+ if (node.name) {
42477
+ const exact = byNameExact.get(node.name) ?? [];
42478
+ exact.push(node);
42479
+ byNameExact.set(node.name, exact);
42480
+ const lower = node.name.toLowerCase();
42481
+ const fuzzy = byNameLower.get(lower) ?? [];
42482
+ fuzzy.push(node);
42483
+ byNameLower.set(lower, fuzzy);
42484
+ }
42485
+ }
42486
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
42487
+ const existingEdges = /* @__PURE__ */ new Set();
42488
+ const rawEdges = typedAll(
42489
+ brainNative.prepare(`
42490
+ SELECT from_id, to_id FROM brain_page_edges WHERE edge_type = 'code_reference'
42491
+ `)
42492
+ );
42493
+ for (const e of rawEdges) {
42494
+ existingEdges.add(`${e.from_id}|${e.to_id}`);
42495
+ }
42496
+ for (const brainNode of brainNodes) {
42497
+ const corpus = `${brainNode.label} ${metadataText(brainNode.metadata_json)}`;
42498
+ const filePaths = extractFilePaths(corpus);
42499
+ const symbolCandidates = extractSymbolCandidates(corpus);
42500
+ const candidates = [];
42501
+ for (const fp of filePaths) {
42502
+ const matches = byFilePath.get(fp.toLowerCase());
42503
+ if (matches) {
42504
+ for (const n of matches) {
42505
+ candidates.push({ nexusNode: n, strategy: "exact-file", weight: 1 });
42506
+ }
42507
+ }
42508
+ }
42509
+ for (const sym of symbolCandidates) {
42510
+ const exactMatches = byNameExact.get(sym);
42511
+ if (exactMatches) {
42512
+ for (const n of exactMatches) {
42513
+ candidates.push({ nexusNode: n, strategy: "exact-symbol", weight: 1 });
42514
+ }
42515
+ }
42516
+ }
42517
+ const exactSymSet = new Set(
42518
+ symbolCandidates.flatMap((s) => byNameExact.get(s) ?? []).map((n) => n.id)
42519
+ );
42520
+ for (const sym of symbolCandidates) {
42521
+ if (sym.length < 5) continue;
42522
+ const lower = sym.toLowerCase();
42523
+ const fuzzyMatches = byNameLower.get(lower);
42524
+ if (fuzzyMatches) {
42525
+ for (const n of fuzzyMatches) {
42526
+ if (!exactSymSet.has(n.id)) {
42527
+ candidates.push({ nexusNode: n, strategy: "fuzzy-symbol", weight: 0.6 });
42528
+ }
42529
+ }
42530
+ }
42531
+ }
42532
+ const bestByNexusId = /* @__PURE__ */ new Map();
42533
+ for (const c of candidates) {
42534
+ const existing = bestByNexusId.get(c.nexusNode.id);
42535
+ if (!existing || c.weight > existing.weight) {
42536
+ bestByNexusId.set(c.nexusNode.id, c);
42537
+ }
42538
+ }
42539
+ const sortedCandidates = Array.from(bestByNexusId.values()).sort((a, b) => b.weight - a.weight).slice(0, 10);
42540
+ for (const { nexusNode, strategy, weight } of sortedCandidates) {
42541
+ const edgeKey = `${brainNode.id}|${nexusNode.id}`;
42542
+ if (existingEdges.has(edgeKey)) {
42543
+ result.alreadyLinked++;
42544
+ continue;
42545
+ }
42546
+ brainNative.prepare(`
42547
+ INSERT OR IGNORE INTO brain_page_nodes
42548
+ (id, node_type, label, quality_score, content_hash, metadata_json, last_activity_at, created_at, updated_at)
42549
+ VALUES (?, ?, ?, ?, NULL, NULL, ?, ?, ?)
42550
+ `).run(
42551
+ brainNode.id,
42552
+ brainNode.node_type,
42553
+ brainNode.label,
42554
+ brainNode.quality_score,
42555
+ now,
42556
+ now,
42557
+ now
42558
+ );
42559
+ try {
42560
+ brainNative.prepare(`
42561
+ INSERT OR IGNORE INTO brain_page_edges
42562
+ (from_id, to_id, edge_type, weight, provenance, created_at)
42563
+ VALUES (?, ?, 'code_reference', ?, ?, ?)
42564
+ `).run(brainNode.id, nexusNode.id, weight, `auto:${strategy}`, now);
42565
+ existingEdges.add(edgeKey);
42566
+ result.linked++;
42567
+ result.links.push({
42568
+ brainNodeId: brainNode.id,
42569
+ nexusNodeId: nexusNode.id,
42570
+ nexusLabel: nexusNode.label,
42571
+ matchStrategy: strategy,
42572
+ weight
42573
+ });
42574
+ } catch (edgeErr) {
42575
+ console.warn("[graph-memory-bridge] edge insert failed:", edgeErr);
42576
+ }
42577
+ }
42578
+ }
42579
+ } catch (err) {
42580
+ console.warn("[graph-memory-bridge] autoLinkMemories failed:", err);
42581
+ }
42582
+ return result;
42583
+ }
42584
+ async function queryMemoriesForCode(projectRoot, symbol2) {
42585
+ const result = { nexusNodeId: symbol2, memories: [] };
42586
+ try {
42587
+ await getBrainDb(projectRoot);
42588
+ const brainNative = getBrainNativeDb();
42589
+ if (!brainNative) return result;
42590
+ const rows = typedAll(
42591
+ brainNative.prepare(`
42592
+ SELECT n.id, n.node_type, n.label, n.quality_score,
42593
+ e.weight, e.provenance
42594
+ FROM brain_page_edges e
42595
+ JOIN brain_page_nodes n ON n.id = e.from_id
42596
+ WHERE e.to_id = ?
42597
+ AND e.edge_type = 'code_reference'
42598
+ ORDER BY e.weight DESC, n.quality_score DESC
42599
+ LIMIT 50
42600
+ `),
42601
+ symbol2
42602
+ );
42603
+ result.memories = rows.map((r) => ({
42604
+ nodeId: r.id,
42605
+ nodeType: r.node_type,
42606
+ label: r.label,
42607
+ qualityScore: r.quality_score,
42608
+ edgeWeight: r.weight,
42609
+ matchStrategy: r.provenance?.replace("auto:", "") ?? "manual"
42610
+ }));
42611
+ } catch (err) {
42612
+ console.warn("[graph-memory-bridge] queryMemoriesForCode failed:", err);
42613
+ }
42614
+ return result;
42615
+ }
42616
+ async function queryCodeForMemory(projectRoot, memoryId) {
42617
+ const result = { brainNodeId: memoryId, codeNodes: [] };
42618
+ try {
42619
+ await getBrainDb(projectRoot);
42620
+ const brainNative = getBrainNativeDb();
42621
+ await getNexusDb();
42622
+ const nexusNative = getNexusNativeDb();
42623
+ if (!brainNative || !nexusNative) return result;
42624
+ const brainEdges = typedAll(
42625
+ brainNative.prepare(`
42626
+ SELECT to_id, weight, provenance
42627
+ FROM brain_page_edges
42628
+ WHERE from_id = ?
42629
+ AND edge_type = 'code_reference'
42630
+ ORDER BY weight DESC
42631
+ LIMIT 50
42632
+ `),
42633
+ memoryId
42634
+ );
42635
+ if (brainEdges.length === 0) return result;
42636
+ for (const edge of brainEdges) {
42637
+ const nexusNode = nexusNative.prepare("SELECT id, label, file_path, kind FROM nexus_nodes WHERE id = ? LIMIT 1").get(edge.to_id);
42638
+ if (nexusNode) {
42639
+ result.codeNodes.push({
42640
+ nexusNodeId: nexusNode.id,
42641
+ label: nexusNode.label,
42642
+ filePath: nexusNode.file_path,
42643
+ kind: nexusNode.kind,
42644
+ edgeWeight: edge.weight,
42645
+ matchStrategy: edge.provenance?.replace("auto:", "") ?? "manual"
42646
+ });
42647
+ }
42648
+ }
42649
+ } catch (err) {
42650
+ console.warn("[graph-memory-bridge] queryCodeForMemory failed:", err);
42651
+ }
42652
+ return result;
42653
+ }
42654
+ async function listCodeLinks(projectRoot, limit = 100) {
42655
+ const entries = [];
42656
+ try {
42657
+ await getBrainDb(projectRoot);
42658
+ const brainNative = getBrainNativeDb();
42659
+ await getNexusDb();
42660
+ const nexusNative = getNexusNativeDb();
42661
+ if (!brainNative || !nexusNative) return entries;
42662
+ const rows = typedAll(
42663
+ brainNative.prepare(`
42664
+ SELECT e.from_id, e.to_id, e.weight, e.created_at,
42665
+ n.node_type, n.label
42666
+ FROM brain_page_edges e
42667
+ JOIN brain_page_nodes n ON n.id = e.from_id
42668
+ WHERE e.edge_type = 'code_reference'
42669
+ ORDER BY e.weight DESC, e.created_at DESC
42670
+ LIMIT ?
42671
+ `),
42672
+ limit
42673
+ );
42674
+ for (const row of rows) {
42675
+ const nexusNode = nexusNative.prepare("SELECT id, label, file_path, kind FROM nexus_nodes WHERE id = ? LIMIT 1").get(row.to_id);
42676
+ entries.push({
42677
+ brainNodeId: row.from_id,
42678
+ brainNodeType: row.node_type,
42679
+ brainNodeLabel: row.label,
42680
+ nexusNodeId: row.to_id,
42681
+ nexusNodeLabel: nexusNode?.label ?? row.to_id,
42682
+ filePath: nexusNode?.file_path ?? null,
42683
+ kind: nexusNode?.kind ?? "unknown",
42684
+ weight: row.weight,
42685
+ createdAt: row.created_at
42686
+ });
42687
+ }
42688
+ } catch (err) {
42689
+ console.warn("[graph-memory-bridge] listCodeLinks failed:", err);
42690
+ }
42691
+ return entries;
42692
+ }
42693
+ var FILE_PATH_PATTERN, SYMBOL_PATTERN, SYMBOL_STOP_WORDS;
42694
+ var init_graph_memory_bridge = __esm({
42695
+ "packages/core/src/memory/graph-memory-bridge.ts"() {
42696
+ "use strict";
42697
+ init_brain_schema();
42698
+ init_brain_sqlite();
42699
+ init_nexus_sqlite();
42700
+ init_typed_query();
42701
+ FILE_PATH_PATTERN = /(?:^|\s|['"`(])([a-zA-Z0-9_\-./]+\.(?:ts|tsx|js|jsx|rs|go|py|mjs|cjs))(?:$|\s|['"`)])/g;
42702
+ SYMBOL_PATTERN = /\b([a-zA-Z_][a-zA-Z0-9_]*(?:[A-Z][a-zA-Z0-9_]*)+|[a-zA-Z_]{4,}[a-zA-Z0-9_]*)\b/g;
42703
+ SYMBOL_STOP_WORDS = /* @__PURE__ */ new Set([
42704
+ "true",
42705
+ "false",
42706
+ "null",
42707
+ "undefined",
42708
+ "const",
42709
+ "async",
42710
+ "await",
42711
+ "return",
42712
+ "export",
42713
+ "import",
42714
+ "from",
42715
+ "type",
42716
+ "interface",
42717
+ "function",
42718
+ "class",
42719
+ "this",
42720
+ "super",
42721
+ "extends",
42722
+ "implements",
42723
+ "with",
42724
+ "that",
42725
+ "then",
42726
+ "when",
42727
+ "have",
42728
+ "been",
42729
+ "will",
42730
+ "should",
42731
+ "could",
42732
+ "would",
42733
+ "error",
42734
+ "result",
42735
+ "value",
42736
+ "data",
42737
+ "info",
42738
+ "note",
42739
+ "todo",
42740
+ "done",
42741
+ "fail",
42742
+ "pass"
42743
+ ]);
42744
+ }
42745
+ });
42746
+
42363
42747
  // packages/core/src/memory/brain-lifecycle.ts
42364
42748
  var brain_lifecycle_exports = {};
42365
42749
  __export(brain_lifecycle_exports, {
@@ -42659,6 +43043,13 @@ async function runConsolidation(projectRoot) {
42659
43043
  } catch (err) {
42660
43044
  console.warn("[consolidation] Step 7 summary generation failed:", err);
42661
43045
  }
43046
+ try {
43047
+ const { autoLinkMemories: autoLinkMemories2 } = await Promise.resolve().then(() => (init_graph_memory_bridge(), graph_memory_bridge_exports));
43048
+ const bridgeResult = await autoLinkMemories2(projectRoot);
43049
+ result.graphLinksCreated = bridgeResult.linked;
43050
+ } catch (err) {
43051
+ console.warn("[consolidation] Step 8 graph memory bridge failed:", err);
43052
+ }
42662
43053
  return result;
42663
43054
  }
42664
43055
  async function deduplicateByEmbedding(projectRoot) {
@@ -52171,6 +52562,19 @@ async function completeTask(options, cwd, accessor) {
52171
52562
  })()
52172
52563
  ).catch(() => {
52173
52564
  });
52565
+ try {
52566
+ const { hooks: hooks2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
52567
+ await hooks2.dispatch("PostToolUse", cwd ?? process.cwd(), {
52568
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
52569
+ taskId: options.taskId,
52570
+ taskTitle: task.title,
52571
+ previousStatus: before.status,
52572
+ newStatus: "done",
52573
+ unblockedCount: unblockedTasks.length
52574
+ }).catch(() => {
52575
+ });
52576
+ } catch {
52577
+ }
52174
52578
  return {
52175
52579
  task,
52176
52580
  ...autoCompleted.length > 0 && { autoCompleted },