diff --git a/app.js b/app.js index 28e9085a..b9b298a4 100644 --- a/app.js +++ b/app.js @@ -4,6 +4,7 @@ import { RenderPass } from 'three/addons/postprocessing/RenderPass.js'; import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js'; import { SMAAPass } from 'three/addons/postprocessing/SMAAPass.js'; import { SpatialMemory } from './nexus/components/spatial-memory.js'; +import { SessionRooms } from './nexus/components/session-rooms.js'; // ═══════════════════════════════════════════ // NEXUS v1.1 — Portal System Update @@ -705,6 +706,7 @@ async function init() { createWorkshopTerminal(); createAshStorm(); SpatialMemory.init(scene); + SessionRooms.init(scene, camera, null); updateLoad(90); loadSession(); @@ -1915,8 +1917,19 @@ function setupControls() { } } + // Priority 3: Session rooms (Mnemosyne #1171) + const roomMeshes = SessionRooms.getClickableMeshes(); + if (roomMeshes.length > 0) { + const roomHits = raycaster.intersectObjects(roomMeshes, false); + if (roomHits.length > 0) { + const session = SessionRooms.handleRoomClick(roomHits[0].object); + if (session) { _showSessionRoomPanel(session); return; } + } + } + // Clicked empty space — dismiss panel dismissMemoryPanel(); + _dismissSessionRoomPanel(); } } }); @@ -2734,6 +2747,62 @@ function _dismissMemoryPanelForce() { }, 200); } +/** + * Show the session room HUD panel when a chamber is entered. + * @param {object} session — { id, timestamp, facts[] } + */ +function _showSessionRoomPanel(session) { + const panel = document.getElementById('session-room-panel'); + if (!panel) return; + + const dt = session.timestamp ? new Date(session.timestamp) : new Date(); + const tsEl = document.getElementById('session-room-timestamp'); + if (tsEl) tsEl.textContent = isNaN(dt.getTime()) ? session.id : dt.toLocaleString(); + + const countEl = document.getElementById('session-room-fact-count'); + const facts = session.facts || []; + if (countEl) countEl.textContent = facts.length + (facts.length === 1 ? ' fact' : ' facts') + ' in this chamber'; + + const listEl = document.getElementById('session-room-facts'); + if (listEl) { + listEl.innerHTML = ''; + facts.slice(0, 8).forEach(f => { + const item = document.createElement('div'); + item.className = 'session-room-fact-item'; + item.textContent = f.content || f.id || '(unknown)'; + item.title = f.content || ''; + listEl.appendChild(item); + }); + if (facts.length > 8) { + const more = document.createElement('div'); + more.className = 'session-room-fact-item'; + more.style.color = 'rgba(200,180,255,0.4)'; + more.textContent = '\u2026 ' + (facts.length - 8) + ' more'; + listEl.appendChild(more); + } + } + + // Close button + const closeBtn = document.getElementById('session-room-close'); + if (closeBtn) closeBtn.onclick = () => _dismissSessionRoomPanel(); + + panel.classList.remove('session-panel-fade-out'); + panel.style.display = 'block'; +} + +/** + * Dismiss the session room panel. + */ +function _dismissSessionRoomPanel() { + const panel = document.getElementById('session-room-panel'); + if (!panel || panel.style.display === 'none') return; + panel.classList.add('session-panel-fade-out'); + setTimeout(() => { + panel.style.display = 'none'; + panel.classList.remove('session-panel-fade-out'); + }, 200); +} + function gameLoop() { requestAnimationFrame(gameLoop); @@ -2765,6 +2834,9 @@ function gameLoop() { animateMemoryOrbs(delta); } + // Project Mnemosyne - Session Rooms (#1171) + SessionRooms.update(delta); + const mode = NAV_MODES[navModeIdx]; const chatActive = document.activeElement === document.getElementById('chat-input'); @@ -3294,6 +3366,37 @@ init().then(() => { // Gravity well clustering — attract related crystals, bake positions (issue #1175) SpatialMemory.runGravityLayout(); + // Project Mnemosyne — seed demo session rooms (#1171) + // Sessions group facts by conversation/work session with a timestamp. + const demoSessions = [ + { + id: 'session_2026_03_01', + timestamp: '2026-03-01T10:00:00.000Z', + facts: [ + { id: 'mem_nexus_birth', content: 'The Nexus came online — first render of the 3D world', category: 'knowledge', strength: 0.95 }, + { id: 'mem_mnemosyne_start', content: 'Project Mnemosyne began — the living archive awakens', category: 'projects', strength: 0.9 }, + ] + }, + { + id: 'session_2026_03_15', + timestamp: '2026-03-15T14:30:00.000Z', + facts: [ + { id: 'mem_first_portal', content: 'First portal deployed — connection to external service', category: 'engineering', strength: 0.85 }, + { id: 'mem_hermes_chat', content: 'First conversation through the Hermes gateway', category: 'social', strength: 0.7 }, + { id: 'mem_spatial_schema', content: 'Spatial Memory Schema defined — memories gain homes', category: 'engineering', strength: 0.8 }, + ] + }, + { + id: 'session_2026_04_10', + timestamp: '2026-04-10T09:00:00.000Z', + facts: [ + { id: 'mem_session_rooms', content: 'Session rooms introduced — holographic chambers per session', category: 'projects', strength: 0.88 }, + { id: 'mem_gravity_wells', content: 'Gravity-well clustering bakes crystal positions on load', category: 'engineering', strength: 0.75 }, + ] + } + ]; + SessionRooms.updateSessions(demoSessions); + fetchGiteaData(); setInterval(fetchGiteaData, 30000); runWeeklyAudit(); diff --git a/index.html b/index.html index b7e3c0b1..54ada489 100644 --- a/index.html +++ b/index.html @@ -236,6 +236,21 @@ + + +