htm 0.0.1

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 (155) hide show
  1. checksums.yaml +7 -0
  2. data/.architecture/decisions/adrs/001-use-postgresql-timescaledb-storage.md +227 -0
  3. data/.architecture/decisions/adrs/002-two-tier-memory-architecture.md +322 -0
  4. data/.architecture/decisions/adrs/003-ollama-default-embedding-provider.md +339 -0
  5. data/.architecture/decisions/adrs/004-multi-robot-shared-memory-hive-mind.md +374 -0
  6. data/.architecture/decisions/adrs/005-rag-based-retrieval-with-hybrid-search.md +443 -0
  7. data/.architecture/decisions/adrs/006-context-assembly-strategies.md +444 -0
  8. data/.architecture/decisions/adrs/007-working-memory-eviction-strategy.md +461 -0
  9. data/.architecture/decisions/adrs/008-robot-identification-system.md +550 -0
  10. data/.architecture/decisions/adrs/009-never-forget-explicit-deletion-only.md +570 -0
  11. data/.architecture/decisions/adrs/010-redis-working-memory-rejected.md +323 -0
  12. data/.architecture/decisions/adrs/011-database-side-embedding-generation-with-pgai.md +585 -0
  13. data/.architecture/decisions/adrs/012-llm-driven-ontology-topic-extraction.md +583 -0
  14. data/.architecture/decisions/adrs/013-activerecord-orm-and-many-to-many-tagging.md +299 -0
  15. data/.architecture/decisions/adrs/014-client-side-embedding-generation-workflow.md +569 -0
  16. data/.architecture/decisions/adrs/015-hierarchical-tag-ontology-and-llm-extraction.md +701 -0
  17. data/.architecture/decisions/adrs/016-async-embedding-and-tag-generation.md +694 -0
  18. data/.architecture/members.yml +144 -0
  19. data/.architecture/reviews/2025-10-29-llm-configuration-and-async-processing-review.md +1137 -0
  20. data/.architecture/reviews/initial-system-analysis.md +330 -0
  21. data/.envrc +32 -0
  22. data/.irbrc +145 -0
  23. data/CHANGELOG.md +150 -0
  24. data/COMMITS.md +196 -0
  25. data/LICENSE +21 -0
  26. data/README.md +1347 -0
  27. data/Rakefile +51 -0
  28. data/SETUP.md +268 -0
  29. data/config/database.yml +67 -0
  30. data/db/migrate/20250101000001_enable_extensions.rb +14 -0
  31. data/db/migrate/20250101000002_create_robots.rb +14 -0
  32. data/db/migrate/20250101000003_create_nodes.rb +42 -0
  33. data/db/migrate/20250101000005_create_tags.rb +38 -0
  34. data/db/migrate/20250101000007_add_node_vector_indexes.rb +30 -0
  35. data/db/schema.sql +473 -0
  36. data/db/seed_data/README.md +100 -0
  37. data/db/seed_data/presidents.md +136 -0
  38. data/db/seed_data/states.md +151 -0
  39. data/db/seeds.rb +208 -0
  40. data/dbdoc/README.md +173 -0
  41. data/dbdoc/public.node_stats.md +48 -0
  42. data/dbdoc/public.node_stats.svg +41 -0
  43. data/dbdoc/public.node_tags.md +40 -0
  44. data/dbdoc/public.node_tags.svg +112 -0
  45. data/dbdoc/public.nodes.md +54 -0
  46. data/dbdoc/public.nodes.svg +118 -0
  47. data/dbdoc/public.nodes_tags.md +39 -0
  48. data/dbdoc/public.nodes_tags.svg +112 -0
  49. data/dbdoc/public.ontology_structure.md +48 -0
  50. data/dbdoc/public.ontology_structure.svg +38 -0
  51. data/dbdoc/public.operations_log.md +42 -0
  52. data/dbdoc/public.operations_log.svg +130 -0
  53. data/dbdoc/public.relationships.md +39 -0
  54. data/dbdoc/public.relationships.svg +41 -0
  55. data/dbdoc/public.robot_activity.md +46 -0
  56. data/dbdoc/public.robot_activity.svg +35 -0
  57. data/dbdoc/public.robots.md +35 -0
  58. data/dbdoc/public.robots.svg +90 -0
  59. data/dbdoc/public.schema_migrations.md +29 -0
  60. data/dbdoc/public.schema_migrations.svg +26 -0
  61. data/dbdoc/public.tags.md +35 -0
  62. data/dbdoc/public.tags.svg +60 -0
  63. data/dbdoc/public.topic_relationships.md +45 -0
  64. data/dbdoc/public.topic_relationships.svg +32 -0
  65. data/dbdoc/schema.json +1437 -0
  66. data/dbdoc/schema.svg +154 -0
  67. data/docs/api/database.md +806 -0
  68. data/docs/api/embedding-service.md +532 -0
  69. data/docs/api/htm.md +797 -0
  70. data/docs/api/index.md +259 -0
  71. data/docs/api/long-term-memory.md +1096 -0
  72. data/docs/api/working-memory.md +665 -0
  73. data/docs/architecture/adrs/001-postgresql-timescaledb.md +314 -0
  74. data/docs/architecture/adrs/002-two-tier-memory.md +411 -0
  75. data/docs/architecture/adrs/003-ollama-embeddings.md +421 -0
  76. data/docs/architecture/adrs/004-hive-mind.md +437 -0
  77. data/docs/architecture/adrs/005-rag-retrieval.md +531 -0
  78. data/docs/architecture/adrs/006-context-assembly.md +496 -0
  79. data/docs/architecture/adrs/007-eviction-strategy.md +645 -0
  80. data/docs/architecture/adrs/008-robot-identification.md +625 -0
  81. data/docs/architecture/adrs/009-never-forget.md +648 -0
  82. data/docs/architecture/adrs/010-redis-working-memory-rejected.md +323 -0
  83. data/docs/architecture/adrs/011-pgai-integration.md +494 -0
  84. data/docs/architecture/adrs/index.md +215 -0
  85. data/docs/architecture/hive-mind.md +736 -0
  86. data/docs/architecture/index.md +351 -0
  87. data/docs/architecture/overview.md +538 -0
  88. data/docs/architecture/two-tier-memory.md +873 -0
  89. data/docs/assets/css/custom.css +83 -0
  90. data/docs/assets/images/htm-core-components.svg +63 -0
  91. data/docs/assets/images/htm-database-schema.svg +93 -0
  92. data/docs/assets/images/htm-hive-mind-architecture.svg +125 -0
  93. data/docs/assets/images/htm-importance-scoring-framework.svg +83 -0
  94. data/docs/assets/images/htm-layered-architecture.svg +71 -0
  95. data/docs/assets/images/htm-long-term-memory-architecture.svg +115 -0
  96. data/docs/assets/images/htm-working-memory-architecture.svg +120 -0
  97. data/docs/assets/images/htm.jpg +0 -0
  98. data/docs/assets/images/htm_demo.gif +0 -0
  99. data/docs/assets/js/mathjax.js +18 -0
  100. data/docs/assets/videos/htm_video.mp4 +0 -0
  101. data/docs/database_rake_tasks.md +322 -0
  102. data/docs/development/contributing.md +787 -0
  103. data/docs/development/index.md +336 -0
  104. data/docs/development/schema.md +596 -0
  105. data/docs/development/setup.md +719 -0
  106. data/docs/development/testing.md +819 -0
  107. data/docs/guides/adding-memories.md +824 -0
  108. data/docs/guides/context-assembly.md +1009 -0
  109. data/docs/guides/getting-started.md +577 -0
  110. data/docs/guides/index.md +118 -0
  111. data/docs/guides/long-term-memory.md +941 -0
  112. data/docs/guides/multi-robot.md +866 -0
  113. data/docs/guides/recalling-memories.md +927 -0
  114. data/docs/guides/search-strategies.md +953 -0
  115. data/docs/guides/working-memory.md +717 -0
  116. data/docs/index.md +214 -0
  117. data/docs/installation.md +477 -0
  118. data/docs/multi_framework_support.md +519 -0
  119. data/docs/quick-start.md +655 -0
  120. data/docs/setup_local_database.md +302 -0
  121. data/docs/using_rake_tasks_in_your_app.md +383 -0
  122. data/examples/basic_usage.rb +93 -0
  123. data/examples/cli_app/README.md +317 -0
  124. data/examples/cli_app/htm_cli.rb +270 -0
  125. data/examples/custom_llm_configuration.rb +183 -0
  126. data/examples/example_app/Rakefile +71 -0
  127. data/examples/example_app/app.rb +206 -0
  128. data/examples/sinatra_app/Gemfile +21 -0
  129. data/examples/sinatra_app/app.rb +335 -0
  130. data/lib/htm/active_record_config.rb +113 -0
  131. data/lib/htm/configuration.rb +342 -0
  132. data/lib/htm/database.rb +594 -0
  133. data/lib/htm/embedding_service.rb +115 -0
  134. data/lib/htm/errors.rb +34 -0
  135. data/lib/htm/job_adapter.rb +154 -0
  136. data/lib/htm/jobs/generate_embedding_job.rb +65 -0
  137. data/lib/htm/jobs/generate_tags_job.rb +82 -0
  138. data/lib/htm/long_term_memory.rb +965 -0
  139. data/lib/htm/models/node.rb +109 -0
  140. data/lib/htm/models/node_tag.rb +33 -0
  141. data/lib/htm/models/robot.rb +52 -0
  142. data/lib/htm/models/tag.rb +76 -0
  143. data/lib/htm/railtie.rb +76 -0
  144. data/lib/htm/sinatra.rb +157 -0
  145. data/lib/htm/tag_service.rb +135 -0
  146. data/lib/htm/tasks.rb +38 -0
  147. data/lib/htm/version.rb +5 -0
  148. data/lib/htm/working_memory.rb +182 -0
  149. data/lib/htm.rb +400 -0
  150. data/lib/tasks/db.rake +19 -0
  151. data/lib/tasks/htm.rake +147 -0
  152. data/lib/tasks/jobs.rake +312 -0
  153. data/mkdocs.yml +190 -0
  154. data/scripts/install_local_database.sh +309 -0
  155. metadata +341 -0
@@ -0,0 +1,625 @@
1
+ # ADR-008: Robot Identification System
2
+
3
+ **Status**: Accepted
4
+
5
+ **Date**: 2025-10-25
6
+
7
+ **Decision Makers**: Dewayne VanHoozer, Claude (Anthropic)
8
+
9
+ ---
10
+
11
+ ## Quick Summary
12
+
13
+ HTM uses a **dual-identifier system** with mandatory unique `robot_id` (UUID) and optional human-readable `robot_name`. Both are auto-generated if not provided, with automatic robot registration and activity tracking in the database.
14
+
15
+ **Why**: Unique robot identification enables memory attribution, cross-robot analytics, debugging, and future features like permissions and groups while maintaining developer-friendly names.
16
+
17
+ **Impact**: Globally unique identity with human-readable names and automatic management, at the cost of dual identifiers and manual persistence requirements for stable identities.
18
+
19
+ ---
20
+
21
+ ## Context
22
+
23
+ In the HTM hive mind architecture (ADR-004), multiple robots share a global memory database. Each robot needs a unique identity to:
24
+
25
+ - Attribute memories to their creator
26
+ - Track robot activity over time
27
+ - Enable queries like "which robot said this?"
28
+ - Debug conversation attribution
29
+ - Support future features (privacy, analytics, collaboration)
30
+
31
+ ### Identity Requirements
32
+
33
+ - **Uniqueness**: Must be globally unique (no collisions)
34
+ - **Persistence**: Should remain stable across sessions
35
+ - **Human-readable**: Developers need to identify robots easily
36
+ - **Automation**: Should auto-generate if not provided
37
+ - **Registration**: Track all robots using the system
38
+
39
+ ### Alternative Identification Schemes
40
+
41
+ 1. **Auto-generated UUID only**: Unique but not human-readable
42
+ 2. **User-provided name only**: Readable but collision-prone
43
+ 3. **UUID + optional name**: Unique ID with optional readable name
44
+ 4. **Sequential ID**: Simple but requires coordination
45
+ 5. **Hostname + PID**: Automatic but not persistent across restarts
46
+
47
+ ---
48
+
49
+ ## Decision
50
+
51
+ We will use a **dual-identifier system**: mandatory unique `robot_id` (UUID) + optional human-readable `robot_name`, with automatic generation if not provided.
52
+
53
+ ### Robot Identification Components
54
+
55
+ **1. Robot ID (`robot_id`)**
56
+
57
+ - **Type**: UUID v4 (RFC 4122)
58
+ - **Format**: `"f47ac10b-58cc-4372-a567-0e02b2c3d479"`
59
+ - **Generation**: `SecureRandom.uuid` if not provided
60
+ - **Persistence**: User-provided for stability, or auto-generated per session
61
+ - **Usage**: Primary key, foreign key references, attribution
62
+
63
+ **2. Robot Name (`robot_name`)**
64
+
65
+ - **Type**: String (optional, human-readable)
66
+ - **Format**: Any descriptive string (e.g., "Code Helper", "Research Assistant")
67
+ - **Generation**: `"robot_#{robot_id[0..7]}"` if not provided
68
+ - **Persistence**: Stored in database, updatable
69
+ - **Usage**: Display, debugging, user interfaces
70
+
71
+ ---
72
+
73
+ ## Rationale
74
+
75
+ ### Why UUID + Name?
76
+
77
+ **UUID provides guarantees**:
78
+
79
+ - Globally unique (collision probability: ~10^-36)
80
+ - No coordination required (decentralized generation)
81
+ - Cryptographically random (unpredictable)
82
+ - Standard format (RFC 4122, widely supported)
83
+
84
+ **Name provides usability**:
85
+
86
+ - Human-readable in logs and debugging
87
+ - Meaningful for user-facing features
88
+ - Easy to remember ("Code Helper" vs UUID)
89
+ - Updatable without breaking references
90
+
91
+ **Combination is best**:
92
+
93
+ - UUID for database integrity
94
+ - Name for developer experience
95
+ - Auto-generation for convenience
96
+ - User control for persistence
97
+
98
+ ### Why Auto-Generate?
99
+
100
+ **Convenience**:
101
+
102
+ - Users don't need to manage UUIDs manually
103
+ - Works out-of-box with no configuration
104
+ - Still allows explicit robot_id for persistence
105
+
106
+ **Session vs Persistent Identity**:
107
+
108
+ - **Session identity**: Auto-generated UUID, ephemeral robot
109
+ - **Persistent identity**: User-provided UUID, stable across restarts
110
+
111
+ ```ruby
112
+ # Ephemeral robot (new UUID every session)
113
+ htm = HTM.new(robot_name: "Temp Helper")
114
+
115
+ # Persistent robot (same UUID across sessions)
116
+ ROBOT_ID = "f47ac10b-58cc-4372-a567-0e02b2c3d479"
117
+ htm = HTM.new(robot_id: ROBOT_ID, robot_name: "Persistent Helper")
118
+ ```
119
+
120
+ ### Why Register Robots?
121
+
122
+ **Activity tracking**:
123
+
124
+ - Know which robots are active
125
+ - Monitor robot usage patterns
126
+ - Identify inactive robots for cleanup
127
+
128
+ **Metadata extensibility**:
129
+
130
+ - Future: Robot roles, permissions, preferences
131
+ - Future: Robot groups/teams
132
+ - Future: Configuration per robot
133
+
134
+ **Debugging**:
135
+
136
+ - "Which robot created this memory?"
137
+ - "What has this robot been doing?"
138
+ - "When was this robot last active?"
139
+
140
+ ---
141
+
142
+ ## Implementation Details
143
+
144
+ ### Robot Registry
145
+
146
+ ```sql
147
+ CREATE TABLE robots (
148
+ id TEXT PRIMARY KEY, -- robot_id (UUID)
149
+ name TEXT, -- robot_name (human-readable)
150
+ created_at TIMESTAMP DEFAULT NOW(),
151
+ last_active TIMESTAMP DEFAULT NOW(),
152
+ metadata JSONB -- future extensibility
153
+ );
154
+ ```
155
+
156
+ ### Robot Attribution
157
+
158
+ Every memory node stores `robot_id`:
159
+
160
+ ```sql
161
+ CREATE TABLE nodes (
162
+ id SERIAL PRIMARY KEY,
163
+ key TEXT UNIQUE NOT NULL,
164
+ value TEXT NOT NULL,
165
+ robot_id TEXT NOT NULL REFERENCES robots(id), -- Attribution
166
+ ...
167
+ );
168
+ ```
169
+
170
+ ### Initialization
171
+
172
+ ```ruby
173
+ htm = HTM.new(
174
+ robot_id: "f47ac10b-58cc-4372-a567-0e02b2c3d479", # optional, auto-generated
175
+ robot_name: "Code Helper" # optional, descriptive
176
+ )
177
+
178
+ # Auto-generated example:
179
+ # robot_id: "3a7b2c4d-8e9f-4a5b-9c8d-7e6f5a4b3c2d"
180
+ # robot_name: "robot_3a7b2c4d"
181
+ ```
182
+
183
+ ### Registration Logic
184
+
185
+ **Upsert semantics**:
186
+
187
+ ```sql
188
+ INSERT INTO robots (id, name)
189
+ VALUES ($1, $2)
190
+ ON CONFLICT (id) DO UPDATE
191
+ SET name = $2, last_active = CURRENT_TIMESTAMP
192
+ ```
193
+
194
+ - Automatic on first HTM initialization
195
+ - Updates name and last_active if robot_id exists
196
+ - Activity tracking: `last_active` updated on every operation
197
+
198
+ ---
199
+
200
+ ## Consequences
201
+
202
+ ### Positive
203
+
204
+ - Uniqueness guaranteed: UUID collision-proof
205
+ - Human-readable: Names easy to identify in logs
206
+ - Auto-generation: Works without manual configuration
207
+ - Persistence option: User can provide stable robot_id
208
+ - Attribution tracking: Every memory linked to creator
209
+ - Activity monitoring: Track robot usage over time
210
+ - Future-proof: Metadata field for extensibility
211
+ - Standard format: UUID is widely recognized
212
+
213
+ ### Negative
214
+
215
+ - Dual identifiers: Two fields instead of one (complexity)
216
+ - Name collisions: Names not unique (only IDs are)
217
+ - Manual persistence: User must manage robot_id for stability
218
+ - No automatic migration: Robot ID changes break historical attribution
219
+ - UUID verbosity: UUIDs are long (36 characters)
220
+
221
+ ### Neutral
222
+
223
+ - Session vs persistent: User chooses ephemeral or stable identity
224
+ - Name mutability: Names can be updated, IDs cannot
225
+ - Registry cleanup: Inactive robots accumulate (manual cleanup needed)
226
+
227
+ ---
228
+
229
+ ## Use Cases
230
+
231
+ ### Use Case 1: Ephemeral Robot (Session Identity)
232
+
233
+ ```ruby
234
+ # New UUID generated every time
235
+ htm = HTM.new(robot_name: "Quick Helper")
236
+
237
+ # robot_id: auto-generated UUID
238
+ # robot_name: "Quick Helper"
239
+
240
+ # Next session: different robot_id, same name
241
+ # Memories attributed to different robot each time
242
+ ```
243
+
244
+ ### Use Case 2: Persistent Robot (Stable Identity)
245
+
246
+ ```ruby
247
+ # Store robot_id in config or environment
248
+ ROBOT_ID = ENV['ROBOT_ID'] || "f47ac10b-58cc-4372-a567-0e02b2c3d479"
249
+
250
+ htm = HTM.new(
251
+ robot_id: ROBOT_ID,
252
+ robot_name: "Code Helper"
253
+ )
254
+
255
+ # Same robot_id across sessions
256
+ # Memories consistently attributed to this robot
257
+ ```
258
+
259
+ ### Use Case 3: Multiple Robots in Same Process
260
+
261
+ ```ruby
262
+ # Research assistant
263
+ research_bot = HTM.new(
264
+ robot_id: "research-001",
265
+ robot_name: "Research Assistant"
266
+ )
267
+
268
+ # Code helper
269
+ code_bot = HTM.new(
270
+ robot_id: "code-001",
271
+ robot_name: "Code Helper"
272
+ )
273
+
274
+ # Each robot has own working memory
275
+ # Both share same long-term memory database
276
+ # Memories attributed to respective robots
277
+ ```
278
+
279
+ ### Use Case 4: Robot Activity Analysis
280
+
281
+ ```sql
282
+ -- Which robots have been active?
283
+ SELECT id, name, last_active
284
+ FROM robots
285
+ ORDER BY last_active DESC;
286
+
287
+ -- Which robot contributed most memories?
288
+ SELECT robot_id, COUNT(*) as memory_count
289
+ FROM nodes
290
+ GROUP BY robot_id
291
+ ORDER BY memory_count DESC;
292
+
293
+ -- What has "Code Helper" been doing?
294
+ SELECT operation, created_at, details
295
+ FROM operations_log
296
+ WHERE robot_id = (SELECT id FROM robots WHERE name = 'Code Helper')
297
+ ORDER BY created_at DESC
298
+ LIMIT 50;
299
+ ```
300
+
301
+ ### Use Case 5: Conversation Attribution
302
+
303
+ ```ruby
304
+ # Which robot discussed PostgreSQL?
305
+ breakdown = htm.which_robot_said("PostgreSQL")
306
+ # => { "f47ac10b-..." => 15, "3a7b2c4d-..." => 8 }
307
+
308
+ # Get robot names
309
+ robot_names = breakdown.keys.map do |robot_id|
310
+ db.query("SELECT name FROM robots WHERE id = $1", [robot_id]).first
311
+ end
312
+ ```
313
+
314
+ ---
315
+
316
+ ## Robot Identity Lifecycle
317
+
318
+ ### 1. Creation
319
+
320
+ ```ruby
321
+ htm = HTM.new(robot_id: uuid, robot_name: name)
322
+ ```
323
+
324
+ ### 2. Registration
325
+
326
+ ```sql
327
+ INSERT INTO robots (id, name, created_at, last_active)
328
+ VALUES (uuid, name, NOW(), NOW())
329
+ ON CONFLICT (id) DO UPDATE SET name = name, last_active = NOW()
330
+ ```
331
+
332
+ ### 3. Activity Tracking
333
+
334
+ ```ruby
335
+ # On every HTM operation (add_node, recall, forget, retrieve)
336
+ @long_term_memory.update_robot_activity(@robot_id)
337
+ ```
338
+
339
+ ```sql
340
+ UPDATE robots
341
+ SET last_active = CURRENT_TIMESTAMP
342
+ WHERE id = robot_id
343
+ ```
344
+
345
+ ### 4. Attribution
346
+
347
+ ```ruby
348
+ # Every node stores robot_id
349
+ node_id = @long_term_memory.add(
350
+ key: key,
351
+ value: value,
352
+ robot_id: @robot_id, # Attribution
353
+ ...
354
+ )
355
+ ```
356
+
357
+ ### 5. Querying
358
+
359
+ ```sql
360
+ -- Find memories by robot
361
+ SELECT * FROM nodes WHERE robot_id = 'f47ac10b-...'
362
+
363
+ -- Find robot by name
364
+ SELECT * FROM robots WHERE name = 'Code Helper'
365
+ ```
366
+
367
+ ### 6. Cleanup (Manual)
368
+
369
+ ```sql
370
+ -- Find inactive robots
371
+ SELECT * FROM robots WHERE last_active < NOW() - INTERVAL '30 days';
372
+
373
+ -- Delete robot and all its memories (use with caution!)
374
+ DELETE FROM nodes WHERE robot_id = 'f47ac10b-...';
375
+ DELETE FROM robots WHERE id = 'f47ac10b-...';
376
+ ```
377
+
378
+ ---
379
+
380
+ ## Performance Characteristics
381
+
382
+ ### UUID Generation
383
+
384
+ - **Time**: < 1ms (SecureRandom.uuid)
385
+ - **Collision probability**: ~10^-36 for v4 UUID
386
+ - **Entropy**: 122 random bits
387
+
388
+ ### Robot Registration
389
+
390
+ - **Upsert query**: < 5ms
391
+ - **Index**: Primary key on `robots.id`
392
+ - **Frequency**: Once per HTM initialization
393
+
394
+ ### Activity Tracking
395
+
396
+ - **Update query**: < 2ms
397
+ - **Frequency**: Every HTM operation
398
+ - **Index**: Primary key on `robots.id`
399
+
400
+ ### Attribution Queries
401
+
402
+ - **Foreign key join**: O(log n) with index
403
+ - **Index**: `nodes.robot_id` indexed as foreign key
404
+
405
+ ---
406
+
407
+ ## Design Decisions
408
+
409
+ ### Decision: UUID v4 (Random) Instead of UUID v1 (Timestamp)
410
+
411
+ **Rationale**:
412
+
413
+ - No MAC address leakage (privacy)
414
+ - Cryptographically random (security)
415
+ - No clock synchronization needed
416
+
417
+ **Alternative**: UUID v1 (timestamp-based)
418
+
419
+ **Rejected**: MAC address exposure, clock sync issues
420
+
421
+ ### Decision: Optional robot_id, Mandatory robot_name
422
+
423
+ **Rationale**: Auto-generate both if not provided, allow user override
424
+
425
+ **Alternative**: Require user to provide robot_id
426
+
427
+ **Rejected**: Too much friction, poor DX
428
+
429
+ ### Decision: Auto-Generated Name Format
430
+
431
+ **Rationale**: `"robot_#{uuid[0..7]}"` provides:
432
+
433
+ - Uniqueness (first 8 chars usually unique)
434
+ - Traceability (prefix of robot_id)
435
+ - Consistency (predictable format)
436
+
437
+ **Alternative**: Random adjective + noun ("Happy Robot")
438
+
439
+ **Rejected**: Harder to correlate with robot_id
440
+
441
+ ### Decision: Upsert Semantics for Registration
442
+
443
+ **Rationale**: Allows robot_name updates, prevents duplicate registration errors
444
+
445
+ **Alternative**: Strict insert-only (error on duplicate)
446
+
447
+ **Rejected**: Prevents name updates, complicates initialization
448
+
449
+ ### Decision: JSONB Metadata Field
450
+
451
+ **Rationale**: Future extensibility without schema migrations
452
+
453
+ **Alternative**: Add columns as needed
454
+
455
+ **Deferred**: JSONB is flexible, add columns for indexed fields later
456
+
457
+ ---
458
+
459
+ ## Risks and Mitigations
460
+
461
+ ### Risk: Robot ID Changes Break Attribution
462
+
463
+ !!! danger "Risk"
464
+ User changes robot_id, breaks historical attribution
465
+
466
+ **Likelihood**: Low (user must explicitly change)
467
+
468
+ **Impact**: High (attribution lost)
469
+
470
+ **Mitigation**:
471
+
472
+ - Document robot_id persistence clearly
473
+ - Recommend storing robot_id in config
474
+ - Consider robot_id migration tool (future)
475
+
476
+ ### Risk: Name Collisions
477
+
478
+ !!! info "Risk"
479
+ Multiple robots with same name
480
+
481
+ **Likelihood**: Medium (names not enforced unique)
482
+
483
+ **Impact**: Low (IDs are unique, names just for display)
484
+
485
+ **Mitigation**:
486
+
487
+ - Document that names are not unique
488
+ - Use robot_id for queries, name for display
489
+ - Consider unique constraint on name (future)
490
+
491
+ ### Risk: Robot Registry Growth
492
+
493
+ !!! warning "Risk"
494
+ Inactive robots accumulate indefinitely
495
+
496
+ **Likelihood**: High (no automatic cleanup)
497
+
498
+ **Impact**: Low (storage, query slowdown)
499
+
500
+ **Mitigation**:
501
+
502
+ - Document cleanup procedures
503
+ - Provide cleanup utilities (future)
504
+ - Monitor robot registry size
505
+
506
+ ### Risk: UUID Verbosity
507
+
508
+ !!! info "Risk"
509
+ UUIDs are long (36 chars) in logs
510
+
511
+ **Likelihood**: High (by design)
512
+
513
+ **Impact**: Low (readability in logs)
514
+
515
+ **Mitigation**:
516
+
517
+ - Use robot_name for logging
518
+ - Truncate UUID for display: `robot_id[0..7]`
519
+ - Full UUID available for debugging
520
+
521
+ ---
522
+
523
+ ## Future Enhancements
524
+
525
+ ### Robot Groups/Teams
526
+
527
+ ```ruby
528
+ # Assign robots to teams
529
+ robot_team = db.exec("INSERT INTO robot_teams (robot_id, team_name) VALUES ($1, $2)",
530
+ [robot_id, "coding-team"])
531
+
532
+ # Query by team
533
+ memories = htm.recall(robot_team: "coding-team", topic: "APIs")
534
+ ```
535
+
536
+ ### Robot Permissions
537
+
538
+ ```ruby
539
+ # Role-based access control
540
+ robot_role = db.exec("INSERT INTO robot_roles (robot_id, role) VALUES ($1, $2)",
541
+ [robot_id, "admin"])
542
+
543
+ # Restrict operations by role
544
+ htm.forget(key, confirm: :confirmed) # Requires admin role
545
+ ```
546
+
547
+ ### Robot Configuration
548
+
549
+ ```ruby
550
+ # Per-robot settings
551
+ htm = HTM.new(
552
+ robot_id: uuid,
553
+ robot_name: name,
554
+ robot_config: {
555
+ embedding_model: "custom-model",
556
+ working_memory_size: 256_000,
557
+ preferences: { language: "en" }
558
+ }
559
+ )
560
+ ```
561
+
562
+ ### Robot Migration Tool
563
+
564
+ ```ruby
565
+ # Migrate memories from old robot_id to new one
566
+ HTM::Migration.migrate_robot(
567
+ from: "old-robot-id",
568
+ to: "new-robot-id"
569
+ )
570
+
571
+ # Updates all nodes.robot_id references
572
+ # Merges robot registry entries
573
+ ```
574
+
575
+ ### Short Robot IDs
576
+
577
+ ```ruby
578
+ # Generate shorter IDs (like GitHub: 7 chars)
579
+ short_id = SecureRandom.hex(4) # "3a7b2c4d"
580
+
581
+ htm = HTM.new(
582
+ robot_id: short_id,
583
+ robot_name: "Helper"
584
+ )
585
+
586
+ # Trade-off: Lower collision resistance, better readability
587
+ ```
588
+
589
+ ---
590
+
591
+ ## Alternatives Comparison
592
+
593
+ | Approach | Pros | Cons | Decision |
594
+ |----------|------|------|----------|
595
+ | **UUID + Name** | **Unique + readable** | **Dual identifiers** | **ACCEPTED** |
596
+ | UUID Only | Simple, guaranteed unique | Not human-readable | Rejected |
597
+ | Name Only | Simple, readable | Collision-prone | Rejected |
598
+ | Sequential IDs | Short, sortable | Requires coordination | Rejected |
599
+ | Hostname + PID | Automatic | Not persistent | Rejected |
600
+ | ULID | Sortable, shorter | Less standard | Deferred |
601
+
602
+ ---
603
+
604
+ ## References
605
+
606
+ - [RFC 4122: UUID Specification](https://tools.ietf.org/html/rfc4122)
607
+ - [UUID v4 (Random)](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))
608
+ - [ULID Specification](https://github.com/ulid/spec)
609
+ - [Robot Registry Pattern](https://martinfowler.com/eaaCatalog/registry.html)
610
+ - [ADR-004: Hive Mind Architecture](004-hive-mind.md)
611
+ - [Multi-Robot Guide](../../guides/multi-robot.md)
612
+
613
+ ---
614
+
615
+ ## Review Notes
616
+
617
+ **Systems Architect**: UUID + name is the right balance. Consider ULID for future versions.
618
+
619
+ **Database Architect**: Foreign key on robot_id is correct. Index on `nodes.robot_id` for attribution queries.
620
+
621
+ **Ruby Expert**: SecureRandom.uuid is standard. Consider `robot_id: SecureRandom.uuid` as default parameter.
622
+
623
+ **Security Specialist**: UUID v4 is cryptographically secure. No MAC address leakage.
624
+
625
+ **Domain Expert**: Auto-generation + manual override gives flexibility. Document persistence clearly.