htm 0.0.1 → 0.0.2

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 (109) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +1 -0
  3. data/.tbls.yml +30 -0
  4. data/CHANGELOG.md +30 -0
  5. data/SETUP.md +132 -101
  6. data/db/migrate/20250125000001_add_content_hash_to_nodes.rb +14 -0
  7. data/db/migrate/20250125000002_create_robot_nodes.rb +35 -0
  8. data/db/migrate/20250125000003_remove_source_and_robot_id_from_nodes.rb +28 -0
  9. data/db/migrate/20250126000001_create_working_memories.rb +19 -0
  10. data/db/migrate/20250126000002_remove_unused_columns.rb +12 -0
  11. data/db/schema.sql +226 -43
  12. data/docs/api/database.md +20 -232
  13. data/docs/api/embedding-service.md +1 -7
  14. data/docs/api/htm.md +195 -449
  15. data/docs/api/index.md +1 -7
  16. data/docs/api/long-term-memory.md +342 -590
  17. data/docs/architecture/adrs/001-postgresql-timescaledb.md +1 -1
  18. data/docs/architecture/adrs/003-ollama-embeddings.md +1 -1
  19. data/docs/architecture/adrs/010-redis-working-memory-rejected.md +2 -27
  20. data/docs/architecture/adrs/index.md +2 -13
  21. data/docs/architecture/hive-mind.md +165 -166
  22. data/docs/architecture/index.md +2 -2
  23. data/docs/architecture/overview.md +5 -171
  24. data/docs/architecture/two-tier-memory.md +1 -35
  25. data/docs/assets/images/adr-010-current-architecture.svg +37 -0
  26. data/docs/assets/images/adr-010-proposed-architecture.svg +48 -0
  27. data/docs/assets/images/adr-dependency-tree.svg +93 -0
  28. data/docs/assets/images/class-hierarchy.svg +55 -0
  29. data/docs/assets/images/exception-hierarchy.svg +45 -0
  30. data/docs/assets/images/htm-architecture-overview.svg +83 -0
  31. data/docs/assets/images/htm-complete-memory-flow.svg +160 -0
  32. data/docs/assets/images/htm-context-assembly-flow.svg +148 -0
  33. data/docs/assets/images/htm-eviction-process.svg +141 -0
  34. data/docs/assets/images/htm-memory-addition-flow.svg +138 -0
  35. data/docs/assets/images/htm-memory-recall-flow.svg +152 -0
  36. data/docs/assets/images/htm-node-states.svg +123 -0
  37. data/docs/assets/images/project-structure.svg +78 -0
  38. data/docs/assets/images/test-directory-structure.svg +38 -0
  39. data/{dbdoc → docs/database}/README.md +5 -3
  40. data/{dbdoc → docs/database}/public.node_tags.md +4 -5
  41. data/docs/database/public.node_tags.svg +106 -0
  42. data/{dbdoc → docs/database}/public.nodes.md +3 -8
  43. data/docs/database/public.nodes.svg +152 -0
  44. data/docs/database/public.robot_nodes.md +44 -0
  45. data/docs/database/public.robot_nodes.svg +121 -0
  46. data/{dbdoc → docs/database}/public.robots.md +1 -2
  47. data/docs/database/public.robots.svg +106 -0
  48. data/docs/database/public.working_memories.md +40 -0
  49. data/docs/database/public.working_memories.svg +112 -0
  50. data/{dbdoc → docs/database}/schema.json +342 -110
  51. data/docs/database/schema.svg +223 -0
  52. data/docs/development/index.md +1 -29
  53. data/docs/development/schema.md +84 -324
  54. data/docs/development/testing.md +1 -9
  55. data/docs/getting-started/index.md +47 -0
  56. data/docs/{installation.md → getting-started/installation.md} +2 -2
  57. data/docs/{quick-start.md → getting-started/quick-start.md} +5 -5
  58. data/docs/guides/adding-memories.md +221 -655
  59. data/docs/guides/search-strategies.md +85 -51
  60. data/docs/images/htm-er-diagram.svg +156 -0
  61. data/docs/index.md +16 -31
  62. data/docs/multi_framework_support.md +4 -4
  63. data/examples/basic_usage.rb +18 -16
  64. data/examples/cli_app/htm_cli.rb +86 -8
  65. data/examples/custom_llm_configuration.rb +1 -2
  66. data/examples/example_app/app.rb +11 -14
  67. data/examples/sinatra_app/Gemfile +1 -0
  68. data/examples/sinatra_app/Gemfile.lock +166 -0
  69. data/examples/sinatra_app/app.rb +219 -24
  70. data/lib/htm/active_record_config.rb +10 -3
  71. data/lib/htm/configuration.rb +265 -78
  72. data/lib/htm/{sinatra.rb → integrations/sinatra.rb} +87 -12
  73. data/lib/htm/job_adapter.rb +10 -3
  74. data/lib/htm/long_term_memory.rb +220 -57
  75. data/lib/htm/models/node.rb +36 -7
  76. data/lib/htm/models/robot.rb +30 -4
  77. data/lib/htm/models/robot_node.rb +50 -0
  78. data/lib/htm/models/tag.rb +52 -0
  79. data/lib/htm/models/working_memory_entry.rb +88 -0
  80. data/lib/htm/tasks.rb +4 -0
  81. data/lib/htm/version.rb +1 -1
  82. data/lib/htm.rb +34 -13
  83. data/lib/tasks/htm.rake +32 -1
  84. data/lib/tasks/jobs.rake +7 -3
  85. data/lib/tasks/tags.rake +34 -0
  86. data/mkdocs.yml +56 -9
  87. metadata +61 -31
  88. data/dbdoc/public.node_tags.svg +0 -112
  89. data/dbdoc/public.nodes.svg +0 -118
  90. data/dbdoc/public.robots.svg +0 -90
  91. data/dbdoc/schema.svg +0 -154
  92. /data/{dbdoc → docs/database}/public.node_stats.md +0 -0
  93. /data/{dbdoc → docs/database}/public.node_stats.svg +0 -0
  94. /data/{dbdoc → docs/database}/public.nodes_tags.md +0 -0
  95. /data/{dbdoc → docs/database}/public.nodes_tags.svg +0 -0
  96. /data/{dbdoc → docs/database}/public.ontology_structure.md +0 -0
  97. /data/{dbdoc → docs/database}/public.ontology_structure.svg +0 -0
  98. /data/{dbdoc → docs/database}/public.operations_log.md +0 -0
  99. /data/{dbdoc → docs/database}/public.operations_log.svg +0 -0
  100. /data/{dbdoc → docs/database}/public.relationships.md +0 -0
  101. /data/{dbdoc → docs/database}/public.relationships.svg +0 -0
  102. /data/{dbdoc → docs/database}/public.robot_activity.md +0 -0
  103. /data/{dbdoc → docs/database}/public.robot_activity.svg +0 -0
  104. /data/{dbdoc → docs/database}/public.schema_migrations.md +0 -0
  105. /data/{dbdoc → docs/database}/public.schema_migrations.svg +0 -0
  106. /data/{dbdoc → docs/database}/public.tags.md +0 -0
  107. /data/{dbdoc → docs/database}/public.tags.svg +0 -0
  108. /data/{dbdoc → docs/database}/public.topic_relationships.md +0 -0
  109. /data/{dbdoc → docs/database}/public.topic_relationships.svg +0 -0
@@ -1,6 +1,6 @@
1
1
  # Database Schema Documentation
2
2
 
3
- This document provides a comprehensive reference for HTM's PostgreSQL database schema, including all tables, indexes, and relationships.
3
+ This document provides a comprehensive reference for HTM's PostgreSQL database schema, including query patterns, optimization strategies, and best practices.
4
4
 
5
5
  ## Schema Overview
6
6
 
@@ -22,367 +22,116 @@ CREATE EXTENSION IF NOT EXISTS vector WITH SCHEMA public;
22
22
 
23
23
  ## Entity-Relationship Diagram
24
24
 
25
- Here's the complete database structure:
25
+ Here's the complete database structure (auto-generated by tbls):
26
26
 
27
- ```svg
28
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 900" style="background: transparent;">
29
- <defs>
30
- <style>
31
- .table-box { fill: #1e1e1e; stroke: #4a9eff; stroke-width: 2; }
32
- .table-header { fill: #2d5a8e; }
33
- .text-header { fill: #ffffff; font-family: monospace; font-size: 14px; font-weight: bold; }
34
- .text-field { fill: #d4d4d4; font-family: monospace; font-size: 11px; }
35
- .text-type { fill: #8cb4e8; font-family: monospace; font-size: 10px; }
36
- .relation-line { stroke: #4a9eff; stroke-width: 1.5; fill: none; }
37
- .arrow { fill: #4a9eff; }
38
- .join-table { fill: #1e3a1e; stroke: #4a9eff; stroke-width: 2; }
39
- </style>
40
- </defs>
27
+ ![HTM Entity-Relationship Diagram](../database/schema.svg)
41
28
 
42
- <!-- Robots Table -->
43
- <rect class="table-box" x="50" y="50" width="280" height="140" rx="5"/>
44
- <rect class="table-header" x="50" y="50" width="280" height="35" rx="5"/>
45
- <text class="text-header" x="190" y="73" text-anchor="middle">robots</text>
29
+ ## Table Reference
46
30
 
47
- <text class="text-field" x="60" y="100">id</text>
48
- <text class="text-type" x="320" y="100" text-anchor="end">BIGSERIAL PK</text>
31
+ For detailed table definitions, columns, indexes, and constraints, see the auto-generated documentation:
49
32
 
50
- <text class="text-field" x="60" y="120">name</text>
51
- <text class="text-type" x="320" y="120" text-anchor="end">TEXT</text>
33
+ ### Core Tables
52
34
 
53
- <text class="text-field" x="60" y="140">created_at</text>
54
- <text class="text-type" x="320" y="140" text-anchor="end">TIMESTAMPTZ</text>
35
+ | Table | Description | Details |
36
+ |-------|-------------|---------|
37
+ | [robots](../database/public.robots.md) | Registry of all LLM robots using the HTM system | Stores robot metadata and activity tracking |
38
+ | [nodes](../database/public.nodes.md) | Core memory storage for conversation messages and context | Vector embeddings, full-text search, deduplication |
39
+ | [tags](../database/public.tags.md) | Unique hierarchical tag names for categorization | Colon-separated namespaces (e.g., `ai:llm:embeddings`) |
40
+ | [working_memories](../database/public.working_memories.md) | Per-robot working memory state | Optional persistence for token-limited context |
55
41
 
56
- <text class="text-field" x="60" y="160">last_active</text>
57
- <text class="text-type" x="320" y="160" text-anchor="end">TIMESTAMPTZ</text>
42
+ ### Join Tables
58
43
 
59
- <text class="text-field" x="60" y="180">metadata</text>
60
- <text class="text-type" x="320" y="180" text-anchor="end">JSONB</text>
44
+ | Table | Description | Details |
45
+ |-------|-------------|---------|
46
+ | [robot_nodes](../database/public.robot_nodes.md) | Links robots to nodes (many-to-many) | Enables "hive mind" shared memory architecture |
47
+ | [node_tags](../database/public.node_tags.md) | Links nodes to tags (many-to-many) | Flexible multi-tag categorization |
61
48
 
62
- <!-- Nodes Table -->
63
- <rect class="table-box" x="50" y="250" width="280" height="400" rx="5"/>
64
- <rect class="table-header" x="50" y="250" width="280" height="35" rx="5"/>
65
- <text class="text-header" x="190" y="273" text-anchor="middle">nodes</text>
49
+ ### System Tables
66
50
 
67
- <text class="text-field" x="60" y="300">id</text>
68
- <text class="text-type" x="320" y="300" text-anchor="end">BIGSERIAL PK</text>
51
+ | Table | Description | Details |
52
+ |-------|-------------|---------|
53
+ | [schema_migrations](../database/public.schema_migrations.md) | ActiveRecord migration tracking | Tracks applied migrations |
69
54
 
70
- <text class="text-field" x="60" y="320">content</text>
71
- <text class="text-type" x="320" y="320" text-anchor="end">TEXT NOT NULL</text>
55
+ For the complete schema overview including all stored procedures and functions, see the [Database Tables Overview](../database/README.md).
72
56
 
73
- <text class="text-field" x="60" y="340">speaker</text>
74
- <text class="text-type" x="320" y="340" text-anchor="end">TEXT NOT NULL</text>
57
+ ## Key Concepts
75
58
 
76
- <text class="text-field" x="60" y="360">type</text>
77
- <text class="text-type" x="320" y="360" text-anchor="end">TEXT</text>
59
+ ### Content Deduplication
78
60
 
79
- <text class="text-field" x="60" y="380">category</text>
80
- <text class="text-type" x="320" y="380" text-anchor="end">TEXT</text>
61
+ Content deduplication is enforced via SHA-256 hashing in the `nodes` table:
81
62
 
82
- <text class="text-field" x="60" y="400">importance</text>
83
- <text class="text-type" x="320" y="400" text-anchor="end">DOUBLE PRECISION</text>
63
+ 1. When `remember()` is called, a SHA-256 hash of the content is computed
64
+ 2. If a node with the same `content_hash` exists, the existing node is reused
65
+ 3. A new `robot_nodes` association is created (or updated if it already exists)
66
+ 4. This ensures identical memories are stored once but can be "remembered" by multiple robots
84
67
 
85
- <text class="text-field" x="60" y="420">created_at</text>
86
- <text class="text-type" x="320" y="420" text-anchor="end">TIMESTAMPTZ</text>
68
+ ### Hierarchical Tags
87
69
 
88
- <text class="text-field" x="60" y="440">updated_at</text>
89
- <text class="text-type" x="320" y="440" text-anchor="end">TIMESTAMPTZ</text>
90
-
91
- <text class="text-field" x="60" y="460">last_accessed</text>
92
- <text class="text-type" x="320" y="460" text-anchor="end">TIMESTAMPTZ</text>
93
-
94
- <text class="text-field" x="60" y="480">token_count</text>
95
- <text class="text-type" x="320" y="480" text-anchor="end">INTEGER</text>
96
-
97
- <text class="text-field" x="60" y="500">in_working_memory</text>
98
- <text class="text-type" x="320" y="500" text-anchor="end">BOOLEAN</text>
99
-
100
- <text class="text-field" x="60" y="520">robot_id</text>
101
- <text class="text-type" x="320" y="520" text-anchor="end">BIGINT FK</text>
102
-
103
- <text class="text-field" x="60" y="540">embedding</text>
104
- <text class="text-type" x="320" y="540" text-anchor="end">vector(2000)</text>
105
-
106
- <text class="text-field" x="60" y="560">embedding_dimension</text>
107
- <text class="text-type" x="320" y="560" text-anchor="end">INTEGER</text>
108
-
109
- <!-- Tags Table -->
110
- <rect class="table-box" x="850" y="250" width="280" height="120" rx="5"/>
111
- <rect class="table-header" x="850" y="250" width="280" height="35" rx="5"/>
112
- <text class="text-header" x="990" y="273" text-anchor="middle">tags</text>
113
-
114
- <text class="text-field" x="860" y="300">id</text>
115
- <text class="text-type" x="1120" y="300" text-anchor="end">BIGSERIAL PK</text>
116
-
117
- <text class="text-field" x="860" y="320">name</text>
118
- <text class="text-type" x="1120" y="320" text-anchor="end">TEXT UNIQUE</text>
119
-
120
- <text class="text-field" x="860" y="340">created_at</text>
121
- <text class="text-type" x="1120" y="340" text-anchor="end">TIMESTAMPTZ</text>
122
-
123
- <!-- nodes_tags Join Table -->
124
- <rect class="join-table" x="450" y="420" width="280" height="140" rx="5"/>
125
- <rect class="table-header" x="450" y="420" width="280" height="35" rx="5"/>
126
- <text class="text-header" x="590" y="443" text-anchor="middle">nodes_tags</text>
127
-
128
- <text class="text-field" x="460" y="470">id</text>
129
- <text class="text-type" x="720" y="470" text-anchor="end">BIGSERIAL PK</text>
130
-
131
- <text class="text-field" x="460" y="490">node_id</text>
132
- <text class="text-type" x="720" y="490" text-anchor="end">BIGINT FK</text>
133
-
134
- <text class="text-field" x="460" y="510">tag_id</text>
135
- <text class="text-type" x="720" y="510" text-anchor="end">BIGINT FK</text>
136
-
137
- <text class="text-field" x="460" y="530">created_at</text>
138
- <text class="text-type" x="720" y="530" text-anchor="end">TIMESTAMPTZ</text>
139
-
140
- <!-- Relationships: robots -> nodes -->
141
- <path class="relation-line" d="M 190 190 L 190 250"/>
142
- <polygon class="arrow" points="190,250 185,240 195,240"/>
143
-
144
- <!-- Relationships: nodes -> nodes_tags -->
145
- <path class="relation-line" d="M 330 490 L 450 490"/>
146
- <polygon class="arrow" points="450,490 440,485 440,495"/>
147
-
148
- <!-- Relationships: tags -> nodes_tags -->
149
- <path class="relation-line" d="M 850 310 L 730 310 L 730 510 L 730 510"/>
150
- <polygon class="arrow" points="730,510 725,500 735,500"/>
151
-
152
- <!-- Legend -->
153
- <text class="text-field" x="50" y="720" font-weight="bold">Legend:</text>
154
- <text class="text-field" x="50" y="740">PK = Primary Key</text>
155
- <text class="text-field" x="200" y="740">FK = Foreign Key</text>
156
- <text class="text-field" x="50" y="760">Green box = Join table (many-to-many)</text>
157
-
158
- <!-- Annotations -->
159
- <text class="text-field" x="400" y="370" font-style="italic">1:N</text>
160
- <text class="text-field" x="380" y="480" font-style="italic">N:M</text>
161
- <text class="text-field" x="770" y="480" font-style="italic">N:M</text>
162
- </svg>
163
- ```
164
-
165
- ## Table Definitions
166
-
167
- ### robots
168
-
169
- The robots table stores registration and metadata for all LLM agents using the HTM system.
170
-
171
- **Purpose**: Registry of all robots (LLM agents) with their configuration and activity tracking.
70
+ Tags use colon-separated hierarchies for organization:
71
+ - `programming:ruby:gems` - Programming > Ruby > Gems
72
+ - `database:postgresql:extensions` - Database > PostgreSQL > Extensions
73
+ - `ai:llm:embeddings` - AI > LLM > Embeddings
172
74
 
75
+ Query by prefix to find all related tags:
173
76
  ```sql
174
- CREATE TABLE public.robots (
175
- id bigint NOT NULL,
176
- name text,
177
- created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
178
- last_active timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
179
- metadata jsonb
180
- );
181
-
182
- ALTER TABLE ONLY public.robots ALTER COLUMN id SET DEFAULT nextval('public.robots_id_seq'::regclass);
183
- ALTER TABLE ONLY public.robots ADD CONSTRAINT robots_pkey PRIMARY KEY (id);
77
+ SELECT * FROM tags WHERE name LIKE 'database:%'; -- All database-related tags
78
+ SELECT * FROM tags WHERE name LIKE 'ai:llm:%'; -- All LLM-related tags
184
79
  ```
185
80
 
186
- **Columns**:
81
+ ### Remember Tracking
187
82
 
188
- | Column | Type | Nullable | Default | Description |
189
- |--------|------|----------|---------|-------------|
190
- | `id` | BIGINT | NO | AUTO | Unique identifier (primary key) |
191
- | `name` | TEXT | YES | NULL | Human-readable name for the robot |
192
- | `created_at` | TIMESTAMPTZ | YES | NOW() | When the robot was first registered |
193
- | `last_active` | TIMESTAMPTZ | YES | NOW() | Last time the robot accessed the system |
194
- | `metadata` | JSONB | YES | NULL | Robot-specific configuration and metadata |
83
+ The `robot_nodes` table tracks per-robot remember metadata:
195
84
 
196
- **Indexes**:
197
- - `PRIMARY KEY` on `id`
85
+ 1. `first_remembered_at` - When this robot first encountered this content
86
+ 2. `last_remembered_at` - Updated each time the robot tries to remember the same content
87
+ 3. `remember_count` - Incremented each time (useful for identifying frequently reinforced memories)
198
88
 
199
- **Relationships**:
200
- - One robot has many nodes (1:N)
89
+ This allows querying for:
90
+ - Recently reinforced memories: `ORDER BY last_remembered_at DESC`
91
+ - Frequently remembered content: `ORDER BY remember_count DESC`
92
+ - New vs old memories: Compare `first_remembered_at` across robots
201
93
 
202
94
  ---
203
95
 
204
- ### nodes
205
-
206
- The core table storing all memory nodes with vector embeddings for semantic search.
207
-
208
- **Purpose**: Stores all memories (conversation messages, facts, decisions, code, etc.) with full-text and vector search capabilities.
209
-
210
- ```sql
211
- CREATE TABLE public.nodes (
212
- id bigint NOT NULL,
213
- content text NOT NULL,
214
- speaker text NOT NULL,
215
- type text,
216
- category text,
217
- importance double precision DEFAULT 1.0,
218
- created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
219
- updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
220
- last_accessed timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
221
- token_count integer,
222
- in_working_memory boolean DEFAULT false,
223
- robot_id bigint NOT NULL,
224
- embedding public.vector(2000),
225
- embedding_dimension integer,
226
- CONSTRAINT check_embedding_dimension CHECK (((embedding_dimension IS NULL) OR ((embedding_dimension > 0) AND (embedding_dimension <= 2000))))
227
- );
228
-
229
- ALTER TABLE ONLY public.nodes ALTER COLUMN id SET DEFAULT nextval('public.nodes_id_seq'::regclass);
230
- ALTER TABLE ONLY public.nodes ADD CONSTRAINT nodes_pkey PRIMARY KEY (id);
231
- ALTER TABLE ONLY public.nodes
232
- ADD CONSTRAINT fk_rails_60162e9d3a FOREIGN KEY (robot_id) REFERENCES public.robots(id) ON DELETE CASCADE;
233
- ```
234
-
235
- **Columns**:
236
-
237
- | Column | Type | Nullable | Default | Description |
238
- |--------|------|----------|---------|-------------|
239
- | `id` | BIGINT | NO | AUTO | Unique identifier (primary key) |
240
- | `content` | TEXT | NO | - | The conversation message/utterance content |
241
- | `speaker` | TEXT | NO | - | Who said it: user or robot name |
242
- | `type` | TEXT | YES | NULL | Memory type: fact, context, code, preference, decision, question |
243
- | `category` | TEXT | YES | NULL | Optional category for organizing memories |
244
- | `importance` | DOUBLE PRECISION | YES | 1.0 | Importance score (0.0-1.0) for prioritizing recall |
245
- | `created_at` | TIMESTAMPTZ | YES | NOW() | When this memory was created |
246
- | `updated_at` | TIMESTAMPTZ | YES | NOW() | When this memory was last modified |
247
- | `last_accessed` | TIMESTAMPTZ | YES | NOW() | When this memory was last accessed |
248
- | `token_count` | INTEGER | YES | NULL | Number of tokens in the content (for context budget management) |
249
- | `in_working_memory` | BOOLEAN | YES | FALSE | Whether this memory is currently in working memory |
250
- | `robot_id` | BIGINT | NO | - | ID of the robot that owns this memory |
251
- | `embedding` | vector(2000) | YES | NULL | Vector embedding (max 2000 dimensions) for semantic search |
252
- | `embedding_dimension` | INTEGER | YES | NULL | Actual number of dimensions used in the embedding vector (max 2000) |
253
-
254
- **Indexes**:
255
-
256
- - `PRIMARY KEY` on `id`
257
- - `idx_nodes_robot_id` BTREE on `robot_id`
258
- - `idx_nodes_speaker` BTREE on `speaker`
259
- - `idx_nodes_type` BTREE on `type`
260
- - `idx_nodes_category` BTREE on `category`
261
- - `idx_nodes_created_at` BTREE on `created_at`
262
- - `idx_nodes_updated_at` BTREE on `updated_at`
263
- - `idx_nodes_last_accessed` BTREE on `last_accessed`
264
- - `idx_nodes_in_working_memory` BTREE on `in_working_memory`
265
- - `idx_nodes_embedding` HNSW on `embedding` using `vector_cosine_ops` (m=16, ef_construction=64)
266
- - `idx_nodes_content_gin` GIN on `to_tsvector('english', content)` for full-text search
267
- - `idx_nodes_content_trgm` GIN on `content` using `gin_trgm_ops` for fuzzy matching
268
-
269
- **Foreign Keys**:
270
- - `robot_id` references `robots(id)` ON DELETE CASCADE
271
-
272
- **Relationships**:
273
- - Many nodes belong to one robot (N:1)
274
- - Many nodes have many tags through nodes_tags (N:M)
275
-
276
- **Check Constraints**:
277
- - `check_embedding_dimension`: Ensures embedding_dimension is NULL or between 1 and 2000
278
-
279
- ---
280
-
281
- ### tags
282
-
283
- The tags table stores unique hierarchical tag names for categorization.
96
+ ## Common Query Patterns
284
97
 
285
- **Purpose**: Provides flexible, hierarchical categorization using colon-separated namespaces (e.g., `database:postgresql:timescaledb`).
98
+ ### Finding Nodes for a Robot
286
99
 
287
100
  ```sql
288
- CREATE TABLE public.tags (
289
- id bigint NOT NULL,
290
- name text NOT NULL,
291
- created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP
292
- );
293
-
294
- ALTER TABLE ONLY public.tags ALTER COLUMN id SET DEFAULT nextval('public.tags_id_seq'::regclass);
295
- ALTER TABLE ONLY public.tags ADD CONSTRAINT tags_pkey PRIMARY KEY (id);
101
+ SELECT n.*
102
+ FROM nodes n
103
+ JOIN robot_nodes rn ON n.id = rn.node_id
104
+ WHERE rn.robot_id = $1
105
+ ORDER BY rn.last_remembered_at DESC;
296
106
  ```
297
107
 
298
- **Columns**:
299
-
300
- | Column | Type | Nullable | Default | Description |
301
- |--------|------|----------|---------|-------------|
302
- | `id` | BIGINT | NO | AUTO | Unique identifier (primary key) |
303
- | `name` | TEXT | NO | - | Hierarchical tag in format: root:level1:level2 (e.g., database:postgresql:timescaledb) |
304
- | `created_at` | TIMESTAMPTZ | YES | NOW() | When this tag was created |
305
-
306
- **Indexes**:
307
- - `PRIMARY KEY` on `id`
308
- - `idx_tags_name_unique` UNIQUE BTREE on `name`
309
- - `idx_tags_name_pattern` BTREE on `name` with `text_pattern_ops` for pattern matching
310
-
311
- **Relationships**:
312
- - Many tags belong to many nodes through nodes_tags (N:M)
313
-
314
- **Tag Hierarchy**:
108
+ ### Finding Robots that Share a Node
315
109
 
316
- Tags use colon-separated hierarchies for organization:
317
- - `programming:ruby:gems` - Programming > Ruby > Gems
318
- - `database:postgresql:extensions` - Database > PostgreSQL > Extensions
319
- - `ai:llm:embeddings` - AI > LLM > Embeddings
320
-
321
- This allows querying by prefix to find all related tags:
322
110
  ```sql
323
- SELECT * FROM tags WHERE name LIKE 'database:%'; -- All database-related tags
324
- SELECT * FROM tags WHERE name LIKE 'ai:llm:%'; -- All LLM-related tags
111
+ SELECT r.*
112
+ FROM robots r
113
+ JOIN robot_nodes rn ON r.id = rn.robot_id
114
+ WHERE rn.node_id = $1
115
+ ORDER BY rn.first_remembered_at;
325
116
  ```
326
117
 
327
- ---
328
-
329
- ### nodes_tags
330
-
331
- The nodes_tags join table implements the many-to-many relationship between nodes and tags.
332
-
333
- **Purpose**: Links nodes to tags, allowing each node to have multiple tags and each tag to be applied to multiple nodes.
118
+ ### Finding Frequently Remembered Content
334
119
 
335
120
  ```sql
336
- CREATE TABLE public.nodes_tags (
337
- id bigint NOT NULL,
338
- node_id bigint NOT NULL,
339
- tag_id bigint NOT NULL,
340
- created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP
341
- );
342
-
343
- ALTER TABLE ONLY public.nodes_tags ALTER COLUMN id SET DEFAULT nextval('public.node_tags_id_seq'::regclass);
344
- ALTER TABLE ONLY public.nodes_tags ADD CONSTRAINT node_tags_pkey PRIMARY KEY (id);
345
-
346
- ALTER TABLE ONLY public.nodes_tags
347
- ADD CONSTRAINT fk_rails_b0b726ecf8 FOREIGN KEY (node_id) REFERENCES public.nodes(id) ON DELETE CASCADE;
348
- ALTER TABLE ONLY public.nodes_tags
349
- ADD CONSTRAINT fk_rails_eccc99cec5 FOREIGN KEY (tag_id) REFERENCES public.tags(id) ON DELETE CASCADE;
121
+ SELECT n.*, rn.remember_count, rn.first_remembered_at, rn.last_remembered_at
122
+ FROM nodes n
123
+ JOIN robot_nodes rn ON n.id = rn.node_id
124
+ WHERE rn.robot_id = $1
125
+ ORDER BY rn.remember_count DESC
126
+ LIMIT 10;
350
127
  ```
351
128
 
352
- **Columns**:
353
-
354
- | Column | Type | Nullable | Default | Description |
355
- |--------|------|----------|---------|-------------|
356
- | `id` | BIGINT | NO | AUTO | Unique identifier (primary key) |
357
- | `node_id` | BIGINT | NO | - | ID of the node being tagged |
358
- | `tag_id` | BIGINT | NO | - | ID of the tag being applied |
359
- | `created_at` | TIMESTAMPTZ | YES | NOW() | When this association was created |
360
-
361
- **Indexes**:
362
- - `PRIMARY KEY` on `id`
363
- - `idx_node_tags_unique` UNIQUE BTREE on `(node_id, tag_id)` - Prevents duplicate associations
364
- - `idx_node_tags_node_id` BTREE on `node_id` - Fast lookups of tags for a node
365
- - `idx_node_tags_tag_id` BTREE on `tag_id` - Fast lookups of nodes for a tag
366
-
367
- **Foreign Keys**:
368
- - `node_id` references `nodes(id)` ON DELETE CASCADE
369
- - `tag_id` references `tags(id)` ON DELETE CASCADE
370
-
371
- **Cascade Behavior**:
372
- - When a node is deleted, all its tag associations are automatically removed
373
- - When a tag is deleted, all associations to that tag are automatically removed
374
- - The join table ensures referential integrity between nodes and tags
375
-
376
- ---
377
-
378
- ## Common Query Patterns
379
-
380
129
  ### Finding Tags for a Node
381
130
 
382
131
  ```sql
383
132
  SELECT t.name
384
133
  FROM tags t
385
- JOIN nodes_tags nt ON t.id = nt.tag_id
134
+ JOIN node_tags nt ON t.id = nt.tag_id
386
135
  WHERE nt.node_id = $1
387
136
  ORDER BY t.name;
388
137
  ```
@@ -392,7 +141,7 @@ ORDER BY t.name;
392
141
  ```sql
393
142
  SELECT n.*
394
143
  FROM nodes n
395
- JOIN nodes_tags nt ON n.id = nt.node_id
144
+ JOIN node_tags nt ON n.id = nt.node_id
396
145
  JOIN tags t ON nt.tag_id = t.id
397
146
  WHERE t.name = 'database:postgresql'
398
147
  ORDER BY n.created_at DESC;
@@ -403,7 +152,7 @@ ORDER BY n.created_at DESC;
403
152
  ```sql
404
153
  SELECT n.*
405
154
  FROM nodes n
406
- JOIN nodes_tags nt ON n.id = nt.node_id
155
+ JOIN node_tags nt ON n.id = nt.node_id
407
156
  JOIN tags t ON nt.tag_id = t.id
408
157
  WHERE t.name LIKE 'ai:llm:%'
409
158
  ORDER BY n.created_at DESC;
@@ -417,8 +166,8 @@ SELECT
417
166
  t2.name AS topic2,
418
167
  COUNT(DISTINCT nt1.node_id) AS shared_nodes
419
168
  FROM tags t1
420
- JOIN nodes_tags nt1 ON t1.id = nt1.tag_id
421
- JOIN nodes_tags nt2 ON nt1.node_id = nt2.node_id
169
+ JOIN node_tags nt1 ON t1.id = nt1.tag_id
170
+ JOIN node_tags nt2 ON nt1.node_id = nt2.node_id
422
171
  JOIN tags t2 ON nt2.tag_id = t2.id
423
172
  WHERE t1.name < t2.name
424
173
  GROUP BY t1.name, t2.name
@@ -431,7 +180,7 @@ ORDER BY shared_nodes DESC;
431
180
  ```sql
432
181
  SELECT n.*, n.embedding <=> $1::vector AS distance
433
182
  FROM nodes n
434
- JOIN nodes_tags nt ON n.id = nt.node_id
183
+ JOIN node_tags nt ON n.id = nt.node_id
435
184
  JOIN tags t ON nt.tag_id = t.id
436
185
  WHERE t.name = 'programming:ruby'
437
186
  AND n.embedding IS NOT NULL
@@ -444,7 +193,7 @@ LIMIT 10;
444
193
  ```sql
445
194
  SELECT n.*, ts_rank(to_tsvector('english', n.content), query) AS rank
446
195
  FROM nodes n
447
- JOIN nodes_tags nt ON n.id = nt.node_id
196
+ JOIN node_tags nt ON n.id = nt.node_id
448
197
  JOIN tags t ON nt.tag_id = t.id,
449
198
  to_tsquery('english', 'database & optimization') query
450
199
  WHERE to_tsvector('english', n.content) @@ query
@@ -453,6 +202,17 @@ ORDER BY rank DESC
453
202
  LIMIT 20;
454
203
  ```
455
204
 
205
+ ### Finding Content Shared by Multiple Robots
206
+
207
+ ```sql
208
+ SELECT n.*, COUNT(DISTINCT rn.robot_id) AS robot_count
209
+ FROM nodes n
210
+ JOIN robot_nodes rn ON n.id = rn.node_id
211
+ GROUP BY n.id
212
+ HAVING COUNT(DISTINCT rn.robot_id) > 1
213
+ ORDER BY robot_count DESC;
214
+ ```
215
+
456
216
  ---
457
217
 
458
218
  ## Database Optimization
@@ -147,15 +147,7 @@ ruby -r debug test/htm_test.rb
147
147
 
148
148
  ### Test File Layout
149
149
 
150
- ```
151
- test/
152
- ├── test_helper.rb # Shared test configuration
153
- ├── htm_test.rb # Unit tests for HTM class
154
- ├── embedding_service_test.rb # Unit tests for EmbeddingService
155
- ├── integration_test.rb # Integration tests
156
- └── fixtures/ # Test data (future)
157
- └── sample_memories.json
158
- ```
150
+ ![Test Directory Structure](../assets/images/test-directory-structure.svg)
159
151
 
160
152
  ### Test File Template
161
153
 
@@ -0,0 +1,47 @@
1
+ # Getting Started
2
+
3
+ Welcome to HTM (Hierarchical Temporary Memory)! This section will help you get up and running quickly.
4
+
5
+ ## Overview
6
+
7
+ HTM provides intelligent memory management for LLM-based applications (robots) with a two-tier architecture:
8
+
9
+ - **Long-term Memory**: Durable PostgreSQL storage with vector embeddings for semantic search
10
+ - **Working Memory**: Token-limited in-memory context for immediate LLM use
11
+
12
+ ## What You'll Learn
13
+
14
+ <div class="grid cards" markdown>
15
+
16
+ - :material-download:{ .lg .middle } **Installation**
17
+
18
+ ---
19
+
20
+ Set up HTM in your Ruby project with all required dependencies including PostgreSQL, pgvector, and Ollama.
21
+
22
+ [:octicons-arrow-right-24: Install HTM](installation.md)
23
+
24
+ - :material-rocket-launch:{ .lg .middle } **Quick Start**
25
+
26
+ ---
27
+
28
+ Build your first memory-enabled robot in minutes with practical examples and code snippets.
29
+
30
+ [:octicons-arrow-right-24: Get started](quick-start.md)
31
+
32
+ </div>
33
+
34
+ ## Prerequisites
35
+
36
+ Before installing HTM, ensure you have:
37
+
38
+ - **Ruby 3.1+** - HTM uses modern Ruby features
39
+ - **PostgreSQL 14+** - With pgvector and pg_trgm extensions
40
+ - **Ollama** (optional) - For local embedding generation
41
+
42
+ ## Next Steps
43
+
44
+ 1. **[Install HTM](installation.md)** - Set up the gem and database
45
+ 2. **[Quick Start](quick-start.md)** - Create your first memory-enabled robot
46
+ 3. **[Architecture Overview](../architecture/overview.md)** - Understand how HTM works
47
+ 4. **[Guides](../guides/index.md)** - Deep dive into specific features
@@ -453,8 +453,8 @@ psql $HTM_DBURL -c "
453
453
  Now that HTM is installed, you're ready to start building:
454
454
 
455
455
  1. **[Quick Start Guide](quick-start.md)**: Build your first HTM application in 5 minutes
456
- 2. **[User Guide](guides/getting-started.md)**: Learn all HTM features in depth
457
- 3. **[API Reference](api/htm.md)**: Explore the complete API documentation
456
+ 2. **[User Guide](../guides/getting-started.md)**: Learn all HTM features in depth
457
+ 3. **[API Reference](../api/htm.md)**: Explore the complete API documentation
458
458
  4. **[Examples](https://github.com/madbomber/htm/tree/main/examples)**: See real-world usage examples
459
459
 
460
460
  ## Getting Help
@@ -499,9 +499,9 @@ Congratulations! You've learned the basics of HTM. Here's what to explore next:
499
499
 
500
500
  ### Explore Advanced Features
501
501
 
502
- - **[User Guide](guides/getting-started.md)**: Deep dive into all HTM features
503
- - **[API Reference](api/htm.md)**: Complete API documentation
504
- - **[Architecture Guide](architecture/overview.md)**: Understand HTM's internals
502
+ - **[User Guide](../guides/getting-started.md)**: Deep dive into all HTM features
503
+ - **[API Reference](../api/htm.md)**: Complete API documentation
504
+ - **[Architecture Guide](../architecture/overview.md)**: Understand HTM's internals
505
505
 
506
506
  ### Build Real Applications
507
507
 
@@ -648,8 +648,8 @@ memories = htm.recall(
648
648
  ## Additional Resources
649
649
 
650
650
  - **[Installation Guide](installation.md)**: Complete setup instructions
651
- - **[User Guide](guides/getting-started.md)**: Comprehensive feature documentation
652
- - **[API Reference](api/htm.md)**: Detailed API documentation
651
+ - **[User Guide](../guides/getting-started.md)**: Comprehensive feature documentation
652
+ - **[API Reference](../api/htm.md)**: Detailed API documentation
653
653
  - **[Examples](https://github.com/madbomber/htm/tree/main/examples)**: Real-world code examples
654
654
 
655
655
  Happy coding with HTM! 🚀