Compare commits
4 Commits
mimo/creat
...
mimo/build
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
024e74defe | ||
| 6c67002161 | |||
| 43699c83cf | |||
|
|
91f0bcb034 |
32
app.js
32
app.js
@@ -72,6 +72,9 @@ let workshopScanMat = null;
|
||||
let workshopPanelRefreshTimer = 0;
|
||||
let lastFocusedPortal = null;
|
||||
|
||||
// ═══ VISITOR / OPERATOR MODE ═══
|
||||
let uiMode = 'visitor'; // 'visitor' | 'operator'
|
||||
|
||||
// ═══ NAVIGATION SYSTEM ═══
|
||||
const NAV_MODES = ['walk', 'orbit', 'fly'];
|
||||
let navModeIdx = 0;
|
||||
@@ -778,6 +781,7 @@ async function init() {
|
||||
|
||||
enterPrompt.addEventListener('click', () => {
|
||||
enterPrompt.classList.add('fade-out');
|
||||
document.body.classList.add('visitor-mode');
|
||||
document.getElementById('hud').style.display = 'block';
|
||||
const erpPanel = document.getElementById('evennia-room-panel');
|
||||
if (erpPanel) erpPanel.style.display = 'block';
|
||||
@@ -1579,15 +1583,22 @@ function createPortal(config) {
|
||||
// Label
|
||||
const labelCanvas = document.createElement('canvas');
|
||||
labelCanvas.width = 512;
|
||||
labelCanvas.height = 64;
|
||||
labelCanvas.height = 96;
|
||||
const lctx = labelCanvas.getContext('2d');
|
||||
lctx.font = 'bold 32px "Orbitron", sans-serif';
|
||||
lctx.fillStyle = '#' + portalColor.getHexString();
|
||||
lctx.textAlign = 'center';
|
||||
lctx.fillText(`◈ ${config.name.toUpperCase()}`, 256, 42);
|
||||
lctx.fillText(`◈ ${config.name.toUpperCase()}`, 256, 36);
|
||||
// Role tag (timmy/reflex/pilot) — defines portal ownership boundary
|
||||
if (config.role) {
|
||||
const roleColors = { timmy: '#4af0c0', reflex: '#ff4466', pilot: '#ffd700' };
|
||||
lctx.font = 'bold 18px "Orbitron", sans-serif';
|
||||
lctx.fillStyle = roleColors[config.role] || '#888888';
|
||||
lctx.fillText(config.role.toUpperCase(), 256, 68);
|
||||
}
|
||||
const labelTex = new THREE.CanvasTexture(labelCanvas);
|
||||
const labelMat = new THREE.MeshBasicMaterial({ map: labelTex, transparent: true, side: THREE.DoubleSide });
|
||||
const labelMesh = new THREE.Mesh(new THREE.PlaneGeometry(4, 0.5), labelMat);
|
||||
const labelMesh = new THREE.Mesh(new THREE.PlaneGeometry(4, 0.75), labelMat);
|
||||
labelMesh.position.y = 7.5;
|
||||
group.add(labelMesh);
|
||||
|
||||
@@ -1863,6 +1874,18 @@ function createAmbientStructures() {
|
||||
}
|
||||
|
||||
// ═══ NAVIGATION MODE ═══
|
||||
// ═══ VISITOR / OPERATOR MODE TOGGLE ═══
|
||||
function toggleUIMode() {
|
||||
uiMode = uiMode === 'visitor' ? 'operator' : 'visitor';
|
||||
document.body.classList.remove('visitor-mode', 'operator-mode');
|
||||
document.body.classList.add(uiMode + '-mode');
|
||||
const label = document.getElementById('mode-label');
|
||||
const icon = document.querySelector('#mode-toggle-btn .hud-icon');
|
||||
if (label) label.textContent = uiMode === 'visitor' ? 'VISITOR' : 'OPERATOR';
|
||||
if (icon) icon.textContent = uiMode === 'visitor' ? '👁' : '⚙';
|
||||
addChatMessage('system', `Switched to ${uiMode.toUpperCase()} mode.`);
|
||||
}
|
||||
|
||||
function cycleNavMode() {
|
||||
navModeIdx = (navModeIdx + 1) % NAV_MODES.length;
|
||||
const mode = NAV_MODES[navModeIdx];
|
||||
@@ -2059,6 +2082,7 @@ function setupControls() {
|
||||
document.getElementById('portal-close-btn').addEventListener('click', closePortalOverlay);
|
||||
document.getElementById('vision-close-btn').addEventListener('click', closeVisionOverlay);
|
||||
|
||||
document.getElementById('mode-toggle-btn').addEventListener('click', toggleUIMode);
|
||||
document.getElementById('atlas-toggle-btn').addEventListener('click', openPortalAtlas);
|
||||
document.getElementById('atlas-close-btn').addEventListener('click', closePortalAtlas);
|
||||
initAtlasControls();
|
||||
@@ -3088,6 +3112,8 @@ function populateAtlas() {
|
||||
<div class="atlas-card-footer">
|
||||
<div class="atlas-card-coord">X:${config.position.x} Z:${config.position.z}</div>
|
||||
<div class="atlas-card-action">${actionLabel} →</div>
|
||||
${config.role ? `<div class="atlas-card-role role-${config.role}">${config.role.toUpperCase()}</div>` : ''}
|
||||
<div class="atlas-card-type">${config.destination?.type?.toUpperCase() || 'UNKNOWN'}</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
104
index.html
104
index.html
@@ -155,6 +155,9 @@
|
||||
<button id="soul-toggle-btn" class="hud-icon-btn" title="Timmy's SOUL">
|
||||
<span class="hud-icon">✦</span>
|
||||
<span class="hud-btn-label">SOUL</span>
|
||||
<button id="mode-toggle-btn" class="hud-icon-btn mode-toggle" title="Toggle Mode">
|
||||
<span class="hud-icon">👁</span>
|
||||
<span class="hud-btn-label" id="mode-label">VISITOR</span>
|
||||
</button>
|
||||
<button id="atlas-toggle-btn" class="hud-icon-btn" title="Portal Atlas">
|
||||
<span class="hud-icon">🌐</span>
|
||||
@@ -375,6 +378,107 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="branch-policy" style="margin-top: 10px; font-size: 12px; color: #aaa;">
|
||||
<strong>BRANCH PROTECTION POLICY</strong><br>
|
||||
<ul style="margin:0; padding-left:15px;">
|
||||
<li>• Require PR for merge ✅</li>
|
||||
<li>• Require 1 approval ✅</li>
|
||||
<li>• Dismiss stale approvals ✅</li>
|
||||
<li>• Require CI ✅ (where available)</li>
|
||||
<li>• Block force push ✅</li>
|
||||
<li>• Block branch deletion ✅</li>
|
||||
<li>• Weekly audit for unreviewed merges ✅</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="mem-palace-container" class="mem-palace-ui">
|
||||
<div class="mem-palace-header">
|
||||
<span id="mem-palace-status">MEMPALACE</span>
|
||||
<button onclick="mineMemPalaceContent()" class="mem-palace-btn">Mine Chat</button>
|
||||
</div>
|
||||
<div class="mem-palace-stats">
|
||||
<div>Compression: <span id="compression-ratio">--</span>x</div>
|
||||
<div>Docs mined: <span id="docs-mined">0</span></div>
|
||||
<div>AAAK size: <span id="aaak-size">0B</span></div>
|
||||
</div>
|
||||
<div class="mem-palace-logs" id="mem-palace-logs"></div>
|
||||
</div>
|
||||
<div class="default-reviewers" style="margin-top: 8px; font-size: 12px; color: #aaa;">
|
||||
<strong>DEFAULT REVIEWERS</strong><br>
|
||||
<ul style="margin:0; padding-left:15px;">
|
||||
<li>• <span style="color:#4af0c0;">@perplexity</span> (QA gate on all repos)</li>
|
||||
<li>• <span style="color:#7b5cff;">@Timmy</span> (owner gate on hermes-agent)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="implementation-status" style="margin-top: 10px; font-size: 12px; color: #aaa;">
|
||||
<strong>IMPLEMENTATION STATUS</strong><br>
|
||||
<div style="margin-top: 5px; display: flex; flex-direction: column; gap: 2px;">
|
||||
<div>• <span style="color:#4af0c0;">hermes-agent</span>: Require PR + 1 approval + CI ✅</div>
|
||||
<div>• <span style="color:#7b5cff;">the-nexus</span>: Require PR + 1 approval ⚠️ (CI disabled)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mem-palace-status" style="position:fixed; right:24px; top:64px; background:rgba(74,240,192,0.1); color:#4af0c0; padding:6px 12px; border-radius:4px; font-family:'Orbitron', sans-serif; font-size:10px; letter-spacing:0.1em;">
|
||||
MEMPALACE INIT
|
||||
</div>
|
||||
<div>• <span style="color:#ffd700;">timmy-home</span>: Require PR + 1 approval ✅</div>
|
||||
<div>• <span style="color:#ab8d00;">timmy-config</span>: Require PR + 1 approval ✅</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mem-palace-container" class="mem-palace-ui">
|
||||
<div class="mem-palace-header">MemPalace <span id="mem-palace-status">Initializing...</span></div>
|
||||
<div class="mem-palace-stats">
|
||||
<div>Compression: <span id="compression-ratio">--</span>x</div>
|
||||
<div>Docs mined: <span id="docs-mined">0</span></div>
|
||||
<div>AAAK size: <span id="aaak-size">0B</span></div>
|
||||
</div>
|
||||
<div class="mem-palace-actions">
|
||||
<button id="mine-now-btn" class="mem-palace-btn" onclick="mineChatToMemPalace()">Mine Chat</button>
|
||||
<button class="mem-palace-btn" onclick="searchMemPalace()">Search</button>
|
||||
</div>
|
||||
<div id="mem-palace-logs" class="mem-palace-logs"></div>
|
||||
</div>
|
||||
<div id="mem-palace-controls" style="position:fixed; right:24px; top:54px; background:rgba(74,240,192,0.05); padding:4px 8px; font-family:'JetBrains Mono',monospace; font-size:11px; border-left:2px solid #4af0c0;">
|
||||
<button onclick="mineMemPalace()">Mine Chat</button>
|
||||
<button onclick="searchMemPalace()">Search</button>
|
||||
</div>
|
||||
<div id="mempalace-results" style="position:fixed; right:24px; top:84px; max-height:200px; overflow-y:auto; background:rgba(0,0,0,0.3); padding:8px; font-family:'JetBrains Mono',monospace; font-size:11px; color:#e0f0ff; border-left:2px solid #4af0c0;"></div>
|
||||
<div id="mem-palace-controls" style="position:fixed; right:24px; top:54px; background:rgba(74,240,192,0.05); padding:4px 8px; font-family:'JetBrains Mono',monospace; font-size:10px; border-left:2px solid #4af0c0;">
|
||||
<button class="mem-palace-mining-btn" onclick="mineChatToMemPalace()">Mine Chat</button>
|
||||
<button onclick="searchMemPalace()">Search</button>
|
||||
</div>
|
||||
<div id="mempalace-results" style="position:fixed; right:24px; top:84px; max-height:200px; overflow-y:auto; background:rgba(0,0,0,0.3); padding:8px; font-family:'JetBrains Mono',monospace; font-size:11px; color:#e0f0ff; border-left:2px solid #4af0c0;"></div>
|
||||
|
||||
```
|
||||
|
||||
index.html
|
||||
```html
|
||||
|
||||
<div class="branch-policy" style="margin-top: 10px; font-size: 12px; color: #aaa;">
|
||||
<strong>BRANCH PROTECTION POLICY</strong><br>
|
||||
<ul style="margin:0; padding-left:15px;">
|
||||
<li>• Require PR for merge ✅</li>
|
||||
<li>• Require 1 approval ✅</li>
|
||||
<li>• Dismiss stale approvals ✅</li>
|
||||
<li>• Require CI ✅ (where available)</li>
|
||||
<li>• Block force push ✅</li>
|
||||
<li>• Block branch deletion ✅</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="default-reviewers" style="margin-top: 8px;">
|
||||
<strong>DEFAULT REVIEWERS</strong><br>
|
||||
<ul style="margin:0; padding-left:15px;">
|
||||
<li>• <span style="color:#4af0c0;">@perplexity</span> (QA gate on all repos)</li>
|
||||
<li>• <span style="color:#7b5cff;">@Timmy</span> (owner gate on hermes-agent)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="implementation-status" style="margin-top: 10px;">
|
||||
<strong>IMPLEMENTATION STATUS</strong><br>
|
||||
<div style="margin-top: 5px; display: flex; flex-direction: column; gap: 2px;">
|
||||
<div>• <span style="color:#4af0c0;">hermes-agent</span>: Require PR + 1 approval + CI ✅</div>
|
||||
<div>• <span style="color:#7b5cff;">the-nexus</span>: Require PR + 1 approval ⚠<> (CI disabled)</div>
|
||||
<div>• <span style="color:#ffd700;">timmy-home</span>: Require PR + 1 approval ✅</div>
|
||||
<div>• <span style="color:#ab8d00;">timmy-config</span>: Require PR + 1 approval ✅</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script type="module" src="./app.js"></script>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"description": "The Vvardenfell harness. Ash storms and ancient mysteries.",
|
||||
"status": "online",
|
||||
"color": "#ff6600",
|
||||
"role": "pilot",
|
||||
"position": { "x": 15, "y": 0, "z": -10 },
|
||||
"rotation": { "y": -0.5 },
|
||||
"portal_type": "game-world",
|
||||
@@ -36,6 +37,7 @@
|
||||
"description": "Calradia battle harness. Massive armies, tactical command.",
|
||||
"status": "downloaded",
|
||||
"color": "#ffd700",
|
||||
"role": "pilot",
|
||||
"position": { "x": -15, "y": 0, "z": -10 },
|
||||
"rotation": { "y": 0.5 },
|
||||
"portal_type": "game-world",
|
||||
@@ -67,6 +69,7 @@
|
||||
"description": "The creative harness. Build, script, and manifest.",
|
||||
"status": "online",
|
||||
"color": "#4af0c0",
|
||||
"role": "timmy",
|
||||
"position": { "x": 0, "y": 0, "z": -20 },
|
||||
"rotation": { "y": 0 },
|
||||
"destination": {
|
||||
@@ -81,6 +84,7 @@
|
||||
"description": "The repository of all knowledge. History, logs, and ancient data.",
|
||||
"status": "online",
|
||||
"color": "#0066ff",
|
||||
"role": "timmy",
|
||||
"position": { "x": 25, "y": 0, "z": 0 },
|
||||
"rotation": { "y": -1.57 },
|
||||
"destination": {
|
||||
@@ -95,6 +99,7 @@
|
||||
"description": "A sanctuary for reflection and digital peace.",
|
||||
"status": "online",
|
||||
"color": "#ffd700",
|
||||
"role": "timmy",
|
||||
"position": { "x": -25, "y": 0, "z": 0 },
|
||||
"rotation": { "y": 1.57 },
|
||||
"destination": {
|
||||
@@ -109,6 +114,7 @@
|
||||
"description": "The open nexus. A place for agents to gather and connect.",
|
||||
"status": "online",
|
||||
"color": "#4af0c0",
|
||||
"role": "reflex",
|
||||
"position": { "x": 15, "y": 0, "z": 10 },
|
||||
"rotation": { "y": -2.5 },
|
||||
"destination": {
|
||||
@@ -123,6 +129,7 @@
|
||||
"description": "The transition point. Entry and exit from the Nexus core.",
|
||||
"status": "standby",
|
||||
"color": "#ff4466",
|
||||
"role": "reflex",
|
||||
"position": { "x": -15, "y": 0, "z": 10 },
|
||||
"rotation": { "y": 2.5 },
|
||||
"destination": {
|
||||
|
||||
85
style.css
85
style.css
@@ -384,6 +384,19 @@ canvas#nexus-canvas {
|
||||
color: rgba(160, 184, 208, 0.6);
|
||||
}
|
||||
|
||||
.atlas-card-role {
|
||||
font-family: var(--font-display);
|
||||
font-size: 9px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.atlas-card-role.role-timmy { color: #4af0c0; background: rgba(74, 240, 192, 0.12); border: 1px solid rgba(74, 240, 192, 0.3); }
|
||||
.atlas-card-role.role-reflex { color: #ff4466; background: rgba(255, 68, 102, 0.12); border: 1px solid rgba(255, 68, 102, 0.3); }
|
||||
.atlas-card-role.role-pilot { color: #ffd700; background: rgba(255, 215, 0, 0.12); border: 1px solid rgba(255, 215, 0, 0.3); }
|
||||
|
||||
.atlas-footer {
|
||||
padding: 15px 30px;
|
||||
border-top: 1px solid var(--color-border);
|
||||
@@ -2484,3 +2497,75 @@ canvas#nexus-canvas {
|
||||
.soul-link a:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════
|
||||
VISITOR / OPERATOR MODE
|
||||
═══════════════════════════════════════════════════════ */
|
||||
|
||||
.mode-toggle {
|
||||
border-color: #4af0c0 !important;
|
||||
}
|
||||
|
||||
.mode-toggle .hud-icon {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#mode-label {
|
||||
color: #4af0c0;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Visitor mode: hide operator-only panels */
|
||||
body.visitor-mode .gofai-hud,
|
||||
body.visitor-mode .hud-debug,
|
||||
body.visitor-mode .hud-agent-log,
|
||||
body.visitor-mode .archive-health-dashboard,
|
||||
body.visitor-mode .memory-feed,
|
||||
body.visitor-mode .memory-inspect-panel,
|
||||
body.visitor-mode .memory-connections-panel,
|
||||
body.visitor-mode .memory-filter,
|
||||
body.visitor-mode #mem-palace-container,
|
||||
body.visitor-mode #mem-palace-controls,
|
||||
body.visitor-mode #mempalace-results,
|
||||
body.visitor-mode .nexus-footer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Visitor mode: simplify bannerlord status */
|
||||
body.visitor-mode #bannerlord-status {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Visitor mode: add a subtle visitor badge */
|
||||
body.visitor-mode .hud-location::after {
|
||||
content: '⬡ VISITOR';
|
||||
margin-left: 12px;
|
||||
font-size: 9px;
|
||||
letter-spacing: 0.15em;
|
||||
color: #4af0c0;
|
||||
opacity: 0.7;
|
||||
font-family: 'Orbitron', sans-serif;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Operator mode: add operator badge */
|
||||
body.operator-mode .hud-location::after {
|
||||
content: '⬢ OPERATOR';
|
||||
margin-left: 12px;
|
||||
font-size: 9px;
|
||||
letter-spacing: 0.15em;
|
||||
color: #ffd700;
|
||||
opacity: 0.8;
|
||||
font-family: 'Orbitron', sans-serif;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Operator mode: golden accent on toggle */
|
||||
body.operator-mode .mode-toggle {
|
||||
border-color: #ffd700 !important;
|
||||
}
|
||||
|
||||
body.operator-mode #mode-label {
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user