memento-mcp-server 1.16.0 → 1.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Procedural Memory 변경 감지 유틸리티
3
+ *
4
+ * 이 유틸리티는 Procedural Memory의 변경 사항을 감지하고 분류합니다.
5
+ * PRD FR4: 판정 기준 구현을 위한 유틸리티 함수 제공
6
+ *
7
+ * 주요 기능:
8
+ * - Procedural Memory 스냅샷 생성
9
+ * - 변경 타입 분류 (version_created, steps_modified, metadata_modified, content_modified, reflection_added, deleted, none)
10
+ * - JSON 정규화 및 해시 계산
11
+ */
12
+ import Database from 'better-sqlite3';
13
+ /**
14
+ * Procedural Memory 스냅샷 인터페이스
15
+ *
16
+ * 변경 감지를 위해 필요한 모든 필드를 포함합니다.
17
+ * memory_item 테이블과 memory_link 테이블의 version_of 관계를 조합하여 생성됩니다.
18
+ */
19
+ export interface ProceduralMemorySnapshot {
20
+ /** 메모리 ID */
21
+ id: string | null;
22
+ /** 메모리 내용 */
23
+ content: string | null;
24
+ /** 중요도 (0-1) */
25
+ importance: number | null;
26
+ /** 프라이버시 범위 */
27
+ privacy_scope: string | null;
28
+ /** 프로세스 이름 */
29
+ workflow_name: string | null;
30
+ /** 기술/능력 이름 */
31
+ skill_name: string | null;
32
+ /** steps JSON 배열의 해시값 */
33
+ steps_hash: string | null;
34
+ /** trigger_conditions JSON 객체의 해시값 */
35
+ trigger_conditions_hash: string | null;
36
+ /** 작업 목표 */
37
+ task_goal: string | null;
38
+ /** reflection_notes 배열의 길이 (JSON 파싱 후) */
39
+ reflection_notes_count: number | null;
40
+ /** 편집 횟수 */
41
+ edit_count: number | null;
42
+ /** version_of 관계의 target_id (memory_link에서 조회) */
43
+ version_of_target_id: string | null;
44
+ }
45
+ /**
46
+ * 변경 타입 열거형
47
+ *
48
+ * PRD FR4 기반 판정 기준:
49
+ * - version_created: versioned 모드로 새 버전 생성
50
+ * - steps_modified: steps JSON 배열 변경
51
+ * - metadata_modified: workflow_name, skill_name, trigger_conditions_hash, task_goal, edit_count 변경
52
+ * - content_modified: content 필드 변경
53
+ * - reflection_added: reflection_notes 배열 길이 증가
54
+ * - deleted: 메모리 삭제
55
+ * - none: 변경 없음
56
+ */
57
+ export type ChangeType = 'version_created' | 'steps_modified' | 'metadata_modified' | 'content_modified' | 'reflection_added' | 'deleted' | 'none';
58
+ /**
59
+ * 변경 감지 결과 인터페이스
60
+ *
61
+ * 변경 여부와 변경 타입, 상세 변경 내역을 포함합니다.
62
+ */
63
+ export interface ChangeDetectionResult {
64
+ /** 변경 여부 */
65
+ hasChanged: boolean;
66
+ /** 변경 타입 */
67
+ changeType: ChangeType;
68
+ /** 변경된 필드 목록 (디버깅 및 로깅용) */
69
+ changedFields: string[];
70
+ /** 변경 전 스냅샷 */
71
+ before: ProceduralMemorySnapshot | null;
72
+ /** 변경 후 스냅샷 */
73
+ after: ProceduralMemorySnapshot | null;
74
+ }
75
+ /**
76
+ * JSON 정규화 유틸리티 함수
77
+ *
78
+ * 해시 계산을 위해 일관된 JSON 문자열을 생성합니다.
79
+ *
80
+ * 정규화 규칙:
81
+ * - 객체의 키를 알파벳 순서로 정렬
82
+ * - 숫자는 일관된 형식으로 직렬화 (JSON.stringify의 기본 동작 사용)
83
+ * - 배열의 순서는 유지 (배열은 순서가 중요하므로 정렬하지 않음)
84
+ * - null 값은 "null" 문자열로 처리
85
+ * - undefined는 제외 (객체에서 undefined 필드는 제외됨)
86
+ *
87
+ * @param value - 정규화할 값 (객체, 배열, 원시 타입)
88
+ * @returns 정규화된 JSON 문자열
89
+ */
90
+ export declare function normalizeJson(value: unknown): string;
91
+ /**
92
+ * JSON 문자열의 SHA-256 해시 계산
93
+ *
94
+ * 해시 계산 전에 JSON을 정규화하여 일관된 해시값을 생성합니다.
95
+ *
96
+ * 처리 규칙:
97
+ * - `jsonString === null`: `"null"` 문자열을 해시 (SHA-256 hash of `"null"`)
98
+ * - `jsonString === ""` (빈 문자열): 빈 문자열을 해시 (SHA-256 hash of `""`)
99
+ * - `jsonString === "null"` (문자열 "null"): JSON 파싱 시도 → `null`로 파싱되면 정규화 후 해시, 실패 시 원문 해시
100
+ * - 일반 JSON 문자열: JSON 파싱 → 정규화 → 해시
101
+ * - 파싱 실패 시: 원문 문자열을 해시 (fallback)
102
+ *
103
+ * **일관성**: null 입력과 "null" 문자열 입력은 다른 해시값을 반환
104
+ * - null → "null" 문자열 해시
105
+ * - "null" → JSON 파싱 후 정규화된 해시
106
+ *
107
+ * @param jsonString - 해시할 JSON 문자열 (또는 null)
108
+ * @returns SHA-256 해시값 (hex 문자열)
109
+ */
110
+ export declare function computeJsonHash(jsonString: string | null): string;
111
+ /**
112
+ * Procedural Memory 스냅샷 생성
113
+ *
114
+ * memory_item 테이블에서 메모리를 조회하고, memory_link 테이블에서 version_of 관계를 조회하여
115
+ * 변경 감지에 필요한 모든 정보를 포함한 스냅샷을 생성합니다.
116
+ *
117
+ * @param db - 데이터베이스 인스턴스
118
+ * @param memoryId - 메모리 ID
119
+ * @returns ProceduralMemorySnapshot 또는 null (메모리가 없거나 procedural 타입이 아닌 경우)
120
+ */
121
+ export declare function createProceduralMemorySnapshot(db: Database.Database, memoryId: string): ProceduralMemorySnapshot | null;
122
+ /**
123
+ * Procedural Memory 변경 감지
124
+ *
125
+ * PRD FR4 기반 판정 기준에 따라 변경 여부와 변경 타입을 판정합니다.
126
+ *
127
+ * 판정 우선순위:
128
+ * 1. 경계값 처리 (null 체크)
129
+ * 2. version_created
130
+ * 3. steps_modified
131
+ * 4. metadata_modified
132
+ * 5. content_modified
133
+ * 6. reflection_added
134
+ * 7. deleted (경계값 처리에서 이미 처리됨)
135
+ * 8. none
136
+ *
137
+ * @param before - 변경 전 스냅샷 (또는 null)
138
+ * @param after - 변경 후 스냅샷 (또는 null)
139
+ * @returns 변경 감지 결과
140
+ */
141
+ export declare function hasProceduralMemoryChanged(before: ProceduralMemorySnapshot | null, after: ProceduralMemorySnapshot | null): ChangeDetectionResult;
142
+ //# sourceMappingURL=procedural-memory-change-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"procedural-memory-change-detector.d.ts","sourceRoot":"","sources":["../../../src/shared/utils/procedural-memory-change-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAGtC;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,aAAa;IACb,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,aAAa;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,gBAAgB;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe;IACf,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc;IACd,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,yBAAyB;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,sCAAsC;IACtC,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,YAAY;IACZ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,0CAA0C;IAC1C,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,YAAY;IACZ,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,kDAAkD;IAClD,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,GAClB,iBAAiB,GACjB,gBAAgB,GAChB,mBAAmB,GACnB,kBAAkB,GAClB,kBAAkB,GAClB,SAAS,GACT,MAAM,CAAC;AAEX;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,YAAY;IACZ,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY;IACZ,UAAU,EAAE,UAAU,CAAC;IACvB,4BAA4B;IAC5B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe;IACf,MAAM,EAAE,wBAAwB,GAAG,IAAI,CAAC;IACxC,eAAe;IACf,KAAK,EAAE,wBAAwB,GAAG,IAAI,CAAC;CACxC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CA2CpD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CA6CjE;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAC5C,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,QAAQ,EAAE,MAAM,GACf,wBAAwB,GAAG,IAAI,CA+DjC;AAkBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,wBAAwB,GAAG,IAAI,EACvC,KAAK,EAAE,wBAAwB,GAAG,IAAI,GACrC,qBAAqB,CAkLvB"}
@@ -0,0 +1,401 @@
1
+ /**
2
+ * Procedural Memory 변경 감지 유틸리티
3
+ *
4
+ * 이 유틸리티는 Procedural Memory의 변경 사항을 감지하고 분류합니다.
5
+ * PRD FR4: 판정 기준 구현을 위한 유틸리티 함수 제공
6
+ *
7
+ * 주요 기능:
8
+ * - Procedural Memory 스냅샷 생성
9
+ * - 변경 타입 분류 (version_created, steps_modified, metadata_modified, content_modified, reflection_added, deleted, none)
10
+ * - JSON 정규화 및 해시 계산
11
+ */
12
+ import { createHash } from 'crypto';
13
+ import Database from 'better-sqlite3';
14
+ import { DatabaseUtils } from './database.js';
15
+ /**
16
+ * JSON 정규화 유틸리티 함수
17
+ *
18
+ * 해시 계산을 위해 일관된 JSON 문자열을 생성합니다.
19
+ *
20
+ * 정규화 규칙:
21
+ * - 객체의 키를 알파벳 순서로 정렬
22
+ * - 숫자는 일관된 형식으로 직렬화 (JSON.stringify의 기본 동작 사용)
23
+ * - 배열의 순서는 유지 (배열은 순서가 중요하므로 정렬하지 않음)
24
+ * - null 값은 "null" 문자열로 처리
25
+ * - undefined는 제외 (객체에서 undefined 필드는 제외됨)
26
+ *
27
+ * @param value - 정규화할 값 (객체, 배열, 원시 타입)
28
+ * @returns 정규화된 JSON 문자열
29
+ */
30
+ export function normalizeJson(value) {
31
+ // null 처리
32
+ if (value === null) {
33
+ return 'null';
34
+ }
35
+ // undefined 처리 (null로 변환)
36
+ if (value === undefined) {
37
+ return 'null';
38
+ }
39
+ // 원시 타입 처리 (JSON.stringify 사용)
40
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
41
+ return JSON.stringify(value);
42
+ }
43
+ // 배열 처리 (순서 유지, 재귀적으로 정규화)
44
+ if (Array.isArray(value)) {
45
+ const normalizedItems = value.map(item => normalizeJson(item));
46
+ return `[${normalizedItems.join(',')}]`;
47
+ }
48
+ // 객체 처리 (키 정렬, 재귀적으로 정규화)
49
+ if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
50
+ const obj = value;
51
+ const sortedKeys = Object.keys(obj).sort();
52
+ const normalizedPairs = [];
53
+ for (const key of sortedKeys) {
54
+ const val = obj[key];
55
+ // undefined 필드는 제외 (일관된 해시를 위해)
56
+ if (val !== undefined) {
57
+ const normalizedValue = normalizeJson(val);
58
+ // 키와 값을 JSON 형식으로 직렬화
59
+ normalizedPairs.push(`${JSON.stringify(key)}:${normalizedValue}`);
60
+ }
61
+ }
62
+ return `{${normalizedPairs.join(',')}}`;
63
+ }
64
+ // 예상치 못한 타입은 null로 처리
65
+ return 'null';
66
+ }
67
+ /**
68
+ * JSON 문자열의 SHA-256 해시 계산
69
+ *
70
+ * 해시 계산 전에 JSON을 정규화하여 일관된 해시값을 생성합니다.
71
+ *
72
+ * 처리 규칙:
73
+ * - `jsonString === null`: `"null"` 문자열을 해시 (SHA-256 hash of `"null"`)
74
+ * - `jsonString === ""` (빈 문자열): 빈 문자열을 해시 (SHA-256 hash of `""`)
75
+ * - `jsonString === "null"` (문자열 "null"): JSON 파싱 시도 → `null`로 파싱되면 정규화 후 해시, 실패 시 원문 해시
76
+ * - 일반 JSON 문자열: JSON 파싱 → 정규화 → 해시
77
+ * - 파싱 실패 시: 원문 문자열을 해시 (fallback)
78
+ *
79
+ * **일관성**: null 입력과 "null" 문자열 입력은 다른 해시값을 반환
80
+ * - null → "null" 문자열 해시
81
+ * - "null" → JSON 파싱 후 정규화된 해시
82
+ *
83
+ * @param jsonString - 해시할 JSON 문자열 (또는 null)
84
+ * @returns SHA-256 해시값 (hex 문자열)
85
+ */
86
+ export function computeJsonHash(jsonString) {
87
+ // null 처리: "null" 문자열을 해시
88
+ if (jsonString === null) {
89
+ const hash = createHash('sha256');
90
+ hash.update('null');
91
+ return hash.digest('hex');
92
+ }
93
+ // 빈 문자열 처리: 빈 문자열을 해시
94
+ if (jsonString === '') {
95
+ const hash = createHash('sha256');
96
+ hash.update('');
97
+ return hash.digest('hex');
98
+ }
99
+ // 문자열 "null" 처리: JSON 파싱 시도
100
+ if (jsonString === 'null') {
101
+ try {
102
+ const parsed = JSON.parse(jsonString);
103
+ // null로 파싱되면 정규화 후 해시
104
+ const normalized = normalizeJson(parsed);
105
+ const hash = createHash('sha256');
106
+ hash.update(normalized);
107
+ return hash.digest('hex');
108
+ }
109
+ catch {
110
+ // 파싱 실패 시 원문 해시 (fallback)
111
+ const hash = createHash('sha256');
112
+ hash.update(jsonString);
113
+ return hash.digest('hex');
114
+ }
115
+ }
116
+ // 일반 JSON 문자열 처리: JSON 파싱 → 정규화 → 해시
117
+ try {
118
+ const parsed = JSON.parse(jsonString);
119
+ const normalized = normalizeJson(parsed);
120
+ const hash = createHash('sha256');
121
+ hash.update(normalized);
122
+ return hash.digest('hex');
123
+ }
124
+ catch {
125
+ // 파싱 실패 시 원문 문자열을 해시 (fallback)
126
+ const hash = createHash('sha256');
127
+ hash.update(jsonString);
128
+ return hash.digest('hex');
129
+ }
130
+ }
131
+ /**
132
+ * reflection_notes JSON 문자열의 배열 길이 계산
133
+ *
134
+ * @param reflectionNotes - reflection_notes JSON 문자열 (또는 null)
135
+ * @returns 배열 길이 (파싱 실패 시 null)
136
+ */
137
+ function computeReflectionNotesCount(reflectionNotes) {
138
+ if (reflectionNotes === null || reflectionNotes === '') {
139
+ return null;
140
+ }
141
+ try {
142
+ const parsed = JSON.parse(reflectionNotes);
143
+ // 배열인 경우 길이 반환
144
+ if (Array.isArray(parsed)) {
145
+ return parsed.length;
146
+ }
147
+ // 단일 객체인 경우 1 반환 (Phase 1 호환성)
148
+ if (typeof parsed === 'object' && parsed !== null) {
149
+ return 1;
150
+ }
151
+ // 예상치 못한 타입
152
+ return null;
153
+ }
154
+ catch {
155
+ // 파싱 실패 시 null 반환
156
+ return null;
157
+ }
158
+ }
159
+ /**
160
+ * Procedural Memory 스냅샷 생성
161
+ *
162
+ * memory_item 테이블에서 메모리를 조회하고, memory_link 테이블에서 version_of 관계를 조회하여
163
+ * 변경 감지에 필요한 모든 정보를 포함한 스냅샷을 생성합니다.
164
+ *
165
+ * @param db - 데이터베이스 인스턴스
166
+ * @param memoryId - 메모리 ID
167
+ * @returns ProceduralMemorySnapshot 또는 null (메모리가 없거나 procedural 타입이 아닌 경우)
168
+ */
169
+ export function createProceduralMemorySnapshot(db, memoryId) {
170
+ // memory_item 테이블에서 메모리 조회
171
+ const memory = DatabaseUtils.get(db, `SELECT
172
+ id, content, importance, privacy_scope, workflow_name, skill_name,
173
+ steps, trigger_conditions, task_goal, reflection_notes, edit_count, last_accessed
174
+ FROM memory_item
175
+ WHERE id = ? AND type = 'procedural'`, [memoryId]);
176
+ // 메모리가 없거나 procedural 타입이 아닌 경우 null 반환
177
+ if (!memory) {
178
+ return null;
179
+ }
180
+ // memory_link 테이블에서 version_of 관계 조회
181
+ // source_id가 현재 메모리 id이고 relation_type이 'version_of'인 경우
182
+ const versionLink = DatabaseUtils.get(db, `SELECT target_id
183
+ FROM memory_link
184
+ WHERE source_id = ? AND relation_type = 'version_of'
185
+ LIMIT 1`, [memoryId]);
186
+ // steps와 trigger_conditions 해시 계산
187
+ const stepsHash = computeJsonHash(memory.steps);
188
+ const triggerConditionsHash = computeJsonHash(memory.trigger_conditions);
189
+ // reflection_notes 배열 길이 계산
190
+ const reflectionNotesCount = computeReflectionNotesCount(memory.reflection_notes);
191
+ // 스냅샷 생성
192
+ return {
193
+ id: memory.id,
194
+ content: memory.content,
195
+ importance: memory.importance,
196
+ privacy_scope: memory.privacy_scope,
197
+ workflow_name: memory.workflow_name,
198
+ skill_name: memory.skill_name,
199
+ steps_hash: stepsHash,
200
+ trigger_conditions_hash: triggerConditionsHash,
201
+ task_goal: memory.task_goal,
202
+ reflection_notes_count: reflectionNotesCount,
203
+ edit_count: memory.edit_count ?? 0,
204
+ version_of_target_id: versionLink?.target_id ?? null,
205
+ };
206
+ }
207
+ /**
208
+ * 두 값가 같은지 비교 (null 처리 포함)
209
+ */
210
+ function isEqual(a, b) {
211
+ // 둘 다 null이거나 undefined인 경우
212
+ if ((a === null || a === undefined) && (b === null || b === undefined)) {
213
+ return true;
214
+ }
215
+ // 하나만 null이거나 undefined인 경우
216
+ if ((a === null || a === undefined) || (b === null || b === undefined)) {
217
+ return false;
218
+ }
219
+ // 값 비교
220
+ return a === b;
221
+ }
222
+ /**
223
+ * Procedural Memory 변경 감지
224
+ *
225
+ * PRD FR4 기반 판정 기준에 따라 변경 여부와 변경 타입을 판정합니다.
226
+ *
227
+ * 판정 우선순위:
228
+ * 1. 경계값 처리 (null 체크)
229
+ * 2. version_created
230
+ * 3. steps_modified
231
+ * 4. metadata_modified
232
+ * 5. content_modified
233
+ * 6. reflection_added
234
+ * 7. deleted (경계값 처리에서 이미 처리됨)
235
+ * 8. none
236
+ *
237
+ * @param before - 변경 전 스냅샷 (또는 null)
238
+ * @param after - 변경 후 스냅샷 (또는 null)
239
+ * @returns 변경 감지 결과
240
+ */
241
+ export function hasProceduralMemoryChanged(before, after) {
242
+ // 경계값 처리: 둘 다 null
243
+ if (before === null && after === null) {
244
+ return {
245
+ hasChanged: false,
246
+ changeType: 'none',
247
+ changedFields: [],
248
+ before: null,
249
+ after: null,
250
+ };
251
+ }
252
+ // 경계값 처리: 신규 생성 (before === null && after !== null)
253
+ if (before === null && after !== null) {
254
+ // versioned 모드로 생성된 경우
255
+ if (after.version_of_target_id !== null) {
256
+ return {
257
+ hasChanged: true,
258
+ changeType: 'version_created',
259
+ changedFields: ['id', 'version_of_target_id'],
260
+ before: null,
261
+ after,
262
+ };
263
+ }
264
+ // 단순 신규 생성 (메타데이터 변경으로 간주)
265
+ return {
266
+ hasChanged: true,
267
+ changeType: 'metadata_modified',
268
+ changedFields: ['id'],
269
+ before: null,
270
+ after,
271
+ };
272
+ }
273
+ // 경계값 처리: 삭제 (before !== null && after === null)
274
+ if (before !== null && after === null) {
275
+ return {
276
+ hasChanged: true,
277
+ changeType: 'deleted',
278
+ changedFields: ['id'],
279
+ before,
280
+ after: null,
281
+ };
282
+ }
283
+ // 이제 before와 after가 모두 null이 아님을 보장
284
+ // TypeScript 타입 가드를 위해 명시적 체크
285
+ if (before === null || after === null) {
286
+ // 이 경우는 발생하지 않아야 하지만 타입 안전성을 위해
287
+ return {
288
+ hasChanged: false,
289
+ changeType: 'none',
290
+ changedFields: [],
291
+ before,
292
+ after,
293
+ };
294
+ }
295
+ // 변경된 필드 추적
296
+ const changedFields = [];
297
+ // version_created 체크: versioned 모드로 새 버전 생성
298
+ if (before.version_of_target_id === null &&
299
+ after.version_of_target_id !== null) {
300
+ changedFields.push('version_of_target_id');
301
+ return {
302
+ hasChanged: true,
303
+ changeType: 'version_created',
304
+ changedFields,
305
+ before,
306
+ after,
307
+ };
308
+ }
309
+ // steps_modified 체크: steps_hash 변경
310
+ if (!isEqual(before.steps_hash, after.steps_hash)) {
311
+ changedFields.push('steps_hash');
312
+ return {
313
+ hasChanged: true,
314
+ changeType: 'steps_modified',
315
+ changedFields,
316
+ before,
317
+ after,
318
+ };
319
+ }
320
+ // metadata_modified 체크: workflow_name, skill_name, trigger_conditions_hash, task_goal, edit_count 변경
321
+ const metadataFields = [
322
+ 'workflow_name',
323
+ 'skill_name',
324
+ 'trigger_conditions_hash',
325
+ 'task_goal',
326
+ 'edit_count',
327
+ ];
328
+ const metadataChanged = metadataFields.some((field) => {
329
+ if (!isEqual(before[field], after[field])) {
330
+ changedFields.push(field);
331
+ return true;
332
+ }
333
+ return false;
334
+ });
335
+ if (metadataChanged) {
336
+ return {
337
+ hasChanged: true,
338
+ changeType: 'metadata_modified',
339
+ changedFields,
340
+ before,
341
+ after,
342
+ };
343
+ }
344
+ // content_modified 체크: content 변경
345
+ if (!isEqual(before.content, after.content)) {
346
+ changedFields.push('content');
347
+ return {
348
+ hasChanged: true,
349
+ changeType: 'content_modified',
350
+ changedFields,
351
+ before,
352
+ after,
353
+ };
354
+ }
355
+ // reflection_added 체크: reflection_notes_count 증가
356
+ if (before.reflection_notes_count !== null &&
357
+ after.reflection_notes_count !== null &&
358
+ after.reflection_notes_count > before.reflection_notes_count) {
359
+ changedFields.push('reflection_notes_count');
360
+ return {
361
+ hasChanged: true,
362
+ changeType: 'reflection_added',
363
+ changedFields,
364
+ before,
365
+ after,
366
+ };
367
+ }
368
+ // 모든 필드 비교 (나머지 필드들도 확인)
369
+ const allFields = [
370
+ 'id',
371
+ 'importance',
372
+ 'privacy_scope',
373
+ 'reflection_notes_count',
374
+ 'version_of_target_id',
375
+ ];
376
+ allFields.forEach((field) => {
377
+ if (!isEqual(before[field], after[field])) {
378
+ changedFields.push(field);
379
+ }
380
+ });
381
+ // 변경이 감지되지 않은 경우
382
+ if (changedFields.length === 0) {
383
+ return {
384
+ hasChanged: false,
385
+ changeType: 'none',
386
+ changedFields: [],
387
+ before,
388
+ after,
389
+ };
390
+ }
391
+ // 예상치 못한 경우: 변경이 감지되었지만 위의 조건에 해당하지 않음
392
+ // metadata_modified로 처리 (안전한 기본값)
393
+ return {
394
+ hasChanged: true,
395
+ changeType: 'metadata_modified',
396
+ changedFields,
397
+ before,
398
+ after,
399
+ };
400
+ }
401
+ //# sourceMappingURL=procedural-memory-change-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"procedural-memory-change-detector.js","sourceRoot":"","sources":["../../../src/shared/utils/procedural-memory-change-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AA0E9C;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,UAAU;IACV,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,0BAA0B;IAC1B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,+BAA+B;IAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QACzF,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,2BAA2B;IAC3B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,eAAe,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/D,OAAO,IAAI,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAC1C,CAAC;IAED,0BAA0B;IAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzE,MAAM,GAAG,GAAG,KAAgC,CAAC;QAC7C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,MAAM,eAAe,GAAa,EAAE,CAAC;QAErC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACrB,gCAAgC;YAChC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACtB,MAAM,eAAe,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;gBAC3C,sBAAsB;gBACtB,eAAe,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;QAED,OAAO,IAAI,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAC1C,CAAC;IAED,sBAAsB;IACtB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,eAAe,CAAC,UAAyB;IACvD,0BAA0B;IAC1B,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,sBAAsB;IACtB,IAAI,UAAU,KAAK,EAAE,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,4BAA4B;IAC5B,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACtC,sBAAsB;YACtB,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;YACzC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;YAClC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,2BAA2B;YAC3B,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;YAClC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,qCAAqC;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACtC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;QAChC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,2BAA2B,CAAC,eAA8B;IACjE,IAAI,eAAe,KAAK,IAAI,IAAI,eAAe,KAAK,EAAE,EAAE,CAAC;QACvD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC3C,eAAe;QACf,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;QACD,+BAA+B;QAC/B,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YAClD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,YAAY;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,8BAA8B,CAC5C,EAAqB,EACrB,QAAgB;IAEhB,2BAA2B;IAC3B,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAC9B,EAAE,EACF;;;;yCAIqC,EACrC,CAAC,QAAQ,CAAC,CAcC,CAAC;IAEd,wCAAwC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,qCAAqC;IACrC,yDAAyD;IACzD,MAAM,WAAW,GAAG,aAAa,CAAC,GAAG,CACnC,EAAE,EACF;;;YAGQ,EACR,CAAC,QAAQ,CAAC,CAC0B,CAAC;IAEvC,kCAAkC;IAClC,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,qBAAqB,GAAG,eAAe,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAEzE,4BAA4B;IAC5B,MAAM,oBAAoB,GAAG,2BAA2B,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAElF,SAAS;IACT,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,UAAU,EAAE,SAAS;QACrB,uBAAuB,EAAE,qBAAqB;QAC9C,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,sBAAsB,EAAE,oBAAoB;QAC5C,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,CAAC;QAClC,oBAAoB,EAAE,WAAW,EAAE,SAAS,IAAI,IAAI;KACrD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,OAAO,CAAC,CAAU,EAAE,CAAU;IACrC,4BAA4B;IAC5B,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,CAAC,EAAE,CAAC;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,4BAA4B;IAC5B,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,CAAC,EAAE,CAAC;QACvE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO;IACP,OAAO,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAAuC,EACvC,KAAsC;IAEtC,mBAAmB;IACnB,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACtC,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,UAAU,EAAE,MAAM;YAClB,aAAa,EAAE,EAAE;YACjB,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAED,oDAAoD;IACpD,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACtC,uBAAuB;QACvB,IAAI,KAAK,CAAC,oBAAoB,KAAK,IAAI,EAAE,CAAC;YACxC,OAAO;gBACL,UAAU,EAAE,IAAI;gBAChB,UAAU,EAAE,iBAAiB;gBAC7B,aAAa,EAAE,CAAC,IAAI,EAAE,sBAAsB,CAAC;gBAC7C,MAAM,EAAE,IAAI;gBACZ,KAAK;aACN,CAAC;QACJ,CAAC;QACD,2BAA2B;QAC3B,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,mBAAmB;YAC/B,aAAa,EAAE,CAAC,IAAI,CAAC;YACrB,MAAM,EAAE,IAAI;YACZ,KAAK;SACN,CAAC;IACJ,CAAC;IAED,iDAAiD;IACjD,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACtC,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,SAAS;YACrB,aAAa,EAAE,CAAC,IAAI,CAAC;YACrB,MAAM;YACN,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAED,oCAAoC;IACpC,8BAA8B;IAC9B,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACtC,gCAAgC;QAChC,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,UAAU,EAAE,MAAM;YAClB,aAAa,EAAE,EAAE;YACjB,MAAM;YACN,KAAK;SACN,CAAC;IACJ,CAAC;IAED,YAAY;IACZ,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,4CAA4C;IAC5C,IACE,MAAM,CAAC,oBAAoB,KAAK,IAAI;QACpC,KAAK,CAAC,oBAAoB,KAAK,IAAI,EACnC,CAAC;QACD,aAAa,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC3C,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,iBAAiB;YAC7B,aAAa;YACb,MAAM;YACN,KAAK;SACN,CAAC;IACJ,CAAC;IAED,mCAAmC;IACnC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QAClD,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACjC,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,gBAAgB;YAC5B,aAAa;YACb,MAAM;YACN,KAAK;SACN,CAAC;IACJ,CAAC;IAED,qGAAqG;IACrG,MAAM,cAAc,GAA0C;QAC5D,eAAe;QACf,YAAY;QACZ,yBAAyB;QACzB,WAAW;QACX,YAAY;KACb,CAAC;IAEF,MAAM,eAAe,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QACpD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC1C,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,mBAAmB;YAC/B,aAAa;YACb,MAAM;YACN,KAAK;SACN,CAAC;IACJ,CAAC;IAED,kCAAkC;IAClC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5C,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC9B,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,kBAAkB;YAC9B,aAAa;YACb,MAAM;YACN,KAAK;SACN,CAAC;IACJ,CAAC;IAED,iDAAiD;IACjD,IACE,MAAM,CAAC,sBAAsB,KAAK,IAAI;QACtC,KAAK,CAAC,sBAAsB,KAAK,IAAI;QACrC,KAAK,CAAC,sBAAsB,GAAG,MAAM,CAAC,sBAAsB,EAC5D,CAAC;QACD,aAAa,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QAC7C,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,kBAAkB;YAC9B,aAAa;YACb,MAAM;YACN,KAAK;SACN,CAAC;IACJ,CAAC;IAED,yBAAyB;IACzB,MAAM,SAAS,GAA0C;QACvD,IAAI;QACJ,YAAY;QACZ,eAAe;QACf,wBAAwB;QACxB,sBAAsB;KACvB,CAAC;IAEF,SAAS,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QAC1B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC1C,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,iBAAiB;IACjB,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,UAAU,EAAE,MAAM;YAClB,aAAa,EAAE,EAAE;YACjB,MAAM;YACN,KAAK;SACN,CAAC;IACJ,CAAC;IAED,uCAAuC;IACvC,kCAAkC;IAClC,OAAO;QACL,UAAU,EAAE,IAAI;QAChB,UAAU,EAAE,mBAAmB;QAC/B,aAAa;QACb,MAAM;QACN,KAAK;KACN,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memento-mcp-server",
3
- "version": "1.16.0",
3
+ "version": "1.16.1",
4
4
  "description": "AI Agent 기억 보조 MCP 서버 - 사람의 기억 구조를 모사한 스토리지+검색+요약+망각 메커니즘",
5
5
  "main": "dist/server/index.js",
6
6
  "type": "module",