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.
- package/LICENSE +21 -0
- package/README.md +362 -0
- package/dist/api/routes/analytics.d.ts +15 -0
- package/dist/api/routes/analytics.js +131 -0
- package/dist/api/routes/analytics.js.map +1 -0
- package/dist/api/routes/conflicts.d.ts +12 -0
- package/dist/api/routes/conflicts.js +67 -0
- package/dist/api/routes/conflicts.js.map +1 -0
- package/dist/api/routes/consolidation.d.ts +11 -0
- package/dist/api/routes/consolidation.js +63 -0
- package/dist/api/routes/consolidation.js.map +1 -0
- package/dist/api/routes/constellation.d.ts +4 -0
- package/dist/api/routes/constellation.js +84 -0
- package/dist/api/routes/constellation.js.map +1 -0
- package/dist/api/routes/memories.d.ts +4 -0
- package/dist/api/routes/memories.js +219 -0
- package/dist/api/routes/memories.js.map +1 -0
- package/dist/api/routes/observations.d.ts +10 -0
- package/dist/api/routes/observations.js +42 -0
- package/dist/api/routes/observations.js.map +1 -0
- package/dist/api/routes/orbit.d.ts +4 -0
- package/dist/api/routes/orbit.js +71 -0
- package/dist/api/routes/orbit.js.map +1 -0
- package/dist/api/routes/projects.d.ts +15 -0
- package/dist/api/routes/projects.js +121 -0
- package/dist/api/routes/projects.js.map +1 -0
- package/dist/api/routes/scan.d.ts +4 -0
- package/dist/api/routes/scan.js +403 -0
- package/dist/api/routes/scan.js.map +1 -0
- package/dist/api/routes/sun.d.ts +4 -0
- package/dist/api/routes/sun.js +43 -0
- package/dist/api/routes/sun.js.map +1 -0
- package/dist/api/routes/system.d.ts +4 -0
- package/dist/api/routes/system.js +70 -0
- package/dist/api/routes/system.js.map +1 -0
- package/dist/api/routes/temporal.d.ts +13 -0
- package/dist/api/routes/temporal.js +82 -0
- package/dist/api/routes/temporal.js.map +1 -0
- package/dist/api/server.d.ts +2 -0
- package/dist/api/server.js +99 -0
- package/dist/api/server.js.map +1 -0
- package/dist/api/websocket.d.ts +53 -0
- package/dist/api/websocket.js +168 -0
- package/dist/api/websocket.js.map +1 -0
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.js +35 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +10 -0
- package/dist/cli/init.js +163 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/engine/analytics.d.ts +93 -0
- package/dist/engine/analytics.js +437 -0
- package/dist/engine/analytics.js.map +1 -0
- package/dist/engine/conflict.d.ts +54 -0
- package/dist/engine/conflict.js +322 -0
- package/dist/engine/conflict.js.map +1 -0
- package/dist/engine/consolidation.d.ts +83 -0
- package/dist/engine/consolidation.js +368 -0
- package/dist/engine/consolidation.js.map +1 -0
- package/dist/engine/constellation.d.ts +66 -0
- package/dist/engine/constellation.js +382 -0
- package/dist/engine/constellation.js.map +1 -0
- package/dist/engine/corona.d.ts +53 -0
- package/dist/engine/corona.js +181 -0
- package/dist/engine/corona.js.map +1 -0
- package/dist/engine/embedding.d.ts +44 -0
- package/dist/engine/embedding.js +168 -0
- package/dist/engine/embedding.js.map +1 -0
- package/dist/engine/gravity.d.ts +63 -0
- package/dist/engine/gravity.js +121 -0
- package/dist/engine/gravity.js.map +1 -0
- package/dist/engine/multiproject.d.ts +75 -0
- package/dist/engine/multiproject.js +241 -0
- package/dist/engine/multiproject.js.map +1 -0
- package/dist/engine/observation.d.ts +82 -0
- package/dist/engine/observation.js +357 -0
- package/dist/engine/observation.js.map +1 -0
- package/dist/engine/orbit.d.ts +91 -0
- package/dist/engine/orbit.js +249 -0
- package/dist/engine/orbit.js.map +1 -0
- package/dist/engine/planet.d.ts +64 -0
- package/dist/engine/planet.js +432 -0
- package/dist/engine/planet.js.map +1 -0
- package/dist/engine/procedural.d.ts +71 -0
- package/dist/engine/procedural.js +259 -0
- package/dist/engine/procedural.js.map +1 -0
- package/dist/engine/quality.d.ts +48 -0
- package/dist/engine/quality.js +245 -0
- package/dist/engine/quality.js.map +1 -0
- package/dist/engine/repository.d.ts +79 -0
- package/dist/engine/repository.js +13 -0
- package/dist/engine/repository.js.map +1 -0
- package/dist/engine/sun.d.ts +61 -0
- package/dist/engine/sun.js +240 -0
- package/dist/engine/sun.js.map +1 -0
- package/dist/engine/temporal.d.ts +67 -0
- package/dist/engine/temporal.js +283 -0
- package/dist/engine/temporal.js.map +1 -0
- package/dist/engine/types.d.ts +179 -0
- package/dist/engine/types.js +27 -0
- package/dist/engine/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/connector-registry.d.ts +20 -0
- package/dist/mcp/connector-registry.js +35 -0
- package/dist/mcp/connector-registry.js.map +1 -0
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.js +242 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/daemon-tool.d.ts +16 -0
- package/dist/mcp/tools/daemon-tool.js +58 -0
- package/dist/mcp/tools/daemon-tool.js.map +1 -0
- package/dist/mcp/tools/ingestion-tools.d.ts +20 -0
- package/dist/mcp/tools/ingestion-tools.js +34 -0
- package/dist/mcp/tools/ingestion-tools.js.map +1 -0
- package/dist/mcp/tools/memory-tools.d.ts +122 -0
- package/dist/mcp/tools/memory-tools.js +1037 -0
- package/dist/mcp/tools/memory-tools.js.map +1 -0
- package/dist/scanner/cloud/github.d.ts +34 -0
- package/dist/scanner/cloud/github.js +260 -0
- package/dist/scanner/cloud/github.js.map +1 -0
- package/dist/scanner/cloud/google-drive.d.ts +30 -0
- package/dist/scanner/cloud/google-drive.js +289 -0
- package/dist/scanner/cloud/google-drive.js.map +1 -0
- package/dist/scanner/cloud/notion.d.ts +33 -0
- package/dist/scanner/cloud/notion.js +231 -0
- package/dist/scanner/cloud/notion.js.map +1 -0
- package/dist/scanner/cloud/slack.d.ts +38 -0
- package/dist/scanner/cloud/slack.js +282 -0
- package/dist/scanner/cloud/slack.js.map +1 -0
- package/dist/scanner/cloud/types.d.ts +73 -0
- package/dist/scanner/cloud/types.js +9 -0
- package/dist/scanner/cloud/types.js.map +1 -0
- package/dist/scanner/index.d.ts +35 -0
- package/dist/scanner/index.js +420 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/local/filesystem.d.ts +33 -0
- package/dist/scanner/local/filesystem.js +203 -0
- package/dist/scanner/local/filesystem.js.map +1 -0
- package/dist/scanner/local/git.d.ts +24 -0
- package/dist/scanner/local/git.js +161 -0
- package/dist/scanner/local/git.js.map +1 -0
- package/dist/scanner/local/parsers/code.d.ts +3 -0
- package/dist/scanner/local/parsers/code.js +127 -0
- package/dist/scanner/local/parsers/code.js.map +1 -0
- package/dist/scanner/local/parsers/index.d.ts +11 -0
- package/dist/scanner/local/parsers/index.js +24 -0
- package/dist/scanner/local/parsers/index.js.map +1 -0
- package/dist/scanner/local/parsers/json-parser.d.ts +3 -0
- package/dist/scanner/local/parsers/json-parser.js +117 -0
- package/dist/scanner/local/parsers/json-parser.js.map +1 -0
- package/dist/scanner/local/parsers/markdown.d.ts +3 -0
- package/dist/scanner/local/parsers/markdown.js +120 -0
- package/dist/scanner/local/parsers/markdown.js.map +1 -0
- package/dist/scanner/local/parsers/text.d.ts +3 -0
- package/dist/scanner/local/parsers/text.js +41 -0
- package/dist/scanner/local/parsers/text.js.map +1 -0
- package/dist/scanner/metadata-scanner.d.ts +67 -0
- package/dist/scanner/metadata-scanner.js +356 -0
- package/dist/scanner/metadata-scanner.js.map +1 -0
- package/dist/scanner/types.d.ts +47 -0
- package/dist/scanner/types.js +19 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/service/daemon.d.ts +23 -0
- package/dist/service/daemon.js +105 -0
- package/dist/service/daemon.js.map +1 -0
- package/dist/service/scheduler.d.ts +73 -0
- package/dist/service/scheduler.js +281 -0
- package/dist/service/scheduler.js.map +1 -0
- package/dist/storage/database.d.ts +10 -0
- package/dist/storage/database.js +265 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/queries.d.ts +85 -0
- package/dist/storage/queries.js +865 -0
- package/dist/storage/queries.js.map +1 -0
- package/dist/storage/sqlite-repository.d.ts +32 -0
- package/dist/storage/sqlite-repository.js +68 -0
- package/dist/storage/sqlite-repository.js.map +1 -0
- package/dist/storage/vec.d.ts +62 -0
- package/dist/storage/vec.js +111 -0
- package/dist/storage/vec.js.map +1 -0
- package/dist/utils/config.d.ts +5 -0
- package/dist/utils/config.js +60 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/logger.d.ts +36 -0
- package/dist/utils/logger.js +86 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/time.d.ts +21 -0
- package/dist/utils/time.js +42 -0
- package/dist/utils/time.js.map +1 -0
- package/dist/utils/tokenizer.d.ts +13 -0
- package/dist/utils/tokenizer.js +46 -0
- package/dist/utils/tokenizer.js.map +1 -0
- package/package.json +77 -0
- package/scripts/check-node.mjs +36 -0
- package/scripts/setup.mjs +157 -0
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* planet.ts — Memory (planet) management
|
|
3
|
+
*
|
|
4
|
+
* Memories are "planets" orbiting the sun. This module handles:
|
|
5
|
+
* - createMemory : place a new memory into orbit.
|
|
6
|
+
* - recallMemories: search memories and apply access boost to results (hybrid).
|
|
7
|
+
* - forgetMemory : push a memory to the Oort cloud or soft-delete it.
|
|
8
|
+
*
|
|
9
|
+
* Phase 2: Hybrid search
|
|
10
|
+
* createMemory kicks off an async background embedding job so that the
|
|
11
|
+
* synchronous call returns immediately while the vector index is populated
|
|
12
|
+
* without blocking the caller.
|
|
13
|
+
*
|
|
14
|
+
* recallMemories merges FTS5 keyword results with vector KNN results using
|
|
15
|
+
* Reciprocal Rank Fusion (RRF), then deduplicates and re-ranks.
|
|
16
|
+
*/
|
|
17
|
+
import { randomUUID, createHash } from 'node:crypto';
|
|
18
|
+
import { IMPACT_DEFAULTS } from './types.js';
|
|
19
|
+
import { insertMemory, searchMemoriesInRange, updateMemoryAccess, updateMemoryOrbit, insertOrbitLog, softDeleteMemory, getMemoryById, getSunState, getMemoryByIds, getMemoryByContentHash, updateQualityScore, getEdgesForBatch, getMemoriesByProject, } from '../storage/queries.js';
|
|
20
|
+
import { getConfig } from '../utils/config.js';
|
|
21
|
+
import { calculateImportance, importanceToDistance, applyAccessBoost, recencyScore, frequencyScore, } from './orbit.js';
|
|
22
|
+
import { keywordRelevance } from './gravity.js';
|
|
23
|
+
import { generateEmbedding } from './embedding.js';
|
|
24
|
+
import { insertEmbedding, searchByVector, deleteEmbedding } from '../storage/vec.js';
|
|
25
|
+
import { getDatabase, withTransaction } from '../storage/database.js';
|
|
26
|
+
import { createLogger } from '../utils/logger.js';
|
|
27
|
+
import { corona } from './corona.js';
|
|
28
|
+
import { calculateQuality } from './quality.js';
|
|
29
|
+
import { trackBgError } from '../mcp/tools/memory-tools.js';
|
|
30
|
+
import { runConsolidation } from './consolidation.js';
|
|
31
|
+
const log = createLogger('planet');
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// createMemory
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
/**
|
|
36
|
+
* Create a new memory planet and place it in initial orbit.
|
|
37
|
+
*
|
|
38
|
+
* Initial placement uses static component values because the memory has just
|
|
39
|
+
* been created and has no access history or proven relevance yet:
|
|
40
|
+
* - recency = 1.0 (brand new)
|
|
41
|
+
* - frequency = 0.0 (never recalled)
|
|
42
|
+
* - impact = type-specific default (or caller-supplied)
|
|
43
|
+
* - relevance = 0.0 (no context yet; updated on next commit)
|
|
44
|
+
*
|
|
45
|
+
* The resulting distance positions the memory in the inner zone for high-impact
|
|
46
|
+
* types (decisions, milestones) and further out for lower-impact types.
|
|
47
|
+
*/
|
|
48
|
+
export function createMemory(data) {
|
|
49
|
+
const config = getConfig();
|
|
50
|
+
const type = data.type ?? 'observation';
|
|
51
|
+
const impact = data.impact ?? IMPACT_DEFAULTS[type];
|
|
52
|
+
const tags = data.tags ?? [];
|
|
53
|
+
// Auto-generate a summary from the first 50 characters if none provided.
|
|
54
|
+
const raw = data.content.trim();
|
|
55
|
+
const summary = data.summary
|
|
56
|
+
? data.summary
|
|
57
|
+
: raw.slice(0, 50).trimEnd() + (raw.length > 50 ? '…' : '');
|
|
58
|
+
// Content-hash deduplication: return the existing memory if identical content
|
|
59
|
+
// has already been stored in this project.
|
|
60
|
+
const contentHash = createHash('sha256').update(data.content).digest('hex');
|
|
61
|
+
const existing = getMemoryByContentHash(data.project, contentHash);
|
|
62
|
+
if (existing) {
|
|
63
|
+
log.debug('Duplicate content detected — returning existing memory', {
|
|
64
|
+
id: existing.id,
|
|
65
|
+
project: data.project,
|
|
66
|
+
content_hash: contentHash,
|
|
67
|
+
});
|
|
68
|
+
return existing;
|
|
69
|
+
}
|
|
70
|
+
// Compute initial importance using static scores.
|
|
71
|
+
const rec = recencyScore(null, new Date().toISOString(), config.decayHalfLifeHours);
|
|
72
|
+
const freq = frequencyScore(0, config.frequencySaturationPoint);
|
|
73
|
+
// Compute relevance against current sun context so new memories start at a
|
|
74
|
+
// position that reflects their relevance to current work, rather than 0.
|
|
75
|
+
const sunState = getSunState(data.project);
|
|
76
|
+
const sunText = sunState
|
|
77
|
+
? [sunState.current_work, ...sunState.recent_decisions, ...sunState.next_steps].join(' ')
|
|
78
|
+
: '';
|
|
79
|
+
const memoryText = data.content + ' ' + tags.join(' ');
|
|
80
|
+
const rel = keywordRelevance(memoryText, sunText);
|
|
81
|
+
const total = Math.min(1.0, config.weights.recency * rec +
|
|
82
|
+
config.weights.frequency * freq +
|
|
83
|
+
config.weights.impact * impact +
|
|
84
|
+
config.weights.relevance * rel);
|
|
85
|
+
const distance = importanceToDistance(total);
|
|
86
|
+
const now = new Date().toISOString();
|
|
87
|
+
const memory = insertMemory({
|
|
88
|
+
id: randomUUID(),
|
|
89
|
+
project: data.project,
|
|
90
|
+
content: data.content,
|
|
91
|
+
summary,
|
|
92
|
+
type,
|
|
93
|
+
tags,
|
|
94
|
+
distance,
|
|
95
|
+
importance: total,
|
|
96
|
+
velocity: 0,
|
|
97
|
+
impact,
|
|
98
|
+
access_count: 0,
|
|
99
|
+
last_accessed_at: null,
|
|
100
|
+
metadata: {},
|
|
101
|
+
content_hash: contentHash,
|
|
102
|
+
created_at: now,
|
|
103
|
+
updated_at: now,
|
|
104
|
+
deleted_at: null,
|
|
105
|
+
});
|
|
106
|
+
// Background embedding: fire-and-forget so createMemory stays synchronous.
|
|
107
|
+
// The vector index will be populated within seconds after the model loads.
|
|
108
|
+
scheduleEmbedding(memory.id, memory.content + ' ' + summary);
|
|
109
|
+
// Calculate and persist initial quality score
|
|
110
|
+
try {
|
|
111
|
+
const quality = calculateQuality(memory);
|
|
112
|
+
updateQualityScore(memory.id, quality.overall);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// Quality scoring is non-critical — don't block creation
|
|
116
|
+
}
|
|
117
|
+
// If the new memory lands in the corona zone, cache it immediately.
|
|
118
|
+
if (memory.distance < 5.0) {
|
|
119
|
+
corona.upsert(memory);
|
|
120
|
+
}
|
|
121
|
+
// Auto-consolidation: trigger background consolidation when project
|
|
122
|
+
// memory count exceeds 100 to keep the memory system lean.
|
|
123
|
+
try {
|
|
124
|
+
const projectMemories = getMemoriesByProject(data.project);
|
|
125
|
+
if (projectMemories.length > 100) {
|
|
126
|
+
runConsolidation(data.project).catch(() => {
|
|
127
|
+
try {
|
|
128
|
+
trackBgError('consolidation');
|
|
129
|
+
}
|
|
130
|
+
catch { /* ignore */ }
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Non-critical — skip silently
|
|
136
|
+
}
|
|
137
|
+
return memory;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Schedule an async embedding generation for a memory.
|
|
141
|
+
* Errors are swallowed so they never affect the calling code path.
|
|
142
|
+
*/
|
|
143
|
+
function scheduleEmbedding(memoryId, text) {
|
|
144
|
+
generateEmbedding(text)
|
|
145
|
+
.then(embedding => {
|
|
146
|
+
try {
|
|
147
|
+
const db = getDatabase();
|
|
148
|
+
insertEmbedding(db, memoryId, embedding);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// DB may have been reset (tests) — ignore silently
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
.catch(() => {
|
|
155
|
+
// Model not loaded / network error — FTS5 fallback remains active
|
|
156
|
+
try {
|
|
157
|
+
trackBgError('embedding');
|
|
158
|
+
}
|
|
159
|
+
catch { /* ignore circular import at startup */ }
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
// forgetMemory
|
|
164
|
+
// ---------------------------------------------------------------------------
|
|
165
|
+
/**
|
|
166
|
+
* Forget a memory.
|
|
167
|
+
*
|
|
168
|
+
* Modes:
|
|
169
|
+
* - 'push' : Push the memory to the Oort cloud (distance ≈ 95 AU).
|
|
170
|
+
* The memory remains searchable but will rarely surface.
|
|
171
|
+
* - 'delete': Soft-delete the memory (sets deleted_at; excluded from queries).
|
|
172
|
+
*/
|
|
173
|
+
export function forgetMemory(memoryId, mode) {
|
|
174
|
+
if (mode === 'delete') {
|
|
175
|
+
softDeleteMemory(memoryId);
|
|
176
|
+
corona.evict(memoryId);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
// Push mode: drift the memory to the deep Oort cloud.
|
|
180
|
+
const memory = getMemoryById(memoryId);
|
|
181
|
+
if (!memory) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const OORT_DISTANCE = 95.0; // deep Oort cloud but not at maximum
|
|
185
|
+
const newImportance = 0.02; // nearly forgotten
|
|
186
|
+
const velocity = OORT_DISTANCE - memory.distance;
|
|
187
|
+
updateMemoryOrbit(memoryId, OORT_DISTANCE, newImportance, velocity);
|
|
188
|
+
insertOrbitLog({
|
|
189
|
+
memory_id: memoryId,
|
|
190
|
+
project: memory.project,
|
|
191
|
+
old_distance: memory.distance,
|
|
192
|
+
new_distance: OORT_DISTANCE,
|
|
193
|
+
old_importance: memory.importance,
|
|
194
|
+
new_importance: newImportance,
|
|
195
|
+
trigger: 'forget',
|
|
196
|
+
});
|
|
197
|
+
// Also remove the embedding from the vector index
|
|
198
|
+
try {
|
|
199
|
+
const db = getDatabase();
|
|
200
|
+
deleteEmbedding(db, memoryId);
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// vec tables may not be available — ignore
|
|
204
|
+
}
|
|
205
|
+
// Evict from corona cache regardless of mode.
|
|
206
|
+
corona.evict(memoryId);
|
|
207
|
+
}
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
// Hybrid search helpers (Phase 2)
|
|
210
|
+
// ---------------------------------------------------------------------------
|
|
211
|
+
/**
|
|
212
|
+
* Reciprocal Rank Fusion: merge FTS5 results and vector result IDs.
|
|
213
|
+
*
|
|
214
|
+
* RRF(d) = Σ 1 / (k + rank_i) where k = 60 (standard constant)
|
|
215
|
+
*
|
|
216
|
+
* Both lists are ranked 1-based. The merged list is sorted by descending
|
|
217
|
+
* RRF score and de-duplicated.
|
|
218
|
+
*
|
|
219
|
+
* Returns an array of Memory objects in merged order. Memories that only
|
|
220
|
+
* appear in the vecIds list will be represented as partial stubs with just
|
|
221
|
+
* the id field populated — callers should call hydrateVectorOnlyResults().
|
|
222
|
+
*/
|
|
223
|
+
function mergeRRF(ftsResults, vecIds, limit) {
|
|
224
|
+
const K = 60;
|
|
225
|
+
const scores = new Map();
|
|
226
|
+
ftsResults.forEach((m, i) => {
|
|
227
|
+
scores.set(m.id, (scores.get(m.id) ?? 0) + 1 / (K + i + 1));
|
|
228
|
+
});
|
|
229
|
+
vecIds.forEach((id, i) => {
|
|
230
|
+
scores.set(id, (scores.get(id) ?? 0) + 1 / (K + i + 1));
|
|
231
|
+
});
|
|
232
|
+
// Sort by descending RRF score
|
|
233
|
+
const sorted = [...scores.entries()]
|
|
234
|
+
.sort((a, b) => b[1] - a[1])
|
|
235
|
+
.slice(0, limit)
|
|
236
|
+
.map(([id]) => id);
|
|
237
|
+
// Build result list: prefer full Memory objects from ftsResults when available
|
|
238
|
+
const ftsMap = new Map(ftsResults.map(m => [m.id, m]));
|
|
239
|
+
return sorted.map(id => ftsMap.get(id) ?? { id });
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Resolve partial Memory stubs (from vector-only results) into full objects.
|
|
243
|
+
* Performs a single batched DB lookup for all missing memories.
|
|
244
|
+
*/
|
|
245
|
+
function hydrateVectorOnlyResults(merged, ftsResults) {
|
|
246
|
+
const ftsIds = new Set(ftsResults.map(m => m.id));
|
|
247
|
+
const missingIds = merged
|
|
248
|
+
.filter(m => !ftsIds.has(m.id) && m.content === undefined)
|
|
249
|
+
.map(m => m.id);
|
|
250
|
+
if (missingIds.length === 0)
|
|
251
|
+
return merged;
|
|
252
|
+
const fetched = getMemoryByIds(missingIds);
|
|
253
|
+
const fetchedMap = new Map(fetched.map(m => [m.id, m]));
|
|
254
|
+
return merged.map(m => m.content === undefined ? (fetchedMap.get(m.id) ?? m) : m);
|
|
255
|
+
}
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
// Tiered recall pipeline (Corona architecture)
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
/** Zone boost factors applied to search results by tier origin. */
|
|
260
|
+
const ZONE_BOOST = {
|
|
261
|
+
core: 1.2,
|
|
262
|
+
near: 1.1,
|
|
263
|
+
active: 1.0,
|
|
264
|
+
archive: 0.95,
|
|
265
|
+
fading: 0.85,
|
|
266
|
+
forgotten: 0.7,
|
|
267
|
+
};
|
|
268
|
+
/** Tier priority multiplier (earlier tiers are preferred at equal relevance). */
|
|
269
|
+
const TIER_PRIORITY = {
|
|
270
|
+
tier1: 1.0,
|
|
271
|
+
tier2: 0.95,
|
|
272
|
+
tier3: 0.90,
|
|
273
|
+
};
|
|
274
|
+
/**
|
|
275
|
+
* Async tiered recall: 3-tier pipeline from corona cache → FTS5 → full hybrid.
|
|
276
|
+
*
|
|
277
|
+
* Tier 1: Corona cache (0ms) — core + near zone, token matching
|
|
278
|
+
* Tier 2: Active zone FTS5 (1-5ms) — distance 5.0–15.0
|
|
279
|
+
* Tier 3: Full hybrid FTS5 + vector (5-50ms) — distance 15.0+
|
|
280
|
+
*
|
|
281
|
+
* Early exit: if Tier 1 fills the requested limit, Tier 2 and 3 are skipped.
|
|
282
|
+
*/
|
|
283
|
+
export async function recallMemoriesAsync(project, query, options) {
|
|
284
|
+
const limit = options?.limit ?? 10;
|
|
285
|
+
const scored = [];
|
|
286
|
+
// Pre-seed seenIds with exclusions (e.g., corona IDs already shown in Sun)
|
|
287
|
+
const seenIds = new Set(options?.excludeIds ?? []);
|
|
288
|
+
// ── Tier 1: Corona cache (in-memory, ~0ms) ─────────────────────────────
|
|
289
|
+
const coronaResults = corona.search(query, limit * 2);
|
|
290
|
+
for (let i = 0; i < coronaResults.length; i++) {
|
|
291
|
+
const m = coronaResults[i];
|
|
292
|
+
const zoneBoost = m.distance < 1.0 ? ZONE_BOOST.core : ZONE_BOOST.near;
|
|
293
|
+
const rankScore = 1 / (1 + i); // rank-based score
|
|
294
|
+
scored.push({
|
|
295
|
+
memory: m,
|
|
296
|
+
score: rankScore * zoneBoost * TIER_PRIORITY.tier1,
|
|
297
|
+
tier: m.distance < 1.0 ? 'CORE' : 'NEAR',
|
|
298
|
+
});
|
|
299
|
+
seenIds.add(m.id);
|
|
300
|
+
}
|
|
301
|
+
// Early exit: if corona filled the limit, skip DB searches
|
|
302
|
+
const remaining = limit - scored.length;
|
|
303
|
+
// ── Tier 2: Active zone FTS5 (distance 5.0–15.0, ~1-5ms) ──────────────
|
|
304
|
+
if (remaining > 0) {
|
|
305
|
+
const tier2Results = searchMemoriesInRange(project, query, 5.0, 15.0, remaining * 2);
|
|
306
|
+
for (let i = 0; i < tier2Results.length; i++) {
|
|
307
|
+
const m = tier2Results[i];
|
|
308
|
+
if (seenIds.has(m.id))
|
|
309
|
+
continue;
|
|
310
|
+
const rankScore = 1 / (1 + i);
|
|
311
|
+
scored.push({
|
|
312
|
+
memory: m,
|
|
313
|
+
score: rankScore * ZONE_BOOST.active * TIER_PRIORITY.tier2,
|
|
314
|
+
tier: 'ACTIVE',
|
|
315
|
+
});
|
|
316
|
+
seenIds.add(m.id);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// ── Tier 3: Full hybrid FTS5 + vector (distance 15.0+, ~5-50ms) ───────
|
|
320
|
+
const remaining3 = limit - scored.filter(s => s.score > 0).length;
|
|
321
|
+
if (remaining3 > 0) {
|
|
322
|
+
const fetchN = remaining3 * 3;
|
|
323
|
+
// FTS5 for far zone
|
|
324
|
+
const ftsResults = searchMemoriesInRange(project, query, 15.0, 100.0, fetchN);
|
|
325
|
+
// Vector KNN search (async embedding)
|
|
326
|
+
let vecIds = [];
|
|
327
|
+
try {
|
|
328
|
+
const db = getDatabase();
|
|
329
|
+
const queryEmbedding = await generateEmbedding(query);
|
|
330
|
+
const vecResults = searchByVector(db, queryEmbedding, fetchN);
|
|
331
|
+
vecIds = vecResults.map(r => r.memoryId);
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
// Model not ready or vec tables unavailable — FTS5 covers it
|
|
335
|
+
}
|
|
336
|
+
// Merge FTS5 + vector via RRF
|
|
337
|
+
let merged = mergeRRF(ftsResults, vecIds, fetchN);
|
|
338
|
+
merged = hydrateVectorOnlyResults(merged, ftsResults);
|
|
339
|
+
for (let i = 0; i < merged.length; i++) {
|
|
340
|
+
const m = merged[i];
|
|
341
|
+
if (seenIds.has(m.id))
|
|
342
|
+
continue;
|
|
343
|
+
if (!m.content)
|
|
344
|
+
continue; // skip unhydrated stubs
|
|
345
|
+
const zoneBoost = m.distance < 40
|
|
346
|
+
? ZONE_BOOST.archive
|
|
347
|
+
: m.distance < 70
|
|
348
|
+
? ZONE_BOOST.fading
|
|
349
|
+
: ZONE_BOOST.forgotten;
|
|
350
|
+
const rankScore = 1 / (1 + i);
|
|
351
|
+
scored.push({
|
|
352
|
+
memory: m,
|
|
353
|
+
score: rankScore * zoneBoost * TIER_PRIORITY.tier3,
|
|
354
|
+
tier: 'DEEP',
|
|
355
|
+
});
|
|
356
|
+
seenIds.add(m.id);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
// ── Constellation edge boost ──────────────────────────────────────────
|
|
360
|
+
// Memories connected via knowledge graph edges get a score boost.
|
|
361
|
+
try {
|
|
362
|
+
const scoredIds = scored.map(s => s.memory.id);
|
|
363
|
+
const edgeMap = getEdgesForBatch(scoredIds, project);
|
|
364
|
+
const EDGE_BOOST = 0.07;
|
|
365
|
+
for (const entry of scored) {
|
|
366
|
+
const neighbors = edgeMap.get(entry.memory.id);
|
|
367
|
+
if (neighbors && neighbors.size > 0) {
|
|
368
|
+
// Boost proportional to number of connections (capped at 3)
|
|
369
|
+
const edgeCount = Math.min(neighbors.size, 3);
|
|
370
|
+
entry.score += edgeCount * EDGE_BOOST;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
// Constellation tables may not exist — skip boost silently
|
|
376
|
+
}
|
|
377
|
+
// ── Sort by composite score descending ─────────────────────────────────
|
|
378
|
+
scored.sort((a, b) => b.score - a.score);
|
|
379
|
+
// ── Filter ─────────────────────────────────────────────────────────────
|
|
380
|
+
let filtered = scored;
|
|
381
|
+
if (options?.type && options.type !== 'all') {
|
|
382
|
+
const filterType = options.type;
|
|
383
|
+
filtered = filtered.filter(s => s.memory.type === filterType);
|
|
384
|
+
}
|
|
385
|
+
if (options?.minDistance !== undefined) {
|
|
386
|
+
const minDist = options.minDistance;
|
|
387
|
+
filtered = filtered.filter(s => s.memory.distance >= minDist);
|
|
388
|
+
}
|
|
389
|
+
if (options?.maxDistance !== undefined) {
|
|
390
|
+
const maxDist = options.maxDistance;
|
|
391
|
+
filtered = filtered.filter(s => s.memory.distance <= maxDist);
|
|
392
|
+
}
|
|
393
|
+
const finalScored = filtered.slice(0, limit);
|
|
394
|
+
// ── Access boost + orbit update ────────────────────────────────────────
|
|
395
|
+
const sunState = getSunState(project);
|
|
396
|
+
const sunText = sunState
|
|
397
|
+
? [sunState.current_work, ...sunState.recent_decisions, ...sunState.next_steps].join(' ')
|
|
398
|
+
: '';
|
|
399
|
+
const config = getConfig();
|
|
400
|
+
const results = withTransaction(() => finalScored.map(({ memory, tier }) => {
|
|
401
|
+
const newDistance = applyAccessBoost(memory.distance);
|
|
402
|
+
const velocity = newDistance - memory.distance;
|
|
403
|
+
updateMemoryAccess(memory.id);
|
|
404
|
+
const updatedMemory = {
|
|
405
|
+
...memory,
|
|
406
|
+
distance: newDistance,
|
|
407
|
+
access_count: memory.access_count + 1,
|
|
408
|
+
last_accessed_at: new Date().toISOString(),
|
|
409
|
+
};
|
|
410
|
+
const components = calculateImportance(updatedMemory, sunText, config);
|
|
411
|
+
updateMemoryOrbit(memory.id, newDistance, components.total, velocity);
|
|
412
|
+
insertOrbitLog({
|
|
413
|
+
memory_id: memory.id,
|
|
414
|
+
project,
|
|
415
|
+
old_distance: memory.distance,
|
|
416
|
+
new_distance: newDistance,
|
|
417
|
+
old_importance: memory.importance,
|
|
418
|
+
new_importance: components.total,
|
|
419
|
+
trigger: 'access',
|
|
420
|
+
});
|
|
421
|
+
const result = { ...updatedMemory, importance: components.total, velocity };
|
|
422
|
+
// If memory moved into the corona zone (< 5.0 AU), update cache
|
|
423
|
+
if (newDistance < 5.0) {
|
|
424
|
+
corona.upsert(result);
|
|
425
|
+
}
|
|
426
|
+
// Attach tier marker to metadata for display
|
|
427
|
+
result.metadata = { ...result.metadata, _tier: tier };
|
|
428
|
+
return result;
|
|
429
|
+
}));
|
|
430
|
+
return results;
|
|
431
|
+
}
|
|
432
|
+
//# sourceMappingURL=planet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planet.js","sourceRoot":"","sources":["../../src/engine/planet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EACL,YAAY,EAEZ,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,cAAc,EACd,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,YAAY,EACZ,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;AAEnC,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,IAO5B;IACC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,MAAM,IAAI,GAAiB,IAAI,CAAC,IAAI,IAAM,aAAa,CAAC;IACxD,MAAM,MAAM,GAAe,IAAI,CAAC,MAAM,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;IAChE,MAAM,IAAI,GAAiB,IAAI,CAAC,IAAI,IAAM,EAAE,CAAC;IAE7C,yEAAyE;IACzE,MAAM,GAAG,GAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACpC,MAAM,OAAO,GAAW,IAAI,CAAC,OAAO;QAClC,CAAC,CAAC,IAAI,CAAC,OAAO;QACd,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAE9D,8EAA8E;IAC9E,2CAA2C;IAC3C,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACnE,IAAI,QAAQ,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,wDAAwD,EAAE;YAClE,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,YAAY,EAAE,WAAW;SAC1B,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,kDAAkD;IAClD,MAAM,GAAG,GAAI,YAAY,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACrF,MAAM,IAAI,GAAG,cAAc,CAAC,CAAC,EAAE,MAAM,CAAC,wBAAwB,CAAC,CAAC;IAEhE,2EAA2E;IAC3E,yEAAyE;IACzE,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAI,QAAQ;QACvB,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,GAAG,QAAQ,CAAC,gBAAgB,EAAE,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACzF,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,gBAAgB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAElD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,GAAG,EACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAK,GAAG;QAC9B,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI;QAC/B,MAAM,CAAC,OAAO,CAAC,MAAM,GAAM,MAAM;QACjC,MAAM,CAAC,OAAO,CAAC,SAAS,GAAG,GAAG,CAC/B,CAAC;IAEF,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAQ,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE1C,MAAM,MAAM,GAAG,YAAY,CAAC;QAC1B,EAAE,EAAe,UAAU,EAAE;QAC7B,OAAO,EAAU,IAAI,CAAC,OAAO;QAC7B,OAAO,EAAU,IAAI,CAAC,OAAO;QAC7B,OAAO;QACP,IAAI;QACJ,IAAI;QACJ,QAAQ;QACR,UAAU,EAAO,KAAK;QACtB,QAAQ,EAAS,CAAC;QAClB,MAAM;QACN,YAAY,EAAK,CAAC;QAClB,gBAAgB,EAAE,IAAI;QACtB,QAAQ,EAAS,EAAE;QACnB,YAAY,EAAK,WAAW;QAC5B,UAAU,EAAO,GAAG;QACpB,UAAU,EAAO,GAAG;QACpB,UAAU,EAAO,IAAI;KACtB,CAAC,CAAC;IAEH,2EAA2E;IAC3E,2EAA2E;IAC3E,iBAAiB,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,GAAG,GAAG,GAAG,OAAO,CAAC,CAAC;IAE7D,8CAA8C;IAC9C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACzC,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;IAED,oEAAoE;IACpE,IAAI,MAAM,CAAC,QAAQ,GAAG,GAAG,EAAE,CAAC;QAC1B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAED,oEAAoE;IACpE,2DAA2D;IAC3D,IAAI,CAAC;QACH,MAAM,eAAe,GAAG,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,eAAe,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACjC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;gBACxC,IAAI,CAAC;oBAAC,YAAY,CAAC,eAAe,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YAC/D,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,+BAA+B;IACjC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAC,QAAgB,EAAE,IAAY;IACvD,iBAAiB,CAAC,IAAI,CAAC;SACpB,IAAI,CAAC,SAAS,CAAC,EAAE;QAChB,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;YACzB,eAAe,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;QACrD,CAAC;IACH,CAAC,CAAC;SACD,KAAK,CAAC,GAAG,EAAE;QACV,kEAAkE;QAClE,IAAI,CAAC;YAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,uCAAuC,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;AACP,CAAC;AAED,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,IAAuB;IACpE,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACvB,OAAO;IACT,CAAC;IAED,sDAAsD;IACtD,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,CAAC,qCAAqC;IACjE,MAAM,aAAa,GAAG,IAAI,CAAC,CAAC,mBAAmB;IAC/C,MAAM,QAAQ,GAAQ,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC;IAEtD,iBAAiB,CAAC,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IAEpE,cAAc,CAAC;QACb,SAAS,EAAO,QAAQ;QACxB,OAAO,EAAS,MAAM,CAAC,OAAO;QAC9B,YAAY,EAAI,MAAM,CAAC,QAAQ;QAC/B,YAAY,EAAI,aAAa;QAC7B,cAAc,EAAE,MAAM,CAAC,UAAU;QACjC,cAAc,EAAE,aAAa;QAC7B,OAAO,EAAS,QAAQ;KACzB,CAAC,CAAC;IAEH,kDAAkD;IAClD,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;QACzB,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,2CAA2C;IAC7C,CAAC;IAED,8CAA8C;IAC9C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACzB,CAAC;AAED,8EAA8E;AAC9E,kCAAkC;AAClC,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,SAAS,QAAQ,CACf,UAAoB,EACpB,MAAgB,EAChB,KAAa;IAEb,MAAM,CAAC,GAAG,EAAE,CAAC;IACb,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEzC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;QACvB,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,+BAA+B;IAC/B,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SACjC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3B,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IAErB,+EAA+E;IAC/E,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,OAAO,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAK,EAAE,EAAE,EAAa,CAAC,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,SAAS,wBAAwB,CAC/B,MAAgB,EAChB,UAAoB;IAEpB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,MAAM;SACtB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC;SACzD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAElB,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAE3C,MAAM,OAAO,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAExD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CACpB,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC1D,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,+CAA+C;AAC/C,8EAA8E;AAE9E,mEAAmE;AACnE,MAAM,UAAU,GAAG;IACjB,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,GAAG;IACT,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,IAAI;IACb,MAAM,EAAE,IAAI;IACZ,SAAS,EAAE,GAAG;CACN,CAAC;AAEX,iFAAiF;AACjF,MAAM,aAAa,GAAG;IACpB,KAAK,EAAE,GAAG;IACV,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,IAAI;CACH,CAAC;AAQX;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAe,EACf,KAAa,EACb,OAMC;IAED,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC;IACnC,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,2EAA2E;IAC3E,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,OAAO,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC;IAE3D,0EAA0E;IAC1E,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IACtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,SAAS,GAAG,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;QACvE,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,mBAAmB;QACnD,MAAM,CAAC,IAAI,CAAC;YACV,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC,KAAK;YAClD,IAAI,EAAE,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;SACzC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpB,CAAC;IAED,2DAA2D;IAC3D,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;IAExC,yEAAyE;IACzE,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClB,MAAM,YAAY,GAAG,qBAAqB,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;QACrF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAE,SAAS;YAChC,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,CAAC;gBACT,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC,MAAM,GAAG,aAAa,CAAC,KAAK;gBAC1D,IAAI,EAAE,QAAQ;aACf,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;IAClE,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACnB,MAAM,MAAM,GAAG,UAAU,GAAG,CAAC,CAAC;QAE9B,oBAAoB;QACpB,MAAM,UAAU,GAAG,qBAAqB,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAE9E,sCAAsC;QACtC,IAAI,MAAM,GAAa,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;YACzB,MAAM,cAAc,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACtD,MAAM,UAAU,GAAG,cAAc,CAAC,EAAE,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;YAC9D,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,6DAA6D;QAC/D,CAAC;QAED,8BAA8B;QAC9B,IAAI,MAAM,GAAG,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,GAAG,wBAAwB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAEtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACpB,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAE,SAAS;YAChC,IAAI,CAAC,CAAC,CAAC,OAAO;gBAAE,SAAS,CAAC,wBAAwB;YAElD,MAAM,SAAS,GAAG,CAAC,CAAC,QAAQ,GAAG,EAAE;gBAC/B,CAAC,CAAC,UAAU,CAAC,OAAO;gBACpB,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,EAAE;oBACf,CAAC,CAAC,UAAU,CAAC,MAAM;oBACnB,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC;YAE3B,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,CAAC;gBACT,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC,KAAK;gBAClD,IAAI,EAAE,MAAM;aACb,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,kEAAkE;IAClE,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACrD,MAAM,UAAU,GAAG,IAAI,CAAC;QAExB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC/C,IAAI,SAAS,IAAI,SAAS,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBACpC,4DAA4D;gBAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC9C,KAAK,CAAC,KAAK,IAAI,SAAS,GAAG,UAAU,CAAC;YACxC,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,2DAA2D;IAC7D,CAAC;IAED,0EAA0E;IAC1E,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAEzC,0EAA0E;IAC1E,IAAI,QAAQ,GAAG,MAAM,CAAC;IAEtB,IAAI,OAAO,EAAE,IAAI,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC5C,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;QAChC,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,OAAO,EAAE,WAAW,KAAK,SAAS,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;QACpC,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,OAAO,EAAE,WAAW,KAAK,SAAS,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;QACpC,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAE7C,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,OAAO,GAAI,QAAQ;QACvB,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,GAAG,QAAQ,CAAC,gBAAgB,EAAE,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACzF,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,EAAE,CACnC,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE;QACnC,MAAM,WAAW,GAAG,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtD,MAAM,QAAQ,GAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC;QAElD,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAE9B,MAAM,aAAa,GAAW;YAC5B,GAAG,MAAM;YACT,QAAQ,EAAU,WAAW;YAC7B,YAAY,EAAM,MAAM,CAAC,YAAY,GAAG,CAAC;YACzC,gBAAgB,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SAC3C,CAAC;QAEF,MAAM,UAAU,GAAG,mBAAmB,CAAC,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACvE,iBAAiB,CAAC,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAEtE,cAAc,CAAC;YACb,SAAS,EAAO,MAAM,CAAC,EAAE;YACzB,OAAO;YACP,YAAY,EAAI,MAAM,CAAC,QAAQ;YAC/B,YAAY,EAAI,WAAW;YAC3B,cAAc,EAAE,MAAM,CAAC,UAAU;YACjC,cAAc,EAAE,UAAU,CAAC,KAAK;YAChC,OAAO,EAAS,QAAQ;SACzB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,EAAE,GAAG,aAAa,EAAE,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC;QAE5E,gEAAgE;QAChE,IAAI,WAAW,GAAG,GAAG,EAAE,CAAC;YACtB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QAED,6CAA6C;QAC7C,MAAM,CAAC,QAAQ,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAEtD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CACH,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* procedural.ts — Procedural Memory ("Navigation Rules")
|
|
3
|
+
*
|
|
4
|
+
* Procedural memories are behavioral rules learned from patterns in other
|
|
5
|
+
* memories. They represent "how we do things here" — conventions, workflows,
|
|
6
|
+
* and recurring solutions extracted from observed repetition.
|
|
7
|
+
*
|
|
8
|
+
* Key behaviors:
|
|
9
|
+
* - Pattern detection: group memories by tags, find groups with 3+ members
|
|
10
|
+
* - Rule creation: procedural memories start with high impact (0.9)
|
|
11
|
+
* - Slow decay: procedural memories decay at 30% of the normal rate
|
|
12
|
+
* - Sun integration: top 5 rules appear in a dedicated section
|
|
13
|
+
*/
|
|
14
|
+
import type { Memory } from './types.js';
|
|
15
|
+
/**
|
|
16
|
+
* Detect patterns in the memory corpus that are strong enough to warrant
|
|
17
|
+
* a procedural rule.
|
|
18
|
+
*
|
|
19
|
+
* Returns one candidate per tag-group that has 3+ members, describing the
|
|
20
|
+
* observed pattern and suggesting a concrete rule.
|
|
21
|
+
*/
|
|
22
|
+
export declare function detectProceduralPattern(memories: Memory[], project: string): Array<{
|
|
23
|
+
pattern: string;
|
|
24
|
+
frequency: number;
|
|
25
|
+
suggestedRule: string;
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* Create a procedural memory from a learned rule and its supporting evidence.
|
|
29
|
+
*
|
|
30
|
+
* Procedural memories:
|
|
31
|
+
* - Use type 'procedural'
|
|
32
|
+
* - Start with high impact (0.9) so they orbit close to the sun
|
|
33
|
+
* - Include both the rule and the evidence that generated it
|
|
34
|
+
* - Are tagged with 'procedural' plus terms extracted from the rule
|
|
35
|
+
*/
|
|
36
|
+
export declare function createProceduralMemory(rule: string, evidence: string[], project: string): Memory;
|
|
37
|
+
/**
|
|
38
|
+
* Get all procedural memories for a project, sorted by importance descending.
|
|
39
|
+
* These feed into the sun content formatter and the suggest logic.
|
|
40
|
+
*/
|
|
41
|
+
export declare function getProceduralMemories(project: string): Memory[];
|
|
42
|
+
/**
|
|
43
|
+
* Format procedural memories as a concise "Navigation Rules" section
|
|
44
|
+
* suitable for inclusion in the sun resource content.
|
|
45
|
+
*
|
|
46
|
+
* At most 5 rules are shown (most important first). Each rule is rendered
|
|
47
|
+
* as a single numbered line extracted from the content (the "Rule: ..." part).
|
|
48
|
+
*/
|
|
49
|
+
export declare function formatProceduralSection(memories: Memory[]): string;
|
|
50
|
+
/**
|
|
51
|
+
* Procedural memories are hard-won knowledge and should be highly durable.
|
|
52
|
+
* Return 0.3 so that the effective half-life is ~3.3x longer than normal.
|
|
53
|
+
*
|
|
54
|
+
* Used by orbit.ts when calculating recency score for procedural memories:
|
|
55
|
+
* effectiveHalfLife = baseHalfLife / getProceduralDecayMultiplier()
|
|
56
|
+
*/
|
|
57
|
+
export declare function getProceduralDecayMultiplier(): number;
|
|
58
|
+
/**
|
|
59
|
+
* Analyse the last 50 memories and suggest concrete procedural rules.
|
|
60
|
+
*
|
|
61
|
+
* Returns candidates sorted by confidence (highest first). Confidence is
|
|
62
|
+
* the proportion of the tag-group that supports a consistent pattern.
|
|
63
|
+
*
|
|
64
|
+
* Skips rules that already exist as procedural memories (by rule text match).
|
|
65
|
+
*/
|
|
66
|
+
export declare function suggestRules(recentMemories: Memory[]): Array<{
|
|
67
|
+
rule: string;
|
|
68
|
+
confidence: number;
|
|
69
|
+
evidence: Memory[];
|
|
70
|
+
}>;
|
|
71
|
+
//# sourceMappingURL=procedural.d.ts.map
|