Smart Contract
CognitiveMemory
A.91d0a5b7c9832a8b.CognitiveMemory
1// CognitiveMemory.cdc
2// Cognitive memory layer for FlowClaw AI agents on Flow.
3// Implements the four biological memory types (episodic, semantic, procedural, self-model),
4// molecular memory bonds for O(k) retrieval, importance scoring, and dream cycle consolidation.
5//
6// Built on top of AgentMemory — this contract adds cognitive structure without
7// replacing the base storage layer. Think of it as the prefrontal cortex
8// sitting on top of the hippocampus.
9//
10// Architecture inspired by:
11// - Stanford Generative Agents (Park et al. 2023) — importance scoring, reflection
12// - CoALA cognitive architecture — episodic/semantic/procedural/self-model split
13// - ByteDance Mole-Syn — molecular memory bonds for graph-based retrieval
14// - Flow advantages: Cadence resources (memories can't be duplicated), native scheduled
15// transactions (dream cycles on-chain), entitlements (fine-grained access control),
16// and XChaCha20 encryption (privacy Solana doesn't have)
17
18import AgentMemory from 0x91d0a5b7c9832a8b
19
20access(all) contract CognitiveMemory {
21
22 // -----------------------------------------------------------------------
23 // Events
24 // -----------------------------------------------------------------------
25 access(all) event CognitiveMemoryStored(
26 memoryId: UInt64,
27 memoryType: UInt8,
28 importance: UInt8,
29 owner: Address
30 )
31 access(all) event BondCreated(
32 fromMemoryId: UInt64,
33 toMemoryId: UInt64,
34 bondType: UInt8,
35 strength: UFix64
36 )
37 access(all) event MoleculeFormed(
38 moleculeId: UInt64,
39 atomCount: UInt64,
40 stability: UFix64,
41 owner: Address
42 )
43 access(all) event DreamCycleCompleted(
44 memoriesConsolidated: UInt64,
45 bondsCreated: UInt64,
46 memoriesPruned: UInt64,
47 owner: Address
48 )
49 access(all) event MemoryPromoted(
50 memoryId: UInt64,
51 fromType: UInt8,
52 toType: UInt8
53 )
54 access(all) event MemoryDecayed(
55 memoryId: UInt64,
56 newStrength: UFix64
57 )
58
59 // -----------------------------------------------------------------------
60 // Paths
61 // -----------------------------------------------------------------------
62 access(all) let CognitiveVaultStoragePath: StoragePath
63
64 // -----------------------------------------------------------------------
65 // Entitlements
66 // -----------------------------------------------------------------------
67 access(all) entitlement Cognize // Store with cognitive metadata
68 access(all) entitlement Bond // Create/modify bonds between memories
69 access(all) entitlement Dream // Run dream cycle consolidation
70 access(all) entitlement Introspect // Read cognitive metadata
71
72 // -----------------------------------------------------------------------
73 // Memory Types — from cognitive science (CoALA framework)
74 // -----------------------------------------------------------------------
75 // 0 = Episodic: "I did X at time T" — events, conversations, experiences
76 // 1 = Semantic: "X means Y" — learned facts, knowledge
77 // 2 = Procedural: "To do X, do Y then Z" — skills, behaviors, workflows
78 // 3 = Self-Model: "I am an agent who..." — identity, beliefs, preferences
79
80 access(all) fun getMemoryTypeName(_ t: UInt8): String {
81 switch t {
82 case 0: return "episodic"
83 case 1: return "semantic"
84 case 2: return "procedural"
85 case 3: return "self-model"
86 default: return "unknown"
87 }
88 }
89
90 // -----------------------------------------------------------------------
91 // Bond Types — molecular connections between memories (Mole-Syn inspired)
92 // -----------------------------------------------------------------------
93 // 0 = Causal: "this led to that" — cause and effect chains
94 // 1 = Semantic: "these are related concepts" — topic/meaning similarity
95 // 2 = Temporal: "these happened together" — co-occurring in time
96 // 3 = Contradictory: "these conflict" — opposing information
97
98 access(all) fun getBondTypeName(_ t: UInt8): String {
99 switch t {
100 case 0: return "causal"
101 case 1: return "semantic"
102 case 2: return "temporal"
103 case 3: return "contradictory"
104 default: return "unknown"
105 }
106 }
107
108 // -----------------------------------------------------------------------
109 // Decay rates per memory type (% per day, scaled as UFix64)
110 // Episodic fades fast unless reinforced. Identity persists.
111 // -----------------------------------------------------------------------
112 access(all) fun getDecayRate(_ memoryType: UInt8): UFix64 {
113 switch memoryType {
114 case 0: return 0.07 // Episodic: 7% per day
115 case 1: return 0.02 // Semantic: 2% per day
116 case 2: return 0.03 // Procedural: 3% per day
117 case 3: return 0.01 // Self-Model: 1% per day
118 default: return 0.05
119 }
120 }
121
122 // -----------------------------------------------------------------------
123 // CognitiveEntry — cognitive metadata layered on top of AgentMemory.MemoryEntry
124 // -----------------------------------------------------------------------
125 access(all) struct CognitiveEntry {
126 access(all) let memoryId: UInt64 // References AgentMemory entry ID
127 access(all) let memoryType: UInt8 // 0=episodic, 1=semantic, 2=procedural, 3=self-model
128 access(all) let importance: UInt8 // 1-10 scale (Stanford Generative Agents)
129 access(all) let strength: UFix64 // Current strength after decay (0.0 - 1.0)
130 access(all) let emotionalWeight: UInt8 // 1-10, how emotionally significant
131 access(all) let moleculeId: UInt64 // 0 if unassigned, else which molecule cluster
132 access(all) let bondCount: UInt64 // Number of bonds this memory has
133 access(all) let promotedFrom: UInt8 // Original type if promoted (255 = never promoted)
134 access(all) let lastDecayAt: UFix64 // Timestamp of last decay calculation
135 access(all) let createdAt: UFix64
136
137 init(
138 memoryId: UInt64,
139 memoryType: UInt8,
140 importance: UInt8,
141 strength: UFix64,
142 emotionalWeight: UInt8,
143 moleculeId: UInt64,
144 bondCount: UInt64,
145 promotedFrom: UInt8,
146 lastDecayAt: UFix64,
147 createdAt: UFix64
148 ) {
149 pre {
150 memoryType <= 3: "Invalid memory type"
151 importance >= 1 && importance <= 10: "Importance must be 1-10"
152 emotionalWeight >= 1 && emotionalWeight <= 10: "Emotional weight must be 1-10"
153 strength >= 0.0 && strength <= 1.0: "Strength must be 0.0-1.0"
154 }
155 self.memoryId = memoryId
156 self.memoryType = memoryType
157 self.importance = importance
158 self.strength = strength
159 self.emotionalWeight = emotionalWeight
160 self.moleculeId = moleculeId
161 self.bondCount = bondCount
162 self.promotedFrom = promotedFrom
163 self.lastDecayAt = lastDecayAt
164 self.createdAt = createdAt
165 }
166 }
167
168 // -----------------------------------------------------------------------
169 // MemoryBond — typed relationship between two memories
170 // -----------------------------------------------------------------------
171 access(all) struct MemoryBond {
172 access(all) let fromMemoryId: UInt64
173 access(all) let toMemoryId: UInt64
174 access(all) let bondType: UInt8 // 0=causal, 1=semantic, 2=temporal, 3=contradictory
175 access(all) let strength: UFix64 // 0.0 - 1.0 (how strong the connection)
176 access(all) let createdAt: UFix64
177
178 init(
179 fromMemoryId: UInt64,
180 toMemoryId: UInt64,
181 bondType: UInt8,
182 strength: UFix64,
183 createdAt: UFix64
184 ) {
185 pre {
186 bondType <= 3: "Invalid bond type"
187 strength >= 0.0 && strength <= 1.0: "Bond strength must be 0.0-1.0"
188 fromMemoryId != toMemoryId: "Cannot bond memory to itself"
189 }
190 self.fromMemoryId = fromMemoryId
191 self.toMemoryId = toMemoryId
192 self.bondType = bondType
193 self.strength = strength
194 self.createdAt = createdAt
195 }
196 }
197
198 // -----------------------------------------------------------------------
199 // Molecule — stable cluster of bonded memories
200 // -----------------------------------------------------------------------
201 access(all) struct Molecule {
202 access(all) let id: UInt64
203 access(all) let atomIds: [UInt64] // Memory IDs in this molecule
204 access(all) let stability: UFix64 // 0.0 - 1.0 (higher = more stable, resists pruning)
205 access(all) let topic: String // Primary topic/label
206 access(all) let bondCount: UInt64 // Total internal bonds
207 access(all) let createdAt: UFix64
208 access(all) let lastConsolidatedAt: UFix64
209
210 init(
211 id: UInt64,
212 atomIds: [UInt64],
213 stability: UFix64,
214 topic: String,
215 bondCount: UInt64,
216 createdAt: UFix64,
217 lastConsolidatedAt: UFix64
218 ) {
219 self.id = id
220 self.atomIds = atomIds
221 self.stability = stability
222 self.topic = topic
223 self.bondCount = bondCount
224 self.createdAt = createdAt
225 self.lastConsolidatedAt = lastConsolidatedAt
226 }
227 }
228
229 // -----------------------------------------------------------------------
230 // DreamCycleResult — output of a consolidation cycle
231 // -----------------------------------------------------------------------
232 access(all) struct DreamCycleResult {
233 access(all) let memoriesConsolidated: UInt64
234 access(all) let bondsCreated: UInt64
235 access(all) let memoriesPruned: UInt64
236 access(all) let moleculesFormed: UInt64
237 access(all) let promotions: UInt64
238 access(all) let timestamp: UFix64
239
240 init(
241 memoriesConsolidated: UInt64,
242 bondsCreated: UInt64,
243 memoriesPruned: UInt64,
244 moleculesFormed: UInt64,
245 promotions: UInt64,
246 timestamp: UFix64
247 ) {
248 self.memoriesConsolidated = memoriesConsolidated
249 self.bondsCreated = bondsCreated
250 self.memoriesPruned = memoriesPruned
251 self.moleculesFormed = moleculesFormed
252 self.promotions = promotions
253 self.timestamp = timestamp
254 }
255 }
256
257 // -----------------------------------------------------------------------
258 // CognitiveVault — the cognitive layer resource
259 // -----------------------------------------------------------------------
260 access(all) resource CognitiveVault {
261 // Cognitive metadata indexed by AgentMemory entry ID
262 access(self) var entries: {UInt64: CognitiveEntry}
263
264 // Bond graph: memory ID → array of bonds FROM this memory
265 access(self) var bonds: {UInt64: [MemoryBond]}
266
267 // Reverse bond index: memory ID → array of memory IDs that bond TO it
268 access(self) var reverseBonds: {UInt64: [UInt64]}
269
270 // Molecules: cluster ID → Molecule
271 access(self) var molecules: {UInt64: Molecule}
272
273 // Type index: memory type → [memory IDs] for fast type-based queries
274 access(self) var typeIndex: {UInt8: [UInt64]}
275
276 // Dream cycle history
277 access(self) var dreamHistory: [DreamCycleResult]
278
279 // Counters
280 access(self) var moleculeCounter: UInt64
281 access(all) var totalCognitiveEntries: UInt64
282 access(all) var totalBonds: UInt64
283 access(all) var totalMolecules: UInt64
284 access(all) var lastDreamCycleAt: UFix64
285
286 init() {
287 self.entries = {}
288 self.bonds = {}
289 self.reverseBonds = {}
290 self.molecules = {}
291 self.typeIndex = {0: [], 1: [], 2: [], 3: []}
292 self.dreamHistory = []
293 self.moleculeCounter = 0
294 self.totalCognitiveEntries = 0
295 self.totalBonds = 0
296 self.totalMolecules = 0
297 self.lastDreamCycleAt = 0.0
298 }
299
300 // ---------------------------------------------------------------
301 // Cognize: Store cognitive metadata for a memory
302 // ---------------------------------------------------------------
303 access(Cognize) fun storeCognitive(
304 memoryId: UInt64,
305 memoryType: UInt8,
306 importance: UInt8,
307 emotionalWeight: UInt8
308 ) {
309 let now = getCurrentBlock().timestamp
310
311 let entry = CognitiveEntry(
312 memoryId: memoryId,
313 memoryType: memoryType,
314 importance: importance,
315 strength: 1.0, // Starts at full strength
316 emotionalWeight: emotionalWeight,
317 moleculeId: 0, // Unassigned
318 bondCount: 0,
319 promotedFrom: 255, // Never promoted
320 lastDecayAt: now,
321 createdAt: now
322 )
323
324 self.entries[memoryId] = entry
325
326 // Update type index
327 if self.typeIndex[memoryType] == nil {
328 self.typeIndex[memoryType] = [memoryId]
329 } else {
330 self.typeIndex[memoryType]!.append(memoryId)
331 }
332
333 self.totalCognitiveEntries = self.totalCognitiveEntries + 1
334
335 emit CognitiveMemoryStored(
336 memoryId: memoryId,
337 memoryType: memoryType,
338 importance: importance,
339 owner: self.owner!.address
340 )
341 }
342
343 // ---------------------------------------------------------------
344 // Bond: Create a typed bond between two memories
345 // ---------------------------------------------------------------
346 access(Bond) fun createBond(
347 fromMemoryId: UInt64,
348 toMemoryId: UInt64,
349 bondType: UInt8,
350 strength: UFix64
351 ) {
352 pre {
353 self.entries[fromMemoryId] != nil: "Source memory not in cognitive vault"
354 self.entries[toMemoryId] != nil: "Target memory not in cognitive vault"
355 }
356
357 let now = getCurrentBlock().timestamp
358
359 let bond = MemoryBond(
360 fromMemoryId: fromMemoryId,
361 toMemoryId: toMemoryId,
362 bondType: bondType,
363 strength: strength,
364 createdAt: now
365 )
366
367 // Forward bond
368 if self.bonds[fromMemoryId] == nil {
369 self.bonds[fromMemoryId] = [bond]
370 } else {
371 // Check max bonds per memory (10, as recommended)
372 if self.bonds[fromMemoryId]!.length < 10 {
373 self.bonds[fromMemoryId]!.append(bond)
374 }
375 }
376
377 // Reverse index
378 if self.reverseBonds[toMemoryId] == nil {
379 self.reverseBonds[toMemoryId] = [fromMemoryId]
380 } else {
381 self.reverseBonds[toMemoryId]!.append(fromMemoryId)
382 }
383
384 // Update bond counts on cognitive entries
385 if let fromEntry = self.entries[fromMemoryId] {
386 self.entries[fromMemoryId] = CognitiveEntry(
387 memoryId: fromEntry.memoryId,
388 memoryType: fromEntry.memoryType,
389 importance: fromEntry.importance,
390 strength: fromEntry.strength,
391 emotionalWeight: fromEntry.emotionalWeight,
392 moleculeId: fromEntry.moleculeId,
393 bondCount: fromEntry.bondCount + 1,
394 promotedFrom: fromEntry.promotedFrom,
395 lastDecayAt: fromEntry.lastDecayAt,
396 createdAt: fromEntry.createdAt
397 )
398 }
399
400 self.totalBonds = self.totalBonds + 1
401
402 emit BondCreated(
403 fromMemoryId: fromMemoryId,
404 toMemoryId: toMemoryId,
405 bondType: bondType,
406 strength: strength
407 )
408 }
409
410 // ---------------------------------------------------------------
411 // Molecular Retrieval: traverse bonds from a seed memory
412 // Returns the molecule cluster — semantically coherent group
413 // O(k) where k = avg bonds per memory (~3-5)
414 // ---------------------------------------------------------------
415 access(Introspect) fun getMolecularCluster(
416 seedMemoryId: UInt64,
417 maxDepth: UInt8
418 ): [UInt64] {
419 var visited: {UInt64: Bool} = {}
420 var result: [UInt64] = []
421 var queue: [UInt64] = [seedMemoryId]
422 var depth: UInt8 = 0
423
424 while queue.length > 0 && depth < maxDepth {
425 var nextQueue: [UInt64] = []
426
427 for memId in queue {
428 if visited[memId] != nil {
429 continue
430 }
431 visited[memId] = true
432 result.append(memId)
433
434 // Traverse forward bonds
435 if let memBonds = self.bonds[memId] {
436 for bond in memBonds {
437 if visited[bond.toMemoryId] == nil {
438 nextQueue.append(bond.toMemoryId)
439 }
440 }
441 }
442
443 // Traverse reverse bonds
444 if let revBonds = self.reverseBonds[memId] {
445 for fromId in revBonds {
446 if visited[fromId] == nil {
447 nextQueue.append(fromId)
448 }
449 }
450 }
451 }
452
453 queue = nextQueue
454 depth = depth + 1
455 }
456
457 return result
458 }
459
460 // ---------------------------------------------------------------
461 // Introspect: Read cognitive metadata
462 // ---------------------------------------------------------------
463 access(Introspect) fun getCognitive(memoryId: UInt64): CognitiveEntry? {
464 return self.entries[memoryId]
465 }
466
467 access(Introspect) fun getByType(memoryType: UInt8): [UInt64] {
468 return self.typeIndex[memoryType] ?? []
469 }
470
471 access(Introspect) fun getBonds(memoryId: UInt64): [MemoryBond] {
472 return self.bonds[memoryId] ?? []
473 }
474
475 access(Introspect) fun getMolecule(moleculeId: UInt64): Molecule? {
476 return self.molecules[moleculeId]
477 }
478
479 access(Introspect) fun getAllMolecules(): [Molecule] {
480 var result: [Molecule] = []
481 for id in self.molecules.keys {
482 if let mol = self.molecules[id] {
483 result.append(mol)
484 }
485 }
486 return result
487 }
488
489 access(Introspect) fun getAllCognitiveEntries(): [CognitiveEntry] {
490 var result: [CognitiveEntry] = []
491 for id in self.entries.keys {
492 if let entry = self.entries[id] {
493 result.append(entry)
494 }
495 }
496 return result
497 }
498
499 access(Introspect) fun getDreamHistory(): [DreamCycleResult] {
500 return self.dreamHistory
501 }
502
503 // ---------------------------------------------------------------
504 // Dream Cycle: Consolidation, decay, promotion, pruning
505 // This is the "sleep" phase — called periodically to maintain
506 // memory health. On Flow, this can be triggered by scheduled tx.
507 // ---------------------------------------------------------------
508 access(Dream) fun runDreamCycle(
509 decayThreshold: UFix64,
510 promotionThreshold: UInt64
511 ): DreamCycleResult {
512 let now = getCurrentBlock().timestamp
513 var consolidated: UInt64 = 0
514 var bondsCreated: UInt64 = 0
515 var pruned: UInt64 = 0
516 var moleculesFormed: UInt64 = 0
517 var promotions: UInt64 = 0
518
519 // --- Phase 1: Decay ---
520 // Apply time-based decay to all memories based on type
521 let memoryIds = self.entries.keys
522 var toRemove: [UInt64] = []
523
524 for memId in memoryIds {
525 if let entry = self.entries[memId] {
526 let decayRate = CognitiveMemory.getDecayRate(entry.memoryType)
527 let daysSinceLastDecay = (now - entry.lastDecayAt) / 86400.0
528
529 if daysSinceLastDecay > 0.0 {
530 // Apply decay: strength = strength * (1 - decayRate)^days
531 // Simplified on-chain: strength -= decayRate * days
532 var newStrength = entry.strength - (decayRate * daysSinceLastDecay)
533
534 // Bond-based retention: connected memories decay slower
535 // Each bond adds 10% decay resistance
536 if entry.bondCount > 0 {
537 let bondBonus = UFix64(entry.bondCount) * 0.1
538 let retained = decayRate * daysSinceLastDecay * (bondBonus > 1.0 ? 1.0 : bondBonus)
539 newStrength = newStrength + retained
540 }
541
542 // Importance-based retention
543 if entry.importance >= 8 {
544 newStrength = newStrength + (decayRate * daysSinceLastDecay * 0.5)
545 }
546
547 // Clamp
548 if newStrength < 0.0 {
549 newStrength = 0.0
550 }
551 if newStrength > 1.0 {
552 newStrength = 1.0
553 }
554
555 // Update entry
556 self.entries[memId] = CognitiveEntry(
557 memoryId: entry.memoryId,
558 memoryType: entry.memoryType,
559 importance: entry.importance,
560 strength: newStrength,
561 emotionalWeight: entry.emotionalWeight,
562 moleculeId: entry.moleculeId,
563 bondCount: entry.bondCount,
564 promotedFrom: entry.promotedFrom,
565 lastDecayAt: now,
566 createdAt: entry.createdAt
567 )
568
569 consolidated = consolidated + 1
570
571 // Mark for pruning if below threshold and isolated
572 if newStrength < decayThreshold && entry.bondCount == 0 {
573 toRemove.append(memId)
574 }
575
576 emit MemoryDecayed(memoryId: memId, newStrength: newStrength)
577 }
578 }
579 }
580
581 // --- Phase 2: Prune isolated weak memories ---
582 for memId in toRemove {
583 if let entry = self.entries[memId] {
584 // Remove from type index
585 if var typeIds = self.typeIndex[entry.memoryType] {
586 var newIds: [UInt64] = []
587 for id in typeIds {
588 if id != memId {
589 newIds.append(id)
590 }
591 }
592 self.typeIndex[entry.memoryType] = newIds
593 }
594 self.entries.remove(key: memId)
595 self.totalCognitiveEntries = self.totalCognitiveEntries - 1
596 pruned = pruned + 1
597 }
598 }
599
600 // --- Phase 3: Auto-molecule detection ---
601 // Find densely connected memory clusters that aren't yet in a molecule
602 for memId in self.entries.keys {
603 if let entry = self.entries[memId] {
604 if entry.moleculeId == 0 && entry.bondCount >= 2 {
605 // This memory has bonds but no molecule — try to form one
606 let cluster = self.getMolecularCluster(seedMemoryId: memId, maxDepth: 2)
607 if cluster.length >= 3 {
608 // Form a new molecule
609 self.moleculeCounter = self.moleculeCounter + 1
610 let molId = self.moleculeCounter
611
612 // Count internal bonds
613 var internalBonds: UInt64 = 0
614 for atomId in cluster {
615 if let atomBonds = self.bonds[atomId] {
616 for bond in atomBonds {
617 // Check if target is in cluster
618 for targetId in cluster {
619 if bond.toMemoryId == targetId {
620 internalBonds = internalBonds + 1
621 }
622 }
623 }
624 }
625 }
626
627 // Stability = internal bonds / (atoms * max_bonds_per_atom)
628 let maxPossible = UFix64(cluster.length) * 10.0
629 let stability = maxPossible > 0.0
630 ? UFix64(internalBonds) / maxPossible
631 : 0.0
632
633 let molecule = Molecule(
634 id: molId,
635 atomIds: cluster,
636 stability: stability > 1.0 ? 1.0 : stability,
637 topic: "", // Set by relay after analysis
638 bondCount: internalBonds,
639 createdAt: now,
640 lastConsolidatedAt: now
641 )
642
643 self.molecules[molId] = molecule
644 self.totalMolecules = self.totalMolecules + 1
645 moleculesFormed = moleculesFormed + 1
646
647 // Assign molecule ID to all atoms
648 for atomId in cluster {
649 if let atom = self.entries[atomId] {
650 self.entries[atomId] = CognitiveEntry(
651 memoryId: atom.memoryId,
652 memoryType: atom.memoryType,
653 importance: atom.importance,
654 strength: atom.strength,
655 emotionalWeight: atom.emotionalWeight,
656 moleculeId: molId,
657 bondCount: atom.bondCount,
658 promotedFrom: atom.promotedFrom,
659 lastDecayAt: atom.lastDecayAt,
660 createdAt: atom.createdAt
661 )
662 }
663 }
664
665 emit MoleculeFormed(
666 moleculeId: molId,
667 atomCount: UInt64(cluster.length),
668 stability: stability > 1.0 ? 1.0 : stability,
669 owner: self.owner!.address
670 )
671 }
672 }
673 }
674 }
675
676 // --- Phase 4: Promotion detection ---
677 // If multiple episodic memories share tags/keys, promote to semantic
678 // (This is done primarily in the relay with LLM analysis,
679 // but we track the promotion on-chain)
680
681 let result = DreamCycleResult(
682 memoriesConsolidated: consolidated,
683 bondsCreated: bondsCreated,
684 memoriesPruned: pruned,
685 moleculesFormed: moleculesFormed,
686 promotions: promotions,
687 timestamp: now
688 )
689
690 self.dreamHistory.append(result)
691 self.lastDreamCycleAt = now
692
693 emit DreamCycleCompleted(
694 memoriesConsolidated: consolidated,
695 bondsCreated: bondsCreated,
696 memoriesPruned: pruned,
697 owner: self.owner!.address
698 )
699
700 return result
701 }
702
703 // ---------------------------------------------------------------
704 // Promote: Change a memory's type (episodic → semantic, etc.)
705 // Called by relay when patterns are detected
706 // ---------------------------------------------------------------
707 access(Dream) fun promoteMemory(
708 memoryId: UInt64,
709 newType: UInt8,
710 newImportance: UInt8
711 ) {
712 pre {
713 self.entries[memoryId] != nil: "Memory not found"
714 newType <= 3: "Invalid memory type"
715 }
716
717 if let entry = self.entries[memoryId] {
718 let oldType = entry.memoryType
719
720 // Remove from old type index
721 if var typeIds = self.typeIndex[oldType] {
722 var newIds: [UInt64] = []
723 for id in typeIds {
724 if id != memoryId {
725 newIds.append(id)
726 }
727 }
728 self.typeIndex[oldType] = newIds
729 }
730
731 // Add to new type index
732 if self.typeIndex[newType] == nil {
733 self.typeIndex[newType] = [memoryId]
734 } else {
735 self.typeIndex[newType]!.append(memoryId)
736 }
737
738 // Update entry
739 self.entries[memoryId] = CognitiveEntry(
740 memoryId: entry.memoryId,
741 memoryType: newType,
742 importance: newImportance,
743 strength: 1.0, // Reset strength on promotion
744 emotionalWeight: entry.emotionalWeight,
745 moleculeId: entry.moleculeId,
746 bondCount: entry.bondCount,
747 promotedFrom: oldType,
748 lastDecayAt: getCurrentBlock().timestamp,
749 createdAt: entry.createdAt
750 )
751
752 emit MemoryPromoted(
753 memoryId: memoryId,
754 fromType: oldType,
755 toType: newType
756 )
757 }
758 }
759 }
760
761 // -----------------------------------------------------------------------
762 // Public factory
763 // -----------------------------------------------------------------------
764 access(all) fun createCognitiveVault(): @CognitiveVault {
765 return <- create CognitiveVault()
766 }
767
768 // -----------------------------------------------------------------------
769 // Init
770 // -----------------------------------------------------------------------
771 init() {
772 self.CognitiveVaultStoragePath = /storage/FlowClawCognitiveVault
773 }
774}
775