stellar-memory 0.5.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 (197) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +362 -0
  3. package/dist/api/routes/analytics.d.ts +15 -0
  4. package/dist/api/routes/analytics.js +131 -0
  5. package/dist/api/routes/analytics.js.map +1 -0
  6. package/dist/api/routes/conflicts.d.ts +12 -0
  7. package/dist/api/routes/conflicts.js +67 -0
  8. package/dist/api/routes/conflicts.js.map +1 -0
  9. package/dist/api/routes/consolidation.d.ts +11 -0
  10. package/dist/api/routes/consolidation.js +63 -0
  11. package/dist/api/routes/consolidation.js.map +1 -0
  12. package/dist/api/routes/constellation.d.ts +4 -0
  13. package/dist/api/routes/constellation.js +84 -0
  14. package/dist/api/routes/constellation.js.map +1 -0
  15. package/dist/api/routes/memories.d.ts +4 -0
  16. package/dist/api/routes/memories.js +219 -0
  17. package/dist/api/routes/memories.js.map +1 -0
  18. package/dist/api/routes/observations.d.ts +10 -0
  19. package/dist/api/routes/observations.js +42 -0
  20. package/dist/api/routes/observations.js.map +1 -0
  21. package/dist/api/routes/orbit.d.ts +4 -0
  22. package/dist/api/routes/orbit.js +71 -0
  23. package/dist/api/routes/orbit.js.map +1 -0
  24. package/dist/api/routes/projects.d.ts +15 -0
  25. package/dist/api/routes/projects.js +121 -0
  26. package/dist/api/routes/projects.js.map +1 -0
  27. package/dist/api/routes/scan.d.ts +4 -0
  28. package/dist/api/routes/scan.js +403 -0
  29. package/dist/api/routes/scan.js.map +1 -0
  30. package/dist/api/routes/sun.d.ts +4 -0
  31. package/dist/api/routes/sun.js +43 -0
  32. package/dist/api/routes/sun.js.map +1 -0
  33. package/dist/api/routes/system.d.ts +4 -0
  34. package/dist/api/routes/system.js +70 -0
  35. package/dist/api/routes/system.js.map +1 -0
  36. package/dist/api/routes/temporal.d.ts +13 -0
  37. package/dist/api/routes/temporal.js +82 -0
  38. package/dist/api/routes/temporal.js.map +1 -0
  39. package/dist/api/server.d.ts +2 -0
  40. package/dist/api/server.js +99 -0
  41. package/dist/api/server.js.map +1 -0
  42. package/dist/api/websocket.d.ts +53 -0
  43. package/dist/api/websocket.js +168 -0
  44. package/dist/api/websocket.js.map +1 -0
  45. package/dist/cli/index.d.ts +12 -0
  46. package/dist/cli/index.js +35 -0
  47. package/dist/cli/index.js.map +1 -0
  48. package/dist/cli/init.d.ts +10 -0
  49. package/dist/cli/init.js +163 -0
  50. package/dist/cli/init.js.map +1 -0
  51. package/dist/engine/analytics.d.ts +93 -0
  52. package/dist/engine/analytics.js +437 -0
  53. package/dist/engine/analytics.js.map +1 -0
  54. package/dist/engine/conflict.d.ts +54 -0
  55. package/dist/engine/conflict.js +322 -0
  56. package/dist/engine/conflict.js.map +1 -0
  57. package/dist/engine/consolidation.d.ts +83 -0
  58. package/dist/engine/consolidation.js +368 -0
  59. package/dist/engine/consolidation.js.map +1 -0
  60. package/dist/engine/constellation.d.ts +66 -0
  61. package/dist/engine/constellation.js +382 -0
  62. package/dist/engine/constellation.js.map +1 -0
  63. package/dist/engine/corona.d.ts +53 -0
  64. package/dist/engine/corona.js +181 -0
  65. package/dist/engine/corona.js.map +1 -0
  66. package/dist/engine/embedding.d.ts +44 -0
  67. package/dist/engine/embedding.js +168 -0
  68. package/dist/engine/embedding.js.map +1 -0
  69. package/dist/engine/gravity.d.ts +63 -0
  70. package/dist/engine/gravity.js +121 -0
  71. package/dist/engine/gravity.js.map +1 -0
  72. package/dist/engine/multiproject.d.ts +75 -0
  73. package/dist/engine/multiproject.js +241 -0
  74. package/dist/engine/multiproject.js.map +1 -0
  75. package/dist/engine/observation.d.ts +82 -0
  76. package/dist/engine/observation.js +357 -0
  77. package/dist/engine/observation.js.map +1 -0
  78. package/dist/engine/orbit.d.ts +91 -0
  79. package/dist/engine/orbit.js +249 -0
  80. package/dist/engine/orbit.js.map +1 -0
  81. package/dist/engine/planet.d.ts +64 -0
  82. package/dist/engine/planet.js +432 -0
  83. package/dist/engine/planet.js.map +1 -0
  84. package/dist/engine/procedural.d.ts +71 -0
  85. package/dist/engine/procedural.js +259 -0
  86. package/dist/engine/procedural.js.map +1 -0
  87. package/dist/engine/quality.d.ts +48 -0
  88. package/dist/engine/quality.js +245 -0
  89. package/dist/engine/quality.js.map +1 -0
  90. package/dist/engine/repository.d.ts +79 -0
  91. package/dist/engine/repository.js +13 -0
  92. package/dist/engine/repository.js.map +1 -0
  93. package/dist/engine/sun.d.ts +61 -0
  94. package/dist/engine/sun.js +240 -0
  95. package/dist/engine/sun.js.map +1 -0
  96. package/dist/engine/temporal.d.ts +67 -0
  97. package/dist/engine/temporal.js +283 -0
  98. package/dist/engine/temporal.js.map +1 -0
  99. package/dist/engine/types.d.ts +179 -0
  100. package/dist/engine/types.js +27 -0
  101. package/dist/engine/types.js.map +1 -0
  102. package/dist/index.d.ts +2 -0
  103. package/dist/index.js +60 -0
  104. package/dist/index.js.map +1 -0
  105. package/dist/mcp/connector-registry.d.ts +20 -0
  106. package/dist/mcp/connector-registry.js +35 -0
  107. package/dist/mcp/connector-registry.js.map +1 -0
  108. package/dist/mcp/server.d.ts +13 -0
  109. package/dist/mcp/server.js +242 -0
  110. package/dist/mcp/server.js.map +1 -0
  111. package/dist/mcp/tools/daemon-tool.d.ts +16 -0
  112. package/dist/mcp/tools/daemon-tool.js +58 -0
  113. package/dist/mcp/tools/daemon-tool.js.map +1 -0
  114. package/dist/mcp/tools/ingestion-tools.d.ts +20 -0
  115. package/dist/mcp/tools/ingestion-tools.js +34 -0
  116. package/dist/mcp/tools/ingestion-tools.js.map +1 -0
  117. package/dist/mcp/tools/memory-tools.d.ts +122 -0
  118. package/dist/mcp/tools/memory-tools.js +1037 -0
  119. package/dist/mcp/tools/memory-tools.js.map +1 -0
  120. package/dist/scanner/cloud/github.d.ts +34 -0
  121. package/dist/scanner/cloud/github.js +260 -0
  122. package/dist/scanner/cloud/github.js.map +1 -0
  123. package/dist/scanner/cloud/google-drive.d.ts +30 -0
  124. package/dist/scanner/cloud/google-drive.js +289 -0
  125. package/dist/scanner/cloud/google-drive.js.map +1 -0
  126. package/dist/scanner/cloud/notion.d.ts +33 -0
  127. package/dist/scanner/cloud/notion.js +231 -0
  128. package/dist/scanner/cloud/notion.js.map +1 -0
  129. package/dist/scanner/cloud/slack.d.ts +38 -0
  130. package/dist/scanner/cloud/slack.js +282 -0
  131. package/dist/scanner/cloud/slack.js.map +1 -0
  132. package/dist/scanner/cloud/types.d.ts +73 -0
  133. package/dist/scanner/cloud/types.js +9 -0
  134. package/dist/scanner/cloud/types.js.map +1 -0
  135. package/dist/scanner/index.d.ts +35 -0
  136. package/dist/scanner/index.js +420 -0
  137. package/dist/scanner/index.js.map +1 -0
  138. package/dist/scanner/local/filesystem.d.ts +33 -0
  139. package/dist/scanner/local/filesystem.js +203 -0
  140. package/dist/scanner/local/filesystem.js.map +1 -0
  141. package/dist/scanner/local/git.d.ts +24 -0
  142. package/dist/scanner/local/git.js +161 -0
  143. package/dist/scanner/local/git.js.map +1 -0
  144. package/dist/scanner/local/parsers/code.d.ts +3 -0
  145. package/dist/scanner/local/parsers/code.js +127 -0
  146. package/dist/scanner/local/parsers/code.js.map +1 -0
  147. package/dist/scanner/local/parsers/index.d.ts +11 -0
  148. package/dist/scanner/local/parsers/index.js +24 -0
  149. package/dist/scanner/local/parsers/index.js.map +1 -0
  150. package/dist/scanner/local/parsers/json-parser.d.ts +3 -0
  151. package/dist/scanner/local/parsers/json-parser.js +117 -0
  152. package/dist/scanner/local/parsers/json-parser.js.map +1 -0
  153. package/dist/scanner/local/parsers/markdown.d.ts +3 -0
  154. package/dist/scanner/local/parsers/markdown.js +120 -0
  155. package/dist/scanner/local/parsers/markdown.js.map +1 -0
  156. package/dist/scanner/local/parsers/text.d.ts +3 -0
  157. package/dist/scanner/local/parsers/text.js +41 -0
  158. package/dist/scanner/local/parsers/text.js.map +1 -0
  159. package/dist/scanner/metadata-scanner.d.ts +67 -0
  160. package/dist/scanner/metadata-scanner.js +356 -0
  161. package/dist/scanner/metadata-scanner.js.map +1 -0
  162. package/dist/scanner/types.d.ts +47 -0
  163. package/dist/scanner/types.js +19 -0
  164. package/dist/scanner/types.js.map +1 -0
  165. package/dist/service/daemon.d.ts +23 -0
  166. package/dist/service/daemon.js +105 -0
  167. package/dist/service/daemon.js.map +1 -0
  168. package/dist/service/scheduler.d.ts +73 -0
  169. package/dist/service/scheduler.js +281 -0
  170. package/dist/service/scheduler.js.map +1 -0
  171. package/dist/storage/database.d.ts +10 -0
  172. package/dist/storage/database.js +265 -0
  173. package/dist/storage/database.js.map +1 -0
  174. package/dist/storage/queries.d.ts +85 -0
  175. package/dist/storage/queries.js +865 -0
  176. package/dist/storage/queries.js.map +1 -0
  177. package/dist/storage/sqlite-repository.d.ts +32 -0
  178. package/dist/storage/sqlite-repository.js +68 -0
  179. package/dist/storage/sqlite-repository.js.map +1 -0
  180. package/dist/storage/vec.d.ts +62 -0
  181. package/dist/storage/vec.js +111 -0
  182. package/dist/storage/vec.js.map +1 -0
  183. package/dist/utils/config.d.ts +5 -0
  184. package/dist/utils/config.js +60 -0
  185. package/dist/utils/config.js.map +1 -0
  186. package/dist/utils/logger.d.ts +36 -0
  187. package/dist/utils/logger.js +86 -0
  188. package/dist/utils/logger.js.map +1 -0
  189. package/dist/utils/time.d.ts +21 -0
  190. package/dist/utils/time.js +42 -0
  191. package/dist/utils/time.js.map +1 -0
  192. package/dist/utils/tokenizer.d.ts +13 -0
  193. package/dist/utils/tokenizer.js +46 -0
  194. package/dist/utils/tokenizer.js.map +1 -0
  195. package/package.json +77 -0
  196. package/scripts/check-node.mjs +36 -0
  197. package/scripts/setup.mjs +157 -0
@@ -0,0 +1,357 @@
1
+ /**
2
+ * observation.ts — Observational Memory ("Comet")
3
+ *
4
+ * Auto-extracts knowledge from raw conversation text and stores it as
5
+ * structured memories. Like comets that bring material from the outer
6
+ * solar system, observations bring new information from conversations
7
+ * into the memory system.
8
+ *
9
+ * Pipeline:
10
+ * observe() → extract pattern-matched memories from a chunk
11
+ * reflect() → categorize observations (novel / reinforcing / conflicting)
12
+ * processConversation → full pipeline: split → observe → reflect → store
13
+ *
14
+ * No LLM is used — all extraction is done via keyword matching and heuristics.
15
+ */
16
+ import { randomUUID } from 'node:crypto';
17
+ import { createMemory } from './planet.js';
18
+ import { recallMemoriesAsync } from './planet.js';
19
+ import { createObservation } from '../storage/queries.js';
20
+ import { updateMemoryOrbit, updateMemoryAccess } from '../storage/queries.js';
21
+ import { applyAccessBoost } from './orbit.js';
22
+ import { createLogger } from '../utils/logger.js';
23
+ const log = createLogger('observation');
24
+ // ---------------------------------------------------------------------------
25
+ // Keyword dictionaries
26
+ // ---------------------------------------------------------------------------
27
+ const DECISION_KEYWORDS = [
28
+ 'chose', 'decided', 'will use', 'switched to', 'selected', 'picked',
29
+ 'going with', 'we will', 'opted for', 'adopted', 'migrated to',
30
+ '결정', '선택', '사용하기로', '변경', '채택',
31
+ ];
32
+ const ERROR_KEYWORDS = [
33
+ 'error', 'bug', 'fix', 'fixed', 'failed', 'crash', 'issue', 'broken',
34
+ 'exception', 'traceback', 'undefined', 'null pointer', 'segfault',
35
+ '에러', '버그', '수정', '실패', '오류', '문제',
36
+ ];
37
+ const MILESTONE_KEYWORDS = [
38
+ 'complete', 'completed', 'done', 'finished', 'implemented', 'shipped',
39
+ 'deployed', 'released', 'merged', 'integrated', 'working', 'passing',
40
+ '완료', '구현', '배포', '완성', '됐', '됩니다',
41
+ ];
42
+ const TASK_KEYWORDS = [
43
+ 'todo', 'to-do', 'need to', 'should', 'must', 'later', 'next step',
44
+ 'will need', 'plan to', 'going to', 'upcoming', 'pending',
45
+ '해야', '필요', '다음에', '나중에', '예정',
46
+ ];
47
+ const CONTEXT_KEYWORDS = [
48
+ 'uses', 'requires', 'depends on', 'built with', 'runs on', 'configured',
49
+ 'connects to', 'integrates', 'relies on', 'powered by',
50
+ '사용', '필요', '의존', '기반',
51
+ ];
52
+ // ---------------------------------------------------------------------------
53
+ // Stop words — filtered out during key term extraction
54
+ // ---------------------------------------------------------------------------
55
+ const STOP_WORDS = new Set([
56
+ // English
57
+ 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
58
+ 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
59
+ 'should', 'may', 'might', 'shall', 'can', 'need', 'must', 'ought',
60
+ 'to', 'of', 'in', 'on', 'at', 'by', 'for', 'with', 'about', 'as',
61
+ 'into', 'through', 'from', 'up', 'down', 'out', 'off', 'over', 'under',
62
+ 'and', 'or', 'but', 'if', 'then', 'that', 'this', 'it', 'its',
63
+ 'i', 'we', 'you', 'he', 'she', 'they', 'them', 'their', 'our', 'my',
64
+ 'so', 'than', 'when', 'where', 'who', 'which', 'what', 'how', 'why',
65
+ 'not', 'no', 'all', 'each', 'both', 'few', 'more', 'other', 'some',
66
+ 'such', 'only', 'own', 'same', 'also', 'just', 'now', 'very', 'too',
67
+ // Korean particles
68
+ '은', '는', '이', '가', '을', '를', '의', '에', '에서', '로', '으로',
69
+ '와', '과', '도', '만', '가', '께', '한테', '에게', '부터', '까지',
70
+ '이다', '입니다', '있다', '없다', '이라', '이면', '라면', '같은',
71
+ ]);
72
+ // ---------------------------------------------------------------------------
73
+ // Key term extraction
74
+ // ---------------------------------------------------------------------------
75
+ /**
76
+ * Extract meaningful key terms from text.
77
+ *
78
+ * Filters out stop words and short tokens; keeps technical terms,
79
+ * proper nouns (by capitalization), version numbers, and path-like strings.
80
+ *
81
+ * Returns unique terms sorted by appearance order.
82
+ */
83
+ export function extractKeyTerms(text) {
84
+ const words = text
85
+ .split(/\s+/)
86
+ .map(w => w.replace(/[^\w.\-/]/g, '').trim())
87
+ .filter(w => w.length >= 2);
88
+ const seen = new Set();
89
+ const terms = [];
90
+ for (const word of words) {
91
+ const lower = word.toLowerCase();
92
+ if (STOP_WORDS.has(lower))
93
+ continue;
94
+ if (seen.has(lower))
95
+ continue;
96
+ seen.add(lower);
97
+ terms.push(word);
98
+ }
99
+ return terms;
100
+ }
101
+ // ---------------------------------------------------------------------------
102
+ // Keyword detection helpers
103
+ // ---------------------------------------------------------------------------
104
+ function containsAny(text, keywords) {
105
+ const lower = text.toLowerCase();
106
+ return keywords.some(kw => lower.includes(kw.toLowerCase()));
107
+ }
108
+ /**
109
+ * Detect the memory type for a given sentence based on keyword presence.
110
+ * Returns null if no pattern matches.
111
+ */
112
+ function detectType(sentence) {
113
+ if (containsAny(sentence, DECISION_KEYWORDS))
114
+ return 'decision';
115
+ if (containsAny(sentence, ERROR_KEYWORDS))
116
+ return 'error';
117
+ if (containsAny(sentence, MILESTONE_KEYWORDS))
118
+ return 'milestone';
119
+ if (containsAny(sentence, TASK_KEYWORDS))
120
+ return 'task';
121
+ if (containsAny(sentence, CONTEXT_KEYWORDS))
122
+ return 'context';
123
+ return null;
124
+ }
125
+ // ---------------------------------------------------------------------------
126
+ // Conversation splitting
127
+ // ---------------------------------------------------------------------------
128
+ /**
129
+ * Split a conversation into chunks suitable for observation.
130
+ *
131
+ * Splits on:
132
+ * - Common turn markers: "User:", "Assistant:", "Human:", "AI:", "System:"
133
+ * - Double newlines (paragraph breaks)
134
+ *
135
+ * Filters out empty or very short chunks.
136
+ * Chunks are bounded to 100-500 words each.
137
+ */
138
+ export function splitConversation(text) {
139
+ const TURN_PATTERN = /^(?:User|Assistant|Human|AI|System|사용자|어시스턴트):/im;
140
+ // First try turn-based splitting
141
+ const turnChunks = text
142
+ .split(/\n(?=(?:User|Assistant|Human|AI|System|사용자|어시스턴트):)/i)
143
+ .map(c => c.trim())
144
+ .filter(c => c.length > 20);
145
+ if (turnChunks.length > 1) {
146
+ return turnChunks;
147
+ }
148
+ // Fallback: paragraph splitting
149
+ return text
150
+ .split(/\n{2,}/)
151
+ .map(c => c.trim())
152
+ .filter(c => {
153
+ const wordCount = c.split(/\s+/).length;
154
+ return wordCount >= 5 && wordCount <= 600;
155
+ });
156
+ }
157
+ // ---------------------------------------------------------------------------
158
+ // Core observation
159
+ // ---------------------------------------------------------------------------
160
+ /**
161
+ * Observe a conversation chunk and extract structured memories from it.
162
+ *
163
+ * For each sentence that matches a known pattern (decision, error, milestone,
164
+ * task, context), a memory is created and stored.
165
+ *
166
+ * Returns the text observations extracted and the Memory objects created.
167
+ */
168
+ export function observe(conversationChunk, project) {
169
+ // Split into sentences
170
+ const sentences = conversationChunk
171
+ .split(/(?<=[.!?])\s+|\n/)
172
+ .map(s => s.trim())
173
+ .filter(s => s.length > 15); // skip very short fragments
174
+ const observations = [];
175
+ const memories = [];
176
+ const seen = new Set();
177
+ for (const sentence of sentences) {
178
+ const type = detectType(sentence);
179
+ if (!type)
180
+ continue;
181
+ // Normalize to avoid creating duplicate memories in the same chunk
182
+ const normalized = sentence.toLowerCase().replace(/\s+/g, ' ').trim();
183
+ if (seen.has(normalized))
184
+ continue;
185
+ seen.add(normalized);
186
+ // Generate summary (first 80 chars or the sentence itself if shorter)
187
+ const summary = sentence.length > 80
188
+ ? sentence.slice(0, 80).trimEnd() + '...'
189
+ : sentence;
190
+ // Extract tags from key technical terms
191
+ const terms = extractKeyTerms(sentence);
192
+ const tags = terms.slice(0, 8); // cap at 8 tags
193
+ try {
194
+ const memory = createMemory({
195
+ project,
196
+ content: sentence,
197
+ summary,
198
+ type,
199
+ tags,
200
+ });
201
+ observations.push(sentence);
202
+ memories.push(memory);
203
+ log.debug('Observed memory', {
204
+ type,
205
+ summary: summary.slice(0, 60),
206
+ });
207
+ }
208
+ catch (err) {
209
+ log.warn('Failed to create observed memory', { error: String(err) });
210
+ }
211
+ }
212
+ // Log the observation entry even if no memories were created
213
+ if (observations.length > 0) {
214
+ const entry = {
215
+ id: randomUUID(),
216
+ content: conversationChunk.slice(0, 500),
217
+ extracted_memories: memories.map(m => m.id),
218
+ source: 'conversation',
219
+ project,
220
+ created_at: new Date().toISOString(),
221
+ };
222
+ try {
223
+ createObservation(entry);
224
+ }
225
+ catch (err) {
226
+ log.warn('Failed to log observation entry', { error: String(err) });
227
+ }
228
+ }
229
+ return { observations, memories };
230
+ }
231
+ // ---------------------------------------------------------------------------
232
+ // Reflection
233
+ // ---------------------------------------------------------------------------
234
+ /**
235
+ * Reflect on a list of observations against the existing memory store.
236
+ *
237
+ * Categorizes each observation string as:
238
+ * - novel : not found in existing memories (truly new)
239
+ * - reinforcing : confirms an existing memory (we boost that memory)
240
+ * - conflicting : appears to contradict an existing memory
241
+ *
242
+ * Heuristics:
243
+ * - If an existing memory contains most of the same key terms → reinforcing
244
+ * - If an existing memory uses contradicting signals (negation patterns) → conflicting
245
+ * - Otherwise → novel
246
+ */
247
+ export async function reflect(newObservations, project) {
248
+ const novel = [];
249
+ const reinforcing = [];
250
+ const conflicting = [];
251
+ for (const obs of newObservations) {
252
+ // Search existing memories for similar content
253
+ const similar = await recallMemoriesAsync(project, obs, { limit: 3 });
254
+ if (similar.length === 0) {
255
+ novel.push(obs);
256
+ continue;
257
+ }
258
+ // Check the top result for reinforcement vs conflict
259
+ const top = similar[0];
260
+ const topTerms = extractKeyTerms(top.content);
261
+ const obsTerms = extractKeyTerms(obs);
262
+ // Count shared key terms
263
+ const topSet = new Set(topTerms.map(t => t.toLowerCase()));
264
+ const sharedCount = obsTerms.filter(t => topSet.has(t.toLowerCase())).length;
265
+ const overlapRatio = sharedCount / Math.max(1, obsTerms.length);
266
+ if (overlapRatio >= 0.5) {
267
+ // High overlap → reinforcing — boost the existing memory slightly
268
+ const boostedDistance = applyAccessBoost(top.distance);
269
+ try {
270
+ updateMemoryAccess(top.id);
271
+ updateMemoryOrbit(top.id, boostedDistance, top.importance, boostedDistance - top.distance);
272
+ }
273
+ catch (err) {
274
+ log.warn('Failed to boost reinforced memory', { id: top.id, error: String(err) });
275
+ }
276
+ reinforcing.push(obs);
277
+ }
278
+ else {
279
+ // Check for explicit contradiction signals
280
+ const obsLower = obs.toLowerCase();
281
+ const topLower = top.content.toLowerCase();
282
+ const negationPatterns = [
283
+ /\bnot\s+\w+/,
284
+ /\bno longer\b/,
285
+ /\binstead of\b/,
286
+ /\breplaced by\b/,
287
+ /\bswitched from\b/,
288
+ ];
289
+ const hasNegation = negationPatterns.some(p => p.test(obsLower) || p.test(topLower));
290
+ if (hasNegation && overlapRatio >= 0.3) {
291
+ conflicting.push(obs);
292
+ }
293
+ else {
294
+ novel.push(obs);
295
+ }
296
+ }
297
+ }
298
+ return { novel, reinforcing, conflicting };
299
+ }
300
+ // ---------------------------------------------------------------------------
301
+ // Full conversation pipeline
302
+ // ---------------------------------------------------------------------------
303
+ /**
304
+ * Process a full conversation through the observe → reflect pipeline.
305
+ *
306
+ * Steps:
307
+ * 1. Split conversation into chunks.
308
+ * 2. Run observe() on each chunk to extract memories.
309
+ * 3. Run reflect() on the extracted observations.
310
+ * 4. Boost reinforced memories.
311
+ * 5. Return aggregate statistics.
312
+ */
313
+ export async function processConversation(conversation, project) {
314
+ log.info('Processing conversation', { project, length: conversation.length });
315
+ const chunks = splitConversation(conversation);
316
+ log.debug('Conversation chunks', { count: chunks.length });
317
+ const allObservations = [];
318
+ let memoriesCreated = 0;
319
+ for (const chunk of chunks) {
320
+ const { observations, memories } = observe(chunk, project);
321
+ allObservations.push(...observations);
322
+ memoriesCreated += memories.length;
323
+ }
324
+ // Reflect on all accumulated observations
325
+ const { novel, reinforcing, conflicting } = await reflect(allObservations, project);
326
+ // Log a reflection observation entry for the session
327
+ if (allObservations.length > 0) {
328
+ const reflectionEntry = {
329
+ id: randomUUID(),
330
+ content: `Reflection: ${novel.length} novel, ${reinforcing.length} reinforcing, ${conflicting.length} conflicting`,
331
+ extracted_memories: [],
332
+ source: 'reflection',
333
+ project,
334
+ created_at: new Date().toISOString(),
335
+ };
336
+ try {
337
+ createObservation(reflectionEntry);
338
+ }
339
+ catch {
340
+ // Non-critical — don't fail the whole pipeline
341
+ }
342
+ }
343
+ log.info('Conversation processed', {
344
+ project,
345
+ chunks: chunks.length,
346
+ memoriesCreated,
347
+ memoriesReinforced: reinforcing.length,
348
+ conflictsDetected: conflicting.length,
349
+ novel: novel.length,
350
+ });
351
+ return {
352
+ memoriesCreated,
353
+ memoriesReinforced: reinforcing.length,
354
+ conflictsDetected: conflicting.length,
355
+ };
356
+ }
357
+ //# sourceMappingURL=observation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observation.js","sourceRoot":"","sources":["../../src/engine/observation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * orbit.ts — Core importance function and orbital mechanics
3
+ *
4
+ * Implements the celestial mechanics metaphor:
5
+ * - High importance → small orbital distance (close to the sun)
6
+ * - Low importance → large orbital distance (far from the sun, fading)
7
+ * - Access boost → pulls a memory closer when it is recalled
8
+ * - Decay → memories drift outward over time via recency score
9
+ */
10
+ import type { Memory, ImportanceComponents, OrbitChange, StellarConfig } from './types.js';
11
+ import type { MemoryType } from './types.js';
12
+ /**
13
+ * Calculate recency score using exponential decay.
14
+ *
15
+ * Formula: 0.5 ^ (hoursSince / effectiveHalfLife)
16
+ * - At t=0 → score = 1.0
17
+ * - At t=halfLife → score = 0.5
18
+ * - At t=2×halfLife → score = 0.25
19
+ *
20
+ * Procedural memories use a slower decay rate (halfLife / 0.3 ≈ 240h for default 72h)
21
+ * so hard-won knowledge persists longer.
22
+ *
23
+ * Returns a value in [0, 1].
24
+ */
25
+ export declare function recencyScore(lastAccessedAt: string | null, createdAt: string, halfLifeHours?: number, memoryType?: MemoryType): number;
26
+ /**
27
+ * Calculate frequency score using logarithmic saturation.
28
+ *
29
+ * Formula: log(1 + count) / log(1 + saturationPoint)
30
+ * - Grows quickly for the first few accesses.
31
+ * - Plateaus as count approaches saturationPoint.
32
+ *
33
+ * Returns a value in [0, 1].
34
+ */
35
+ export declare function frequencyScore(accessCount: number, saturationPoint?: number): number;
36
+ /**
37
+ * Calculate overall importance from all four components.
38
+ *
39
+ * Weights are configured via StellarConfig and must sum to 1.0 for a
40
+ * meaningful 0–1 total (they do in the defaults: 0.30+0.20+0.30+0.20=1.00).
41
+ */
42
+ export declare function calculateImportance(memory: Memory, sunText: string, config: StellarConfig): ImportanceComponents;
43
+ /**
44
+ * Convert importance (0–1) to orbital distance (0.1–100).
45
+ *
46
+ * Uses quadratic mapping so that:
47
+ * - importance = 1.0 → distance ≈ 0.1 (core / working memory)
48
+ * - importance = 0.0 → distance = 100 (Oort cloud / nearly forgotten)
49
+ *
50
+ * The quadratic curve creates a non-linear relationship: a memory must fall
51
+ * significantly in importance before it drifts noticeably outward, which
52
+ * mirrors how cognitive salience works in practice.
53
+ */
54
+ export declare function importanceToDistance(importance: number): number;
55
+ /**
56
+ * Inverse of importanceToDistance — derive importance from a given distance.
57
+ *
58
+ * Used when a user manually drags a memory to a new orbital position.
59
+ */
60
+ export declare function distanceToImportance(distance: number): number;
61
+ /**
62
+ * Return the orbit zone label for a given distance.
63
+ *
64
+ * Iterates ORBIT_ZONES in definition order (core → forgotten) and returns the
65
+ * first zone whose [min, max) range contains the distance. Falls back to
66
+ * the 'forgotten' label for any distance at or beyond 70.
67
+ */
68
+ export declare function getOrbitZone(distance: number): string;
69
+ /**
70
+ * Apply access boost — pull a memory closer when it is recalled.
71
+ *
72
+ * The boost is proportional to the current distance so that:
73
+ * - Far-away memories (high distance) receive a large absolute pull.
74
+ * - Close memories (low distance) are nudged only slightly.
75
+ *
76
+ * MIN_BOOST ensures even core memories get a small reward.
77
+ * The floor of 0.1 prevents distance from going below the core minimum.
78
+ */
79
+ export declare function applyAccessBoost(currentDistance: number): number;
80
+ /**
81
+ * Run a full orbit recalculation for all memories in a project.
82
+ *
83
+ * Called during stellar_commit and stellar_orbit. For each non-deleted memory:
84
+ * 1. Compute new importance using current sun context.
85
+ * 2. Map importance → distance.
86
+ * 3. If the distance shifted by more than 0.01, persist the change and log it.
87
+ *
88
+ * Returns every OrbitChange that was actually written.
89
+ */
90
+ export declare function recalculateOrbits(project: string, config: StellarConfig): OrbitChange[];
91
+ //# sourceMappingURL=orbit.d.ts.map