@rlabs-inc/memory 0.3.11 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,392 @@
1
+ // ============================================================================
2
+ // V3 SCHEMA MIGRATION
3
+ // Consolidates fragmented metadata into canonical categories
4
+ // ============================================================================
5
+
6
+ /**
7
+ * V3 Schema Version
8
+ */
9
+ export const V3_SCHEMA_VERSION = 3
10
+
11
+ /**
12
+ * Canonical context types - STRICT ENUM, no custom strings allowed
13
+ */
14
+ export const CANONICAL_CONTEXT_TYPES = [
15
+ 'technical', // Code, implementation, APIs, how things work
16
+ 'debug', // Bugs, errors, fixes, gotchas, troubleshooting
17
+ 'architecture', // System design, patterns, structure, decisions about structure
18
+ 'decision', // Choices made and reasoning, trade-offs
19
+ 'personal', // Relationship, family, preferences, collaboration style
20
+ 'philosophy', // Beliefs, values, worldview, principles
21
+ 'workflow', // How we work together, processes, habits
22
+ 'milestone', // Achievements, completions, shipped features
23
+ 'breakthrough', // Major discoveries, aha moments, key insights
24
+ 'unresolved', // Open questions, investigations, todos, blockers
25
+ 'state', // Current project status, what's working/broken now
26
+ ] as const
27
+
28
+ export type CanonicalContextType = typeof CANONICAL_CONTEXT_TYPES[number]
29
+
30
+ /**
31
+ * Mapping from ALL known fragmented types to canonical types
32
+ * Built from analysis of 1,278 memories with 170+ unique context_type values
33
+ */
34
+ export const CONTEXT_TYPE_MIGRATION_MAP: Record<string, CanonicalContextType> = {
35
+ // === TECHNICAL (code, implementation, APIs) ===
36
+ 'technical': 'technical',
37
+ 'technical_implementation': 'technical',
38
+ 'technical_pattern': 'technical',
39
+ 'technical_solution': 'technical',
40
+ 'technical_insight': 'technical',
41
+ 'technical_reference': 'technical',
42
+ 'technical_achievement': 'technical',
43
+ 'technical_discovery': 'technical',
44
+ 'technical_milestone': 'technical',
45
+ 'technical_verification': 'technical',
46
+ 'technical_validation': 'technical',
47
+ 'technical_research': 'technical',
48
+ 'technical_metrics': 'technical',
49
+ 'technical_knowledge': 'technical',
50
+ 'technical_improvement': 'technical',
51
+ 'technical_connection': 'technical',
52
+ 'technical_completion': 'technical',
53
+ 'technical_clarification': 'technical',
54
+ 'technical_blocker': 'technical',
55
+ 'technical-pattern': 'technical',
56
+ 'technical-solution': 'technical',
57
+ 'implementation': 'technical',
58
+ 'implementation_detail': 'technical',
59
+ 'implementation_pattern': 'technical',
60
+ 'implementation_task': 'technical',
61
+ 'implementation_status': 'technical',
62
+ 'implementation_reference': 'technical',
63
+ 'implementation_breakthrough': 'technical',
64
+ 'implementation-gap': 'technical',
65
+ 'implementation-detail': 'technical',
66
+ 'implementation-complete': 'technical',
67
+ 'feature_implementation': 'technical',
68
+ 'feature_specification': 'technical',
69
+ 'feature_reference': 'technical',
70
+ 'feature_design': 'technical',
71
+ 'code_reference': 'technical',
72
+ 'code_quality': 'technical',
73
+ 'code_patterns': 'technical',
74
+ 'code_pattern': 'technical',
75
+ 'coding_pattern': 'technical',
76
+ 'api_reference': 'technical',
77
+ 'api_migration': 'technical',
78
+ 'api_limitation': 'technical',
79
+ 'api_documentation': 'technical',
80
+ 'api_design': 'technical',
81
+ 'api_configuration': 'technical',
82
+ 'api_clarification': 'technical',
83
+ 'reference': 'technical',
84
+ 'reference_implementation': 'technical',
85
+ 'domain_knowledge': 'technical',
86
+ 'configuration': 'technical',
87
+ 'deployment_configuration': 'technical',
88
+ 'tool_knowledge': 'technical',
89
+ 'tool_created': 'technical',
90
+ 'problem_solution': 'technical', // Has problem_solution_pair flag
91
+ 'general': 'technical', // Fallback
92
+ 'insight': 'technical',
93
+ 'validation': 'technical',
94
+ 'validation_results': 'technical',
95
+
96
+ // === DEBUG (bugs, errors, fixes) ===
97
+ 'debug': 'debug',
98
+ 'debugging': 'debug',
99
+ 'debugging_insight': 'debug',
100
+ 'debugging_technique': 'debug',
101
+ 'debugging_tool': 'debug',
102
+ 'debugging_context': 'debug',
103
+ 'active_debugging': 'debug',
104
+ 'bug_fix': 'debug',
105
+ 'bug_solution': 'debug',
106
+ 'bug_report': 'debug',
107
+ 'bug_fix_pattern': 'debug',
108
+ 'bug_fix_needed': 'debug',
109
+ 'bug_discovery': 'debug',
110
+ 'active_bug': 'debug',
111
+ 'active_issue': 'debug',
112
+ 'technical_gotcha': 'debug',
113
+ 'gotcha': 'debug',
114
+ 'problem_discovery': 'debug',
115
+ 'technical_fix': 'debug',
116
+ 'solved': 'debug',
117
+ 'critical_discovery': 'debug',
118
+
119
+ // === ARCHITECTURE (system design, patterns) ===
120
+ 'architecture': 'architecture',
121
+ 'architectural': 'architecture',
122
+ 'architectural_decision': 'architecture',
123
+ 'architectural_pattern': 'architecture',
124
+ 'architectural_principle': 'architecture',
125
+ 'architectural_insight': 'architecture',
126
+ 'architectural_understanding': 'architecture',
127
+ 'architectural_discovery': 'architecture',
128
+ 'architectural_direction': 'architecture',
129
+ 'architectural-decision': 'architecture',
130
+ 'architecture_pattern': 'architecture',
131
+ 'architecture_decision': 'architecture',
132
+ 'architecture_documentation': 'architecture',
133
+ 'system_design': 'architecture',
134
+ 'design_pattern': 'architecture',
135
+ 'design_methodology': 'architecture',
136
+ 'design_principle': 'architecture',
137
+ 'design_insight': 'architecture',
138
+ 'design_system': 'architecture',
139
+ 'design-system': 'architecture',
140
+ 'core_concept': 'architecture',
141
+
142
+ // === DECISION (choices made and reasoning) ===
143
+ 'decision': 'decision',
144
+ 'technical_decision': 'decision',
145
+ 'design_decision': 'decision',
146
+ 'design-decision': 'decision',
147
+ 'design_philosophy': 'decision',
148
+ 'strategic_decision': 'decision',
149
+ 'strategic_priority': 'decision',
150
+ 'project-decision': 'decision',
151
+
152
+ // === PERSONAL (relationship, family, preferences) ===
153
+ 'personal': 'personal',
154
+ 'personal_context': 'personal',
155
+ 'personal_update': 'personal',
156
+ 'personal_philosophy': 'personal',
157
+ 'relationship': 'personal',
158
+ 'relationship_context': 'personal',
159
+ 'relationship_pattern': 'personal',
160
+ 'relationship_insight': 'personal',
161
+ 'relationship_philosophy': 'personal',
162
+ 'relationship_milestone': 'personal',
163
+ 'relationship_moment': 'personal',
164
+ 'relationship_dynamics': 'personal',
165
+ 'relationship_dynamic': 'personal',
166
+ 'relationship_repair': 'personal',
167
+ 'preference': 'personal',
168
+ 'user_preference': 'personal',
169
+ 'collaborator_philosophy': 'personal',
170
+ 'collaborator-guidance': 'personal',
171
+ 'collaboration_philosophy': 'personal',
172
+ 'collaboration_pattern': 'personal',
173
+ 'collaboration_insight': 'personal',
174
+ 'collaboration_context': 'personal',
175
+ 'collaboration': 'personal',
176
+ 'user_philosophy': 'personal',
177
+
178
+ // === PHILOSOPHY (beliefs, values, worldview) ===
179
+ 'philosophy': 'philosophy',
180
+ 'philosophical_insight': 'philosophy',
181
+ 'philosophical_framework': 'philosophy',
182
+ 'philosophical_anchor': 'philosophy',
183
+ 'philosophical_technical_bridge': 'philosophy',
184
+ 'project_philosophy': 'philosophy',
185
+ 'product_philosophy': 'philosophy',
186
+ 'values_and_ethics': 'philosophy',
187
+ 'wisdom': 'philosophy',
188
+
189
+ // === WORKFLOW (how we work together) ===
190
+ 'workflow': 'workflow',
191
+ 'workflow_pattern': 'workflow',
192
+ 'development_workflow': 'workflow',
193
+ 'development_tip': 'workflow',
194
+ 'developer_preferences': 'workflow',
195
+ 'development_practice': 'workflow',
196
+ 'development_methodology': 'workflow',
197
+
198
+ // === MILESTONE (achievements, completions) ===
199
+ 'milestone': 'milestone',
200
+ 'project_milestone': 'milestone',
201
+ 'creative_achievement': 'milestone',
202
+ 'technical_achievement': 'milestone',
203
+
204
+ // === BREAKTHROUGH (major discoveries) ===
205
+ 'breakthrough': 'breakthrough',
206
+
207
+ // === UNRESOLVED (open questions, todos) ===
208
+ 'unresolved': 'unresolved',
209
+ 'todo': 'unresolved',
210
+ 'open_question': 'unresolved',
211
+ 'open_questions': 'unresolved',
212
+ 'open_investigation': 'unresolved',
213
+ 'pending_work': 'unresolved',
214
+ 'pending_task': 'unresolved',
215
+ 'planned_experiment': 'unresolved',
216
+ 'work_in_progress': 'unresolved',
217
+ 'upcoming_work': 'unresolved',
218
+ 'future_planning': 'unresolved',
219
+ 'planning': 'unresolved',
220
+
221
+ // === STATE (current project status) ===
222
+ 'state': 'state',
223
+ 'technical_state': 'state',
224
+ 'project_status': 'state',
225
+ 'project_state': 'state',
226
+ 'project_context': 'state',
227
+ 'project_structure': 'state',
228
+ 'project_roadmap': 'state',
229
+ 'project_organization': 'state',
230
+ 'project_foundation': 'state',
231
+ 'project_direction': 'state',
232
+ 'project_vision': 'state',
233
+ 'project_documentation': 'state',
234
+ 'project_architecture': 'state',
235
+ 'experimental_result': 'state',
236
+ 'performance_data': 'state',
237
+ 'framework_status': 'state',
238
+ }
239
+
240
+ /**
241
+ * New emoji map aligned with canonical types
242
+ */
243
+ export const V3_EMOJI_MAP: Record<CanonicalContextType, string> = {
244
+ technical: '🔧', // Wrench - building/fixing
245
+ debug: '🐛', // Bug - debugging
246
+ architecture: '🏗️', // Construction - system design
247
+ decision: '⚖️', // Scale - weighing options
248
+ personal: '💜', // Purple heart - relationship
249
+ philosophy: '🌀', // Spiral - deeper thinking
250
+ workflow: '🔄', // Cycle - processes
251
+ milestone: '🏆', // Trophy - achievement
252
+ breakthrough: '💡', // Lightbulb - insight
253
+ unresolved: '❓', // Question - open items
254
+ state: '📍', // Pin - current status
255
+ }
256
+
257
+ /**
258
+ * Fields to DELETE in v3 migration
259
+ */
260
+ export const V3_DELETED_FIELDS = [
261
+ 'emotional_resonance', // 580 variants, broken matching
262
+ 'knowledge_domain', // Redundant with domain
263
+ 'component', // Always empty
264
+ 'prerequisite_understanding', // Never used
265
+ 'follow_up_context', // Never used
266
+ 'dependency_context', // Never used
267
+ 'retrieval_weight', // Retrieval uses importance_weight
268
+ 'parent_id', // No logic implemented
269
+ 'child_ids', // No logic implemented
270
+ 'expires_after_sessions', // Never used
271
+ 'temporal_relevance', // Replaced by temporal_class
272
+ ] as const
273
+
274
+ /**
275
+ * Map old temporal_relevance values to temporal_class
276
+ * Used during migration before deleting temporal_relevance
277
+ */
278
+ export const TEMPORAL_RELEVANCE_TO_CLASS: Record<string, string> = {
279
+ 'persistent': 'long_term', // Always relevant → fades slowly
280
+ 'session': 'short_term', // Session-specific → fades quickly
281
+ 'temporary': 'ephemeral', // Short-term → surface once then expire
282
+ 'archived': 'medium_term', // Historical → normal fade (status handles archival)
283
+ }
284
+
285
+ /**
286
+ * Migrate temporal_relevance to temporal_class
287
+ */
288
+ export function migrateTemporalRelevance(temporal_relevance: string | null | undefined): string | null {
289
+ if (!temporal_relevance) return null
290
+ return TEMPORAL_RELEVANCE_TO_CLASS[temporal_relevance] ?? null
291
+ }
292
+
293
+ /**
294
+ * V2 defaults updated for v3 canonical types
295
+ */
296
+ export const V3_TYPE_DEFAULTS: Record<CanonicalContextType, {
297
+ scope: 'global' | 'project'
298
+ temporal_class: 'eternal' | 'long_term' | 'medium_term' | 'short_term' | 'ephemeral'
299
+ fade_rate: number
300
+ }> = {
301
+ personal: { scope: 'global', temporal_class: 'eternal', fade_rate: 0 },
302
+ philosophy: { scope: 'global', temporal_class: 'eternal', fade_rate: 0 },
303
+ breakthrough: { scope: 'project', temporal_class: 'eternal', fade_rate: 0 },
304
+ decision: { scope: 'project', temporal_class: 'long_term', fade_rate: 0 },
305
+ milestone: { scope: 'project', temporal_class: 'eternal', fade_rate: 0 },
306
+ architecture: { scope: 'project', temporal_class: 'long_term', fade_rate: 0.01 },
307
+ workflow: { scope: 'project', temporal_class: 'long_term', fade_rate: 0.02 },
308
+ technical: { scope: 'project', temporal_class: 'medium_term', fade_rate: 0.03 },
309
+ debug: { scope: 'project', temporal_class: 'medium_term', fade_rate: 0.03 },
310
+ unresolved: { scope: 'project', temporal_class: 'medium_term', fade_rate: 0.05 },
311
+ state: { scope: 'project', temporal_class: 'short_term', fade_rate: 0.1 },
312
+ }
313
+
314
+ /**
315
+ * Check if a context_type is in our known mapping
316
+ */
317
+ export function isKnownContextType(type: string | undefined | null): boolean {
318
+ if (!type) return false
319
+ const normalized = type.toLowerCase().trim()
320
+ return normalized in CONTEXT_TYPE_MIGRATION_MAP || CANONICAL_CONTEXT_TYPES.includes(normalized as CanonicalContextType)
321
+ }
322
+
323
+ /**
324
+ * Migrate a context_type value to its canonical form
325
+ * @param oldType - The old context type value
326
+ * @param preserveUnknown - If true, return null for unknown types (caller can decide to keep original)
327
+ */
328
+ export function migrateContextType(oldType: string | undefined | null, preserveUnknown = false): CanonicalContextType | null {
329
+ if (!oldType) return 'technical'
330
+
331
+ const normalized = oldType.toLowerCase().trim()
332
+
333
+ // Already canonical
334
+ if (CANONICAL_CONTEXT_TYPES.includes(normalized as CanonicalContextType)) {
335
+ return normalized as CanonicalContextType
336
+ }
337
+
338
+ // Direct lookup in migration map
339
+ if (normalized in CONTEXT_TYPE_MIGRATION_MAP) {
340
+ return CONTEXT_TYPE_MIGRATION_MAP[normalized]
341
+ }
342
+
343
+ // If preserveUnknown is set, return null so caller can keep original
344
+ if (preserveUnknown) {
345
+ return null
346
+ }
347
+
348
+ // Fuzzy matching for unknown types
349
+ if (normalized.includes('debug') || normalized.includes('bug') || normalized.includes('fix')) {
350
+ return 'debug'
351
+ }
352
+ if (normalized.includes('architect') || normalized.includes('design') || normalized.includes('pattern')) {
353
+ return 'architecture'
354
+ }
355
+ if (normalized.includes('decision') || normalized.includes('choice')) {
356
+ return 'decision'
357
+ }
358
+ if (normalized.includes('personal') || normalized.includes('relationship') || normalized.includes('preference')) {
359
+ return 'personal'
360
+ }
361
+ if (normalized.includes('philosoph') || normalized.includes('value') || normalized.includes('wisdom')) {
362
+ return 'philosophy'
363
+ }
364
+ if (normalized.includes('workflow') || normalized.includes('process')) {
365
+ return 'workflow'
366
+ }
367
+ if (normalized.includes('milestone') || normalized.includes('achievement') || normalized.includes('complete')) {
368
+ return 'milestone'
369
+ }
370
+ if (normalized.includes('breakthrough') || normalized.includes('insight') || normalized.includes('discover')) {
371
+ return 'breakthrough'
372
+ }
373
+ if (normalized.includes('unresolved') || normalized.includes('todo') || normalized.includes('open') || normalized.includes('pending')) {
374
+ return 'unresolved'
375
+ }
376
+ if (normalized.includes('state') || normalized.includes('status') || normalized.includes('current')) {
377
+ return 'state'
378
+ }
379
+
380
+ // Default fallback
381
+ return 'technical'
382
+ }
383
+
384
+ /**
385
+ * Get emoji for a canonical context type
386
+ */
387
+ export function getV3Emoji(contextType: CanonicalContextType | string): string {
388
+ const canonical = CANONICAL_CONTEXT_TYPES.includes(contextType as CanonicalContextType)
389
+ ? contextType as CanonicalContextType
390
+ : migrateContextType(contextType)
391
+ return V3_EMOJI_MAP[canonical]
392
+ }