memento-mcp-server 1.12.0 → 1.13.0-b

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 (119) hide show
  1. package/dist/algorithms/forgetting-algorithm.d.ts +21 -13
  2. package/dist/algorithms/forgetting-algorithm.d.ts.map +1 -1
  3. package/dist/algorithms/forgetting-algorithm.js +32 -24
  4. package/dist/algorithms/forgetting-algorithm.js.map +1 -1
  5. package/dist/algorithms/hybrid-search-engine.d.ts +11 -9
  6. package/dist/algorithms/hybrid-search-engine.d.ts.map +1 -1
  7. package/dist/algorithms/hybrid-search-engine.js +77 -75
  8. package/dist/algorithms/hybrid-search-engine.js.map +1 -1
  9. package/dist/algorithms/search-engine.d.ts +33 -11
  10. package/dist/algorithms/search-engine.d.ts.map +1 -1
  11. package/dist/algorithms/search-engine.js +157 -62
  12. package/dist/algorithms/search-engine.js.map +1 -1
  13. package/dist/algorithms/search-ranking.d.ts +57 -50
  14. package/dist/algorithms/search-ranking.d.ts.map +1 -1
  15. package/dist/algorithms/search-ranking.js +91 -84
  16. package/dist/algorithms/search-ranking.js.map +1 -1
  17. package/dist/algorithms/spaced-repetition.d.ts +18 -13
  18. package/dist/algorithms/spaced-repetition.d.ts.map +1 -1
  19. package/dist/algorithms/spaced-repetition.js +28 -23
  20. package/dist/algorithms/spaced-repetition.js.map +1 -1
  21. package/dist/algorithms/vector-search-engine-migration.d.ts +8 -6
  22. package/dist/algorithms/vector-search-engine-migration.d.ts.map +1 -1
  23. package/dist/algorithms/vector-search-engine-migration.js +13 -11
  24. package/dist/algorithms/vector-search-engine-migration.js.map +1 -1
  25. package/dist/algorithms/vector-search-engine-refactored.d.ts +7 -7
  26. package/dist/algorithms/vector-search-engine-refactored.d.ts.map +1 -1
  27. package/dist/algorithms/vector-search-engine-refactored.js +7 -7
  28. package/dist/algorithms/vector-search-engine-refactored.js.map +1 -1
  29. package/dist/algorithms/vector-search-engine.d.ts +25 -20
  30. package/dist/algorithms/vector-search-engine.d.ts.map +1 -1
  31. package/dist/algorithms/vector-search-engine.js +47 -43
  32. package/dist/algorithms/vector-search-engine.js.map +1 -1
  33. package/dist/config/index.d.ts.map +1 -1
  34. package/dist/config/index.js +4 -1
  35. package/dist/config/index.js.map +1 -1
  36. package/dist/database/init.d.ts.map +1 -1
  37. package/dist/database/init.js +24 -4
  38. package/dist/database/init.js.map +1 -1
  39. package/dist/database/migration/migrations/006-fts5-reflection-notes-migration-status.sql +30 -0
  40. package/dist/database/migration/migrations/006-fts5-reflection-notes.d.ts +113 -0
  41. package/dist/database/migration/migrations/006-fts5-reflection-notes.d.ts.map +1 -0
  42. package/dist/database/migration/migrations/006-fts5-reflection-notes.js +441 -0
  43. package/dist/database/migration/migrations/006-fts5-reflection-notes.js.map +1 -0
  44. package/dist/database/migration/migrations/006-fts5-reflection-notes.sql +26 -0
  45. package/dist/database/schema.sql +11 -9
  46. package/dist/server/bootstrap.d.ts +4 -0
  47. package/dist/server/bootstrap.d.ts.map +1 -1
  48. package/dist/server/bootstrap.js +11 -1
  49. package/dist/server/bootstrap.js.map +1 -1
  50. package/dist/server/context.d.ts.map +1 -1
  51. package/dist/server/context.js +3 -1
  52. package/dist/server/context.js.map +1 -1
  53. package/dist/server/http-server.d.ts.map +1 -1
  54. package/dist/server/http-server.js +2 -1
  55. package/dist/server/http-server.js.map +1 -1
  56. package/dist/server/index.js +3 -1
  57. package/dist/server/index.js.map +1 -1
  58. package/dist/services/async-optimizer.d.ts +2 -1
  59. package/dist/services/async-optimizer.d.ts.map +1 -1
  60. package/dist/services/async-optimizer.js +28 -1
  61. package/dist/services/async-optimizer.js.map +1 -1
  62. package/dist/services/batch-scheduler.d.ts +5 -1
  63. package/dist/services/batch-scheduler.d.ts.map +1 -1
  64. package/dist/services/batch-scheduler.js +13 -1
  65. package/dist/services/batch-scheduler.js.map +1 -1
  66. package/dist/services/cache-service.js +1 -1
  67. package/dist/services/cache-service.js.map +1 -1
  68. package/dist/services/failure-detector.d.ts +120 -0
  69. package/dist/services/failure-detector.d.ts.map +1 -0
  70. package/dist/services/failure-detector.js +370 -0
  71. package/dist/services/failure-detector.js.map +1 -0
  72. package/dist/services/llm-based-relation-extractor.js +1 -1
  73. package/dist/services/llm-based-relation-extractor.js.map +1 -1
  74. package/dist/services/reflexion-worker.d.ts +170 -0
  75. package/dist/services/reflexion-worker.d.ts.map +1 -0
  76. package/dist/services/reflexion-worker.js +636 -0
  77. package/dist/services/reflexion-worker.js.map +1 -0
  78. package/dist/services/relation-graph.d.ts +2 -2
  79. package/dist/services/relation-graph.js +3 -3
  80. package/dist/services/relation-graph.js.map +1 -1
  81. package/dist/tools/base-tool.d.ts +5 -0
  82. package/dist/tools/base-tool.d.ts.map +1 -1
  83. package/dist/tools/base-tool.js +39 -0
  84. package/dist/tools/base-tool.js.map +1 -1
  85. package/dist/tools/recall-tool.d.ts.map +1 -1
  86. package/dist/tools/recall-tool.js +36 -2
  87. package/dist/tools/recall-tool.js.map +1 -1
  88. package/dist/tools/remember-tool.d.ts +24 -0
  89. package/dist/tools/remember-tool.d.ts.map +1 -1
  90. package/dist/tools/remember-tool.js +445 -273
  91. package/dist/tools/remember-tool.js.map +1 -1
  92. package/dist/tools/types.d.ts +5 -1
  93. package/dist/tools/types.d.ts.map +1 -1
  94. package/dist/tools/types.js +1 -1
  95. package/dist/tools/types.js.map +1 -1
  96. package/dist/types/index.d.ts +2 -0
  97. package/dist/types/index.d.ts.map +1 -1
  98. package/dist/types/index.js.map +1 -1
  99. package/dist/utils/database.d.ts.map +1 -1
  100. package/dist/utils/database.js +34 -10
  101. package/dist/utils/database.js.map +1 -1
  102. package/dist/utils/fts5-migration-status.d.ts +72 -0
  103. package/dist/utils/fts5-migration-status.d.ts.map +1 -0
  104. package/dist/utils/fts5-migration-status.js +304 -0
  105. package/dist/utils/fts5-migration-status.js.map +1 -0
  106. package/dist/utils/reflection-notes-merge.d.ts +58 -0
  107. package/dist/utils/reflection-notes-merge.d.ts.map +1 -0
  108. package/dist/utils/reflection-notes-merge.js +227 -0
  109. package/dist/utils/reflection-notes-merge.js.map +1 -0
  110. package/dist/utils/reflection-notes-normalize.d.ts +43 -0
  111. package/dist/utils/reflection-notes-normalize.d.ts.map +1 -0
  112. package/dist/utils/reflection-notes-normalize.js +164 -0
  113. package/dist/utils/reflection-notes-normalize.js.map +1 -0
  114. package/dist/utils/reflection-notes-schema.d.ts +84 -0
  115. package/dist/utils/reflection-notes-schema.d.ts.map +1 -0
  116. package/dist/utils/reflection-notes-schema.js +215 -0
  117. package/dist/utils/reflection-notes-schema.js.map +1 -0
  118. package/package.json +3 -1
  119. package/src/database/schema.sql +11 -9
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Migration: 006 - FTS5 Reflection Notes Column
3
+ * Description: Create new FTS5 table (memory_item_fts_new) with reflection_notes column for Zero-Downtime migration
4
+ * Version: 6.0
5
+ * Date: 2025-01-XX
6
+ *
7
+ * This migration implements Step 1 of the Zero-Downtime migration strategy:
8
+ * - Creates memory_item_fts_new table with reflection_notes column
9
+ * - Does NOT re-index existing data (handled in Step 2)
10
+ * - Does NOT create triggers (handled in Step 3)
11
+ * - Does NOT replace tables (handled in Step 4)
12
+ *
13
+ * See docs/architecture/zero-downtime-fts5-migration.md for full migration strategy.
14
+ */
15
+ import type Database from 'better-sqlite3';
16
+ import type { Migration } from '../types.js';
17
+ /**
18
+ * FTS5 Reflection Notes Migration (Step 1: New Table Creation)
19
+ *
20
+ * This migration:
21
+ * 1. Creates memory_item_fts_new virtual table with reflection_notes column
22
+ * 2. Validates table creation
23
+ * 3. Does NOT re-index existing data (handled separately)
24
+ * 4. Does NOT create triggers (handled separately)
25
+ */
26
+ export declare class FTS5ReflectionNotesMigration implements Migration {
27
+ version: string;
28
+ name: string;
29
+ description: string;
30
+ /**
31
+ * Load SQL file content
32
+ */
33
+ private loadSQLFile;
34
+ /**
35
+ * Execute SQL script
36
+ * Removes transaction commands (BEGIN TRANSACTION, COMMIT) as MigrationRunner manages transactions
37
+ */
38
+ private executeSQL;
39
+ /**
40
+ * Check if virtual table exists
41
+ */
42
+ private virtualTableExists;
43
+ /**
44
+ * Validate before migration
45
+ */
46
+ validateBefore(db: Database.Database): Promise<void>;
47
+ /**
48
+ * Re-index existing data from memory_item to memory_item_fts_new
49
+ *
50
+ * This implements Step 2 of the Zero-Downtime migration strategy:
51
+ * - Processes data in batches (1000 records per batch)
52
+ * - Normalizes reflection_notes using normalizeReflectionNotes utility
53
+ * - Commits each batch separately for performance and safety
54
+ * - Logs progress every 10%
55
+ */
56
+ private reindexExistingData;
57
+ /**
58
+ * Create temporary dual triggers for synchronizing new writes during migration
59
+ *
60
+ * This implements Step 3 of the Zero-Downtime migration strategy:
61
+ * - Creates temporary triggers that insert into memory_item_fts_new
62
+ * - Existing triggers continue to insert into memory_item_fts
63
+ * - Both tables are kept in sync during migration
64
+ *
65
+ * Duplicate Insert Prevention:
66
+ * - FTS5 automatically handles duplicate rowid inserts (updates existing record)
67
+ * - Triggers fire only once per INSERT/UPDATE/DELETE event, so duplicates are unlikely
68
+ * - Transaction-level duplicate prevention is handled at application level
69
+ *
70
+ * Note: reflection_notes normalization is applied using normalize_reflection_notes function.
71
+ */
72
+ private createDualTriggers;
73
+ /**
74
+ * Drop temporary dual triggers
75
+ * Used for rollback or cleanup
76
+ */
77
+ private dropDualTriggers;
78
+ /**
79
+ * Check if trigger exists
80
+ */
81
+ private triggerExists;
82
+ /**
83
+ * Register normalize_reflection_notes user-defined function
84
+ * This function must be registered before triggers that use it
85
+ */
86
+ private registerNormalizeFunction;
87
+ /**
88
+ * Perform atomic table replacement
89
+ *
90
+ * This implements Step 4 of the Zero-Downtime migration strategy:
91
+ * - Drops existing triggers
92
+ * - Drops temporary dual triggers
93
+ * - Drops existing FTS5 table
94
+ * - Renames new table to original name
95
+ * - Creates new triggers with reflection_notes support and normalization
96
+ *
97
+ * All operations are performed in a single transaction for atomicity.
98
+ */
99
+ private performAtomicTableReplacement;
100
+ /**
101
+ * Execute migration (Up)
102
+ */
103
+ up(db: Database.Database): Promise<void>;
104
+ /**
105
+ * Rollback migration (Down)
106
+ */
107
+ down(db: Database.Database): Promise<void>;
108
+ /**
109
+ * Validate after migration
110
+ */
111
+ validateAfter(db: Database.Database): Promise<void>;
112
+ }
113
+ //# sourceMappingURL=006-fts5-reflection-notes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"006-fts5-reflection-notes.d.ts","sourceRoot":"","sources":["../../../../src/database/migration/migrations/006-fts5-reflection-notes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAI3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAY7C;;;;;;;;GAQG;AACH,qBAAa,4BAA6B,YAAW,SAAS;IAC5D,OAAO,SAAS;IAChB,IAAI,SAA2B;IAC/B,WAAW,SAA0G;IAErH;;OAEG;IACH,OAAO,CAAC,WAAW;IAKnB;;;OAGG;IACH,OAAO,CAAC,UAAU;IAsBlB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;OAEG;IACG,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC1D;;;;;;;;OAQG;YACW,mBAAmB;IAgGjC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,kBAAkB;IAyC1B;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;OAEG;IACH,OAAO,CAAC,aAAa;IAQrB;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IASjC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,6BAA6B;IAqDrC;;OAEG;IACG,EAAE,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAwC9C;;OAEG;IACG,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBhD;;OAEG;IACG,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CA0E1D"}
@@ -0,0 +1,441 @@
1
+ /**
2
+ * Migration: 006 - FTS5 Reflection Notes Column
3
+ * Description: Create new FTS5 table (memory_item_fts_new) with reflection_notes column for Zero-Downtime migration
4
+ * Version: 6.0
5
+ * Date: 2025-01-XX
6
+ *
7
+ * This migration implements Step 1 of the Zero-Downtime migration strategy:
8
+ * - Creates memory_item_fts_new table with reflection_notes column
9
+ * - Does NOT re-index existing data (handled in Step 2)
10
+ * - Does NOT create triggers (handled in Step 3)
11
+ * - Does NOT replace tables (handled in Step 4)
12
+ *
13
+ * See docs/architecture/zero-downtime-fts5-migration.md for full migration strategy.
14
+ */
15
+ import { readFileSync } from 'fs';
16
+ import { join, dirname } from 'path';
17
+ import { fileURLToPath } from 'url';
18
+ import { DependencyValidator } from '../dependency-validator.js';
19
+ import { normalizeReflectionNotes } from '../../../utils/reflection-notes-normalize.js';
20
+ import { initializeMigrationStatusTable, setMigrationStatus, getMigrationStatus } from '../../../utils/fts5-migration-status.js';
21
+ const __filename = fileURLToPath(import.meta.url);
22
+ const __dirname = dirname(__filename);
23
+ /**
24
+ * FTS5 Reflection Notes Migration (Step 1: New Table Creation)
25
+ *
26
+ * This migration:
27
+ * 1. Creates memory_item_fts_new virtual table with reflection_notes column
28
+ * 2. Validates table creation
29
+ * 3. Does NOT re-index existing data (handled separately)
30
+ * 4. Does NOT create triggers (handled separately)
31
+ */
32
+ export class FTS5ReflectionNotesMigration {
33
+ version = '6.0';
34
+ name = 'fts5-reflection-notes';
35
+ description = 'Create new FTS5 table (memory_item_fts_new) with reflection_notes column for Zero-Downtime migration';
36
+ /**
37
+ * Load SQL file content
38
+ */
39
+ loadSQLFile(filename) {
40
+ const filePath = join(__dirname, filename);
41
+ return readFileSync(filePath, 'utf-8');
42
+ }
43
+ /**
44
+ * Execute SQL script
45
+ * Removes transaction commands (BEGIN TRANSACTION, COMMIT) as MigrationRunner manages transactions
46
+ */
47
+ executeSQL(db, sql) {
48
+ // MigrationRunner가 트랜잭션을 관리하므로 SQL에서 트랜잭션 명령 제거
49
+ let cleanedSQL = sql
50
+ // BEGIN TRANSACTION 제거
51
+ .replace(/BEGIN\s+TRANSACTION\s*;/gi, '')
52
+ // COMMIT 제거
53
+ .replace(/COMMIT\s*;/gi, '')
54
+ // PRAGMA foreign_keys 명령은 유지 (트랜잭션 외부에서도 작동)
55
+ .trim();
56
+ // 빈 줄 제거 및 정리
57
+ cleanedSQL = cleanedSQL
58
+ .split('\n')
59
+ .map(line => line.trim())
60
+ .filter(line => line.length > 0)
61
+ .join('\n');
62
+ if (cleanedSQL.length > 0) {
63
+ db.exec(cleanedSQL);
64
+ }
65
+ }
66
+ /**
67
+ * Check if virtual table exists
68
+ */
69
+ virtualTableExists(db, tableName) {
70
+ const result = db.prepare(`
71
+ SELECT name FROM sqlite_master
72
+ WHERE type='table' AND name=?
73
+ `).get(tableName);
74
+ return !!result;
75
+ }
76
+ /**
77
+ * Validate before migration
78
+ */
79
+ async validateBefore(db) {
80
+ // Check if memory_item table exists (required for content table reference)
81
+ const memoryItemExists = db.prepare(`
82
+ SELECT name FROM sqlite_master
83
+ WHERE type='table' AND name=?
84
+ `).get('memory_item');
85
+ if (!memoryItemExists) {
86
+ throw new Error('memory_item table does not exist. Cannot proceed with migration.');
87
+ }
88
+ // Check if migration has already been applied
89
+ if (this.virtualTableExists(db, 'memento_schema_version')) {
90
+ const version = db.prepare(`
91
+ SELECT version FROM memento_schema_version WHERE version = ?
92
+ `).get('6.0');
93
+ if (version) {
94
+ throw new Error('Migration 006 has already been applied. Current schema version: 6.0');
95
+ }
96
+ }
97
+ // Check if memory_item_fts_new table already exists (should not exist)
98
+ if (this.virtualTableExists(db, 'memory_item_fts_new')) {
99
+ throw new Error('memory_item_fts_new table already exists. Migration may have been partially applied.');
100
+ }
101
+ // Check if FTS5 is available
102
+ try {
103
+ db.exec('CREATE VIRTUAL TABLE IF NOT EXISTS test_fts5 USING fts5(content)');
104
+ db.exec('DROP TABLE IF EXISTS test_fts5');
105
+ }
106
+ catch (error) {
107
+ throw new Error('FTS5 is not available. Cannot proceed with migration.');
108
+ }
109
+ }
110
+ /**
111
+ * Re-index existing data from memory_item to memory_item_fts_new
112
+ *
113
+ * This implements Step 2 of the Zero-Downtime migration strategy:
114
+ * - Processes data in batches (1000 records per batch)
115
+ * - Normalizes reflection_notes using normalizeReflectionNotes utility
116
+ * - Commits each batch separately for performance and safety
117
+ * - Logs progress every 10%
118
+ */
119
+ async reindexExistingData(db) {
120
+ const BATCH_SIZE = 1000;
121
+ const BATCH_DELAY_MS = 10;
122
+ // Get total record count
123
+ const totalCount = db.prepare(`
124
+ SELECT COUNT(*) as count FROM memory_item
125
+ `).get();
126
+ const totalRecords = totalCount.count;
127
+ if (totalRecords === 0) {
128
+ // stderr로 로그 출력 (MCP 프로토콜 준수)
129
+ process.stderr.write('[Migration 006] No records to re-index\n');
130
+ return;
131
+ }
132
+ // stderr로 로그 출력 (MCP 프로토콜 준수)
133
+ process.stderr.write(`[Migration 006] Starting re-indexing: ${totalRecords} records\n`);
134
+ let processedCount = 0;
135
+ let offset = 0;
136
+ let lastLoggedPercent = -1;
137
+ // Prepare statements
138
+ const selectStmt = db.prepare(`
139
+ SELECT rowid, content, tags, source, reflection_notes
140
+ FROM memory_item
141
+ ORDER BY rowid
142
+ LIMIT ? OFFSET ?
143
+ `);
144
+ const insertStmt = db.prepare(`
145
+ INSERT INTO memory_item_fts_new(rowid, content, tags, source, reflection_notes)
146
+ VALUES (?, ?, ?, ?, ?)
147
+ `);
148
+ // Process in batches
149
+ // Note: MigrationRunner가 이미 트랜잭션을 관리하므로 중첩 트랜잭션을 사용하지 않음
150
+ // 모든 배치 처리는 MigrationRunner의 단일 트랜잭션 내에서 실행됨
151
+ while (offset < totalRecords) {
152
+ try {
153
+ // Fetch batch
154
+ const batch = selectStmt.all(BATCH_SIZE, offset);
155
+ if (batch.length === 0) {
156
+ break;
157
+ }
158
+ // Insert each record with normalized reflection_notes
159
+ for (const record of batch) {
160
+ // Normalize reflection_notes for FTS5 indexing
161
+ const normalizedReflectionNotes = normalizeReflectionNotes(record.reflection_notes);
162
+ insertStmt.run(record.rowid, record.content, record.tags, record.source, normalizedReflectionNotes || null // Empty string becomes null
163
+ );
164
+ }
165
+ processedCount += batch.length;
166
+ offset += BATCH_SIZE;
167
+ // Log progress every 10%
168
+ const currentPercent = Math.floor((processedCount / totalRecords) * 100);
169
+ if (currentPercent >= lastLoggedPercent + 10 || processedCount === totalRecords) {
170
+ // stderr로 로그 출력 (MCP 프로토콜 준수)
171
+ process.stderr.write(`[Migration 006] Re-indexing progress: ${processedCount}/${totalRecords} (${currentPercent}%)\n`);
172
+ lastLoggedPercent = currentPercent;
173
+ }
174
+ // Delay between batches to minimize impact on other operations
175
+ if (offset < totalRecords) {
176
+ await new Promise(resolve => setTimeout(resolve, BATCH_DELAY_MS));
177
+ }
178
+ }
179
+ catch (error) {
180
+ // MigrationRunner가 트랜잭션을 관리하므로 여기서는 에러만 전파
181
+ throw new Error(`Re-indexing failed at batch starting at offset ${offset}: ${error instanceof Error ? error.message : String(error)}`);
182
+ }
183
+ }
184
+ // stderr로 로그 출력 (MCP 프로토콜 준수)
185
+ process.stderr.write(`[Migration 006] Re-indexing completed: ${processedCount} records\n`);
186
+ }
187
+ /**
188
+ * Create temporary dual triggers for synchronizing new writes during migration
189
+ *
190
+ * This implements Step 3 of the Zero-Downtime migration strategy:
191
+ * - Creates temporary triggers that insert into memory_item_fts_new
192
+ * - Existing triggers continue to insert into memory_item_fts
193
+ * - Both tables are kept in sync during migration
194
+ *
195
+ * Duplicate Insert Prevention:
196
+ * - FTS5 automatically handles duplicate rowid inserts (updates existing record)
197
+ * - Triggers fire only once per INSERT/UPDATE/DELETE event, so duplicates are unlikely
198
+ * - Transaction-level duplicate prevention is handled at application level
199
+ *
200
+ * Note: reflection_notes normalization is applied using normalize_reflection_notes function.
201
+ */
202
+ createDualTriggers(db) {
203
+ // stderr로 로그 출력 (MCP 프로토콜 준수)
204
+ process.stderr.write('[Migration 006] Creating temporary dual triggers...\n');
205
+ // Register normalize_reflection_notes function before creating triggers
206
+ this.registerNormalizeFunction(db);
207
+ // INSERT trigger: Insert new records into memory_item_fts_new with normalization
208
+ // FTS5 automatically handles duplicate rowid: if rowid exists, it updates the record
209
+ db.exec(`
210
+ CREATE TRIGGER IF NOT EXISTS memory_item_fts_insert_new AFTER INSERT ON memory_item BEGIN
211
+ INSERT INTO memory_item_fts_new(rowid, content, tags, source, reflection_notes)
212
+ VALUES (new.rowid, new.content, new.tags, new.source, normalize_reflection_notes(new.reflection_notes));
213
+ END
214
+ `);
215
+ // UPDATE trigger: Update records in memory_item_fts_new with normalization
216
+ // Delete old record first, then insert new record
217
+ db.exec(`
218
+ CREATE TRIGGER IF NOT EXISTS memory_item_fts_update_new AFTER UPDATE ON memory_item BEGIN
219
+ -- Delete old record
220
+ INSERT INTO memory_item_fts_new(memory_item_fts_new, rowid, content, tags, source, reflection_notes)
221
+ VALUES('delete', old.rowid, old.content, old.tags, old.source, normalize_reflection_notes(old.reflection_notes));
222
+ -- Insert new record
223
+ INSERT INTO memory_item_fts_new(rowid, content, tags, source, reflection_notes)
224
+ VALUES (new.rowid, new.content, new.tags, new.source, normalize_reflection_notes(new.reflection_notes));
225
+ END
226
+ `);
227
+ // DELETE trigger: Delete records from memory_item_fts_new with normalization
228
+ db.exec(`
229
+ CREATE TRIGGER IF NOT EXISTS memory_item_fts_delete_new AFTER DELETE ON memory_item BEGIN
230
+ INSERT INTO memory_item_fts_new(memory_item_fts_new, rowid, content, tags, source, reflection_notes)
231
+ VALUES('delete', old.rowid, old.content, old.tags, old.source, normalize_reflection_notes(old.reflection_notes));
232
+ END
233
+ `);
234
+ // stderr로 로그 출력 (MCP 프로토콜 준수)
235
+ process.stderr.write('[Migration 006] Temporary dual triggers created\n');
236
+ }
237
+ /**
238
+ * Drop temporary dual triggers
239
+ * Used for rollback or cleanup
240
+ */
241
+ dropDualTriggers(db) {
242
+ db.exec('DROP TRIGGER IF EXISTS memory_item_fts_insert_new');
243
+ db.exec('DROP TRIGGER IF EXISTS memory_item_fts_update_new');
244
+ db.exec('DROP TRIGGER IF EXISTS memory_item_fts_delete_new');
245
+ }
246
+ /**
247
+ * Check if trigger exists
248
+ */
249
+ triggerExists(db, triggerName) {
250
+ const result = db.prepare(`
251
+ SELECT name FROM sqlite_master
252
+ WHERE type='trigger' AND name=?
253
+ `).get(triggerName);
254
+ return !!result;
255
+ }
256
+ /**
257
+ * Register normalize_reflection_notes user-defined function
258
+ * This function must be registered before triggers that use it
259
+ */
260
+ registerNormalizeFunction(db) {
261
+ db.function('normalize_reflection_notes', {
262
+ deterministic: true,
263
+ varargs: false
264
+ }, (reflectionNotes) => {
265
+ return normalizeReflectionNotes(reflectionNotes);
266
+ });
267
+ }
268
+ /**
269
+ * Perform atomic table replacement
270
+ *
271
+ * This implements Step 4 of the Zero-Downtime migration strategy:
272
+ * - Drops existing triggers
273
+ * - Drops temporary dual triggers
274
+ * - Drops existing FTS5 table
275
+ * - Renames new table to original name
276
+ * - Creates new triggers with reflection_notes support and normalization
277
+ *
278
+ * All operations are performed in a single transaction for atomicity.
279
+ */
280
+ performAtomicTableReplacement(db) {
281
+ // stderr로 로그 출력 (MCP 프로토콜 준수)
282
+ process.stderr.write('[Migration 006] Performing atomic table replacement...\n');
283
+ // Register normalize_reflection_notes function before creating triggers
284
+ this.registerNormalizeFunction(db);
285
+ // MigrationRunner가 트랜잭션을 관리하므로 여기서는 트랜잭션을 시작하지 않음
286
+ // All operations are performed within the existing transaction managed by MigrationRunner
287
+ // 1. Drop existing triggers
288
+ db.exec('DROP TRIGGER IF EXISTS memory_item_fts_insert');
289
+ db.exec('DROP TRIGGER IF EXISTS memory_item_fts_update');
290
+ db.exec('DROP TRIGGER IF EXISTS memory_item_fts_delete');
291
+ // 2. Drop temporary dual triggers
292
+ this.dropDualTriggers(db);
293
+ // 3. Drop existing FTS5 table
294
+ db.exec('DROP TABLE IF EXISTS memory_item_fts');
295
+ // 4. Rename new table to original name
296
+ db.exec('ALTER TABLE memory_item_fts_new RENAME TO memory_item_fts');
297
+ // 5. Create new triggers with reflection_notes support and normalization
298
+ // Note: normalize_reflection_notes function must be registered before this migration
299
+ db.exec(`
300
+ CREATE TRIGGER memory_item_fts_insert AFTER INSERT ON memory_item BEGIN
301
+ INSERT INTO memory_item_fts(rowid, content, tags, source, reflection_notes)
302
+ VALUES (new.rowid, new.content, new.tags, new.source, normalize_reflection_notes(new.reflection_notes));
303
+ END
304
+ `);
305
+ db.exec(`
306
+ CREATE TRIGGER memory_item_fts_update AFTER UPDATE ON memory_item BEGIN
307
+ INSERT INTO memory_item_fts(memory_item_fts, rowid, content, tags, source, reflection_notes)
308
+ VALUES('delete', old.rowid, old.content, old.tags, old.source, normalize_reflection_notes(old.reflection_notes));
309
+ INSERT INTO memory_item_fts(rowid, content, tags, source, reflection_notes)
310
+ VALUES (new.rowid, new.content, new.tags, new.source, normalize_reflection_notes(new.reflection_notes));
311
+ END
312
+ `);
313
+ db.exec(`
314
+ CREATE TRIGGER memory_item_fts_delete AFTER DELETE ON memory_item BEGIN
315
+ INSERT INTO memory_item_fts(memory_item_fts, rowid, content, tags, source, reflection_notes)
316
+ VALUES('delete', old.rowid, old.content, old.tags, old.source, normalize_reflection_notes(old.reflection_notes));
317
+ END
318
+ `);
319
+ // stderr로 로그 출력 (MCP 프로토콜 준수)
320
+ process.stderr.write('[Migration 006] Atomic table replacement completed\n');
321
+ }
322
+ /**
323
+ * Execute migration (Up)
324
+ */
325
+ async up(db) {
326
+ // Initialize migration status table
327
+ initializeMigrationStatusTable(db);
328
+ // Update status to 'in_progress'
329
+ setMigrationStatus(db, 'in_progress');
330
+ try {
331
+ // Step 1: Load and execute SQL script (create new table)
332
+ const sqlScript = this.loadSQLFile('006-fts5-reflection-notes.sql');
333
+ this.executeSQL(db, sqlScript);
334
+ // Step 2: Re-index existing data
335
+ await this.reindexExistingData(db);
336
+ // Step 3: Create temporary dual triggers
337
+ this.createDualTriggers(db);
338
+ // Step 4: Perform atomic table replacement
339
+ this.performAtomicTableReplacement(db);
340
+ // Update status to 'completed'
341
+ setMigrationStatus(db, 'completed');
342
+ // Note: Schema version is recorded by MigrationRunner, not here
343
+ // MigrationRunner.recordVersion() will be called after successful migration
344
+ //
345
+ // Note: This migration implements Steps 1, 2, 3, and 4 of the Zero-Downtime migration strategy.
346
+ // Trigger update with reflection_notes normalization (Step 3.8) is handled separately.
347
+ }
348
+ catch (error) {
349
+ // Update status to 'failed' on error
350
+ setMigrationStatus(db, 'failed', error instanceof Error ? error.message : String(error));
351
+ throw error; // Re-throw to trigger rollback
352
+ }
353
+ }
354
+ /**
355
+ * Rollback migration (Down)
356
+ */
357
+ async down(db) {
358
+ // Drop temporary dual triggers
359
+ this.dropDualTriggers(db);
360
+ // Drop the new FTS5 table
361
+ db.exec('DROP TABLE IF EXISTS memory_item_fts_new');
362
+ // Update status to 'pending' (재시도 가능하도록)
363
+ try {
364
+ setMigrationStatus(db, 'pending');
365
+ }
366
+ catch (error) {
367
+ // 상태 업데이트 실패는 무시 (롤백은 계속 진행)
368
+ // stderr로 로그 출력 (MCP 프로토콜 준수)
369
+ process.stderr.write(`⚠️ 마이그레이션 상태 롤백 실패: ${error instanceof Error ? error.message : String(error)}\n`);
370
+ }
371
+ // Remove schema version record
372
+ db.prepare('DELETE FROM memento_schema_version WHERE version = ?').run('6.0');
373
+ }
374
+ /**
375
+ * Validate after migration
376
+ */
377
+ async validateAfter(db) {
378
+ // After atomic table replacement, memory_item_fts_new should not exist
379
+ // and memory_item_fts should exist with reflection_notes column
380
+ // Verify memory_item_fts table exists (renamed from memory_item_fts_new)
381
+ if (!this.virtualTableExists(db, 'memory_item_fts')) {
382
+ throw new Error('memory_item_fts table was not created or renamed');
383
+ }
384
+ // Verify memory_item_fts_new table does not exist (should be renamed)
385
+ if (this.virtualTableExists(db, 'memory_item_fts_new')) {
386
+ throw new Error('memory_item_fts_new table still exists (should be renamed to memory_item_fts)');
387
+ }
388
+ // Verify table structure by checking if it's a virtual table
389
+ const tableInfo = db.prepare(`
390
+ SELECT sql FROM sqlite_master
391
+ WHERE type='table' AND name='memory_item_fts'
392
+ `).get();
393
+ if (!tableInfo) {
394
+ throw new Error('memory_item_fts table information not found');
395
+ }
396
+ // Verify reflection_notes column is included in the table definition
397
+ if (!tableInfo.sql.includes('reflection_notes')) {
398
+ throw new Error('reflection_notes column was not included in memory_item_fts table');
399
+ }
400
+ // Verify content table reference
401
+ if (!tableInfo.sql.includes("content='memory_item'")) {
402
+ throw new Error("content table reference 'memory_item' was not found in memory_item_fts table");
403
+ }
404
+ // Verify content_rowid reference
405
+ if (!tableInfo.sql.includes("content_rowid='rowid'")) {
406
+ throw new Error("content_rowid='rowid' was not found in memory_item_fts table");
407
+ }
408
+ // Verify new triggers were created (temporary dual triggers should be removed)
409
+ const requiredTriggers = [
410
+ 'memory_item_fts_insert',
411
+ 'memory_item_fts_update',
412
+ 'memory_item_fts_delete'
413
+ ];
414
+ for (const triggerName of requiredTriggers) {
415
+ if (!this.triggerExists(db, triggerName)) {
416
+ throw new Error(`New trigger ${triggerName} was not created`);
417
+ }
418
+ }
419
+ // Verify temporary dual triggers were removed
420
+ const temporaryTriggers = [
421
+ 'memory_item_fts_insert_new',
422
+ 'memory_item_fts_update_new',
423
+ 'memory_item_fts_delete_new'
424
+ ];
425
+ for (const triggerName of temporaryTriggers) {
426
+ if (this.triggerExists(db, triggerName)) {
427
+ throw new Error(`Temporary dual trigger ${triggerName} still exists (should be removed)`);
428
+ }
429
+ }
430
+ // Verify existing dependencies are intact using DependencyValidator
431
+ const dependencyReport = await DependencyValidator.validateAll(db);
432
+ if (!dependencyReport.success) {
433
+ const errors = dependencyReport.results
434
+ .filter(r => !r.success)
435
+ .map(r => `${r.name}: ${r.error}`)
436
+ .join('; ');
437
+ throw new Error(`Dependency validation failed: ${errors}`);
438
+ }
439
+ }
440
+ }
441
+ //# sourceMappingURL=006-fts5-reflection-notes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"006-fts5-reflection-notes.js","sourceRoot":"","sources":["../../../../src/database/migration/migrations/006-fts5-reflection-notes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ -- Migration: 006 - FTS5 Reflection Notes Column
2
+ -- Description: Create new FTS5 table (memory_item_fts_new) with reflection_notes column for Zero-Downtime migration
3
+ -- Version: 6.0
4
+ -- Date: 2025-01-XX
5
+ --
6
+ -- This is Step 1 of the Zero-Downtime migration strategy:
7
+ -- 1. Create new FTS5 table with reflection_notes column
8
+ -- 2. Re-index existing data (Step 2, handled separately)
9
+ -- 3. Create temporary dual triggers (Step 3, handled separately)
10
+ -- 4. Atomic table replacement (Step 4, handled separately)
11
+ -- 5. Activate new triggers (Step 5, handled separately)
12
+
13
+ -- Create new FTS5 virtual table with reflection_notes column
14
+ CREATE VIRTUAL TABLE IF NOT EXISTS memory_item_fts_new USING fts5(
15
+ content,
16
+ tags,
17
+ source,
18
+ reflection_notes, -- New column for reflection notes search
19
+ content='memory_item',
20
+ content_rowid='rowid'
21
+ );
22
+
23
+ -- Note: This migration only creates the new table.
24
+ -- Data re-indexing, trigger creation, and table replacement are handled in subsequent steps
25
+ -- to ensure Zero-Downtime migration.
26
+
@@ -98,26 +98,28 @@ CREATE VIRTUAL TABLE IF NOT EXISTS memory_item_fts USING fts5(
98
98
  content,
99
99
  tags,
100
100
  source,
101
+ reflection_notes,
101
102
  content='memory_item',
102
103
  content_rowid='rowid'
103
104
  );
104
105
 
105
- -- FTS5 트리거 (자동 동기화)
106
+ -- FTS5 트리거 (자동 동기화, reflection_notes 정규화 포함)
107
+ -- Note: normalize_reflection_notes 함수는 데이터베이스 초기화 시 등록되어야 함
106
108
  CREATE TRIGGER IF NOT EXISTS memory_item_fts_insert AFTER INSERT ON memory_item BEGIN
107
- INSERT INTO memory_item_fts(rowid, content, tags, source)
108
- VALUES (new.rowid, new.content, new.tags, new.source);
109
+ INSERT INTO memory_item_fts(rowid, content, tags, source, reflection_notes)
110
+ VALUES (new.rowid, new.content, new.tags, new.source, normalize_reflection_notes(new.reflection_notes));
109
111
  END;
110
112
 
111
113
  CREATE TRIGGER IF NOT EXISTS memory_item_fts_delete AFTER DELETE ON memory_item BEGIN
112
- INSERT INTO memory_item_fts(memory_item_fts, rowid, content, tags, source)
113
- VALUES('delete', old.rowid, old.content, old.tags, old.source);
114
+ INSERT INTO memory_item_fts(memory_item_fts, rowid, content, tags, source, reflection_notes)
115
+ VALUES('delete', old.rowid, old.content, old.tags, old.source, normalize_reflection_notes(old.reflection_notes));
114
116
  END;
115
117
 
116
118
  CREATE TRIGGER IF NOT EXISTS memory_item_fts_update AFTER UPDATE ON memory_item BEGIN
117
- INSERT INTO memory_item_fts(memory_item_fts, rowid, content, tags, source)
118
- VALUES('delete', old.rowid, old.content, old.tags, old.source);
119
- INSERT INTO memory_item_fts(rowid, content, tags, source)
120
- VALUES (new.rowid, new.content, new.tags, new.source);
119
+ INSERT INTO memory_item_fts(memory_item_fts, rowid, content, tags, source, reflection_notes)
120
+ VALUES('delete', old.rowid, old.content, old.tags, old.source, normalize_reflection_notes(old.reflection_notes));
121
+ INSERT INTO memory_item_fts(rowid, content, tags, source, reflection_notes)
122
+ VALUES (new.rowid, new.content, new.tags, new.source, normalize_reflection_notes(new.reflection_notes));
121
123
  END;
122
124
 
123
125
  -- 임베딩 저장 테이블 (다중 제공자/차원 지원)
@@ -14,6 +14,8 @@ import { PerformanceAlertService } from '../services/performance-alert-service.j
14
14
  import { ConsolidationScoreService } from '../services/consolidation-score-service.js';
15
15
  import { WriteCoalescingManager } from '../utils/write-coalescing.js';
16
16
  import { AnchorManager } from '../services/anchor-manager.js';
17
+ import { FailureDetector } from '../services/failure-detector.js';
18
+ import { ReflexionWorker } from '../services/reflexion-worker.js';
17
19
  /**
18
20
  * 서버 서비스 집합 인터페이스
19
21
  *
@@ -43,6 +45,8 @@ export interface ServerServices {
43
45
  consolidationScoreService?: ConsolidationScoreService;
44
46
  writeCoalescingManager?: WriteCoalescingManager;
45
47
  anchorManager: AnchorManager;
48
+ failureDetector: FailureDetector;
49
+ reflexionWorker?: ReflexionWorker;
46
50
  }
47
51
  /**
48
52
  * 모든 서비스를 초기화하는 공용 부트스트랩 함수