@claude-flow/cli 3.10.20 → 3.10.21
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": "@claude-flow/cli",
|
|
3
|
-
"version": "3.10.
|
|
3
|
+
"version": "3.10.21",
|
|
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",
|
|
@@ -20,23 +20,86 @@ const CLI_ROOT = resolve(SCRIPT_DIR, '..');
|
|
|
20
20
|
const REPO_ROOT = resolve(SCRIPT_DIR, '../../../..');
|
|
21
21
|
const RUNS_DIR = join(REPO_ROOT, 'docs', 'benchmarks', 'runs');
|
|
22
22
|
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
23
|
+
// ADR-081 labelled held-out corpus. Each query has hand-curated
|
|
24
|
+
// `expectedSubstrings` — case-insensitive substring matches against the
|
|
25
|
+
// pattern's name. A result is "relevant" if its name contains ANY of the
|
|
26
|
+
// substrings. Tighter than the regex proxy used in ADRs 077-080 (which
|
|
27
|
+
// matched related-but-not-exact commits).
|
|
28
|
+
//
|
|
29
|
+
// `expect` (regex) is kept for backwards compatibility with the older
|
|
30
|
+
// numbers in ADRs 077-080. New metrics use expectedSubstrings.
|
|
27
31
|
const QUERIES = [
|
|
28
|
-
{
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
{
|
|
33
|
+
q: 'how was the Opus model alias fixed',
|
|
34
|
+
expect: /opus|2232|model.*alias|4\.8/i,
|
|
35
|
+
expectedSubstrings: ['opus 4.8', 'opus alias', 'opus model alias', '#2232'],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
q: 'self-learning wiring task-completed pretrain',
|
|
39
|
+
expect: /self.?learning|task.?completed|pretrain|2245|074/i,
|
|
40
|
+
expectedSubstrings: ['self-learning', 'adr-074', 'self learning', '#2245', 'task-completed'],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
q: 'deterministic codemod engine var-to-const',
|
|
44
|
+
expect: /codemod|var.?to.?const|143|deterministic/i,
|
|
45
|
+
expectedSubstrings: ['deterministic tier-1 codemod', 'adr-143', 'codemod', 'var-to-const'],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
q: 'MCP server orphan leak parent-death',
|
|
49
|
+
expect: /mcp.*orphan|orphan.*mcp|parent.?death|leak/i,
|
|
50
|
+
expectedSubstrings: ['mcp orphan', 'mcp servers orphan', 'parent-death', '#2234', 'orphan on every claude'],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
q: 'unified learning stats aggregator',
|
|
54
|
+
expect: /unified|stats|aggregator|075/i,
|
|
55
|
+
expectedSubstrings: ['unified learning-stats', 'adr-075', 'unified learning stats'],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
q: 'structured distillation 4-field schema',
|
|
59
|
+
expect: /distillation|structured|076|4.?field/i,
|
|
60
|
+
expectedSubstrings: ['structured distillation', 'adr-076', '4-field schema'],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
q: 'SQL injection migrate.ts table identifier',
|
|
64
|
+
expect: /sql.?injection|migrate|table|identifier/i,
|
|
65
|
+
expectedSubstrings: ['sql injection', 'shell injection', 'migrate.ts', 'agentdb', 'cve'],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
q: 'recall@k HNSW benchmark harness',
|
|
69
|
+
expect: /recall|hnsw|benchmark|harness/i,
|
|
70
|
+
expectedSubstrings: ['hnsw', 'memory-recall', 'benchmark suite', 'recall@k', 'benchmark intelligence'],
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
q: 'Q-learning encoder keyword block',
|
|
74
|
+
expect: /q.?learning|encoder|keyword|2239/i,
|
|
75
|
+
expectedSubstrings: ['q-state encoder', 'route q-state', 'keyword block', '#2239', 'q-encoder'],
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
q: 'security hardening crypto random IDs',
|
|
79
|
+
expect: /security|hardening|crypto|random/i,
|
|
80
|
+
expectedSubstrings: ['cwe-347', 'crypto.randomuuid', 'security fix', 'random id', 'crypto random'],
|
|
81
|
+
},
|
|
38
82
|
];
|
|
39
83
|
|
|
84
|
+
/** Returns true if name contains ANY of the labelled substrings (case-insensitive). */
|
|
85
|
+
function isRelevant(name, expectedSubstrings) {
|
|
86
|
+
if (!name || !expectedSubstrings?.length) return false;
|
|
87
|
+
const lower = String(name).toLowerCase();
|
|
88
|
+
return expectedSubstrings.some((s) => lower.includes(s.toLowerCase()));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** nDCG@k with binary relevance (each relevant item contributes 1 / log2(i+1)). */
|
|
92
|
+
function ndcgAtK(rankedRelevance, k) {
|
|
93
|
+
const arr = rankedRelevance.slice(0, k);
|
|
94
|
+
const dcg = arr.reduce((acc, rel, i) => acc + (rel ? 1 / Math.log2(i + 2) : 0), 0);
|
|
95
|
+
const numRelevant = arr.filter(Boolean).length;
|
|
96
|
+
if (numRelevant === 0) return 0;
|
|
97
|
+
// Ideal: all relevant items packed at positions 1..numRelevant
|
|
98
|
+
let idcg = 0;
|
|
99
|
+
for (let i = 0; i < numRelevant; i++) idcg += 1 / Math.log2(i + 2);
|
|
100
|
+
return idcg > 0 ? dcg / idcg : 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
40
103
|
const TOP_K = 5;
|
|
41
104
|
|
|
42
105
|
async function main() {
|
|
@@ -66,32 +129,45 @@ async function main() {
|
|
|
66
129
|
|
|
67
130
|
const tQuery0 = performance.now();
|
|
68
131
|
const results = [];
|
|
69
|
-
for (const { q, expect } of QUERIES) {
|
|
132
|
+
for (const { q, expect, expectedSubstrings } of QUERIES) {
|
|
70
133
|
const r = await listTool.handler({ action: 'search', query: q, mode, limit: TOP_K, rerank: useRerank });
|
|
71
134
|
const matches = (r.patterns || r.results || r.matches || []).slice(0, TOP_K);
|
|
72
135
|
if (matches.length > 0) {
|
|
73
136
|
const top1 = matches[0].id;
|
|
74
137
|
top1Ids.set(top1, (top1Ids.get(top1) ?? 0) + 1);
|
|
75
138
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
139
|
+
|
|
140
|
+
// Two relevance signals per result:
|
|
141
|
+
// regexRel — old proxy (kept for back-compat with ADR-077-080 numbers)
|
|
142
|
+
// labelRel — ADR-081 hand-curated label match
|
|
143
|
+
const regexRel = matches.map((m) => expect.test(m?.name ?? ''));
|
|
144
|
+
const labelRel = matches.map((m) => isRelevant(m?.name, expectedSubstrings));
|
|
145
|
+
|
|
146
|
+
// First rank where a labelled-relevant doc appears.
|
|
147
|
+
let firstLabelRank = -1;
|
|
148
|
+
for (let i = 0; i < matches.length; i++) {
|
|
149
|
+
if (labelRel[i]) { firstLabelRank = i + 1; break; }
|
|
87
150
|
}
|
|
151
|
+
let firstRegexRank = -1;
|
|
152
|
+
for (let i = 0; i < matches.length; i++) {
|
|
153
|
+
if (regexRel[i]) { firstRegexRank = i + 1; break; }
|
|
154
|
+
}
|
|
155
|
+
|
|
88
156
|
results.push({
|
|
89
157
|
query: q,
|
|
90
158
|
matched: matches.length > 0,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
159
|
+
// Regex-proxy metrics (back-compat with ADR-077-080)
|
|
160
|
+
top1Relevant: regexRel[0] || false,
|
|
161
|
+
top3Relevant: regexRel.slice(0, 3).some(Boolean),
|
|
162
|
+
firstRelevantRank: firstRegexRank,
|
|
163
|
+
// ADR-081 labelled metrics
|
|
164
|
+
label_top1: labelRel[0] || false,
|
|
165
|
+
label_top3_count: labelRel.slice(0, 3).filter(Boolean).length,
|
|
166
|
+
label_top5_count: labelRel.slice(0, 5).filter(Boolean).length,
|
|
167
|
+
label_firstRank: firstLabelRank,
|
|
168
|
+
label_ndcg3: ndcgAtK(labelRel, 3),
|
|
169
|
+
label_ndcg5: ndcgAtK(labelRel, 5),
|
|
170
|
+
topK: matches.map((m, i) => ({
|
|
95
171
|
id: m.id,
|
|
96
172
|
name: m.name?.slice(0, 100),
|
|
97
173
|
type: m.type,
|
|
@@ -99,20 +175,38 @@ async function main() {
|
|
|
99
175
|
cosineScore: m.cosineScore,
|
|
100
176
|
bm25Score: m.bm25Score,
|
|
101
177
|
mmrScore: m.mmrScore,
|
|
178
|
+
labelRelevant: labelRel[i],
|
|
102
179
|
})),
|
|
103
180
|
});
|
|
104
181
|
}
|
|
105
182
|
const queryMs = performance.now() - tQuery0;
|
|
106
183
|
|
|
107
184
|
const matchedQueries = results.filter((r) => r.matched).length;
|
|
185
|
+
// Regex-proxy metrics (back-compat)
|
|
108
186
|
const top1Hits = results.filter((r) => r.top1Relevant).length;
|
|
109
187
|
const top3Hits = results.filter((r) => r.top3Relevant).length;
|
|
110
188
|
const ranks = results.filter((r) => r.firstRelevantRank > 0).map((r) => r.firstRelevantRank);
|
|
111
|
-
// MRR over the top-3 window (rank-of-first-relevant). Queries with no
|
|
112
|
-
// relevant result in top-3 contribute 0 to the mean.
|
|
113
189
|
const mrr3 = QUERIES.length > 0
|
|
114
190
|
? Number((ranks.reduce((s, r) => s + 1 / r, 0) / QUERIES.length).toFixed(4))
|
|
115
191
|
: 0;
|
|
192
|
+
|
|
193
|
+
// ADR-081 labelled metrics — tighter ground truth than regex proxy.
|
|
194
|
+
const label_top1Hits = results.filter((r) => r.label_top1).length;
|
|
195
|
+
const label_top3HitsBinary = results.filter((r) => r.label_top3_count > 0).length;
|
|
196
|
+
const label_ranks = results.filter((r) => r.label_firstRank > 0).map((r) => r.label_firstRank);
|
|
197
|
+
const label_mrr3 = QUERIES.length > 0
|
|
198
|
+
? Number((label_ranks.reduce((s, r) => s + 1 / r, 0) / QUERIES.length).toFixed(4))
|
|
199
|
+
: 0;
|
|
200
|
+
const label_ndcg3_mean = QUERIES.length > 0
|
|
201
|
+
? Number((results.reduce((s, r) => s + r.label_ndcg3, 0) / QUERIES.length).toFixed(4))
|
|
202
|
+
: 0;
|
|
203
|
+
const label_ndcg5_mean = QUERIES.length > 0
|
|
204
|
+
? Number((results.reduce((s, r) => s + r.label_ndcg5, 0) / QUERIES.length).toFixed(4))
|
|
205
|
+
: 0;
|
|
206
|
+
// Mean precision@3 — fraction of top-3 that's relevant per query, averaged.
|
|
207
|
+
const label_precision3 = QUERIES.length > 0
|
|
208
|
+
? Number((results.reduce((s, r) => s + r.label_top3_count / 3, 0) / QUERIES.length).toFixed(4))
|
|
209
|
+
: 0;
|
|
116
210
|
// top-1 collision: number of distinct top-1 IDs over the query count.
|
|
117
211
|
const uniqueTop1 = top1Ids.size;
|
|
118
212
|
const top1Diversity = Number((uniqueTop1 / QUERIES.length).toFixed(4));
|
|
@@ -141,9 +235,17 @@ async function main() {
|
|
|
141
235
|
queries: QUERIES.length,
|
|
142
236
|
matchedQueries,
|
|
143
237
|
matchRate: Number((matchedQueries / QUERIES.length).toFixed(4)),
|
|
144
|
-
|
|
238
|
+
// Regex-proxy metrics (ADR-077-080 back-compat)
|
|
239
|
+
top1HitRate: Number((top1Hits / QUERIES.length).toFixed(4)),
|
|
145
240
|
top3HitRate: Number((top3Hits / QUERIES.length).toFixed(4)),
|
|
146
|
-
mrr3,
|
|
241
|
+
mrr3,
|
|
242
|
+
// ADR-081 labelled metrics — tighter ground truth
|
|
243
|
+
label_top1HitRate: Number((label_top1Hits / QUERIES.length).toFixed(4)),
|
|
244
|
+
label_top3HitRate: Number((label_top3HitsBinary / QUERIES.length).toFixed(4)),
|
|
245
|
+
label_mrr3,
|
|
246
|
+
label_precision3,
|
|
247
|
+
label_ndcg3: label_ndcg3_mean,
|
|
248
|
+
label_ndcg5: label_ndcg5_mean,
|
|
147
249
|
top1Diversity, // 1.0 = every query gets a distinct top-1
|
|
148
250
|
top3DupRate, // 0.0 = no duplicate IDs inside any top-3
|
|
149
251
|
avgQueryLatencyMs: Number((queryMs / QUERIES.length).toFixed(2)),
|
|
@@ -160,9 +262,16 @@ async function main() {
|
|
|
160
262
|
console.log(`Store size: ${total} patterns`);
|
|
161
263
|
console.log(`Queries: ${QUERIES.length}`);
|
|
162
264
|
console.log(`Match rate: ${(summary.matchRate * 100).toFixed(0)}% (${matchedQueries}/${QUERIES.length})`);
|
|
163
|
-
console.log(`Top-1 hit rate (
|
|
164
|
-
console.log(`Top-3 hit rate (
|
|
165
|
-
console.log(`MRR@3:
|
|
265
|
+
console.log(`Top-1 hit rate (regex proxy): ${(summary.top1HitRate * 100).toFixed(0)}% (${top1Hits}/${QUERIES.length})`);
|
|
266
|
+
console.log(`Top-3 hit rate (regex proxy): ${(summary.top3HitRate * 100).toFixed(0)}% (${top3Hits}/${QUERIES.length})`);
|
|
267
|
+
console.log(`MRR@3 (regex proxy): ${summary.mrr3}`);
|
|
268
|
+
console.log('');
|
|
269
|
+
console.log(`Top-1 hit rate (ADR-081 labelled): ${(summary.label_top1HitRate * 100).toFixed(0)}% (${label_top1Hits}/${QUERIES.length})`);
|
|
270
|
+
console.log(`Top-3 hit rate (ADR-081 labelled): ${(summary.label_top3HitRate * 100).toFixed(0)}% (${label_top3HitsBinary}/${QUERIES.length})`);
|
|
271
|
+
console.log(`MRR@3 (labelled): ${summary.label_mrr3}`);
|
|
272
|
+
console.log(`Precision@3 (labelled, mean): ${summary.label_precision3}`);
|
|
273
|
+
console.log(`nDCG@3 (labelled, mean): ${summary.label_ndcg3}`);
|
|
274
|
+
console.log(`nDCG@5 (labelled, mean): ${summary.label_ndcg5}`);
|
|
166
275
|
console.log(`Top-1 diversity: ${(summary.top1Diversity * 100).toFixed(0)}% (${uniqueTop1} distinct top-1 IDs across ${QUERIES.length} queries)`);
|
|
167
276
|
console.log(`Top-3 dup rate: ${(summary.top3DupRate * 100).toFixed(0)}%`);
|
|
168
277
|
console.log(`Avg query latency: ${summary.avgQueryLatencyMs} ms`);
|