alma-memory 0.5.0__py3-none-any.whl → 0.7.0__py3-none-any.whl

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.
Files changed (111) hide show
  1. alma/__init__.py +296 -194
  2. alma/compression/__init__.py +33 -0
  3. alma/compression/pipeline.py +980 -0
  4. alma/confidence/__init__.py +47 -47
  5. alma/confidence/engine.py +540 -540
  6. alma/confidence/types.py +351 -351
  7. alma/config/loader.py +157 -157
  8. alma/consolidation/__init__.py +23 -23
  9. alma/consolidation/engine.py +678 -678
  10. alma/consolidation/prompts.py +84 -84
  11. alma/core.py +1189 -322
  12. alma/domains/__init__.py +30 -30
  13. alma/domains/factory.py +359 -359
  14. alma/domains/schemas.py +448 -448
  15. alma/domains/types.py +272 -272
  16. alma/events/__init__.py +75 -75
  17. alma/events/emitter.py +285 -284
  18. alma/events/storage_mixin.py +246 -246
  19. alma/events/types.py +126 -126
  20. alma/events/webhook.py +425 -425
  21. alma/exceptions.py +49 -49
  22. alma/extraction/__init__.py +31 -31
  23. alma/extraction/auto_learner.py +265 -264
  24. alma/extraction/extractor.py +420 -420
  25. alma/graph/__init__.py +106 -81
  26. alma/graph/backends/__init__.py +32 -18
  27. alma/graph/backends/kuzu.py +624 -0
  28. alma/graph/backends/memgraph.py +432 -0
  29. alma/graph/backends/memory.py +236 -236
  30. alma/graph/backends/neo4j.py +417 -417
  31. alma/graph/base.py +159 -159
  32. alma/graph/extraction.py +198 -198
  33. alma/graph/store.py +860 -860
  34. alma/harness/__init__.py +35 -35
  35. alma/harness/base.py +386 -386
  36. alma/harness/domains.py +705 -705
  37. alma/initializer/__init__.py +37 -37
  38. alma/initializer/initializer.py +418 -418
  39. alma/initializer/types.py +250 -250
  40. alma/integration/__init__.py +62 -62
  41. alma/integration/claude_agents.py +444 -432
  42. alma/integration/helena.py +423 -423
  43. alma/integration/victor.py +471 -471
  44. alma/learning/__init__.py +101 -86
  45. alma/learning/decay.py +878 -0
  46. alma/learning/forgetting.py +1446 -1446
  47. alma/learning/heuristic_extractor.py +390 -390
  48. alma/learning/protocols.py +374 -374
  49. alma/learning/validation.py +346 -346
  50. alma/mcp/__init__.py +123 -45
  51. alma/mcp/__main__.py +156 -156
  52. alma/mcp/resources.py +122 -122
  53. alma/mcp/server.py +955 -591
  54. alma/mcp/tools.py +3254 -511
  55. alma/observability/__init__.py +91 -0
  56. alma/observability/config.py +302 -0
  57. alma/observability/guidelines.py +170 -0
  58. alma/observability/logging.py +424 -0
  59. alma/observability/metrics.py +583 -0
  60. alma/observability/tracing.py +440 -0
  61. alma/progress/__init__.py +21 -21
  62. alma/progress/tracker.py +607 -607
  63. alma/progress/types.py +250 -250
  64. alma/retrieval/__init__.py +134 -53
  65. alma/retrieval/budget.py +525 -0
  66. alma/retrieval/cache.py +1304 -1061
  67. alma/retrieval/embeddings.py +202 -202
  68. alma/retrieval/engine.py +850 -366
  69. alma/retrieval/modes.py +365 -0
  70. alma/retrieval/progressive.py +560 -0
  71. alma/retrieval/scoring.py +344 -344
  72. alma/retrieval/trust_scoring.py +637 -0
  73. alma/retrieval/verification.py +797 -0
  74. alma/session/__init__.py +19 -19
  75. alma/session/manager.py +442 -399
  76. alma/session/types.py +288 -288
  77. alma/storage/__init__.py +101 -61
  78. alma/storage/archive.py +233 -0
  79. alma/storage/azure_cosmos.py +1259 -1048
  80. alma/storage/base.py +1083 -525
  81. alma/storage/chroma.py +1443 -1443
  82. alma/storage/constants.py +103 -0
  83. alma/storage/file_based.py +614 -619
  84. alma/storage/migrations/__init__.py +21 -0
  85. alma/storage/migrations/base.py +321 -0
  86. alma/storage/migrations/runner.py +323 -0
  87. alma/storage/migrations/version_stores.py +337 -0
  88. alma/storage/migrations/versions/__init__.py +11 -0
  89. alma/storage/migrations/versions/v1_0_0.py +373 -0
  90. alma/storage/migrations/versions/v1_1_0_workflow_context.py +551 -0
  91. alma/storage/pinecone.py +1080 -1080
  92. alma/storage/postgresql.py +1948 -1452
  93. alma/storage/qdrant.py +1306 -1306
  94. alma/storage/sqlite_local.py +3041 -1358
  95. alma/testing/__init__.py +46 -0
  96. alma/testing/factories.py +301 -0
  97. alma/testing/mocks.py +389 -0
  98. alma/types.py +292 -264
  99. alma/utils/__init__.py +19 -0
  100. alma/utils/tokenizer.py +521 -0
  101. alma/workflow/__init__.py +83 -0
  102. alma/workflow/artifacts.py +170 -0
  103. alma/workflow/checkpoint.py +311 -0
  104. alma/workflow/context.py +228 -0
  105. alma/workflow/outcomes.py +189 -0
  106. alma/workflow/reducers.py +393 -0
  107. {alma_memory-0.5.0.dist-info → alma_memory-0.7.0.dist-info}/METADATA +244 -72
  108. alma_memory-0.7.0.dist-info/RECORD +112 -0
  109. alma_memory-0.5.0.dist-info/RECORD +0 -76
  110. {alma_memory-0.5.0.dist-info → alma_memory-0.7.0.dist-info}/WHEEL +0 -0
  111. {alma_memory-0.5.0.dist-info → alma_memory-0.7.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,637 @@
1
+ """
2
+ ALMA Trust-Integrated Scoring.
3
+
4
+ Extends memory scoring to incorporate trust patterns from agent behavior.
5
+ Based on Veritas trust evolution concepts:
6
+ - Trust decays without activity
7
+ - Per-behavior trust tracking
8
+ - Cross-session trust persistence
9
+
10
+ Features:
11
+ - Trust-weighted scoring for memories from different sources
12
+ - Agent trust profile integration
13
+ - Trust pattern storage and retrieval
14
+ - Violation-aware scoring (anti-patterns from violations)
15
+ """
16
+
17
+ import logging
18
+ import math
19
+ from dataclasses import dataclass, field
20
+ from datetime import datetime, timezone
21
+ from typing import Any, Dict, List, Optional
22
+
23
+ from alma.retrieval.scoring import MemoryScorer, ScoredItem, ScoringWeights
24
+ from alma.types import (
25
+ AntiPattern,
26
+ Heuristic,
27
+ MemorySlice,
28
+ Outcome,
29
+ )
30
+
31
+ logger = logging.getLogger(__name__)
32
+
33
+
34
+ class TrustLevel:
35
+ """Trust level constants matching Veritas framework."""
36
+
37
+ UNTRUSTED = 0.0
38
+ MINIMAL = 0.2
39
+ LOW = 0.4
40
+ MODERATE = 0.5
41
+ GOOD = 0.7
42
+ HIGH = 0.85
43
+ FULL = 1.0
44
+
45
+ @classmethod
46
+ def label(cls, score: float) -> str:
47
+ """Get human-readable label for trust score."""
48
+ if score >= cls.FULL:
49
+ return "FULL"
50
+ elif score >= cls.HIGH:
51
+ return "HIGH"
52
+ elif score >= cls.GOOD:
53
+ return "GOOD"
54
+ elif score >= cls.MODERATE:
55
+ return "MODERATE"
56
+ elif score >= cls.LOW:
57
+ return "LOW"
58
+ elif score >= cls.MINIMAL:
59
+ return "MINIMAL"
60
+ return "UNTRUSTED"
61
+
62
+
63
+ @dataclass
64
+ class TrustWeights(ScoringWeights):
65
+ """
66
+ Extended scoring weights that include trust factor.
67
+
68
+ Extends base ScoringWeights with trust component.
69
+ All weights are normalized to sum to 1.0.
70
+ """
71
+
72
+ # Inherited from ScoringWeights
73
+ similarity: float = 0.35
74
+ recency: float = 0.25
75
+ success_rate: float = 0.15
76
+ confidence: float = 0.10
77
+
78
+ # Trust factor
79
+ trust: float = 0.15 # Agent/source trust score
80
+
81
+ def __post_init__(self):
82
+ """Validate and normalize weights."""
83
+ total = (
84
+ self.similarity
85
+ + self.recency
86
+ + self.success_rate
87
+ + self.confidence
88
+ + self.trust
89
+ )
90
+ if not (0.99 <= total <= 1.01):
91
+ # Normalize
92
+ self.similarity /= total
93
+ self.recency /= total
94
+ self.success_rate /= total
95
+ self.confidence /= total
96
+ self.trust /= total
97
+
98
+
99
+ @dataclass
100
+ class AgentTrustProfile:
101
+ """
102
+ Trust profile for an agent, stored in ALMA memory.
103
+
104
+ Tracks trust metrics that influence memory scoring.
105
+ """
106
+
107
+ agent_id: str
108
+ current_trust: float = TrustLevel.MODERATE
109
+ sessions_completed: int = 0
110
+ total_actions: int = 0
111
+ total_violations: int = 0
112
+ consecutive_clean_sessions: int = 0
113
+ last_session: Optional[datetime] = None
114
+ trust_half_life_days: int = 30
115
+
116
+ # Per-behavior trust scores
117
+ behavior_trust: Dict[str, float] = field(
118
+ default_factory=lambda: {
119
+ "verification_before_claim": 1.0,
120
+ "loud_failure": 1.0,
121
+ "honest_uncertainty": 1.0,
122
+ "paper_trail": 1.0,
123
+ "diligent_execution": 1.0,
124
+ }
125
+ )
126
+
127
+ def calculate_trust(self) -> float:
128
+ """Calculate current trust with decay."""
129
+ if self.sessions_completed == 0:
130
+ return TrustLevel.MODERATE
131
+
132
+ # Performance factor
133
+ if self.total_actions > 0:
134
+ performance = 1.0 - (self.total_violations / self.total_actions)
135
+ else:
136
+ performance = TrustLevel.MODERATE
137
+
138
+ # Behavior average
139
+ behavior_avg = (
140
+ sum(self.behavior_trust.values()) / len(self.behavior_trust)
141
+ if self.behavior_trust
142
+ else 1.0
143
+ )
144
+
145
+ # Time decay
146
+ decay = self._calculate_decay()
147
+
148
+ # Streak bonus/penalty
149
+ streak_bonus = min(0.1, self.consecutive_clean_sessions * 0.02)
150
+
151
+ # Combine
152
+ raw_trust = performance * 0.4 + behavior_avg * 0.4 + TrustLevel.MODERATE * 0.2
153
+ self.current_trust = max(0.0, min(1.0, raw_trust * decay + streak_bonus))
154
+
155
+ return self.current_trust
156
+
157
+ def _calculate_decay(self) -> float:
158
+ """Calculate trust decay based on time since last session."""
159
+ if not self.last_session:
160
+ return 1.0
161
+
162
+ now = datetime.now(timezone.utc)
163
+ if self.last_session.tzinfo is None:
164
+ last = self.last_session.replace(tzinfo=timezone.utc)
165
+ else:
166
+ last = self.last_session
167
+
168
+ days_since = (now - last).total_seconds() / (24 * 60 * 60)
169
+ decay = math.exp(-0.693 * days_since / self.trust_half_life_days)
170
+ return max(0.5, decay)
171
+
172
+ def to_dict(self) -> Dict[str, Any]:
173
+ """Convert to dictionary for storage."""
174
+ return {
175
+ "agent_id": self.agent_id,
176
+ "current_trust": self.current_trust,
177
+ "sessions_completed": self.sessions_completed,
178
+ "total_actions": self.total_actions,
179
+ "total_violations": self.total_violations,
180
+ "consecutive_clean_sessions": self.consecutive_clean_sessions,
181
+ "last_session": self.last_session.isoformat()
182
+ if self.last_session
183
+ else None,
184
+ "trust_half_life_days": self.trust_half_life_days,
185
+ "behavior_trust": self.behavior_trust,
186
+ }
187
+
188
+ @classmethod
189
+ def from_dict(cls, data: Dict[str, Any]) -> "AgentTrustProfile":
190
+ """Create from dictionary."""
191
+ last_session = data.get("last_session")
192
+ if isinstance(last_session, str):
193
+ last_session = datetime.fromisoformat(last_session)
194
+
195
+ return cls(
196
+ agent_id=data["agent_id"],
197
+ current_trust=data.get("current_trust", TrustLevel.MODERATE),
198
+ sessions_completed=data.get("sessions_completed", 0),
199
+ total_actions=data.get("total_actions", 0),
200
+ total_violations=data.get("total_violations", 0),
201
+ consecutive_clean_sessions=data.get("consecutive_clean_sessions", 0),
202
+ last_session=last_session,
203
+ trust_half_life_days=data.get("trust_half_life_days", 30),
204
+ behavior_trust=data.get("behavior_trust", {}),
205
+ )
206
+
207
+
208
+ @dataclass
209
+ class TrustScoredItem(ScoredItem):
210
+ """Extended scored item with trust information."""
211
+
212
+ trust_score: float = 1.0
213
+ source_agent: Optional[str] = None
214
+ trust_level: str = "MODERATE"
215
+
216
+
217
+ @dataclass
218
+ class AgentTrustContext:
219
+ """
220
+ Lightweight trust context for passing to scoring functions.
221
+
222
+ Distinct from AgentTrustProfile - this is a simplified view
223
+ used during retrieval operations.
224
+ """
225
+
226
+ agent_id: str
227
+ trust_score: float = TrustLevel.MODERATE
228
+ trust_behaviors: Dict[str, float] = field(default_factory=dict)
229
+
230
+ @classmethod
231
+ def from_profile(cls, profile: AgentTrustProfile) -> "AgentTrustContext":
232
+ """Create context from full profile."""
233
+ return cls(
234
+ agent_id=profile.agent_id,
235
+ trust_score=profile.current_trust,
236
+ trust_behaviors=dict(profile.behavior_trust),
237
+ )
238
+
239
+ @property
240
+ def trust_level(self) -> str:
241
+ """Get human-readable trust level."""
242
+ return TrustLevel.label(self.trust_score)
243
+
244
+
245
+ class TrustAwareScorer(MemoryScorer):
246
+ """
247
+ Memory scorer that incorporates trust patterns.
248
+
249
+ Extends base MemoryScorer to weight memories by:
250
+ - Source agent's trust level
251
+ - Memory's verification status
252
+ - Trust-relevant metadata
253
+ """
254
+
255
+ def __init__(
256
+ self,
257
+ weights: Optional[TrustWeights] = None,
258
+ recency_half_life_days: float = 30.0,
259
+ trust_profiles: Optional[Dict[str, AgentTrustProfile]] = None,
260
+ default_trust: float = TrustLevel.MODERATE,
261
+ ):
262
+ # Convert TrustWeights to base ScoringWeights for parent
263
+ tw = weights or TrustWeights()
264
+ base_weights = ScoringWeights(
265
+ similarity=tw.similarity,
266
+ recency=tw.recency,
267
+ success_rate=tw.success_rate,
268
+ confidence=tw.confidence,
269
+ )
270
+ super().__init__(
271
+ weights=base_weights, recency_half_life_days=recency_half_life_days
272
+ )
273
+
274
+ self.trust_weights = tw
275
+ self.trust_profiles = trust_profiles or {}
276
+ self.default_trust = default_trust
277
+
278
+ def set_trust_profile(self, agent_id: str, profile: AgentTrustProfile) -> None:
279
+ """Set trust profile for an agent."""
280
+ self.trust_profiles[agent_id] = profile
281
+
282
+ def get_agent_trust(self, agent_id: str) -> float:
283
+ """Get trust score for an agent."""
284
+ if agent_id in self.trust_profiles:
285
+ return self.trust_profiles[agent_id].calculate_trust()
286
+ return self.default_trust
287
+
288
+ def score_heuristics_with_trust(
289
+ self,
290
+ heuristics: List[Heuristic],
291
+ similarities: Optional[List[float]] = None,
292
+ requesting_agent: Optional[str] = None,
293
+ ) -> List[TrustScoredItem]:
294
+ """
295
+ Score heuristics including trust factor.
296
+
297
+ Args:
298
+ heuristics: List of heuristics to score
299
+ similarities: Optional pre-computed similarity scores
300
+ requesting_agent: Agent requesting the memories (for trust context)
301
+
302
+ Returns:
303
+ Sorted list of TrustScoredItems
304
+ """
305
+ if not heuristics:
306
+ return []
307
+
308
+ similarities = similarities or [1.0] * len(heuristics)
309
+ scored = []
310
+
311
+ for h, sim in zip(heuristics, similarities, strict=False):
312
+ recency = self._compute_recency_score(h.last_validated)
313
+ success = h.success_rate
314
+ confidence = h.confidence
315
+
316
+ # Get trust for source agent
317
+ source_trust = self.get_agent_trust(h.agent)
318
+
319
+ # Check if memory has verification metadata
320
+ verified = h.metadata.get("verified", False)
321
+ if verified:
322
+ source_trust = min(1.0, source_trust * 1.1) # 10% boost for verified
323
+
324
+ # Compute weighted score
325
+ total = (
326
+ self.trust_weights.similarity * sim
327
+ + self.trust_weights.recency * recency
328
+ + self.trust_weights.success_rate * success
329
+ + self.trust_weights.confidence * confidence
330
+ + self.trust_weights.trust * source_trust
331
+ )
332
+
333
+ scored.append(
334
+ TrustScoredItem(
335
+ item=h,
336
+ score=total,
337
+ similarity_score=sim,
338
+ recency_score=recency,
339
+ success_score=success,
340
+ confidence_score=confidence,
341
+ trust_score=source_trust,
342
+ source_agent=h.agent,
343
+ trust_level=TrustLevel.label(source_trust),
344
+ )
345
+ )
346
+
347
+ return sorted(scored, key=lambda x: -x.score)
348
+
349
+ def score_outcomes_with_trust(
350
+ self,
351
+ outcomes: List[Outcome],
352
+ similarities: Optional[List[float]] = None,
353
+ ) -> List[TrustScoredItem]:
354
+ """Score outcomes including trust factor."""
355
+ if not outcomes:
356
+ return []
357
+
358
+ similarities = similarities or [1.0] * len(outcomes)
359
+ scored = []
360
+
361
+ for o, sim in zip(outcomes, similarities, strict=False):
362
+ recency = self._compute_recency_score(o.timestamp)
363
+ success = 1.0 if o.success else 0.3
364
+ confidence = 1.0
365
+
366
+ source_trust = self.get_agent_trust(o.agent)
367
+
368
+ # Boost trust for outcomes with user feedback
369
+ if o.user_feedback:
370
+ source_trust = min(1.0, source_trust * 1.05)
371
+
372
+ total = (
373
+ self.trust_weights.similarity * sim
374
+ + self.trust_weights.recency * recency
375
+ + self.trust_weights.success_rate * success
376
+ + self.trust_weights.confidence * confidence
377
+ + self.trust_weights.trust * source_trust
378
+ )
379
+
380
+ scored.append(
381
+ TrustScoredItem(
382
+ item=o,
383
+ score=total,
384
+ similarity_score=sim,
385
+ recency_score=recency,
386
+ success_score=success,
387
+ confidence_score=confidence,
388
+ trust_score=source_trust,
389
+ source_agent=o.agent,
390
+ trust_level=TrustLevel.label(source_trust),
391
+ )
392
+ )
393
+
394
+ return sorted(scored, key=lambda x: -x.score)
395
+
396
+ def score_anti_patterns_with_trust(
397
+ self,
398
+ anti_patterns: List[AntiPattern],
399
+ similarities: Optional[List[float]] = None,
400
+ ) -> List[TrustScoredItem]:
401
+ """
402
+ Score anti-patterns including trust factor.
403
+
404
+ Anti-patterns from high-trust agents are MORE important (they've
405
+ learned from experience), so trust boosts rather than reduces score.
406
+ """
407
+ if not anti_patterns:
408
+ return []
409
+
410
+ similarities = similarities or [1.0] * len(anti_patterns)
411
+ scored = []
412
+
413
+ for ap, sim in zip(anti_patterns, similarities, strict=False):
414
+ recency = self._compute_recency_score(ap.last_seen)
415
+ # More occurrences = more important
416
+ occurrence_score = min(ap.occurrence_count / 10.0, 1.0)
417
+ confidence = 1.0
418
+
419
+ source_trust = self.get_agent_trust(ap.agent)
420
+
421
+ # For anti-patterns, higher trust = more reliable warning
422
+ # Check if this came from a trust violation
423
+ from_violation = ap.metadata.get("from_trust_violation", False)
424
+ if from_violation:
425
+ source_trust = min(1.0, source_trust * 1.2) # 20% boost
426
+
427
+ total = (
428
+ self.trust_weights.similarity * sim
429
+ + self.trust_weights.recency * recency
430
+ + self.trust_weights.success_rate * occurrence_score
431
+ + self.trust_weights.confidence * confidence
432
+ + self.trust_weights.trust * source_trust
433
+ )
434
+
435
+ scored.append(
436
+ TrustScoredItem(
437
+ item=ap,
438
+ score=total,
439
+ similarity_score=sim,
440
+ recency_score=recency,
441
+ success_score=occurrence_score,
442
+ confidence_score=confidence,
443
+ trust_score=source_trust,
444
+ source_agent=ap.agent,
445
+ trust_level=TrustLevel.label(source_trust),
446
+ )
447
+ )
448
+
449
+ return sorted(scored, key=lambda x: -x.score)
450
+
451
+ def score_with_trust(
452
+ self,
453
+ memory_slice: MemorySlice,
454
+ similarities: Optional[Dict[str, List[float]]] = None,
455
+ ) -> Dict[str, List[TrustScoredItem]]:
456
+ """
457
+ Score all memories in a slice with trust integration.
458
+
459
+ Args:
460
+ memory_slice: Memories to score
461
+ similarities: Optional dict of similarity scores by type
462
+
463
+ Returns:
464
+ Dict with scored items by type
465
+ """
466
+ similarities = similarities or {}
467
+
468
+ return {
469
+ "heuristics": self.score_heuristics_with_trust(
470
+ memory_slice.heuristics,
471
+ similarities.get("heuristics"),
472
+ ),
473
+ "outcomes": self.score_outcomes_with_trust(
474
+ memory_slice.outcomes,
475
+ similarities.get("outcomes"),
476
+ ),
477
+ "anti_patterns": self.score_anti_patterns_with_trust(
478
+ memory_slice.anti_patterns,
479
+ similarities.get("anti_patterns"),
480
+ ),
481
+ }
482
+
483
+
484
+ class TrustPatternStore:
485
+ """
486
+ Stores and retrieves trust patterns in ALMA memory.
487
+
488
+ Enables:
489
+ - Storing trust violations as AntiPatterns
490
+ - Storing successful verification patterns as Heuristics
491
+ - Retrieving trust-relevant memories for a task
492
+ """
493
+
494
+ def __init__(self, alma_core: Any): # ALMA instance
495
+ self.alma = alma_core
496
+
497
+ async def store_trust_violation(
498
+ self,
499
+ agent_id: str,
500
+ project_id: str,
501
+ violation_type: str,
502
+ description: str,
503
+ severity: str,
504
+ remediation: str,
505
+ context: Optional[Dict[str, Any]] = None,
506
+ ) -> None:
507
+ """
508
+ Store a trust violation as an ALMA AntiPattern.
509
+
510
+ This allows trust violations to be retrieved as warnings
511
+ for similar future tasks.
512
+ """
513
+ anti_pattern_data = {
514
+ "pattern": f"Trust violation: {violation_type}",
515
+ "why_bad": description,
516
+ "better_alternative": remediation,
517
+ "metadata": {
518
+ "from_trust_violation": True,
519
+ "severity": severity,
520
+ "original_context": context or {},
521
+ },
522
+ }
523
+
524
+ # Use ALMA's learn method to store
525
+ await self.alma.learn(
526
+ task_type="trust_enforcement",
527
+ strategy=f"Avoid: {violation_type}",
528
+ outcome="failure",
529
+ details=anti_pattern_data,
530
+ agent=agent_id,
531
+ project_id=project_id,
532
+ )
533
+
534
+ logger.info(
535
+ f"Stored trust violation as anti-pattern: {violation_type} "
536
+ f"for agent {agent_id}"
537
+ )
538
+
539
+ async def store_verification_pattern(
540
+ self,
541
+ agent_id: str,
542
+ project_id: str,
543
+ task_type: str,
544
+ verification_strategy: str,
545
+ evidence_types: List[str],
546
+ verification_rate: float,
547
+ ) -> None:
548
+ """
549
+ Store a successful verification pattern as an ALMA Heuristic.
550
+
551
+ This allows effective verification strategies to be retrieved
552
+ for similar future tasks.
553
+ """
554
+ await self.alma.learn(
555
+ task_type=task_type,
556
+ strategy=verification_strategy,
557
+ outcome="success",
558
+ details={
559
+ "evidence_types_used": evidence_types,
560
+ "verification_rate": verification_rate,
561
+ "metadata": {
562
+ "is_verification_pattern": True,
563
+ },
564
+ },
565
+ agent=agent_id,
566
+ project_id=project_id,
567
+ )
568
+
569
+ logger.info(
570
+ f"Stored verification pattern for {task_type}: "
571
+ f"{verification_strategy} ({verification_rate:.0%} rate)"
572
+ )
573
+
574
+ async def store_trust_profile(
575
+ self,
576
+ profile: AgentTrustProfile,
577
+ project_id: str,
578
+ ) -> None:
579
+ """Store agent trust profile as domain knowledge."""
580
+ await self.alma.add_knowledge(
581
+ domain="trust_profiles",
582
+ fact=profile.to_dict(),
583
+ source="veritas_trust_evolution",
584
+ confidence=1.0,
585
+ agent="trust_system",
586
+ project_id=project_id,
587
+ )
588
+
589
+ async def retrieve_trust_profile(
590
+ self,
591
+ agent_id: str,
592
+ project_id: str,
593
+ ) -> Optional[AgentTrustProfile]:
594
+ """Retrieve agent trust profile from domain knowledge."""
595
+ memories = await self.alma.retrieve(
596
+ task=f"trust_profile:{agent_id}",
597
+ agent="trust_system",
598
+ project_id=project_id,
599
+ )
600
+
601
+ for knowledge in memories.domain_knowledge:
602
+ if knowledge.domain == "trust_profiles":
603
+ fact = knowledge.fact
604
+ if isinstance(fact, dict) and fact.get("agent_id") == agent_id:
605
+ return AgentTrustProfile.from_dict(fact)
606
+
607
+ return None
608
+
609
+ async def retrieve_trust_warnings(
610
+ self,
611
+ task_description: str,
612
+ agent_id: str,
613
+ project_id: str,
614
+ ) -> List[str]:
615
+ """
616
+ Retrieve trust-related warnings for a task.
617
+
618
+ Returns warnings based on past trust violations
619
+ that are relevant to the current task.
620
+ """
621
+ memories = await self.alma.retrieve(
622
+ task=f"trust_verification:{task_description}",
623
+ agent=agent_id,
624
+ project_id=project_id,
625
+ include_anti_patterns=True,
626
+ )
627
+
628
+ warnings = []
629
+ for ap in memories.anti_patterns:
630
+ if ap.metadata.get("from_trust_violation"):
631
+ if ap.occurrence_count >= 2:
632
+ warnings.append(
633
+ f"Repeated trust issue: {ap.pattern}. "
634
+ f"Suggestion: {ap.better_alternative}"
635
+ )
636
+
637
+ return warnings