@cachly-dev/mcp-server 0.9.14 → 0.9.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cachly-dev/mcp-server",
3
- "version": "0.9.14",
3
+ "version": "0.9.16",
4
4
  "mcpName": "io.github.cachly-dev/cachly-mcp",
5
5
  "description": "Your AI forgets everything between sessions. cachly fixes that permanently. A causal brain that learns WHY things break — built from every bug fix, git commit, and CI run, without any explicit calls. Arrives pre-briefed each session. Predicts failures before they happen. Never re-researches the same problem. 63 MCP tools · Claude Code · Cursor · GitHub Copilot · Windsurf · Free tier · EU servers.",
6
6
  "type": "module",
package/src/index.ts CHANGED
@@ -4032,6 +4032,27 @@ const TOOLS = [
4032
4032
  required: ['instance_id'],
4033
4033
  },
4034
4034
  },
4035
+ {
4036
+ name: 'brain_federate',
4037
+ description:
4038
+ 'FedBrain Layer 6 — Private org knowledge transfer: copy CKG edges + lessons from a source brain ' +
4039
+ 'into your brain for a specific domain (e.g. "billing", "auth", "deploy"). ' +
4040
+ 'The new hire use case: one command gives you the senior engineer\'s 5 years of typed, confidence-weighted ' +
4041
+ 'knowledge in your domain. Unlike syndicate_search (global, anonymous), brain_federate is org-private — ' +
4042
+ 'both brains must be in the same Cachly org, or the source instance_id must be explicitly shared. ' +
4043
+ 'Example: brain_federate(source="prod-brain-id", domain="billing", min_confidence=0.6)',
4044
+ inputSchema: {
4045
+ type: 'object',
4046
+ properties: {
4047
+ instance_id: { type: 'string', description: 'Your brain instance ID (destination)' },
4048
+ source: { type: 'string', description: 'Source brain instance ID to federate from' },
4049
+ domain: { type: 'string', description: 'Domain to transfer, e.g. "billing", "auth", "deploy", "infra". Use "*" for all domains.' },
4050
+ min_confidence: { type: 'number', description: 'Minimum edge confidence to transfer (default: 0.6)' },
4051
+ dry_run: { type: 'boolean', description: 'Preview what would be transferred without writing (default: false)' },
4052
+ },
4053
+ required: ['instance_id', 'source', 'domain'],
4054
+ },
4055
+ },
4035
4056
  {
4036
4057
  name: 'crystal_view',
4037
4058
  description:
@@ -5302,6 +5323,8 @@ async function handleTool(name: string, args: Record<string, unknown>): Promise<
5302
5323
  // Store conflict marker
5303
5324
  const conflictKey = `cachly:ckg:conflict:${conceptId}`;
5304
5325
  await redis.set(conflictKey, JSON.stringify({ topic, detected_at: new Date().toISOString(), fix_confidence: existEdge.confidence, fix_trials: existEdge.trials, failure_outcome: outcome }), 'EX', 60 * 60 * 24 * 90);
5326
+ // Auto-trigger MADC deliberation in background — never blocks learn_from_attempts
5327
+ handleTool('madc_deliberate', { instance_id, topic }).catch(() => undefined);
5305
5328
  }
5306
5329
  }
5307
5330
  }
@@ -5918,6 +5941,34 @@ async function handleTool(name: string, args: Record<string, unknown>): Promise<
5918
5941
  }
5919
5942
  } catch { /* non-critical */ }
5920
5943
 
5944
+ // ── Layer 7 MCM: Blind Spot Detection ────────────────────────────────────
5945
+ // If the focus mentions a domain that has no CKG node → surface blind spot
5946
+ if (focus && focus.length > 3) {
5947
+ try {
5948
+ const focusTokens = focus.toLowerCase().replace(/[^a-z0-9\s:_-]/g, ' ').split(/\s+/).filter(t => t.length > 3);
5949
+ const blindSpots: string[] = [];
5950
+ for (const token of focusTokens.slice(0, 6)) {
5951
+ const nodeExists = await redis.exists(`cachly:ckg:node:${token}`);
5952
+ if (!nodeExists) {
5953
+ // Check if any node starts with this token (prefix match)
5954
+ const prefixKeys: string[] = [];
5955
+ const psStream = redis.scanStream({ match: `cachly:ckg:node:${token}*`, count: 10 });
5956
+ await new Promise<void>((res, rej) => { psStream.on('data', (b: string[]) => prefixKeys.push(...b)); psStream.on('end', res); psStream.on('error', rej); });
5957
+ if (prefixKeys.length === 0) blindSpots.push(token);
5958
+ }
5959
+ }
5960
+ if (blindSpots.length > 0) {
5961
+ lines.push(`🔭 **Blind spots detected for this focus:**`);
5962
+ for (const bs of blindSpots.slice(0, 3)) {
5963
+ lines.push(` ⬜ \`${bs}\` — no CKG knowledge. Suggestions:`);
5964
+ lines.push(` • \`brain_from_git(instance_id="...", concept="${bs}")\` — bootstrap from commits`);
5965
+ lines.push(` • \`fedbrain_search(query="${bs}")\` — search global commons`);
5966
+ }
5967
+ lines.push('');
5968
+ }
5969
+ } catch { /* non-critical */ }
5970
+ }
5971
+
5921
5972
  if (focusLessons.length > 0) {
5922
5973
  lines.push(`🎯 **Relevant for "${focus}":**`);
5923
5974
  for (const l of focusLessons.slice(0, 4)) {
@@ -6082,6 +6133,111 @@ async function handleTool(name: string, args: Record<string, unknown>): Promise<
6082
6133
  }
6083
6134
  } catch { /* non-critical */ }
6084
6135
 
6136
+ // ── 🔮 PPE: Predictive Pre-fetch — CKG-powered risk detection ────────────
6137
+ // Layer 4: Before starting any work, scan the CKG for nodes matching focus
6138
+ // tokens and traverse causal edges to surface predicted failure points inline.
6139
+ // This is the PPE "pre-fetch" that was previously only available via brain_predict.
6140
+ if (focus && focus.length > 3) {
6141
+ try {
6142
+ const ppeFocusTokens = focus.toLowerCase().replace(/[^a-z0-9\s\-_:]/g, ' ').split(/\s+/).filter(t => t.length > 2).slice(0, 5);
6143
+ type PPEPrediction = { concept: string; edgeType: string; target: string; confidence: number; lesson?: { what_worked?: string; topic: string } };
6144
+ const ppePredictions: PPEPrediction[] = [];
6145
+
6146
+ for (const token of ppeFocusTokens) {
6147
+ const nodeKeys: string[] = [];
6148
+ const nStream = redis.scanStream({ match: `cachly:ckg:node:*${token}*`, count: 20 });
6149
+ await new Promise<void>((res, rej) => { nStream.on('data', (b: string[]) => nodeKeys.push(...b)); nStream.on('end', res); nStream.on('error', rej); });
6150
+
6151
+ for (const nk of nodeKeys.slice(0, 3)) {
6152
+ const nodeRaw = await redis.get(nk);
6153
+ if (!nodeRaw) continue;
6154
+ const node: CKGNode = JSON.parse(nodeRaw);
6155
+ const edgeKeys = await redis.smembers(`cachly:ckg:idx:from:${node.id}`);
6156
+ for (const ek of edgeKeys.slice(0, 15)) {
6157
+ const edgeRaw = await redis.get(ek);
6158
+ if (!edgeRaw) continue;
6159
+ const edge: CKGEdge = JSON.parse(edgeRaw);
6160
+ if (edge.edgeType !== 'causes' && edge.edgeType !== 'co-occurs' && edge.edgeType !== 'fixes') continue;
6161
+ if (edge.confidence < 0.35) continue;
6162
+ // For "fixes" edges, the lesson is on the "from" node (fix for "to")
6163
+ // For "causes" edges, target is the failure mode
6164
+ const lessonKey = edge.edgeType === 'fixes' ? `cachly:lesson:best:${edge.from}` : `cachly:lesson:best:${edge.to}`;
6165
+ const lessonRaw = await redis.get(lessonKey);
6166
+ const lesson = lessonRaw ? JSON.parse(lessonRaw) : undefined;
6167
+ ppePredictions.push({ concept: node.id, edgeType: edge.edgeType, target: edge.to, confidence: edge.confidence, lesson });
6168
+ }
6169
+ }
6170
+ }
6171
+
6172
+ const ppeSeen = new Set<string>();
6173
+ const ppeUniq = ppePredictions
6174
+ .filter(p => { const k = `${p.concept}:${p.target}`; if (ppeSeen.has(k)) return false; ppeSeen.add(k); return true; })
6175
+ .sort((a, b) => b.confidence - a.confidence)
6176
+ .slice(0, 4);
6177
+
6178
+ if (ppeUniq.length > 0) {
6179
+ lines.push(`🔮 **Predicted risks for "${focus}"** (PPE pre-fetch):`);
6180
+ for (const p of ppeUniq) {
6181
+ const confPct = Math.round(p.confidence * 100);
6182
+ const icon = p.edgeType === 'causes' ? '⚡' : p.edgeType === 'fixes' ? '🔧' : '🔄';
6183
+ lines.push(` ${icon} **${confPct}%** \`${p.concept}\` ${p.edgeType} \`${p.target}\``);
6184
+ if (p.lesson?.what_worked) lines.push(` ✅ ${(p.lesson.what_worked as string).slice(0, 110)}`);
6185
+ }
6186
+ lines.push(` _Full analysis: \`brain_predict(context="${focus}")\`_`);
6187
+ lines.push('');
6188
+ }
6189
+ } catch { /* non-critical — never block session start */ }
6190
+ }
6191
+
6192
+ // ── 📐 MCM Confidence Calibration — 30-day accuracy pass ─────────────────
6193
+ // Layer 7: Periodically check if high-confidence lessons are actually reliable.
6194
+ // If last calibration was >30 days ago (or never), run a quick pass.
6195
+ // Measures: of recalled lessons with confidence > 0.85, what % had outcome=success?
6196
+ try {
6197
+ const calRaw = await redis.get('cachly:mcm:calibration:last');
6198
+ const lastCalMs = calRaw ? JSON.parse(calRaw).ts : 0;
6199
+ const daysSinceCal = (Date.now() - lastCalMs) / 86_400_000;
6200
+ if (daysSinceCal >= 30 && lessons.length >= 5) {
6201
+ // Quick calibration pass on recalled lessons (recall_count > 0, outcome=success)
6202
+ const recalledSuccess = lessons.filter(l => l.outcome === 'success' && (l.recall_count ?? 0) > 0);
6203
+ const recalledAll = lessons.filter(l => (l.recall_count ?? 0) > 0);
6204
+ if (recalledAll.length >= 3) {
6205
+ const precision = recalledAll.length > 0 ? recalledSuccess.length / recalledAll.length : 1;
6206
+ const lowPrecisionDomains: string[] = [];
6207
+ // Per-domain breakdown
6208
+ const domCalMap = new Map<string, { success: number; total: number }>();
6209
+ for (const l of recalledAll) {
6210
+ const dom = l.topic.split(':')[0] ?? 'other';
6211
+ if (!domCalMap.has(dom)) domCalMap.set(dom, { success: 0, total: 0 });
6212
+ const d = domCalMap.get(dom)!;
6213
+ d.total++;
6214
+ if (l.outcome === 'success') d.success++;
6215
+ }
6216
+ for (const [dom, d] of domCalMap) {
6217
+ if (d.total >= 2 && d.success / d.total < 0.6) lowPrecisionDomains.push(dom);
6218
+ }
6219
+ // Save calibration result
6220
+ await redis.set('cachly:mcm:calibration:last', JSON.stringify({
6221
+ ts: Date.now(),
6222
+ precision: precision,
6223
+ recalled: recalledAll.length,
6224
+ low_precision_domains: lowPrecisionDomains,
6225
+ }));
6226
+ if (lowPrecisionDomains.length > 0 || precision < 0.7) {
6227
+ lines.push(`📐 **MCM Calibration** (30-day pass — ${recalledAll.length} recalled lessons):`);
6228
+ lines.push(` Overall precision: **${(precision * 100).toFixed(0)}%** recalled lessons actually worked`);
6229
+ if (lowPrecisionDomains.length > 0) {
6230
+ lines.push(` ⚠️ Low-precision domains: ${lowPrecisionDomains.map(d => `\`${d}\``).join(', ')} — consider revisiting these lessons`);
6231
+ }
6232
+ lines.push(` 💡 Use \`learn_from_attempts\` to update stale lessons and improve accuracy.`);
6233
+ lines.push('');
6234
+ }
6235
+ }
6236
+ // Even if no issues, stamp the date so we don't re-check for 30d
6237
+ await redis.set('cachly:mcm:calibration:last', JSON.stringify({ ts: Date.now(), precision: 1, recalled: 0 }), 'EX', 35 * 86400);
6238
+ }
6239
+ } catch { /* non-critical */ }
6240
+
6085
6241
  // ── 🌍 Knowledge Commons — community stats banner ───────────────────────
6086
6242
  // Fetch syndication stats and show a 1-liner: total lessons + confirms + weekly growth.
6087
6243
  // Non-fatal: never blocks session start if the API call fails.
@@ -8071,8 +8227,51 @@ async function handleBulkLockStream(name: string, args: Record<string, unknown>)
8071
8227
  ``,
8072
8228
  `🔍 **Active** (recalled at least once): ${recalled.length}`,
8073
8229
  ``,
8074
- `💡 Run \`memory_consolidate\` to merge duplicates · \`knowledge_decay\` to see confidence scores.`,
8075
8230
  ].filter(s => s !== '');
8231
+
8232
+ // ── 10X brain_diff extensions ──────────────────────────────────────────
8233
+ // 1. Contested → Established (resolution nodes created in window)
8234
+ const resolutionKeys: string[] = [];
8235
+ const rsStream = redis.scanStream({ match: 'cachly:ckg:node:resolution-*', count: 100 });
8236
+ await new Promise<void>((res, rej) => { rsStream.on('data', (b: string[]) => resolutionKeys.push(...b)); rsStream.on('end', res); rsStream.on('error', rej); });
8237
+ const recentResolutions: Array<{ topic: string; resolution: string; ts: string }> = [];
8238
+ for (const rk of resolutionKeys) {
8239
+ const rr = await redis.get(rk);
8240
+ if (!rr) continue;
8241
+ try {
8242
+ const rn = JSON.parse(rr) as { topic?: string; resolution?: string; ts?: string };
8243
+ if (rn.ts && new Date(rn.ts).getTime() >= sinceMs) recentResolutions.push({ topic: rn.topic ?? rk, resolution: rn.resolution ?? 'unknown', ts: rn.ts });
8244
+ } catch { /* skip */ }
8245
+ }
8246
+ if (recentResolutions.length > 0) {
8247
+ lines.push(`🗳️ **MADC Resolutions** (${recentResolutions.length} contested beliefs resolved):`);
8248
+ for (const r of recentResolutions.slice(0, 5)) {
8249
+ const rIcon = r.resolution === 'unanimous_success' ? '✅' : r.resolution === 'unanimous_failure' ? '❌' : '⚠️';
8250
+ lines.push(` ${rIcon} \`${r.topic}\` → ${r.resolution}`);
8251
+ }
8252
+ lines.push('');
8253
+ }
8254
+
8255
+ // 2. New domains bootstrapped (domains in added lessons that weren't in older lessons)
8256
+ const existingDomains = new Set(updated.concat(recalled).map(l => l.topic.split(':')[0]));
8257
+ const newDomains = [...new Set(added.map(l => l.topic.split(':')[0]))].filter(d => !existingDomains.has(d));
8258
+ if (newDomains.length > 0) {
8259
+ lines.push(`🌱 **New domains bootstrapped:** ${newDomains.map(d => `\`${d}\``).join(', ')}`, '');
8260
+ }
8261
+
8262
+ // 3. FedBrain transfers received in window
8263
+ const fedHistRaw = await redis.lrange('cachly:fedbrain:federations', -20, -1);
8264
+ const recentFeds = fedHistRaw.map(r => { try { return JSON.parse(r) as { source: string; domain: string; transferred_at: string; nodes: number; edges: number }; } catch { return null; } })
8265
+ .filter(f => f && new Date(f!.transferred_at).getTime() >= sinceMs) as Array<{ source: string; domain: string; transferred_at: string; nodes: number; edges: number }>;
8266
+ if (recentFeds.length > 0) {
8267
+ lines.push(`🧠 **FedBrain transfers received (${recentFeds.length}):**`);
8268
+ for (const f of recentFeds.slice(0, 3)) {
8269
+ lines.push(` 📥 domain \`${f.domain}\` from \`${f.source.slice(0, 16)}…\` — ${f.nodes} nodes, ${f.edges} edges`);
8270
+ }
8271
+ lines.push('');
8272
+ }
8273
+
8274
+ lines.push(`💡 Run \`memory_consolidate\` to merge duplicates · \`knowledge_decay\` to see confidence scores.`);
8076
8275
  return lines.join('\n');
8077
8276
  }
8078
8277
 
@@ -8975,9 +9174,34 @@ smart_recall(
8975
9174
  };
8976
9175
  await redis.set(`cachly:ckg:node:${resNodeId}`, JSON.stringify(resNode));
8977
9176
 
8978
- // Write contradicts edge if contested
9177
+ // Write contradicts edge if contested; decay loser confidence to 0.1 if unanimous
8979
9178
  if (resolution === 'contested') {
8980
9179
  await ckgUpdateEdge(redis, ckgSlug(topic), 'contradicts', resNodeId, false);
9180
+ } else {
9181
+ // Unanimous — demote the losing side's edges to near-zero confidence
9182
+ const loserOutcome = resolution === 'unanimous_success' ? 'failure' : 'success';
9183
+ const loserLessons = (loserOutcome === 'failure' ? failureLessons : successLessons);
9184
+ if (loserLessons.length > 0) {
9185
+ // Decay all 'fixes' edges from this concept that contradict the resolution
9186
+ const fromKeys = await redis.smembers(`cachly:ckg:idx:from:${ckgSlug(topic)}`);
9187
+ for (const fk of fromKeys) {
9188
+ const er = await redis.get(fk);
9189
+ if (!er) continue;
9190
+ try {
9191
+ const edge: CKGEdge = JSON.parse(er);
9192
+ if (edge.edgeType === 'fixes' && edge.confidence > 0.15) {
9193
+ if (resolution === 'unanimous_failure') {
9194
+ // Fix was wrong — decay to 0.1
9195
+ edge.confidence = 0.1;
9196
+ edge.last_updated = new Date().toISOString();
9197
+ await redis.set(fk, JSON.stringify(edge));
9198
+ }
9199
+ }
9200
+ } catch { /* skip corrupt edges */ }
9201
+ }
9202
+ }
9203
+ // Remove the conflict marker — deliberation resolved it
9204
+ await redis.del(`cachly:ckg:conflict:${ckgSlug(topic)}`);
8981
9205
  }
8982
9206
 
8983
9207
  const lines = [
@@ -9436,6 +9660,118 @@ smart_recall(
9436
9660
  return lines.join('\n');
9437
9661
  }
9438
9662
 
9663
+ // ── Layer 6: FedBrain — brain_federate ───────────────────────────────────
9664
+ case 'brain_federate': {
9665
+ const { instance_id, source, domain, min_confidence = 0.6, dry_run = false } = args as {
9666
+ instance_id: string; source: string; domain: string;
9667
+ min_confidence?: number; dry_run?: boolean;
9668
+ };
9669
+ if (instance_id === source) return `❌ Source and destination cannot be the same brain.`;
9670
+
9671
+ const destRedis = await getConnection(instance_id);
9672
+ const srcRedis = await getConnection(source);
9673
+
9674
+ const domainPattern = domain === '*' ? 'cachly:ckg:node:*' : `cachly:ckg:node:${domain}*`;
9675
+
9676
+ // Scan source CKG nodes matching the domain
9677
+ const nodeKeys: string[] = [];
9678
+ const nStream = srcRedis.scanStream({ match: domainPattern, count: 100 });
9679
+ await new Promise<void>((res, rej) => { nStream.on('data', (b: string[]) => nodeKeys.push(...b)); nStream.on('end', res); nStream.on('error', rej); });
9680
+
9681
+ if (nodeKeys.length === 0) {
9682
+ return [
9683
+ `🧠 **brain_federate: "${domain}"**`, '',
9684
+ `No CKG nodes found in source brain for domain \`${domain}\`.`,
9685
+ `The source brain may not have knowledge in this area yet.`,
9686
+ `Try: \`fedbrain_search(query="${domain}")\` to find global commons knowledge instead.`,
9687
+ ].join('\n');
9688
+ }
9689
+
9690
+ // Transfer nodes + their outgoing edges
9691
+ let nodesTransferred = 0;
9692
+ let edgesTransferred = 0;
9693
+ let lessonsTransferred = 0;
9694
+ let skippedLowConf = 0;
9695
+ const transferLog: string[] = [];
9696
+
9697
+ for (const nk of nodeKeys) {
9698
+ const nodeRaw = await srcRedis.get(nk);
9699
+ if (!nodeRaw) continue;
9700
+ let node: CKGNode;
9701
+ try { node = JSON.parse(nodeRaw); } catch { continue; }
9702
+
9703
+ if (!dry_run) await destRedis.set(nk, nodeRaw);
9704
+ nodesTransferred++;
9705
+
9706
+ // Transfer outgoing edges for this node
9707
+ const edgeKeys = await srcRedis.smembers(`cachly:ckg:idx:from:${node.id}`);
9708
+ for (const ek of edgeKeys) {
9709
+ const edgeRaw = await srcRedis.get(ek);
9710
+ if (!edgeRaw) continue;
9711
+ let edge: CKGEdge;
9712
+ try { edge = JSON.parse(edgeRaw); } catch { continue; }
9713
+ if (edge.confidence < (min_confidence as number)) { skippedLowConf++; continue; }
9714
+ if (!dry_run) {
9715
+ await destRedis.set(ek, edgeRaw);
9716
+ await destRedis.sadd(`cachly:ckg:idx:from:${edge.from}`, ek);
9717
+ await destRedis.sadd(`cachly:ckg:idx:to:${edge.to}`, ek);
9718
+ }
9719
+ edgesTransferred++;
9720
+ }
9721
+
9722
+ // Transfer best-lesson for the same topic slug
9723
+ const lessonKey = `cachly:lesson:best:${node.id}`;
9724
+ const lessonRaw = await srcRedis.get(lessonKey);
9725
+ if (lessonRaw) {
9726
+ if (!dry_run) await destRedis.set(lessonKey, lessonRaw);
9727
+ lessonsTransferred++;
9728
+ if (transferLog.length < 8) {
9729
+ try {
9730
+ const l = JSON.parse(lessonRaw) as { topic: string; outcome: string; what_worked?: string };
9731
+ const icon = l.outcome === 'success' ? '✅' : l.outcome === 'failure' ? '❌' : '⚠️';
9732
+ transferLog.push(` ${icon} \`${l.topic}\` — ${(l.what_worked ?? '').slice(0, 80)}`);
9733
+ } catch { /* skip */ }
9734
+ }
9735
+ }
9736
+ }
9737
+
9738
+ // Record federation provenance
9739
+ if (!dry_run) {
9740
+ const provEntry = JSON.stringify({
9741
+ source, domain, transferred_at: new Date().toISOString(),
9742
+ nodes: nodesTransferred, edges: edgesTransferred, lessons: lessonsTransferred,
9743
+ });
9744
+ await destRedis.rpush('cachly:fedbrain:federations', provEntry);
9745
+ await destRedis.ltrim('cachly:fedbrain:federations', -50, -1);
9746
+ }
9747
+
9748
+ const dryTag = dry_run ? ' (DRY RUN — no writes)' : '';
9749
+ const lines = [
9750
+ `🧠 **brain_federate: "${domain}"**${dryTag}`, '',
9751
+ `📤 Source: \`${source}\``,
9752
+ `📥 Destination: \`${instance_id}\``,
9753
+ `🔍 Domain filter: \`${domain}\` | min_confidence: ${min_confidence}`,
9754
+ '',
9755
+ `### Transfer Summary`,
9756
+ ` 🕸️ CKG nodes: ${nodesTransferred}`,
9757
+ ` 🔗 CKG edges: ${edgesTransferred} (${skippedLowConf} skipped, confidence < ${min_confidence})`,
9758
+ ` 📚 Lessons: ${lessonsTransferred}`,
9759
+ '',
9760
+ ];
9761
+ if (transferLog.length > 0) {
9762
+ lines.push(`### Sample lessons transferred:`, ...transferLog);
9763
+ if (lessonsTransferred > transferLog.length) lines.push(` _... and ${lessonsTransferred - transferLog.length} more_`);
9764
+ lines.push('');
9765
+ }
9766
+ if (dry_run) {
9767
+ lines.push(`💡 Run without \`dry_run: true\` to apply the transfer.`);
9768
+ } else {
9769
+ lines.push(`✅ Transfer complete. Your brain now has the \`${domain}\` knowledge from \`${source}\`.`);
9770
+ lines.push(`🔍 Explore: \`ckg_inspect(concept="${domain}")\` | \`recall_best_solution(topic="${domain}:...")\``);
9771
+ }
9772
+ return lines.join('\n');
9773
+ }
9774
+
9439
9775
  // ── crystal_view ──────────────────────────────────────────────────────────
9440
9776
  case 'crystal_view': {
9441
9777
  const { instance_id, show_raw = false } = args as { instance_id: string; show_raw?: boolean };