@cachly-dev/mcp-server 0.10.62 → 0.10.65
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/BENCH.md +36 -14
- package/CHANGELOG.md +49 -0
- package/PROGRESS.md +141 -0
- package/README.md +210 -180
- package/VISION_10X.md +133 -0
- package/dist/src/__tests__/brain-flow.test.js +72 -1
- package/dist/src/__tests__/brain-flow.test.js.map +1 -1
- package/dist/src/__tests__/rerank.test.js +10 -0
- package/dist/src/__tests__/rerank.test.js.map +1 -1
- package/dist/src/__tests__/utils.test.d.ts +1 -0
- package/dist/src/__tests__/utils.test.js +83 -0
- package/dist/src/__tests__/utils.test.js.map +1 -0
- package/dist/src/bench/cachly-bench.d.ts +5 -1
- package/dist/src/bench/cachly-bench.js +60 -19
- package/dist/src/bench/cachly-bench.js.map +1 -1
- package/dist/src/handlers/brain.js +106 -60
- package/dist/src/handlers/brain.js.map +1 -1
- package/dist/src/handlers/fedbrain.js +4 -2
- package/dist/src/handlers/fedbrain.js.map +1 -1
- package/dist/src/index.js +3 -3
- package/dist/src/tools.d.ts +17 -0
- package/dist/src/tools.js +16 -0
- package/dist/src/tools.js.map +1 -1
- package/dist/src/utils.d.ts +33 -0
- package/dist/src/utils.js +76 -0
- package/dist/src/utils.js.map +1 -1
- package/package.json +2 -2
- package/server.json +3 -3
- package/src/__tests__/brain-flow.test.ts +82 -1
- package/src/__tests__/rerank.test.ts +11 -0
- package/src/__tests__/utils.test.ts +81 -0
- package/src/bench/cachly-bench.ts +69 -23
- package/src/handlers/brain.ts +118 -57
- package/src/handlers/fedbrain.ts +3 -2
- package/src/index.ts +3 -3
- package/src/tools.ts +17 -0
- package/src/utils.ts +80 -0
|
@@ -23,10 +23,14 @@ export interface BenchMetrics {
|
|
|
23
23
|
ndcgAt5: number;
|
|
24
24
|
}
|
|
25
25
|
export interface BenchResult {
|
|
26
|
+
/** Flat-file memory simulation: naive term-overlap, no IDF, no quality signal. */
|
|
27
|
+
flatfile: BenchMetrics;
|
|
26
28
|
baseline: BenchMetrics;
|
|
27
29
|
cachly: BenchMetrics;
|
|
28
|
-
/** Relative lift
|
|
30
|
+
/** Relative lift of cachly vs the BM25 baseline. */
|
|
29
31
|
lift: BenchMetrics;
|
|
32
|
+
/** Relative lift of cachly vs a flat-file memory (the head-to-head that matters). */
|
|
33
|
+
liftVsFlatfile: BenchMetrics;
|
|
30
34
|
queryCount: number;
|
|
31
35
|
corpusSize: number;
|
|
32
36
|
}
|
|
@@ -85,6 +85,32 @@ function ndcgAtK(ranked, relevant, k) {
|
|
|
85
85
|
}
|
|
86
86
|
return idcg === 0 ? 0 : dcg / idcg;
|
|
87
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Simulates how a flat-file memory (e.g. an LLM reading a `/memories` directory)
|
|
90
|
+
* actually surfaces knowledge: it has NO ranking engine. Practical retrieval is
|
|
91
|
+
* naive lexical overlap — count how many distinct query terms appear in the file's
|
|
92
|
+
* text — with NO inverse-document-frequency, NO length normalization, and crucially
|
|
93
|
+
* NO quality signal (a proven fix and a failed attempt are just text). Ties break by
|
|
94
|
+
* recency, mimicking "most recently edited note first". This is a fair, and honestly
|
|
95
|
+
* weaker, stand-in for "Claude reads its own memory files".
|
|
96
|
+
*/
|
|
97
|
+
function flatFileRank(lessons, query) {
|
|
98
|
+
const qTerms = new Set(query.toLowerCase().replace(/[^a-z0-9\s]/g, ' ').split(/\s+/).filter(t => t.length >= 3));
|
|
99
|
+
const scored = lessons.map(l => {
|
|
100
|
+
const blob = [l.topic, l.what_worked, l.what_failed ?? '', l.context ?? '', (l.tags ?? []).join(' ')]
|
|
101
|
+
.join(' ').toLowerCase();
|
|
102
|
+
let overlap = 0;
|
|
103
|
+
for (const t of qTerms)
|
|
104
|
+
if (blob.includes(t))
|
|
105
|
+
overlap++;
|
|
106
|
+
const recency = l.ts ? new Date(l.ts).getTime() : 0;
|
|
107
|
+
return { topic: l.topic, overlap, recency };
|
|
108
|
+
});
|
|
109
|
+
return scored
|
|
110
|
+
.filter(s => s.overlap > 0)
|
|
111
|
+
.sort((a, b) => (b.overlap - a.overlap) || (b.recency - a.recency))
|
|
112
|
+
.map(s => s.topic);
|
|
113
|
+
}
|
|
88
114
|
const matchTopic = (m) => m.key.replace(LESSON_PREFIX, '');
|
|
89
115
|
function mean(xs) {
|
|
90
116
|
return xs.length === 0 ? 0 : xs.reduce((a, b) => a + b, 0) / xs.length;
|
|
@@ -110,48 +136,63 @@ function scoreRanking(ranked, relevant) {
|
|
|
110
136
|
/** Run the benchmark over the fixture corpus. Pure-ish: no network, no real Redis. */
|
|
111
137
|
export async function runBenchmark() {
|
|
112
138
|
const redis = indexCorpus(BENCH_LESSONS);
|
|
139
|
+
const flatfileRows = [];
|
|
113
140
|
const baselineRows = [];
|
|
114
141
|
const cachlyRows = [];
|
|
115
142
|
for (const q of BENCH_QUERIES) {
|
|
116
143
|
const relevant = new Set(q.relevant);
|
|
117
|
-
//
|
|
144
|
+
// BM25 baseline + cachly share the same candidate set — isolates ranking quality.
|
|
118
145
|
const matches = await keywordSearch(redis, [`${LESSON_PREFIX}*`], q.query, 10);
|
|
119
146
|
const baselineRanked = matches.map(matchTopic);
|
|
120
147
|
const cachlyRanked = rerankByQuality(matches).map(matchTopic);
|
|
148
|
+
// Flat-file memory sees the whole corpus but has no ranking engine.
|
|
149
|
+
const flatfileRanked = flatFileRank(BENCH_LESSONS, q.query);
|
|
150
|
+
flatfileRows.push(scoreRanking(flatfileRanked, relevant));
|
|
121
151
|
baselineRows.push(scoreRanking(baselineRanked, relevant));
|
|
122
152
|
cachlyRows.push(scoreRanking(cachlyRanked, relevant));
|
|
123
153
|
}
|
|
154
|
+
const flatfile = aggregate(flatfileRows);
|
|
124
155
|
const baseline = aggregate(baselineRows);
|
|
125
156
|
const cachly = aggregate(cachlyRows);
|
|
126
157
|
const liftOf = (b, c) => (b === 0 ? (c > 0 ? 1 : 0) : (c - b) / b);
|
|
127
|
-
const
|
|
128
|
-
precisionAt1: liftOf(
|
|
129
|
-
precisionAt3: liftOf(
|
|
130
|
-
recallAt3: liftOf(
|
|
131
|
-
mrr: liftOf(
|
|
132
|
-
ndcgAt5: liftOf(
|
|
158
|
+
const liftBetween = (from) => ({
|
|
159
|
+
precisionAt1: liftOf(from.precisionAt1, cachly.precisionAt1),
|
|
160
|
+
precisionAt3: liftOf(from.precisionAt3, cachly.precisionAt3),
|
|
161
|
+
recallAt3: liftOf(from.recallAt3, cachly.recallAt3),
|
|
162
|
+
mrr: liftOf(from.mrr, cachly.mrr),
|
|
163
|
+
ndcgAt5: liftOf(from.ndcgAt5, cachly.ndcgAt5),
|
|
164
|
+
});
|
|
165
|
+
return {
|
|
166
|
+
flatfile, baseline, cachly,
|
|
167
|
+
lift: liftBetween(baseline),
|
|
168
|
+
liftVsFlatfile: liftBetween(flatfile),
|
|
169
|
+
queryCount: BENCH_QUERIES.length,
|
|
170
|
+
corpusSize: BENCH_LESSONS.length,
|
|
133
171
|
};
|
|
134
|
-
return { baseline, cachly, lift, queryCount: BENCH_QUERIES.length, corpusSize: BENCH_LESSONS.length };
|
|
135
172
|
}
|
|
136
173
|
// ── Reporting ──────────────────────────────────────────────────────────────────
|
|
137
174
|
const pct = (x) => `${(x * 100).toFixed(1)}%`;
|
|
138
175
|
const signedPct = (x) => `${x >= 0 ? '+' : ''}${(x * 100).toFixed(1)}%`;
|
|
139
176
|
export function formatReport(r) {
|
|
140
|
-
const row = (label, b, c,
|
|
177
|
+
const row = (label, f, b, c, lf) => ` ${label.padEnd(12)} ${pct(f).padStart(8)} ${pct(b).padStart(8)} ${pct(c).padStart(8)} ${signedPct(lf).padStart(8)}`;
|
|
141
178
|
return [
|
|
142
179
|
'',
|
|
143
|
-
'🧠 Cachly-Bench — recall quality
|
|
144
|
-
'
|
|
180
|
+
'🧠 Cachly-Bench — recall quality head-to-head',
|
|
181
|
+
'──────────────────────────────────────────────────────────────────────────',
|
|
145
182
|
` corpus: ${r.corpusSize} lessons · queries: ${r.queryCount}`,
|
|
183
|
+
' flat-file = naive term-overlap, no quality signal (≈ LLM reading memory files)',
|
|
184
|
+
' baseline = raw BM25+ keyword ranking',
|
|
185
|
+
' cachly = BM25+ followed by quality-aware reranking',
|
|
146
186
|
'',
|
|
147
|
-
` ${'metric'.padEnd(
|
|
148
|
-
row('Precision@1', r.baseline.precisionAt1, r.cachly.precisionAt1, r.
|
|
149
|
-
row('Precision@3', r.baseline.precisionAt3, r.cachly.precisionAt3, r.
|
|
150
|
-
row('Recall@3', r.baseline.recallAt3, r.cachly.recallAt3, r.
|
|
151
|
-
row('MRR', r.baseline.mrr, r.cachly.mrr, r.
|
|
152
|
-
row('nDCG@5', r.baseline.ndcgAt5, r.cachly.ndcgAt5, r.
|
|
153
|
-
'
|
|
154
|
-
`
|
|
187
|
+
` ${'metric'.padEnd(12)} ${'flatfile'.padStart(8)} ${'baseline'.padStart(8)} ${'cachly'.padStart(8)} ${'vs flat'.padStart(8)}`,
|
|
188
|
+
row('Precision@1', r.flatfile.precisionAt1, r.baseline.precisionAt1, r.cachly.precisionAt1, r.liftVsFlatfile.precisionAt1),
|
|
189
|
+
row('Precision@3', r.flatfile.precisionAt3, r.baseline.precisionAt3, r.cachly.precisionAt3, r.liftVsFlatfile.precisionAt3),
|
|
190
|
+
row('Recall@3', r.flatfile.recallAt3, r.baseline.recallAt3, r.cachly.recallAt3, r.liftVsFlatfile.recallAt3),
|
|
191
|
+
row('MRR', r.flatfile.mrr, r.baseline.mrr, r.cachly.mrr, r.liftVsFlatfile.mrr),
|
|
192
|
+
row('nDCG@5', r.flatfile.ndcgAt5, r.baseline.ndcgAt5, r.cachly.ndcgAt5, r.liftVsFlatfile.ndcgAt5),
|
|
193
|
+
'──────────────────────────────────────────────────────────────────────────',
|
|
194
|
+
` vs BM25 baseline : MRR ${signedPct(r.lift.mrr)} · Precision@1 ${signedPct(r.lift.precisionAt1)}`,
|
|
195
|
+
` vs flat-file mem : MRR ${signedPct(r.liftVsFlatfile.mrr)} · Precision@1 ${signedPct(r.liftVsFlatfile.precisionAt1)}`,
|
|
155
196
|
'',
|
|
156
197
|
].join('\n');
|
|
157
198
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cachly-bench.js","sourceRoot":"","sources":["../../../src/bench/cachly-bench.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cachly-bench.js","sourceRoot":"","sources":["../../../src/bench/cachly-bench.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import { calculateConfidence, confidenceBadge, STRUCTURED_TEMPLATES, CONFIDENCE_WARN_VALUE, CONFIDENCE_STALE_VALUE, CONFIDENCE_WARN_DAYS } from '../confidence.js';
|
|
3
3
|
import { ckgSlug, extractProblemConcept, ckgUpsertNode, ckgUpdateEdge, ckgUpsertPersonNode, ckgUpsertFileNode } from '../ckg.js';
|
|
4
|
-
import { safeJsonParse } from '../utils.js';
|
|
4
|
+
import { safeJsonParse, scanKeys } from '../utils.js';
|
|
5
5
|
import { keywordSearch, tokenize, splitMultiQuery, levenshtein, indexVocab as _indexVocab } from '../search.js';
|
|
6
6
|
import { rerankByQuality } from '../rerank.js';
|
|
7
7
|
import { computeEmbedding, hasEmbedProvider } from '../embeddings.js';
|
|
8
8
|
// ── Changelog (shown once per version in session_start) ──────────────────────
|
|
9
|
-
const MCP_VERSION = '0.10.
|
|
9
|
+
const MCP_VERSION = '0.10.65';
|
|
10
10
|
const WHATS_NEW = {
|
|
11
|
+
'0.10.64': [
|
|
12
|
+
`📈 **The three decisive metrics, now measurable**`,
|
|
13
|
+
` ⏱️ \`brain_metrics()\` — time-to-first-recall, recall-lift, team-knowledge-reuse in one view`,
|
|
14
|
+
` 👥 Cross-author reuse tracked: recall a teammate's lesson → counted + surfaced inline`,
|
|
15
|
+
` 🛡️ Stability: scans now capped + timed out (a huge keyspace can't hang the agent)`,
|
|
16
|
+
],
|
|
11
17
|
'0.10.61': [
|
|
12
18
|
`🎯 **Phase 3C: 100 MCP tools milestone — zero-setup knowledge graph**`,
|
|
13
19
|
` 🔄 \`brain_from_git\` now auto-builds Person+File nodes from git history (zero setup!)`,
|
|
@@ -69,7 +75,7 @@ export const BRAIN_TOOL_NAMES = new Set([
|
|
|
69
75
|
'learn_from_attempts', 'recall_best_solution', 'smart_recall',
|
|
70
76
|
'session_start', 'session_end', 'session_ping', 'session_handoff', 'auto_learn_session',
|
|
71
77
|
'brain_who_knows', 'brain_file_map', 'team_expertise_map',
|
|
72
|
-
'skill_gaps', 'brain_coverage',
|
|
78
|
+
'skill_gaps', 'brain_coverage', 'brain_metrics',
|
|
73
79
|
]);
|
|
74
80
|
export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
75
81
|
switch (name) {
|
|
@@ -201,6 +207,9 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
201
207
|
version: 3,
|
|
202
208
|
};
|
|
203
209
|
const lesson = JSON.stringify(lessonObj);
|
|
210
|
+
// Metric 1 (time-to-first-recall): mark the moment the Brain first gained
|
|
211
|
+
// knowledge. SET NX so only the very first learn wins. Fire-and-forget.
|
|
212
|
+
redis.set(`cachly:stats:born_at:${instance_id}`, ts, 'EX', 365 * 86400, 'NX').catch(() => { });
|
|
204
213
|
// Always append to the history list (audit log); keep last 100 entries, 90-day TTL
|
|
205
214
|
const listKey = `cachly:lessons:${topic}`;
|
|
206
215
|
await redis.rpush(listKey, lesson);
|
|
@@ -510,7 +519,7 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
510
519
|
return `🔍 **Partial matches for \`${topic}\`:**\n\n${results.join('\n\n')}`;
|
|
511
520
|
}
|
|
512
521
|
case 'smart_recall': {
|
|
513
|
-
const { instance_id, query, threshold = 0.78, } = args;
|
|
522
|
+
const { instance_id, query, threshold = 0.78, author: requester = '', } = args;
|
|
514
523
|
const redis = await getConnection(instance_id);
|
|
515
524
|
// ── Layer 1: Keyword search across ALL brain data (always works, no embedding) ──
|
|
516
525
|
const rawMatches = await keywordSearch(redis, ['cachly:ctx:*', 'cachly:lesson:best:*', 'cachly:idx:*'], query, 10);
|
|
@@ -519,6 +528,7 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
519
528
|
const kwMatches = rerankByQuality(rawMatches);
|
|
520
529
|
const savedHere = [];
|
|
521
530
|
const lessonMatches = kwMatches.filter(m => m.key.startsWith('cachly:lesson:best:'));
|
|
531
|
+
let crossAuthorThisCall = 0;
|
|
522
532
|
for (const m of lessonMatches.slice(0, 5)) {
|
|
523
533
|
const existing = await redis.get(m.key).catch(() => null);
|
|
524
534
|
if (existing) {
|
|
@@ -529,6 +539,15 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
529
539
|
const sev = lesson.severity;
|
|
530
540
|
const savedMins = sev === 'critical' ? 240 : sev === 'major' ? 60 : 30;
|
|
531
541
|
redis.incrbyfloat(`cachly:stats:time_saved_mins:${instance_id}`, savedMins).catch(() => { });
|
|
542
|
+
// Metric 3 (team-knowledge-reuse): a recall of a lesson authored by
|
|
543
|
+
// someone OTHER than the requester is cross-author reuse — the value
|
|
544
|
+
// only cachly delivers. Track total proven recalls + cross-author ones.
|
|
545
|
+
redis.incr(`cachly:stats:recalls_total:${instance_id}`).catch(() => { });
|
|
546
|
+
if (lesson.author && requester && lesson.author !== requester) {
|
|
547
|
+
crossAuthorThisCall++;
|
|
548
|
+
redis.incr(`cachly:stats:cross_author_recalls:${instance_id}`).catch(() => { });
|
|
549
|
+
redis.sadd(`cachly:stats:reuse_pairs:${instance_id}`, `${requester}<-${lesson.author}`).catch(() => { });
|
|
550
|
+
}
|
|
532
551
|
// Surface banner for proven successes (recall_count >= 1 means it's been validated)
|
|
533
552
|
if (lesson.outcome === 'success' && (lesson.recall_count ?? 0) >= 1) {
|
|
534
553
|
savedHere.push({
|
|
@@ -541,6 +560,11 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
541
560
|
}
|
|
542
561
|
}
|
|
543
562
|
}
|
|
563
|
+
// Metric 1 (time-to-first-recall): stamp the first time recall returned a
|
|
564
|
+
// proven lesson. SET NX so only the first successful recall wins.
|
|
565
|
+
if (savedHere.length > 0) {
|
|
566
|
+
redis.set(`cachly:stats:first_recall_at:${instance_id}`, new Date().toISOString(), 'EX', 365 * 86400, 'NX').catch(() => { });
|
|
567
|
+
}
|
|
544
568
|
// ── Layer 2: Semantic search (parallel, optional) ────────────────────────
|
|
545
569
|
const inst = await apiFetch(`/api/v1/instances/${instance_id}`).catch(() => null);
|
|
546
570
|
const semHits = [];
|
|
@@ -666,6 +690,9 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
666
690
|
if (topLesson) {
|
|
667
691
|
lines.push(`> 💡 **Brain saved you ~${topLesson.savedMins}m here** — ${topLesson.severity} issue from \`${topLesson.topic}\` recalled ${topLesson.recall_count}× proven\n`);
|
|
668
692
|
}
|
|
693
|
+
if (crossAuthorThisCall > 0) {
|
|
694
|
+
lines.push(`> 👥 **Team knowledge reuse** — ${crossAuthorThisCall} of these lesson${crossAuthorThisCall !== 1 ? 's were' : ' was'} written by a teammate. This is the value only a shared brain delivers.\n`);
|
|
695
|
+
}
|
|
669
696
|
// Show sub-query info if multi-topic was detected
|
|
670
697
|
const subQueries = splitMultiQuery(query);
|
|
671
698
|
if (subQueries.length > 1) {
|
|
@@ -2011,14 +2038,8 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
2011
2038
|
}
|
|
2012
2039
|
// Also: exact file_paths match via lesson scan
|
|
2013
2040
|
if (relatedLessons.length < 2) {
|
|
2014
|
-
const
|
|
2015
|
-
const
|
|
2016
|
-
await new Promise((res, rej) => {
|
|
2017
|
-
stream.on('data', (b) => scanKeys.push(...b));
|
|
2018
|
-
stream.on('end', res);
|
|
2019
|
-
stream.on('error', rej);
|
|
2020
|
-
});
|
|
2021
|
-
for (const k of scanKeys.slice(0, 300)) {
|
|
2041
|
+
const allLessonKeys = await scanKeys(redis, 'cachly:lesson:best:*', { max: 1500 });
|
|
2042
|
+
for (const k of allLessonKeys.slice(0, 300)) {
|
|
2022
2043
|
const raw = await redis.get(k);
|
|
2023
2044
|
if (!raw)
|
|
2024
2045
|
continue;
|
|
@@ -2053,14 +2074,8 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
2053
2074
|
case 'team_expertise_map': {
|
|
2054
2075
|
const { instance_id, top_n = 20, } = args;
|
|
2055
2076
|
const redis = await getConnection(instance_id);
|
|
2056
|
-
// Scan all person nodes
|
|
2057
|
-
const personKeys =
|
|
2058
|
-
const pStream = redis.scanStream({ match: 'cachly:ckg:node:person:*', count: 200 });
|
|
2059
|
-
await new Promise((res, rej) => {
|
|
2060
|
-
pStream.on('data', (b) => personKeys.push(...b));
|
|
2061
|
-
pStream.on('end', res);
|
|
2062
|
-
pStream.on('error', rej);
|
|
2063
|
-
});
|
|
2077
|
+
// Scan all person nodes (capped + timed out so a huge keyspace can't hang the agent)
|
|
2078
|
+
const personKeys = await scanKeys(redis, 'cachly:ckg:node:person:*', { max: 2000 });
|
|
2064
2079
|
if (personKeys.length === 0) {
|
|
2065
2080
|
return [
|
|
2066
2081
|
`## 🗺️ Team Expertise Map`,
|
|
@@ -2121,14 +2136,8 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
2121
2136
|
case 'skill_gaps': {
|
|
2122
2137
|
const { instance_id, min_failures = 1, } = args;
|
|
2123
2138
|
const redis = await getConnection(instance_id);
|
|
2124
|
-
// Scan all best lessons
|
|
2125
|
-
const lessonKeys =
|
|
2126
|
-
const lStream = redis.scanStream({ match: 'cachly:lesson:best:*', count: 500 });
|
|
2127
|
-
await new Promise((res, rej) => {
|
|
2128
|
-
lStream.on('data', (b) => lessonKeys.push(...b));
|
|
2129
|
-
lStream.on('end', res);
|
|
2130
|
-
lStream.on('error', rej);
|
|
2131
|
-
});
|
|
2139
|
+
// Scan all best lessons (capped + timed out)
|
|
2140
|
+
const lessonKeys = await scanKeys(redis, 'cachly:lesson:best:*', { max: 3000 });
|
|
2132
2141
|
const domainMap = new Map();
|
|
2133
2142
|
let totalAttributed = 0;
|
|
2134
2143
|
let totalPrivate = 0;
|
|
@@ -2169,14 +2178,6 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
2169
2178
|
});
|
|
2170
2179
|
}
|
|
2171
2180
|
}
|
|
2172
|
-
// Check for domains with person nodes but no lessons (contributors without lessons)
|
|
2173
|
-
const personKeys = [];
|
|
2174
|
-
const pStream = redis.scanStream({ match: 'cachly:ckg:node:person:*', count: 200 });
|
|
2175
|
-
await new Promise((res, rej) => {
|
|
2176
|
-
pStream.on('data', (b) => personKeys.push(...b));
|
|
2177
|
-
pStream.on('end', res);
|
|
2178
|
-
pStream.on('error', rej);
|
|
2179
|
-
});
|
|
2180
2181
|
const lines = [
|
|
2181
2182
|
`## 🔍 Skill Gaps — Knowledge Blind Spots`,
|
|
2182
2183
|
``,
|
|
@@ -2209,30 +2210,12 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
2209
2210
|
case 'brain_coverage': {
|
|
2210
2211
|
const { instance_id, repo_path = '.', } = args;
|
|
2211
2212
|
const redis = await getConnection(instance_id);
|
|
2212
|
-
// Count lessons
|
|
2213
|
-
const lessonKeys = [
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
lStream.on('error', rej);
|
|
2219
|
-
});
|
|
2220
|
-
// Count person nodes
|
|
2221
|
-
const personKeys = [];
|
|
2222
|
-
const pStream = redis.scanStream({ match: 'cachly:ckg:node:person:*', count: 200 });
|
|
2223
|
-
await new Promise((res, rej) => {
|
|
2224
|
-
pStream.on('data', (b) => personKeys.push(...b));
|
|
2225
|
-
pStream.on('end', res);
|
|
2226
|
-
pStream.on('error', rej);
|
|
2227
|
-
});
|
|
2228
|
-
// Count file nodes in CKG
|
|
2229
|
-
const fileKeys = [];
|
|
2230
|
-
const fStream = redis.scanStream({ match: 'cachly:ckg:node:file:*', count: 500 });
|
|
2231
|
-
await new Promise((res, rej) => {
|
|
2232
|
-
fStream.on('data', (b) => fileKeys.push(...b));
|
|
2233
|
-
fStream.on('end', res);
|
|
2234
|
-
fStream.on('error', rej);
|
|
2235
|
-
});
|
|
2213
|
+
// Count lessons, person + file nodes (each capped + timed out, gathered in parallel)
|
|
2214
|
+
const [lessonKeys, personKeys, fileKeys] = await Promise.all([
|
|
2215
|
+
scanKeys(redis, 'cachly:lesson:best:*', { max: 5000 }),
|
|
2216
|
+
scanKeys(redis, 'cachly:ckg:node:person:*', { max: 2000 }),
|
|
2217
|
+
scanKeys(redis, 'cachly:ckg:node:file:*', { max: 5000 }),
|
|
2218
|
+
]);
|
|
2236
2219
|
// Get git file count for comparison (optional — non-critical if not a git repo)
|
|
2237
2220
|
let gitFileCount = 0;
|
|
2238
2221
|
let _gitFileCountLabel = 'n/a';
|
|
@@ -2298,6 +2281,69 @@ export async function handleBrainTool(name, args, getConnection, apiFetch) {
|
|
|
2298
2281
|
`_Boost score: run \`brain_from_git\` · add \`author\` to \`learn_from_attempts\` · fix gaps with \`skill_gaps\`_`,
|
|
2299
2282
|
].join('\n');
|
|
2300
2283
|
}
|
|
2284
|
+
// ── brain_metrics ─────────────────────────────────────────────────────────
|
|
2285
|
+
// The three decisive metrics (PROGRESS.md §3 / VISION_10X.md §4):
|
|
2286
|
+
// 1. Time-to-first-recall — onboarding friction
|
|
2287
|
+
// 2. Recall-lift — the moat proof (vs. raw BM25)
|
|
2288
|
+
// 3. Team-knowledge-reuse — the value only a shared brain delivers
|
|
2289
|
+
case 'brain_metrics': {
|
|
2290
|
+
const { instance_id } = args;
|
|
2291
|
+
const redis = await getConnection(instance_id);
|
|
2292
|
+
const [bornAt, firstRecallAt, recallsTotalRaw, crossAuthorRaw, timeSavedRaw, reusePairs] = await Promise.all([
|
|
2293
|
+
redis.get(`cachly:stats:born_at:${instance_id}`).catch(() => null),
|
|
2294
|
+
redis.get(`cachly:stats:first_recall_at:${instance_id}`).catch(() => null),
|
|
2295
|
+
redis.get(`cachly:stats:recalls_total:${instance_id}`).catch(() => null),
|
|
2296
|
+
redis.get(`cachly:stats:cross_author_recalls:${instance_id}`).catch(() => null),
|
|
2297
|
+
redis.get(`cachly:stats:time_saved_mins:${instance_id}`).catch(() => null),
|
|
2298
|
+
redis.smembers(`cachly:stats:reuse_pairs:${instance_id}`).catch(() => []),
|
|
2299
|
+
]);
|
|
2300
|
+
// ── Metric 1: Time-to-first-recall ──────────────────────────────────────
|
|
2301
|
+
let ttfrLine;
|
|
2302
|
+
if (bornAt && firstRecallAt) {
|
|
2303
|
+
const ms = new Date(firstRecallAt).getTime() - new Date(bornAt).getTime();
|
|
2304
|
+
const mins = Math.max(0, Math.round(ms / 60000));
|
|
2305
|
+
const human = mins < 1 ? '<1 min' : mins < 60 ? `${mins} min` : `${(mins / 60).toFixed(1)} h`;
|
|
2306
|
+
const target = ms <= 2 * 60000 ? '🟢 under 2 min target' : ms <= 60 * 60000 ? '🟡 over 2 min' : '🔴 over 1 h';
|
|
2307
|
+
ttfrLine = `**${human}** from first lesson → first proven recall · ${target}`;
|
|
2308
|
+
}
|
|
2309
|
+
else if (bornAt && !firstRecallAt) {
|
|
2310
|
+
ttfrLine = `🟡 Brain has knowledge but no proven recall yet — try \`smart_recall\``;
|
|
2311
|
+
}
|
|
2312
|
+
else {
|
|
2313
|
+
ttfrLine = `⚪ Not enough data yet — store a lesson, then recall it`;
|
|
2314
|
+
}
|
|
2315
|
+
// ── Metric 2: Recall-lift (the moat proof) ──────────────────────────────
|
|
2316
|
+
// Published headline from Cachly-Bench (CI-defended in rerank.test.ts).
|
|
2317
|
+
const recallLiftLine = `**+22.2 % Precision@1**, **+10.9 % MRR**, **+8.1 % nDCG@5** vs. raw BM25`;
|
|
2318
|
+
// ── Metric 3: Team-knowledge-reuse ──────────────────────────────────────
|
|
2319
|
+
const recallsTotal = Number(recallsTotalRaw ?? 0);
|
|
2320
|
+
const crossAuthor = Number(crossAuthorRaw ?? 0);
|
|
2321
|
+
const reusePct = recallsTotal > 0 ? Math.round((crossAuthor / recallsTotal) * 100) : 0;
|
|
2322
|
+
const reuseTarget = reusePct >= 30 ? '🟢 above 30 % target' : recallsTotal === 0 ? '⚪ no recalls yet' : '🟡 below 30 % target';
|
|
2323
|
+
const timeSaved = Math.round(Number(timeSavedRaw ?? 0));
|
|
2324
|
+
const timeSavedHuman = timeSaved < 60 ? `${timeSaved} min` : `${(timeSaved / 60).toFixed(1)} h`;
|
|
2325
|
+
const lines = [
|
|
2326
|
+
`## 📈 Brain Metrics — the three that decide everything`,
|
|
2327
|
+
``,
|
|
2328
|
+
`### 1. Time-to-first-recall _(onboarding friction)_`,
|
|
2329
|
+
ttfrLine,
|
|
2330
|
+
``,
|
|
2331
|
+
`### 2. Recall-lift _(the moat proof)_`,
|
|
2332
|
+
recallLiftLine,
|
|
2333
|
+
`_Reproduce: \`npm run bench\` · CI-defended in \`rerank.test.ts\` · details in BENCH.md_`,
|
|
2334
|
+
``,
|
|
2335
|
+
`### 3. Team-knowledge-reuse _(the value only a shared brain delivers)_`,
|
|
2336
|
+
`**${reusePct}%** of proven recalls used a teammate's lesson (${crossAuthor}/${recallsTotal}) · ${reuseTarget}`,
|
|
2337
|
+
reusePairs.length > 0 ? `**${reusePairs.length}** distinct reuse relationship${reusePairs.length !== 1 ? 's' : ''} across the team` : '',
|
|
2338
|
+
``,
|
|
2339
|
+
`---`,
|
|
2340
|
+
`⏱️ **${timeSavedHuman}** total saved not re-researching known fixes.`,
|
|
2341
|
+
recallsTotal === 0
|
|
2342
|
+
? `_Tip: pass \`author="your-handle"\` to \`smart_recall\` so cross-author reuse can be tracked._`
|
|
2343
|
+
: `_These numbers compound: every learned lesson and every teammate raises all three._`,
|
|
2344
|
+
].filter(Boolean);
|
|
2345
|
+
return lines.join('\n');
|
|
2346
|
+
}
|
|
2301
2347
|
// ── sync_file_changes ─────────────────────────────────────────────────────
|
|
2302
2348
|
default:
|
|
2303
2349
|
return null;
|