cozo-memory 1.1.8 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const index_1 = require("./index");
37
+ const fs = __importStar(require("fs"));
38
+ const TEST_DB_PATH = 'test_advanced_search_mcp';
39
+ async function runTest() {
40
+ console.error('=== Testing qafd_search and hierarchical_memory_query MCP Tools ===\n');
41
+ // Clean up old test database
42
+ const dbFile = `${TEST_DB_PATH}.db`;
43
+ if (fs.existsSync(dbFile)) {
44
+ try {
45
+ fs.unlinkSync(dbFile);
46
+ console.error('[Cleanup] Removed old test database');
47
+ }
48
+ catch (e) {
49
+ console.error('[Cleanup] Warning: Could not remove old database:', e);
50
+ }
51
+ }
52
+ const server = new index_1.MemoryServer(TEST_DB_PATH);
53
+ await server.initPromise;
54
+ try {
55
+ console.error('1. Creating test entities and relationships...');
56
+ const entity1 = await server.createEntity({
57
+ name: 'Machine Learning',
58
+ type: 'Topic',
59
+ metadata: {}
60
+ });
61
+ const entity2 = await server.createEntity({
62
+ name: 'Neural Networks',
63
+ type: 'Topic',
64
+ metadata: {}
65
+ });
66
+ const entity3 = await server.createEntity({
67
+ name: 'Deep Learning',
68
+ type: 'Topic',
69
+ metadata: {}
70
+ });
71
+ console.error(`✓ Created 3 entities\n`);
72
+ // Create relationships
73
+ await server.createRelation({
74
+ from_id: entity1.id,
75
+ to_id: entity2.id,
76
+ relation_type: 'includes',
77
+ strength: 0.9
78
+ });
79
+ await server.createRelation({
80
+ from_id: entity2.id,
81
+ to_id: entity3.id,
82
+ relation_type: 'specializes_to',
83
+ strength: 0.85
84
+ });
85
+ console.error('✓ Created relationships\n');
86
+ // Add observations at different levels
87
+ await server.addObservation({
88
+ entity_id: entity1.id,
89
+ text: 'Machine learning is a subset of artificial intelligence',
90
+ metadata: { memory_level: 0 },
91
+ deduplicate: false
92
+ });
93
+ await server.addObservation({
94
+ entity_id: entity2.id,
95
+ text: 'Neural networks are inspired by biological neurons',
96
+ metadata: { memory_level: 0 },
97
+ deduplicate: false
98
+ });
99
+ await server.addObservation({
100
+ entity_id: entity3.id,
101
+ text: 'Deep learning uses multiple layers of neural networks',
102
+ metadata: { memory_level: 1 },
103
+ deduplicate: false
104
+ });
105
+ console.error('✓ Added observations at different memory levels\n');
106
+ console.error('2. Testing qafd_search (Query-Aware Flow Diffusion)...');
107
+ const qafdResult = await server.getQueryAwareTraversal().hybridSearch('artificial intelligence and neural networks', {
108
+ seedTopK: 2,
109
+ maxHops: 2,
110
+ dampingFactor: 0.85,
111
+ minScore: 0.05,
112
+ topK: 10
113
+ });
114
+ console.error(`✓ QAFD search completed: ${qafdResult.length} results found`);
115
+ if (qafdResult.length > 0) {
116
+ console.error('\n3. Analyzing QAFD results...');
117
+ qafdResult.slice(0, 3).forEach((result, i) => {
118
+ console.error(`\n Result ${i + 1}:`);
119
+ console.error(` Entity: ${result.name || result.entity_name || 'Unknown'}`);
120
+ console.error(` Score: ${result.score?.toFixed(4) || result.finalScore?.toFixed(4) || 'N/A'}`);
121
+ console.error(` Hops: ${result.hops || result.hop || 0}`);
122
+ });
123
+ }
124
+ console.error('\n4. Testing hierarchical_memory_query...');
125
+ // Query all levels
126
+ const queryEmbedding = await server.embeddingService.embed('neural networks and deep learning');
127
+ const allLevelsResult = await server.db.run(`
128
+ ?[id, entity_id, text, memory_level, dist] :=
129
+ ~observation:semantic{
130
+ id |
131
+ query: vec($embedding),
132
+ k: 10,
133
+ ef: 100,
134
+ bind_distance: dist
135
+ },
136
+ *observation{id, entity_id, text, metadata, @ "NOW"},
137
+ memory_level = get(metadata, "memory_level", 0)
138
+
139
+ :order dist
140
+ `, { embedding: queryEmbedding });
141
+ const observations = allLevelsResult.rows.map((r) => ({
142
+ id: r[0],
143
+ entity_id: r[1],
144
+ text: r[2],
145
+ memory_level: r[3],
146
+ distance: r[4]
147
+ }));
148
+ console.error(`✓ Hierarchical memory query completed: ${observations.length} results found`);
149
+ if (observations.length > 0) {
150
+ console.error('\n5. Analyzing hierarchical memory results...');
151
+ const byLevel = {};
152
+ observations.forEach((obs) => {
153
+ byLevel[obs.memory_level] = (byLevel[obs.memory_level] || 0) + 1;
154
+ });
155
+ console.error(' Distribution by level:');
156
+ Object.entries(byLevel).forEach(([level, count]) => {
157
+ console.error(` L${level}: ${count} observations`);
158
+ });
159
+ console.error('\n Top 3 results:');
160
+ observations.slice(0, 3).forEach((obs, i) => {
161
+ console.error(`\n ${i + 1}. Level ${obs.memory_level}`);
162
+ console.error(` Text: ${obs.text.substring(0, 60)}...`);
163
+ console.error(` Distance: ${obs.distance.toFixed(4)}`);
164
+ });
165
+ }
166
+ console.error('\n6. Testing hierarchical_memory_query with level filter...');
167
+ const l0OnlyResult = await server.db.run(`
168
+ ?[id, entity_id, text, memory_level, dist] :=
169
+ ~observation:semantic{
170
+ id |
171
+ query: vec($embedding),
172
+ k: 10,
173
+ ef: 100,
174
+ bind_distance: dist
175
+ },
176
+ *observation{id, entity_id, text, metadata, @ "NOW"},
177
+ memory_level = get(metadata, "memory_level", 0),
178
+ memory_level = 0
179
+
180
+ :order dist
181
+ `, { embedding: queryEmbedding });
182
+ console.error(`✓ L0-only query completed: ${l0OnlyResult.rows.length} results found`);
183
+ console.error('\n=== ✓ Advanced Search MCP Tools Test Passed ===\n');
184
+ }
185
+ catch (error) {
186
+ console.error('\n=== ✗ Test Failed ===');
187
+ console.error('Error:', error);
188
+ throw error;
189
+ }
190
+ finally {
191
+ // Cleanup
192
+ server.db.close();
193
+ if (fs.existsSync(dbFile)) {
194
+ try {
195
+ fs.unlinkSync(dbFile);
196
+ console.error('[Cleanup] Test database removed');
197
+ }
198
+ catch (e) {
199
+ console.error('[Cleanup] Warning: Could not remove test database');
200
+ }
201
+ }
202
+ }
203
+ }
204
+ runTest().catch(console.error);
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const index_1 = require("./index");
37
+ const fs = __importStar(require("fs"));
38
+ const TEST_DB_PATH = 'test_conflicts_mcp';
39
+ async function runTest() {
40
+ console.error('=== Testing detect_conflicts and resolve_conflicts MCP Tools ===\n');
41
+ // Clean up old test database
42
+ const dbFile = `${TEST_DB_PATH}.db`;
43
+ if (fs.existsSync(dbFile)) {
44
+ try {
45
+ fs.unlinkSync(dbFile);
46
+ console.error('[Cleanup] Removed old test database');
47
+ }
48
+ catch (e) {
49
+ console.error('[Cleanup] Warning: Could not remove old database:', e);
50
+ }
51
+ }
52
+ const server = new index_1.MemoryServer(TEST_DB_PATH);
53
+ await server.initPromise;
54
+ try {
55
+ console.error('1. Creating test entity...');
56
+ const entityResult = await server.createEntity({
57
+ name: 'Project Alpha',
58
+ type: 'Project',
59
+ metadata: {}
60
+ });
61
+ const entityId = entityResult.id;
62
+ console.error(`✓ Created entity: ${entityId}\n`);
63
+ console.error('2. Adding observations with potential conflicts...');
64
+ // Add first observation
65
+ const obs1 = await server.addObservation({
66
+ entity_id: entityId,
67
+ text: 'Project status is pending approval',
68
+ metadata: { timestamp: Date.now() }
69
+ });
70
+ console.error(`✓ Added observation 1: ${obs1.id?.substring(0, 8)}...`);
71
+ // Wait a bit to ensure different timestamps
72
+ await new Promise(resolve => setTimeout(resolve, 100));
73
+ // Add redundant observation (very similar)
74
+ const obs2 = await server.addObservation({
75
+ entity_id: entityId,
76
+ text: 'Project status is pending approval and waiting',
77
+ metadata: { timestamp: Date.now() }
78
+ });
79
+ console.error(`✓ Added observation 2 (redundant): ${obs2.id?.substring(0, 8)}...`);
80
+ await new Promise(resolve => setTimeout(resolve, 100));
81
+ // Add superseding observation
82
+ const obs3 = await server.addObservation({
83
+ entity_id: entityId,
84
+ text: 'Project status updated: now approved and in progress',
85
+ metadata: { timestamp: Date.now() }
86
+ });
87
+ console.error(`✓ Added observation 3 (superseding): ${obs3.id?.substring(0, 8)}...`);
88
+ await new Promise(resolve => setTimeout(resolve, 100));
89
+ // Add contradictory observation
90
+ const obs4 = await server.addObservation({
91
+ entity_id: entityId,
92
+ text: 'Project is not approved and has been rejected',
93
+ metadata: { timestamp: Date.now() }
94
+ });
95
+ console.error(`✓ Added observation 4 (contradictory): ${obs4.id?.substring(0, 8)}...\n`);
96
+ console.error('3. Testing detect_conflicts...');
97
+ const conflicts = await server.getConflictService().detectConflicts(entityId);
98
+ console.error(`✓ Conflict detection completed: ${conflicts.length} conflicts found`);
99
+ if (conflicts.length > 0) {
100
+ console.error('\n4. Analyzing detected conflicts...');
101
+ conflicts.forEach((conflict, i) => {
102
+ console.error(`\n Conflict ${i + 1}:`);
103
+ console.error(` Type: ${conflict.conflict_type}`);
104
+ console.error(` Confidence: ${conflict.confidence.toFixed(2)} (${conflict.confidence_level})`);
105
+ console.error(` Older: "${conflict.older_text.substring(0, 50)}..."`);
106
+ console.error(` Newer: "${conflict.newer_text.substring(0, 50)}..."`);
107
+ console.error(` Reason: ${conflict.reason}`);
108
+ });
109
+ // Verify conflict types
110
+ console.error('\n5. Verifying conflict types...');
111
+ const redundancyConflicts = conflicts.filter(c => c.conflict_type === 'temporal_redundancy');
112
+ const contradictionConflicts = conflicts.filter(c => c.conflict_type === 'semantic_contradiction');
113
+ const supersededConflicts = conflicts.filter(c => c.conflict_type === 'superseded_fact');
114
+ console.error(` - Temporal Redundancy: ${redundancyConflicts.length}`);
115
+ console.error(` - Semantic Contradiction: ${contradictionConflicts.length}`);
116
+ console.error(` - Superseded Fact: ${supersededConflicts.length}`);
117
+ // Check confidence levels
118
+ const highConfidence = conflicts.filter(c => c.confidence_level === 'high');
119
+ const mediumConfidence = conflicts.filter(c => c.confidence_level === 'medium');
120
+ const lowConfidence = conflicts.filter(c => c.confidence_level === 'low');
121
+ console.error('\n6. Confidence distribution:');
122
+ console.error(` - High: ${highConfidence.length}`);
123
+ console.error(` - Medium: ${mediumConfidence.length}`);
124
+ console.error(` - Low: ${lowConfidence.length}`);
125
+ console.error('\n7. Testing resolve_conflicts...');
126
+ const resolution = await server.getConflictService().resolveConflicts(entityId);
127
+ console.error(`✓ Conflict resolution completed:`);
128
+ console.error(` - Resolved conflicts: ${resolution.resolved_conflicts}`);
129
+ console.error(` - Invalidated observations: ${resolution.invalidated_observations.length}`);
130
+ console.error(` - Audit trail entries: ${resolution.audit_observations.length}`);
131
+ if (resolution.invalidated_observations.length > 0) {
132
+ console.error('\n8. Verifying invalidated observations...');
133
+ console.error(` Invalidated IDs: ${resolution.invalidated_observations.map(id => id.substring(0, 8)).join(', ')}...`);
134
+ }
135
+ if (resolution.audit_observations.length > 0) {
136
+ console.error('\n9. Verifying audit trail...');
137
+ console.error(` Audit IDs: ${resolution.audit_observations.map(id => id.substring(0, 8)).join(', ')}...`);
138
+ }
139
+ console.error('\n10. Re-checking for conflicts after resolution...');
140
+ const remainingConflicts = await server.getConflictService().detectConflicts(entityId);
141
+ console.error(`✓ Remaining conflicts: ${remainingConflicts.length} (expected: 0)`);
142
+ if (remainingConflicts.length === 0) {
143
+ console.error(' ✓ All conflicts successfully resolved!');
144
+ }
145
+ else {
146
+ console.error(' ⚠ Some conflicts remain (this may be expected for certain conflict types)');
147
+ }
148
+ }
149
+ else {
150
+ console.error('⚠ No conflicts detected (observations may be too dissimilar)');
151
+ }
152
+ console.error('\n=== ✓ Conflict Detection and Resolution MCP Tools Test Passed ===\n');
153
+ }
154
+ catch (error) {
155
+ console.error('\n=== ✗ Test Failed ===');
156
+ console.error('Error:', error);
157
+ throw error;
158
+ }
159
+ finally {
160
+ // Cleanup
161
+ server.db.close();
162
+ if (fs.existsSync(dbFile)) {
163
+ try {
164
+ fs.unlinkSync(dbFile);
165
+ console.error('[Cleanup] Test database removed');
166
+ }
167
+ catch (e) {
168
+ console.error('[Cleanup] Warning: Could not remove test database');
169
+ }
170
+ }
171
+ }
172
+ }
173
+ runTest().catch(console.error);
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const cozo_node_1 = require("cozo-node");
4
+ const emotional_salience_1 = require("./emotional-salience");
5
+ async function testEmotionalSalience() {
6
+ console.log('=== Emotional Salience Weighting Test ===\n');
7
+ const db = new cozo_node_1.CozoDb();
8
+ const salienceService = new emotional_salience_1.EmotionalSalienceService(db, {
9
+ enableSalience: true,
10
+ salienceBoostFactor: 2.0,
11
+ decaySlowdownFactor: 0.5,
12
+ minSalienceThreshold: 0.3
13
+ });
14
+ try {
15
+ // Initialize database schema
16
+ await db.run(`
17
+ :create entity {
18
+ id: String,
19
+ =>
20
+ name: String,
21
+ type: String,
22
+ }
23
+ `);
24
+ await db.run(`
25
+ :create observation {
26
+ id: String,
27
+ =>
28
+ entity_id: String,
29
+ text: String,
30
+ metadata: Json?,
31
+ }
32
+ `);
33
+ console.log('✓ Database initialized\n');
34
+ // Test 1: Create test observations with varying emotional salience
35
+ console.log('Test 1: Creating observations with different salience levels...');
36
+ const testObservations = [
37
+ {
38
+ text: 'CRITICAL: Never forget to backup the database before deployment. This is extremely important!',
39
+ expected: 'high'
40
+ },
41
+ {
42
+ text: 'Important reminder: The deadline for the project is next Friday.',
43
+ expected: 'medium'
44
+ },
45
+ {
46
+ text: 'Interesting discovery: The new algorithm is 20% faster than the old one.',
47
+ expected: 'medium'
48
+ },
49
+ {
50
+ text: 'Note: The meeting is scheduled for 3 PM tomorrow.',
51
+ expected: 'low'
52
+ },
53
+ {
54
+ text: 'The weather is nice today.',
55
+ expected: 'neutral'
56
+ },
57
+ {
58
+ text: 'URGENT: Security vulnerability detected in authentication module. Immediate action required!',
59
+ expected: 'high'
60
+ },
61
+ {
62
+ text: 'Surprising breakthrough in machine learning research announced today.',
63
+ expected: 'medium'
64
+ }
65
+ ];
66
+ // Create entity
67
+ const entityResult = await db.run(`
68
+ ?[id, name, type] <- [['test-entity', 'Test Entity', 'Test']]
69
+ :put entity {id, name, type}
70
+ `);
71
+ for (const obs of testObservations) {
72
+ const obsId = `obs-${Math.random().toString(36).substring(7)}`;
73
+ await db.run(`
74
+ ?[id, entity_id, text, metadata] <- [[
75
+ $id,
76
+ 'test-entity',
77
+ $text,
78
+ {}
79
+ ]]
80
+ :put observation {id, entity_id, text, metadata}
81
+ `, { id: obsId, text: obs.text });
82
+ }
83
+ console.log(`✓ Created ${testObservations.length} test observations\n`);
84
+ // Test 2: Calculate salience scores
85
+ console.log('Test 2: Calculating salience scores...');
86
+ const scores = await salienceService.scoreAllObservations();
87
+ console.log(`\nSalience Scores (sorted by score):`);
88
+ console.log('─'.repeat(80));
89
+ for (const score of scores.slice(0, 10)) {
90
+ console.log(`Score: ${score.salienceScore.toFixed(3)} | Category: ${score.category.toUpperCase()}`);
91
+ console.log(`Text: ${score.text.substring(0, 70)}${score.text.length > 70 ? '...' : ''}`);
92
+ console.log(`Keywords: ${score.detectedKeywords.join(', ')}`);
93
+ console.log(`Boost: Strength ×${score.boost.strengthMultiplier.toFixed(2)}, Decay -${(score.boost.decayReduction * 100).toFixed(0)}%`);
94
+ console.log(`Reason: ${score.reason}`);
95
+ console.log('─'.repeat(80));
96
+ }
97
+ // Test 3: Verify keyword detection
98
+ console.log('\nTest 3: Verifying keyword detection accuracy...');
99
+ let correctDetections = 0;
100
+ for (let i = 0; i < testObservations.length; i++) {
101
+ const expected = testObservations[i].expected;
102
+ const actual = scores.find(s => s.text === testObservations[i].text)?.category || 'neutral';
103
+ const match = expected === actual;
104
+ correctDetections += match ? 1 : 0;
105
+ console.log(`${match ? '✓' : '✗'} Expected: ${expected.padEnd(8)} | Actual: ${actual.padEnd(8)} | "${testObservations[i].text.substring(0, 50)}..."`);
106
+ }
107
+ console.log(`\nAccuracy: ${correctDetections}/${testObservations.length} (${(correctDetections / testObservations.length * 100).toFixed(1)}%)\n`);
108
+ // Test 4: Apply salience metadata (dry run)
109
+ console.log('Test 4: Applying salience metadata (dry run)...');
110
+ const dryRunResult = await salienceService.applySalienceMetadata(true);
111
+ console.log(`Would update ${dryRunResult.updated} observations (dry run)`);
112
+ console.log(`Observations with salience >= threshold: ${dryRunResult.scores.length}\n`);
113
+ // Test 5: Apply salience metadata (actual)
114
+ console.log('Test 5: Applying salience metadata (actual)...');
115
+ const applyResult = await salienceService.applySalienceMetadata(false);
116
+ console.log(`✓ Updated ${applyResult.updated} observations with salience metadata\n`);
117
+ // Test 6: Get statistics
118
+ console.log('Test 6: Getting salience statistics...');
119
+ const stats = await salienceService.getSalienceStats();
120
+ console.log(`Total Observations: ${stats.totalObservations}`);
121
+ console.log(`With Salience (>= threshold): ${stats.withSalience}`);
122
+ console.log(`Average Salience: ${stats.averageSalience.toFixed(3)}`);
123
+ console.log(`\nDistribution:`);
124
+ console.log(` High (>= 0.7): ${stats.distribution.high}`);
125
+ console.log(` Medium (0.4-0.7): ${stats.distribution.medium}`);
126
+ console.log(` Low (0.3-0.4): ${stats.distribution.low}`);
127
+ console.log(` Neutral (< 0.3): ${stats.distribution.neutral}`);
128
+ console.log(`\nTop Keywords:`);
129
+ for (const { keyword, count } of stats.topKeywords.slice(0, 5)) {
130
+ console.log(` ${keyword.padEnd(20)} ${count}`);
131
+ }
132
+ console.log();
133
+ // Test 7: Get specific observation salience
134
+ console.log('Test 7: Getting salience for specific observation...');
135
+ const firstScore = scores[0];
136
+ const specificSalience = await salienceService.getObservationSalience(firstScore.observationId);
137
+ if (specificSalience) {
138
+ console.log(`✓ Retrieved salience for observation: ${specificSalience.observationId}`);
139
+ console.log(` Score: ${specificSalience.salienceScore.toFixed(3)}`);
140
+ console.log(` Category: ${specificSalience.category}`);
141
+ console.log(` Keywords: ${specificSalience.detectedKeywords.join(', ')}`);
142
+ }
143
+ console.log();
144
+ // Test 8: Test edge cases
145
+ console.log('Test 8: Testing edge cases...');
146
+ const edgeCases = [
147
+ { text: '', expected: 0 },
148
+ { text: 'CRITICAL URGENT IMPORTANT NEVER FORGET', expected: 1.0 },
149
+ { text: 'critical critical critical', expected: 1.0 }, // Duplicate keywords
150
+ { text: 'This is critically important and urgent!', expected: 0.8 }
151
+ ];
152
+ for (const testCase of edgeCases) {
153
+ const result = salienceService.calculateSalienceScore(testCase.text);
154
+ const pass = Math.abs(result.score - testCase.expected) < 0.2; // Allow 0.2 tolerance
155
+ console.log(`${pass ? '✓' : '✗'} "${testCase.text}" => ${result.score.toFixed(3)} (expected ~${testCase.expected})`);
156
+ }
157
+ console.log();
158
+ // Test 9: Integration with Memory Activation
159
+ console.log('Test 9: Demonstrating integration with Memory Activation...');
160
+ console.log('Salience boosts can be applied to ACT-R Memory Activation:');
161
+ console.log(' - High salience (0.8): Strength ×1.8, Decay -40%');
162
+ console.log(' - Medium salience (0.5): Strength ×1.5, Decay -25%');
163
+ console.log(' - Low salience (0.3): Strength ×1.3, Decay -15%');
164
+ console.log(' - Neutral (0.0): No boost applied');
165
+ console.log('\nThis slows down Ebbinghaus forgetting curve for emotionally salient memories.\n');
166
+ console.log('=== All Tests Completed Successfully ===');
167
+ }
168
+ catch (error) {
169
+ console.error('Test failed:', error);
170
+ throw error;
171
+ }
172
+ finally {
173
+ db.close();
174
+ }
175
+ }
176
+ // Run tests
177
+ testEmotionalSalience().catch(console.error);