@devflow-tools/benchmark 0.16.12 → 0.16.13

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.d.ts CHANGED
@@ -9,4 +9,6 @@ export { runBenchmarkSuite } from "./suite-runner.js";
9
9
  export type { BenchmarkRetrievalRunner, SuiteRunOptions } from "./suite-runner.js";
10
10
  export { renderBenchmarkReport } from "./report-renderer.js";
11
11
  export type { BenchmarkReportFormat } from "./report-renderer.js";
12
+ export { runRetrievalQualityBenchmark } from './retrieval-quality.js';
13
+ export type { RetrievalQualityCase, RetrievalQualityFixture, RetrievalQualityReport, RetrievalQualityThresholds, } from './retrieval-quality.js';
12
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,YAAY,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,YAAY,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AACtE,YAAY,EACV,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -4,4 +4,5 @@ export { ACCURACY_TESTS } from "./accuracy-queries.js";
4
4
  export { LexicalBenchmarkRunner } from "./lexical-runner.js";
5
5
  export { runBenchmarkSuite } from "./suite-runner.js";
6
6
  export { renderBenchmarkReport } from "./report-renderer.js";
7
+ export { runRetrievalQualityBenchmark } from './retrieval-quality.js';
7
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,76 @@
1
+ import type { ContextFileRole } from '@devflow-tools/sdk';
2
+ export interface RetrievalQualityFixture {
3
+ schemaVersion: 'devflow.retrieval-quality.v1';
4
+ thresholds: RetrievalQualityThresholds;
5
+ queries: RetrievalQualityCase[];
6
+ forbiddenCodeEdges?: Array<{
7
+ sourceFile: string;
8
+ targetFile: string;
9
+ kind?: string;
10
+ }>;
11
+ }
12
+ export interface RetrievalQualityThresholds {
13
+ codeFileRecallAt5: number;
14
+ symbolNdcgAt5: number;
15
+ falseCrossFileEdgeRate: number;
16
+ memoryPrecisionAt5: number;
17
+ expectedEmptyMemoryAccuracy: number;
18
+ knowledgeVectorCoverage: number;
19
+ knowledgeChunkP95: number;
20
+ knowledgeVersionMatch: number;
21
+ }
22
+ export interface RetrievalQualityCase {
23
+ id: string;
24
+ query: string;
25
+ intent: string;
26
+ relevantCode?: Array<{
27
+ path: string;
28
+ role: ContextFileRole;
29
+ }>;
30
+ relevantSymbols?: string[];
31
+ relevantMemoryIds?: string[];
32
+ relevantMemoryTerms?: string[];
33
+ expectedEmptyMemory?: boolean;
34
+ relevantKnowledgeIds?: string[];
35
+ relevantKnowledgeSources?: string[];
36
+ expectedVersions?: Record<string, string>;
37
+ }
38
+ export interface RetrievalQualityReport {
39
+ schemaVersion: 'devflow.retrieval-quality-report.v1';
40
+ projectRoot: string;
41
+ fixturePath: string;
42
+ createdAt: number;
43
+ status: 'passed' | 'failed';
44
+ metrics: {
45
+ codeFileRecallAt5: number;
46
+ codeFilePrecisionAt5: number;
47
+ symbolNdcgAt5: number;
48
+ falseCrossFileEdgeRate: number;
49
+ memoryPrecisionAt5: number;
50
+ expectedEmptyMemoryAccuracy: number;
51
+ knowledgeNdcgAt5: number;
52
+ knowledgeVectorCoverage: number;
53
+ knowledgeChunkP95: number;
54
+ knowledgeVersionMatch: number;
55
+ };
56
+ thresholds: RetrievalQualityThresholds;
57
+ gates: Record<string, boolean>;
58
+ cases: Array<{
59
+ id: string;
60
+ requestId: string;
61
+ selectedCode: string[];
62
+ selectedMemory: string[];
63
+ selectedKnowledge: string[];
64
+ codeRecallAt5?: number;
65
+ memoryPrecisionAt5?: number;
66
+ expectedEmptyMemoryCorrect?: boolean;
67
+ knowledgeNdcgAt5?: number;
68
+ }>;
69
+ diagnostics: string[];
70
+ }
71
+ export declare function runRetrievalQualityBenchmark(options: {
72
+ projectRoot: string;
73
+ fixturePath?: string;
74
+ persist?: boolean;
75
+ }): Promise<RetrievalQualityReport>;
76
+ //# sourceMappingURL=retrieval-quality.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrieval-quality.d.ts","sourceRoot":"","sources":["../src/retrieval-quality.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,236 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { createEngines } from '@devflow-tools/context-engine';
5
+ import { openGlobalDevFlowDatabase } from '@devflow-tools/database';
6
+ export async function runRetrievalQualityBenchmark(options) {
7
+ const projectRoot = resolve(options.projectRoot);
8
+ const fixturePath = resolve(options.fixturePath ?? defaultFixturePath());
9
+ const fixture = loadFixture(fixturePath);
10
+ const engines = await createEngines(projectRoot, { warmSymbolVectors: false });
11
+ const envelopes = [];
12
+ const diagnostics = [];
13
+ try {
14
+ for (const testCase of fixture.queries) {
15
+ const result = await engines.context.buildTaskContext(testCase.query, {
16
+ mode: 'deep',
17
+ maxTokens: 8_000,
18
+ sessionId: `quality:${testCase.id}`,
19
+ executionId: `quality:${testCase.id}`,
20
+ requestId: `quality:${testCase.id}:${Date.now()}`,
21
+ host: 'benchmark',
22
+ command: 'retrieval-quality',
23
+ });
24
+ if (!result.taskEnvelope)
25
+ throw new Error(`Query ${testCase.id} did not produce a TaskContextEnvelope`);
26
+ envelopes.push({ fixture: testCase, envelope: result.taskEnvelope });
27
+ }
28
+ const graph = engines.graph.export();
29
+ const rejected = engines.graph.getRejectedRelations();
30
+ const nodeFiles = new Map(graph.nodes.map(node => [node.id, normalizePath(node.file)]));
31
+ const acceptedCrossFile = graph.edges.filter(edge => {
32
+ const source = nodeFiles.get(edge.from);
33
+ const target = nodeFiles.get(edge.to);
34
+ return source && target && source !== target;
35
+ });
36
+ const forbidden = fixture.forbiddenCodeEdges ?? [];
37
+ const falseAccepted = acceptedCrossFile.filter(edge => {
38
+ const source = nodeFiles.get(edge.from) ?? '';
39
+ const target = nodeFiles.get(edge.to) ?? '';
40
+ return forbidden.some(candidate => edgeMatches(candidate, source, target, edge.type));
41
+ });
42
+ for (const candidate of forbidden) {
43
+ const rejectedMatch = rejected.some(edge => edgeMatches(candidate, normalizePath(edge.sourceFile ?? ''), normalizePath(edge.targetFile ?? ''), edge.kind));
44
+ const acceptedMatch = falseAccepted.some(edge => edgeMatches(candidate, nodeFiles.get(edge.from) ?? '', nodeFiles.get(edge.to) ?? '', edge.type));
45
+ if (!rejectedMatch && !acceptedMatch)
46
+ diagnostics.push(`forbidden edge was not observable: ${candidate.sourceFile} -> ${candidate.targetFile}`);
47
+ }
48
+ const fileCases = envelopes.filter(item => (item.fixture.relevantCode?.length ?? 0) > 0);
49
+ const symbolCases = envelopes.filter(item => (item.fixture.relevantSymbols?.length ?? 0) > 0);
50
+ const memoryCases = envelopes.filter(item => (item.fixture.relevantMemoryIds?.length ?? 0) > 0 || (item.fixture.relevantMemoryTerms?.length ?? 0) > 0);
51
+ const emptyMemoryCases = envelopes.filter(item => item.fixture.expectedEmptyMemory === true);
52
+ const knowledgeCases = envelopes.filter(item => (item.fixture.relevantKnowledgeIds?.length ?? 0) > 0 || (item.fixture.relevantKnowledgeSources?.length ?? 0) > 0);
53
+ const versionCases = envelopes.filter(item => Object.keys(item.fixture.expectedVersions ?? {}).length > 0);
54
+ const knowledgeHealth = engines.knowledge.getIndexHealth();
55
+ const metrics = {
56
+ codeFileRecallAt5: average(fileCases.map(item => fileRecall(item.envelope, item.fixture, 5))),
57
+ codeFilePrecisionAt5: average(fileCases.map(item => filePrecision(item.envelope, item.fixture, 5))),
58
+ symbolNdcgAt5: average(symbolCases.map(item => symbolNdcg(item.envelope, item.fixture, 5))),
59
+ falseCrossFileEdgeRate: acceptedCrossFile.length > 0 ? falseAccepted.length / acceptedCrossFile.length : 0,
60
+ memoryPrecisionAt5: average(memoryCases.map(item => memoryPrecision(item.envelope, item.fixture, 5))),
61
+ expectedEmptyMemoryAccuracy: average(emptyMemoryCases.map(item => item.envelope.memory.entries.length === 0 ? 1 : 0)),
62
+ knowledgeNdcgAt5: average(knowledgeCases.map(item => knowledgeNdcg(item.envelope, item.fixture, 5))),
63
+ knowledgeVectorCoverage: knowledgeHealth.vectorCoverage,
64
+ knowledgeChunkP95: knowledgeHealth.chunkTokens.p95,
65
+ knowledgeVersionMatch: average(versionCases.map(item => knowledgeVersionMatch(item.envelope, item.fixture))),
66
+ };
67
+ const thresholds = fixture.thresholds;
68
+ const gates = {
69
+ codeFileRecallAt5: metrics.codeFileRecallAt5 >= thresholds.codeFileRecallAt5,
70
+ symbolNdcgAt5: metrics.symbolNdcgAt5 >= thresholds.symbolNdcgAt5,
71
+ falseCrossFileEdgeRate: metrics.falseCrossFileEdgeRate < thresholds.falseCrossFileEdgeRate,
72
+ memoryPrecisionAt5: metrics.memoryPrecisionAt5 >= thresholds.memoryPrecisionAt5,
73
+ expectedEmptyMemoryAccuracy: metrics.expectedEmptyMemoryAccuracy >= thresholds.expectedEmptyMemoryAccuracy,
74
+ knowledgeVectorCoverage: metrics.knowledgeVectorCoverage >= thresholds.knowledgeVectorCoverage,
75
+ knowledgeChunkP95: metrics.knowledgeChunkP95 <= thresholds.knowledgeChunkP95,
76
+ knowledgeVersionMatch: metrics.knowledgeVersionMatch >= thresholds.knowledgeVersionMatch,
77
+ };
78
+ const report = {
79
+ schemaVersion: 'devflow.retrieval-quality-report.v1',
80
+ projectRoot,
81
+ fixturePath,
82
+ createdAt: Date.now(),
83
+ status: Object.values(gates).every(Boolean) ? 'passed' : 'failed',
84
+ metrics,
85
+ thresholds,
86
+ gates,
87
+ cases: envelopes.map(item => ({
88
+ id: item.fixture.id,
89
+ requestId: item.envelope.request.requestId,
90
+ selectedCode: item.envelope.code.files.map(file => `${file.role}:${file.path}`),
91
+ selectedMemory: item.envelope.memory.entries.map(entry => entry.id),
92
+ selectedKnowledge: item.envelope.knowledge.entries.map(entry => `${entry.source}:${entry.id}`),
93
+ ...((item.fixture.relevantCode?.length ?? 0) > 0 ? { codeRecallAt5: fileRecall(item.envelope, item.fixture, 5) } : {}),
94
+ ...((item.fixture.relevantMemoryIds?.length ?? 0) + (item.fixture.relevantMemoryTerms?.length ?? 0) > 0
95
+ ? { memoryPrecisionAt5: memoryPrecision(item.envelope, item.fixture, 5) } : {}),
96
+ ...(item.fixture.expectedEmptyMemory ? { expectedEmptyMemoryCorrect: item.envelope.memory.entries.length === 0 } : {}),
97
+ ...((item.fixture.relevantKnowledgeIds?.length ?? 0) + (item.fixture.relevantKnowledgeSources?.length ?? 0) > 0
98
+ ? { knowledgeNdcgAt5: knowledgeNdcg(item.envelope, item.fixture, 5) } : {}),
99
+ })),
100
+ diagnostics,
101
+ };
102
+ if (options.persist !== false)
103
+ persistReport(report);
104
+ return report;
105
+ }
106
+ finally {
107
+ engines.context.close();
108
+ engines.memory.close();
109
+ engines.knowledge.close();
110
+ engines.telemetry.close();
111
+ engines.codegraph.close();
112
+ engines.data.close?.();
113
+ }
114
+ }
115
+ function persistReport(report) {
116
+ const database = openGlobalDevFlowDatabase();
117
+ try {
118
+ database.insertBenchmarkReport({
119
+ runId: `retrieval-quality:${report.createdAt}`,
120
+ suiteId: 'retrieval-quality',
121
+ suiteVersion: '1',
122
+ projectRoot: report.projectRoot,
123
+ commit: null,
124
+ createdAt: report.createdAt,
125
+ status: 'completed',
126
+ tasks: report.cases,
127
+ qualityStatus: report.status,
128
+ metrics: report.metrics,
129
+ thresholds: report.thresholds,
130
+ gates: report.gates,
131
+ diagnostics: report.diagnostics,
132
+ fixturePath: report.fixturePath,
133
+ });
134
+ }
135
+ finally {
136
+ database.close();
137
+ }
138
+ }
139
+ function loadFixture(path) {
140
+ if (!existsSync(path))
141
+ throw new Error(`Retrieval quality fixture not found: ${path}`);
142
+ const value = JSON.parse(readFileSync(path, 'utf8'));
143
+ if (value.schemaVersion !== 'devflow.retrieval-quality.v1' || !Array.isArray(value.queries)) {
144
+ throw new Error(`Invalid retrieval quality fixture: ${path}`);
145
+ }
146
+ return value;
147
+ }
148
+ function defaultFixturePath() {
149
+ return resolve(dirname(fileURLToPath(import.meta.url)), '..', 'fixtures', 'retrieval-quality.json');
150
+ }
151
+ function fileRecall(envelope, fixture, k) {
152
+ const expected = new Set((fixture.relevantCode ?? []).map(file => normalizePath(file.path)));
153
+ const selected = new Set(envelope.code.files.slice(0, k).map(file => normalizePath(file.path)));
154
+ return expected.size > 0 ? [...expected].filter(path => selected.has(path)).length / expected.size : 1;
155
+ }
156
+ function filePrecision(envelope, fixture, k) {
157
+ const expected = new Set((fixture.relevantCode ?? []).map(file => normalizePath(file.path)));
158
+ const selected = envelope.code.files.slice(0, k).map(file => normalizePath(file.path));
159
+ return selected.length > 0 ? selected.filter(path => expected.has(path)).length / selected.length : 0;
160
+ }
161
+ function symbolNdcg(envelope, fixture, k) {
162
+ const expected = new Set((fixture.relevantSymbols ?? []).map(normalizeText));
163
+ const selected = envelope.code.files.flatMap(file => file.symbols).slice(0, k).map(normalizeText);
164
+ return ndcg(selected.map(value => expected.has(value) ? 1 : 0), Math.min(k, expected.size));
165
+ }
166
+ function memoryPrecision(envelope, fixture, k) {
167
+ const ids = new Set(fixture.relevantMemoryIds ?? []);
168
+ const terms = (fixture.relevantMemoryTerms ?? []).map(normalizeText);
169
+ const selected = envelope.memory.entries.slice(0, k);
170
+ if (selected.length === 0)
171
+ return 0;
172
+ const relevant = selected.filter(entry => ids.has(entry.id)
173
+ || terms.some(term => normalizeText(`${entry.title} ${entry.applicability.join(' ')}`).includes(term)));
174
+ return relevant.length / selected.length;
175
+ }
176
+ function knowledgeNdcg(envelope, fixture, k) {
177
+ const ids = new Set(fixture.relevantKnowledgeIds ?? []);
178
+ const sources = new Set((fixture.relevantKnowledgeSources ?? []).map(normalizeText));
179
+ const relevance = envelope.knowledge.entries.slice(0, k)
180
+ .map(entry => ids.has(entry.id) || sources.has(normalizeText(entry.source)) ? 1 : 0);
181
+ // A relevant source can contribute multiple useful chunks. When source-level
182
+ // relevance is specified, every position up to k can therefore be relevant.
183
+ const idealRelevant = sources.size > 0 ? k : Math.min(k, ids.size);
184
+ return ndcg(relevance, idealRelevant);
185
+ }
186
+ function knowledgeVersionMatch(envelope, fixture) {
187
+ const expected = fixture.expectedVersions ?? {};
188
+ const applicable = envelope.knowledge.entries.filter(entry => expected[entry.source] !== undefined);
189
+ if (applicable.length === 0)
190
+ return 0;
191
+ return applicable.filter(entry => major(entry.version) === major(expected[entry.source])).length / applicable.length;
192
+ }
193
+ function edgeMatches(expected, source, target, kind) {
194
+ const forward = normalizePath(expected.sourceFile) === source && normalizePath(expected.targetFile) === target;
195
+ const reverse = normalizePath(expected.sourceFile) === target && normalizePath(expected.targetFile) === source;
196
+ return (forward || reverse) && (!expected.kind || normalizeText(expected.kind) === normalizeText(kind));
197
+ }
198
+ function ndcg(relevance, idealRelevant) {
199
+ const dcg = relevance.reduce((sum, value, index) => sum + value / Math.log2(index + 2), 0);
200
+ const idcg = Array.from({ length: Math.min(relevance.length, idealRelevant) }, (_, index) => 1 / Math.log2(index + 2))
201
+ .reduce((sum, value) => sum + value, 0);
202
+ return idcg > 0 ? Math.min(1, dcg / idcg) : 1;
203
+ }
204
+ function average(values) {
205
+ return values.length > 0 ? values.reduce((sum, value) => sum + value, 0) / values.length : 1;
206
+ }
207
+ function normalizePath(value) {
208
+ return value.replaceAll('\\', '/').replace(/^\.\//u, '').toLocaleLowerCase('en-US');
209
+ }
210
+ function normalizeText(value) {
211
+ return value.normalize('NFKC').toLocaleLowerCase('en-US').trim();
212
+ }
213
+ function major(value) {
214
+ return value?.match(/\d+/u)?.[0];
215
+ }
216
+ async function main() {
217
+ const args = process.argv.slice(2);
218
+ const projectIndex = args.indexOf('--project');
219
+ const fixtureIndex = args.indexOf('--fixture');
220
+ if (projectIndex < 0 || !args[projectIndex + 1]) {
221
+ throw new Error('Usage: retrieval-quality --project <path> [--fixture <path>] [--json]');
222
+ }
223
+ const report = await runRetrievalQualityBenchmark({
224
+ projectRoot: args[projectIndex + 1],
225
+ fixturePath: fixtureIndex >= 0 ? args[fixtureIndex + 1] : undefined,
226
+ });
227
+ console.log(JSON.stringify(report, null, args.includes('--json') ? 0 : 2));
228
+ process.exitCode = report.status === 'passed' ? 0 : 1;
229
+ }
230
+ if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
231
+ void main().catch(error => {
232
+ console.error(error instanceof Error ? error.message : String(error));
233
+ process.exitCode = 1;
234
+ });
235
+ }
236
+ //# sourceMappingURL=retrieval-quality.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrieval-quality.js","sourceRoot":"","sources":["../src/retrieval-quality.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAqEpE,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,OAIlD;IACC,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,IAAI,kBAAkB,EAAE,CAAC,CAAC;IACzE,MAAM,OAAO,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,MAAM,SAAS,GAA4E,EAAE,CAAC;IAC9F,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAK,EAAE;gBACpE,IAAI,EAAE,MAAM;gBACZ,SAAS,EAAE,KAAK;gBAChB,SAAS,EAAE,WAAW,QAAQ,CAAC,EAAE,EAAE;gBACnC,WAAW,EAAE,WAAW,QAAQ,CAAC,EAAE,EAAE;gBACrC,SAAS,EAAE,WAAW,QAAQ,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE;gBACjD,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,mBAAmB;aAC7B,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,YAAY;gBAAE,MAAM,IAAI,KAAK,CAAC,SAAS,QAAQ,CAAC,EAAE,wCAAwC,CAAC,CAAC;YACxG,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,CAAC;QACtD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACxF,MAAM,iBAAiB,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YAClD,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtC,OAAO,MAAM,IAAI,MAAM,IAAI,MAAM,KAAK,MAAM,CAAC;QAC/C,CAAC,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,OAAO,CAAC,kBAAkB,IAAI,EAAE,CAAC;QACnD,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YACpD,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC9C,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;YAC5C,OAAO,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACxF,CAAC,CAAC,CAAC;QACH,KAAK,MAAM,SAAS,IAAI,SAAS,EAAE,CAAC;YAClC,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,aAAa,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC3J,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAC1D,SAAS,EACT,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAC9B,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,EAC5B,IAAI,CAAC,IAAI,CACV,CAAC,CAAC;YACH,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa;gBAAE,WAAW,CAAC,IAAI,CAAC,sCAAsC,SAAS,CAAC,UAAU,OAAO,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC;QAClJ,CAAC;QAED,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzF,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9F,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAC1C,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5G,MAAM,gBAAgB,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,KAAK,IAAI,CAAC,CAAC;QAC7F,MAAM,cAAc,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAC7C,CAAC,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpH,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC3G,MAAM,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC;QAE3D,MAAM,OAAO,GAAG;YACd,iBAAiB,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7F,oBAAoB,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YACnG,aAAa,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YAC3F,sBAAsB,EAAE,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC1G,kBAAkB,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YACrG,2BAA2B,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACrH,gBAAgB,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YACpG,uBAAuB,EAAE,eAAe,CAAC,cAAc;YACvD,iBAAiB,EAAE,eAAe,CAAC,WAAW,CAAC,GAAG;YAClD,qBAAqB,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;SAC7G,CAAC;QACF,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACtC,MAAM,KAAK,GAAG;YACZ,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,IAAI,UAAU,CAAC,iBAAiB;YAC5E,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,UAAU,CAAC,aAAa;YAChE,sBAAsB,EAAE,OAAO,CAAC,sBAAsB,GAAG,UAAU,CAAC,sBAAsB;YAC1F,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,UAAU,CAAC,kBAAkB;YAC/E,2BAA2B,EAAE,OAAO,CAAC,2BAA2B,IAAI,UAAU,CAAC,2BAA2B;YAC1G,uBAAuB,EAAE,OAAO,CAAC,uBAAuB,IAAI,UAAU,CAAC,uBAAuB;YAC9F,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,IAAI,UAAU,CAAC,iBAAiB;YAC5E,qBAAqB,EAAE,OAAO,CAAC,qBAAqB,IAAI,UAAU,CAAC,qBAAqB;SACzF,CAAC;QACF,MAAM,MAAM,GAA2B;YACrC,aAAa,EAAE,qCAAqC;YACpD,WAAW;YACX,WAAW;YACX,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;YACjE,OAAO;YACP,UAAU;YACV,KAAK;YACL,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC5B,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;gBACnB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS;gBAC1C,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC/E,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;gBACnE,iBAAiB,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;gBAC9F,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtH,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC;oBACrG,CAAC,CAAC,EAAE,kBAAkB,EAAE,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjF,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,0BAA0B,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtH,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC;oBAC7G,CAAC,CAAC,EAAE,gBAAgB,EAAE,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9E,CAAC,CAAC;YACH,WAAW;SACZ,CAAC;QACF,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK;YAAE,aAAa,CAAC,MAAM,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,IAA+B,CAAC,KAAK,EAAE,EAAE,CAAC;IACrD,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,MAA8B;IACnD,MAAM,QAAQ,GAAG,yBAAyB,EAAE,CAAC;IAC7C,IAAI,CAAC;QACH,QAAQ,CAAC,qBAAqB,CAAC;YAC7B,KAAK,EAAE,qBAAqB,MAAM,CAAC,SAAS,EAAE;YAC9C,OAAO,EAAE,mBAAmB;YAC5B,YAAY,EAAE,GAAG;YACjB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,aAAa,EAAE,MAAM,CAAC,MAAM;YAC5B,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;SAChC,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,QAAQ,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,EAAE,CAAC,CAAC;IACvF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAA4B,CAAC;IAChF,IAAI,KAAK,CAAC,aAAa,KAAK,8BAA8B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5F,MAAM,IAAI,KAAK,CAAC,sCAAsC,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,wBAAwB,CAAC,CAAC;AACtG,CAAC;AAED,SAAS,UAAU,CAAC,QAA6B,EAAE,OAA6B,EAAE,CAAS;IACzF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7F,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChG,OAAO,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACzG,CAAC;AAED,SAAS,aAAa,CAAC,QAA6B,EAAE,OAA6B,EAAE,CAAS;IAC5F,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7F,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACvF,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACxG,CAAC;AAED,SAAS,UAAU,CAAC,QAA6B,EAAE,OAA6B,EAAE,CAAS;IACzF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IAC7E,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAClG,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9F,CAAC;AAED,SAAS,eAAe,CAAC,QAA6B,EAAE,OAA6B,EAAE,CAAS;IAC9F,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACrE,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;WACtD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1G,OAAO,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;AAC3C,CAAC;AAED,SAAS,aAAa,CAAC,QAA6B,EAAE,OAA6B,EAAE,CAAS;IAC5F,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IACrF,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACrD,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvF,6EAA6E;IAC7E,4EAA4E;IAC5E,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACnE,OAAO,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,qBAAqB,CAAC,QAA6B,EAAE,OAA6B;IACzF,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC;IAChD,MAAM,UAAU,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC;IACpG,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACtC,OAAO,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;AACvH,CAAC;AAED,SAAS,WAAW,CAClB,QAAmE,EACnE,MAAc,EACd,MAAc,EACd,IAAY;IAEZ,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,MAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,MAAM,CAAC;IAC/G,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,MAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,MAAM,CAAC;IAC/G,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1G,CAAC;AAED,SAAS,IAAI,CAAC,SAAmB,EAAE,aAAqB;IACtD,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3F,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;SACnH,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;IAC1C,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,OAAO,CAAC,MAAgB;IAC/B,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;AACtF,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AACnE,CAAC;AAED,SAAS,KAAK,CAAC,KAAyB;IACtC,OAAO,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,YAAY,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC3F,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAAC;QAChD,WAAW,EAAE,IAAI,CAAC,YAAY,GAAG,CAAC,CAAE;QACpC,WAAW,EAAE,YAAY,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;KACpE,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACnF,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;QACxB,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,61 @@
1
+ {
2
+ "schemaVersion": "devflow.retrieval-quality.v1",
3
+ "thresholds": {
4
+ "codeFileRecallAt5": 0.85,
5
+ "symbolNdcgAt5": 0.85,
6
+ "falseCrossFileEdgeRate": 0.01,
7
+ "memoryPrecisionAt5": 0.8,
8
+ "expectedEmptyMemoryAccuracy": 1,
9
+ "knowledgeVectorCoverage": 0.95,
10
+ "knowledgeChunkP95": 3000,
11
+ "knowledgeVersionMatch": 1
12
+ },
13
+ "queries": [
14
+ {
15
+ "id": "video-player-performance",
16
+ "query": "分析 src/components/video-player/VideoPlayer.tsx 组件的 React 性能问题",
17
+ "intent": "performance",
18
+ "relevantCode": [
19
+ { "path": "src/components/video-player/VideoPlayer.tsx", "role": "target" },
20
+ { "path": "src/pages/video-player/VideoPlayerPage.tsx", "role": "caller" },
21
+ { "path": "src/components/video-player/VideoPlayer.css", "role": "resource" },
22
+ { "path": "src/routes/video-player.tsx", "role": "route" }
23
+ ],
24
+ "relevantSymbols": ["VideoPlayer", "VideoPlayerInner"],
25
+ "expectedEmptyMemory": true,
26
+ "relevantKnowledgeSources": ["react"],
27
+ "expectedVersions": { "react": "19" }
28
+ },
29
+ {
30
+ "id": "animation-convention",
31
+ "query": "这个项目统一采用什么动画方案",
32
+ "intent": "understand",
33
+ "relevantMemoryTerms": ["motion"]
34
+ },
35
+ {
36
+ "id": "package-manager-convention",
37
+ "query": "这个项目使用什么包管理器",
38
+ "intent": "understand",
39
+ "relevantMemoryTerms": ["pnpm"]
40
+ },
41
+ {
42
+ "id": "styling-convention",
43
+ "query": "这个项目统一采用什么样式和组件方案",
44
+ "intent": "understand",
45
+ "relevantMemoryTerms": ["tailwind", "shadcn"]
46
+ },
47
+ {
48
+ "id": "react-version-convention",
49
+ "query": "这个项目采用什么 React 版本和语法约定",
50
+ "intent": "understand",
51
+ "relevantMemoryTerms": ["react"]
52
+ }
53
+ ],
54
+ "forbiddenCodeEdges": [
55
+ {
56
+ "sourceFile": "src/components/video-player/VideoPlayer.tsx",
57
+ "targetFile": "src/services/webrtc/peer-connection.ts",
58
+ "kind": "calls"
59
+ }
60
+ ]
61
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devflow-tools/benchmark",
3
- "version": "0.16.12",
3
+ "version": "0.16.13",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -18,15 +18,17 @@
18
18
  "accuracy": "npx tsx src/run-accuracy-tests.ts"
19
19
  },
20
20
  "dependencies": {
21
- "@devflow-tools/context-engine": "0.16.12",
22
- "@devflow-tools/sdk": "0.16.12"
21
+ "@devflow-tools/context-engine": "0.16.13",
22
+ "@devflow-tools/database": "0.16.13",
23
+ "@devflow-tools/sdk": "0.16.13"
23
24
  },
24
25
  "devDependencies": {
25
26
  "typescript": "^5.5.0",
26
27
  "vitest": "^2.0.0"
27
28
  },
28
29
  "files": [
29
- "dist"
30
+ "dist",
31
+ "fixtures"
30
32
  ],
31
- "gitHead": "d4a018f3031a3570c794c253f8edeff405956133"
33
+ "gitHead": "67c9dfc3709bd0ce36b7c2a9341896eedcc8a725"
32
34
  }