Compare commits

..

3 Commits

Author SHA1 Message Date
f9146b40ef feat(mnemosyne): add Spatial Memory Schema
Some checks failed
CI / test (pull_request) Failing after 10s
CI / validate (pull_request) Failing after 12s
Review Approval Gate / verify-review (pull_request) Failing after 2s
Implements #1152:
- SpatialMemorySchema class with 6 default memory zones
- Zones mapped to Nexus regions (conversations, skills, facts, preferences, transient, deep)
- spawnMemoryOrb routes memories to their zone based on type
- spawnRetrievalOrbs uses schema for spatial positioning
- Zone visualization via ground rings at each zone boundary
- localStorage persistence for orb counts across sessions
2026-04-10 04:45:31 +00:00
c1b56571ed feat: implement spatial memory schema for Project Mnemosyne
Some checks failed
CI / test (pull_request) Failing after 21s
CI / validate (pull_request) Failing after 32s
Review Approval Gate / verify-review (pull_request) Failing after 8s
Maps memory categories to Nexus rooms with visual themes, spatial coordinates, and lifecycle events. This is the foundation for the holographic memory visualization system.
2026-04-10 03:11:05 +00:00
182a1148eb Merge pull request '[PERPLEXITY-03] Replace SOUL.md with pointer to canonical timmy-home version' (#1133) from perplexity/soul-md-pointer into main
Some checks failed
Deploy Nexus / deploy (push) Failing after 2s
Staging Verification Gate / verify-staging (push) Failing after 3s
2026-04-08 11:10:32 +00:00
2 changed files with 508 additions and 0 deletions

196
app.js
View File

@@ -41,6 +41,7 @@ let harnessPulseMesh;
let powerMeterBars = [];
let particles, dustParticles;
let debugOverlay;
let spatialSchema; // Project Mnemosyne — Spatial Memory Schema
let frameCount = 0, lastFPSTime = 0, fps = 0;
let chatOpen = true;
let loadProgress = 0;
@@ -592,6 +593,192 @@ let pseLayer;
let metaLayer, neuroBridge, cbr, symbolicPlanner, knowledgeGraph, blackboard, symbolicEngine, calibrator;
let agentFSMs = {};
// ═══════════════════════════════════════════
// PROJECT MNEMOSYNE — SPATIAL MEMORY SCHEMA
// ═══════════════════════════════════════════
/**
* SpatialMemorySchema — Maps memory categories to persistent 3D world regions.
* Each memory type has a dedicated "zone" in the Nexus, so recalled memories
* always appear in their neighborhood. Zones persist via localStorage.
*/
class SpatialMemorySchema {
constructor() {
this.zones = new Map();
this.zoneVisuals = [];
this.STORAGE_KEY = 'nexus_spatial_memory_zones';
// Default zones mapped to Nexus regions
this._defineDefaultZones();
this._loadPersistedZones();
}
_defineDefaultZones() {
// Workshop area — conversations and chat memories
this.registerZone('conversations', new THREE.Vector3(0, 0, -18), 6, 0x4af0c0, {
description: 'Chat history and conversation memories',
icon: '💬'
});
// Archive region — skills and procedures
this.registerZone('skills', new THREE.Vector3(23, 0, 0), 6, 0x0066ff, {
description: 'Learned skills and procedural knowledge',
icon: '⚙️'
});
// Central hub — environment facts
this.registerZone('facts', new THREE.Vector3(0, 0, 0), 5, 0xffd700, {
description: 'Environmental facts and stable knowledge',
icon: '📋'
});
// Near player start — user preferences and corrections
this.registerZone('preferences', new THREE.Vector3(-8, 0, 8), 4, 0x7b5cff, {
description: 'User preferences and corrections',
icon: '🎯'
});
// Outer ring — transient/session data
this.registerZone('transient', new THREE.Vector3(0, 0, 20), 8, 0xff4466, {
description: 'Session data and temporary memories (fades quickly)',
icon: '⏳'
});
// Chapel area — deep/sacred memories
this.registerZone('deep', new THREE.Vector3(-20, 0, 0), 5, 0xff8800, {
description: 'Deep memories, insights, and important events',
icon: '🔮'
});
}
registerZone(name, center, radius, color, metadata = {}) {
this.zones.set(name, {
name,
center: center.clone(),
radius,
color,
metadata,
orbCount: 0,
createdAt: Date.now()
});
}
/**
* Route a memory object to its zone based on type.
* @param {object} memoryObj — { type, source, content, score, ... }
* @returns {{ zone: string, position: THREE.Vector3, color: number }}
*/
assignMemory(memoryObj) {
const type = (memoryObj.type || 'facts').toLowerCase();
const zone = this.zones.get(type) || this.zones.get('facts');
zone.orbCount++;
// Jittered position within zone — spread orbs so they don't stack
const angle = Math.random() * Math.PI * 2;
const dist = Math.random() * zone.radius * 0.8;
const position = new THREE.Vector3(
zone.center.x + Math.cos(angle) * dist,
1.5 + Math.random() * 2,
zone.center.z + Math.sin(angle) * dist
);
return { zone: zone.name, position, color: zone.color };
}
getZonePosition(type) {
const zone = this.zones.get(type) || this.zones.get('facts');
return zone.center.clone();
}
listZones() {
const result = [];
this.zones.forEach((z, name) => {
result.push({
name,
center: { x: z.center.x, y: z.center.y, z: z.center.z },
radius: z.radius,
color: '#' + z.color.toString(16).padStart(6, '0'),
orbCount: z.orbCount,
description: z.metadata.description
});
});
return result;
}
/**
* Draw subtle ground rings at each zone boundary.
* Call once after scene is initialized.
*/
visualizeZones() {
if (typeof scene === 'undefined') return;
this.zones.forEach((zone, name) => {
// Ground ring
const ringGeo = new THREE.RingGeometry(zone.radius - 0.15, zone.radius + 0.15, 64);
const ringMat = new THREE.MeshBasicMaterial({
color: zone.color,
transparent: true,
opacity: 0.25,
side: THREE.DoubleSide
});
const ring = new THREE.Mesh(ringGeo, ringMat);
ring.rotation.x = -Math.PI / 2;
ring.position.copy(zone.center);
ring.position.y = 0.02;
scene.add(ring);
// Inner glow disc
const discGeo = new THREE.CircleGeometry(zone.radius, 64);
const discMat = new THREE.MeshBasicMaterial({
color: zone.color,
transparent: true,
opacity: 0.04,
side: THREE.DoubleSide
});
const disc = new THREE.Mesh(discGeo, discMat);
disc.rotation.x = -Math.PI / 2;
disc.position.copy(zone.center);
disc.position.y = 0.01;
scene.add(disc);
this.zoneVisuals.push(ring, disc);
});
console.info('[Mnemosyne] Zone visualization created for', this.zones.size, 'zones');
}
_persistZones() {
try {
const data = {};
this.zones.forEach((z, name) => {
data[name] = {
center: { x: z.center.x, y: z.center.y, z: z.center.z },
radius: z.radius,
orbCount: z.orbCount
};
});
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(data));
} catch (e) { /* storage full or unavailable */ }
}
_loadPersistedZones() {
try {
const raw = localStorage.getItem(this.STORAGE_KEY);
if (!raw) return;
const data = JSON.parse(raw);
Object.entries(data).forEach(([name, saved]) => {
const zone = this.zones.get(name);
if (zone && saved.orbCount) {
zone.orbCount = saved.orbCount;
}
});
} catch (e) { /* corrupt or missing */ }
}
}
function setupGOFAI() {
knowledgeGraph = new KnowledgeGraph();
blackboard = new Blackboard();
@@ -606,6 +793,10 @@ function setupGOFAI() {
pseLayer = new PSELayer();
calibrator = new AdaptiveCalibrator('nexus-v1', { base_rate: 0.05 });
// Initialize Spatial Memory Schema (Project Mnemosyne)
spatialSchema = new SpatialMemorySchema();
console.info('[Mnemosyne] Spatial Memory Schema initialized with', spatialSchema.zones.size, 'zones');
// Setup initial facts
symbolicEngine.addFact('energy', 100);
symbolicEngine.addFact('stability', 1.0);
@@ -2936,6 +3127,11 @@ function updateAshStorm(delta, elapsed) {
init().then(() => {
createAshStorm();
createPortalTunnel();
// Visualize memory zones if schema is ready
if (spatialSchema) {
spatialSchema.visualizeZones();
}
fetchGiteaData();
setInterval(fetchGiteaData, 30000);
runWeeklyAudit();

312
spatial-memory-schema.json Normal file
View File

@@ -0,0 +1,312 @@
{
"version": "1.0.0",
"project": "Mnemosyne",
"description": "Spatial memory schema for holographic memory visualization",
"rooms": {
"library": {
"name": "The Library",
"category": "user_pref",
"description": "User preferences and personal settings",
"visual_theme": {
"lighting": "soft_ambient",
"colors": {
"primary": "#8B4513",
"secondary": "#DAA520",
"accent": "#FFD700",
"particle": "#FFE4B5"
},
"materials": {
"floor": "dark_wood",
"walls": "bookshelf",
"ceiling": "vaulted_stone"
},
"particle_effects": [
"dust_motes",
"book_sparkles"
]
},
"spatial_bounds": {
"center": [
0,
0,
0
],
"dimensions": [
20,
10,
20
],
"orb_density": 0.7
},
"object_types": {
"preference": {
"shape": "sphere",
"base_size": 0.3,
"glow_intensity": 0.8
},
"setting": {
"shape": "cube",
"base_size": 0.4,
"glow_intensity": 0.6
}
}
},
"workshop": {
"name": "The Workshop",
"category": "project",
"description": "Active projects and development work",
"visual_theme": {
"lighting": "bright_work",
"colors": {
"primary": "#4682B4",
"secondary": "#B0C4DE",
"accent": "#00BFFF",
"particle": "#87CEEB"
},
"materials": {
"floor": "polished_concrete",
"walls": "blueprint_paper",
"ceiling": "industrial_metal"
},
"particle_effects": [
"blueprint_lines",
"tool_sparks"
]
},
"spatial_bounds": {
"center": [
30,
0,
0
],
"dimensions": [
25,
12,
25
],
"orb_density": 0.8
},
"object_types": {
"project": {
"shape": "pyramid",
"base_size": 0.5,
"glow_intensity": 0.9
},
"task": {
"shape": "cube",
"base_size": 0.3,
"glow_intensity": 0.7
}
}
},
"armory": {
"name": "The Armory",
"category": "tool",
"description": "Tools, skills, and capabilities",
"visual_theme": {
"lighting": "neon_glow",
"colors": {
"primary": "#2E8B57",
"secondary": "#3CB371",
"accent": "#00FF7F",
"particle": "#98FB98"
},
"materials": {
"floor": "chrome_grid",
"walls": "server_rack",
"ceiling": "neon_tube"
},
"particle_effects": [
"data_streams",
"circuit_traces"
]
},
"spatial_bounds": {
"center": [
0,
0,
30
],
"dimensions": [
15,
8,
15
],
"orb_density": 0.6
},
"object_types": {
"tool": {
"shape": "octahedron",
"base_size": 0.4,
"glow_intensity": 1.0
},
"skill": {
"shape": "sphere",
"base_size": 0.35,
"glow_intensity": 0.85
}
}
},
"commons": {
"name": "The Commons",
"category": "general",
"description": "General knowledge and miscellaneous facts",
"visual_theme": {
"lighting": "natural_daylight",
"colors": {
"primary": "#9370DB",
"secondary": "#BA55D3",
"accent": "#DA70D6",
"particle": "#E6E6FA"
},
"materials": {
"floor": "grass",
"walls": "floating_islands",
"ceiling": "open_sky"
},
"particle_effects": [
"floating_pollen",
"lightning_bugs"
]
},
"spatial_bounds": {
"center": [
30,
0,
30
],
"dimensions": [
30,
15,
30
],
"orb_density": 0.5
},
"object_types": {
"fact": {
"shape": "sphere",
"base_size": 0.25,
"glow_intensity": 0.7
},
"memory": {
"shape": "dodecahedron",
"base_size": 0.3,
"glow_intensity": 0.65
}
}
}
},
"object_properties": {
"trust_mapping": {
"description": "Maps trust score (0.0-1.0) to visual properties",
"glow_intensity": {
"min": 0.2,
"max": 1.0,
"curve": "linear"
},
"opacity": {
"min": 0.3,
"max": 1.0,
"curve": "ease_in_out"
}
},
"importance_mapping": {
"description": "Maps importance (relation count) to visual properties",
"scale": {
"min": 0.2,
"max": 2.0,
"curve": "logarithmic"
},
"particle_density": {
"min": 10,
"max": 100,
"curve": "linear"
}
},
"lifecycle_events": {
"FACT_CREATED": {
"animation": "fade_in",
"duration": 1.5,
"particle_effect": "spawn_burst"
},
"FACT_UPDATED": {
"animation": "pulse_glow",
"duration": 0.8,
"particle_effect": "update_ripple"
},
"FACT_REMOVED": {
"animation": "dissolve",
"duration": 2.0,
"particle_effect": "scatter"
},
"FACT_RECALLED": {
"animation": "beam_light",
"duration": 1.0,
"particle_effect": "recall_beam"
}
}
},
"connections": {
"holographic_threads": {
"description": "Visual connections between related memory orbs",
"material": "transparent_glow",
"colors": {
"strong_relation": "#00FFFF",
"medium_relation": "#00CED1",
"weak_relation": "#5F9EA0"
},
"thickness": {
"min": 0.02,
"max": 0.1,
"curve": "linear"
}
},
"cross_room_portals": {
"description": "Portals connecting different memory rooms",
"effect": "swirling_vortex",
"colors": {
"library_workshop": "#FFD700",
"workshop_armory": "#00BFFF",
"armory_commons": "#00FF7F",
"commons_library": "#DA70D6"
}
}
},
"rag_integration": {
"retrieval_visualization": {
"description": "How RAG retrieval results are visualized",
"highlight_effect": "golden_glow",
"spiral_arrangement": {
"radius": 3.0,
"height_step": 0.5,
"rotation_step": 0.618033988749895
},
"relevance_scoring": {
"high": {
"color": "#FFD700",
"size_multiplier": 1.5
},
"medium": {
"color": "#FFA500",
"size_multiplier": 1.2
},
"low": {
"color": "#FF8C00",
"size_multiplier": 1.0
}
}
},
"query_beam": {
"description": "Beam from user to relevant memory orbs",
"color": "#FFFFFF",
"opacity": 0.8,
"pulse_frequency": 2.0
}
},
"animation_timing": {
"orb_spawn_delay": 0.1,
"room_transition_duration": 2.0,
"connection_draw_speed": 0.5,
"particle_fade_time": 1.5
}
}