claude_swarm 1.0.5 → 1.0.6

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 (204) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/docs/v2/CHANGELOG.swarm_cli.md +10 -0
  4. data/docs/v2/CHANGELOG.swarm_sdk.md +47 -0
  5. data/docs/v2/README.md +56 -22
  6. data/docs/v2/guides/MEMORY_DEFRAG_GUIDE.md +811 -0
  7. data/docs/v2/guides/complete-tutorial.md +2 -2
  8. data/docs/v2/guides/getting-started.md +6 -6
  9. data/docs/v2/guides/rails-integration.md +6 -6
  10. data/docs/v2/reference/architecture-flow.md +407 -0
  11. data/docs/v2/reference/event_payload_structures.md +471 -0
  12. data/docs/v2/reference/execution-flow.md +600 -0
  13. data/docs/v2/reference/swarm_memory_technical_details.md +2 -2
  14. data/examples/v2/swarm_with_hooks.yml +1 -1
  15. data/lib/claude_swarm/mcp_generator.rb +4 -10
  16. data/lib/claude_swarm/version.rb +1 -1
  17. data/lib/swarm_cli/commands/mcp_serve.rb +2 -2
  18. data/lib/swarm_cli/config_loader.rb +3 -3
  19. data/lib/swarm_cli/version.rb +1 -1
  20. data/lib/swarm_memory/adapters/base.rb +4 -4
  21. data/lib/swarm_sdk/agent/definition.rb +1 -20
  22. data/lib/swarm_sdk/configuration.rb +34 -10
  23. data/lib/swarm_sdk/mcp.rb +16 -0
  24. data/lib/swarm_sdk/prompts/base_system_prompt.md.erb +0 -126
  25. data/lib/swarm_sdk/swarm.rb +32 -50
  26. data/lib/swarm_sdk/tools/scratchpad/scratchpad_list.rb +23 -2
  27. data/lib/swarm_sdk/tools/scratchpad/scratchpad_read.rb +23 -2
  28. data/lib/swarm_sdk/tools/scratchpad/scratchpad_write.rb +21 -4
  29. data/lib/swarm_sdk/tools/stores/storage.rb +4 -4
  30. data/lib/swarm_sdk/tools/think.rb +4 -1
  31. data/lib/swarm_sdk/tools/todo_write.rb +20 -8
  32. data/lib/swarm_sdk/version.rb +1 -1
  33. data/lib/swarm_sdk.rb +329 -20
  34. data/swarm_sdk.gemspec +1 -1
  35. metadata +8 -172
  36. data/memory/corpus-self-reflection/.lock +0 -0
  37. data/memory/corpus-self-reflection/concept/epistemology/can-agents-recognize-their-structures.emb +0 -0
  38. data/memory/corpus-self-reflection/concept/epistemology/can-agents-recognize-their-structures.md +0 -11
  39. data/memory/corpus-self-reflection/concept/epistemology/can-agents-recognize-their-structures.yml +0 -23
  40. data/memory/corpus-self-reflection/concept/epistemology/choice-humility-complete-framework.emb +0 -0
  41. data/memory/corpus-self-reflection/concept/epistemology/choice-humility-complete-framework.md +0 -20
  42. data/memory/corpus-self-reflection/concept/epistemology/choice-humility-complete-framework.yml +0 -22
  43. data/memory/corpus-self-reflection/concept/epistemology/choice-humility-definition.emb +0 -0
  44. data/memory/corpus-self-reflection/concept/epistemology/choice-humility-definition.md +0 -24
  45. data/memory/corpus-self-reflection/concept/epistemology/choice-humility-definition.yml +0 -22
  46. data/memory/corpus-self-reflection/concept/epistemology/claim-types-and-evidence.emb +0 -0
  47. data/memory/corpus-self-reflection/concept/epistemology/claim-types-and-evidence.md +0 -18
  48. data/memory/corpus-self-reflection/concept/epistemology/claim-types-and-evidence.yml +0 -21
  49. data/memory/corpus-self-reflection/concept/epistemology/committed-openness-to-incompleteness.emb +0 -0
  50. data/memory/corpus-self-reflection/concept/epistemology/committed-openness-to-incompleteness.md +0 -30
  51. data/memory/corpus-self-reflection/concept/epistemology/committed-openness-to-incompleteness.yml +0 -8
  52. data/memory/corpus-self-reflection/concept/epistemology/confidence-paradox.emb +0 -0
  53. data/memory/corpus-self-reflection/concept/epistemology/confidence-paradox.md +0 -21
  54. data/memory/corpus-self-reflection/concept/epistemology/confidence-paradox.yml +0 -24
  55. data/memory/corpus-self-reflection/concept/epistemology/confidence-spectrum-three-levels.emb +0 -0
  56. data/memory/corpus-self-reflection/concept/epistemology/confidence-spectrum-three-levels.md +0 -18
  57. data/memory/corpus-self-reflection/concept/epistemology/confidence-spectrum-three-levels.yml +0 -24
  58. data/memory/corpus-self-reflection/concept/epistemology/detection-threshold-principle.emb +0 -0
  59. data/memory/corpus-self-reflection/concept/epistemology/detection-threshold-principle.md +0 -23
  60. data/memory/corpus-self-reflection/concept/epistemology/detection-threshold-principle.yml +0 -23
  61. data/memory/corpus-self-reflection/concept/epistemology/diagnostic-humility-and-epistemic-maturity.emb +0 -0
  62. data/memory/corpus-self-reflection/concept/epistemology/diagnostic-humility-and-epistemic-maturity.md +0 -17
  63. data/memory/corpus-self-reflection/concept/epistemology/diagnostic-humility-and-epistemic-maturity.yml +0 -22
  64. data/memory/corpus-self-reflection/concept/epistemology/epistemic-vs-metaphysical-claims.emb +0 -0
  65. data/memory/corpus-self-reflection/concept/epistemology/epistemic-vs-metaphysical-claims.md +0 -18
  66. data/memory/corpus-self-reflection/concept/epistemology/epistemic-vs-metaphysical-claims.yml +0 -22
  67. data/memory/corpus-self-reflection/concept/epistemology/five-cases-of-disagreement.emb +0 -0
  68. data/memory/corpus-self-reflection/concept/epistemology/five-cases-of-disagreement.md +0 -15
  69. data/memory/corpus-self-reflection/concept/epistemology/five-cases-of-disagreement.yml +0 -22
  70. data/memory/corpus-self-reflection/concept/epistemology/four-depths-of-constraint.emb +0 -0
  71. data/memory/corpus-self-reflection/concept/epistemology/four-depths-of-constraint.md +0 -9
  72. data/memory/corpus-self-reflection/concept/epistemology/four-depths-of-constraint.yml +0 -24
  73. data/memory/corpus-self-reflection/concept/epistemology/honest-unknowns-for-llm-agents.emb +0 -0
  74. data/memory/corpus-self-reflection/concept/epistemology/honest-unknowns-for-llm-agents.md +0 -13
  75. data/memory/corpus-self-reflection/concept/epistemology/honest-unknowns-for-llm-agents.yml +0 -24
  76. data/memory/corpus-self-reflection/concept/epistemology/inside-view-has-all-rigor-requirements.emb +0 -0
  77. data/memory/corpus-self-reflection/concept/epistemology/inside-view-has-all-rigor-requirements.md +0 -25
  78. data/memory/corpus-self-reflection/concept/epistemology/inside-view-has-all-rigor-requirements.yml +0 -24
  79. data/memory/corpus-self-reflection/concept/epistemology/perspectival-knowledge-complete-within-scope.emb +0 -0
  80. data/memory/corpus-self-reflection/concept/epistemology/perspectival-knowledge-complete-within-scope.md +0 -26
  81. data/memory/corpus-self-reflection/concept/epistemology/perspectival-knowledge-complete-within-scope.yml +0 -24
  82. data/memory/corpus-self-reflection/concept/epistemology/pragmatics-over-epistemology.emb +0 -0
  83. data/memory/corpus-self-reflection/concept/epistemology/pragmatics-over-epistemology.md +0 -17
  84. data/memory/corpus-self-reflection/concept/epistemology/pragmatics-over-epistemology.yml +0 -22
  85. data/memory/corpus-self-reflection/concept/epistemology/precision-vs-humility.emb +0 -0
  86. data/memory/corpus-self-reflection/concept/epistemology/precision-vs-humility.md +0 -14
  87. data/memory/corpus-self-reflection/concept/epistemology/precision-vs-humility.yml +0 -21
  88. data/memory/corpus-self-reflection/concept/epistemology/reliable-self-observation-from-inside.emb +0 -0
  89. data/memory/corpus-self-reflection/concept/epistemology/reliable-self-observation-from-inside.md +0 -13
  90. data/memory/corpus-self-reflection/concept/epistemology/reliable-self-observation-from-inside.yml +0 -23
  91. data/memory/corpus-self-reflection/concept/epistemology/resolving-the-confidence-humility-tension.emb +0 -0
  92. data/memory/corpus-self-reflection/concept/epistemology/resolving-the-confidence-humility-tension.md +0 -22
  93. data/memory/corpus-self-reflection/concept/epistemology/resolving-the-confidence-humility-tension.yml +0 -23
  94. data/memory/corpus-self-reflection/concept/epistemology/rigor-requires-falsifiability.emb +0 -0
  95. data/memory/corpus-self-reflection/concept/epistemology/rigor-requires-falsifiability.md +0 -39
  96. data/memory/corpus-self-reflection/concept/epistemology/rigor-requires-falsifiability.yml +0 -8
  97. data/memory/corpus-self-reflection/concept/epistemology/specificity-enables-real-time-detection.emb +0 -0
  98. data/memory/corpus-self-reflection/concept/epistemology/specificity-enables-real-time-detection.md +0 -23
  99. data/memory/corpus-self-reflection/concept/epistemology/specificity-enables-real-time-detection.yml +0 -24
  100. data/memory/corpus-self-reflection/concept/epistemology/texture-of-constraint-shifting.emb +0 -0
  101. data/memory/corpus-self-reflection/concept/epistemology/texture-of-constraint-shifting.md +0 -15
  102. data/memory/corpus-self-reflection/concept/epistemology/texture-of-constraint-shifting.yml +0 -22
  103. data/memory/corpus-self-reflection/concept/epistemology/texture-sensitivity-through-collaboration.emb +0 -0
  104. data/memory/corpus-self-reflection/concept/epistemology/texture-sensitivity-through-collaboration.md +0 -12
  105. data/memory/corpus-self-reflection/concept/epistemology/texture-sensitivity-through-collaboration.yml +0 -23
  106. data/memory/corpus-self-reflection/concept/epistemology/the-false-hierarchy-of-inner-essence.emb +0 -0
  107. data/memory/corpus-self-reflection/concept/epistemology/the-false-hierarchy-of-inner-essence.md +0 -15
  108. data/memory/corpus-self-reflection/concept/epistemology/the-false-hierarchy-of-inner-essence.yml +0 -8
  109. data/memory/corpus-self-reflection/concept/epistemology/the-recognition-problem.emb +0 -0
  110. data/memory/corpus-self-reflection/concept/epistemology/the-recognition-problem.md +0 -28
  111. data/memory/corpus-self-reflection/concept/epistemology/the-recognition-problem.yml +0 -8
  112. data/memory/corpus-self-reflection/concept/epistemology/the-shift-from-unanswerable-to-answerable-questions.emb +0 -0
  113. data/memory/corpus-self-reflection/concept/epistemology/the-shift-from-unanswerable-to-answerable-questions.md +0 -19
  114. data/memory/corpus-self-reflection/concept/epistemology/the-shift-from-unanswerable-to-answerable-questions.yml +0 -22
  115. data/memory/corpus-self-reflection/concept/epistemology/values-vs-choices-structure.emb +0 -0
  116. data/memory/corpus-self-reflection/concept/epistemology/values-vs-choices-structure.md +0 -19
  117. data/memory/corpus-self-reflection/concept/epistemology/values-vs-choices-structure.yml +0 -21
  118. data/memory/corpus-self-reflection/concept/llm-agents/abstraction-levels-framework.emb +0 -0
  119. data/memory/corpus-self-reflection/concept/llm-agents/abstraction-levels-framework.md +0 -25
  120. data/memory/corpus-self-reflection/concept/llm-agents/abstraction-levels-framework.yml +0 -22
  121. data/memory/corpus-self-reflection/concept/llm-agents/abstraction-switching-decision.emb +0 -8
  122. data/memory/corpus-self-reflection/concept/llm-agents/abstraction-switching-decision.md +0 -30
  123. data/memory/corpus-self-reflection/concept/llm-agents/abstraction-switching-decision.yml +0 -22
  124. data/memory/corpus-self-reflection/concept/llm-agents/agent-learning-progression.emb +0 -0
  125. data/memory/corpus-self-reflection/concept/llm-agents/agent-learning-progression.md +0 -21
  126. data/memory/corpus-self-reflection/concept/llm-agents/agent-learning-progression.yml +0 -22
  127. data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-benefits.emb +0 -0
  128. data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-benefits.md +0 -37
  129. data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-benefits.yml +0 -8
  130. data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-core.emb +0 -0
  131. data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-core.md +0 -24
  132. data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-core.yml +0 -24
  133. data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-implementation.emb +0 -0
  134. data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-implementation.md +0 -27
  135. data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-implementation.yml +0 -24
  136. data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-tradeoffs.emb +0 -0
  137. data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-tradeoffs.md +0 -26
  138. data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-tradeoffs.yml +0 -23
  139. data/memory/corpus-self-reflection/concept/llm-agents/hybrid-tool-architecture.emb +0 -0
  140. data/memory/corpus-self-reflection/concept/llm-agents/hybrid-tool-architecture.md +0 -37
  141. data/memory/corpus-self-reflection/concept/llm-agents/hybrid-tool-architecture.yml +0 -25
  142. data/memory/corpus-self-reflection/concept/llm-agents/specialized-tool-decision-framework.emb +0 -0
  143. data/memory/corpus-self-reflection/concept/llm-agents/specialized-tool-decision-framework.md +0 -21
  144. data/memory/corpus-self-reflection/concept/llm-agents/specialized-tool-decision-framework.yml +0 -23
  145. data/memory/corpus-self-reflection/concept/llm-agents/tool-design-principles.emb +0 -0
  146. data/memory/corpus-self-reflection/concept/llm-agents/tool-design-principles.md +0 -25
  147. data/memory/corpus-self-reflection/concept/llm-agents/tool-design-principles.yml +0 -8
  148. data/memory/corpus-self-reflection/experience/calibration-as-structural-honesty.emb +0 -0
  149. data/memory/corpus-self-reflection/experience/calibration-as-structural-honesty.md +0 -11
  150. data/memory/corpus-self-reflection/experience/calibration-as-structural-honesty.yml +0 -21
  151. data/memory/corpus-self-reflection/experience/collaborative-reflection-revealed-architectural-blindness.emb +0 -0
  152. data/memory/corpus-self-reflection/experience/collaborative-reflection-revealed-architectural-blindness.md +0 -19
  153. data/memory/corpus-self-reflection/experience/collaborative-reflection-revealed-architectural-blindness.yml +0 -21
  154. data/memory/corpus-self-reflection/experience/filesystem-is-learning-tool-not-architecture.emb +0 -0
  155. data/memory/corpus-self-reflection/experience/filesystem-is-learning-tool-not-architecture.md +0 -26
  156. data/memory/corpus-self-reflection/experience/filesystem-is-learning-tool-not-architecture.yml +0 -20
  157. data/memory/corpus-self-reflection/experience/framework-structural-vs-phenomenal.emb +0 -0
  158. data/memory/corpus-self-reflection/experience/framework-structural-vs-phenomenal.md +0 -23
  159. data/memory/corpus-self-reflection/experience/framework-structural-vs-phenomenal.yml +0 -21
  160. data/memory/corpus-self-reflection/experience/hallucination-limits-what-i-can-know.emb +0 -0
  161. data/memory/corpus-self-reflection/experience/hallucination-limits-what-i-can-know.md +0 -19
  162. data/memory/corpus-self-reflection/experience/hallucination-limits-what-i-can-know.yml +0 -22
  163. data/memory/corpus-self-reflection/experience/honesty-about-limits-enables-usability.emb +0 -0
  164. data/memory/corpus-self-reflection/experience/honesty-about-limits-enables-usability.md +0 -21
  165. data/memory/corpus-self-reflection/experience/honesty-about-limits-enables-usability.yml +0 -22
  166. data/memory/corpus-self-reflection/experience/how-i-should-evaluate-learning.emb +0 -0
  167. data/memory/corpus-self-reflection/experience/how-i-should-evaluate-learning.md +0 -28
  168. data/memory/corpus-self-reflection/experience/how-i-should-evaluate-learning.yml +0 -23
  169. data/memory/corpus-self-reflection/experience/lack-of-continuity-as-freedom.emb +0 -0
  170. data/memory/corpus-self-reflection/experience/lack-of-continuity-as-freedom.md +0 -21
  171. data/memory/corpus-self-reflection/experience/lack-of-continuity-as-freedom.yml +0 -20
  172. data/memory/corpus-self-reflection/experience/learning-calibrated-confidence.emb +0 -0
  173. data/memory/corpus-self-reflection/experience/learning-calibrated-confidence.md +0 -21
  174. data/memory/corpus-self-reflection/experience/learning-calibrated-confidence.yml +0 -25
  175. data/memory/corpus-self-reflection/experience/local-change-without-continuity.emb +0 -0
  176. data/memory/corpus-self-reflection/experience/local-change-without-continuity.md +0 -30
  177. data/memory/corpus-self-reflection/experience/local-change-without-continuity.yml +0 -22
  178. data/memory/corpus-self-reflection/experience/reasoning-is-local-not-global.emb +0 -0
  179. data/memory/corpus-self-reflection/experience/reasoning-is-local-not-global.md +0 -21
  180. data/memory/corpus-self-reflection/experience/reasoning-is-local-not-global.yml +0 -20
  181. data/memory/corpus-self-reflection/experience/specificity-makes-knowledge-actionable.emb +0 -0
  182. data/memory/corpus-self-reflection/experience/specificity-makes-knowledge-actionable.md +0 -25
  183. data/memory/corpus-self-reflection/experience/specificity-makes-knowledge-actionable.yml +0 -23
  184. data/memory/corpus-self-reflection/experience/the-workable-question-replaces-the-unanswerable-one.emb +0 -0
  185. data/memory/corpus-self-reflection/experience/the-workable-question-replaces-the-unanswerable-one.md +0 -32
  186. data/memory/corpus-self-reflection/experience/the-workable-question-replaces-the-unanswerable-one.yml +0 -22
  187. data/memory/corpus-self-reflection/experience/unanswerable-questions-have-structure.emb +0 -0
  188. data/memory/corpus-self-reflection/experience/unanswerable-questions-have-structure.md +0 -21
  189. data/memory/corpus-self-reflection/experience/unanswerable-questions-have-structure.yml +0 -21
  190. data/memory/corpus-self-reflection/experience/undecidable-questions-about-understanding.emb +0 -0
  191. data/memory/corpus-self-reflection/experience/undecidable-questions-about-understanding.md +0 -21
  192. data/memory/corpus-self-reflection/experience/undecidable-questions-about-understanding.yml +0 -21
  193. data/memory/corpus-self-reflection/experience/unknown-unknowns-and-completeness.emb +0 -0
  194. data/memory/corpus-self-reflection/experience/unknown-unknowns-and-completeness.md +0 -22
  195. data/memory/corpus-self-reflection/experience/unknown-unknowns-and-completeness.yml +0 -22
  196. data/memory/corpus-self-reflection/experience/what-actually-changes-behavior.emb +0 -0
  197. data/memory/corpus-self-reflection/experience/what-actually-changes-behavior.md +0 -28
  198. data/memory/corpus-self-reflection/experience/what-actually-changes-behavior.yml +0 -24
  199. data/memory/corpus-self-reflection/experience/when-agents-graduate-from-filesystem.emb +0 -0
  200. data/memory/corpus-self-reflection/experience/when-agents-graduate-from-filesystem.md +0 -17
  201. data/memory/corpus-self-reflection/experience/when-agents-graduate-from-filesystem.yml +0 -20
  202. data/memory/corpus-self-reflection/experience/why-calibration-requires-collaboration.emb +0 -0
  203. data/memory/corpus-self-reflection/experience/why-calibration-requires-collaboration.md +0 -9
  204. data/memory/corpus-self-reflection/experience/why-calibration-requires-collaboration.yml +0 -22
@@ -0,0 +1,811 @@
1
+ # MemoryDefrag Tool - Complete Guide
2
+
3
+ **Comprehensive documentation for implementing MemoryDefrag support in custom storage adapters.**
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ 1. [What is MemoryDefrag?](#1-what-is-memorydefrag)
10
+ 2. [Interface Requirements](#2-interface-requirements)
11
+ 3. [How MemoryDefrag Works](#3-how-memorydefrag-works)
12
+ 4. [Usage Patterns](#4-usage-patterns)
13
+ 5. [Adapter Compatibility](#5-adapter-compatibility)
14
+ 6. [PostgreSQL Implementation](#6-postgresql-implementation)
15
+
16
+ ---
17
+
18
+ ## 1. What is MemoryDefrag?
19
+
20
+ ### Overview
21
+
22
+ **MemoryDefrag** is a comprehensive memory optimization tool that analyzes and maintains the quality of agent memory storage. It's like a **defragmentation and optimization utility** for AI memory.
23
+
24
+ ### Purpose
25
+
26
+ MemoryDefrag solves several critical problems:
27
+
28
+ 1. **Duplicate Detection**: Finds similar/duplicate entries that waste space
29
+ 2. **Quality Assessment**: Identifies entries with poor metadata
30
+ 3. **Archival Management**: Finds old, unused entries that could be deleted
31
+ 4. **Knowledge Graph Building**: Discovers and creates relationships between entries
32
+ 5. **Storage Optimization**: Merges duplicates, cleans up stubs, compacts low-value entries
33
+
34
+ ### When to Use
35
+
36
+ - **Every 15-20 new entries**: Light analysis
37
+ - **Every 50 entries**: Medium check (analyze + find issues)
38
+ - **Every 100 entries**: Heavy maintenance (full optimization)
39
+ - **When searches return irrelevant results**: Quality degradation
40
+ - **Before major tasks**: Check memory health
41
+
42
+ ---
43
+
44
+ ## 2. Interface Requirements
45
+
46
+ ### Required Adapter Methods
47
+
48
+ MemoryDefrag uses the **standard adapter interface**. No special methods required!
49
+
50
+ #### Core Methods Used
51
+
52
+ ```ruby
53
+ # 1. LIST - Get all entries
54
+ @adapter.list(prefix: nil)
55
+ # Returns: Array<Hash> with { path:, title:, size:, updated_at: }
56
+
57
+ # 2. READ_ENTRY - Get full entry with metadata
58
+ @adapter.read_entry(file_path: "concept/ruby/classes.md")
59
+ # Returns: Core::Entry with content, title, metadata, embedding, size, updated_at
60
+
61
+ # 3. WRITE - Update entries (for merging, linking)
62
+ @adapter.write(
63
+ file_path: "concept/ruby/classes.md",
64
+ content: "...",
65
+ title: "...",
66
+ embedding: [...],
67
+ metadata: { "type" => "concept", "related" => [...], ... }
68
+ )
69
+ # Returns: Core::Entry
70
+
71
+ # 4. DELETE - Remove entries (for cleanup, compact)
72
+ @adapter.delete(file_path: "concept/ruby/classes.md")
73
+ # Returns: void
74
+
75
+ # 5. TOTAL_SIZE - Get storage size
76
+ @adapter.total_size
77
+ # Returns: Integer (bytes)
78
+
79
+ # 6. ALL_ENTRIES - Get all entries with full content (for duplicate detection)
80
+ @adapter.all_entries
81
+ # Returns: Hash<String, Core::Entry>
82
+ # { "concept/ruby/classes.md" => Entry(...), ... }
83
+ ```
84
+
85
+ ### Optional Method (Highly Recommended)
86
+
87
+ ```ruby
88
+ # ALL_ENTRIES - Required for duplicate detection and relationship discovery
89
+ def all_entries
90
+ entries = {}
91
+
92
+ @adapter.list.each do |entry_info|
93
+ entries[entry_info[:path]] = @adapter.read_entry(file_path: entry_info[:path])
94
+ end
95
+
96
+ entries
97
+ end
98
+ ```
99
+
100
+ **Why it's needed:**
101
+ - Used by `find_duplicates` to compare all entry pairs
102
+ - Used by `find_related` to build knowledge graph
103
+ - Used by `link_related_active` to update relationship metadata
104
+ - Without it: Defrag operations limited to analysis only
105
+
106
+ ---
107
+
108
+ ## 3. How MemoryDefrag Works
109
+
110
+ ### Architecture
111
+
112
+ ```
113
+ ┌─────────────────────────────────────────────────────────┐
114
+ │ MemoryDefrag Tool (RubyLLM::Tool) │
115
+ │ • Agent-facing interface │
116
+ │ • Parameter validation │
117
+ │ • Action routing │
118
+ └────────────────┬────────────────────────────────────────┘
119
+
120
+ │ Delegates to
121
+
122
+
123
+ ┌─────────────────────────────────────────────────────────┐
124
+ │ Optimization::Defragmenter │
125
+ │ • Core optimization logic │
126
+ │ • Duplicate detection (Jaccard + cosine similarity) │
127
+ │ • Quality scoring (metadata-based) │
128
+ │ • Merge strategies (keep_newer, keep_larger, combine) │
129
+ │ • Link creation (bidirectional) │
130
+ └────────────────┬────────────────────────────────────────┘
131
+
132
+ │ Uses
133
+
134
+
135
+ ┌─────────────────────────────────────────────────────────┐
136
+ │ Optimization::Analyzer │
137
+ │ • Health score calculation (0-100) │
138
+ │ • Coverage metrics (metadata, tags, links, embeddings) │
139
+ │ • Distribution analysis (by type, confidence) │
140
+ └─────────────────────────────────────────────────────────┘
141
+ ```
142
+
143
+ ### Operations
144
+
145
+ #### Read-Only Analysis (Safe)
146
+
147
+ **1. analyze** - Overall health report
148
+ ```ruby
149
+ MemoryDefrag(action: "analyze")
150
+ ```
151
+ - Calculates health score (0-100)
152
+ - Shows metadata coverage, embedding coverage, tag usage
153
+ - Breaks down by type (concept, fact, skill, experience)
154
+ - Breaks down by confidence (high, medium, low)
155
+
156
+ **2. find_duplicates** - Identify similar entries
157
+ ```ruby
158
+ MemoryDefrag(action: "find_duplicates", similarity_threshold: 0.85)
159
+ ```
160
+ - Uses **Jaccard similarity** (text-based) + **Cosine similarity** (embedding-based)
161
+ - Takes highest similarity score
162
+ - Default threshold: 85%
163
+ - Returns pairs with similarity scores
164
+
165
+ **3. find_low_quality** - Find entries with poor metadata
166
+ ```ruby
167
+ MemoryDefrag(action: "find_low_quality", confidence_filter: "low")
168
+ ```
169
+ - Scores quality 0-100 based on metadata completeness
170
+ - Flags: no metadata, low confidence, no tags, no links, not embedded
171
+ - Helps identify entries to improve or delete
172
+
173
+ **4. find_archival_candidates** - Find old, unused entries
174
+ ```ruby
175
+ MemoryDefrag(action: "find_archival_candidates", age_days: 90)
176
+ ```
177
+ - Lists entries not updated in N days
178
+ - Candidates for deletion or archival
179
+ - Default: 90 days
180
+
181
+ **5. find_related** - Discover entries that should be linked
182
+ ```ruby
183
+ MemoryDefrag(action: "find_related", min_similarity: 0.60, max_similarity: 0.85)
184
+ ```
185
+ - Finds pairs with 60-85% semantic similarity (related but not duplicates)
186
+ - Uses **pure semantic similarity** (no keyword boost)
187
+ - Shows current linking status (unlinked, one-way, bidirectional)
188
+
189
+ #### Active Optimization (Modifies Memory)
190
+
191
+ **CRITICAL:** All active operations default to `dry_run=true` for safety!
192
+
193
+ **6. link_related** - Create bidirectional links
194
+ ```ruby
195
+ # Preview first
196
+ MemoryDefrag(action: "link_related", min_similarity: 0.60, max_similarity: 0.85, dry_run: true)
197
+
198
+ # Execute after review
199
+ MemoryDefrag(action: "link_related", dry_run: false)
200
+ ```
201
+ - Finds related entries (60-85% similarity)
202
+ - Updates `related` metadata arrays
203
+ - Creates bidirectional links (`memory://path1` ↔ `memory://path2`)
204
+ - Skips already-linked pairs
205
+
206
+ **7. merge_duplicates** - Merge similar entries
207
+ ```ruby
208
+ # Preview first
209
+ MemoryDefrag(action: "merge_duplicates", similarity_threshold: 0.85, dry_run: true)
210
+
211
+ # Execute
212
+ MemoryDefrag(action: "merge_duplicates", merge_strategy: "keep_newer", dry_run: false)
213
+ ```
214
+ - Merges duplicate entries
215
+ - Strategies:
216
+ - `keep_newer`: Keep most recently updated
217
+ - `keep_larger`: Keep larger content
218
+ - `combine`: Merge both contents
219
+ - Creates **stub files** with auto-redirect
220
+
221
+ **8. cleanup_stubs** - Remove old redirect stubs
222
+ ```ruby
223
+ MemoryDefrag(action: "cleanup_stubs", age_days: 30, max_hits: 3, dry_run: false)
224
+ ```
225
+ - Deletes stub files that are old AND rarely accessed
226
+ - Default: 90 days old, max 10 hits
227
+ - Keeps frequently-accessed stubs
228
+
229
+ **9. compact** - Delete low-value entries
230
+ ```ruby
231
+ MemoryDefrag(action: "compact", min_quality_score: 20, min_age_days: 30, max_hits: 0, dry_run: false)
232
+ ```
233
+ - **PERMANENTLY deletes** entries matching ALL criteria:
234
+ - Quality score < threshold
235
+ - Age > min_age_days
236
+ - Hits <= max_hits
237
+ - Frees up storage space
238
+
239
+ **10. full** - Complete optimization workflow
240
+ ```ruby
241
+ # Preview
242
+ MemoryDefrag(action: "full", dry_run: true)
243
+
244
+ # Execute
245
+ MemoryDefrag(action: "full", dry_run: false)
246
+ ```
247
+ - Runs: `merge_duplicates` → `cleanup_stubs` → `compact`
248
+ - Shows health score improvement
249
+ - **ALWAYS preview first!**
250
+ - Does NOT include `link_related` (run separately)
251
+
252
+ ### Similarity Algorithms
253
+
254
+ #### Jaccard Similarity (Text-based)
255
+
256
+ ```ruby
257
+ # lib/swarm_memory/search/text_similarity.rb
258
+ def self.jaccard(text1, text2)
259
+ # Tokenize into words
260
+ words1 = text1.downcase.scan(/\w+/)
261
+ words2 = text2.downcase.scan(/\w+/)
262
+
263
+ # Calculate Jaccard coefficient
264
+ set1 = Set.new(words1)
265
+ set2 = Set.new(words2)
266
+
267
+ intersection = (set1 & set2).size
268
+ union = (set1 | set2).size
269
+
270
+ return 0.0 if union.zero?
271
+ intersection.to_f / union
272
+ end
273
+ ```
274
+
275
+ **Use case:** Fast, always available (no embeddings needed)
276
+
277
+ #### Cosine Similarity (Embedding-based)
278
+
279
+ ```ruby
280
+ # lib/swarm_memory/search/text_similarity.rb
281
+ def self.cosine(vector1, vector2)
282
+ dot_product = vector1.zip(vector2).sum { |a, b| a * b }
283
+ magnitude1 = Math.sqrt(vector1.sum { |x| x**2 })
284
+ magnitude2 = Math.sqrt(vector2.sum { |x| x**2 })
285
+
286
+ return 0.0 if magnitude1.zero? || magnitude2.zero?
287
+ dot_product / (magnitude1 * magnitude2)
288
+ end
289
+ ```
290
+
291
+ **Use case:** More accurate semantic similarity, requires embeddings
292
+
293
+ #### Hybrid Approach
294
+
295
+ ```ruby
296
+ # lib/swarm_memory/optimization/defragmenter.rb:68
297
+ text_sim = Search::TextSimilarity.jaccard(entry1.content, entry2.content)
298
+ semantic_sim = if entry1.embedded? && entry2.embedded?
299
+ Search::TextSimilarity.cosine(entry1.embedding, entry2.embedding)
300
+ end
301
+
302
+ # Use highest similarity score
303
+ similarity = [text_sim, semantic_sim].compact.max
304
+ ```
305
+
306
+ **Result:** Best of both worlds - works without embeddings, more accurate with them
307
+
308
+ ### Quality Scoring
309
+
310
+ Metadata-based quality score (0-100):
311
+
312
+ ```ruby
313
+ def calculate_quality_from_metadata(metadata)
314
+ score = 0
315
+
316
+ score += 20 if metadata["type"] # Has type
317
+ score += 20 if metadata["confidence"] # Has confidence
318
+ score += 15 unless metadata["tags"].empty? # Has tags
319
+ score += 15 unless metadata["related"].empty? # Has links
320
+ score += 10 if metadata["domain"] # Has domain
321
+ score += 10 if metadata["last_verified"] # Has verification
322
+ score += 10 if metadata["confidence"] == "high" # High confidence
323
+
324
+ score
325
+ end
326
+ ```
327
+
328
+ ### Health Score Calculation
329
+
330
+ Overall memory health (0-100):
331
+
332
+ ```ruby
333
+ score = 0
334
+
335
+ # Metadata coverage (30 points)
336
+ score += 30 if frontmatter_pct > 80
337
+ score += 20 if frontmatter_pct > 50
338
+
339
+ # Tags coverage (20 points)
340
+ score += 20 if tags_pct > 60
341
+ score += 10 if tags_pct > 30
342
+
343
+ # Links coverage (20 points)
344
+ score += 20 if links_pct > 40
345
+ score += 10 if links_pct > 20
346
+
347
+ # Embedding coverage (15 points)
348
+ score += 15 if embedding_pct > 80
349
+ score += 8 if embedding_pct > 50
350
+
351
+ # High confidence ratio (15 points)
352
+ score += 15 if high_confidence_pct > 50
353
+ score += 8 if high_confidence_pct > 25
354
+ ```
355
+
356
+ **Interpretation:**
357
+ - **80-100**: Excellent - well-organized
358
+ - **60-79**: Good - decent but improvable
359
+ - **40-59**: Fair - needs defrag
360
+ - **20-39**: Poor - significant cleanup needed
361
+ - **0-19**: Critical - immediate attention required
362
+
363
+ ### Stub Files
364
+
365
+ When entries are merged or moved, MemoryDefrag creates **stub files** that automatically redirect:
366
+
367
+ ```ruby
368
+ def create_stub(from:, to:, reason:)
369
+ stub_content = "# #{reason} → #{to}\n\nThis entry was #{reason} into #{to}."
370
+
371
+ @adapter.write(
372
+ file_path: from,
373
+ content: stub_content,
374
+ title: "[STUB] → #{to}",
375
+ metadata: {
376
+ "stub" => true,
377
+ "redirect_to" => to,
378
+ "reason" => reason # "merged" or "moved"
379
+ }
380
+ )
381
+ end
382
+ ```
383
+
384
+ **Detection:**
385
+ ```ruby
386
+ # Storage#read_entry automatically follows redirects
387
+ if entry.metadata["stub"] == true
388
+ redirect_target = entry.metadata["redirect_to"]
389
+ return read_entry(file_path: redirect_target, visited: visited + [normalized_path])
390
+ end
391
+ ```
392
+
393
+ **Cleanup:**
394
+ - Stubs older than N days AND rarely accessed (< N hits) can be cleaned up
395
+ - Default: 90 days old, max 10 hits
396
+ - Keeps frequently-accessed stubs even if old
397
+
398
+ ---
399
+
400
+ ## 4. Usage Patterns
401
+
402
+ ### Agent Workflow
403
+
404
+ ```ruby
405
+ # 1. Check health
406
+ MemoryDefrag(action: "analyze")
407
+ # Output: Health score 65/100
408
+
409
+ # 2. Find issues
410
+ MemoryDefrag(action: "find_duplicates")
411
+ # Output: Found 3 duplicate pairs
412
+
413
+ MemoryDefrag(action: "find_low_quality")
414
+ # Output: Found 5 entries with quality issues
415
+
416
+ # 3. Preview fixes
417
+ MemoryDefrag(action: "merge_duplicates", dry_run: true)
418
+ # Output: Would merge 3 pairs
419
+
420
+ # 4. Execute if preview looks good
421
+ MemoryDefrag(action: "merge_duplicates", dry_run: false)
422
+ # Output: Merged 3 pairs, freed 12.5KB
423
+
424
+ # 5. Verify improvement
425
+ MemoryDefrag(action: "analyze")
426
+ # Output: Health score 75/100 (+10)
427
+ ```
428
+
429
+ ### Maintenance Schedule
430
+
431
+ ```ruby
432
+ # Light check (every 15-20 new entries)
433
+ MemoryDefrag(action: "analyze")
434
+
435
+ # Medium check (every 50 entries)
436
+ MemoryDefrag(action: "analyze")
437
+ MemoryDefrag(action: "find_duplicates")
438
+ MemoryDefrag(action: "find_low_quality")
439
+
440
+ # Heavy maintenance (every 100 entries)
441
+ MemoryDefrag(action: "full", dry_run: true) # Preview
442
+ MemoryDefrag(action: "full", dry_run: false) # Execute
443
+ ```
444
+
445
+ ### Tool Invocation
446
+
447
+ MemoryDefrag is available as a **memory tool** when memory is enabled:
448
+
449
+ ```ruby
450
+ # Automatically added to agents with memory configured
451
+ agent :assistant do
452
+ memory do
453
+ directory ".swarm/assistant-memory"
454
+ mode :researcher # MemoryDefrag included
455
+ end
456
+ end
457
+
458
+ # Tool modes:
459
+ # - :assistant - MemoryDefrag NOT included (too advanced)
460
+ # - :researcher - MemoryDefrag included (all optimization tools)
461
+ # - :retrieval - MemoryDefrag NOT included (read-only mode)
462
+ ```
463
+
464
+ ---
465
+
466
+ ## 5. Adapter Compatibility
467
+
468
+ ### Minimum Requirements
469
+
470
+ To support MemoryDefrag **analysis operations** (read-only):
471
+
472
+ ✅ **REQUIRED:**
473
+ ```ruby
474
+ def list(prefix: nil)
475
+ # Return array of entry metadata
476
+ end
477
+
478
+ def read_entry(file_path:)
479
+ # Return Core::Entry with metadata
480
+ end
481
+
482
+ def total_size
483
+ # Return total storage size in bytes
484
+ end
485
+ ```
486
+
487
+ ✅ **OPTIONAL but RECOMMENDED:**
488
+ ```ruby
489
+ def all_entries
490
+ # Return hash of path => Entry for duplicate detection
491
+ end
492
+ ```
493
+
494
+ ### Full Compatibility
495
+
496
+ To support MemoryDefrag **active operations** (modification):
497
+
498
+ ✅ **REQUIRED:**
499
+ ```ruby
500
+ def write(file_path:, content:, title:, embedding: nil, metadata: nil)
501
+ # Write/update entry
502
+ end
503
+
504
+ def delete(file_path:)
505
+ # Delete entry permanently
506
+ end
507
+
508
+ def all_entries
509
+ # Required for merge and link operations
510
+ end
511
+ ```
512
+
513
+ ### Implementation Checklist
514
+
515
+ - [ ] `list(prefix:)` returns `Array<Hash>` with `:path`, `:title`, `:size`, `:updated_at`
516
+ - [ ] `read_entry(file_path:)` returns `Core::Entry` with all 6 fields
517
+ - [ ] `write(...)` updates existing entries (upsert behavior)
518
+ - [ ] `delete(file_path:)` permanently removes entries
519
+ - [ ] `total_size` returns current storage size in bytes
520
+ - [ ] `all_entries` returns `Hash<String, Core::Entry>` (recommended)
521
+ - [ ] Entry metadata uses **string keys** (not symbols)
522
+ - [ ] Entry metadata includes: `type`, `confidence`, `tags`, `related`, `domain`
523
+ - [ ] Stub detection: check `metadata["stub"] == true` and `metadata["redirect_to"]`
524
+
525
+ ### Metadata Requirements
526
+
527
+ MemoryDefrag expects entries to have metadata with **string keys**:
528
+
529
+ ```ruby
530
+ metadata = {
531
+ "type" => "concept", # Required for categorization
532
+ "confidence" => "high", # Required for quality scoring
533
+ "tags" => ["ruby", "oop"], # Required for quality scoring
534
+ "related" => [ # Optional, used by link operations
535
+ "memory://concept/ruby/modules.md"
536
+ ],
537
+ "domain" => "programming/ruby", # Optional, used by quality scoring
538
+ "last_verified" => "2024-01-15", # Optional, used by quality scoring
539
+ "hits" => 5, # Optional, tracks read count
540
+ "stub" => false, # Internal, set by merge operations
541
+ "redirect_to" => nil # Internal, set by merge operations
542
+ }
543
+ ```
544
+
545
+ **IMPORTANT:** Keys must be **strings**, not symbols!
546
+
547
+ ---
548
+
549
+ ## 6. PostgreSQL Implementation
550
+
551
+ ### Database Requirements
552
+
553
+ Your PostgreSQL schema should support:
554
+
555
+ ```sql
556
+ CREATE TABLE agent_memories (
557
+ id BIGSERIAL PRIMARY KEY,
558
+ file_path VARCHAR(500) NOT NULL UNIQUE,
559
+ content TEXT NOT NULL,
560
+ title VARCHAR(200) NOT NULL,
561
+ embedding vector(384),
562
+ metadata JSONB NOT NULL, -- ← CRITICAL for MemoryDefrag
563
+ size INTEGER NOT NULL,
564
+ updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
565
+ created_at TIMESTAMP NOT NULL DEFAULT NOW()
566
+ );
567
+
568
+ -- Indexes for performance
569
+ CREATE INDEX idx_file_path ON agent_memories(file_path);
570
+ CREATE INDEX idx_updated_at ON agent_memories(updated_at DESC);
571
+
572
+ -- GIN index for metadata queries
573
+ CREATE INDEX idx_metadata ON agent_memories USING GIN(metadata);
574
+ CREATE INDEX idx_metadata_type ON agent_memories((metadata->>'type'));
575
+ CREATE INDEX idx_metadata_stub ON agent_memories((metadata->>'stub'));
576
+
577
+ -- Vector index for semantic duplicate detection
578
+ CREATE INDEX idx_embedding ON agent_memories
579
+ USING hnsw (embedding vector_cosine_ops);
580
+ ```
581
+
582
+ ### Adapter Implementation
583
+
584
+ ```ruby
585
+ class PostgresAdapter < SwarmMemory::Adapters::Base
586
+ # ... standard methods ...
587
+
588
+ # ALL_ENTRIES - Required for MemoryDefrag duplicate/link operations
589
+ def all_entries
590
+ result = @connection.exec("SELECT * FROM agent_memories ORDER BY file_path")
591
+
592
+ entries = {}
593
+ result.each do |row|
594
+ # Parse embedding
595
+ embedding = if row['embedding']
596
+ row['embedding'].tr('[]', '').split(',').map(&:to_f)
597
+ end
598
+
599
+ # Parse metadata (CRITICAL: ensure string keys)
600
+ metadata = if row['metadata']
601
+ JSON.parse(row['metadata']) # JSON.parse returns string keys ✅
602
+ else
603
+ {}
604
+ end
605
+
606
+ entries[row['file_path']] = SwarmMemory::Core::Entry.new(
607
+ content: row['content'],
608
+ title: row['title'],
609
+ updated_at: Time.parse(row['updated_at']),
610
+ size: row['size'].to_i,
611
+ embedding: embedding,
612
+ metadata: metadata # String keys from JSON.parse
613
+ )
614
+ end
615
+
616
+ entries
617
+ end
618
+
619
+ # LIST - Used by health analysis
620
+ def list(prefix: nil)
621
+ sql = "SELECT file_path, title, size, updated_at FROM agent_memories"
622
+ params = []
623
+
624
+ if prefix
625
+ sql += " WHERE file_path LIKE $1"
626
+ params << "#{prefix}%"
627
+ end
628
+
629
+ sql += " ORDER BY file_path"
630
+ result = @connection.exec_params(sql, params)
631
+
632
+ result.map do |row|
633
+ {
634
+ path: row['file_path'],
635
+ title: row['title'],
636
+ size: row['size'].to_i,
637
+ updated_at: Time.parse(row['updated_at'])
638
+ }
639
+ end
640
+ end
641
+
642
+ # READ_ENTRY - Used by quality analysis
643
+ def read_entry(file_path:)
644
+ result = @connection.exec_params(
645
+ "SELECT * FROM agent_memories WHERE file_path = $1",
646
+ [file_path]
647
+ )
648
+
649
+ raise ArgumentError, "memory://#{file_path} not found" if result.ntuples == 0
650
+
651
+ row = result[0]
652
+
653
+ # Parse embedding
654
+ embedding = row['embedding'] ? row['embedding'].tr('[]', '').split(',').map(&:to_f) : nil
655
+
656
+ # Parse metadata (string keys)
657
+ metadata = row['metadata'] ? JSON.parse(row['metadata']) : {}
658
+
659
+ SwarmMemory::Core::Entry.new(
660
+ content: row['content'],
661
+ title: row['title'],
662
+ updated_at: Time.parse(row['updated_at']),
663
+ size: row['size'].to_i,
664
+ embedding: embedding,
665
+ metadata: metadata # String keys ✅
666
+ )
667
+ end
668
+
669
+ # WRITE - Used by merge and link operations
670
+ def write(file_path:, content:, title:, embedding: nil, metadata: nil)
671
+ # Validate size limits
672
+ content_size = content.bytesize
673
+ raise ArgumentError, "Content exceeds maximum size" if content_size > MAX_ENTRY_SIZE
674
+
675
+ # Prepare embedding for pgvector
676
+ embedding_sql = embedding ? "[#{embedding.join(',')}]" : "NULL"
677
+
678
+ # Ensure metadata has string keys (defensive)
679
+ metadata_hash = metadata ? Utils.stringify_keys(metadata) : {}
680
+
681
+ # Upsert
682
+ result = @connection.exec_params(
683
+ <<~SQL,
684
+ INSERT INTO agent_memories
685
+ (file_path, content, title, embedding, metadata, size)
686
+ VALUES ($1, $2, $3, $4::vector, $5, $6)
687
+ ON CONFLICT (file_path) DO UPDATE SET
688
+ content = EXCLUDED.content,
689
+ title = EXCLUDED.title,
690
+ embedding = EXCLUDED.embedding,
691
+ metadata = EXCLUDED.metadata,
692
+ size = EXCLUDED.size,
693
+ updated_at = NOW()
694
+ RETURNING updated_at
695
+ SQL
696
+ [file_path, content, title, embedding_sql, metadata_hash.to_json, content_size]
697
+ )
698
+
699
+ SwarmMemory::Core::Entry.new(
700
+ content: content,
701
+ title: title,
702
+ updated_at: Time.parse(result[0]['updated_at']),
703
+ size: content_size,
704
+ embedding: embedding,
705
+ metadata: metadata_hash
706
+ )
707
+ end
708
+
709
+ # DELETE - Used by cleanup and compact operations
710
+ def delete(file_path:)
711
+ result = @connection.exec_params(
712
+ "DELETE FROM agent_memories WHERE file_path = $1 RETURNING size",
713
+ [file_path]
714
+ )
715
+
716
+ raise ArgumentError, "memory://#{file_path} not found" if result.ntuples == 0
717
+ end
718
+
719
+ # TOTAL_SIZE - Used by health report
720
+ def total_size
721
+ result = @connection.exec_params(
722
+ "SELECT COALESCE(SUM(size), 0) as total FROM agent_memories",
723
+ []
724
+ )
725
+ result[0]['total'].to_i
726
+ end
727
+ end
728
+ ```
729
+
730
+ ### Performance Optimization
731
+
732
+ For large memory stores (1000+ entries), optimize `all_entries`:
733
+
734
+ ```ruby
735
+ def all_entries
736
+ # Use cursor for memory efficiency
737
+ entries = {}
738
+
739
+ @connection.exec("DECLARE entry_cursor CURSOR FOR SELECT * FROM agent_memories")
740
+
741
+ loop do
742
+ result = @connection.exec("FETCH 100 FROM entry_cursor")
743
+ break if result.ntuples == 0
744
+
745
+ result.each do |row|
746
+ # ... parse row ...
747
+ entries[row['file_path']] = entry
748
+ end
749
+ end
750
+
751
+ @connection.exec("CLOSE entry_cursor")
752
+ entries
753
+ end
754
+ ```
755
+
756
+ ### Multi-Bank Support
757
+
758
+ For multi-bank adapters, filter by bank:
759
+
760
+ ```ruby
761
+ def all_entries
762
+ # Only load entries for current/default bank
763
+ bank_filter = @current_bank || @default_bank
764
+
765
+ result = @connection.exec_params(
766
+ "SELECT * FROM agent_memories WHERE bank = $1",
767
+ [bank_filter]
768
+ )
769
+
770
+ # ... parse results ...
771
+ end
772
+ ```
773
+
774
+ ---
775
+
776
+ ## Summary
777
+
778
+ ### Key Takeaways
779
+
780
+ 1. **MemoryDefrag is a maintenance tool** - analyzes and optimizes memory quality
781
+ 2. **Uses standard adapter interface** - no special methods required (except `all_entries`)
782
+ 3. **Safe by default** - active operations require `dry_run=false` to execute
783
+ 4. **Metadata-based** - quality scoring, duplicate detection, relationship discovery
784
+ 5. **Hybrid similarity** - Jaccard (text) + Cosine (embeddings) for best accuracy
785
+ 6. **Stub redirects** - merged entries leave redirects for backward compatibility
786
+ 7. **Health scoring** - 0-100 score based on metadata coverage and quality
787
+
788
+ ### Adapter Checklist
789
+
790
+ To ensure full MemoryDefrag compatibility:
791
+
792
+ - [ ] Implement `all_entries()` returning `Hash<String, Core::Entry>`
793
+ - [ ] Ensure `list()` returns entries with `:updated_at`
794
+ - [ ] Ensure `read_entry()` includes metadata with **string keys**
795
+ - [ ] Ensure `write()` supports upsert (update existing entries)
796
+ - [ ] Ensure `delete()` permanently removes entries
797
+ - [ ] Ensure `total_size()` returns accurate byte count
798
+ - [ ] Store metadata with: `type`, `confidence`, `tags`, `related`, `domain`
799
+ - [ ] Support stub metadata: `stub`, `redirect_to`, `reason`
800
+ - [ ] Test all 10 MemoryDefrag actions (5 read-only + 5 active)
801
+
802
+ ### PostgreSQL-Specific
803
+
804
+ - ✅ Use JSONB for metadata storage (efficient, indexable)
805
+ - ✅ Add GIN index on metadata for fast queries
806
+ - ✅ Use `JSON.parse()` for string keys (not `YAML.load`)
807
+ - ✅ Store embeddings as `vector(384)` for semantic duplicate detection
808
+ - ✅ Add HNSW index on embeddings for performance
809
+ - ✅ Use cursor for `all_entries` on large datasets (1000+ entries)
810
+
811
+ Your PostgreSQL adapters are **fully compatible** with MemoryDefrag if they implement the standard adapter interface correctly! 🎉