@devflow-tools/memory-engine 0.16.12 → 0.16.14

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.
Files changed (39) hide show
  1. package/dist/explicit-memory-enricher.d.ts +24 -0
  2. package/dist/explicit-memory-enricher.d.ts.map +1 -0
  3. package/dist/explicit-memory-enricher.js +292 -0
  4. package/dist/explicit-memory-enricher.js.map +1 -0
  5. package/dist/hybrid-search.d.ts +23 -0
  6. package/dist/hybrid-search.d.ts.map +1 -1
  7. package/dist/hybrid-search.js +97 -24
  8. package/dist/hybrid-search.js.map +1 -1
  9. package/dist/index.d.ts +4 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +2 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/memory-engine.d.ts +18 -0
  14. package/dist/memory-engine.d.ts.map +1 -1
  15. package/dist/memory-engine.js +140 -12
  16. package/dist/memory-engine.js.map +1 -1
  17. package/dist/memory-gate.d.ts +17 -0
  18. package/dist/memory-gate.d.ts.map +1 -1
  19. package/dist/memory-gate.js +72 -28
  20. package/dist/memory-gate.js.map +1 -1
  21. package/dist/memory-relevance.d.ts +38 -0
  22. package/dist/memory-relevance.d.ts.map +1 -0
  23. package/dist/memory-relevance.js +289 -0
  24. package/dist/memory-relevance.js.map +1 -0
  25. package/dist/memory-store.d.ts +14 -1
  26. package/dist/memory-store.d.ts.map +1 -1
  27. package/dist/memory-store.js +114 -18
  28. package/dist/memory-store.js.map +1 -1
  29. package/dist/migrations/v2-to-v3.js +1 -1
  30. package/dist/migrations/v2-to-v3.js.map +1 -1
  31. package/dist/migrations/v7-to-v8.d.ts +3 -0
  32. package/dist/migrations/v7-to-v8.d.ts.map +1 -0
  33. package/dist/migrations/v7-to-v8.js +20 -0
  34. package/dist/migrations/v7-to-v8.js.map +1 -0
  35. package/dist/migrations/v8-to-v9.d.ts +3 -0
  36. package/dist/migrations/v8-to-v9.d.ts.map +1 -0
  37. package/dist/migrations/v8-to-v9.js +18 -0
  38. package/dist/migrations/v8-to-v9.js.map +1 -0
  39. package/package.json +4 -4
@@ -0,0 +1,24 @@
1
+ import type { ObservationType } from './observation-types.js';
2
+ export interface ExplicitMemoryEvidenceItem {
3
+ kind: 'dependency' | 'config' | 'instruction' | 'source_event';
4
+ source: string;
5
+ summary: string;
6
+ }
7
+ export interface ExplicitMemoryEvidence {
8
+ type: ObservationType;
9
+ title: string;
10
+ narrative: string;
11
+ facts: string[];
12
+ concepts: string[];
13
+ files: string[];
14
+ tools: string[];
15
+ evidenceStatus: 'verified' | 'unverified';
16
+ evidence: ExplicitMemoryEvidenceItem[];
17
+ }
18
+ export interface EnrichExplicitMemoryInput {
19
+ projectRoot: string;
20
+ content: string;
21
+ sourceEventIds?: string[];
22
+ }
23
+ export declare function enrichExplicitMemory(input: EnrichExplicitMemoryInput): ExplicitMemoryEvidence;
24
+ //# sourceMappingURL=explicit-memory-enricher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explicit-memory-enricher.d.ts","sourceRoot":"","sources":["../src/explicit-memory-enricher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,YAAY,GAAG,QAAQ,GAAG,aAAa,GAAG,cAAc,CAAC;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,EAAE,UAAU,GAAG,YAAY,CAAC;IAC1C,QAAQ,EAAE,0BAA0B,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAwED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,sBAAsB,CAqC7F"}
@@ -0,0 +1,292 @@
1
+ import { closeSync, existsSync, openSync, readSync } from 'node:fs';
2
+ import { join, relative } from 'node:path';
3
+ const MAX_PACKAGE_JSON_BYTES = 256 * 1024;
4
+ const MAX_LOCKFILE_BYTES = 512 * 1024;
5
+ const MAX_CONFIG_BYTES = 128 * 1024;
6
+ const MAX_INSTRUCTION_BYTES = 96 * 1024;
7
+ const MAX_CONTENT_LENGTH = 4_000;
8
+ const ENTITIES = [
9
+ {
10
+ canonical: 'motion',
11
+ aliases: ['motion', 'framer motion', 'framer-motion'],
12
+ packages: ['motion', 'framer-motion'],
13
+ concepts: ['motion', 'animation', 'framer-motion'],
14
+ },
15
+ {
16
+ canonical: 'react',
17
+ aliases: ['react', 'reactjs', 'react.js'],
18
+ packages: ['react'],
19
+ concepts: ['react'],
20
+ },
21
+ {
22
+ canonical: 'tailwind',
23
+ aliases: ['tailwind', 'tailwind css', 'tailwindcss'],
24
+ packages: ['tailwindcss'],
25
+ concepts: ['tailwind', 'tailwindcss', 'css'],
26
+ },
27
+ {
28
+ canonical: 'shadcn',
29
+ aliases: ['shadcn', 'shadcn ui', 'shadcn/ui'],
30
+ packages: ['shadcn'],
31
+ concepts: ['shadcn', 'ui-components'],
32
+ },
33
+ {
34
+ canonical: 'pnpm',
35
+ aliases: ['pnpm'],
36
+ concepts: ['pnpm', 'package-manager'],
37
+ tool: 'pnpm',
38
+ },
39
+ {
40
+ canonical: 'npm',
41
+ aliases: ['npm'],
42
+ concepts: ['npm', 'package-manager'],
43
+ tool: 'npm',
44
+ },
45
+ {
46
+ canonical: 'yarn',
47
+ aliases: ['yarn'],
48
+ concepts: ['yarn', 'package-manager'],
49
+ tool: 'yarn',
50
+ },
51
+ {
52
+ canonical: 'bun',
53
+ aliases: ['bun'],
54
+ concepts: ['bun', 'package-manager'],
55
+ tool: 'bun',
56
+ },
57
+ ];
58
+ const PROJECT_SCOPE = /(?:\bproject\b|\brepository\b|\bcodebase\b|\bteam\b|项目|仓库|代码库|团队|全局|统一|一律)/iu;
59
+ const PERSONAL_PREFERENCE = /(?:\bi\s+(?:prefer|like|want)\b|\bmy preference\b|我(?:更)?(?:喜欢|偏好|希望))/iu;
60
+ const DECISION = /(?:\bdecid(?:e|ed)\b|\bchosen?\b|决定|选定|已选)/iu;
61
+ const CONVENTION = /(?:\b(?:always|never|must|should|required?|standard(?:ize|ized)?)\b|\b(?:do not|don't)\s+use\b|\buse\s+[^\s]+|统一|一律|必须|需要|默认|规范|约定|不要|不使用|使用)/iu;
62
+ export function enrichExplicitMemory(input) {
63
+ const narrative = input.content.normalize('NFKC').trim().slice(0, MAX_CONTENT_LENGTH);
64
+ if (!narrative)
65
+ throw new Error('Explicit memory content must be nonblank');
66
+ const matchedEntities = ENTITIES.filter(entity => containsAlias(narrative, entity.aliases));
67
+ const type = classifyExplicitMemory(narrative);
68
+ const projectEvidence = collectProjectEvidence(input.projectRoot, matchedEntities);
69
+ const sourceEvidence = uniqueStrings(input.sourceEventIds ?? []).map(source => ({
70
+ kind: 'source_event',
71
+ source,
72
+ summary: 'Explicit user memory request captured from the canonical session event.',
73
+ }));
74
+ const evidence = dedupeEvidence([...projectEvidence.evidence, ...sourceEvidence]);
75
+ const concepts = uniqueStrings(matchedEntities.flatMap(entity => entity.concepts));
76
+ const tools = uniqueStrings(matchedEntities.flatMap(entity => entity.tool ? [entity.tool] : []));
77
+ const entitySummary = matchedEntities.map(entity => entity.canonical).join(', ');
78
+ const titlePrefix = type === 'project_convention'
79
+ ? 'Project convention'
80
+ : type === 'decision_made'
81
+ ? 'Project decision'
82
+ : 'User preference';
83
+ const titleSubject = entitySummary || firstClause(narrative);
84
+ return {
85
+ type,
86
+ title: `${titlePrefix}: ${titleSubject}`.slice(0, 160),
87
+ narrative,
88
+ facts: uniqueStrings([
89
+ narrative,
90
+ ...matchedEntities.map(entity => `Referenced entity: ${entity.canonical}`),
91
+ ]),
92
+ concepts,
93
+ files: uniqueStrings(projectEvidence.files),
94
+ tools,
95
+ evidenceStatus: projectEvidence.evidence.length > 0 ? 'verified' : 'unverified',
96
+ evidence,
97
+ };
98
+ }
99
+ function classifyExplicitMemory(content) {
100
+ if (PROJECT_SCOPE.test(content) && (CONVENTION.test(content) || DECISION.test(content))) {
101
+ return 'project_convention';
102
+ }
103
+ if (PERSONAL_PREFERENCE.test(content))
104
+ return 'user_preference';
105
+ if (DECISION.test(content))
106
+ return 'decision_made';
107
+ if (CONVENTION.test(content))
108
+ return 'project_convention';
109
+ return 'user_preference';
110
+ }
111
+ function collectProjectEvidence(projectRoot, entities) {
112
+ if (entities.length === 0)
113
+ return { evidence: [], files: [] };
114
+ const evidence = [];
115
+ const files = [];
116
+ const packagePath = join(projectRoot, 'package.json');
117
+ const packageText = readBoundedText(packagePath, MAX_PACKAGE_JSON_BYTES);
118
+ if (packageText !== null) {
119
+ const dependencyVersions = parseDependencyVersions(packageText);
120
+ const packageManager = parsePackageManager(packageText);
121
+ for (const entity of entities) {
122
+ for (const packageName of entity.packages ?? []) {
123
+ const version = dependencyVersions.get(packageName);
124
+ if (!version)
125
+ continue;
126
+ addEvidence(evidence, files, projectRoot, packagePath, {
127
+ kind: 'dependency',
128
+ source: 'package.json',
129
+ summary: `${packageName} is declared at ${version}.`,
130
+ });
131
+ }
132
+ if (entity.tool && packageManager?.name === entity.tool) {
133
+ addEvidence(evidence, files, projectRoot, packagePath, {
134
+ kind: 'config',
135
+ source: 'package.json',
136
+ summary: `packageManager selects ${packageManager.raw}.`,
137
+ });
138
+ }
139
+ }
140
+ }
141
+ const lockfiles = [
142
+ { name: 'package-lock.json', tool: 'npm' },
143
+ { name: 'pnpm-lock.yaml', tool: 'pnpm' },
144
+ { name: 'yarn.lock', tool: 'yarn' },
145
+ { name: 'bun.lock', tool: 'bun' },
146
+ { name: 'bun.lockb', tool: 'bun' },
147
+ ];
148
+ for (const lockfile of lockfiles) {
149
+ const path = join(projectRoot, lockfile.name);
150
+ const text = readBoundedText(path, MAX_LOCKFILE_BYTES);
151
+ if (text === null)
152
+ continue;
153
+ for (const entity of entities) {
154
+ const packageMatch = (entity.packages ?? []).find(packageName => lockfileContainsPackage(text, packageName));
155
+ if (packageMatch) {
156
+ addEvidence(evidence, files, projectRoot, path, {
157
+ kind: 'dependency',
158
+ source: lockfile.name,
159
+ summary: `${packageMatch} is resolved by ${lockfile.name}.`,
160
+ });
161
+ }
162
+ if (entity.tool === lockfile.tool) {
163
+ addEvidence(evidence, files, projectRoot, path, {
164
+ kind: 'config',
165
+ source: lockfile.name,
166
+ summary: `${lockfile.name} confirms the ${lockfile.tool} package-manager workflow.`,
167
+ });
168
+ }
169
+ }
170
+ }
171
+ const configFiles = ['.devflow/config.json', 'components.json'];
172
+ for (const name of configFiles) {
173
+ collectTextEvidence(projectRoot, name, MAX_CONFIG_BYTES, 'config', entities, evidence, files);
174
+ }
175
+ const instructionFiles = ['CLAUDE.md', 'AGENTS.md', 'GEMINI.md', '.github/copilot-instructions.md'];
176
+ for (const name of instructionFiles) {
177
+ collectTextEvidence(projectRoot, name, MAX_INSTRUCTION_BYTES, 'instruction', entities, evidence, files);
178
+ }
179
+ return { evidence: dedupeEvidence(evidence), files: uniqueStrings(files) };
180
+ }
181
+ function collectTextEvidence(projectRoot, name, maxBytes, kind, entities, evidence, files) {
182
+ const path = join(projectRoot, name);
183
+ const text = readBoundedText(path, maxBytes);
184
+ if (text === null)
185
+ return;
186
+ for (const entity of entities) {
187
+ if (!containsAlias(text, entity.aliases))
188
+ continue;
189
+ addEvidence(evidence, files, projectRoot, path, {
190
+ kind,
191
+ source: name,
192
+ summary: `${name} references ${entity.canonical}.`,
193
+ });
194
+ }
195
+ }
196
+ function addEvidence(evidence, files, projectRoot, path, item) {
197
+ evidence.push(item);
198
+ files.push(relative(projectRoot, path) || item.source);
199
+ }
200
+ function parseDependencyVersions(text) {
201
+ try {
202
+ const parsed = JSON.parse(text);
203
+ const result = new Map();
204
+ for (const field of ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies']) {
205
+ const dependencies = parsed[field];
206
+ if (!dependencies || typeof dependencies !== 'object' || Array.isArray(dependencies))
207
+ continue;
208
+ for (const [name, version] of Object.entries(dependencies)) {
209
+ if (typeof version === 'string')
210
+ result.set(name, version);
211
+ }
212
+ }
213
+ return result;
214
+ }
215
+ catch {
216
+ return new Map();
217
+ }
218
+ }
219
+ function parsePackageManager(text) {
220
+ try {
221
+ const parsed = JSON.parse(text);
222
+ if (typeof parsed.packageManager !== 'string')
223
+ return null;
224
+ const raw = parsed.packageManager.trim();
225
+ const name = raw.split('@')[0]?.toLowerCase();
226
+ return name ? { name, raw } : null;
227
+ }
228
+ catch {
229
+ return null;
230
+ }
231
+ }
232
+ function lockfileContainsPackage(text, packageName) {
233
+ const escaped = escapeRegExp(packageName);
234
+ return new RegExp(`(?:node_modules/|[/'\"\\s])${escaped}(?:@|[/'\"\\s:])`, 'iu').test(text);
235
+ }
236
+ function containsAlias(text, aliases) {
237
+ const normalized = text.normalize('NFKC').toLocaleLowerCase('en-US');
238
+ return aliases.some(alias => {
239
+ const escaped = escapeRegExp(alias.toLocaleLowerCase('en-US')).replace(/\\[\s/.-]/g, '[\\s/.-]+');
240
+ // ASCII technology names often touch CJK text directly, as in
241
+ // "使用motion作为". Only adjacent ASCII identifier characters block a match.
242
+ return new RegExp(`(^|[^a-z0-9_])${escaped}(?=$|[^a-z0-9_])`, 'u').test(normalized);
243
+ });
244
+ }
245
+ function readBoundedText(path, maxBytes) {
246
+ if (!existsSync(path))
247
+ return null;
248
+ let descriptor;
249
+ try {
250
+ descriptor = openSync(path, 'r');
251
+ const buffer = Buffer.allocUnsafe(maxBytes);
252
+ const bytesRead = readSync(descriptor, buffer, 0, maxBytes, 0);
253
+ return buffer.subarray(0, bytesRead).toString('utf8');
254
+ }
255
+ catch {
256
+ return null;
257
+ }
258
+ finally {
259
+ if (descriptor !== undefined)
260
+ closeSync(descriptor);
261
+ }
262
+ }
263
+ function firstClause(value) {
264
+ return value.split(/[.。!!??\n]/u)[0].trim().slice(0, 120) || 'explicit memory';
265
+ }
266
+ function dedupeEvidence(items) {
267
+ const seen = new Set();
268
+ return items.filter(item => {
269
+ const key = `${item.kind}\0${item.source}\0${item.summary}`;
270
+ if (seen.has(key))
271
+ return false;
272
+ seen.add(key);
273
+ return true;
274
+ }).slice(0, 32);
275
+ }
276
+ function uniqueStrings(values) {
277
+ const seen = new Set();
278
+ const result = [];
279
+ for (const value of values) {
280
+ const normalized = value.normalize('NFKC').trim();
281
+ const key = normalized.toLocaleLowerCase('en-US');
282
+ if (!normalized || seen.has(key))
283
+ continue;
284
+ seen.add(key);
285
+ result.push(normalized);
286
+ }
287
+ return result.slice(0, 32);
288
+ }
289
+ function escapeRegExp(value) {
290
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
291
+ }
292
+ //# sourceMappingURL=explicit-memory-enricher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explicit-memory-enricher.js","sourceRoot":"","sources":["../src/explicit-memory-enricher.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,8 @@ export interface SearchOptions {
11
11
  sessionId?: string;
12
12
  maxPerFailureCategory?: number;
13
13
  excludedIds?: ReadonlySet<string>;
14
+ requestId?: string;
15
+ executionId?: string;
14
16
  }
15
17
  export interface SearchResultEntry {
16
18
  id: string;
@@ -31,10 +33,30 @@ export interface SearchResultEntry {
31
33
  resolutionState: 'current' | 'resolved' | 'superseded';
32
34
  failureCategory: FailureCategory | null;
33
35
  clusterKey: string;
36
+ concepts: string[];
37
+ evidenceStatus: 'verified' | 'unverified';
34
38
  }
35
39
  export interface SearchResult {
36
40
  entry: SearchResultEntry;
37
41
  score: number;
42
+ applicability?: string[];
43
+ relevanceSignals?: {
44
+ semantic: number;
45
+ entityOverlap: number;
46
+ evidenceStrength: number;
47
+ taskApplicability: number;
48
+ };
49
+ }
50
+ export interface SearchDiagnostics {
51
+ threshold: number;
52
+ candidateCount: number;
53
+ selectedCount: number;
54
+ rejectedCount: number;
55
+ rejectionCategories: Record<string, number>;
56
+ }
57
+ export interface SearchWithDiagnosticsResult {
58
+ results: SearchResult[];
59
+ diagnostics: SearchDiagnostics;
38
60
  }
39
61
  export declare function rrfFusion(results: Map<string, {
40
62
  ranks: Map<string, number>;
@@ -49,5 +71,6 @@ export declare class HybridSearch {
49
71
  private engine;
50
72
  constructor(store: MemoryStore, embedder: EmbeddingProvider, engine?: MemoryEngine);
51
73
  search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
74
+ searchWithDiagnostics(query: string, options?: SearchOptions): Promise<SearchWithDiagnosticsResult>;
52
75
  }
53
76
  //# sourceMappingURL=hybrid-search.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hybrid-search.d.ts","sourceRoot":"","sources":["../src/hybrid-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,SAAS,GAAG,UAAU,GAAG,YAAY,CAAC;IACvD,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,iBAAiB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAcD,wBAAgB,SAAS,CACvB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,CAAC,EAC9E,CAAC,EAAE,MAAM,GACR,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAkBtC;AAmED,qBAAa,YAAY;IAIrB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;IAJlB,OAAO,CAAC,MAAM,CAAsB;gBAG1B,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,iBAAiB,EACnC,MAAM,CAAC,EAAE,YAAY;IAKjB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CAwNlF"}
1
+ {"version":3,"file":"hybrid-search.d.ts","sourceRoot":"","sources":["../src/hybrid-search.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { classifyFailureCategory, observationClusterKey, } from './observation-quality.js';
2
+ import { evaluateMemoryRelevance, MEMORY_SELECTION_THRESHOLD, } from './memory-relevance.js';
2
3
  const DEFAULT_WEIGHTS = {
3
4
  bm25: 0.25,
4
5
  observationBm25: 0.2,
@@ -53,10 +54,12 @@ function rowToEntry(row) {
53
54
  title: row.title,
54
55
  narrative: row.content,
55
56
  }),
57
+ concepts: [],
58
+ evidenceStatus: row.source === 'manual' ? 'verified' : 'unverified',
56
59
  };
57
60
  }
58
61
  function observationToEntry(row) {
59
- const createdAt = row.source === 'explicit_intent' && row.type === 'user_preference'
62
+ const createdAt = row.source === 'explicit_intent'
60
63
  ? row.explicit_accepted_at ?? row.timestamp
61
64
  : row.timestamp;
62
65
  return {
@@ -83,6 +86,8 @@ function observationToEntry(row) {
83
86
  narrative: row.narrative,
84
87
  facts: parseStringArray(row.facts),
85
88
  }),
89
+ concepts: parseStringArray(row.concepts),
90
+ evidenceStatus: row.evidence_status,
86
91
  };
87
92
  }
88
93
  const MIN_EFFECTIVE_CONFIDENCE = 0.3;
@@ -96,10 +101,22 @@ export class HybridSearch {
96
101
  this.engine = engine ?? null;
97
102
  }
98
103
  async search(query, options = {}) {
104
+ return (await this.searchWithDiagnostics(query, options)).results;
105
+ }
106
+ async searchWithDiagnostics(query, options = {}) {
99
107
  const requestedLimit = options.limit ?? 10;
100
108
  const limit = Number.isFinite(requestedLimit) ? Math.max(0, Math.floor(requestedLimit)) : 10;
101
109
  if (limit === 0)
102
- return [];
110
+ return {
111
+ results: [],
112
+ diagnostics: {
113
+ threshold: MEMORY_SELECTION_THRESHOLD,
114
+ candidateCount: 0,
115
+ selectedCount: 0,
116
+ rejectedCount: 0,
117
+ rejectionCategories: {},
118
+ },
119
+ };
103
120
  const exclusionAllowance = options.excludedIds?.size ?? 0;
104
121
  const fetchLimit = limit * 3 + exclusionAllowance;
105
122
  let bm25Results = [];
@@ -114,10 +131,17 @@ export class HybridSearch {
114
131
  catch { /* Observation lexical retrieval is independently non-fatal */ }
115
132
  let vectorResults = [];
116
133
  let observationResults = [];
134
+ const semanticScores = new Map();
117
135
  try {
118
136
  const embedding = await this.embedder.embed(query);
119
137
  vectorResults = this.store.searchVector(embedding, fetchLimit);
120
138
  observationResults = this.store.searchObservationVector(embedding, fetchLimit, options.excludedIds);
139
+ for (const result of vectorResults) {
140
+ semanticScores.set(result.id, cosineSimilarityFromDistance(result.distance));
141
+ }
142
+ for (const result of observationResults) {
143
+ semanticScores.set(result.observation.id, cosineSimilarityFromDistance(result.distance));
144
+ }
121
145
  }
122
146
  catch { /* embedding may fail */ }
123
147
  const graphIds = new Set();
@@ -207,30 +231,53 @@ export class HybridSearch {
207
231
  continue;
208
232
  newestResolutionByCategory.set(entry.failureCategory, Math.max(newestResolutionByCategory.get(entry.failureCategory) ?? 0, entry.createdAt));
209
233
  }
210
- const now = Date.now();
234
+ const rejected = new Map();
211
235
  const ranked = fused.map(result => {
212
236
  const entry = docs.get(result.id).entry;
213
- const ageDays = Math.max(0, now - entry.createdAt) / 86_400_000;
214
- const recency = Math.exp(-ageDays / 180);
215
- const accessFeedback = Math.min(1, Math.log1p(entry.accessCount) / Math.log(11));
216
- const projectMatch = options.scope ? (entry.scope === options.scope ? 1 : 0) : 0.5;
217
- const evidenceScore = 0.28 * entry.confidence
218
- + 0.22 * entry.strength
219
- + 0.2 * recency
220
- + 0.15 * projectMatch
221
- + 0.15 * accessFeedback;
222
- let score = 0.55 * result.score + 0.45 * evidenceScore;
223
- if (entry.resolutionState === 'resolved')
224
- score *= 0.85;
225
- if (entry.resolutionState === 'superseded')
226
- score *= 0.1;
227
237
  const newerResolution = entry.failureCategory
228
238
  ? newestResolutionByCategory.get(entry.failureCategory)
229
239
  : undefined;
230
- if (entry.type !== 'error_resolution' && newerResolution && newerResolution > entry.createdAt) {
231
- score *= 0.3;
240
+ const failureCategory = entry.type !== 'error_resolution'
241
+ && newerResolution
242
+ && newerResolution > entry.createdAt
243
+ ? entry.failureCategory
244
+ : entry.failureCategory;
245
+ const evaluation = evaluateMemoryRelevance({
246
+ query,
247
+ purpose: options.purpose,
248
+ type: entry.type,
249
+ source: entry.source === 'observation' ? this.store.getObservation(entry.id)?.source ?? 'distill' : entry.source,
250
+ title: entry.title,
251
+ content: entry.content,
252
+ concepts: entry.concepts,
253
+ evidenceStatus: entry.evidenceStatus,
254
+ confidence: entry.confidence,
255
+ importance: entry.strength * 10,
256
+ createdAt: entry.createdAt,
257
+ semanticScore: semanticScores.get(entry.id) ?? 0,
258
+ resolutionState: entry.resolutionState,
259
+ failureCategory,
260
+ });
261
+ if (!evaluation.eligible && evaluation.rejectionReason) {
262
+ rejected.set(evaluation.rejectionReason, (rejected.get(evaluation.rejectionReason) ?? 0) + 1);
263
+ if (options.requestId) {
264
+ try {
265
+ this.store.recordRetrievalAccess({
266
+ sourceType: entry.source === 'observation' ? 'observation' : 'memory',
267
+ sourceId: entry.id,
268
+ accessType: 'rejected',
269
+ sessionId: options.sessionId,
270
+ requestId: options.requestId,
271
+ executionId: options.executionId,
272
+ query,
273
+ purpose: `${options.purpose ?? 'search'}:${evaluation.rejectionReason}`,
274
+ score: 0,
275
+ });
276
+ }
277
+ catch { /* rejection telemetry is non-critical */ }
278
+ }
232
279
  }
233
- return { ...result, score };
280
+ return { ...result, score: evaluation.score, evaluation };
234
281
  }).sort((left, right) => right.score - left.score
235
282
  || docs.get(right.id).entry.createdAt - docs.get(left.id).entry.createdAt
236
283
  || left.id.localeCompare(right.id));
@@ -239,7 +286,9 @@ export class HybridSearch {
239
286
  const sessionCounts = new Map();
240
287
  const failureCategoryCounts = new Map();
241
288
  const maxPerFailureCategory = Math.max(1, options.maxPerFailureCategory ?? 2);
242
- for (const { id, score } of ranked) {
289
+ for (const { id, score, evaluation } of ranked) {
290
+ if (!evaluation.eligible)
291
+ continue;
243
292
  if (options.excludedIds?.has(id))
244
293
  continue;
245
294
  const doc = docs.get(id);
@@ -280,18 +329,30 @@ export class HybridSearch {
280
329
  sessionCounts.set(doc.entry.sessionId, (sessionCounts.get(doc.entry.sessionId) ?? 0) + 1);
281
330
  }
282
331
  const roundedScore = Math.round(score * 10000) / 10000;
283
- results.push({ entry: doc.entry, score: roundedScore });
332
+ results.push({
333
+ entry: doc.entry,
334
+ score: roundedScore,
335
+ applicability: evaluation.applicability,
336
+ relevanceSignals: {
337
+ semantic: evaluation.signals.semantic,
338
+ entityOverlap: evaluation.signals.entityOverlap,
339
+ evidenceStrength: evaluation.signals.evidenceStrength,
340
+ taskApplicability: evaluation.signals.taskApplicability,
341
+ },
342
+ });
284
343
  if (options.recordAccess !== false) {
285
344
  try {
286
345
  this.store.recordRetrievalAccess({
287
346
  sourceType: doc.entry.source === 'observation' ? 'observation' : 'memory',
288
347
  sourceId: doc.entry.id,
289
- accessType: 'search_hit',
348
+ accessType: 'exposed',
290
349
  sessionId: options.sessionId,
291
350
  query,
292
351
  purpose: options.purpose ?? 'search',
293
352
  rank: results.length,
294
353
  score: roundedScore,
354
+ requestId: options.requestId,
355
+ executionId: options.executionId,
295
356
  });
296
357
  }
297
358
  catch { /* non-critical */ }
@@ -299,9 +360,21 @@ export class HybridSearch {
299
360
  if (results.length >= limit)
300
361
  break;
301
362
  }
302
- return results;
363
+ return {
364
+ results,
365
+ diagnostics: {
366
+ threshold: MEMORY_SELECTION_THRESHOLD,
367
+ candidateCount: docs.size,
368
+ selectedCount: results.length,
369
+ rejectedCount: Math.max(0, docs.size - results.length),
370
+ rejectionCategories: Object.fromEntries(rejected),
371
+ },
372
+ };
303
373
  }
304
374
  }
375
+ function cosineSimilarityFromDistance(distance) {
376
+ return Math.max(0, Math.min(1, 1 - distance));
377
+ }
305
378
  function parseStringArray(value) {
306
379
  try {
307
380
  const parsed = JSON.parse(value);