@rlabs-inc/memory 0.3.10 → 0.4.0
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.
- package/README.md +8 -0
- package/dist/index.js +32924 -11907
- package/dist/index.mjs +33020 -12003
- package/dist/server/index.js +22512 -1351
- package/dist/server/index.mjs +22719 -1558
- package/package.json +2 -1
- package/skills/memory-management.md +143 -154
- package/src/cli/commands/ingest.ts +227 -23
- package/src/cli/commands/migrate.ts +561 -80
- package/src/cli/index.ts +17 -4
- package/src/core/curator.ts +132 -22
- package/src/core/engine.test.ts +6 -14
- package/src/core/manager.ts +175 -1
- package/src/core/retrieval.ts +9 -22
- package/src/core/store.ts +24 -44
- package/src/migrations/v3-schema.ts +392 -0
- package/src/types/memory.ts +85 -123
- package/src/types/schema.ts +12 -11
- package/src/utils/logger.ts +10 -1
package/src/core/store.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { createDatabase, type Database, type PersistentCollection } from '@rlabs-inc/fsdb'
|
|
7
7
|
import { homedir } from 'os'
|
|
8
8
|
import { join } from 'path'
|
|
9
|
+
import { logger } from '../utils/logger.ts'
|
|
9
10
|
import {
|
|
10
11
|
type CuratedMemory,
|
|
11
12
|
type StoredMemory,
|
|
@@ -126,7 +127,7 @@ export class MemoryStore {
|
|
|
126
127
|
|
|
127
128
|
// Use the configured global path (always central)
|
|
128
129
|
const globalPath = this._config.globalPath
|
|
129
|
-
|
|
130
|
+
logger.debug(`Initializing global database at ${globalPath}`, 'store')
|
|
130
131
|
|
|
131
132
|
const db = createDatabase({
|
|
132
133
|
name: 'global',
|
|
@@ -176,9 +177,7 @@ export class MemoryStore {
|
|
|
176
177
|
importance_weight: record.importance_weight,
|
|
177
178
|
confidence_score: record.confidence_score,
|
|
178
179
|
context_type: record.context_type as StoredMemory['context_type'],
|
|
179
|
-
|
|
180
|
-
knowledge_domain: record.knowledge_domain as StoredMemory['knowledge_domain'],
|
|
181
|
-
emotional_resonance: record.emotional_resonance as StoredMemory['emotional_resonance'],
|
|
180
|
+
temporal_class: record.temporal_class as StoredMemory['temporal_class'],
|
|
182
181
|
action_required: record.action_required,
|
|
183
182
|
problem_solution_pair: record.problem_solution_pair,
|
|
184
183
|
semantic_tags: record.semantic_tags,
|
|
@@ -210,30 +209,28 @@ export class MemoryStore {
|
|
|
210
209
|
const typeDefaults = V2_DEFAULTS.typeDefaults[contextType] ?? V2_DEFAULTS.typeDefaults.personal
|
|
211
210
|
|
|
212
211
|
const id = memories.insert({
|
|
213
|
-
// Core
|
|
212
|
+
// Core fields
|
|
214
213
|
content: memory.content,
|
|
215
214
|
reasoning: memory.reasoning,
|
|
216
215
|
importance_weight: memory.importance_weight,
|
|
217
216
|
confidence_score: memory.confidence_score,
|
|
218
217
|
context_type: memory.context_type,
|
|
219
|
-
|
|
220
|
-
knowledge_domain: memory.knowledge_domain,
|
|
221
|
-
emotional_resonance: memory.emotional_resonance,
|
|
218
|
+
temporal_class: memory.temporal_class ?? typeDefaults?.temporal_class ?? 'eternal',
|
|
222
219
|
action_required: memory.action_required,
|
|
223
220
|
problem_solution_pair: memory.problem_solution_pair,
|
|
224
221
|
semantic_tags: memory.semantic_tags,
|
|
225
222
|
trigger_phrases: memory.trigger_phrases,
|
|
226
223
|
question_types: memory.question_types,
|
|
224
|
+
anti_triggers: memory.anti_triggers ?? [],
|
|
227
225
|
session_id: sessionId,
|
|
228
226
|
project_id: 'global',
|
|
229
227
|
embedding: embedding
|
|
230
228
|
? (embedding instanceof Float32Array ? embedding : new Float32Array(embedding))
|
|
231
229
|
: null,
|
|
232
230
|
|
|
233
|
-
//
|
|
231
|
+
// Lifecycle fields - global memories are always scope: 'global'
|
|
234
232
|
status: V2_DEFAULTS.fallback.status,
|
|
235
233
|
scope: 'global', // Always global for global memories
|
|
236
|
-
temporal_class: memory.temporal_class ?? typeDefaults?.temporal_class ?? 'eternal',
|
|
237
234
|
fade_rate: typeDefaults?.fade_rate ?? 0, // Global memories typically don't fade
|
|
238
235
|
session_created: sessionNumber ?? 0,
|
|
239
236
|
session_updated: sessionNumber ?? 0,
|
|
@@ -243,18 +240,15 @@ export class MemoryStore {
|
|
|
243
240
|
related_files: memory.related_files ?? [],
|
|
244
241
|
awaiting_implementation: memory.awaiting_implementation ?? false,
|
|
245
242
|
awaiting_decision: memory.awaiting_decision ?? false,
|
|
246
|
-
retrieval_weight: memory.importance_weight,
|
|
247
243
|
exclude_from_retrieval: false,
|
|
248
244
|
schema_version: MEMORY_SCHEMA_VERSION,
|
|
249
245
|
|
|
250
|
-
//
|
|
246
|
+
// Relationship fields
|
|
251
247
|
supersedes: null,
|
|
252
248
|
superseded_by: null,
|
|
253
249
|
related_to: [],
|
|
254
250
|
resolves: [],
|
|
255
251
|
resolved_by: null,
|
|
256
|
-
parent_id: null,
|
|
257
|
-
child_ids: [],
|
|
258
252
|
blocked_by: null,
|
|
259
253
|
blocks: [],
|
|
260
254
|
})
|
|
@@ -414,13 +408,13 @@ export class MemoryStore {
|
|
|
414
408
|
*/
|
|
415
409
|
async getProject(projectId: string): Promise<ProjectDB> {
|
|
416
410
|
if (this._projects.has(projectId)) {
|
|
417
|
-
|
|
411
|
+
logger.debug(`Returning cached databases for ${projectId}`, 'store')
|
|
418
412
|
return this._projects.get(projectId)!
|
|
419
413
|
}
|
|
420
414
|
|
|
421
|
-
|
|
415
|
+
logger.debug(`Creating NEW databases for ${projectId}`, 'store')
|
|
422
416
|
const projectPath = join(this._config.basePath, projectId)
|
|
423
|
-
|
|
417
|
+
logger.debug(`Path: ${projectPath}`, 'store')
|
|
424
418
|
|
|
425
419
|
// Create the database for this project
|
|
426
420
|
const db = createDatabase({
|
|
@@ -490,30 +484,28 @@ export class MemoryStore {
|
|
|
490
484
|
const typeDefaults = V2_DEFAULTS.typeDefaults[contextType] ?? V2_DEFAULTS.typeDefaults.technical
|
|
491
485
|
|
|
492
486
|
const id = memories.insert({
|
|
493
|
-
// Core
|
|
487
|
+
// Core fields
|
|
494
488
|
content: memory.content,
|
|
495
489
|
reasoning: memory.reasoning,
|
|
496
490
|
importance_weight: memory.importance_weight,
|
|
497
491
|
confidence_score: memory.confidence_score,
|
|
498
492
|
context_type: memory.context_type,
|
|
499
|
-
|
|
500
|
-
knowledge_domain: memory.knowledge_domain,
|
|
501
|
-
emotional_resonance: memory.emotional_resonance,
|
|
493
|
+
temporal_class: memory.temporal_class ?? typeDefaults?.temporal_class ?? V2_DEFAULTS.fallback.temporal_class,
|
|
502
494
|
action_required: memory.action_required,
|
|
503
495
|
problem_solution_pair: memory.problem_solution_pair,
|
|
504
496
|
semantic_tags: memory.semantic_tags,
|
|
505
497
|
trigger_phrases: memory.trigger_phrases,
|
|
506
498
|
question_types: memory.question_types,
|
|
499
|
+
anti_triggers: memory.anti_triggers ?? [],
|
|
507
500
|
session_id: sessionId,
|
|
508
501
|
project_id: projectId,
|
|
509
502
|
embedding: embedding
|
|
510
503
|
? (embedding instanceof Float32Array ? embedding : new Float32Array(embedding))
|
|
511
504
|
: null,
|
|
512
505
|
|
|
513
|
-
//
|
|
506
|
+
// Lifecycle fields - use curator-provided values or smart defaults
|
|
514
507
|
status: V2_DEFAULTS.fallback.status,
|
|
515
508
|
scope: memory.scope ?? typeDefaults?.scope ?? V2_DEFAULTS.fallback.scope,
|
|
516
|
-
temporal_class: memory.temporal_class ?? typeDefaults?.temporal_class ?? V2_DEFAULTS.fallback.temporal_class,
|
|
517
509
|
fade_rate: typeDefaults?.fade_rate ?? V2_DEFAULTS.fallback.fade_rate,
|
|
518
510
|
session_created: sessionNumber ?? 0,
|
|
519
511
|
session_updated: sessionNumber ?? 0,
|
|
@@ -523,18 +515,15 @@ export class MemoryStore {
|
|
|
523
515
|
related_files: memory.related_files ?? [],
|
|
524
516
|
awaiting_implementation: memory.awaiting_implementation ?? false,
|
|
525
517
|
awaiting_decision: memory.awaiting_decision ?? false,
|
|
526
|
-
retrieval_weight: memory.importance_weight, // Start with importance as retrieval weight
|
|
527
518
|
exclude_from_retrieval: false,
|
|
528
519
|
schema_version: MEMORY_SCHEMA_VERSION,
|
|
529
520
|
|
|
530
|
-
//
|
|
521
|
+
// Relationship fields
|
|
531
522
|
supersedes: null,
|
|
532
523
|
superseded_by: null,
|
|
533
524
|
related_to: [],
|
|
534
525
|
resolves: [],
|
|
535
526
|
resolved_by: null,
|
|
536
|
-
parent_id: null,
|
|
537
|
-
child_ids: [],
|
|
538
527
|
blocked_by: null,
|
|
539
528
|
blocks: [],
|
|
540
529
|
})
|
|
@@ -555,9 +544,7 @@ export class MemoryStore {
|
|
|
555
544
|
importance_weight: record.importance_weight,
|
|
556
545
|
confidence_score: record.confidence_score,
|
|
557
546
|
context_type: record.context_type as StoredMemory['context_type'],
|
|
558
|
-
|
|
559
|
-
knowledge_domain: record.knowledge_domain as StoredMemory['knowledge_domain'],
|
|
560
|
-
emotional_resonance: record.emotional_resonance as StoredMemory['emotional_resonance'],
|
|
547
|
+
temporal_class: record.temporal_class as StoredMemory['temporal_class'],
|
|
561
548
|
action_required: record.action_required,
|
|
562
549
|
problem_solution_pair: record.problem_solution_pair,
|
|
563
550
|
semantic_tags: record.semantic_tags,
|
|
@@ -595,9 +582,7 @@ export class MemoryStore {
|
|
|
595
582
|
importance_weight: record.importance_weight,
|
|
596
583
|
confidence_score: record.confidence_score,
|
|
597
584
|
context_type: record.context_type as StoredMemory['context_type'],
|
|
598
|
-
|
|
599
|
-
knowledge_domain: record.knowledge_domain as StoredMemory['knowledge_domain'],
|
|
600
|
-
emotional_resonance: record.emotional_resonance as StoredMemory['emotional_resonance'],
|
|
585
|
+
temporal_class: record.temporal_class as StoredMemory['temporal_class'],
|
|
601
586
|
action_required: record.action_required,
|
|
602
587
|
problem_solution_pair: record.problem_solution_pair,
|
|
603
588
|
semantic_tags: record.semantic_tags,
|
|
@@ -619,9 +604,7 @@ export class MemoryStore {
|
|
|
619
604
|
importance_weight: result.record.importance_weight,
|
|
620
605
|
confidence_score: result.record.confidence_score,
|
|
621
606
|
context_type: result.record.context_type as StoredMemory['context_type'],
|
|
622
|
-
|
|
623
|
-
knowledge_domain: result.record.knowledge_domain as StoredMemory['knowledge_domain'],
|
|
624
|
-
emotional_resonance: result.record.emotional_resonance as StoredMemory['emotional_resonance'],
|
|
607
|
+
temporal_class: result.record.temporal_class as StoredMemory['temporal_class'],
|
|
625
608
|
action_required: result.record.action_required,
|
|
626
609
|
problem_solution_pair: result.record.problem_solution_pair,
|
|
627
610
|
semantic_tags: result.record.semantic_tags,
|
|
@@ -743,9 +726,7 @@ export class MemoryStore {
|
|
|
743
726
|
): Promise<string> {
|
|
744
727
|
const { summaries } = await this.getProject(projectId)
|
|
745
728
|
|
|
746
|
-
|
|
747
|
-
console.log(` Summary length: ${summary.length} chars`)
|
|
748
|
-
console.log(` Summaries count before: ${summaries.all().length}`)
|
|
729
|
+
logger.debug(`Storing summary for ${projectId}: ${summary.length} chars`, 'store')
|
|
749
730
|
|
|
750
731
|
const id = summaries.insert({
|
|
751
732
|
session_id: sessionId,
|
|
@@ -754,8 +735,7 @@ export class MemoryStore {
|
|
|
754
735
|
interaction_tone: interactionTone,
|
|
755
736
|
})
|
|
756
737
|
|
|
757
|
-
|
|
758
|
-
console.log(` Inserted ID: ${id}`)
|
|
738
|
+
logger.debug(`Summary stored with ID: ${id}`, 'store')
|
|
759
739
|
|
|
760
740
|
return id
|
|
761
741
|
}
|
|
@@ -766,14 +746,14 @@ export class MemoryStore {
|
|
|
766
746
|
async getLatestSummary(projectId: string): Promise<SessionSummary | null> {
|
|
767
747
|
const { summaries } = await this.getProject(projectId)
|
|
768
748
|
|
|
769
|
-
|
|
749
|
+
logger.debug(`Getting latest summary for ${projectId}`, 'store')
|
|
770
750
|
const all = summaries.all()
|
|
771
|
-
console.log(` Summaries found: ${all.length}`)
|
|
772
751
|
|
|
773
752
|
if (!all.length) {
|
|
774
|
-
|
|
753
|
+
logger.debug(`No summaries found for ${projectId}`, 'store')
|
|
775
754
|
return null
|
|
776
755
|
}
|
|
756
|
+
logger.debug(`Found ${all.length} summaries for ${projectId}`, 'store')
|
|
777
757
|
|
|
778
758
|
// Sort by created timestamp (most recent first)
|
|
779
759
|
const sorted = [...all].sort((a, b) => b.created - a.created)
|
|
@@ -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
|
+
}
|