@getplumb/core 0.4.0 → 0.4.1
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 +1 -1
- package/dist/extraction-queue.d.ts +0 -72
- package/dist/extraction-queue.d.ts.map +0 -1
- package/dist/extraction-queue.js +0 -101
- package/dist/extraction-queue.js.map +0 -1
- package/dist/extractor.d.ts +0 -22
- package/dist/extractor.d.ts.map +0 -1
- package/dist/extractor.js +0 -188
- package/dist/extractor.js.map +0 -1
- package/dist/extractor.test.d.ts +0 -2
- package/dist/extractor.test.d.ts.map +0 -1
- package/dist/extractor.test.js +0 -158
- package/dist/extractor.test.js.map +0 -1
- package/dist/fact-search.d.ts +0 -32
- package/dist/fact-search.d.ts.map +0 -1
- package/dist/fact-search.js +0 -174
- package/dist/fact-search.js.map +0 -1
- package/dist/fact-search.test.d.ts +0 -12
- package/dist/fact-search.test.d.ts.map +0 -1
- package/dist/fact-search.test.js +0 -117
- package/dist/fact-search.test.js.map +0 -1
- package/dist/llm-client.d.ts +0 -59
- package/dist/llm-client.d.ts.map +0 -1
- package/dist/llm-client.js +0 -227
- package/dist/llm-client.js.map +0 -1
- package/dist/local-store.test.d.ts +0 -2
- package/dist/local-store.test.d.ts.map +0 -1
- package/dist/local-store.test.js +0 -146
- package/dist/local-store.test.js.map +0 -1
- package/dist/raw-log-search.test.d.ts +0 -12
- package/dist/raw-log-search.test.d.ts.map +0 -1
- package/dist/raw-log-search.test.js +0 -124
- package/dist/raw-log-search.test.js.map +0 -1
- package/dist/read-path.test.d.ts +0 -15
- package/dist/read-path.test.d.ts.map +0 -1
- package/dist/read-path.test.js +0 -393
- package/dist/read-path.test.js.map +0 -1
- package/dist/scorer.test.d.ts +0 -10
- package/dist/scorer.test.d.ts.map +0 -1
- package/dist/scorer.test.js +0 -169
- package/dist/scorer.test.js.map +0 -1
package/dist/read-path.test.js
DELETED
|
@@ -1,393 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for read-path.ts (buildMemoryContext) and context-builder.ts (formatContextBlock).
|
|
3
|
-
*
|
|
4
|
-
* Strategy:
|
|
5
|
-
* - Unit tests use a mock ReadPathStore to avoid ML model downloads and keep
|
|
6
|
-
* tests fast and deterministic.
|
|
7
|
-
* - One integration smoke test uses a real LocalStore with real facts inserted
|
|
8
|
-
* via store.store() (keyword search, no embedder needed) to verify the
|
|
9
|
-
* end-to-end cross-session provenance path.
|
|
10
|
-
*
|
|
11
|
-
* Cross-session test (acceptance criteria): facts ingested in session A must
|
|
12
|
-
* be returned when querying in session B context — no session filter applied.
|
|
13
|
-
*/
|
|
14
|
-
import { test, describe, after } from 'node:test';
|
|
15
|
-
import assert from 'node:assert/strict';
|
|
16
|
-
import { tmpdir } from 'node:os';
|
|
17
|
-
import { join } from 'node:path';
|
|
18
|
-
import { rmSync } from 'node:fs';
|
|
19
|
-
import { buildMemoryContext } from './read-path.js';
|
|
20
|
-
import { formatContextBlock, formatAge } from './context-builder.js';
|
|
21
|
-
import { LocalStore } from './local-store.js';
|
|
22
|
-
import { DecayRate } from './types.js';
|
|
23
|
-
// ─── Mock store factory ───────────────────────────────────────────────────────
|
|
24
|
-
function makeStore(searchResults = [], rawLogResults = []) {
|
|
25
|
-
let searchCallCount = 0;
|
|
26
|
-
let rawLogCallCount = 0;
|
|
27
|
-
return {
|
|
28
|
-
get searchCallCount() { return searchCallCount; },
|
|
29
|
-
get rawLogCallCount() { return rawLogCallCount; },
|
|
30
|
-
async search(_query, _limit) {
|
|
31
|
-
searchCallCount++;
|
|
32
|
-
return searchResults;
|
|
33
|
-
},
|
|
34
|
-
async searchRawLog(_query, _limit) {
|
|
35
|
-
rawLogCallCount++;
|
|
36
|
-
return rawLogResults;
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
/** Build a minimal Fact with configurable fields. */
|
|
41
|
-
function makeFact(opts) {
|
|
42
|
-
const now = opts.now ?? new Date('2026-01-01T00:00:00.000Z');
|
|
43
|
-
const ageInDays = opts.ageInDays ?? 0;
|
|
44
|
-
const timestamp = new Date(now.getTime() - ageInDays * 24 * 60 * 60 * 1_000);
|
|
45
|
-
return {
|
|
46
|
-
id: crypto.randomUUID(),
|
|
47
|
-
subject: opts.subject ?? 'user',
|
|
48
|
-
predicate: opts.predicate ?? 'is',
|
|
49
|
-
object: opts.object ?? 'a developer',
|
|
50
|
-
confidence: opts.confidence,
|
|
51
|
-
decayRate: opts.decayRate ?? DecayRate.slow,
|
|
52
|
-
timestamp,
|
|
53
|
-
sourceSessionId: opts.sessionId ?? 'session-default',
|
|
54
|
-
...(opts.sessionLabel !== undefined ? { sourceSessionLabel: opts.sessionLabel } : {}),
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
/** Build a SearchResult wrapping a fact (store score is ignored; read-path re-scores). */
|
|
58
|
-
function makeSearchResult(fact, now) {
|
|
59
|
-
const ageInDays = (now.getTime() - fact.timestamp.getTime()) / (1_000 * 60 * 60 * 24);
|
|
60
|
-
return { fact, score: 1.0, ageInDays };
|
|
61
|
-
}
|
|
62
|
-
/** Build a RawLogSearchResult for testing. */
|
|
63
|
-
function makeRawChunk(opts) {
|
|
64
|
-
const now = opts.now ?? new Date('2026-01-01T00:00:00.000Z');
|
|
65
|
-
const ageInDays = opts.ageInDays ?? 0;
|
|
66
|
-
const timestamp = new Date(now.getTime() - ageInDays * 24 * 60 * 60 * 1_000);
|
|
67
|
-
return {
|
|
68
|
-
chunk_text: opts.text,
|
|
69
|
-
session_id: opts.sessionId,
|
|
70
|
-
session_label: opts.sessionLabel ?? null,
|
|
71
|
-
timestamp: timestamp.toISOString(),
|
|
72
|
-
final_score: opts.score ?? 0.5,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
// ─── formatAge unit tests ─────────────────────────────────────────────────────
|
|
76
|
-
describe('formatAge', () => {
|
|
77
|
-
test('< 1 day → today', () => {
|
|
78
|
-
assert.equal(formatAge(0), 'today');
|
|
79
|
-
assert.equal(formatAge(0.5), 'today');
|
|
80
|
-
assert.equal(formatAge(0.99), 'today');
|
|
81
|
-
});
|
|
82
|
-
test('1-2 days → yesterday', () => {
|
|
83
|
-
assert.equal(formatAge(1), 'yesterday');
|
|
84
|
-
assert.equal(formatAge(1.9), 'yesterday');
|
|
85
|
-
});
|
|
86
|
-
test('2-7 days → N days ago', () => {
|
|
87
|
-
assert.equal(formatAge(2), '2 days ago');
|
|
88
|
-
assert.equal(formatAge(6.9), '6 days ago');
|
|
89
|
-
});
|
|
90
|
-
test('7-14 days → 1 week ago', () => {
|
|
91
|
-
assert.equal(formatAge(7), '1 week ago');
|
|
92
|
-
assert.equal(formatAge(13.9), '1 week ago');
|
|
93
|
-
});
|
|
94
|
-
test('14-30 days → N weeks ago', () => {
|
|
95
|
-
assert.equal(formatAge(14), '2 weeks ago');
|
|
96
|
-
assert.equal(formatAge(21), '3 weeks ago');
|
|
97
|
-
});
|
|
98
|
-
test('30-60 days → 1 month ago', () => {
|
|
99
|
-
assert.equal(formatAge(30), '1 month ago');
|
|
100
|
-
assert.equal(formatAge(59), '1 month ago');
|
|
101
|
-
});
|
|
102
|
-
test('60-365 days → N months ago', () => {
|
|
103
|
-
assert.equal(formatAge(60), '2 months ago');
|
|
104
|
-
assert.equal(formatAge(90), '3 months ago');
|
|
105
|
-
});
|
|
106
|
-
test('365-730 days → 1 year ago', () => {
|
|
107
|
-
assert.equal(formatAge(365), '1 year ago');
|
|
108
|
-
assert.equal(formatAge(729), '1 year ago');
|
|
109
|
-
});
|
|
110
|
-
test('≥ 730 days → N years ago', () => {
|
|
111
|
-
assert.equal(formatAge(730), '2 years ago');
|
|
112
|
-
assert.equal(formatAge(1095), '3 years ago');
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
// ─── buildMemoryContext unit tests ────────────────────────────────────────────
|
|
116
|
-
describe('buildMemoryContext', () => {
|
|
117
|
-
const NOW = new Date('2026-01-01T00:00:00.000Z');
|
|
118
|
-
test('queries Layer 1 and Layer 2 in parallel (both called once)', async () => {
|
|
119
|
-
const store = makeStore();
|
|
120
|
-
await buildMemoryContext('anything', store, { now: NOW });
|
|
121
|
-
assert.equal(store.searchCallCount, 1, 'search() must be called once');
|
|
122
|
-
assert.equal(store.rawLogCallCount, 1, 'searchRawLog() must be called once');
|
|
123
|
-
});
|
|
124
|
-
test('empty store → empty MemoryContext', async () => {
|
|
125
|
-
const store = makeStore();
|
|
126
|
-
const ctx = await buildMemoryContext('test query', store, { now: NOW });
|
|
127
|
-
assert.deepEqual(ctx.highConfidence, []);
|
|
128
|
-
assert.deepEqual(ctx.mediumConfidence, []);
|
|
129
|
-
assert.deepEqual(ctx.lowConfidence, []);
|
|
130
|
-
assert.deepEqual(ctx.relatedConversations, []);
|
|
131
|
-
});
|
|
132
|
-
test('facts tiered correctly by scoreFact() score', async () => {
|
|
133
|
-
// confidence=0.95, slow decay, age=0 → score ~0.95 (high)
|
|
134
|
-
const highFact = makeFact({ confidence: 0.95, decayRate: DecayRate.slow, ageInDays: 0, now: NOW });
|
|
135
|
-
// confidence=0.5, slow decay, age=0 → score ~0.5 (medium)
|
|
136
|
-
const medFact = makeFact({ confidence: 0.5, decayRate: DecayRate.slow, ageInDays: 0, now: NOW });
|
|
137
|
-
// confidence=0.2, slow decay, age=0 → score ~0.2 (low)
|
|
138
|
-
const lowFact = makeFact({ confidence: 0.2, decayRate: DecayRate.slow, ageInDays: 0, now: NOW });
|
|
139
|
-
const store = makeStore([
|
|
140
|
-
makeSearchResult(highFact, NOW),
|
|
141
|
-
makeSearchResult(medFact, NOW),
|
|
142
|
-
makeSearchResult(lowFact, NOW),
|
|
143
|
-
]);
|
|
144
|
-
const ctx = await buildMemoryContext('query', store, { now: NOW });
|
|
145
|
-
assert.equal(ctx.highConfidence.length, 1, 'one high-confidence fact');
|
|
146
|
-
assert.equal(ctx.mediumConfidence.length, 1, 'one medium-confidence fact');
|
|
147
|
-
assert.equal(ctx.lowConfidence.length, 1, 'one low-confidence fact');
|
|
148
|
-
assert.ok(ctx.highConfidence[0].score > 0.7, 'high score > 0.7');
|
|
149
|
-
assert.ok(ctx.mediumConfidence[0].score >= 0.3 && ctx.mediumConfidence[0].score <= 0.7);
|
|
150
|
-
assert.ok(ctx.lowConfidence[0].score < 0.3, 'low score < 0.3');
|
|
151
|
-
});
|
|
152
|
-
test('facts sorted by score descending within each tier', async () => {
|
|
153
|
-
const f1 = makeFact({ confidence: 0.95, decayRate: DecayRate.slow, ageInDays: 0, now: NOW });
|
|
154
|
-
const f2 = makeFact({ confidence: 0.85, decayRate: DecayRate.slow, ageInDays: 0, now: NOW });
|
|
155
|
-
const f3 = makeFact({ confidence: 0.72, decayRate: DecayRate.slow, ageInDays: 0, now: NOW });
|
|
156
|
-
const store = makeStore([
|
|
157
|
-
makeSearchResult(f3, NOW),
|
|
158
|
-
makeSearchResult(f1, NOW),
|
|
159
|
-
makeSearchResult(f2, NOW),
|
|
160
|
-
]);
|
|
161
|
-
const ctx = await buildMemoryContext('query', store, { now: NOW });
|
|
162
|
-
const scores = ctx.highConfidence.map((sf) => sf.score);
|
|
163
|
-
for (let i = 1; i < scores.length; i++) {
|
|
164
|
-
assert.ok(scores[i - 1] >= scores[i], 'scores should be descending');
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
test('respects maxFactsPerTier limit', async () => {
|
|
168
|
-
const facts = Array.from({ length: 10 }, () => makeFact({ confidence: 0.9, decayRate: DecayRate.slow, ageInDays: 0, now: NOW }));
|
|
169
|
-
const store = makeStore(facts.map((f) => makeSearchResult(f, NOW)));
|
|
170
|
-
const ctx = await buildMemoryContext('query', store, { now: NOW, maxFactsPerTier: 3 });
|
|
171
|
-
assert.ok(ctx.highConfidence.length <= 3, 'high tier capped at 3');
|
|
172
|
-
});
|
|
173
|
-
test('respects maxRawChunks limit', async () => {
|
|
174
|
-
const chunks = Array.from({ length: 6 }, (_, i) => makeRawChunk({ text: `chunk ${i}`, sessionId: `sess-${i}`, score: 0.9 - i * 0.1, now: NOW }));
|
|
175
|
-
const store = makeStore([], chunks);
|
|
176
|
-
const ctx = await buildMemoryContext('query', store, { now: NOW, maxRawChunks: 2 });
|
|
177
|
-
assert.ok(ctx.relatedConversations.length <= 2, 'raw chunks capped at 2');
|
|
178
|
-
});
|
|
179
|
-
test('provenance fields present on ScoredFact', async () => {
|
|
180
|
-
const fact = makeFact({
|
|
181
|
-
confidence: 0.9,
|
|
182
|
-
decayRate: DecayRate.slow,
|
|
183
|
-
ageInDays: 3,
|
|
184
|
-
sessionId: 'session-A',
|
|
185
|
-
sessionLabel: 'planning-session',
|
|
186
|
-
now: NOW,
|
|
187
|
-
});
|
|
188
|
-
const store = makeStore([makeSearchResult(fact, NOW)]);
|
|
189
|
-
const ctx = await buildMemoryContext('query', store, { now: NOW });
|
|
190
|
-
const sf = ctx.highConfidence[0];
|
|
191
|
-
assert.ok(sf !== undefined, 'should have a high confidence fact');
|
|
192
|
-
assert.equal(sf.fact.sourceSessionId, 'session-A');
|
|
193
|
-
assert.equal(sf.fact.sourceSessionLabel, 'planning-session');
|
|
194
|
-
assert.ok(sf.ageInDays >= 3 && sf.ageInDays < 4, `ageInDays should be ~3, got ${sf.ageInDays}`);
|
|
195
|
-
});
|
|
196
|
-
test('provenance fields present on RawChunk', async () => {
|
|
197
|
-
const chunk = makeRawChunk({
|
|
198
|
-
text: 'We discussed the memory architecture in detail.',
|
|
199
|
-
sessionId: 'session-B',
|
|
200
|
-
sessionLabel: 'architecture-review',
|
|
201
|
-
ageInDays: 1,
|
|
202
|
-
score: 0.8,
|
|
203
|
-
now: NOW,
|
|
204
|
-
});
|
|
205
|
-
const store = makeStore([], [chunk]);
|
|
206
|
-
const ctx = await buildMemoryContext('query', store, { now: NOW });
|
|
207
|
-
const rc = ctx.relatedConversations[0];
|
|
208
|
-
assert.ok(rc !== undefined, 'should have a related conversation');
|
|
209
|
-
assert.equal(rc.sessionId, 'session-B');
|
|
210
|
-
assert.equal(rc.sessionLabel, 'architecture-review');
|
|
211
|
-
assert.equal(rc.score, 0.8);
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
// ─── formatContextBlock unit tests ───────────────────────────────────────────
|
|
215
|
-
describe('formatContextBlock', () => {
|
|
216
|
-
const NOW = new Date('2026-01-01T00:00:00.000Z');
|
|
217
|
-
test('empty MemoryContext → empty string (no block injected)', () => {
|
|
218
|
-
const ctx = {
|
|
219
|
-
highConfidence: [],
|
|
220
|
-
mediumConfidence: [],
|
|
221
|
-
lowConfidence: [],
|
|
222
|
-
relatedConversations: [],
|
|
223
|
-
};
|
|
224
|
-
assert.equal(formatContextBlock(ctx), '');
|
|
225
|
-
});
|
|
226
|
-
test('output starts with [MEMORY CONTEXT]', () => {
|
|
227
|
-
const fact = makeFact({ confidence: 0.9, decayRate: DecayRate.slow, ageInDays: 0, now: NOW });
|
|
228
|
-
const ctx = {
|
|
229
|
-
highConfidence: [{ fact, score: 0.9, ageInDays: 0 }],
|
|
230
|
-
mediumConfidence: [],
|
|
231
|
-
lowConfidence: [],
|
|
232
|
-
relatedConversations: [],
|
|
233
|
-
};
|
|
234
|
-
const output = formatContextBlock(ctx);
|
|
235
|
-
assert.ok(output.startsWith('[MEMORY CONTEXT]'), `expected block header, got: ${output.slice(0, 50)}`);
|
|
236
|
-
});
|
|
237
|
-
test('fact line includes description, score (2dp), session label, age', () => {
|
|
238
|
-
const fact = makeFact({
|
|
239
|
-
subject: 'user',
|
|
240
|
-
predicate: 'is building',
|
|
241
|
-
object: 'Plumb',
|
|
242
|
-
confidence: 0.98,
|
|
243
|
-
decayRate: DecayRate.slow,
|
|
244
|
-
ageInDays: 0,
|
|
245
|
-
sessionId: 'session-X',
|
|
246
|
-
sessionLabel: 'tech-planning',
|
|
247
|
-
now: NOW,
|
|
248
|
-
});
|
|
249
|
-
const ctx = {
|
|
250
|
-
highConfidence: [{ fact, score: 0.98, ageInDays: 0 }],
|
|
251
|
-
mediumConfidence: [],
|
|
252
|
-
lowConfidence: [],
|
|
253
|
-
relatedConversations: [],
|
|
254
|
-
};
|
|
255
|
-
const output = formatContextBlock(ctx);
|
|
256
|
-
assert.ok(output.includes('user is building Plumb'), 'should include fact description');
|
|
257
|
-
assert.ok(output.includes('0.98'), 'should include score (2dp)');
|
|
258
|
-
assert.ok(output.includes('tech-planning'), 'should include session label');
|
|
259
|
-
assert.ok(output.includes('today'), 'should include age');
|
|
260
|
-
});
|
|
261
|
-
test('fact line falls back to sourceSessionId when label absent', () => {
|
|
262
|
-
const fact = makeFact({
|
|
263
|
-
confidence: 0.9,
|
|
264
|
-
decayRate: DecayRate.slow,
|
|
265
|
-
ageInDays: 0,
|
|
266
|
-
sessionId: 'session-fallback',
|
|
267
|
-
now: NOW,
|
|
268
|
-
// no sessionLabel
|
|
269
|
-
});
|
|
270
|
-
const ctx = {
|
|
271
|
-
highConfidence: [{ fact, score: 0.9, ageInDays: 0 }],
|
|
272
|
-
mediumConfidence: [],
|
|
273
|
-
lowConfidence: [],
|
|
274
|
-
relatedConversations: [],
|
|
275
|
-
};
|
|
276
|
-
const output = formatContextBlock(ctx);
|
|
277
|
-
assert.ok(output.includes('session-fallback'), 'should fall back to session ID');
|
|
278
|
-
});
|
|
279
|
-
test('raw chunk line includes session label, age, excerpt (max 200 chars)', () => {
|
|
280
|
-
const longText = 'A'.repeat(300);
|
|
281
|
-
const chunk = {
|
|
282
|
-
chunkText: longText,
|
|
283
|
-
sessionId: 'sess-raw',
|
|
284
|
-
sessionLabel: 'architecture-review',
|
|
285
|
-
timestamp: new Date(NOW.getTime() - 2 * 24 * 60 * 60 * 1_000), // 2 days ago
|
|
286
|
-
score: 0.75,
|
|
287
|
-
};
|
|
288
|
-
const ctx = {
|
|
289
|
-
highConfidence: [],
|
|
290
|
-
mediumConfidence: [],
|
|
291
|
-
lowConfidence: [],
|
|
292
|
-
relatedConversations: [chunk],
|
|
293
|
-
};
|
|
294
|
-
const output = formatContextBlock(ctx);
|
|
295
|
-
assert.ok(output.includes('architecture-review'), 'should include session label');
|
|
296
|
-
// Excerpt should be truncated to 200 chars.
|
|
297
|
-
const excerptMatch = output.match(/"([^"]+)"/);
|
|
298
|
-
assert.ok(excerptMatch !== null, 'should contain quoted excerpt');
|
|
299
|
-
assert.ok(excerptMatch[1].length <= 200, 'excerpt should be ≤ 200 chars');
|
|
300
|
-
});
|
|
301
|
-
test('omits tier section when that tier is empty', () => {
|
|
302
|
-
const fact = makeFact({ confidence: 0.5, decayRate: DecayRate.slow, ageInDays: 0, now: NOW });
|
|
303
|
-
const ctx = {
|
|
304
|
-
highConfidence: [],
|
|
305
|
-
mediumConfidence: [{ fact, score: 0.5, ageInDays: 0 }],
|
|
306
|
-
lowConfidence: [],
|
|
307
|
-
relatedConversations: [],
|
|
308
|
-
};
|
|
309
|
-
const output = formatContextBlock(ctx);
|
|
310
|
-
assert.ok(!output.includes('## High confidence'), 'no high section when empty');
|
|
311
|
-
assert.ok(output.includes('## Medium confidence'), 'medium section present');
|
|
312
|
-
assert.ok(!output.includes('## Low confidence'), 'no low section when empty');
|
|
313
|
-
assert.ok(!output.includes('## Related conversations'), 'no raw section when empty');
|
|
314
|
-
});
|
|
315
|
-
});
|
|
316
|
-
// ─── Cross-session integration test ─────────────────────────────────────────
|
|
317
|
-
// Uses a real LocalStore with store.store() (no embedder needed).
|
|
318
|
-
// Verifies that facts from session A appear when querying in session B context.
|
|
319
|
-
describe('Cross-session integration', () => {
|
|
320
|
-
const dbPath = join(tmpdir(), `plumb-readpath-integration-${Date.now()}.db`);
|
|
321
|
-
const store = new LocalStore({ dbPath, userId: 'readpath-test-user' });
|
|
322
|
-
after(() => {
|
|
323
|
-
store.close();
|
|
324
|
-
rmSync(dbPath, { force: true });
|
|
325
|
-
});
|
|
326
|
-
test('facts from session A returned in session B context', async () => {
|
|
327
|
-
const now = new Date();
|
|
328
|
-
// Ingest facts from session A.
|
|
329
|
-
await store.store({
|
|
330
|
-
subject: 'user',
|
|
331
|
-
predicate: 'prefers',
|
|
332
|
-
object: 'TypeScript',
|
|
333
|
-
confidence: 0.95,
|
|
334
|
-
decayRate: DecayRate.slow,
|
|
335
|
-
timestamp: now,
|
|
336
|
-
sourceSessionId: 'session-A',
|
|
337
|
-
sourceSessionLabel: 'tech-session',
|
|
338
|
-
});
|
|
339
|
-
await store.store({
|
|
340
|
-
subject: 'user',
|
|
341
|
-
predicate: 'is building',
|
|
342
|
-
object: 'Plumb memory system',
|
|
343
|
-
confidence: 0.9,
|
|
344
|
-
decayRate: DecayRate.slow,
|
|
345
|
-
timestamp: now,
|
|
346
|
-
sourceSessionId: 'session-A',
|
|
347
|
-
sourceSessionLabel: 'tech-session',
|
|
348
|
-
});
|
|
349
|
-
// Query from session B context — no session filter, so session A facts must appear.
|
|
350
|
-
// Use 'TypeScript' as query keyword (LIKE search in current store.search impl).
|
|
351
|
-
const ctx = await buildMemoryContext('TypeScript', store, { now });
|
|
352
|
-
const allFacts = [
|
|
353
|
-
...ctx.highConfidence,
|
|
354
|
-
...ctx.mediumConfidence,
|
|
355
|
-
...ctx.lowConfidence,
|
|
356
|
-
];
|
|
357
|
-
// At least one fact from session A must be in the results.
|
|
358
|
-
const sessionAFact = allFacts.find((sf) => sf.fact.sourceSessionId === 'session-A');
|
|
359
|
-
assert.ok(sessionAFact !== undefined, 'session A fact must appear in cross-session query');
|
|
360
|
-
// Verify provenance fields are populated.
|
|
361
|
-
assert.equal(sessionAFact.fact.sourceSessionLabel, 'tech-session', 'session label must be preserved in provenance');
|
|
362
|
-
assert.ok(sessionAFact.score > 0, 'score must be positive');
|
|
363
|
-
assert.ok(sessionAFact.ageInDays >= 0, 'ageInDays must be non-negative');
|
|
364
|
-
// Verify the formatted output includes provenance.
|
|
365
|
-
const formatted = formatContextBlock(ctx);
|
|
366
|
-
if (formatted !== '') {
|
|
367
|
-
assert.ok(formatted.startsWith('[MEMORY CONTEXT]'), 'output must start with block header');
|
|
368
|
-
assert.ok(formatted.includes('tech-session'), 'session label must appear in formatted output');
|
|
369
|
-
}
|
|
370
|
-
});
|
|
371
|
-
test('buildMemoryContext + formatContextBlock: full pipeline smoke test', async () => {
|
|
372
|
-
const now = new Date();
|
|
373
|
-
await store.store({
|
|
374
|
-
subject: 'user',
|
|
375
|
-
predicate: 'uses',
|
|
376
|
-
object: 'dark mode',
|
|
377
|
-
confidence: 0.85,
|
|
378
|
-
decayRate: DecayRate.slow,
|
|
379
|
-
timestamp: now,
|
|
380
|
-
sourceSessionId: 'session-B',
|
|
381
|
-
sessionLabel: 'settings-session',
|
|
382
|
-
});
|
|
383
|
-
const ctx = await buildMemoryContext('dark mode', store, { now });
|
|
384
|
-
const output = formatContextBlock(ctx);
|
|
385
|
-
// Either we got results (block present) or the keyword didn't match (empty) —
|
|
386
|
-
// both are valid since store.search() uses LIKE and 'dark mode' should match.
|
|
387
|
-
if (output !== '') {
|
|
388
|
-
assert.ok(output.includes('[MEMORY CONTEXT]'), 'block header present');
|
|
389
|
-
}
|
|
390
|
-
// No throw means pipeline ran end-to-end without error.
|
|
391
|
-
});
|
|
392
|
-
});
|
|
393
|
-
//# sourceMappingURL=read-path.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read-path.test.js","sourceRoot":"","sources":["../src/read-path.test.ts"],"names":[],"mappings":"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"}
|
package/dist/scorer.test.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* scorer.test.ts — decay curve verification for scoreFact() and scoreRawLog().
|
|
3
|
-
*
|
|
4
|
-
* Note on the "~0.31 at 49 days medium" reference in the architecture doc:
|
|
5
|
-
* With lambda=0.012 the correct value at 49 days is ~0.528 (confidence=0.95).
|
|
6
|
-
* The ~0.31 figure likely derives from an earlier lambda value (~0.023).
|
|
7
|
-
* These tests assert against the actual computed values for the specified lambdas.
|
|
8
|
-
*/
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=scorer.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scorer.test.d.ts","sourceRoot":"","sources":["../src/scorer.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
package/dist/scorer.test.js
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* scorer.test.ts — decay curve verification for scoreFact() and scoreRawLog().
|
|
3
|
-
*
|
|
4
|
-
* Note on the "~0.31 at 49 days medium" reference in the architecture doc:
|
|
5
|
-
* With lambda=0.012 the correct value at 49 days is ~0.528 (confidence=0.95).
|
|
6
|
-
* The ~0.31 figure likely derives from an earlier lambda value (~0.023).
|
|
7
|
-
* These tests assert against the actual computed values for the specified lambdas.
|
|
8
|
-
*/
|
|
9
|
-
import { strict as assert } from 'node:assert';
|
|
10
|
-
import { describe, it } from 'node:test';
|
|
11
|
-
import { DecayRate } from './types.js';
|
|
12
|
-
import { computeDecay, scoreFact, scoreRawLog } from './scorer.js';
|
|
13
|
-
/** Build a minimal Fact for testing. */
|
|
14
|
-
function makeFact(opts) {
|
|
15
|
-
const now = opts.now ?? new Date('2026-01-01T00:00:00.000Z');
|
|
16
|
-
const timestamp = new Date(now.getTime() - opts.ageInDays * 24 * 60 * 60 * 1_000);
|
|
17
|
-
return {
|
|
18
|
-
fact: {
|
|
19
|
-
id: 'test-id',
|
|
20
|
-
subject: 'test subject',
|
|
21
|
-
predicate: 'test predicate',
|
|
22
|
-
object: 'test object',
|
|
23
|
-
confidence: opts.confidence,
|
|
24
|
-
decayRate: opts.decayRate,
|
|
25
|
-
timestamp,
|
|
26
|
-
sourceSessionId: 'session-1',
|
|
27
|
-
},
|
|
28
|
-
now,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
describe('computeDecay', () => {
|
|
32
|
-
it('returns 1.0 at age 0 regardless of lambda', () => {
|
|
33
|
-
assert.equal(computeDecay(0.003, 0), 1.0);
|
|
34
|
-
assert.equal(computeDecay(0.012, 0), 1.0);
|
|
35
|
-
assert.equal(computeDecay(0.05, 0), 1.0);
|
|
36
|
-
});
|
|
37
|
-
it('medium lambda at 49 days matches expected decay', () => {
|
|
38
|
-
const decay = computeDecay(0.012, 49);
|
|
39
|
-
// e^(-0.012 * 49) = e^(-0.588) ≈ 0.5557
|
|
40
|
-
assert.ok(decay > 0.55 && decay < 0.57, `expected ~0.5557, got ${decay}`);
|
|
41
|
-
});
|
|
42
|
-
it('fast lambda decays faster than slow at same age', () => {
|
|
43
|
-
assert.ok(computeDecay(0.05, 30) < computeDecay(0.003, 30));
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
describe('scoreFact — decay curves', () => {
|
|
47
|
-
it('age=0, slow decay, confidence=0.95 → ~0.95', () => {
|
|
48
|
-
const { fact, now } = makeFact({
|
|
49
|
-
confidence: 0.95,
|
|
50
|
-
decayRate: DecayRate.slow,
|
|
51
|
-
ageInDays: 0,
|
|
52
|
-
});
|
|
53
|
-
const result = scoreFact(fact, now);
|
|
54
|
-
assert.ok(result.score > 0.949 && result.score <= 0.95, `expected ~0.95, got ${result.score}`);
|
|
55
|
-
assert.equal(result.isCold, false);
|
|
56
|
-
});
|
|
57
|
-
it('age=49 days, medium decay, confidence=0.95 → ~0.528', () => {
|
|
58
|
-
const { fact, now } = makeFact({
|
|
59
|
-
confidence: 0.95,
|
|
60
|
-
decayRate: DecayRate.medium,
|
|
61
|
-
ageInDays: 49,
|
|
62
|
-
});
|
|
63
|
-
const result = scoreFact(fact, now);
|
|
64
|
-
// 0.95 × e^(-0.012 × 49) ≈ 0.5277
|
|
65
|
-
assert.ok(result.score > 0.52 && result.score < 0.54, `expected ~0.528, got ${result.score}`);
|
|
66
|
-
assert.equal(result.isCold, false);
|
|
67
|
-
});
|
|
68
|
-
it('age=365 days, medium decay, confidence=0.95 → ~0.012 (near cold)', () => {
|
|
69
|
-
const { fact, now } = makeFact({
|
|
70
|
-
confidence: 0.95,
|
|
71
|
-
decayRate: DecayRate.medium,
|
|
72
|
-
ageInDays: 365,
|
|
73
|
-
});
|
|
74
|
-
const result = scoreFact(fact, now);
|
|
75
|
-
// 0.95 × e^(-0.012 × 365) ≈ 0.01190
|
|
76
|
-
assert.ok(result.score > 0.01 && result.score < 0.02, `expected ~0.012, got ${result.score}`);
|
|
77
|
-
assert.equal(result.isCold, false);
|
|
78
|
-
});
|
|
79
|
-
it('age=400 days, medium decay, confidence=0.95 → isCold (score < 0.01)', () => {
|
|
80
|
-
const { fact, now } = makeFact({
|
|
81
|
-
confidence: 0.95,
|
|
82
|
-
decayRate: DecayRate.medium,
|
|
83
|
-
ageInDays: 400,
|
|
84
|
-
});
|
|
85
|
-
const result = scoreFact(fact, now);
|
|
86
|
-
// 0.95 × e^(-0.012 × 400) ≈ 0.00782
|
|
87
|
-
assert.ok(result.score < 0.01, `expected score < 0.01, got ${result.score}`);
|
|
88
|
-
assert.equal(result.isCold, true);
|
|
89
|
-
});
|
|
90
|
-
it('age=30 days, fast decay, confidence=0.95 → < 0.25', () => {
|
|
91
|
-
const { fact, now } = makeFact({
|
|
92
|
-
confidence: 0.95,
|
|
93
|
-
decayRate: DecayRate.fast,
|
|
94
|
-
ageInDays: 30,
|
|
95
|
-
});
|
|
96
|
-
const result = scoreFact(fact, now);
|
|
97
|
-
// 0.95 × e^(-0.05 × 30) ≈ 0.2120
|
|
98
|
-
assert.ok(result.score < 0.25, `expected < 0.25, got ${result.score}`);
|
|
99
|
-
assert.equal(result.isCold, false);
|
|
100
|
-
});
|
|
101
|
-
it('confidence=0 → score=0, isCold=true', () => {
|
|
102
|
-
const { fact, now } = makeFact({
|
|
103
|
-
confidence: 0,
|
|
104
|
-
decayRate: DecayRate.medium,
|
|
105
|
-
ageInDays: 49,
|
|
106
|
-
});
|
|
107
|
-
const result = scoreFact(fact, now);
|
|
108
|
-
assert.equal(result.score, 0);
|
|
109
|
-
assert.equal(result.isCold, true);
|
|
110
|
-
});
|
|
111
|
-
it('score is bounded between 0 and 1', () => {
|
|
112
|
-
const ages = [0, 1, 30, 100, 365, 730];
|
|
113
|
-
const rates = [DecayRate.slow, DecayRate.medium, DecayRate.fast];
|
|
114
|
-
for (const ageInDays of ages) {
|
|
115
|
-
for (const decayRate of rates) {
|
|
116
|
-
const { fact, now } = makeFact({ confidence: 0.95, decayRate, ageInDays });
|
|
117
|
-
const { score } = scoreFact(fact, now);
|
|
118
|
-
assert.ok(score >= 0 && score <= 1, `score out of range: ${score}`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
it('uses current time when now is omitted (smoke test)', () => {
|
|
123
|
-
const fact = {
|
|
124
|
-
id: 'x',
|
|
125
|
-
subject: 's',
|
|
126
|
-
predicate: 'p',
|
|
127
|
-
object: 'o',
|
|
128
|
-
confidence: 0.8,
|
|
129
|
-
decayRate: DecayRate.slow,
|
|
130
|
-
timestamp: new Date(),
|
|
131
|
-
sourceSessionId: 'sess',
|
|
132
|
-
};
|
|
133
|
-
// Should not throw; score should be close to 0.8 for age≈0
|
|
134
|
-
const { score } = scoreFact(fact);
|
|
135
|
-
assert.ok(score > 0.79 && score <= 0.8, `expected ~0.8, got ${score}`);
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
describe('scoreRawLog — medium decay', () => {
|
|
139
|
-
it('age=0 → score ≈ 1.0, not cold', () => {
|
|
140
|
-
const now = new Date('2026-01-01T00:00:00.000Z');
|
|
141
|
-
const chunk = { timestamp: now };
|
|
142
|
-
const result = scoreRawLog(chunk, now);
|
|
143
|
-
assert.equal(result.score, 1.0);
|
|
144
|
-
assert.equal(result.isCold, false);
|
|
145
|
-
});
|
|
146
|
-
it('age=49 days → score ~0.557 (medium decay on base 1.0)', () => {
|
|
147
|
-
const now = new Date('2026-01-01T00:00:00.000Z');
|
|
148
|
-
const timestamp = new Date(now.getTime() - 49 * 24 * 60 * 60 * 1_000);
|
|
149
|
-
const result = scoreRawLog({ timestamp }, now);
|
|
150
|
-
// e^(-0.012 × 49) ≈ 0.5557
|
|
151
|
-
assert.ok(result.score > 0.54 && result.score < 0.57, `expected ~0.556, got ${result.score}`);
|
|
152
|
-
assert.equal(result.isCold, false);
|
|
153
|
-
});
|
|
154
|
-
it('age=365 days → score ~0.0125, not yet cold', () => {
|
|
155
|
-
const now = new Date('2026-01-01T00:00:00.000Z');
|
|
156
|
-
const timestamp = new Date(now.getTime() - 365 * 24 * 60 * 60 * 1_000);
|
|
157
|
-
const result = scoreRawLog({ timestamp }, now);
|
|
158
|
-
assert.ok(result.score > 0.01 && result.score < 0.02, `expected ~0.0125, got ${result.score}`);
|
|
159
|
-
assert.equal(result.isCold, false);
|
|
160
|
-
});
|
|
161
|
-
it('age=400 days → isCold', () => {
|
|
162
|
-
const now = new Date('2026-01-01T00:00:00.000Z');
|
|
163
|
-
const timestamp = new Date(now.getTime() - 400 * 24 * 60 * 60 * 1_000);
|
|
164
|
-
const result = scoreRawLog({ timestamp }, now);
|
|
165
|
-
assert.ok(result.score < 0.01, `expected < 0.01, got ${result.score}`);
|
|
166
|
-
assert.equal(result.isCold, true);
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
//# sourceMappingURL=scorer.test.js.map
|
package/dist/scorer.test.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scorer.test.js","sourceRoot":"","sources":["../src/scorer.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEnE,wCAAwC;AACxC,SAAS,QAAQ,CAAC,IAKjB;IACC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,IAAI,IAAI,CACxB,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,CACtD,CAAC;IACF,OAAO;QACL,IAAI,EAAE;YACJ,EAAE,EAAE,SAAS;YACb,OAAO,EAAE,cAAc;YACvB,SAAS,EAAE,gBAAgB;YAC3B,MAAM,EAAE,aAAa;YACrB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS;YACT,eAAe,EAAE,WAAW;SAC7B;QACD,GAAG;KACJ,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACtC,wCAAwC;QACxC,MAAM,CAAC,EAAE,CAAC,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,EAAE,yBAAyB,KAAK,EAAE,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,YAAY,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC;YAC7B,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,SAAS,CAAC,IAAI;YACzB,SAAS,EAAE,CAAC;SACb,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,KAAK,GAAG,KAAK,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,EAC5C,uBAAuB,MAAM,CAAC,KAAK,EAAE,CACtC,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC;YAC7B,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,SAAS,CAAC,MAAM;YAC3B,SAAS,EAAE,EAAE;SACd,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,kCAAkC;QAClC,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,KAAK,GAAG,IAAI,IAAI,MAAM,CAAC,KAAK,GAAG,IAAI,EAC1C,wBAAwB,MAAM,CAAC,KAAK,EAAE,CACvC,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC;YAC7B,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,SAAS,CAAC,MAAM;YAC3B,SAAS,EAAE,GAAG;SACf,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,oCAAoC;QACpC,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,KAAK,GAAG,IAAI,IAAI,MAAM,CAAC,KAAK,GAAG,IAAI,EAC1C,wBAAwB,MAAM,CAAC,KAAK,EAAE,CACvC,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC7E,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC;YAC7B,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,SAAS,CAAC,MAAM;YAC3B,SAAS,EAAE,GAAG;SACf,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,oCAAoC;QACpC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,EAAE,8BAA8B,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC;YAC7B,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,SAAS,CAAC,IAAI;YACzB,SAAS,EAAE,EAAE;SACd,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,iCAAiC;QACjC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,EAAE,wBAAwB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC;YAC7B,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,SAAS,CAAC,MAAM;YAC3B,SAAS,EAAE,EAAE;SACd,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACjE,KAAK,MAAM,SAAS,IAAI,IAAI,EAAE,CAAC;YAC7B,KAAK,MAAM,SAAS,IAAI,KAAK,EAAE,CAAC;gBAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;gBAC3E,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBACvC,MAAM,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,uBAAuB,KAAK,EAAE,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,IAAI,GAAG;YACX,EAAE,EAAE,GAAG;YACP,OAAO,EAAE,GAAG;YACZ,SAAS,EAAE,GAAG;YACd,MAAM,EAAE,GAAG;YACX,UAAU,EAAE,GAAG;YACf,SAAS,EAAE,SAAS,CAAC,IAAI;YACzB,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,eAAe,EAAE,MAAM;SACxB,CAAC;QACF,2DAA2D;QAC3D,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAC,EAAE,CAAC,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,EAAE,sBAAsB,KAAK,EAAE,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,WAAW,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/C,2BAA2B;QAC3B,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,KAAK,GAAG,IAAI,IAAI,MAAM,CAAC,KAAK,GAAG,IAAI,EAC1C,wBAAwB,MAAM,CAAC,KAAK,EAAE,CACvC,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,WAAW,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/C,MAAM,CAAC,EAAE,CACP,MAAM,CAAC,KAAK,GAAG,IAAI,IAAI,MAAM,CAAC,KAAK,GAAG,IAAI,EAC1C,yBAAyB,MAAM,CAAC,KAAK,EAAE,CACxC,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,WAAW,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/C,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,EAAE,wBAAwB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|