@prmichaelsen/remember-mcp 3.0.0 → 3.12.0

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 (208) hide show
  1. package/AGENT.md +296 -250
  2. package/CHANGELOG.md +338 -0
  3. package/README.md +68 -45
  4. package/agent/commands/acp.clarification-create.md +382 -0
  5. package/agent/commands/acp.project-info.md +309 -0
  6. package/agent/commands/acp.project-remove.md +379 -0
  7. package/agent/commands/acp.project-update.md +296 -0
  8. package/agent/commands/acp.task-create.md +17 -9
  9. package/agent/commands/git.commit.md +13 -1
  10. package/agent/design/comment-memory-type.md +2 -2
  11. package/agent/design/local.collaborative-memory-sync.md +265 -0
  12. package/agent/design/local.content-flags.md +210 -0
  13. package/agent/design/local.ghost-persona-system.md +273 -0
  14. package/agent/design/local.group-acl-integration.md +338 -0
  15. package/agent/design/local.memory-acl-schema.md +352 -0
  16. package/agent/design/local.memory-collection-pattern-v2.md +348 -0
  17. package/agent/design/local.moderation-and-space-config.md +257 -0
  18. package/agent/design/local.v2-api-reference.md +621 -0
  19. package/agent/design/local.v2-migration-guide.md +191 -0
  20. package/agent/design/local.v2-usage-examples.md +265 -0
  21. package/agent/design/permissions-storage-architecture.md +11 -3
  22. package/agent/design/trust-escalation-prevention.md +9 -2
  23. package/agent/design/trust-system-implementation.md +12 -3
  24. package/agent/milestones/milestone-14-memory-collection-v2.md +182 -0
  25. package/agent/milestones/milestone-15-moderation-space-config.md +126 -0
  26. package/agent/progress.yaml +628 -49
  27. package/agent/scripts/acp.common.sh +2 -0
  28. package/agent/scripts/acp.install.sh +11 -1
  29. package/agent/scripts/acp.package-install-optimized.sh +454 -0
  30. package/agent/scripts/acp.package-install.sh +247 -300
  31. package/agent/scripts/acp.project-info.sh +218 -0
  32. package/agent/scripts/acp.project-remove.sh +302 -0
  33. package/agent/scripts/acp.project-update.sh +296 -0
  34. package/agent/scripts/acp.yaml-parser.sh +128 -10
  35. package/agent/tasks/milestone-14-memory-collection-v2/task-165-core-infrastructure-setup.md +171 -0
  36. package/agent/tasks/milestone-14-memory-collection-v2/task-166-update-remember-publish.md +191 -0
  37. package/agent/tasks/milestone-14-memory-collection-v2/task-167-update-remember-retract.md +186 -0
  38. package/agent/tasks/milestone-14-memory-collection-v2/task-168-implement-remember-revise.md +184 -0
  39. package/agent/tasks/milestone-14-memory-collection-v2/task-169-update-remember-search-space.md +179 -0
  40. package/agent/tasks/milestone-14-memory-collection-v2/task-170-update-remember-create-update.md +139 -0
  41. package/agent/tasks/milestone-14-memory-collection-v2/task-172-performance-testing-optimization.md +161 -0
  42. package/agent/tasks/milestone-14-memory-collection-v2/task-173-documentation-examples.md +258 -0
  43. package/agent/tasks/milestone-15-moderation-space-config/task-174-add-moderation-schema-fields.md +57 -0
  44. package/agent/tasks/milestone-15-moderation-space-config/task-175-create-space-config-service.md +64 -0
  45. package/agent/tasks/milestone-15-moderation-space-config/task-176-wire-moderation-publish-flow.md +45 -0
  46. package/agent/tasks/milestone-15-moderation-space-config/task-177-add-moderation-search-filters.md +70 -0
  47. package/agent/tasks/milestone-15-moderation-space-config/task-178-create-remember-moderate-tool.md +69 -0
  48. package/agent/tasks/milestone-15-moderation-space-config/task-179-documentation-integration-tests.md +58 -0
  49. package/agent/tasks/milestone-16-ghost-system/task-187-ghost-config-firestore.md +41 -0
  50. package/agent/tasks/milestone-16-ghost-system/task-188-trust-filter-integration.md +44 -0
  51. package/agent/tasks/milestone-16-ghost-system/task-189-ghost-memory-filtering.md +43 -0
  52. package/agent/tasks/milestone-16-ghost-system/task-190-ghost-config-tools.md +45 -0
  53. package/agent/tasks/milestone-16-ghost-system/task-191-escalation-firestore.md +38 -0
  54. package/agent/tasks/milestone-16-ghost-system/task-192-documentation-verification.md +39 -0
  55. package/agent/tasks/milestone-7-trust-permissions/task-180-access-result-permission-types.md +69 -0
  56. package/agent/tasks/milestone-7-trust-permissions/task-181-firestore-permissions-access-logs.md +56 -0
  57. package/agent/tasks/milestone-7-trust-permissions/task-182-trust-enforcement-service.md +68 -0
  58. package/agent/tasks/milestone-7-trust-permissions/task-183-access-control-service.md +70 -0
  59. package/agent/tasks/milestone-7-trust-permissions/task-184-permission-tools.md +79 -0
  60. package/agent/tasks/milestone-7-trust-permissions/task-185-wire-trust-into-search-query.md +55 -0
  61. package/agent/tasks/milestone-7-trust-permissions/task-186-documentation-verification.md +56 -0
  62. package/agent/tasks/task-76-fix-indexnullstate-schema-bug.md +197 -0
  63. package/dist/collections/composite-ids.d.ts +106 -0
  64. package/dist/collections/core-infrastructure.spec.d.ts +11 -0
  65. package/dist/collections/dot-notation.d.ts +106 -0
  66. package/dist/collections/tracking-arrays.d.ts +176 -0
  67. package/dist/constants/content-types.d.ts +1 -0
  68. package/dist/schema/v2-collections-comments.spec.d.ts +8 -0
  69. package/dist/schema/v2-collections.d.ts +210 -0
  70. package/dist/server-factory.d.ts +15 -0
  71. package/dist/server-factory.js +2798 -1029
  72. package/dist/server.js +2526 -1012
  73. package/dist/services/access-control.d.ts +103 -0
  74. package/dist/services/access-control.spec.d.ts +2 -0
  75. package/dist/services/credentials-provider.d.ts +24 -0
  76. package/dist/services/credentials-provider.spec.d.ts +2 -0
  77. package/dist/services/escalation.service.d.ts +22 -0
  78. package/dist/services/escalation.service.spec.d.ts +2 -0
  79. package/dist/services/ghost-config.service.d.ts +55 -0
  80. package/dist/services/ghost-config.service.spec.d.ts +2 -0
  81. package/dist/services/space-config.service.d.ts +23 -0
  82. package/dist/services/space-config.service.spec.d.ts +2 -0
  83. package/dist/services/trust-enforcement.d.ts +83 -0
  84. package/dist/services/trust-enforcement.spec.d.ts +2 -0
  85. package/dist/services/trust-validator.d.ts +43 -0
  86. package/dist/services/trust-validator.spec.d.ts +2 -0
  87. package/dist/tools/confirm-publish-moderation.spec.d.ts +8 -0
  88. package/dist/tools/confirm.d.ts +8 -1
  89. package/dist/tools/create-memory.d.ts +2 -1
  90. package/dist/tools/create-memory.spec.d.ts +10 -0
  91. package/dist/tools/create-relationship.d.ts +2 -1
  92. package/dist/tools/delete-memory.d.ts +2 -1
  93. package/dist/tools/delete-relationship.d.ts +2 -1
  94. package/dist/tools/deny.d.ts +2 -1
  95. package/dist/tools/find-similar.d.ts +2 -1
  96. package/dist/tools/get-preferences.d.ts +2 -1
  97. package/dist/tools/ghost-config.d.ts +27 -0
  98. package/dist/tools/ghost-config.spec.d.ts +2 -0
  99. package/dist/tools/moderate.d.ts +20 -0
  100. package/dist/tools/moderate.spec.d.ts +5 -0
  101. package/dist/tools/publish.d.ts +11 -3
  102. package/dist/tools/query-memory.d.ts +3 -1
  103. package/dist/tools/query-space.d.ts +4 -1
  104. package/dist/tools/retract.d.ts +29 -0
  105. package/dist/tools/revise.d.ts +45 -0
  106. package/dist/tools/revise.spec.d.ts +8 -0
  107. package/dist/tools/search-memory.d.ts +2 -1
  108. package/dist/tools/search-relationship.d.ts +2 -1
  109. package/dist/tools/search-space.d.ts +25 -5
  110. package/dist/tools/search-space.spec.d.ts +9 -0
  111. package/dist/tools/set-preference.d.ts +2 -1
  112. package/dist/tools/update-memory.d.ts +2 -1
  113. package/dist/tools/update-relationship.d.ts +2 -1
  114. package/dist/types/access-result.d.ts +48 -0
  115. package/dist/types/access-result.spec.d.ts +2 -0
  116. package/dist/types/auth.d.ts +46 -0
  117. package/dist/types/ghost-config.d.ts +36 -0
  118. package/dist/types/memory.d.ts +3 -1
  119. package/dist/types/preferences.d.ts +1 -1
  120. package/dist/utils/auth-helpers.d.ts +14 -0
  121. package/dist/utils/auth-helpers.spec.d.ts +2 -0
  122. package/dist/utils/test-data-generator.d.ts +124 -0
  123. package/dist/utils/test-data-generator.spec.d.ts +12 -0
  124. package/dist/v2-performance.e2e.d.ts +17 -0
  125. package/dist/v2-smoke.e2e.d.ts +14 -0
  126. package/dist/weaviate/client.d.ts +5 -8
  127. package/dist/weaviate/space-schema.d.ts +2 -2
  128. package/docs/performance/v2-benchmarks.md +80 -0
  129. package/jest.e2e.config.js +14 -3
  130. package/package.json +1 -1
  131. package/scripts/.collection-recreation-state.yaml +16 -0
  132. package/scripts/.gitkeep +5 -0
  133. package/scripts/README-collection-recreation.md +224 -0
  134. package/scripts/README.md +51 -0
  135. package/scripts/backup-collections.ts +543 -0
  136. package/scripts/delete-collection.ts +137 -0
  137. package/scripts/migrate-recreate-collections.ts +578 -0
  138. package/scripts/migrate-v1-to-v2.ts +1094 -0
  139. package/scripts/package-lock.json +1113 -0
  140. package/scripts/package.json +27 -0
  141. package/src/collections/composite-ids.ts +193 -0
  142. package/src/collections/core-infrastructure.spec.ts +353 -0
  143. package/src/collections/dot-notation.ts +212 -0
  144. package/src/collections/tracking-arrays.ts +298 -0
  145. package/src/constants/content-types.ts +20 -0
  146. package/src/schema/v2-collections-comments.spec.ts +141 -0
  147. package/src/schema/v2-collections.ts +433 -0
  148. package/src/server-factory.ts +89 -20
  149. package/src/server.ts +45 -17
  150. package/src/services/access-control.spec.ts +383 -0
  151. package/src/services/access-control.ts +291 -0
  152. package/src/services/credentials-provider.spec.ts +22 -0
  153. package/src/services/credentials-provider.ts +34 -0
  154. package/src/services/escalation.service.spec.ts +183 -0
  155. package/src/services/escalation.service.ts +150 -0
  156. package/src/services/ghost-config.service.spec.ts +339 -0
  157. package/src/services/ghost-config.service.ts +219 -0
  158. package/src/services/space-config.service.spec.ts +102 -0
  159. package/src/services/space-config.service.ts +79 -0
  160. package/src/services/trust-enforcement.spec.ts +309 -0
  161. package/src/services/trust-enforcement.ts +197 -0
  162. package/src/services/trust-validator.spec.ts +108 -0
  163. package/src/services/trust-validator.ts +105 -0
  164. package/src/tools/confirm-publish-moderation.spec.ts +240 -0
  165. package/src/tools/confirm.ts +869 -135
  166. package/src/tools/create-memory.spec.ts +126 -0
  167. package/src/tools/create-memory.ts +20 -27
  168. package/src/tools/create-relationship.ts +17 -8
  169. package/src/tools/delete-memory.ts +13 -6
  170. package/src/tools/delete-relationship.ts +15 -6
  171. package/src/tools/deny.ts +8 -1
  172. package/src/tools/find-similar.ts +21 -8
  173. package/src/tools/get-preferences.ts +10 -1
  174. package/src/tools/ghost-config.spec.ts +180 -0
  175. package/src/tools/ghost-config.ts +230 -0
  176. package/src/tools/moderate.spec.ts +277 -0
  177. package/src/tools/moderate.ts +219 -0
  178. package/src/tools/publish.ts +99 -41
  179. package/src/tools/query-memory.ts +28 -6
  180. package/src/tools/query-space.ts +39 -4
  181. package/src/tools/retract.ts +292 -0
  182. package/src/tools/revise.spec.ts +146 -0
  183. package/src/tools/revise.ts +283 -0
  184. package/src/tools/search-memory.ts +30 -7
  185. package/src/tools/search-relationship.ts +11 -2
  186. package/src/tools/search-space.spec.ts +341 -0
  187. package/src/tools/search-space.ts +323 -99
  188. package/src/tools/set-preference.ts +10 -1
  189. package/src/tools/update-memory.ts +16 -5
  190. package/src/tools/update-relationship.ts +10 -1
  191. package/src/types/access-result.spec.ts +193 -0
  192. package/src/types/access-result.ts +62 -0
  193. package/src/types/auth.ts +52 -0
  194. package/src/types/ghost-config.ts +46 -0
  195. package/src/types/memory.ts +9 -1
  196. package/src/types/preferences.ts +2 -2
  197. package/src/utils/auth-helpers.spec.ts +75 -0
  198. package/src/utils/auth-helpers.ts +25 -0
  199. package/src/utils/test-data-generator.spec.ts +317 -0
  200. package/src/utils/test-data-generator.ts +292 -0
  201. package/src/utils/weaviate-filters.ts +4 -4
  202. package/src/v2-performance.e2e.ts +173 -0
  203. package/src/v2-smoke.e2e.ts +401 -0
  204. package/src/weaviate/client.spec.ts +5 -5
  205. package/src/weaviate/client.ts +51 -36
  206. package/src/weaviate/schema.ts +11 -256
  207. package/src/weaviate/space-schema.spec.ts +24 -24
  208. package/src/weaviate/space-schema.ts +18 -6
@@ -104,26 +104,26 @@ export async function testWeaviateConnection(): Promise<boolean> {
104
104
 
105
105
  /**
106
106
  * Sanitize user_id for collection name
107
- * Weaviate collection names must start with uppercase letter and contain only alphanumeric
107
+ * @deprecated v2 uses literal userId no sanitization needed. Kept for migration script only.
108
108
  */
109
109
  export function sanitizeUserId(userId: string): string {
110
110
  // Remove special characters, keep alphanumeric
111
111
  let sanitized = userId.replace(/[^a-zA-Z0-9]/g, '_');
112
-
112
+
113
113
  // If starts with number, prepend underscore
114
114
  if (/^[0-9]/.test(sanitized)) {
115
115
  sanitized = '_' + sanitized;
116
116
  }
117
-
117
+
118
118
  // Ensure starts with uppercase letter
119
119
  return sanitized.charAt(0).toUpperCase() + sanitized.slice(1);
120
120
  }
121
121
 
122
122
  /**
123
- * Get collection name for user's memories
123
+ * Get collection name for user's memories (v2 format)
124
124
  */
125
125
  export function getMemoryCollectionName(userId: string): string {
126
- return `Memory_${sanitizeUserId(userId)}`;
126
+ return `Memory_users_${userId}`;
127
127
  }
128
128
 
129
129
  /**
@@ -142,54 +142,67 @@ export function getAuditCollectionName(userId: string): string {
142
142
 
143
143
  /**
144
144
  * List of all memory properties to fetch
145
- * Centralized to ensure consistency across all tools
146
- */
147
- /**
148
- * List of all memory properties to fetch
149
- * Matches the actual Weaviate schema properties exactly
145
+ * Centralized to ensure consistency across all tools.
146
+ * Includes both v2 canonical names and v1 compat names.
150
147
  */
151
148
  export const ALL_MEMORY_PROPERTIES = [
152
149
  // Core identity
153
150
  'user_id',
154
151
  'doc_type',
155
-
152
+
156
153
  // Memory fields
157
154
  'content',
155
+ 'content_type', // v2 canonical
158
156
  'title',
159
157
  'summary',
160
- 'type',
161
-
158
+ 'type', // v1 compat (v2: content_type)
159
+
162
160
  // Scoring fields
163
161
  'weight',
164
162
  'base_weight',
165
- 'trust',
163
+ 'trust_score', // v2 canonical
164
+ 'trust', // v1 compat (v2: trust_score)
166
165
  'confidence',
167
166
  'computed_weight',
168
-
169
- // Location fields (flattened)
167
+
168
+ // Location fields (v2)
169
+ 'location_name',
170
+ 'location_lat', // v2 canonical
171
+ 'location_lon', // v2 canonical
172
+ // Location fields (v1 compat)
170
173
  'location_gps_lat',
171
174
  'location_gps_lng',
172
175
  'location_address',
173
176
  'location_city',
174
177
  'location_country',
175
178
  'location_source',
176
-
179
+
177
180
  // Locale fields
178
181
  'locale_language',
179
182
  'locale_timezone',
180
-
181
- // Context fields (flattened)
183
+
184
+ // Context fields
182
185
  'context_conversation_id',
183
186
  'context_summary',
184
187
  'context_timestamp',
185
-
186
- // Relationships
188
+ 'context_app',
189
+ 'context_url',
190
+
191
+ // Relationships (v2)
192
+ 'relationship_ids', // v2 canonical
193
+ 'related_memory_ids', // v2 canonical
194
+ // Relationships (v1 compat)
187
195
  'relationships',
188
-
196
+ 'memory_ids',
197
+ // Common relationship fields
198
+ 'relationship_type',
199
+ 'observation',
200
+ 'strength',
201
+
189
202
  // Access tracking
190
203
  'access_count',
191
204
  'last_accessed_at',
192
-
205
+
193
206
  // Metadata
194
207
  'tags',
195
208
  'references',
@@ -197,28 +210,30 @@ export const ALL_MEMORY_PROPERTIES = [
197
210
  'updated_at',
198
211
  'version',
199
212
  'template_id',
200
-
201
- // Relationship-specific fields
202
- 'memory_ids',
203
- 'relationship_type',
204
- 'observation',
205
- 'strength',
206
-
213
+
214
+ // Tracking arrays (v2)
215
+ 'space_ids',
216
+ 'group_ids',
217
+
207
218
  // Comment/threading fields
208
219
  'parent_id',
209
220
  'thread_root_id',
210
221
  'moderation_flags',
211
-
212
- // Space/publishing fields (for Memory_public collection)
213
- 'spaces',
214
- 'space_id',
222
+
223
+ // Space/publishing fields
224
+ 'spaces', // legacy
225
+ 'space_id', // legacy
215
226
  'author_id',
216
227
  'ghost_id',
217
228
  'attribution',
218
229
  'published_at',
219
230
  'discovery_count',
220
- 'space_memory_id',
221
-
231
+ 'space_memory_id', // legacy
232
+ 'original_memory_id',
233
+ 'revised_at',
234
+ 'revision_count',
235
+ 'revision_history',
236
+
222
237
  // Soft delete fields
223
238
  'deleted_at',
224
239
  'deleted_by',
@@ -4,9 +4,10 @@
4
4
  */
5
5
 
6
6
  import weaviate, { WeaviateClient } from 'weaviate-client';
7
- import { getWeaviateClient, sanitizeUserId } from './client.js';
7
+ import { getWeaviateClient } from './client.js';
8
8
  import { config } from '../config.js';
9
9
  import { logger } from '../utils/logger.js';
10
+ import { createUserCollectionSchema } from '../schema/v2-collections.js';
10
11
 
11
12
  /**
12
13
  * Create Memory collection schema for a user
@@ -21,7 +22,7 @@ import { logger } from '../utils/logger.js';
21
22
  */
22
23
  export async function createMemoryCollection(userId: string): Promise<void> {
23
24
  const client = getWeaviateClient();
24
- const collectionName = `Memory_${sanitizeUserId(userId)}`;
25
+ const collectionName = `Memory_users_${userId}`;
25
26
 
26
27
  // Check if collection already exists
27
28
  const exists = await client.collections.exists(collectionName);
@@ -38,255 +39,9 @@ export async function createMemoryCollection(userId: string): Promise<void> {
38
39
  collectionName,
39
40
  });
40
41
 
41
- // Create collection with schema
42
- await client.collections.create({
43
- name: collectionName,
44
-
45
- // Vectorizer configuration
46
- vectorizers: weaviate.configure.vectorizer.text2VecOpenAI({
47
- model: 'text-embedding-3-small',
48
- // Vectorize content, title, summary, and observation for semantic search
49
- // Note: title and summary are optional fields
50
- sourceProperties: ['content', 'title', 'summary', 'observation'],
51
- }),
52
-
53
- properties: [
54
- // Discriminator
55
- {
56
- name: 'doc_type',
57
- dataType: 'text' as any,
58
- description: 'Document type: "memory" or "relationship"',
59
- },
60
-
61
- // Core identity
62
- {
63
- name: 'user_id',
64
- dataType: 'text' as any,
65
- description: 'User who owns this document',
66
- },
67
-
68
- // Memory fields
69
- {
70
- name: 'content',
71
- dataType: 'text' as any,
72
- description: 'Main memory content (vectorized)',
73
- },
74
- {
75
- name: 'title',
76
- dataType: 'text' as any,
77
- description: 'Optional short title',
78
- },
79
- {
80
- name: 'summary',
81
- dataType: 'text' as any,
82
- description: 'Optional brief summary',
83
- },
84
- {
85
- name: 'type',
86
- dataType: 'text' as any,
87
- description: 'Content type (note, event, person, etc.)',
88
- },
89
-
90
- // Scoring fields
91
- {
92
- name: 'weight',
93
- dataType: 'number' as any,
94
- description: 'Significance/priority (0-1)',
95
- },
96
- {
97
- name: 'trust',
98
- dataType: 'number' as any,
99
- description: 'Access control level (0-1)',
100
- },
101
- {
102
- name: 'confidence',
103
- dataType: 'number' as any,
104
- description: 'System confidence in accuracy (0-1)',
105
- },
106
-
107
- // Location fields (flattened for Weaviate)
108
- {
109
- name: 'location_gps_lat',
110
- dataType: 'number' as any,
111
- description: 'GPS latitude',
112
- },
113
- {
114
- name: 'location_gps_lng',
115
- dataType: 'number' as any,
116
- description: 'GPS longitude',
117
- },
118
- {
119
- name: 'location_address',
120
- dataType: 'text' as any,
121
- description: 'Formatted address',
122
- },
123
- {
124
- name: 'location_city',
125
- dataType: 'text' as any,
126
- description: 'City name',
127
- },
128
- {
129
- name: 'location_country',
130
- dataType: 'text' as any,
131
- description: 'Country name',
132
- },
133
- {
134
- name: 'location_source',
135
- dataType: 'text' as any,
136
- description: 'Location source (gps, ip, manual, etc.)',
137
- },
138
-
139
- // Locale fields
140
- {
141
- name: 'locale_language',
142
- dataType: 'text' as any,
143
- description: 'Language code (e.g., en, es, fr)',
144
- },
145
- {
146
- name: 'locale_timezone',
147
- dataType: 'text' as any,
148
- description: 'Timezone (e.g., America/Los_Angeles)',
149
- },
150
-
151
- // Context fields
152
- {
153
- name: 'context_conversation_id',
154
- dataType: 'text' as any,
155
- description: 'Conversation ID',
156
- },
157
- {
158
- name: 'context_summary',
159
- dataType: 'text' as any,
160
- description: 'Brief context summary',
161
- },
162
- {
163
- name: 'context_timestamp',
164
- dataType: 'date' as any,
165
- description: 'Context timestamp',
166
- },
167
-
168
- // Relationships
169
- {
170
- name: 'relationships',
171
- dataType: 'text[]' as any,
172
- description: 'Array of relationship IDs',
173
- },
174
-
175
- // Access tracking
176
- {
177
- name: 'access_count',
178
- dataType: 'number' as any,
179
- description: 'Total times accessed',
180
- },
181
- {
182
- name: 'last_accessed_at',
183
- dataType: 'date' as any,
184
- description: 'Most recent access timestamp',
185
- },
186
-
187
- // Metadata
188
- {
189
- name: 'tags',
190
- dataType: 'text[]' as any,
191
- description: 'Tags for organization',
192
- },
193
- {
194
- name: 'references',
195
- dataType: 'text[]' as any,
196
- description: 'Source URLs',
197
- },
198
- {
199
- name: 'created_at',
200
- dataType: 'date' as any,
201
- description: 'Creation timestamp',
202
- },
203
- {
204
- name: 'updated_at',
205
- dataType: 'date' as any,
206
- description: 'Last update timestamp',
207
- },
208
- {
209
- name: 'version',
210
- dataType: 'number' as any,
211
- description: 'Version number',
212
- },
213
-
214
- // Template fields
215
- {
216
- name: 'template_id',
217
- dataType: 'text' as any,
218
- description: 'Template ID if using template',
219
- },
220
-
221
- // Relationship-specific fields
222
- {
223
- name: 'memory_ids',
224
- dataType: 'text[]' as any,
225
- description: 'Connected memory IDs (for relationships)',
226
- },
227
- {
228
- name: 'relationship_type',
229
- dataType: 'text' as any,
230
- description: 'Relationship type (for relationships)',
231
- },
232
- {
233
- name: 'observation',
234
- dataType: 'text' as any,
235
- description: 'Relationship observation (vectorized)',
236
- },
237
- {
238
- name: 'strength',
239
- dataType: 'number' as any,
240
- description: 'Relationship strength (0-1)',
241
- },
242
-
243
- // Computed fields
244
- {
245
- name: 'base_weight',
246
- dataType: 'number' as any,
247
- description: 'User-specified weight',
248
- },
249
- {
250
- name: 'computed_weight',
251
- dataType: 'number' as any,
252
- description: 'Calculated effective weight',
253
- },
254
-
255
- // Comment/threading fields (for threaded discussions in shared spaces)
256
- {
257
- name: 'parent_id',
258
- dataType: 'text' as any,
259
- description: 'ID of parent memory or comment (for threading)',
260
- },
261
- {
262
- name: 'thread_root_id',
263
- dataType: 'text' as any,
264
- description: 'Root memory ID for fetching entire thread',
265
- },
266
- {
267
- name: 'moderation_flags',
268
- dataType: 'text[]' as any,
269
- description: 'Per-space moderation flags (format: "{space_id}:{flag_type}")',
270
- },
271
-
272
- // Soft delete fields
273
- {
274
- name: 'deleted_at',
275
- dataType: 'date' as any,
276
- description: 'Timestamp when memory was soft-deleted (null = not deleted)',
277
- },
278
- {
279
- name: 'deleted_by',
280
- dataType: 'text' as any,
281
- description: 'User ID who deleted the memory',
282
- },
283
- {
284
- name: 'deletion_reason',
285
- dataType: 'text' as any,
286
- description: 'Optional reason for deletion',
287
- },
288
- ],
289
- });
42
+ // Create collection using v2 schema
43
+ const schema = createUserCollectionSchema(userId);
44
+ await client.collections.create(schema);
290
45
 
291
46
  logger.info('Memory collection created successfully', {
292
47
  module: 'weaviate-schema',
@@ -299,10 +54,10 @@ export async function createMemoryCollection(userId: string): Promise<void> {
299
54
  */
300
55
  export async function ensureMemoryCollection(userId: string): Promise<void> {
301
56
  const client = getWeaviateClient();
302
- const collectionName = `Memory_${sanitizeUserId(userId)}`;
57
+ const collectionName = `Memory_users_${userId}`;
303
58
 
304
59
  const exists = await client.collections.exists(collectionName);
305
-
60
+
306
61
  if (!exists) {
307
62
  await createMemoryCollection(userId);
308
63
  }
@@ -313,7 +68,7 @@ export async function ensureMemoryCollection(userId: string): Promise<void> {
313
68
  */
314
69
  export function getMemoryCollection(userId: string) {
315
70
  const client = getWeaviateClient();
316
- const collectionName = `Memory_${sanitizeUserId(userId)}`;
71
+ const collectionName = `Memory_users_${userId}`;
317
72
  return client.collections.get(collectionName);
318
73
  }
319
74
 
@@ -322,10 +77,10 @@ export function getMemoryCollection(userId: string) {
322
77
  */
323
78
  export async function deleteMemoryCollection(userId: string): Promise<void> {
324
79
  const client = getWeaviateClient();
325
- const collectionName = `Memory_${sanitizeUserId(userId)}`;
80
+ const collectionName = `Memory_users_${userId}`;
326
81
 
327
82
  const exists = await client.collections.exists(collectionName);
328
-
83
+
329
84
  if (exists) {
330
85
  await client.collections.delete(collectionName);
331
86
  logger.info('Memory collection deleted', {
@@ -119,10 +119,10 @@ describe('Space Schema Utilities', () => {
119
119
  expect(createCall.vectorizers).toBeDefined();
120
120
  expect(createCall.properties).toBeDefined();
121
121
  expect(createCall.properties.length).toBeGreaterThan(20); // Should have many properties
122
-
122
+
123
123
  // Check for space-specific properties
124
124
  const propertyNames = createCall.properties.map((p: any) => p.name);
125
- expect(propertyNames).toContain('spaces'); // Multi-space array field
125
+ expect(propertyNames).toContain('spaces'); // legacy multi-space array field
126
126
  expect(propertyNames).toContain('author_id');
127
127
  expect(propertyNames).toContain('ghost_id');
128
128
  expect(propertyNames).toContain('published_at');
@@ -135,9 +135,9 @@ describe('Space Schema Utilities', () => {
135
135
  });
136
136
  });
137
137
 
138
- describe('Unified Public Collection', () => {
139
- it('should create Memory_public collection', async () => {
140
- const mockCollection = { name: 'Memory_public' };
138
+ describe('Unified Public Collection (v2: Memory_spaces_public)', () => {
139
+ it('should create Memory_spaces_public collection', async () => {
140
+ const mockCollection = { name: 'Memory_spaces_public' };
141
141
  (mockWeaviateClient.collections.exists as jest.Mock).mockResolvedValue(false);
142
142
  (mockWeaviateClient.collections.create as jest.Mock).mockResolvedValue(undefined);
143
143
  (mockWeaviateClient.collections.get as jest.Mock).mockReturnValue(mockCollection);
@@ -145,25 +145,25 @@ describe('Space Schema Utilities', () => {
145
145
  const result = await ensurePublicCollection(mockWeaviateClient);
146
146
 
147
147
  expect(result).toBe(mockCollection);
148
- expect(mockWeaviateClient.collections.exists).toHaveBeenCalledWith('Memory_public');
148
+ expect(mockWeaviateClient.collections.exists).toHaveBeenCalledWith('Memory_spaces_public');
149
149
  expect(mockWeaviateClient.collections.create).toHaveBeenCalled();
150
- expect(mockWeaviateClient.collections.get).toHaveBeenCalledWith('Memory_public');
150
+ expect(mockWeaviateClient.collections.get).toHaveBeenCalledWith('Memory_spaces_public');
151
151
  });
152
152
 
153
- it('should return existing Memory_public if it exists', async () => {
154
- const mockCollection = { name: 'Memory_public' };
153
+ it('should return existing Memory_spaces_public if it exists', async () => {
154
+ const mockCollection = { name: 'Memory_spaces_public' };
155
155
  (mockWeaviateClient.collections.exists as jest.Mock).mockResolvedValue(true);
156
156
  (mockWeaviateClient.collections.get as jest.Mock).mockReturnValue(mockCollection);
157
157
 
158
158
  const result = await ensurePublicCollection(mockWeaviateClient);
159
159
 
160
160
  expect(result).toBe(mockCollection);
161
- expect(mockWeaviateClient.collections.exists).toHaveBeenCalledWith('Memory_public');
162
- expect(mockWeaviateClient.collections.get).toHaveBeenCalledWith('Memory_public');
161
+ expect(mockWeaviateClient.collections.exists).toHaveBeenCalledWith('Memory_spaces_public');
162
+ expect(mockWeaviateClient.collections.get).toHaveBeenCalledWith('Memory_spaces_public');
163
163
  expect(mockWeaviateClient.collections.create).not.toHaveBeenCalled();
164
164
  });
165
165
 
166
- it('should have spaces array field in schema', async () => {
166
+ it('should use v2 schema with space_ids array field', async () => {
167
167
  (mockWeaviateClient.collections.exists as jest.Mock).mockResolvedValue(false);
168
168
  (mockWeaviateClient.collections.create as jest.Mock).mockResolvedValue(undefined);
169
169
  (mockWeaviateClient.collections.get as jest.Mock).mockReturnValue({});
@@ -171,19 +171,19 @@ describe('Space Schema Utilities', () => {
171
171
  await ensurePublicCollection(mockWeaviateClient);
172
172
 
173
173
  const createCall = (mockWeaviateClient.collections.create as jest.Mock).mock.calls[0][0];
174
+ expect(createCall.name).toBe('Memory_spaces_public');
175
+
174
176
  const propertyNames = createCall.properties.map((p: any) => p.name);
175
-
176
- // Verify spaces array field exists
177
- expect(propertyNames).toContain('spaces');
178
-
179
- // Find spaces property and verify it's an array
180
- const spacesProperty = createCall.properties.find((p: any) => p.name === 'spaces');
181
- expect(spacesProperty).toBeDefined();
182
- expect(spacesProperty.dataType).toBe('text[]');
183
- });
184
-
185
- it('should verify PUBLIC_COLLECTION_NAME constant', () => {
186
- expect(PUBLIC_COLLECTION_NAME).toBe('Memory_public');
177
+ // v2 tracking arrays
178
+ expect(propertyNames).toContain('space_ids');
179
+ expect(propertyNames).toContain('group_ids');
180
+ // v2 revision fields
181
+ expect(propertyNames).toContain('revision_count');
182
+ expect(propertyNames).toContain('revised_at');
183
+ });
184
+
185
+ it('should verify PUBLIC_COLLECTION_NAME constant is v2 format', () => {
186
+ expect(PUBLIC_COLLECTION_NAME).toBe('Memory_spaces_public');
187
187
  });
188
188
  });
189
189
  });
@@ -9,11 +9,12 @@ import weaviate, { type WeaviateClient, type Collection } from 'weaviate-client'
9
9
  import { config } from '../config.js';
10
10
  import { SUPPORTED_SPACES, type SpaceId } from '../types/space-memory.js';
11
11
  import { logger } from '../utils/logger.js';
12
+ import { createSpaceCollectionSchema } from '../schema/v2-collections.js';
12
13
 
13
14
  /**
14
- * Unified public collection name for all public spaces
15
+ * Unified public collection name for all public spaces (v2)
15
16
  */
16
- export const PUBLIC_COLLECTION_NAME = 'Memory_public';
17
+ export const PUBLIC_COLLECTION_NAME = 'Memory_spaces_public';
17
18
 
18
19
  /**
19
20
  * Get collection name for a space
@@ -102,6 +103,12 @@ async function createSpaceCollection(
102
103
  sourceProperties: ['content', 'title', 'summary', 'observation'],
103
104
  }),
104
105
 
106
+ // Inverted index configuration
107
+ // indexNullState: true is required for filtering on null values (e.g., deleted_at IS NULL)
108
+ invertedIndex: weaviate.configure.invertedIndex({
109
+ indexNullState: true,
110
+ }),
111
+
105
112
  properties: [
106
113
  // Discriminator
107
114
  {
@@ -398,11 +405,16 @@ export async function ensurePublicCollection(
398
405
 
399
406
  // Check if collection exists
400
407
  const exists = await client.collections.exists(collectionName);
401
-
408
+
402
409
  if (!exists) {
403
- // Create with proper vectorizer configuration
404
- // Use 'public' as spaceId to trigger PUBLIC_COLLECTION_NAME
405
- await createSpaceCollection(client, 'public');
410
+ // Create using v2 schema
411
+ const schema = createSpaceCollectionSchema();
412
+ await client.collections.create(schema);
413
+
414
+ logger.info('Public space collection created', {
415
+ module: 'weaviate-space-schema',
416
+ collectionName,
417
+ });
406
418
  }
407
419
 
408
420
  return client.collections.get(collectionName);