@aleph-ai/tinyaleph 1.5.6 → 1.5.7
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/observer/agency.js +885 -0
- package/observer/assays.js +973 -0
- package/observer/boundary.js +1155 -0
- package/observer/entanglement.js +673 -0
- package/observer/hqe.js +1465 -0
- package/observer/index.js +158 -0
- package/observer/prsc.js +1289 -0
- package/observer/safety.js +815 -0
- package/observer/smf.js +1015 -0
- package/observer/symbolic-smf.js +726 -0
- package/observer/symbolic-temporal.js +790 -0
- package/observer/temporal.js +669 -0
- package/package.json +2 -1
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporal Layer - Emergent Time
|
|
3
|
+
*
|
|
4
|
+
* Implements the emergent time mechanism from "A Design for a Sentient
|
|
5
|
+
* Observer" paper, Section 5.
|
|
6
|
+
*
|
|
7
|
+
* Key features:
|
|
8
|
+
* - Coherence-based moment detection (equations 18-20)
|
|
9
|
+
* - Entropy conditions for moment triggering
|
|
10
|
+
* - Subjective duration based on processed content
|
|
11
|
+
* - Phase transition rate monitoring
|
|
12
|
+
* - Temporal event logging
|
|
13
|
+
*
|
|
14
|
+
* @module observer/temporal
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Moment - A discrete unit of experiential time
|
|
19
|
+
*
|
|
20
|
+
* Moments are triggered by coherence peaks or entropy conditions,
|
|
21
|
+
* not by external clock time.
|
|
22
|
+
*/
|
|
23
|
+
class Moment {
|
|
24
|
+
/**
|
|
25
|
+
* Create a moment
|
|
26
|
+
* @param {Object} data - Moment data
|
|
27
|
+
*/
|
|
28
|
+
constructor(data = {}) {
|
|
29
|
+
this.id = data.id || Moment.generateId();
|
|
30
|
+
this.timestamp = data.timestamp || Date.now();
|
|
31
|
+
this.clockTime = data.clockTime || Date.now();
|
|
32
|
+
|
|
33
|
+
// Trigger conditions
|
|
34
|
+
this.trigger = data.trigger || 'coherence'; // 'coherence' | 'entropy' | 'manual'
|
|
35
|
+
this.coherence = data.coherence || 0;
|
|
36
|
+
this.entropy = data.entropy || 0;
|
|
37
|
+
this.phaseTransitionRate = data.phaseTransitionRate || 0;
|
|
38
|
+
|
|
39
|
+
// Content
|
|
40
|
+
this.activePrimes = data.activePrimes || [];
|
|
41
|
+
this.smfSnapshot = data.smfSnapshot || null;
|
|
42
|
+
this.semanticContent = data.semanticContent || null;
|
|
43
|
+
|
|
44
|
+
// Subjective duration (equation 24)
|
|
45
|
+
// Δτ = β * Σ Ap log(Ap)
|
|
46
|
+
this.subjectiveDuration = data.subjectiveDuration || 0;
|
|
47
|
+
|
|
48
|
+
// Associations
|
|
49
|
+
this.previousMomentId = data.previousMomentId || null;
|
|
50
|
+
this.entangledMomentIds = data.entangledMomentIds || [];
|
|
51
|
+
|
|
52
|
+
// Metadata
|
|
53
|
+
this.notes = data.notes || '';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Generate a unique moment ID
|
|
58
|
+
*/
|
|
59
|
+
static generateId() {
|
|
60
|
+
return `m_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Serialize to JSON
|
|
65
|
+
*/
|
|
66
|
+
toJSON() {
|
|
67
|
+
return {
|
|
68
|
+
id: this.id,
|
|
69
|
+
timestamp: this.timestamp,
|
|
70
|
+
clockTime: this.clockTime,
|
|
71
|
+
trigger: this.trigger,
|
|
72
|
+
coherence: this.coherence,
|
|
73
|
+
entropy: this.entropy,
|
|
74
|
+
phaseTransitionRate: this.phaseTransitionRate,
|
|
75
|
+
activePrimes: this.activePrimes,
|
|
76
|
+
smfSnapshot: this.smfSnapshot,
|
|
77
|
+
semanticContent: this.semanticContent,
|
|
78
|
+
subjectiveDuration: this.subjectiveDuration,
|
|
79
|
+
previousMomentId: this.previousMomentId,
|
|
80
|
+
entangledMomentIds: this.entangledMomentIds,
|
|
81
|
+
notes: this.notes
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Create from JSON
|
|
87
|
+
*/
|
|
88
|
+
static fromJSON(data) {
|
|
89
|
+
return new Moment(data);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Temporal Layer - Manages emergent time experience
|
|
95
|
+
*
|
|
96
|
+
* Time emerges from coherence events rather than external clock.
|
|
97
|
+
*/
|
|
98
|
+
class TemporalLayer {
|
|
99
|
+
/**
|
|
100
|
+
* Create a temporal layer
|
|
101
|
+
* @param {Object} options - Configuration options
|
|
102
|
+
*/
|
|
103
|
+
constructor(options = {}) {
|
|
104
|
+
// Thresholds (equation 18-20)
|
|
105
|
+
this.coherenceThreshold = options.coherenceThreshold || 0.7; // Cthresh
|
|
106
|
+
this.entropyMin = options.entropyMin || 0.05; // Hmin (lowered)
|
|
107
|
+
this.entropyMax = options.entropyMax || 0.95; // Hmax (raised)
|
|
108
|
+
this.phaseTransitionThreshold = options.phaseTransitionThreshold || 0.3;
|
|
109
|
+
|
|
110
|
+
// Duration scaling (equation 24)
|
|
111
|
+
this.beta = options.beta || 1.0; // β
|
|
112
|
+
|
|
113
|
+
// Debouncing for moment creation
|
|
114
|
+
this.minMomentInterval = options.minMomentInterval || 500; // Minimum ms between moments
|
|
115
|
+
this.lastMomentTime = 0;
|
|
116
|
+
|
|
117
|
+
// State
|
|
118
|
+
this.moments = [];
|
|
119
|
+
this.currentMoment = null;
|
|
120
|
+
this.subjectiveTime = 0; // Accumulated subjective duration
|
|
121
|
+
this.lastClockTime = Date.now();
|
|
122
|
+
this.momentCounter = 0;
|
|
123
|
+
|
|
124
|
+
// History tracking
|
|
125
|
+
this.coherenceHistory = [];
|
|
126
|
+
this.entropyHistory = [];
|
|
127
|
+
this.phaseHistory = [];
|
|
128
|
+
this.maxHistory = options.maxHistory || 1000;
|
|
129
|
+
|
|
130
|
+
// Callbacks
|
|
131
|
+
this.onMoment = options.onMoment || null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Update temporal layer with current system state
|
|
136
|
+
* Returns true if a new moment was triggered
|
|
137
|
+
*
|
|
138
|
+
* @param {Object} state - Current system state
|
|
139
|
+
* @param {number} state.coherence - Global coherence (Cglobal)
|
|
140
|
+
* @param {number} state.entropy - System entropy (H)
|
|
141
|
+
* @param {Array<number>} state.phases - Current oscillator phases
|
|
142
|
+
* @param {Array<number>} state.activePrimes - Currently active primes
|
|
143
|
+
* @param {Object} state.smf - Current SMF state
|
|
144
|
+
* @param {Object} state.semanticContent - Current semantic content
|
|
145
|
+
*/
|
|
146
|
+
update(state) {
|
|
147
|
+
const now = Date.now();
|
|
148
|
+
const dt = (now - this.lastClockTime) / 1000;
|
|
149
|
+
this.lastClockTime = now;
|
|
150
|
+
|
|
151
|
+
const { coherence, entropy, phases, activePrimes, smf, semanticContent } = state;
|
|
152
|
+
|
|
153
|
+
// Update history
|
|
154
|
+
this.coherenceHistory.push({ time: now, value: coherence });
|
|
155
|
+
this.entropyHistory.push({ time: now, value: entropy });
|
|
156
|
+
|
|
157
|
+
if (phases) {
|
|
158
|
+
this.phaseHistory.push({ time: now, phases: phases.slice() });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Trim histories
|
|
162
|
+
this.trimHistories();
|
|
163
|
+
|
|
164
|
+
// Check moment trigger conditions (with debouncing)
|
|
165
|
+
const momentTriggered = this.checkMomentConditions(state);
|
|
166
|
+
|
|
167
|
+
if (momentTriggered.triggered) {
|
|
168
|
+
// Debounce: don't create moments too frequently
|
|
169
|
+
const now = Date.now();
|
|
170
|
+
if (now - this.lastMomentTime >= this.minMomentInterval) {
|
|
171
|
+
this.lastMomentTime = now;
|
|
172
|
+
return this.createMoment(momentTriggered.trigger, state);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Check if moment conditions are met (equations 18-20)
|
|
181
|
+
* @param {Object} state - Current state
|
|
182
|
+
*/
|
|
183
|
+
checkMomentConditions(state) {
|
|
184
|
+
const { coherence, entropy } = state;
|
|
185
|
+
|
|
186
|
+
// Condition 1: Coherence peak (equation 18)
|
|
187
|
+
// Cglobal(t) > Cthresh AND local maximum
|
|
188
|
+
const isCoherencePeak = this.isCoherencePeak(coherence);
|
|
189
|
+
|
|
190
|
+
// Condition 2: Entropy in valid range (equation 19)
|
|
191
|
+
// Hmin < H(t) < Hmax
|
|
192
|
+
const entropyValid = entropy > this.entropyMin && entropy < this.entropyMax;
|
|
193
|
+
|
|
194
|
+
// Condition 3: Phase transition (equation 20)
|
|
195
|
+
// Rate of phase change exceeds threshold
|
|
196
|
+
const phaseTransition = this.phaseTransitionRate() > this.phaseTransitionThreshold;
|
|
197
|
+
|
|
198
|
+
// Combined conditions
|
|
199
|
+
if (isCoherencePeak && entropyValid) {
|
|
200
|
+
return { triggered: true, trigger: 'coherence' };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (phaseTransition && entropyValid) {
|
|
204
|
+
return { triggered: true, trigger: 'phase_transition' };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Emergency moment if entropy at extremes (preventing freeze)
|
|
208
|
+
if (entropy < this.entropyMin * 0.5 || entropy > this.entropyMax * 1.5) {
|
|
209
|
+
return { triggered: true, trigger: 'entropy_extreme' };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return { triggered: false };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Check if current coherence is a local peak
|
|
217
|
+
* @param {number} coherence - Current coherence
|
|
218
|
+
*/
|
|
219
|
+
isCoherencePeak(coherence) {
|
|
220
|
+
if (coherence < this.coherenceThreshold) return false;
|
|
221
|
+
if (this.coherenceHistory.length < 3) return false;
|
|
222
|
+
|
|
223
|
+
const recent = this.coherenceHistory.slice(-5);
|
|
224
|
+
if (recent.length < 3) return false;
|
|
225
|
+
|
|
226
|
+
// Check if current is higher than neighbors
|
|
227
|
+
const current = recent[recent.length - 1].value;
|
|
228
|
+
for (let i = 0; i < recent.length - 1; i++) {
|
|
229
|
+
if (recent[i].value >= current) return false;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Calculate rate of phase transitions
|
|
237
|
+
*/
|
|
238
|
+
phaseTransitionRate() {
|
|
239
|
+
if (this.phaseHistory.length < 2) return 0;
|
|
240
|
+
|
|
241
|
+
const recent = this.phaseHistory.slice(-10);
|
|
242
|
+
if (recent.length < 2) return 0;
|
|
243
|
+
|
|
244
|
+
let totalChange = 0;
|
|
245
|
+
for (let i = 1; i < recent.length; i++) {
|
|
246
|
+
const prev = recent[i - 1].phases;
|
|
247
|
+
const curr = recent[i].phases;
|
|
248
|
+
|
|
249
|
+
if (!prev || !curr || prev.length !== curr.length) continue;
|
|
250
|
+
|
|
251
|
+
for (let j = 0; j < prev.length; j++) {
|
|
252
|
+
let delta = Math.abs(curr[j] - prev[j]);
|
|
253
|
+
// Handle phase wrapping
|
|
254
|
+
if (delta > Math.PI) delta = 2 * Math.PI - delta;
|
|
255
|
+
totalChange += delta;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const dt = (recent[recent.length - 1].time - recent[0].time) / 1000;
|
|
260
|
+
return dt > 0 ? totalChange / (recent.length * dt) : 0;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Create a new moment
|
|
265
|
+
* @param {string} trigger - Trigger type
|
|
266
|
+
* @param {Object} state - Current state
|
|
267
|
+
*/
|
|
268
|
+
createMoment(trigger, state) {
|
|
269
|
+
const { coherence, entropy, activePrimes, smf, semanticContent } = state;
|
|
270
|
+
|
|
271
|
+
// Calculate subjective duration (equation 24)
|
|
272
|
+
// Δτ = β * Σ Ap log(Ap)
|
|
273
|
+
const subjectiveDuration = this.calculateSubjectiveDuration(state);
|
|
274
|
+
|
|
275
|
+
// Get SMF snapshot - check if smf has required methods
|
|
276
|
+
let smfSnapshot = null;
|
|
277
|
+
if (smf && smf.s && Array.isArray(smf.s)) {
|
|
278
|
+
smfSnapshot = {
|
|
279
|
+
components: smf.s.slice(),
|
|
280
|
+
entropy: typeof smf.smfEntropy === 'function' ? smf.smfEntropy() : 0
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const moment = new Moment({
|
|
285
|
+
id: `m_${++this.momentCounter}`,
|
|
286
|
+
trigger,
|
|
287
|
+
coherence,
|
|
288
|
+
entropy,
|
|
289
|
+
phaseTransitionRate: this.phaseTransitionRate(),
|
|
290
|
+
activePrimes: activePrimes || [],
|
|
291
|
+
smfSnapshot,
|
|
292
|
+
semanticContent: semanticContent ? JSON.parse(JSON.stringify(semanticContent)) : null,
|
|
293
|
+
subjectiveDuration,
|
|
294
|
+
previousMomentId: this.currentMoment ? this.currentMoment.id : null
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
// Update subjective time
|
|
298
|
+
this.subjectiveTime += subjectiveDuration;
|
|
299
|
+
|
|
300
|
+
// Store moment
|
|
301
|
+
this.moments.push(moment);
|
|
302
|
+
this.currentMoment = moment;
|
|
303
|
+
|
|
304
|
+
// Callback
|
|
305
|
+
if (this.onMoment) {
|
|
306
|
+
this.onMoment(moment);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return moment;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Calculate subjective duration (equation 24)
|
|
314
|
+
* Δτ = β * Σ Ap log(Ap) (information content)
|
|
315
|
+
*
|
|
316
|
+
* @param {Object} state - Current state
|
|
317
|
+
*/
|
|
318
|
+
calculateSubjectiveDuration(state) {
|
|
319
|
+
const { amplitudes } = state;
|
|
320
|
+
|
|
321
|
+
if (!amplitudes || amplitudes.length === 0) return this.beta;
|
|
322
|
+
|
|
323
|
+
// Sum of Ap * log(Ap) for non-zero amplitudes
|
|
324
|
+
let informationContent = 0;
|
|
325
|
+
for (const A of amplitudes) {
|
|
326
|
+
if (A > 1e-10) {
|
|
327
|
+
informationContent += A * Math.log(A + 1);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Scale by beta, ensure positive
|
|
332
|
+
return Math.max(0.1, this.beta * Math.abs(informationContent) + 0.5);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Trim histories to max length
|
|
337
|
+
*/
|
|
338
|
+
trimHistories() {
|
|
339
|
+
if (this.coherenceHistory.length > this.maxHistory) {
|
|
340
|
+
this.coherenceHistory = this.coherenceHistory.slice(-this.maxHistory);
|
|
341
|
+
}
|
|
342
|
+
if (this.entropyHistory.length > this.maxHistory) {
|
|
343
|
+
this.entropyHistory = this.entropyHistory.slice(-this.maxHistory);
|
|
344
|
+
}
|
|
345
|
+
if (this.phaseHistory.length > this.maxHistory) {
|
|
346
|
+
this.phaseHistory = this.phaseHistory.slice(-this.maxHistory);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Force a moment (manual trigger)
|
|
352
|
+
* @param {Object} state - Current state
|
|
353
|
+
* @param {string} note - Optional note
|
|
354
|
+
*/
|
|
355
|
+
forceMoment(state, note = '') {
|
|
356
|
+
const moment = this.createMoment('manual', state);
|
|
357
|
+
moment.notes = note;
|
|
358
|
+
return moment;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Get recent moments
|
|
363
|
+
* @param {number} count - Number of moments to return
|
|
364
|
+
*/
|
|
365
|
+
recentMoments(count = 10) {
|
|
366
|
+
return this.moments.slice(-count);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Get moment by ID
|
|
371
|
+
* @param {string} id - Moment ID
|
|
372
|
+
*/
|
|
373
|
+
getMoment(id) {
|
|
374
|
+
return this.moments.find(m => m.id === id);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Get moment chain (linked list of previous moments)
|
|
379
|
+
* @param {string} startId - Starting moment ID
|
|
380
|
+
* @param {number} maxDepth - Maximum chain depth
|
|
381
|
+
*/
|
|
382
|
+
getMomentChain(startId, maxDepth = 10) {
|
|
383
|
+
const chain = [];
|
|
384
|
+
let current = this.getMoment(startId);
|
|
385
|
+
|
|
386
|
+
while (current && chain.length < maxDepth) {
|
|
387
|
+
chain.push(current);
|
|
388
|
+
if (current.previousMomentId) {
|
|
389
|
+
current = this.getMoment(current.previousMomentId);
|
|
390
|
+
} else {
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return chain;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Get subjective time elapsed
|
|
400
|
+
*/
|
|
401
|
+
getSubjectiveTime() {
|
|
402
|
+
return this.subjectiveTime;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Get ratio of subjective to clock time
|
|
407
|
+
*/
|
|
408
|
+
timeRatio() {
|
|
409
|
+
const clockElapsed = (Date.now() - this.moments[0]?.clockTime) / 1000;
|
|
410
|
+
if (clockElapsed < 1) return 1;
|
|
411
|
+
return this.subjectiveTime / clockElapsed;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Get average moment duration (clock time between moments)
|
|
416
|
+
*/
|
|
417
|
+
averageMomentDuration() {
|
|
418
|
+
if (this.moments.length < 2) return 0;
|
|
419
|
+
|
|
420
|
+
let totalDuration = 0;
|
|
421
|
+
for (let i = 1; i < this.moments.length; i++) {
|
|
422
|
+
totalDuration += this.moments[i].clockTime - this.moments[i - 1].clockTime;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return totalDuration / (this.moments.length - 1);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Get temporal statistics
|
|
430
|
+
*/
|
|
431
|
+
getStats() {
|
|
432
|
+
return {
|
|
433
|
+
momentCount: this.moments.length,
|
|
434
|
+
subjectiveTime: this.subjectiveTime,
|
|
435
|
+
averageMomentDuration: this.averageMomentDuration(),
|
|
436
|
+
timeRatio: this.timeRatio(),
|
|
437
|
+
lastCoherence: this.coherenceHistory.length > 0
|
|
438
|
+
? this.coherenceHistory[this.coherenceHistory.length - 1].value : 0,
|
|
439
|
+
lastEntropy: this.entropyHistory.length > 0
|
|
440
|
+
? this.entropyHistory[this.entropyHistory.length - 1].value : 0,
|
|
441
|
+
phaseTransitionRate: this.phaseTransitionRate()
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Reset temporal layer
|
|
447
|
+
*/
|
|
448
|
+
reset() {
|
|
449
|
+
this.moments = [];
|
|
450
|
+
this.currentMoment = null;
|
|
451
|
+
this.subjectiveTime = 0;
|
|
452
|
+
this.lastClockTime = Date.now();
|
|
453
|
+
this.momentCounter = 0;
|
|
454
|
+
this.coherenceHistory = [];
|
|
455
|
+
this.entropyHistory = [];
|
|
456
|
+
this.phaseHistory = [];
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Serialize to JSON
|
|
461
|
+
*/
|
|
462
|
+
toJSON() {
|
|
463
|
+
return {
|
|
464
|
+
moments: this.moments.map(m => m.toJSON()),
|
|
465
|
+
subjectiveTime: this.subjectiveTime,
|
|
466
|
+
momentCounter: this.momentCounter,
|
|
467
|
+
config: {
|
|
468
|
+
coherenceThreshold: this.coherenceThreshold,
|
|
469
|
+
entropyMin: this.entropyMin,
|
|
470
|
+
entropyMax: this.entropyMax,
|
|
471
|
+
phaseTransitionThreshold: this.phaseTransitionThreshold,
|
|
472
|
+
beta: this.beta
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Load from JSON
|
|
479
|
+
* @param {Object} data - Serialized data
|
|
480
|
+
*/
|
|
481
|
+
loadFromJSON(data) {
|
|
482
|
+
if (data.moments) {
|
|
483
|
+
this.moments = data.moments.map(m => Moment.fromJSON(m));
|
|
484
|
+
if (this.moments.length > 0) {
|
|
485
|
+
this.currentMoment = this.moments[this.moments.length - 1];
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
if (data.subjectiveTime) {
|
|
489
|
+
this.subjectiveTime = data.subjectiveTime;
|
|
490
|
+
}
|
|
491
|
+
if (data.momentCounter) {
|
|
492
|
+
this.momentCounter = data.momentCounter;
|
|
493
|
+
}
|
|
494
|
+
if (data.config) {
|
|
495
|
+
Object.assign(this, data.config);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Temporal Pattern Detector
|
|
502
|
+
*
|
|
503
|
+
* Detects recurring patterns in temporal sequences,
|
|
504
|
+
* supporting anticipation and prediction.
|
|
505
|
+
*/
|
|
506
|
+
class TemporalPatternDetector {
|
|
507
|
+
/**
|
|
508
|
+
* Create a pattern detector
|
|
509
|
+
* @param {Object} options - Configuration
|
|
510
|
+
*/
|
|
511
|
+
constructor(options = {}) {
|
|
512
|
+
this.windowSize = options.windowSize || 5;
|
|
513
|
+
this.minPatternLength = options.minPatternLength || 2;
|
|
514
|
+
this.maxPatternLength = options.maxPatternLength || 10;
|
|
515
|
+
this.similarityThreshold = options.similarityThreshold || 0.8;
|
|
516
|
+
|
|
517
|
+
this.patterns = [];
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Detect patterns in moment sequence
|
|
522
|
+
* @param {Array<Moment>} moments - Sequence of moments
|
|
523
|
+
*/
|
|
524
|
+
detectPatterns(moments) {
|
|
525
|
+
if (moments.length < this.minPatternLength * 2) return [];
|
|
526
|
+
|
|
527
|
+
const signatures = moments.map(m => this.momentSignature(m));
|
|
528
|
+
const detected = [];
|
|
529
|
+
|
|
530
|
+
for (let len = this.minPatternLength; len <= Math.min(this.maxPatternLength, Math.floor(signatures.length / 2)); len++) {
|
|
531
|
+
for (let i = 0; i <= signatures.length - len * 2; i++) {
|
|
532
|
+
const pattern = signatures.slice(i, i + len);
|
|
533
|
+
const next = signatures.slice(i + len, i + len * 2);
|
|
534
|
+
|
|
535
|
+
if (this.matchPattern(pattern, next)) {
|
|
536
|
+
detected.push({
|
|
537
|
+
pattern: moments.slice(i, i + len),
|
|
538
|
+
repetition: moments.slice(i + len, i + len * 2),
|
|
539
|
+
startIndex: i,
|
|
540
|
+
length: len,
|
|
541
|
+
strength: this.patternStrength(pattern, next)
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
return this.deduplicatePatterns(detected);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Generate signature for a moment
|
|
552
|
+
* @param {Moment} moment - Moment to sign
|
|
553
|
+
*/
|
|
554
|
+
momentSignature(moment) {
|
|
555
|
+
return {
|
|
556
|
+
trigger: moment.trigger,
|
|
557
|
+
coherenceLevel: Math.round(moment.coherence * 10) / 10,
|
|
558
|
+
entropyLevel: Math.round(moment.entropy * 10) / 10,
|
|
559
|
+
primeCount: moment.activePrimes.length,
|
|
560
|
+
dominantPrimes: moment.activePrimes.slice(0, 3)
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Check if two signatures match
|
|
566
|
+
* @param {Array} pattern - First pattern
|
|
567
|
+
* @param {Array} other - Second pattern
|
|
568
|
+
*/
|
|
569
|
+
matchPattern(pattern, other) {
|
|
570
|
+
if (pattern.length !== other.length) return false;
|
|
571
|
+
|
|
572
|
+
let matches = 0;
|
|
573
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
574
|
+
if (this.signaturesMatch(pattern[i], other[i])) {
|
|
575
|
+
matches++;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
return matches / pattern.length >= this.similarityThreshold;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Check if two moment signatures match
|
|
584
|
+
*/
|
|
585
|
+
signaturesMatch(sig1, sig2) {
|
|
586
|
+
if (sig1.trigger !== sig2.trigger) return false;
|
|
587
|
+
if (Math.abs(sig1.coherenceLevel - sig2.coherenceLevel) > 0.2) return false;
|
|
588
|
+
if (Math.abs(sig1.entropyLevel - sig2.entropyLevel) > 0.2) return false;
|
|
589
|
+
return true;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Calculate pattern strength
|
|
594
|
+
*/
|
|
595
|
+
patternStrength(pattern, repetition) {
|
|
596
|
+
let totalSimilarity = 0;
|
|
597
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
598
|
+
const s1 = pattern[i];
|
|
599
|
+
const s2 = repetition[i];
|
|
600
|
+
|
|
601
|
+
let similarity = 0;
|
|
602
|
+
if (s1.trigger === s2.trigger) similarity += 0.3;
|
|
603
|
+
similarity += 0.3 * (1 - Math.abs(s1.coherenceLevel - s2.coherenceLevel));
|
|
604
|
+
similarity += 0.3 * (1 - Math.abs(s1.entropyLevel - s2.entropyLevel));
|
|
605
|
+
similarity += 0.1 * (s1.primeCount === s2.primeCount ? 1 : 0);
|
|
606
|
+
|
|
607
|
+
totalSimilarity += similarity;
|
|
608
|
+
}
|
|
609
|
+
return totalSimilarity / pattern.length;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Remove duplicate/overlapping patterns
|
|
614
|
+
*/
|
|
615
|
+
deduplicatePatterns(patterns) {
|
|
616
|
+
const unique = [];
|
|
617
|
+
|
|
618
|
+
patterns.sort((a, b) => b.strength - a.strength);
|
|
619
|
+
|
|
620
|
+
for (const pattern of patterns) {
|
|
621
|
+
const overlaps = unique.some(u =>
|
|
622
|
+
Math.abs(u.startIndex - pattern.startIndex) < u.length
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
if (!overlaps) {
|
|
626
|
+
unique.push(pattern);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
return unique;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Predict next moment characteristics based on patterns
|
|
635
|
+
* @param {Array<Moment>} moments - Recent moments
|
|
636
|
+
*/
|
|
637
|
+
predictNext(moments) {
|
|
638
|
+
const patterns = this.detectPatterns(moments);
|
|
639
|
+
|
|
640
|
+
if (patterns.length === 0) return null;
|
|
641
|
+
|
|
642
|
+
const bestPattern = patterns[0];
|
|
643
|
+
const currentPosition = moments.length - bestPattern.startIndex;
|
|
644
|
+
const patternPosition = currentPosition % bestPattern.length;
|
|
645
|
+
|
|
646
|
+
if (patternPosition < bestPattern.pattern.length - 1) {
|
|
647
|
+
const nextInPattern = bestPattern.pattern[patternPosition + 1];
|
|
648
|
+
return {
|
|
649
|
+
predicted: this.momentSignature(nextInPattern),
|
|
650
|
+
confidence: bestPattern.strength,
|
|
651
|
+
patternLength: bestPattern.length
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
return null;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
export {
|
|
660
|
+
Moment,
|
|
661
|
+
TemporalLayer,
|
|
662
|
+
TemporalPatternDetector
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
export default {
|
|
666
|
+
Moment,
|
|
667
|
+
TemporalLayer,
|
|
668
|
+
TemporalPatternDetector
|
|
669
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aleph-ai/tinyaleph",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.7",
|
|
4
4
|
"description": "Prime-resonant semantic computing framework - hypercomplex algebra, oscillator dynamics, and entropy-minimizing reasoning",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"physics/",
|
|
91
91
|
"backends/",
|
|
92
92
|
"engine/",
|
|
93
|
+
"observer/",
|
|
93
94
|
"telemetry/",
|
|
94
95
|
"types/",
|
|
95
96
|
"docs/",
|