@getplumb/core 0.1.6 → 0.3.0

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 (68) hide show
  1. package/README.md +2 -2
  2. package/dist/embedder.d.ts +16 -2
  3. package/dist/embedder.d.ts.map +1 -1
  4. package/dist/embedder.js +23 -4
  5. package/dist/embedder.js.map +1 -1
  6. package/dist/extraction-queue.d.ts +13 -3
  7. package/dist/extraction-queue.d.ts.map +1 -1
  8. package/dist/extraction-queue.js +21 -4
  9. package/dist/extraction-queue.js.map +1 -1
  10. package/dist/extractor.d.ts +2 -1
  11. package/dist/extractor.d.ts.map +1 -1
  12. package/dist/extractor.js +106 -7
  13. package/dist/extractor.js.map +1 -1
  14. package/dist/extractor.test.d.ts +2 -0
  15. package/dist/extractor.test.d.ts.map +1 -0
  16. package/dist/extractor.test.js +158 -0
  17. package/dist/extractor.test.js.map +1 -0
  18. package/dist/fact-search.d.ts +9 -5
  19. package/dist/fact-search.d.ts.map +1 -1
  20. package/dist/fact-search.js +25 -16
  21. package/dist/fact-search.js.map +1 -1
  22. package/dist/fact-search.test.d.ts +12 -0
  23. package/dist/fact-search.test.d.ts.map +1 -0
  24. package/dist/fact-search.test.js +117 -0
  25. package/dist/fact-search.test.js.map +1 -0
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +1 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/llm-client.d.ts +11 -2
  31. package/dist/llm-client.d.ts.map +1 -1
  32. package/dist/llm-client.js +47 -3
  33. package/dist/llm-client.js.map +1 -1
  34. package/dist/local-store.d.ts +32 -1
  35. package/dist/local-store.d.ts.map +1 -1
  36. package/dist/local-store.js +510 -35
  37. package/dist/local-store.js.map +1 -1
  38. package/dist/local-store.test.d.ts +2 -0
  39. package/dist/local-store.test.d.ts.map +1 -0
  40. package/dist/local-store.test.js +146 -0
  41. package/dist/local-store.test.js.map +1 -0
  42. package/dist/raw-log-search.d.ts +9 -5
  43. package/dist/raw-log-search.d.ts.map +1 -1
  44. package/dist/raw-log-search.js +107 -29
  45. package/dist/raw-log-search.js.map +1 -1
  46. package/dist/raw-log-search.test.d.ts +12 -0
  47. package/dist/raw-log-search.test.d.ts.map +1 -0
  48. package/dist/raw-log-search.test.js +124 -0
  49. package/dist/raw-log-search.test.js.map +1 -0
  50. package/dist/read-path.test.d.ts +15 -0
  51. package/dist/read-path.test.d.ts.map +1 -0
  52. package/dist/read-path.test.js +393 -0
  53. package/dist/read-path.test.js.map +1 -0
  54. package/dist/schema.d.ts +2 -2
  55. package/dist/schema.d.ts.map +1 -1
  56. package/dist/schema.js +58 -1
  57. package/dist/schema.js.map +1 -1
  58. package/dist/scorer.test.d.ts +10 -0
  59. package/dist/scorer.test.d.ts.map +1 -0
  60. package/dist/scorer.test.js +169 -0
  61. package/dist/scorer.test.js.map +1 -0
  62. package/dist/store.d.ts +3 -1
  63. package/dist/store.d.ts.map +1 -1
  64. package/dist/wasm-db.d.ts +63 -8
  65. package/dist/wasm-db.d.ts.map +1 -1
  66. package/dist/wasm-db.js +124 -31
  67. package/dist/wasm-db.js.map +1 -1
  68. package/package.json +14 -2
@@ -0,0 +1,15 @@
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
+ export {};
15
+ //# sourceMappingURL=read-path.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-path.test.d.ts","sourceRoot":"","sources":["../src/read-path.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -0,0 +1,393 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-path.test.js","sourceRoot":"","sources":["../src/read-path.test.ts"],"names":[],"mappings":"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"}
package/dist/schema.d.ts CHANGED
@@ -10,9 +10,9 @@
10
10
  * - Cross-session by design: session info stored as metadata, not as a boundary
11
11
  * - Indexes on high-cardinality query axes: user_id, session_id, timestamp, deleted_at
12
12
  */
13
- export declare const CREATE_FACTS_TABLE = "\n CREATE TABLE IF NOT EXISTS facts (\n id TEXT PRIMARY KEY,\n user_id TEXT NOT NULL,\n subject TEXT NOT NULL,\n predicate TEXT NOT NULL,\n object TEXT NOT NULL,\n confidence REAL NOT NULL,\n decay_rate TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n source_session_id TEXT NOT NULL,\n source_session_label TEXT,\n context TEXT,\n deleted_at TEXT\n )\n";
13
+ export declare const CREATE_FACTS_TABLE = "\n CREATE TABLE IF NOT EXISTS facts (\n id TEXT PRIMARY KEY,\n user_id TEXT NOT NULL,\n subject TEXT NOT NULL,\n predicate TEXT NOT NULL,\n object TEXT NOT NULL,\n confidence REAL NOT NULL,\n decay_rate TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n source_session_id TEXT NOT NULL,\n source_session_label TEXT,\n context TEXT,\n deleted_at TEXT,\n source_chunk_id TEXT\n )\n";
14
14
  export declare const CREATE_FACTS_INDEXES: string[];
15
- export declare const CREATE_RAW_LOG_TABLE = "\n CREATE TABLE IF NOT EXISTS raw_log (\n id TEXT PRIMARY KEY,\n user_id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n session_label TEXT,\n user_message TEXT NOT NULL,\n agent_response TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n source TEXT NOT NULL,\n chunk_text TEXT NOT NULL,\n chunk_index INTEGER NOT NULL,\n vec_rowid INTEGER,\n content_hash TEXT,\n UNIQUE(user_id, content_hash)\n )\n";
15
+ export declare const CREATE_RAW_LOG_TABLE = "\n CREATE TABLE IF NOT EXISTS raw_log (\n id TEXT PRIMARY KEY,\n user_id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n session_label TEXT,\n user_message TEXT NOT NULL,\n agent_response TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n source TEXT NOT NULL,\n chunk_text TEXT NOT NULL,\n chunk_index INTEGER NOT NULL,\n vec_rowid INTEGER,\n content_hash TEXT,\n embed_status TEXT NOT NULL DEFAULT 'pending',\n embed_error TEXT,\n embed_model TEXT,\n extract_status TEXT NOT NULL DEFAULT 'pending',\n extract_error TEXT,\n parent_id TEXT REFERENCES raw_log(id),\n UNIQUE(user_id, content_hash)\n )\n";
16
16
  export declare const CREATE_RAW_LOG_INDEXES: string[];
17
17
  /**
18
18
  * Embeddings table for vector search over raw_log chunks.
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,kBAAkB,0fAe9B,CAAC;AAEF,eAAO,MAAM,oBAAoB,UAKhC,CAAC;AAEF,eAAO,MAAM,oBAAoB,8dAgBhC,CAAC;AAEF,eAAO,MAAM,sBAAsB,UAIlC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,gIAK9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,8HAK5B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,8JAMlC,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAAE,EAAE,OAAO,cAAc,EAAE,MAAM,GAAG,IAAI,CA8CnE"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,kBAAkB,yhBAgB9B,CAAC;AAEF,eAAO,MAAM,oBAAoB,UAKhC,CAAC;AAEF,eAAO,MAAM,oBAAoB,ksBAsBhC,CAAC;AAEF,eAAO,MAAM,sBAAsB,UAKlC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,gIAK9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,8HAK5B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,8JAMlC,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAAE,EAAE,OAAO,cAAc,EAAE,MAAM,GAAG,IAAI,CAoGnE"}
package/dist/schema.js CHANGED
@@ -23,7 +23,8 @@ export const CREATE_FACTS_TABLE = `
23
23
  source_session_id TEXT NOT NULL,
24
24
  source_session_label TEXT,
25
25
  context TEXT,
26
- deleted_at TEXT
26
+ deleted_at TEXT,
27
+ source_chunk_id TEXT
27
28
  )
28
29
  `;
29
30
  export const CREATE_FACTS_INDEXES = [
@@ -46,6 +47,12 @@ export const CREATE_RAW_LOG_TABLE = `
46
47
  chunk_index INTEGER NOT NULL,
47
48
  vec_rowid INTEGER,
48
49
  content_hash TEXT,
50
+ embed_status TEXT NOT NULL DEFAULT 'pending',
51
+ embed_error TEXT,
52
+ embed_model TEXT,
53
+ extract_status TEXT NOT NULL DEFAULT 'pending',
54
+ extract_error TEXT,
55
+ parent_id TEXT REFERENCES raw_log(id),
49
56
  UNIQUE(user_id, content_hash)
50
57
  )
51
58
  `;
@@ -53,6 +60,7 @@ export const CREATE_RAW_LOG_INDEXES = [
53
60
  `CREATE INDEX IF NOT EXISTS idx_raw_log_user_id ON raw_log (user_id)`,
54
61
  `CREATE INDEX IF NOT EXISTS idx_raw_log_session_id ON raw_log (session_id)`,
55
62
  `CREATE INDEX IF NOT EXISTS idx_raw_log_timestamp ON raw_log (timestamp)`,
63
+ `CREATE INDEX IF NOT EXISTS idx_raw_log_parent_id ON raw_log (parent_id)`,
56
64
  ];
57
65
  /**
58
66
  * Embeddings table for vector search over raw_log chunks.
@@ -128,5 +136,54 @@ export function applySchema(db) {
128
136
  if (tables.length === 0) {
129
137
  db.exec(CREATE_NUDGE_LOG_TABLE);
130
138
  }
139
+ // T-079: Conditional migration for processing state machine columns.
140
+ // Refetch column info for raw_log and facts after prior migrations.
141
+ const rawLogColumns2 = db.exec({
142
+ sql: 'PRAGMA table_info(raw_log)',
143
+ rowMode: 'object',
144
+ returnValue: 'resultRows',
145
+ });
146
+ const factsColumns2 = db.exec({
147
+ sql: 'PRAGMA table_info(facts)',
148
+ rowMode: 'object',
149
+ returnValue: 'resultRows',
150
+ });
151
+ // Add new columns to raw_log if they don't exist.
152
+ const hasEmbedStatus = rawLogColumns2.some((c) => c.name === 'embed_status');
153
+ if (!hasEmbedStatus) {
154
+ // Add new columns with defaults.
155
+ db.exec('ALTER TABLE raw_log ADD COLUMN embed_status TEXT NOT NULL DEFAULT \'pending\'');
156
+ db.exec('ALTER TABLE raw_log ADD COLUMN embed_error TEXT');
157
+ db.exec('ALTER TABLE raw_log ADD COLUMN embed_model TEXT');
158
+ db.exec('ALTER TABLE raw_log ADD COLUMN extract_status TEXT NOT NULL DEFAULT \'pending\'');
159
+ db.exec('ALTER TABLE raw_log ADD COLUMN extract_error TEXT');
160
+ // Backfill embed_status for existing rows based on vec_rowid.
161
+ // Rows with vec_rowid already set -> embed_status='done', embed_model='Xenova/bge-small-en-v1.5'
162
+ db.exec(`
163
+ UPDATE raw_log
164
+ SET embed_status = 'done', embed_model = 'Xenova/bge-small-en-v1.5'
165
+ WHERE vec_rowid IS NOT NULL
166
+ `);
167
+ // Rows with vec_rowid=NULL remain embed_status='pending' (from DEFAULT).
168
+ // All rows remain extract_status='pending' (from DEFAULT) — cannot infer which were extracted.
169
+ }
170
+ // Add source_chunk_id column to facts if it doesn't exist.
171
+ const hasSourceChunkId = factsColumns2.some((c) => c.name === 'source_chunk_id');
172
+ if (!hasSourceChunkId) {
173
+ db.exec('ALTER TABLE facts ADD COLUMN source_chunk_id TEXT');
174
+ // Existing facts have source_chunk_id=NULL (no retroactive mapping).
175
+ }
176
+ // T-108: Add parent_id column to raw_log if it doesn't exist (for parent-child chunking).
177
+ const rawLogColumns3 = db.exec({
178
+ sql: 'PRAGMA table_info(raw_log)',
179
+ rowMode: 'object',
180
+ returnValue: 'resultRows',
181
+ });
182
+ const hasParentId = rawLogColumns3.some((c) => c.name === 'parent_id');
183
+ if (!hasParentId) {
184
+ db.exec('ALTER TABLE raw_log ADD COLUMN parent_id TEXT REFERENCES raw_log(id)');
185
+ db.exec('CREATE INDEX IF NOT EXISTS idx_raw_log_parent_id ON raw_log (parent_id)');
186
+ // Existing rows have parent_id=NULL (they are parent-only rows, treated as searchable fallback).
187
+ }
131
188
  }
132
189
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;CAejC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,iEAAiE;IACjE,8EAA8E;IAC9E,qEAAqE;IACrE,uEAAuE;CACxE,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;CAgBnC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,qEAAqE;IACrE,2EAA2E;IAC3E,yEAAyE;CAC1E,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;CAKjC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;CAK/B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;;;;;;CAMrC,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,EAAiC;IAC3D,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC5B,KAAK,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACvC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IACD,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,sBAAsB,EAAE,CAAC;QACzC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;IACD,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC5B,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAE1B,gFAAgF;IAChF,MAAM,YAAY,GAAG,EAAE,CAAC,IAAI,CAAC;QAC3B,GAAG,EAAE,0BAA0B;QAC/B,OAAO,EAAE,QAAQ;QACjB,WAAW,EAAE,YAAY;KAC1B,CAA4B,CAAC;IAC9B,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;IACrE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,EAAE,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;IAC5D,CAAC;IAED,qFAAqF;IACrF,MAAM,aAAa,GAAG,EAAE,CAAC,IAAI,CAAC;QAC5B,GAAG,EAAE,4BAA4B;QACjC,OAAO,EAAE,QAAQ;QACjB,WAAW,EAAE,YAAY;KAC1B,CAA4B,CAAC;IAC9B,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;IAC5E,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,EAAE,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;QAC5D,uDAAuD;QACvD,2FAA2F;QAC3F,EAAE,CAAC,IAAI,CAAC,8FAA8F,CAAC,CAAC;IAC1G,CAAC;IAED,yEAAyE;IACzE,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC;QACrB,GAAG,EAAE,wEAAwE;QAC7E,OAAO,EAAE,QAAQ;QACjB,WAAW,EAAE,YAAY;KAC1B,CAA4B,CAAC;IAC9B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAClC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scorer.test.d.ts","sourceRoot":"","sources":["../src/scorer.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}