mindlore 0.6.7 → 0.6.8

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 (169) hide show
  1. package/README.md +259 -259
  2. package/SCHEMA.md +292 -292
  3. package/dist/scripts/cc-memory-bulk-sync.d.ts.map +1 -1
  4. package/dist/scripts/cc-memory-bulk-sync.js +47 -42
  5. package/dist/scripts/cc-memory-bulk-sync.js.map +1 -1
  6. package/dist/scripts/cc-session-sync.d.ts.map +1 -1
  7. package/dist/scripts/cc-session-sync.js +58 -48
  8. package/dist/scripts/cc-session-sync.js.map +1 -1
  9. package/dist/scripts/init.js +8 -8
  10. package/dist/scripts/init.js.map +1 -1
  11. package/dist/scripts/lib/all-migrations.d.ts.map +1 -1
  12. package/dist/scripts/lib/all-migrations.js +4 -1
  13. package/dist/scripts/lib/all-migrations.js.map +1 -1
  14. package/dist/scripts/lib/consolidation.d.ts +4 -3
  15. package/dist/scripts/lib/consolidation.d.ts.map +1 -1
  16. package/dist/scripts/lib/consolidation.js +10 -10
  17. package/dist/scripts/lib/consolidation.js.map +1 -1
  18. package/dist/scripts/lib/constants.d.ts +1 -7
  19. package/dist/scripts/lib/constants.d.ts.map +1 -1
  20. package/dist/scripts/lib/constants.js +2 -9
  21. package/dist/scripts/lib/constants.js.map +1 -1
  22. package/dist/scripts/lib/db-helpers.d.ts +0 -15
  23. package/dist/scripts/lib/db-helpers.d.ts.map +1 -1
  24. package/dist/scripts/lib/db-helpers.js +1 -51
  25. package/dist/scripts/lib/db-helpers.js.map +1 -1
  26. package/dist/scripts/lib/decay.d.ts.map +1 -1
  27. package/dist/scripts/lib/decay.js +9 -9
  28. package/dist/scripts/lib/decay.js.map +1 -1
  29. package/dist/scripts/lib/episodes.js +23 -23
  30. package/dist/scripts/lib/migrations-v061.js +21 -21
  31. package/dist/scripts/lib/migrations-v062.js +11 -11
  32. package/dist/scripts/lib/migrations-v063.js +14 -14
  33. package/dist/scripts/lib/migrations-v067.js +11 -11
  34. package/dist/scripts/lib/migrations-v068.d.ts +3 -0
  35. package/dist/scripts/lib/migrations-v068.d.ts.map +1 -0
  36. package/dist/scripts/lib/migrations-v068.js +37 -0
  37. package/dist/scripts/lib/migrations-v068.js.map +1 -0
  38. package/dist/scripts/lib/migrations.d.ts.map +1 -1
  39. package/dist/scripts/lib/migrations.js +0 -15
  40. package/dist/scripts/lib/migrations.js.map +1 -1
  41. package/dist/scripts/lib/schema-version.js +6 -6
  42. package/dist/scripts/lib/search-cache.js +11 -11
  43. package/dist/scripts/lib/session-payload.d.ts.map +1 -1
  44. package/dist/scripts/lib/session-payload.js +7 -7
  45. package/dist/scripts/lib/session-payload.js.map +1 -1
  46. package/dist/scripts/lib/triage.js +3 -3
  47. package/dist/scripts/mindlore-backup.js +9 -9
  48. package/dist/scripts/mindlore-fts5-index.d.ts +1 -2
  49. package/dist/scripts/mindlore-fts5-index.d.ts.map +1 -1
  50. package/dist/scripts/mindlore-fts5-index.js +12 -64
  51. package/dist/scripts/mindlore-fts5-index.js.map +1 -1
  52. package/dist/scripts/mindlore-health-check.d.ts.map +1 -1
  53. package/dist/scripts/mindlore-health-check.js +0 -11
  54. package/dist/scripts/mindlore-health-check.js.map +1 -1
  55. package/dist/tests/cc-memory-bulk-sync.test.js +23 -0
  56. package/dist/tests/cc-memory-bulk-sync.test.js.map +1 -1
  57. package/dist/tests/cc-session-sync.test.js +25 -0
  58. package/dist/tests/cc-session-sync.test.js.map +1 -1
  59. package/dist/tests/compaction-snapshot.test.js +2 -2
  60. package/dist/tests/consolidation.test.js +5 -5
  61. package/dist/tests/consolidation.test.js.map +1 -1
  62. package/dist/tests/decay.test.js +9 -9
  63. package/dist/tests/diary.test.js +4 -4
  64. package/dist/tests/episode-kind-constant.test.d.ts +2 -0
  65. package/dist/tests/episode-kind-constant.test.d.ts.map +1 -0
  66. package/dist/tests/episode-kind-constant.test.js +28 -0
  67. package/dist/tests/episode-kind-constant.test.js.map +1 -0
  68. package/dist/tests/episodes-inject.test.js +9 -9
  69. package/dist/tests/fts5.test.js +66 -125
  70. package/dist/tests/fts5.test.js.map +1 -1
  71. package/dist/tests/globalSetup.d.ts +2 -0
  72. package/dist/tests/globalSetup.d.ts.map +1 -0
  73. package/dist/tests/globalSetup.js +36 -0
  74. package/dist/tests/globalSetup.js.map +1 -0
  75. package/dist/tests/helpers/db.d.ts +13 -5
  76. package/dist/tests/helpers/db.d.ts.map +1 -1
  77. package/dist/tests/helpers/db.js +60 -33
  78. package/dist/tests/helpers/db.js.map +1 -1
  79. package/dist/tests/lesson-graduation.test.js +11 -11
  80. package/dist/tests/lesson-graduation.test.js.map +1 -1
  81. package/dist/tests/migrations-v053.test.js +16 -16
  82. package/dist/tests/migrations-v061.test.js +10 -10
  83. package/dist/tests/migrations-v063.test.js +2 -2
  84. package/dist/tests/migrations-v068.test.d.ts +2 -0
  85. package/dist/tests/migrations-v068.test.d.ts.map +1 -0
  86. package/dist/tests/migrations-v068.test.js +53 -0
  87. package/dist/tests/migrations-v068.test.js.map +1 -0
  88. package/dist/tests/nomination-counts.test.d.ts +2 -0
  89. package/dist/tests/nomination-counts.test.d.ts.map +1 -0
  90. package/dist/tests/nomination-counts.test.js +51 -0
  91. package/dist/tests/nomination-counts.test.js.map +1 -0
  92. package/dist/tests/recall-telemetry.test.js +8 -8
  93. package/dist/tests/schema-version.test.js +3 -7
  94. package/dist/tests/schema-version.test.js.map +1 -1
  95. package/dist/tests/search-hook.test.js +2 -2
  96. package/dist/tests/sec-regression.test.js +0 -50
  97. package/dist/tests/sec-regression.test.js.map +1 -1
  98. package/dist/tests/session-end-cleanup.test.js +3 -20
  99. package/dist/tests/session-end-cleanup.test.js.map +1 -1
  100. package/dist/tests/session-focus.test.js +7 -30
  101. package/dist/tests/session-focus.test.js.map +1 -1
  102. package/dist/tests/session-payload.test.js +1 -1
  103. package/dist/tests/session-summary.test.js +1 -1
  104. package/hooks/lib/constants.cjs +15 -0
  105. package/hooks/lib/mindlore-common.cjs +974 -1042
  106. package/hooks/mindlore-cwd-changed.cjs +57 -57
  107. package/hooks/mindlore-decision-detector.cjs +54 -54
  108. package/hooks/mindlore-dont-repeat.cjs +222 -222
  109. package/hooks/mindlore-fts5-sync.cjs +97 -88
  110. package/hooks/mindlore-index.cjs +229 -229
  111. package/hooks/mindlore-model-router.cjs +54 -54
  112. package/hooks/mindlore-post-compact.cjs +69 -69
  113. package/hooks/mindlore-post-read.cjs +106 -106
  114. package/hooks/mindlore-pre-compact.cjs +154 -154
  115. package/hooks/mindlore-read-guard.cjs +105 -105
  116. package/hooks/mindlore-research-guard.cjs +176 -176
  117. package/hooks/mindlore-search.cjs +200 -200
  118. package/hooks/mindlore-session-end.cjs +509 -526
  119. package/hooks/mindlore-session-focus.cjs +256 -259
  120. package/package.json +75 -78
  121. package/plugin.json +1 -1
  122. package/skills/mindlore-diary/SKILL.md +85 -85
  123. package/skills/mindlore-evolve/SKILL.md +126 -126
  124. package/skills/mindlore-explore/SKILL.md +109 -109
  125. package/skills/mindlore-ingest/SKILL.md +195 -195
  126. package/skills/mindlore-maintain/SKILL.md +125 -125
  127. package/skills/mindlore-query/SKILL.md +151 -151
  128. package/skills/mindlore-reflect/SKILL.md +141 -141
  129. package/skills/mindlore-stats/SKILL.md +106 -106
  130. package/templates/INDEX.md +14 -14
  131. package/templates/SCHEMA.md +292 -292
  132. package/templates/config.json +1 -1
  133. package/templates/extraction/article.md +15 -15
  134. package/templates/extraction/changelog.md +15 -15
  135. package/templates/extraction/default.md +15 -15
  136. package/templates/extraction/docs.md +15 -15
  137. package/templates/extraction/github-repo.md +17 -17
  138. package/dist/scripts/lib/daemon.d.ts +0 -16
  139. package/dist/scripts/lib/daemon.d.ts.map +0 -1
  140. package/dist/scripts/lib/daemon.js +0 -133
  141. package/dist/scripts/lib/daemon.js.map +0 -1
  142. package/dist/scripts/lib/embedding.d.ts +0 -5
  143. package/dist/scripts/lib/embedding.d.ts.map +0 -1
  144. package/dist/scripts/lib/embedding.js +0 -44
  145. package/dist/scripts/lib/embedding.js.map +0 -1
  146. package/dist/scripts/mindlore-daemon.d.ts +0 -2
  147. package/dist/scripts/mindlore-daemon.d.ts.map +0 -1
  148. package/dist/scripts/mindlore-daemon.js +0 -117
  149. package/dist/scripts/mindlore-daemon.js.map +0 -1
  150. package/dist/tests/daemon-integration.test.d.ts +0 -2
  151. package/dist/tests/daemon-integration.test.d.ts.map +0 -1
  152. package/dist/tests/daemon-integration.test.js +0 -37
  153. package/dist/tests/daemon-integration.test.js.map +0 -1
  154. package/dist/tests/daemon.test.d.ts +0 -2
  155. package/dist/tests/daemon.test.d.ts.map +0 -1
  156. package/dist/tests/daemon.test.js +0 -187
  157. package/dist/tests/daemon.test.js.map +0 -1
  158. package/dist/tests/embedding-hf-integration.test.d.ts +0 -2
  159. package/dist/tests/embedding-hf-integration.test.d.ts.map +0 -1
  160. package/dist/tests/embedding-hf-integration.test.js +0 -52
  161. package/dist/tests/embedding-hf-integration.test.js.map +0 -1
  162. package/dist/tests/embedding.test.d.ts +0 -6
  163. package/dist/tests/embedding.test.d.ts.map +0 -1
  164. package/dist/tests/embedding.test.js +0 -71
  165. package/dist/tests/embedding.test.js.map +0 -1
  166. package/dist/tests/sqlite-vec-v12.test.d.ts +0 -2
  167. package/dist/tests/sqlite-vec-v12.test.d.ts.map +0 -1
  168. package/dist/tests/sqlite-vec-v12.test.js +0 -72
  169. package/dist/tests/sqlite-vec-v12.test.js.map +0 -1
@@ -22,9 +22,9 @@ afterEach(() => {
22
22
  (0, db_js_1.destroyEpisodesTestEnv)(env);
23
23
  });
24
24
  function insertEpisode(db, opts) {
25
- db.prepare(`
26
- INSERT INTO episodes (id, kind, scope, summary, status, created_at, consolidation_status)
27
- VALUES (?, ?, 'project', ?, ?, ?, ?)
25
+ db.prepare(`
26
+ INSERT INTO episodes (id, kind, scope, summary, status, created_at, consolidation_status)
27
+ VALUES (?, ?, 'project', ?, ?, ?, ?)
28
28
  `).run(opts.id, opts.kind, opts.summary, opts.status ?? 'active', new Date().toISOString(), opts.consolidation_status ?? 'raw');
29
29
  }
30
30
  describe('countRawEpisodes', () => {
@@ -41,12 +41,12 @@ describe('groupEpisodesByKind', () => {
41
41
  insertEpisode(env.db, { id: 'ep-2', kind: 'session', summary: 'Session B' });
42
42
  insertEpisode(env.db, { id: 'ep-3', kind: 'decision', summary: 'Decision A' });
43
43
  insertEpisode(env.db, { id: 'ep-4', kind: 'session', summary: 'Consolidated', consolidation_status: 'consolidated' });
44
- insertEpisode(env.db, { id: 'ep-5', kind: 'insight', summary: 'Inactive', status: 'inactive' });
44
+ insertEpisode(env.db, { id: 'ep-5', kind: 'learning', summary: 'Inactive', status: 'inactive' });
45
45
  const groups = (0, consolidation_js_1.groupEpisodesByKind)(env.db);
46
46
  expect(groups.size).toBe(2);
47
47
  expect(groups.get('session')).toHaveLength(2);
48
48
  expect(groups.get('decision')).toHaveLength(1);
49
- expect(groups.has('insight')).toBe(false);
49
+ expect(groups.has('learning')).toBe(false);
50
50
  });
51
51
  });
52
52
  describe('markConsolidated', () => {
@@ -1 +1 @@
1
- {"version":3,"file":"consolidation.test.js","sourceRoot":"","sources":["../../tests/consolidation.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"consolidation.test.js","sourceRoot":"","sources":["../../tests/consolidation.test.ts"],"names":[],"mappings":"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"}
@@ -95,7 +95,7 @@ describe('recall shield', () => {
95
95
  });
96
96
  describe('archiveDocument / restoreDocument', () => {
97
97
  test('archiveDocument sets archived_at, restoreDocument clears it', () => {
98
- db.prepare(`INSERT INTO file_hashes (path, content_hash, last_indexed, recall_count, last_recalled_at, importance)
98
+ db.prepare(`INSERT INTO file_hashes (path, content_hash, last_indexed, recall_count, last_recalled_at, importance)
99
99
  VALUES (?, ?, ?, ?, ?, ?)`).run('/test/doc.md', 'abc123', new Date().toISOString(), 0, null, 1.0);
100
100
  (0, decay_js_1.archiveDocument)(db, '/test/doc.md');
101
101
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown, narrowing to expected row shape
@@ -112,10 +112,10 @@ describe('listStaleDocuments', () => {
112
112
  const ninetyDaysAgo = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000).toISOString();
113
113
  const now = new Date().toISOString();
114
114
  // Stale: old, never recalled
115
- db.prepare(`INSERT INTO file_hashes (path, content_hash, last_indexed, recall_count, last_recalled_at, importance)
115
+ db.prepare(`INSERT INTO file_hashes (path, content_hash, last_indexed, recall_count, last_recalled_at, importance)
116
116
  VALUES (?, ?, ?, ?, ?, ?)`).run('/test/stale.md', 'hash1', ninetyDaysAgo, 0, null, 1.0);
117
117
  // Active: recently recalled with high recall_count
118
- db.prepare(`INSERT INTO file_hashes (path, content_hash, last_indexed, recall_count, last_recalled_at, importance)
118
+ db.prepare(`INSERT INTO file_hashes (path, content_hash, last_indexed, recall_count, last_recalled_at, importance)
119
119
  VALUES (?, ?, ?, ?, ?, ?)`).run('/test/active.md', 'hash2', now, 20, now, 1.0);
120
120
  const stale = (0, decay_js_1.listStaleDocuments)(db, 0.3);
121
121
  const paths = stale.map(d => d.path);
@@ -129,7 +129,7 @@ describe('listStaleDocuments', () => {
129
129
  });
130
130
  describe('persistDecayScores', () => {
131
131
  test('should write decay_score and last_decay_calc to episodes', () => {
132
- db.prepare(`INSERT INTO episodes (id, kind, scope, summary, created_at)
132
+ db.prepare(`INSERT INTO episodes (id, kind, scope, summary, created_at)
133
133
  VALUES ('test-decay-1', 'learning', 'project', 'test', datetime('now'))`).run();
134
134
  (0, decay_js_1.persistDecayScores)(db);
135
135
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown
@@ -139,15 +139,15 @@ describe('persistDecayScores', () => {
139
139
  expect(row.last_decay_calc).toBeTruthy();
140
140
  });
141
141
  test('should return count of updated episodes', () => {
142
- db.prepare(`INSERT INTO episodes (id, kind, scope, summary, created_at)
142
+ db.prepare(`INSERT INTO episodes (id, kind, scope, summary, created_at)
143
143
  VALUES ('test-decay-2', 'decision', 'project', 'decision test', datetime('now'))`).run();
144
- db.prepare(`INSERT INTO episodes (id, kind, scope, summary, created_at)
144
+ db.prepare(`INSERT INTO episodes (id, kind, scope, summary, created_at)
145
145
  VALUES ('test-decay-3', 'observation', 'project', 'obs test', datetime('now'))`).run();
146
146
  const count = (0, decay_js_1.persistDecayScores)(db);
147
147
  expect(count).toBe(2);
148
148
  });
149
149
  test('should skip non-active episodes', () => {
150
- db.prepare(`INSERT INTO episodes (id, kind, scope, summary, status, created_at)
150
+ db.prepare(`INSERT INTO episodes (id, kind, scope, summary, status, created_at)
151
151
  VALUES ('test-decay-4', 'learning', 'project', 'archived', 'archived', datetime('now'))`).run();
152
152
  const count = (0, decay_js_1.persistDecayScores)(db);
153
153
  expect(count).toBe(0);
@@ -157,9 +157,9 @@ describe('persistDecayScores', () => {
157
157
  });
158
158
  test('should assign higher importance to learning and decision kinds', () => {
159
159
  const oldDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
160
- db.prepare(`INSERT INTO episodes (id, kind, scope, summary, created_at)
160
+ db.prepare(`INSERT INTO episodes (id, kind, scope, summary, created_at)
161
161
  VALUES ('decay-learn', 'learning', 'project', 'learn', ?)`).run(oldDate);
162
- db.prepare(`INSERT INTO episodes (id, kind, scope, summary, created_at)
162
+ db.prepare(`INSERT INTO episodes (id, kind, scope, summary, created_at)
163
163
  VALUES ('decay-obs', 'observation', 'project', 'obs', ?)`).run(oldDate);
164
164
  (0, decay_js_1.persistDecayScores)(db);
165
165
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown
@@ -100,9 +100,9 @@ describe('diary workflow: bare session → enriched episodes', () => {
100
100
  });
101
101
  test('finding latest bare session for diary analysis', () => {
102
102
  // Simulate multiple sessions
103
- db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
103
+ db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
104
104
  VALUES ('ep-old', 'session', 'project', 'mindlore', 'Old session', 'active', 'hook', '2026-04-12T10:00:00.000Z')`).run();
105
- db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
105
+ db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
106
106
  VALUES ('ep-new', 'session', 'project', 'mindlore', 'Latest session', 'active', 'hook', '2026-04-13T15:00:00.000Z')`).run();
107
107
  // Query like diary would: find latest session episode
108
108
  const sessions = queryRecentEpisodes(db, { project: 'mindlore', limit: 1 });
@@ -154,9 +154,9 @@ describe('reflect input: episodes query', () => {
154
154
  expect(reflectInput.some(e => e.source === 'reflect')).toBe(false);
155
155
  });
156
156
  test('reflect filters by date range', () => {
157
- db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
157
+ db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
158
158
  VALUES ('ep-old', 'friction', 'project', 'mindlore', 'Old friction', 'active', 'diary', '2026-04-01T10:00:00.000Z')`).run();
159
- db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
159
+ db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
160
160
  VALUES ('ep-recent', 'friction', 'project', 'mindlore', 'Recent friction', 'active', 'diary', '2026-04-13T10:00:00.000Z')`).run();
161
161
  const lastWeek = (0, episodes_js_1.queryEpisodes)(db, {
162
162
  project: 'mindlore',
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=episode-kind-constant.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"episode-kind-constant.test.d.ts","sourceRoot":"","sources":["../../tests/episode-kind-constant.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ describe('Episode kind shared constant', () => {
4
+ test('CJS and TS share the same kinds array', () => {
5
+ const { EPISODE_KINDS: cjsKinds } = require('../hooks/lib/constants.cjs');
6
+ const { EPISODE_KINDS: tsKinds } = require('../scripts/lib/episodes.js');
7
+ expect(cjsKinds).toEqual([...tsKinds]);
8
+ });
9
+ test('isValidKind validates correctly', () => {
10
+ const { isValidKind } = require('../hooks/lib/constants.cjs');
11
+ expect(isValidKind('nomination')).toBe(true);
12
+ expect(isValidKind('invalid-kind')).toBe(false);
13
+ expect(isValidKind('')).toBe(false);
14
+ });
15
+ });
16
+ describe('DB_BUSY_TIMEOUT_MS shared constant', () => {
17
+ test('CJS and TS export the same value', () => {
18
+ const { DB_BUSY_TIMEOUT_MS: cjsTimeout } = require('../hooks/lib/constants.cjs');
19
+ const { DB_BUSY_TIMEOUT_MS: tsTimeout } = require('../scripts/lib/constants.js');
20
+ expect(cjsTimeout).toBe(tsTimeout);
21
+ });
22
+ test('value is a positive integer', () => {
23
+ const { DB_BUSY_TIMEOUT_MS } = require('../hooks/lib/constants.cjs');
24
+ expect(Number.isInteger(DB_BUSY_TIMEOUT_MS)).toBe(true);
25
+ expect(DB_BUSY_TIMEOUT_MS).toBeGreaterThan(0);
26
+ });
27
+ });
28
+ //# sourceMappingURL=episode-kind-constant.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"episode-kind-constant.test.js","sourceRoot":"","sources":["../../tests/episode-kind-constant.test.ts"],"names":[],"mappings":";;AAAA,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,IAAI,CAAC,uCAAuC,EAAE,GAAG,EAAE;QACjD,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;QAC1E,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;QACzE,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iCAAiC,EAAE,GAAG,EAAE;QAC3C,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;QAC9D,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,IAAI,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC5C,MAAM,EAAE,kBAAkB,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;QACjF,MAAM,EAAE,kBAAkB,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAAC;QACjF,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACvC,MAAM,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;QACrE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,MAAM,CAAC,kBAAkB,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -25,11 +25,11 @@ afterEach(() => {
25
25
  describe('session-focus episode injection', () => {
26
26
  test('queryRecentEpisodes returns episodes ordered by created_at DESC', () => {
27
27
  // Insert with explicit timestamps to guarantee order
28
- db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
28
+ db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
29
29
  VALUES ('ep-1', 'session', 'project', 'mindlore', 'First session', 'active', 'hook', '2026-04-13T10:00:00.000Z')`).run();
30
- db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
30
+ db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
31
31
  VALUES ('ep-2', 'decision', 'project', 'mindlore', 'Chose SQLite', 'active', 'diary', '2026-04-13T11:00:00.000Z')`).run();
32
- db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
32
+ db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
33
33
  VALUES ('ep-3', 'learning', 'project', 'mindlore', 'Use ctx_execute_file', 'active', 'reflect', '2026-04-13T12:00:00.000Z')`).run();
34
34
  const episodes = queryRecentEpisodes(db, { project: 'mindlore', limit: 3 });
35
35
  expect(episodes).toHaveLength(3);
@@ -147,9 +147,9 @@ describe('episode stale filter', () => {
147
147
  test('excludes episodes older than 7 days', () => {
148
148
  const oldDate = new Date(Date.now() - 8 * 24 * 60 * 60 * 1000).toISOString();
149
149
  const recentDate = new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString();
150
- migEnv.db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
150
+ migEnv.db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
151
151
  VALUES ('ep-old', 'decision', 'project', 'mindlore', 'Old decision', 'active', 'diary', ?)`).run(oldDate);
152
- migEnv.db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
152
+ migEnv.db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
153
153
  VALUES ('ep-new', 'decision', 'project', 'mindlore', 'Recent decision', 'active', 'diary', ?)`).run(recentDate);
154
154
  const payload = (0, session_payload_js_1.buildSessionPayload)({ db: migEnv.db, baseDir: migEnv.tmpDir, project: 'mindlore' });
155
155
  const decisionsSection = payload.sections.find(s => s.label === 'Decisions');
@@ -159,7 +159,7 @@ describe('episode stale filter', () => {
159
159
  });
160
160
  test('includes episodes within 7 days', () => {
161
161
  const recentDate = new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString();
162
- migEnv.db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
162
+ migEnv.db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
163
163
  VALUES ('ep-r', 'learning', 'project', 'mindlore', 'Recent learning', 'active', 'reflect', ?)`).run(recentDate);
164
164
  const payload = (0, session_payload_js_1.buildSessionPayload)({ db: migEnv.db, baseDir: migEnv.tmpDir, project: 'mindlore' });
165
165
  const learningsSection = payload.sections.find(s => s.label === 'Learnings');
@@ -177,7 +177,7 @@ describe('episode inject dedup', () => {
177
177
  });
178
178
  test('excludes episodes already injected in this session', () => {
179
179
  const recentDate = new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString();
180
- migEnv.db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
180
+ migEnv.db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
181
181
  VALUES ('ep-d1', 'decision', 'project', 'mindlore', 'Already injected decision', 'active', 'diary', ?)`).run(recentDate);
182
182
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown
183
183
  const rowid = migEnv.db.prepare(`SELECT rowid FROM episodes WHERE id = 'ep-d1'`).get().rowid;
@@ -189,7 +189,7 @@ describe('episode inject dedup', () => {
189
189
  });
190
190
  test('logs newly injected episodes to episode_inject_log', () => {
191
191
  const recentDate = new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString();
192
- migEnv.db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
192
+ migEnv.db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
193
193
  VALUES ('ep-d2', 'learning', 'project', 'mindlore', 'New learning to log', 'active', 'reflect', ?)`).run(recentDate);
194
194
  (0, session_payload_js_1.buildSessionPayload)({ db: migEnv.db, baseDir: migEnv.tmpDir, project: 'mindlore', tokenBudget: 2000, sessionId: 'session-xyz' });
195
195
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .all() returns unknown[]
@@ -198,7 +198,7 @@ describe('episode inject dedup', () => {
198
198
  });
199
199
  test('does not log when sessionId is not provided', () => {
200
200
  const recentDate = new Date(Date.now() - 1 * 24 * 60 * 60 * 1000).toISOString();
201
- migEnv.db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
201
+ migEnv.db.prepare(`INSERT INTO episodes (id, kind, scope, project, summary, status, source, created_at)
202
202
  VALUES ('ep-d3', 'friction', 'project', 'mindlore', 'Friction point', 'active', 'diary', ?)`).run(recentDate);
203
203
  (0, session_payload_js_1.buildSessionPayload)({ db: migEnv.db, baseDir: migEnv.tmpDir, project: 'mindlore' });
204
204
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .all() returns unknown[]
@@ -8,6 +8,7 @@ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
8
8
  const fs_1 = __importDefault(require("fs"));
9
9
  const db_js_1 = require("./helpers/db.js");
10
10
  const db_helpers_js_1 = require("../scripts/lib/db-helpers.js");
11
+ const constants_js_1 = require("../scripts/lib/constants.js");
11
12
  const TEST_DIR = path_1.default.join(__dirname, '..', '.test-mindlore-fts5');
12
13
  const DB_PATH = path_1.default.join(TEST_DIR, 'mindlore.db');
13
14
  beforeEach(() => {
@@ -33,9 +34,9 @@ describe('FTS5 Database', () => {
33
34
  const testPath = path_1.default.join(TEST_DIR, 'sources', 'typescript-guide.md');
34
35
  const content = '# TypeScript Guide\n\nTypeScript provides static typing for JavaScript applications.';
35
36
  (0, db_js_1.insertFts)(db, { path: testPath, slug: 'typescript-guide', description: 'TypeScript static typing for JavaScript', type: 'source', category: 'sources', title: 'TypeScript Guide', content, tags: '', quality: null, dateCaptured: null });
36
- const results = (0, db_helpers_js_1.dbAll)(db, `SELECT path, rank FROM mindlore_fts
37
- WHERE mindlore_fts MATCH ?
38
- ORDER BY rank
37
+ const results = (0, db_helpers_js_1.dbAll)(db, `SELECT path, rank FROM mindlore_fts
38
+ WHERE mindlore_fts MATCH ?
39
+ ORDER BY rank
39
40
  LIMIT 3`, 'TypeScript');
40
41
  expect(results).toHaveLength(1);
41
42
  expect(results[0].path).toBe(testPath);
@@ -45,9 +46,9 @@ describe('FTS5 Database', () => {
45
46
  const db = new better_sqlite3_1.default(DB_PATH);
46
47
  const testPath = path_1.default.join(TEST_DIR, 'sources', 'python-guide.md');
47
48
  (0, db_js_1.insertFts)(db, { path: testPath, slug: 'python-guide', description: 'Python for data science', type: 'source', category: 'sources', title: 'Python Guide', content: '# Python Guide\n\nPython is great for data science.', tags: '', quality: null, dateCaptured: null });
48
- const results = (0, db_helpers_js_1.dbAll)(db, `SELECT path FROM mindlore_fts
49
- WHERE mindlore_fts MATCH ?
50
- ORDER BY rank
49
+ const results = (0, db_helpers_js_1.dbAll)(db, `SELECT path FROM mindlore_fts
50
+ WHERE mindlore_fts MATCH ?
51
+ ORDER BY rank
51
52
  LIMIT 3`, 'Kubernetes');
52
53
  expect(results).toHaveLength(0);
53
54
  db.close();
@@ -56,9 +57,9 @@ describe('FTS5 Database', () => {
56
57
  const db = new better_sqlite3_1.default(DB_PATH);
57
58
  (0, db_js_1.insertFts)(db, { path: path_1.default.join(TEST_DIR, 'sources', 'hooks-overview.md'), slug: 'hooks-overview', description: 'Hooks lifecycle callbacks overview', type: 'source', category: 'sources', title: 'Hooks Overview', content: '# Hooks Overview\n\nHooks are lifecycle callbacks.', tags: '', quality: null, dateCaptured: null });
58
59
  (0, db_js_1.insertFts)(db, { path: path_1.default.join(TEST_DIR, 'sources', 'hooks-deep-dive.md'), slug: 'hooks-deep-dive', description: 'Deep dive into hooks patterns', type: 'source', category: 'sources', title: 'Hooks Deep Dive', content: '# Hooks Deep Dive\n\nHooks hooks hooks. PreToolUse hooks, PostToolUse hooks, SessionStart hooks.', tags: '', quality: null, dateCaptured: null });
59
- const results = (0, db_helpers_js_1.dbAll)(db, `SELECT path, rank FROM mindlore_fts
60
- WHERE mindlore_fts MATCH ?
61
- ORDER BY rank
60
+ const results = (0, db_helpers_js_1.dbAll)(db, `SELECT path, rank FROM mindlore_fts
61
+ WHERE mindlore_fts MATCH ?
62
+ ORDER BY rank
62
63
  LIMIT 3`, 'hooks');
63
64
  expect(results).toHaveLength(2);
64
65
  const deepDive = results.find((r) => r.path.includes('deep-dive'));
@@ -70,9 +71,9 @@ describe('FTS5 Database', () => {
70
71
  test('should index and search by tags column', () => {
71
72
  const db = new better_sqlite3_1.default(DB_PATH);
72
73
  (0, db_js_1.insertFts)(db, { path: path_1.default.join(TEST_DIR, 'sources', 'tagged-doc.md'), slug: 'tagged-doc', description: 'A doc with tags', type: 'source', category: 'sources', title: 'Tagged Doc', content: '# Tagged\n\nContent here.', tags: 'security, hooks, fts5', quality: null, dateCaptured: null });
73
- const results = (0, db_helpers_js_1.dbAll)(db, `SELECT path, tags FROM mindlore_fts
74
- WHERE tags MATCH ?
75
- ORDER BY rank
74
+ const results = (0, db_helpers_js_1.dbAll)(db, `SELECT path, tags FROM mindlore_fts
75
+ WHERE tags MATCH ?
76
+ ORDER BY rank
76
77
  LIMIT 3`, 'security');
77
78
  expect(results).toHaveLength(1);
78
79
  expect(results[0].tags).toBe('security, hooks, fts5');
@@ -109,7 +110,7 @@ describe('openDatabaseTs', () => {
109
110
  const walMode = db.pragma('journal_mode', { simple: true });
110
111
  expect(walMode).toBe('wal');
111
112
  const timeout = db.pragma('busy_timeout', { simple: true });
112
- expect(timeout).toBe(5000);
113
+ expect(timeout).toBe(constants_js_1.DB_BUSY_TIMEOUT_MS);
113
114
  db.close();
114
115
  });
115
116
  test('readonly should NOT set WAL', () => {
@@ -129,67 +130,7 @@ describe('openDatabase CJS', () => {
129
130
  const walMode = db.pragma('journal_mode', { simple: true });
130
131
  expect(walMode).toBe('wal');
131
132
  const timeout = db.pragma('busy_timeout', { simple: true });
132
- expect(timeout).toBe(5000);
133
- db.close();
134
- });
135
- });
136
- describe('Index with Embedding', () => {
137
- test('should populate vec table when sqlite-vec is loaded', () => {
138
- const { loadSqliteVec, ensureVecTable, hasVecTable: hasVec } = require('../scripts/lib/db-helpers.js');
139
- const db = new better_sqlite3_1.default(DB_PATH);
140
- const vecLoaded = loadSqliteVec(db);
141
- if (!vecLoaded) {
142
- console.log('sqlite-vec not available — skipping embed test');
143
- db.close();
144
- return;
145
- }
146
- ensureVecTable(db);
147
- expect(hasVec(db)).toBe(true);
148
- // Insert a document to FTS
149
- (0, db_js_1.insertFts)(db, {
150
- path: path_1.default.join(TEST_DIR, 'sources', 'embed-test.md'),
151
- slug: 'embed-test',
152
- description: 'Document for embedding test',
153
- type: 'source',
154
- category: 'sources',
155
- title: 'Embed Test',
156
- content: 'This document tests the embedding pipeline integration',
157
- tags: 'test,embedding',
158
- });
159
- // Manually test vec insert with fake embedding
160
- const fakeEmbedding = new Float32Array(384);
161
- fakeEmbedding[0] = 1.0;
162
- const buf = Buffer.from(fakeEmbedding.buffer);
163
- db.prepare('INSERT INTO documents_vec (embedding, slug, created_at, model_name) VALUES (?, ?, ?, ?)').run(buf, 'embed-test', new Date().toISOString(), 'Xenova/multilingual-e5-small');
164
- // Verify vec entry
165
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- test: better-sqlite3 .get() returns unknown
166
- const row = db.prepare('SELECT slug FROM documents_vec WHERE slug = ?').get('embed-test');
167
- expect(row?.slug).toBe('embed-test');
168
- db.close();
169
- });
170
- });
171
- describe('Vec Table', () => {
172
- test('should load sqlite-vec extension and create vec table', () => {
173
- const { loadSqliteVec, ensureVecTable } = require('../scripts/lib/db-helpers.js');
174
- const db = new better_sqlite3_1.default(DB_PATH);
175
- const loaded = loadSqliteVec(db);
176
- expect(loaded).toBe(true);
177
- ensureVecTable(db);
178
- // Verify table exists by inserting and querying
179
- const testEmbedding = new Float32Array(384);
180
- testEmbedding[0] = 1.0; // unit vector along first dimension
181
- db.prepare('INSERT INTO documents_vec (embedding, slug, created_at, model_name) VALUES (?, ?, ?, ?)').run(Buffer.from(testEmbedding.buffer), 'test-slug', new Date().toISOString(), 'test-model');
182
- // vec0 metadata columns are filterable in WHERE
183
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- test: better-sqlite3 .get() returns unknown
184
- const row = db.prepare('SELECT slug FROM documents_vec WHERE slug = ?').get('test-slug');
185
- expect(row?.slug).toBe('test-slug');
186
- db.close();
187
- });
188
- test('should return false when sqlite-vec is not available', () => {
189
- const { ensureVecTable } = require('../scripts/lib/db-helpers.js');
190
- const db = new better_sqlite3_1.default(DB_PATH);
191
- // Without loadSqliteVec, ensureVecTable should handle gracefully
192
- expect(() => ensureVecTable(db)).not.toThrow();
133
+ expect(timeout).toBe(constants_js_1.DB_BUSY_TIMEOUT_MS);
193
134
  db.close();
194
135
  });
195
136
  });
@@ -202,13 +143,13 @@ describe('Timestamp columns', () => {
202
143
  const hash1 = 'aaa111';
203
144
  const now1 = '2026-04-19T10:00:00.000Z';
204
145
  // Simulate first index: INSERT with created_at, no updated_at
205
- const upsertHash = db.prepare(`
206
- INSERT INTO file_hashes (path, content_hash, last_indexed, created_at)
207
- VALUES (?, ?, ?, datetime('now'))
208
- ON CONFLICT(path) DO UPDATE SET
209
- content_hash = excluded.content_hash,
210
- last_indexed = excluded.last_indexed,
211
- updated_at = datetime('now')
146
+ const upsertHash = db.prepare(`
147
+ INSERT INTO file_hashes (path, content_hash, last_indexed, created_at)
148
+ VALUES (?, ?, ?, datetime('now'))
149
+ ON CONFLICT(path) DO UPDATE SET
150
+ content_hash = excluded.content_hash,
151
+ last_indexed = excluded.last_indexed,
152
+ updated_at = datetime('now')
212
153
  `);
213
154
  upsertHash.run(testPath, hash1, now1);
214
155
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown
@@ -235,14 +176,14 @@ describe('Project scope on index', () => {
235
176
  const hash = 'abc123';
236
177
  const now = '2026-04-19T12:00:00.000Z';
237
178
  const projectName = 'test-project';
238
- const upsertHash = db.prepare(`
239
- INSERT INTO file_hashes (path, content_hash, last_indexed, created_at, project_scope)
240
- VALUES (?, ?, ?, datetime('now'), ?)
241
- ON CONFLICT(path) DO UPDATE SET
242
- content_hash = excluded.content_hash,
243
- last_indexed = excluded.last_indexed,
244
- updated_at = datetime('now'),
245
- project_scope = excluded.project_scope
179
+ const upsertHash = db.prepare(`
180
+ INSERT INTO file_hashes (path, content_hash, last_indexed, created_at, project_scope)
181
+ VALUES (?, ?, ?, datetime('now'), ?)
182
+ ON CONFLICT(path) DO UPDATE SET
183
+ content_hash = excluded.content_hash,
184
+ last_indexed = excluded.last_indexed,
185
+ updated_at = datetime('now'),
186
+ project_scope = excluded.project_scope
246
187
  `);
247
188
  upsertHash.run(testPath, hash, now, projectName);
248
189
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown
@@ -259,15 +200,15 @@ describe('Quality to importance mapping', () => {
259
200
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- test helper returns Database
260
201
  const db = createTestDbWithMigrations(DB_PATH);
261
202
  const testPath = path_1.default.join(TEST_DIR, 'sources', 'test-importance-high.md');
262
- const upsertHash = db.prepare(`
263
- INSERT INTO file_hashes (path, content_hash, last_indexed, created_at, project_scope, importance)
264
- VALUES (?, ?, ?, datetime('now'), ?, ?)
265
- ON CONFLICT(path) DO UPDATE SET
266
- content_hash = excluded.content_hash,
267
- last_indexed = excluded.last_indexed,
268
- updated_at = datetime('now'),
269
- project_scope = excluded.project_scope,
270
- importance = excluded.importance
203
+ const upsertHash = db.prepare(`
204
+ INSERT INTO file_hashes (path, content_hash, last_indexed, created_at, project_scope, importance)
205
+ VALUES (?, ?, ?, datetime('now'), ?, ?)
206
+ ON CONFLICT(path) DO UPDATE SET
207
+ content_hash = excluded.content_hash,
208
+ last_indexed = excluded.last_indexed,
209
+ updated_at = datetime('now'),
210
+ project_scope = excluded.project_scope,
211
+ importance = excluded.importance
271
212
  `);
272
213
  // Simulate indexer: quality 'high' -> importance 1.0
273
214
  upsertHash.run(testPath, 'aaa', '2026-04-19T10:00:00.000Z', 'test', 1.0);
@@ -281,15 +222,15 @@ describe('Quality to importance mapping', () => {
281
222
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- test helper returns Database
282
223
  const db = createTestDbWithMigrations(DB_PATH);
283
224
  const testPath = path_1.default.join(TEST_DIR, 'sources', 'test-importance-medium.md');
284
- const upsertHash = db.prepare(`
285
- INSERT INTO file_hashes (path, content_hash, last_indexed, created_at, project_scope, importance)
286
- VALUES (?, ?, ?, datetime('now'), ?, ?)
287
- ON CONFLICT(path) DO UPDATE SET
288
- content_hash = excluded.content_hash,
289
- last_indexed = excluded.last_indexed,
290
- updated_at = datetime('now'),
291
- project_scope = excluded.project_scope,
292
- importance = excluded.importance
225
+ const upsertHash = db.prepare(`
226
+ INSERT INTO file_hashes (path, content_hash, last_indexed, created_at, project_scope, importance)
227
+ VALUES (?, ?, ?, datetime('now'), ?, ?)
228
+ ON CONFLICT(path) DO UPDATE SET
229
+ content_hash = excluded.content_hash,
230
+ last_indexed = excluded.last_indexed,
231
+ updated_at = datetime('now'),
232
+ project_scope = excluded.project_scope,
233
+ importance = excluded.importance
293
234
  `);
294
235
  upsertHash.run(testPath, 'bbb', '2026-04-19T10:00:00.000Z', 'test', 0.6);
295
236
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown
@@ -302,15 +243,15 @@ describe('Quality to importance mapping', () => {
302
243
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- test helper returns Database
303
244
  const db = createTestDbWithMigrations(DB_PATH);
304
245
  const testPath = path_1.default.join(TEST_DIR, 'sources', 'test-importance-low.md');
305
- const upsertHash = db.prepare(`
306
- INSERT INTO file_hashes (path, content_hash, last_indexed, created_at, project_scope, importance)
307
- VALUES (?, ?, ?, datetime('now'), ?, ?)
308
- ON CONFLICT(path) DO UPDATE SET
309
- content_hash = excluded.content_hash,
310
- last_indexed = excluded.last_indexed,
311
- updated_at = datetime('now'),
312
- project_scope = excluded.project_scope,
313
- importance = excluded.importance
246
+ const upsertHash = db.prepare(`
247
+ INSERT INTO file_hashes (path, content_hash, last_indexed, created_at, project_scope, importance)
248
+ VALUES (?, ?, ?, datetime('now'), ?, ?)
249
+ ON CONFLICT(path) DO UPDATE SET
250
+ content_hash = excluded.content_hash,
251
+ last_indexed = excluded.last_indexed,
252
+ updated_at = datetime('now'),
253
+ project_scope = excluded.project_scope,
254
+ importance = excluded.importance
314
255
  `);
315
256
  upsertHash.run(testPath, 'ccc', '2026-04-19T10:00:00.000Z', 'test', 0.3);
316
257
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown
@@ -323,15 +264,15 @@ describe('Quality to importance mapping', () => {
323
264
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- test helper returns Database
324
265
  const db = createTestDbWithMigrations(DB_PATH);
325
266
  const testPath = path_1.default.join(TEST_DIR, 'sources', 'test-no-quality.md');
326
- const upsertHash = db.prepare(`
327
- INSERT INTO file_hashes (path, content_hash, last_indexed, created_at, project_scope, importance)
328
- VALUES (?, ?, ?, datetime('now'), ?, ?)
329
- ON CONFLICT(path) DO UPDATE SET
330
- content_hash = excluded.content_hash,
331
- last_indexed = excluded.last_indexed,
332
- updated_at = datetime('now'),
333
- project_scope = excluded.project_scope,
334
- importance = excluded.importance
267
+ const upsertHash = db.prepare(`
268
+ INSERT INTO file_hashes (path, content_hash, last_indexed, created_at, project_scope, importance)
269
+ VALUES (?, ?, ?, datetime('now'), ?, ?)
270
+ ON CONFLICT(path) DO UPDATE SET
271
+ content_hash = excluded.content_hash,
272
+ last_indexed = excluded.last_indexed,
273
+ updated_at = datetime('now'),
274
+ project_scope = excluded.project_scope,
275
+ importance = excluded.importance
335
276
  `);
336
277
  // quality undefined -> default 0.5
337
278
  upsertHash.run(testPath, 'ddd', '2026-04-19T10:00:00.000Z', 'test', 0.5);