@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.
@@ -4,60 +4,43 @@
4
4
  // ============================================================================
5
5
 
6
6
  /**
7
- * Context types for memories - what kind of insight is this?
7
+ * Context types for memories - STRICT ENUM (v3 schema)
8
+ * NO custom strings allowed - use exactly these 11 values
8
9
  */
9
10
  export type ContextType =
10
- | 'breakthrough' // Major discovery or insight
11
- | 'decision' // Important decision made
12
- | 'personal' // Personal/relationship information
13
- | 'technical' // Technical knowledge
14
- | 'technical_state' // Current technical state
15
- | 'unresolved' // Open question or problem
16
- | 'preference' // User preference
17
- | 'workflow' // How user likes to work
18
- | 'architectural' // System design decisions
19
- | 'debugging' // Debug insights
20
- | 'philosophy' // Philosophical discussions
21
- | string // Allow custom types
11
+ | 'technical' // Code, implementation, APIs, how things work
12
+ | 'debug' // Bugs, errors, fixes, gotchas, troubleshooting
13
+ | 'architecture' // System design, patterns, structure
14
+ | 'decision' // Choices made and reasoning, trade-offs
15
+ | 'personal' // Relationship, family, preferences, collaboration style
16
+ | 'philosophy' // Beliefs, values, worldview, principles
17
+ | 'workflow' // How we work together, processes, habits
18
+ | 'milestone' // Achievements, completions, shipped features
19
+ | 'breakthrough' // Major discoveries, aha moments, key insights
20
+ | 'unresolved' // Open questions, investigations, todos, blockers
21
+ | 'state' // Current project status, what's working/broken now
22
+
23
+ export const CONTEXT_TYPES = [
24
+ 'technical', 'debug', 'architecture', 'decision', 'personal',
25
+ 'philosophy', 'workflow', 'milestone', 'breakthrough', 'unresolved', 'state'
26
+ ] as const
22
27
 
23
28
  /**
24
- * Temporal relevance - how long should this memory persist?
29
+ * Temporal class - how long should this memory persist? (v3: replaces temporal_relevance)
25
30
  */
26
- export type TemporalRelevance =
27
- | 'persistent' // Always relevant (0.8 score)
28
- | 'session' // Session-specific (0.6 score)
29
- | 'temporary' // Short-term (0.3 score)
30
- | 'archived' // Historical (0.1 score)
31
-
32
- /**
33
- * Emotional resonance - the emotional context of the memory
34
- */
35
- export type EmotionalResonance =
36
- | 'joy'
37
- | 'frustration'
38
- | 'discovery'
39
- | 'gratitude'
40
- | 'curiosity'
41
- | 'determination'
42
- | 'satisfaction'
43
- | 'neutral'
44
- | string // Allow custom emotions
45
-
46
- /**
47
- * Knowledge domains - what area does this memory relate to?
48
- */
49
- export type KnowledgeDomain =
50
- | 'architecture'
51
- | 'debugging'
52
- | 'philosophy'
53
- | 'workflow'
54
- | 'personal'
55
- | 'project'
56
- | 'tooling'
57
- | 'testing'
58
- | 'deployment'
59
- | 'security'
60
- | string // Allow custom domains
31
+ export type TemporalClass =
32
+ | 'eternal' // Never fades (personal, philosophy, breakthroughs)
33
+ | 'long_term' // Years - fades slowly (decisions, architecture)
34
+ | 'medium_term' // Weeks - normal fade (technical, debug)
35
+ | 'short_term' // Days - fades quickly (state, todos)
36
+ | 'ephemeral' // Session only - surface once then expire
37
+
38
+ // NOTE: Removed in v3:
39
+ // - TemporalRelevance (replaced by TemporalClass)
40
+ // - EmotionalResonance (580 variants, never used)
41
+ // - KnowledgeDomain (overlaps with project_id + domain)
42
+ // - EmotionalResonance: 580 variants, never used in retrieval
43
+ // - KnowledgeDomain: overlaps with project_id + domain field
61
44
 
62
45
  /**
63
46
  * Trigger types for memory curation
@@ -71,7 +54,7 @@ export type CurationTrigger =
71
54
 
72
55
  /**
73
56
  * A memory curated by Claude with semantic understanding
74
- * EXACT MATCH to Python CuratedMemory dataclass
57
+ * v3 schema - consolidated metadata, strict context types
75
58
  */
76
59
  export interface CuratedMemory {
77
60
  // Core content
@@ -80,10 +63,9 @@ export interface CuratedMemory {
80
63
  semantic_tags: string[] // Concepts this relates to
81
64
  reasoning: string // Why Claude thinks this is important
82
65
 
83
- // Classification
84
- context_type: ContextType // breakthrough, decision, technical, etc.
85
- temporal_relevance: TemporalRelevance // persistent, session, temporary
86
- knowledge_domain: KnowledgeDomain // architecture, debugging, philosophy, etc.
66
+ // Classification (v3: strict enums)
67
+ context_type: ContextType // STRICT: one of 11 canonical types
68
+ temporal_class: TemporalClass // How long this memory persists
87
69
 
88
70
  // Flags
89
71
  action_required: boolean // Does this need follow-up?
@@ -93,15 +75,9 @@ export interface CuratedMemory {
93
75
  // Retrieval optimization (the secret sauce)
94
76
  trigger_phrases: string[] // Phrases that should trigger this memory
95
77
  question_types: string[] // Types of questions this answers
96
- emotional_resonance: EmotionalResonance // joy, frustration, discovery, gratitude
97
-
98
- // Optional extended metadata (from Python, may not always be present)
99
78
  anti_triggers?: string[] // Phrases where this memory is NOT relevant
100
- prerequisite_understanding?: string[] // Concepts user should know first
101
- follow_up_context?: string[] // What might come next
102
- dependency_context?: string[] // Other memories this relates to
103
79
 
104
- // ========== V2 CURATOR FIELDS (optional - get smart defaults if not provided) ==========
80
+ // ========== V2+ CURATOR FIELDS (optional - get smart defaults if not provided) ==========
105
81
  scope?: 'global' | 'project' // Shared across projects or project-specific
106
82
  temporal_class?: 'eternal' | 'long_term' | 'medium_term' | 'short_term' | 'ephemeral'
107
83
  domain?: string // Specific area (embeddings, auth, family)
@@ -113,7 +89,7 @@ export interface CuratedMemory {
113
89
 
114
90
  /**
115
91
  * A stored memory with database metadata
116
- * Includes v2 lifecycle management fields (optional for backwards compat)
92
+ * v3 schema - removed unused fields, consolidated metadata
117
93
  */
118
94
  export interface StoredMemory extends CuratedMemory {
119
95
  id: string // Unique identifier
@@ -124,7 +100,7 @@ export interface StoredMemory extends CuratedMemory {
124
100
  embedding?: Float32Array // Vector embedding (384 dimensions)
125
101
  stale?: boolean // Is embedding out of sync with content?
126
102
 
127
- // ========== V2 LIFECYCLE FIELDS (optional for backwards compat) ==========
103
+ // ========== LIFECYCLE FIELDS ==========
128
104
  status?: 'active' | 'pending' | 'superseded' | 'deprecated' | 'archived'
129
105
  scope?: 'global' | 'project'
130
106
 
@@ -133,16 +109,11 @@ export interface StoredMemory extends CuratedMemory {
133
109
  session_updated?: number
134
110
  last_surfaced?: number
135
111
  sessions_since_surfaced?: number
136
-
137
- // Temporal class & decay
138
- temporal_class?: 'eternal' | 'long_term' | 'medium_term' | 'short_term' | 'ephemeral'
139
- fade_rate?: number
140
- expires_after_sessions?: number
112
+ fade_rate?: number // Decay rate per session (derived from temporal_class)
141
113
 
142
114
  // Categorization
143
115
  domain?: string
144
116
  feature?: string
145
- component?: string
146
117
 
147
118
  // Relationships
148
119
  supersedes?: string
@@ -150,8 +121,6 @@ export interface StoredMemory extends CuratedMemory {
150
121
  related_to?: string[]
151
122
  resolves?: string[]
152
123
  resolved_by?: string
153
- parent_id?: string
154
- child_ids?: string[]
155
124
 
156
125
  // Lifecycle triggers
157
126
  awaiting_implementation?: boolean
@@ -161,7 +130,6 @@ export interface StoredMemory extends CuratedMemory {
161
130
  related_files?: string[]
162
131
 
163
132
  // Retrieval control
164
- retrieval_weight?: number
165
133
  exclude_from_retrieval?: boolean
166
134
 
167
135
  // Schema version
@@ -169,27 +137,24 @@ export interface StoredMemory extends CuratedMemory {
169
137
  }
170
138
 
171
139
  /**
172
- * Default values for v2 fields based on context_type
173
- * Used for backwards compatibility with v1 memories
140
+ * Default values for v3 fields based on context_type
141
+ * Uses only the 11 canonical context types
174
142
  */
175
- export const V2_DEFAULTS = {
176
- // Type-specific defaults
143
+ export const V3_DEFAULTS = {
144
+ // Type-specific defaults (all 11 canonical types)
177
145
  typeDefaults: {
178
146
  personal: { scope: 'global', temporal_class: 'eternal', fade_rate: 0 },
179
147
  philosophy: { scope: 'global', temporal_class: 'eternal', fade_rate: 0 },
180
- preference: { scope: 'global', temporal_class: 'long_term', fade_rate: 0.01 },
181
148
  breakthrough: { scope: 'project', temporal_class: 'eternal', fade_rate: 0 },
182
- decision: { scope: 'project', temporal_class: 'long_term', fade_rate: 0 },
183
149
  milestone: { scope: 'project', temporal_class: 'eternal', fade_rate: 0 },
150
+ decision: { scope: 'project', temporal_class: 'long_term', fade_rate: 0 },
151
+ architecture: { scope: 'project', temporal_class: 'long_term', fade_rate: 0.01 },
152
+ workflow: { scope: 'project', temporal_class: 'long_term', fade_rate: 0.02 },
184
153
  technical: { scope: 'project', temporal_class: 'medium_term', fade_rate: 0.03 },
185
- architectural: { scope: 'project', temporal_class: 'long_term', fade_rate: 0.01 },
186
- debugging: { scope: 'project', temporal_class: 'medium_term', fade_rate: 0.03 },
154
+ debug: { scope: 'project', temporal_class: 'medium_term', fade_rate: 0.03 },
187
155
  unresolved: { scope: 'project', temporal_class: 'medium_term', fade_rate: 0.05 },
188
- todo: { scope: 'project', temporal_class: 'short_term', fade_rate: 0.1 },
189
- technical_state: { scope: 'project', temporal_class: 'short_term', fade_rate: 0.1 },
190
- workflow: { scope: 'project', temporal_class: 'long_term', fade_rate: 0.02 },
191
- project_context: { scope: 'project', temporal_class: 'medium_term', fade_rate: 0.03 },
192
- } as Record<string, { scope: string; temporal_class: string; fade_rate: number }>,
156
+ state: { scope: 'project', temporal_class: 'short_term', fade_rate: 0.1 },
157
+ } as Record<ContextType, { scope: 'global' | 'project'; temporal_class: string; fade_rate: number }>,
193
158
 
194
159
  // Fallback defaults
195
160
  fallback: {
@@ -204,56 +169,58 @@ export const V2_DEFAULTS = {
204
169
  },
205
170
  }
206
171
 
172
+ // Backwards compatibility alias
173
+ export const V2_DEFAULTS = V3_DEFAULTS
174
+
207
175
  /**
208
- * Apply v2 defaults to a memory (for backwards compatibility)
176
+ * Apply v3 defaults to a memory
209
177
  * Uses context_type to determine appropriate defaults
210
178
  */
211
- export function applyV2Defaults(memory: Partial<StoredMemory>): StoredMemory {
212
- const contextType = memory.context_type ?? 'general'
213
- const typeDefaults = V2_DEFAULTS.typeDefaults[contextType] ?? V2_DEFAULTS.typeDefaults.technical
179
+ export function applyV3Defaults(memory: Partial<StoredMemory>): StoredMemory {
180
+ const contextType = (memory.context_type ?? 'technical') as ContextType
181
+ const typeDefaults = V3_DEFAULTS.typeDefaults[contextType] ?? V3_DEFAULTS.typeDefaults.technical
214
182
 
215
183
  return {
216
184
  // Spread existing memory
217
185
  ...memory,
218
186
 
219
187
  // Apply status default
220
- status: memory.status ?? V2_DEFAULTS.fallback.status,
188
+ status: memory.status ?? V3_DEFAULTS.fallback.status,
221
189
 
222
190
  // Apply scope from type defaults
223
- scope: memory.scope ?? typeDefaults?.scope ?? V2_DEFAULTS.fallback.scope,
191
+ scope: memory.scope ?? typeDefaults?.scope ?? V3_DEFAULTS.fallback.scope,
224
192
 
225
193
  // Apply temporal class from type defaults
226
- temporal_class: memory.temporal_class ?? typeDefaults?.temporal_class ?? V2_DEFAULTS.fallback.temporal_class,
194
+ temporal_class: memory.temporal_class ?? typeDefaults?.temporal_class ?? V3_DEFAULTS.fallback.temporal_class,
227
195
 
228
196
  // Apply fade rate from type defaults
229
- fade_rate: memory.fade_rate ?? typeDefaults?.fade_rate ?? V2_DEFAULTS.fallback.fade_rate,
197
+ fade_rate: memory.fade_rate ?? typeDefaults?.fade_rate ?? V3_DEFAULTS.fallback.fade_rate,
230
198
 
231
199
  // Apply other defaults
232
- sessions_since_surfaced: memory.sessions_since_surfaced ?? V2_DEFAULTS.fallback.sessions_since_surfaced,
233
- awaiting_implementation: memory.awaiting_implementation ?? V2_DEFAULTS.fallback.awaiting_implementation,
234
- awaiting_decision: memory.awaiting_decision ?? V2_DEFAULTS.fallback.awaiting_decision,
235
- exclude_from_retrieval: memory.exclude_from_retrieval ?? V2_DEFAULTS.fallback.exclude_from_retrieval,
236
-
237
- // Retrieval weight defaults to importance_weight
238
- retrieval_weight: memory.retrieval_weight ?? memory.importance_weight ?? 0.5,
200
+ sessions_since_surfaced: memory.sessions_since_surfaced ?? V3_DEFAULTS.fallback.sessions_since_surfaced,
201
+ awaiting_implementation: memory.awaiting_implementation ?? V3_DEFAULTS.fallback.awaiting_implementation,
202
+ awaiting_decision: memory.awaiting_decision ?? V3_DEFAULTS.fallback.awaiting_decision,
203
+ exclude_from_retrieval: memory.exclude_from_retrieval ?? V3_DEFAULTS.fallback.exclude_from_retrieval,
239
204
 
240
205
  // Initialize empty arrays if not present
241
206
  related_to: memory.related_to ?? [],
242
207
  resolves: memory.resolves ?? [],
243
- child_ids: memory.child_ids ?? [],
244
208
  blocks: memory.blocks ?? [],
245
209
  related_files: memory.related_files ?? [],
246
210
 
247
211
  // Mark as current schema version
248
- schema_version: memory.schema_version ?? 2,
212
+ schema_version: memory.schema_version ?? 3,
249
213
  } as StoredMemory
250
214
  }
251
215
 
216
+ // Backwards compatibility alias
217
+ export const applyV2Defaults = applyV3Defaults
218
+
252
219
  /**
253
- * Check if a memory needs migration (is v1)
220
+ * Check if a memory needs migration to v3
254
221
  */
255
222
  export function needsMigration(memory: Partial<StoredMemory>): boolean {
256
- return !memory.schema_version || memory.schema_version < 2
223
+ return !memory.schema_version || memory.schema_version < 3
257
224
  }
258
225
 
259
226
  /**
@@ -315,27 +282,21 @@ export interface SessionPrimer {
315
282
  }
316
283
 
317
284
  /**
318
- * Emoji map for memory context types
285
+ * Emoji map for memory context types (v3 schema)
319
286
  * Compact visual representation for efficient parsing
320
287
  */
321
- export const MEMORY_TYPE_EMOJI: Record<string, string> = {
322
- breakthrough: 'πŸ’‘', // Insight, discovery
323
- decision: 'βš–οΈ', // Choice made
324
- personal: 'πŸ’œ', // Relationship, friendship
325
- technical: 'πŸ”§', // Technical knowledge
326
- technical_state: 'πŸ“', // Current state
327
- unresolved: '❓', // Open question
328
- preference: 'βš™οΈ', // User preference
329
- workflow: 'πŸ”„', // How work flows
330
- architectural: 'πŸ—οΈ', // System design
331
- debugging: 'πŸ›', // Debug insight
332
- philosophy: 'πŸŒ€', // Deeper thinking
333
- todo: '🎯', // Action needed
334
- implementation: '⚑', // Implementation detail
335
- problem_solution: 'βœ…', // Problemβ†’Solution pair
336
- project_context: 'πŸ“¦', // Project context
337
- milestone: 'πŸ†', // Achievement
338
- general: 'πŸ“', // General note
288
+ export const MEMORY_TYPE_EMOJI: Record<ContextType, string> = {
289
+ technical: 'πŸ”§', // Wrench - building/fixing code
290
+ debug: 'πŸ›', // Bug - debugging
291
+ architecture: 'πŸ—οΈ', // Construction - system design
292
+ decision: 'βš–οΈ', // Scale - weighing options
293
+ personal: 'πŸ’œ', // Purple heart - relationship
294
+ philosophy: 'πŸŒ€', // Spiral - deeper thinking
295
+ workflow: 'πŸ”„', // Cycle - processes
296
+ milestone: 'πŸ†', // Trophy - achievement
297
+ breakthrough: 'πŸ’‘', // Lightbulb - insight
298
+ unresolved: '❓', // Question - open items
299
+ state: 'πŸ“', // Pin - current status
339
300
  }
340
301
 
341
302
  /**
@@ -9,7 +9,7 @@ import type { SchemaDefinition } from '@rlabs-inc/fsdb'
9
9
  * Schema version for migration tracking
10
10
  * Increment this when adding new fields that require migration
11
11
  */
12
- export const MEMORY_SCHEMA_VERSION = 2
12
+ export const MEMORY_SCHEMA_VERSION = 3
13
13
 
14
14
  /**
15
15
  * Memory storage schema
@@ -18,6 +18,15 @@ export const MEMORY_SCHEMA_VERSION = 2
18
18
  * VERSION HISTORY:
19
19
  * v1: Original schema (content, reasoning, importance_weight, etc.)
20
20
  * v2: Added lifecycle management fields (status, scope, domain, relationships, etc.)
21
+ * v3: Consolidated metadata - removed fragmented/unused fields:
22
+ * - knowledge_domain (overlaps with project_id + domain)
23
+ * - emotional_resonance (580 variants, never used)
24
+ * - component (always empty)
25
+ * - expires_after_sessions (never used)
26
+ * - parent_id/child_ids (no logic implemented)
27
+ * - retrieval_weight (retrieval uses importance_weight)
28
+ * - temporal_relevance (replaced by temporal_class)
29
+ * Also: context_type now strict enum (11 canonical values)
21
30
  */
22
31
  export const memorySchema = {
23
32
  // ========== CORE CONTENT (v1) ==========
@@ -28,11 +37,8 @@ export const memorySchema = {
28
37
  importance_weight: 'number', // 0.0 to 1.0
29
38
  confidence_score: 'number', // 0.0 to 1.0
30
39
 
31
- // ========== CLASSIFICATION (v1) ==========
32
- context_type: 'string', // breakthrough, decision, technical, etc.
33
- temporal_relevance: 'string', // persistent, session, temporary, archived
34
- knowledge_domain: 'string', // architecture, debugging, philosophy
35
- emotional_resonance: 'string', // joy, frustration, discovery, gratitude
40
+ // ========== CLASSIFICATION (v3) ==========
41
+ context_type: 'string', // v3: strict enum (technical, debug, architecture, decision, personal, philosophy, workflow, milestone, breakthrough, unresolved, state)
36
42
 
37
43
  // ========== FLAGS (v1) ==========
38
44
  action_required: 'boolean',
@@ -63,12 +69,10 @@ export const memorySchema = {
63
69
  // ========== TEMPORAL CLASS & DECAY (v2) ==========
64
70
  temporal_class: 'string', // eternal | long_term | medium_term | short_term | ephemeral
65
71
  fade_rate: 'number', // Decay rate per session
66
- expires_after_sessions: 'number', // For ephemeral only
67
72
 
68
73
  // ========== CATEGORIZATION (v2) ==========
69
74
  domain: 'string', // embeddings, gpu, auth, family, etc.
70
75
  feature: 'string', // Specific feature within domain
71
- component: 'string', // Code component if applicable
72
76
 
73
77
  // ========== RELATIONSHIPS (v2) ==========
74
78
  supersedes: 'string', // ID of memory this replaces
@@ -76,8 +80,6 @@ export const memorySchema = {
76
80
  related_to: 'string[]', // IDs of related memories
77
81
  resolves: 'string[]', // IDs of unresolved/debug/todo this solved
78
82
  resolved_by: 'string', // ID of solved memory that resolved this
79
- parent_id: 'string', // For chains/sequences
80
- child_ids: 'string[]', // Children in chain
81
83
 
82
84
  // ========== LIFECYCLE TRIGGERS (v2) ==========
83
85
  awaiting_implementation: 'boolean', // Set true for planned features
@@ -87,7 +89,6 @@ export const memorySchema = {
87
89
  related_files: 'string[]', // Source files for technical memories
88
90
 
89
91
  // ========== RETRIEVAL CONTROL (v2) ==========
90
- retrieval_weight: 'number', // Current weight (affected by decay)
91
92
  exclude_from_retrieval: 'boolean', // Force exclusion
92
93
 
93
94
  // ========== SCHEMA VERSION (v2) ==========
@@ -153,7 +153,6 @@ export const logger = {
153
153
  importance_weight: number
154
154
  context_type: string
155
155
  semantic_tags?: string[]
156
- emotional_resonance?: string
157
156
  action_required?: boolean
158
157
  }>) {
159
158
  console.log()
@@ -575,6 +574,7 @@ export const logger = {
575
574
  domain: number
576
575
  feature: number
577
576
  content: number
577
+ files: number
578
578
  vector: number
579
579
  total: number
580
580
  }
@@ -601,6 +601,7 @@ export const logger = {
601
601
  { name: 'domain', count: signalBreakdown.domain },
602
602
  { name: 'feature', count: signalBreakdown.feature },
603
603
  { name: 'content', count: signalBreakdown.content },
604
+ { name: 'files', count: signalBreakdown.files },
604
605
  { name: 'vector', count: signalBreakdown.vector },
605
606
  ]
606
607
  for (const sig of signals) {
@@ -621,7 +622,7 @@ export const logger = {
621
622
  if (Object.keys(buckets).length > 0) {
622
623
  console.log(` ${style('bold', 'Distribution:')}`)
623
624
  const maxBucketCount = Math.max(...Object.values(buckets), 1)
624
- const bucketOrder = ['2 signals', '3 signals', '4 signals', '5 signals', '6 signals']
625
+ const bucketOrder = ['2 signals', '3 signals', '4 signals', '5 signals', '6 signals', '7 signals']
625
626
 
626
627
  for (const bucket of bucketOrder) {
627
628
  const count = buckets[bucket] ?? 0